--- /dev/null
+--- 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)
--- /dev/null
+include/linux/mm.h
+mm/filemap.c
--- /dev/null
+/* -*- 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);
+}
--- /dev/null
+#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;
+}
--- /dev/null
+Makefile
+Makefile.in
+.deps
+*.pyc
--- /dev/null
+pymod_SCRIPTS = __init__.py lustredb.py error.py cmdline.py
+EXTRA_DIST = $(pymod_SCRIPTS)
--- /dev/null
+__all__ = ["lustredb"]
+
+from lustredb import LustreDB, LustreDB_XML, LustreDB_LDAP
+from error import LconfError, OptionError
+from cmdline import Options
--- /dev/null
+#!/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])
--- /dev/null
+import exceptions
+
+class LconfError (exceptions.Exception):
+ def __init__(self, args):
+ self.args = args
+
+class OptionError (exceptions.Exception):
+ def __init__(self, args):
+ self.args = args
+
--- /dev/null
+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
+
+
--- /dev/null
+#!/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)
+
+
+
--- /dev/null
+#!/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