Whamcloud - gitweb
* Up to date b_devel (SWAB_LAND)
authoreeb <eeb>
Sun, 6 Apr 2003 14:44:11 +0000 (14:44 +0000)
committereeb <eeb>
Sun, 6 Apr 2003 14:44:11 +0000 (14:44 +0000)
12 files changed:
lustre/kernel_patches/patches/export-truncate.patch [new file with mode: 0644]
lustre/kernel_patches/pc/export-truncate.pc [new file with mode: 0644]
lustre/tests/openfile.c [new file with mode: 0644]
lustre/tests/unlinkmany.c [new file with mode: 0644]
lustre/utils/Lustre/.cvsignore [new file with mode: 0644]
lustre/utils/Lustre/Makefile.am [new file with mode: 0644]
lustre/utils/Lustre/__init__.py [new file with mode: 0644]
lustre/utils/Lustre/cmdline.py [new file with mode: 0644]
lustre/utils/Lustre/error.py [new file with mode: 0644]
lustre/utils/Lustre/lustredb.py [new file with mode: 0644]
lustre/utils/lactive [new file with mode: 0644]
lustre/utils/load_ldap.sh [new file with mode: 0755]

diff --git a/lustre/kernel_patches/patches/export-truncate.patch b/lustre/kernel_patches/patches/export-truncate.patch
new file mode 100644 (file)
index 0000000..12e6f44
--- /dev/null
@@ -0,0 +1,29 @@
+--- linux/include/linux/mm.h.truncexport       2003-03-21 20:03:18.000000000 -0500
++++ linux/include/linux/mm.h   2003-03-21 20:05:04.000000000 -0500
+@@ -650,6 +650,7 @@
+ /* filemap.c */
+ extern void remove_inode_page(struct page *);
+ extern unsigned long page_unuse(struct page *);
++extern void truncate_complete_page(struct page *);
+ extern void truncate_inode_pages(struct address_space *, loff_t);
+ /* generic vm_area_ops exported for stackable file systems */
+--- linux/mm/filemap.c.truncexport     2003-03-21 20:01:19.000000000 -0500
++++ linux/mm/filemap.c 2003-03-21 20:01:41.000000000 -0500
+@@ -245,7 +245,7 @@
+               do_flushpage(page, partial);
+ }
+-static void truncate_complete_page(struct page *page)
++void truncate_complete_page(struct page *page)
+ {
+       /*
+        * Leave it on the LRU if it gets converted into anonymous buffers
+@@ -266,6 +266,7 @@
+       remove_inode_page(page);
+       page_cache_release(page);
+ }
++EXPORT_SYMBOL_GPL(truncate_complete_page);
+ static int FASTCALL(truncate_list_pages(struct list_head *, unsigned long, unsigned *));
+ static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial)
diff --git a/lustre/kernel_patches/pc/export-truncate.pc b/lustre/kernel_patches/pc/export-truncate.pc
new file mode 100644 (file)
index 0000000..bd58c82
--- /dev/null
@@ -0,0 +1,2 @@
+include/linux/mm.h
+mm/filemap.c
diff --git a/lustre/tests/openfile.c b/lustre/tests/openfile.c
new file mode 100644 (file)
index 0000000..ab5cbdb
--- /dev/null
@@ -0,0 +1,162 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+
+#if 0
+#define DEBUG
+#endif
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+typedef struct flag_mapping {
+       char string[20];
+       int  flag;
+} FLAG_MAPPING;
+
+FLAG_MAPPING flag_table[] = {
+       {"O_RDONLY", O_RDONLY},
+       {"O_WRONLY", O_WRONLY},
+       {"O_RDWR", O_RDWR},
+       {"O_CREAT", O_CREAT},
+       {"O_EXCL", O_EXCL},
+       {"O_NOCTTY", O_NOCTTY},
+       {"O_TRUNC", O_TRUNC},
+       {"O_APPEND", O_APPEND},
+       {"O_NONBLOCK", O_NONBLOCK},
+       {"O_NDELAY", O_NDELAY},
+       {"O_SYNC", O_SYNC},
+       {"O_NOFOLLOW", O_NOFOLLOW},
+       {"O_DIRECTORY", O_DIRECTORY},
+       {"O_LARGEFILE", O_LARGEFILE},
+       {"", -1}
+};
+
+void Usage_and_abort(void)
+{
+       fprintf(stderr, "Usage: openfile -f flags [ -m mode ] filename \n");
+       fprintf(stderr, "e.g. openfile -f O_RDWR:O_CREAT -m 0755 /etc/passwd\n");
+       exit(-1);
+}
+
+int main(int argc, char** argv)
+{
+        int i;
+        int    flags=0;
+        mode_t mode=0;
+        char*  fname=NULL;
+        int    mode_set=0;
+        int    flag_set=0;
+        int    file_set=0;
+        char   c;
+        char*  cloned_flags;
+
+        if(argc == 1) {
+                Usage_and_abort();
+        }
+
+        while ((c = getopt (argc, argv, "f:m:")) != -1) {
+                switch (c) {
+                case 'f': {
+                        char *tmp;
+
+                        cloned_flags = (char*)malloc(strlen(optarg));
+                        if (cloned_flags==NULL) {
+                                fprintf(stderr, "Insufficient memory.\n");
+                                exit(-1);
+                        }
+
+                        strncpy(cloned_flags, optarg, strlen(optarg));
+                        tmp = strtok(optarg, ":");
+                        while (tmp) {
+                                int i = 0;
+#ifdef DEBUG
+                                printf("flags = %s\n",tmp);
+#endif
+                                flag_set = 1;
+                                while (flag_table[i].flag != -1) {
+                                        int r;
+                                        r = strncasecmp(tmp, (flag_table[i].string),
+                                                        strlen((flag_table[i].string)) );
+
+                                        if (r == 0)
+                                                break;
+                                        i++;
+                                }
+
+                                if (flag_table[i].flag != -1) {
+                                        flags |= flag_table[i].flag;
+                                } else {
+                                        fprintf(stderr, "No such flag: %s\n",
+                                                tmp);
+                                        exit(-1);
+                                }
+
+                                tmp = strtok(NULL, ":");
+
+                        }
+#ifdef DEBUG
+                        printf("flags = %x\n", flags);
+#endif
+                        break;
+                }
+                case 'm':
+#ifdef DEBUG
+                        printf("mode = %s\n", optarg);
+#endif
+                        mode = strtol (optarg, NULL, 8);
+                        mode_set = 1;
+#ifdef DEBUG
+                        printf("mode = %o\n", mode);
+#endif
+                        break;
+                default:
+                        fprintf(stderr, "Bad parameters.\n");
+                        Usage_and_abort();
+                }
+        }
+
+        if (optind == argc) {
+                fprintf(stderr, "Bad parameters.\n");
+                Usage_and_abort();
+        }
+
+        fname = argv[optind];
+        file_set = 1;
+
+        if (!flag_set || !file_set) {
+                fprintf(stderr, "Missing flag or file-name\n");
+                exit(-1);
+        }
+
+
+        if (mode_set)
+                i = open(fname, flags, mode);
+        else
+                i = open(fname, flags);
+
+        if (i != -1) {
+                fprintf(stderr, "Succeed in opening file \"%s\"(flags=%s",
+                        fname, cloned_flags);
+
+                if (mode_set)
+                        fprintf(stderr, ", mode=%o", mode);
+                fprintf(stderr, ")\n");
+                close (i);
+        } else {
+                fprintf(stderr, "Error in opening file \"%s\"(flags=%s",
+                        fname, cloned_flags);
+                if (mode_set)
+                        fprintf(stderr, ", mode=%o", mode);
+                fprintf(stderr, ") %s\n", strerror(errno));
+        }
+        return(i);
+}
diff --git a/lustre/tests/unlinkmany.c b/lustre/tests/unlinkmany.c
new file mode 100644 (file)
index 0000000..ba1bee7
--- /dev/null
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+void usage(char *prog)
+{
+       printf("usage: %s filenamefmt count\n", prog);
+       printf("       %s filenamefmt start count\n", prog);
+}
+
+int main(int argc, char ** argv)
+{
+        int i, rc = 0;
+        char format[4096], *fmt;
+        char filename[4096];
+        long start, last;
+       long begin = 0, count;
+
+        if (argc < 3 || argc > 4) {
+               usage(argv[0]);
+                return 1;
+        }
+
+        if (strlen(argv[1]) > 4080) {
+                printf("name too long\n");
+                return 1;
+        }
+
+        start = last = time(0);
+
+       if (argc == 3) {
+               count = strtol(argv[2], NULL, 0);
+               if (count < 1) {
+                        printf("count must be at least one\n");
+                        return 1;
+                }
+       } else {
+               begin = strtol(argv[2], NULL, 0);
+               count = strtol(argv[3], NULL, 0);
+       }
+
+       if (strchr(argv[1], '%')) {
+               fmt = argv[1];
+        } else {
+               sprintf(format, "%s%%d", argv[1]);
+               fmt = format;
+       }
+        for (i = 0; i < count; i++, begin++) {
+                sprintf(filename, fmt, begin);
+                rc = unlink(filename);
+                if (rc) {
+                        printf("unlink(%s) error: %s\n",
+                               filename, strerror(errno));
+                        rc = errno;
+                        break;
+                }
+                if ((i % 10000) == 0) {
+                        printf(" - unlinked %d (time %ld ; total %ld ; last "
+                               "%ld)\n", i, time(0), time(0) - start,
+                               time(0) - last);
+                        last = time(0);
+                }
+        }
+        printf("total: %d unlinks in %ld seconds: %f unlinks/second\n", i,
+               time(0) - start, ((float)i / (time(0) - start)));
+
+        return rc;
+}
diff --git a/lustre/utils/Lustre/.cvsignore b/lustre/utils/Lustre/.cvsignore
new file mode 100644 (file)
index 0000000..97e22b9
--- /dev/null
@@ -0,0 +1,4 @@
+Makefile
+Makefile.in
+.deps
+*.pyc
diff --git a/lustre/utils/Lustre/Makefile.am b/lustre/utils/Lustre/Makefile.am
new file mode 100644 (file)
index 0000000..e8e522f
--- /dev/null
@@ -0,0 +1,2 @@
+pymod_SCRIPTS = __init__.py lustredb.py error.py cmdline.py
+EXTRA_DIST = $(pymod_SCRIPTS)
diff --git a/lustre/utils/Lustre/__init__.py b/lustre/utils/Lustre/__init__.py
new file mode 100644 (file)
index 0000000..a4f4367
--- /dev/null
@@ -0,0 +1,5 @@
+__all__ = ["lustredb"]
+
+from lustredb import LustreDB, LustreDB_XML, LustreDB_LDAP
+from error import LconfError, OptionError
+from cmdline import Options
diff --git a/lustre/utils/Lustre/cmdline.py b/lustre/utils/Lustre/cmdline.py
new file mode 100644 (file)
index 0000000..d87da80
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+#
+#  Copyright (C) 2002 Cluster File Systems, Inc.
+#   Author: Robert Read <rread@clusterfs.com>
+#   This file is part of Lustre, http://www.lustre.org.
+#
+#   Lustre is free software; you can redistribute it and/or
+#   modify it under the terms of version 2 of the GNU General Public
+#   License as published by the Free Software Foundation.
+#
+#   Lustre is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with Lustre; if not, write to the Free Software
+#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+# Standard the comand line handling for all the python tools.
+
+import sys, getopt, types
+import string
+import error
+
+class Options:
+    FLAG = 1
+    PARAM = 2
+    INTPARAM = 3
+    def __init__(self, cmd, remain_help, options):
+        self.options = options
+        shorts = ""
+        longs = []
+        options.append(('help,h', "Print this help")) 
+        for opt in options:
+            long = self.long(opt)
+            short = self.short(opt)
+            if self.type(opt) in (Options.PARAM, Options.INTPARAM):
+                if short:  short = short + ':'
+                if long: long = long + '='
+            shorts = shorts + short
+            longs.append(long)
+        self.short_opts = shorts
+        self.long_opts = longs
+        self.cmd = cmd
+        self.remain_help = remain_help
+
+    def init_values(self):
+        values = {}
+        for opt in self.options:
+            values[self.long(opt)] = self.default(opt)
+        return values
+
+    def long(self, option):
+        n = string.find(option[0], ',')
+        if n < 0: return option[0]
+        else:     return option[0][0:n]
+
+    def short(self, option):
+        n = string.find(option[0], ',')
+        if n < 0: return ''
+        else:     return option[0][n+1:]
+
+    def help(self, option):
+        return option[1]
+    
+    def type(self, option):
+        if len(option) >= 3:
+            return option[2]
+        return Options.FLAG
+    
+    def default(self, option):
+        if len(option) >= 4:
+            return option[3]
+        return None
+
+    def lookup_option(self, key, key_func):
+        for opt in self.options:
+            if key_func(opt) == key:
+                return opt
+
+    def lookup_short(self, key):
+        return self.lookup_option(key, self.short)
+
+    def lookup_long(self, key):
+        return self.lookup_option(key, self.long)
+
+    def handle_opts(self, opts):
+        values = self.init_values()
+        for o, a in opts:
+            if o[0:2] != '--':
+                option = self.lookup_short(o[1:])
+            else:
+                option = self.lookup_long(o[2:])
+            if self.type(option) == Options.PARAM:
+                val = a
+            elif self.type(option) == Options.INTPARAM:
+                try: 
+                    val = int(a)
+                except ValueError, e:
+                    raise error.OptionError("option: '%s' expects integer value, got '%s' "  % (o,a))
+            else:
+                val = 1
+            values[self.long(option)] = val
+        return values
+                
+    class option_wrapper:
+        def __init__(self, values):
+            self.__dict__['values'] = values
+        def __getattr__(self, name):
+            if self.values.has_key(name):
+                return self.values[name]
+            else:
+                raise error.OptionError("bad option name: " + name)
+        def __setattr__(self, name, value):
+            self.values[name] = value
+
+    def parse(self, argv):
+        try:
+            opts, args = getopt.getopt(argv, self.short_opts, self.long_opts)
+            values = self.handle_opts(opts)
+            if values["help"]:
+                self.usage()
+                sys.exit(0)
+            return self.option_wrapper(values), args
+        except getopt.error, e:
+            raise error.OptionError(e)
+
+    def usage(self):
+        ret = 'usage: %s [options] %s\n' % (self.cmd, self.remain_help)
+        for opt in self.options:
+            s = self.short(opt)
+            if s: str = "-%s|--%s" % (s,self.long(opt))
+            else: str = "--%s" % (self.long(opt),)
+            if self.type(opt) in (Options.PARAM, Options.INTPARAM):
+                str = "%s <arg>" % (str,)
+            help = self.help(opt)
+            n = string.find(help, '\n')
+            if self.default(opt) != None:
+                if n < 0:
+                    str = "%-15s  %s (default=%s)" %(str, help,
+                                                     self.default(opt))
+                else:
+                    str = "%-15s  %s (default=%s)%s" %(str, help[0:n],
+                                                       self.default(opt),
+                                                       help[n:])
+            else:
+                str = "%-15s  %s" %(str, help)
+            ret = ret + str + "\n"
+        print ret
+
+# Test driver
+if __name__ == "__main__":
+    cl = Options("test", "xml_file", [
+                  ('verbose,v', "verbose ", Options.FLAG, 0),
+                  ('cleanup,d', "shutdown"),
+                  ('gdb',     "Display gdb module file ", Options.FLAG, 0),
+                  ('device', "device path ", Options.PARAM),
+                  ('ldapurl', "LDAP server URL ", Options.PARAM),
+                  ('lustre', "Lustre source dir ", Options.PARAM),
+                  ('portals', "Portals source dir ", Options.PARAM),
+                  ('maxlevel', """Specify the maximum level
+                    Levels are aproximatly like:
+                            70 - mountpoint, echo_client, osc, mdc, lov""",
+                   Options.INTPARAM, 100),
+
+                  ])
+
+    conf, args = cl.parse(sys.argv[1:])
+
+    for key in conf.values.keys():
+        print "%-10s = %s" % (key, conf.values[key])
diff --git a/lustre/utils/Lustre/error.py b/lustre/utils/Lustre/error.py
new file mode 100644 (file)
index 0000000..6c30416
--- /dev/null
@@ -0,0 +1,10 @@
+import exceptions
+
+class LconfError (exceptions.Exception):
+    def __init__(self, args):
+        self.args = args
+
+class OptionError (exceptions.Exception):
+    def __init__(self, args):
+        self.args = args
+
diff --git a/lustre/utils/Lustre/lustredb.py b/lustre/utils/Lustre/lustredb.py
new file mode 100644 (file)
index 0000000..14be906
--- /dev/null
@@ -0,0 +1,389 @@
+import sys, types, string, os
+import re, exceptions
+import xml.dom.minidom
+import Lustre
+
+# ============================================================
+# XML processing and query
+
+class LustreDB:
+    def lookup(self, uuid):
+        """ lookup returns a new LustreDB instance"""
+        return self._lookup_by_uuid(uuid)
+
+    def lookup_name(self, name, class_name = ""):
+        """ lookup returns a new LustreDB instance"""
+        return self._lookup_by_name(name, class_name)
+
+    def lookup_class(self, class_name):
+        """ lookup returns a new LustreDB instance"""
+        return self._lookup_by_class(class_name)
+
+    def get_val(self, tag, default=None):
+        v =  self._get_val(tag)
+        if v:
+            return v
+        if default != None:
+            return default
+        return None
+
+    def get_class(self):
+        return self._get_class()
+
+    def get_val_int(self, tag, default=0):
+        str = self._get_val(tag)
+        try:
+            if str:
+                return int(str)
+            return default
+        except ValueError:
+            raise LconfError("text value is not integer:", str)
+            
+    def get_first_ref(self, tag):
+        """ Get the first uuidref of the type TAG. Only
+        one is expected.  Returns the uuid."""
+        uuids = self._get_refs(tag)
+        if len(uuids) > 0:
+            return  uuids[0]
+        return None
+    
+    def get_refs(self, tag):
+        """ Get all the refs of type TAG.  Returns list of uuids. """
+        uuids = self._get_refs(tag)
+        return uuids
+
+    def get_all_refs(self):
+        """ Get all the refs.  Returns list of uuids. """
+        uuids = self._get_all_refs()
+        return uuids
+
+    def nid2server(self, nid, net_type):
+        netlist = self.lookup_class('network')
+        for net_db in netlist:
+            if net_db.get_val('nid') == nid and net_db.get_val('nettype') == net_type: 
+                return net_db
+        return None
+    
+    # Find the target_device for target on a node
+    # node->profiles->device_refs->target
+    def get_node_tgt_dev(self, node_name, target_uuid):
+        node_db = self.lookup_name(node_name)
+        if not node_db:
+            return None
+        return self.get_tgt_dev(target_uuid)
+
+    # get all network uuids for this node
+    def get_networks(self):
+        ret = []
+        prof_list = self.get_refs('profile')
+        for prof_uuid in prof_list:
+            prof_db = self.lookup(prof_uuid)
+            net_list = prof_db.get_refs('network')
+            for net_uuid in net_list:
+                ret.append(net_uuid)
+        return ret
+
+    def get_active_dev(self, tgtuuid):
+        tgt = self.lookup(tgtuuid)
+        tgt_dev_uuid =tgt.get_first_ref('active')
+        return tgt_dev_uuid
+
+    def get_tgt_dev(self, tgtuuid):
+        prof_list = self.get_refs('profile')
+        for prof_uuid in prof_list:
+            prof_db = self.lookup(prof_uuid)
+            if not prof_db:
+                panic("profile:", profile, "not found.")
+            for ref_class, ref_uuid in prof_db.get_all_refs(): 
+                if ref_class in ('osd', 'mdsdev'):
+                    devdb = self.lookup(ref_uuid)
+                    uuid = devdb.get_first_ref('target')
+                    if tgtuuid == uuid:
+                        return ref_uuid
+        return None
+
+    # Change the current active device for a target
+    def update_active(self, tgtuuid, new_uuid):
+        self._update_active(tgtuuid, new_uuid)
+
+class LustreDB_XML(LustreDB):
+    def __init__(self, dom, root_node):
+        # init xmlfile
+        self.dom_node = dom
+        self.root_node = root_node
+
+    def xmltext(self, dom_node, tag):
+        list = dom_node.getElementsByTagName(tag)
+        if len(list) > 0:
+            dom_node = list[0]
+            dom_node.normalize()
+            if dom_node.firstChild:
+                txt = string.strip(dom_node.firstChild.data)
+                if txt:
+                    return txt
+
+    def xmlattr(self, dom_node, attr):
+        return dom_node.getAttribute(attr)
+
+    def _get_val(self, tag):
+        """a value could be an attribute of the current node
+        or the text value in a child node"""
+        ret  = self.xmlattr(self.dom_node, tag)
+        if not ret:
+            ret = self.xmltext(self.dom_node, tag)
+        return ret
+
+    def _get_class(self):
+        return self.dom_node.nodeName
+
+    def get_ref_type(self, ref_tag):
+        res = string.split(ref_tag, '_')
+        return res[0]
+
+    #
+    # [(ref_class, ref_uuid),]
+    def _get_all_refs(self):
+        list = []
+        for n in self.dom_node.childNodes: 
+            if n.nodeType == n.ELEMENT_NODE:
+                ref_uuid = self.xml_get_ref(n)
+                ref_class = self.get_ref_type(n.nodeName)
+                list.append((ref_class, ref_uuid))
+                    
+        list.sort()
+        return list
+
+    def _get_refs(self, tag):
+        """ Get all the refs of type TAG.  Returns list of uuids. """
+        uuids = []
+        refname = '%s_ref' % tag
+        reflist = self.dom_node.getElementsByTagName(refname)
+        for r in reflist:
+            uuids.append(self.xml_get_ref(r))
+        return uuids
+
+    def xmllookup_by_uuid(self, dom_node, uuid):
+        for n in dom_node.childNodes:
+            if n.nodeType == n.ELEMENT_NODE:
+                if self.xml_get_uuid(n) == uuid:
+                    return n
+                else:
+                    n = self.xmllookup_by_uuid(n, uuid)
+                    if n: return n
+        return None
+
+    def _lookup_by_uuid(self, uuid):
+        dom = self. xmllookup_by_uuid(self.root_node, uuid)
+        if dom:
+            return LustreDB_XML(dom, self.root_node)
+
+    def xmllookup_by_name(self, dom_node, name):
+        for n in dom_node.childNodes:
+            if n.nodeType == n.ELEMENT_NODE:
+                if self.xml_get_name(n) == name:
+                    return n
+                else:
+                    n = self.xmllookup_by_name(n, name)
+                    if n: return n
+        return None
+
+    def _lookup_by_name(self, name, class_name):
+        dom = self.xmllookup_by_name(self.root_node, name)
+        if dom:
+            return LustreDB_XML(dom, self.root_node)
+
+    def xmllookup_by_class(self, dom_node, class_name):
+        return dom_node.getElementsByTagName(class_name)
+
+    def _lookup_by_class(self, class_name):
+        ret = []
+        domlist = self.xmllookup_by_class(self.root_node, class_name)
+        for node in domlist:
+            ret.append(LustreDB_XML(node, self.root_node))
+        return ret
+
+    def xml_get_name(self, n):
+        return n.getAttribute('name')
+        
+    def getName(self):
+        return self.xml_get_name(self.dom_node)
+
+    def xml_get_ref(self, n):
+        return n.getAttribute('uuidref')
+
+    def xml_get_uuid(self, dom_node):
+        return dom_node.getAttribute('uuid')
+
+    def getUUID(self):
+        return self.xml_get_uuid(self.dom_node)
+
+    def get_routes(self, type, gw):
+        """ Return the routes as a list of tuples of the form:
+        [(type, gw, lo, hi),]"""
+        res = []
+        tbl = self.dom_node.getElementsByTagName('routetbl')
+        for t in tbl:
+            routes = t.getElementsByTagName('route')
+            for r in routes:
+                net_type = self.xmlattr(r, 'type')
+                if type != net_type:
+                    lo = self.xmlattr(r, 'lo')
+                    hi = self.xmlattr(r, 'hi')
+                    res.append((type, gw, lo, hi))
+        return res
+
+    def get_route_tbl(self):
+        ret = []
+        for r in self.dom_node.getElementsByTagName('route'):
+            net_type = self.xmlattr(r, 'type')
+            gw = self.xmlattr(r, 'gw')
+            lo = self.xmlattr(r, 'lo')
+            hi = self.xmlattr(r, 'hi')
+            ret.append((net_type, gw, lo, hi))
+        return ret
+
+    def _update_active(self, tgt, new):
+        raise LconfError("updates not implemented for XML")
+
+# ================================================================    
+# LDAP Support
+class LustreDB_LDAP(LustreDB):
+    def __init__(self, name, attrs,
+                 base = "fs=lustre",
+                 parent = None,
+                 url  = "ldap://localhost",
+                 user = "cn=Manager, fs=lustre",
+                 pw   = "secret"
+                 ):
+        self._name = name
+        self._attrs = attrs
+        self._base = base
+        self._parent = parent
+        self._url  = url
+        self._user = user
+        self._pw   = pw
+        if parent:
+            self.l = parent.l
+            self._base = parent._base
+        else:
+            self.open()
+
+    def open(self):
+        import ldap
+        try:
+            self.l = ldap.initialize(self._url)
+            # Set LDAP protocol version used
+            self.l.protocol_version=ldap.VERSION3
+            # user and pw only needed if modifying db
+            self.l.bind_s(self._user, self._pw, ldap.AUTH_SIMPLE);
+        except ldap.LDAPError, e:
+            raise LconfError(e)
+            # FIXME, do something useful here
+
+    def close(self):
+        self.l.unbind_s()
+
+    def ldap_search(self, filter):
+        """Return list of uuids matching the filter."""
+        import ldap
+        dn = self._base
+        ret = []
+        uuids = []
+        try:
+            for name, attrs in self.l.search_s(dn, ldap.SCOPE_ONELEVEL,
+                                        filter, ["uuid"]):
+                for v in attrs['uuid']:
+                    uuids.append(v)
+        except ldap.NO_SUCH_OBJECT, e:
+            pass
+        except ldap.LDAPError, e:
+            print e                     # FIXME: die here?
+        if len(uuids) > 0:
+            for uuid in uuids:
+                ret.append(self._lookup_by_uuid(uuid))
+        return ret
+
+    def _lookup_by_name(self, name, class_name):
+        list =  self.ldap_search("lustreName=%s" %(name))
+        if len(list) == 1:
+            return list[0]
+        return None
+
+    def _lookup_by_class(self, class_name):
+        return self.ldap_search("objectclass=%s" %(string.upper(class_name)))
+
+    def _lookup_by_uuid(self, uuid):
+        import ldap
+        dn = "uuid=%s,%s" % (uuid, self._base)
+        ret = None
+        try:
+            for name, attrs in self.l.search_s(dn, ldap.SCOPE_BASE,
+                                               "objectclass=*"):
+                ret = LustreDB_LDAP(name, attrs,  parent = self)
+                        
+        except ldap.NO_SUCH_OBJECT, e:
+            pass                        # just return empty list
+        except ldap.LDAPError, e:
+            print e                     # FIXME: die here?
+        return ret
+
+
+    def _get_val(self, k):
+        ret = None
+        if self._attrs.has_key(k):
+            v = self._attrs[k]
+            if type(v) == types.ListType:
+                ret = str(v[0])
+            else:
+                ret = str(v)
+        return ret
+
+    def _get_class(self):
+        return string.lower(self._attrs['objectClass'][0])
+
+    def get_ref_type(self, ref_tag):
+        return ref_tag[:-3]
+
+    #
+    # [(ref_class, ref_uuid),]
+    def _get_all_refs(self):
+        list = []
+        for k in self._attrs.keys():
+            if re.search('.*Ref', k):
+                for uuid in self._attrs[k]:
+                    ref_class = self.get_ref_type(k)
+                    list.append((ref_class, uuid))
+        return list
+
+    def _get_refs(self, tag):
+        """ Get all the refs of type TAG.  Returns list of uuids. """
+        uuids = []
+        refname = '%sRef' % tag
+        if self._attrs.has_key(refname):
+            return self._attrs[refname]
+        return []
+
+    def getName(self):
+        return self._get_val('lustreName')
+
+    def getUUID(self):
+        return self._get_val('uuid')
+
+    def get_route_tbl(self):
+        return []
+
+    def _update_active(self, tgtuuid, newuuid):
+        """Return list of uuids matching the filter."""
+        import ldap
+        dn = "uuid=%s,%s" %(tgtuuid, self._base)
+        ret = []
+        uuids = []
+        try:
+            self.l.modify_s(dn, [(ldap.MOD_REPLACE, "activeRef", newuuid)])
+        except ldap.NO_SUCH_OBJECT, e:
+            print e
+        except ldap.LDAPError, e:
+            print e                     # FIXME: die here?
+        return 
+
+
diff --git a/lustre/utils/lactive b/lustre/utils/lactive
new file mode 100644 (file)
index 0000000..6fd5815
--- /dev/null
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+#
+#  Copyright (C) 2002 Cluster File Systems, Inc.
+#   Author: Robert Read <rread@clusterfs.com>
+#   This file is part of Lustre, http://www.lustre.org.
+#
+#   Lustre is free software; you can redistribute it and/or
+#   modify it under the terms of version 2 of the GNU General Public
+#   License as published by the Free Software Foundation.
+#
+#   Lustre is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with Lustre; if not, write to the Free Software
+#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+# Make the new node the active node for all devices it shares with the
+# old. The bulk of this code is for figuring out which devices to
+# change, and what to change them to.
+
+# XXX add error checking
+# XXX make this code less ugly
+
+import sys, getopt, types
+import string, os
+import ldap
+import Lustre
+
+lactive_options = [
+    ('ldapurl',"LDAP server URL, eg. ldap://localhost", Lustre.Options.PARAM),
+    ('config', "Cluster config name used for LDAP query", Lustre.Options.PARAM),
+    ('old', "The old, failed node name", Lustre.Options.PARAM),
+    ('new', "The new node name", Lustre.Options.PARAM),
+    ]
+
+cl = Lustre.Options("lactive","", lactive_options)
+config, args = cl.parse(sys.argv[1:])
+
+base = "config=%s,fs=lustre" % (config.config,)
+db = Lustre.LustreDB_LDAP('', {}, base=base, url = config.ldapurl)
+
+old = db.lookup_name(config.old)
+new = db.lookup_name(config.new)
+
+print "old:", old.getUUID()
+print "new:",  new.getUUID()
+
+# find all the targets on the failed node and, change the active
+# pointers to point to the devices on the new node.
+prof_list = old.get_refs('profile')
+for prof_uuid in prof_list:
+    prof_db = db.lookup(prof_uuid)
+    if not prof_db:
+        panic("profile:", profile, "not found.")
+    for ref_class, ref_uuid in prof_db.get_all_refs(): 
+        if ref_class in ('osd', 'mdsdev'):
+            devdb = db.lookup(ref_uuid)
+            tgtuuid = devdb.get_first_ref('target')
+            active_uuid = old.get_active_dev(tgtuuid)
+            if ref_uuid != active_uuid:
+                continue
+            inactive_uuid = new.get_tgt_dev(tgtuuid)
+            print ("%s: changing active %s:%s to %s:%s"
+                   % (tgtuuid, config.old, active_uuid,
+                      config.new, inactive_uuid))
+            db.update_active(tgtuuid, inactive_uuid)
+
+
+
diff --git a/lustre/utils/load_ldap.sh b/lustre/utils/load_ldap.sh
new file mode 100755 (executable)
index 0000000..531d385
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Load a lustre config xml into an openldap database.
+# See https://projects.clusterfs.com/lustre/LustreLDAP
+# for more details.
+#
+# Usage: load_ldap.sh <xml_file>
+set -e
+
+LDAP_BASE=${LDAP_BASE:-fs=lustre}
+LDAP_ROOTDN=${LDAP_ROOTDN:-cn=Manager,fs=lustre}
+LDAP_PW=${LDAP_PW:-secret}
+LDAP_AUTH="-x -D $LDAP_ROOTDN -w $LDAP_PW"
+LUSTRE=${LUSTRE:-`dirname $0`/..}
+
+[ ! -z $LDAPURL ] && LDAP_AUTH="$LDAP_AUTH -H $LDAPURL"
+
+XML=${XML:-$1}
+
+if [ -z "$XML" ] || [  ! -r $XML ]; then
+     echo "usage: $0 xmlfile"
+     exit 1
+fi
+
+NAME=`basename $XML .xml`
+LDIF=/tmp/$NAME.ldif
+
+# add the top level record, if needed
+ldapsearch $LDAP_AUTH -b $LDAP_BASE > /dev/null 2>&1 ||
+    ldapadd $LDAP_AUTH -f $LUSTRE/conf/top.ldif
+
+# If this config already exists, then delete it
+ldapsearch $LDAP_AUTH -b config=$NAME,$LDAP_BASE > /dev/null 2>&1 && 
+    ldapdelete $LDAP_AUTH -r config=$NAME,$LDAP_BASE
+
+4xslt -D config=$NAME $XML $LUSTRE/conf/lustre2ldif.xsl  > $LDIF
+
+echo "Loading config to 'config=$NAME,$LDAP_BASE' ..."
+ldapadd $LDAP_AUTH -f $LDIF
+
+rm -f $LDIF