From: eeb Date: Sun, 6 Apr 2003 14:44:11 +0000 (+0000) Subject: * Up to date b_devel (SWAB_LAND) X-Git-Tag: v1_7_110~1^13~219 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=99d3a4f69c863a908f899fbbaf658c1cf41045fa;p=fs%2Flustre-release.git * Up to date b_devel (SWAB_LAND) --- diff --git a/lustre/kernel_patches/patches/export-truncate.patch b/lustre/kernel_patches/patches/export-truncate.patch new file mode 100644 index 0000000..12e6f440b --- /dev/null +++ b/lustre/kernel_patches/patches/export-truncate.patch @@ -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 index 0000000..bd58c82 --- /dev/null +++ b/lustre/kernel_patches/pc/export-truncate.pc @@ -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 index 0000000..ab5cbdb --- /dev/null +++ b/lustre/tests/openfile.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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 index 0000000..ba1bee7 --- /dev/null +++ b/lustre/tests/unlinkmany.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 index 0000000..97e22b9 --- /dev/null +++ b/lustre/utils/Lustre/.cvsignore @@ -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 index 0000000..e8e522f --- /dev/null +++ b/lustre/utils/Lustre/Makefile.am @@ -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 index 0000000..a4f4367 --- /dev/null +++ b/lustre/utils/Lustre/__init__.py @@ -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 index 0000000..d87da80 --- /dev/null +++ b/lustre/utils/Lustre/cmdline.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# +# Copyright (C) 2002 Cluster File Systems, Inc. +# Author: Robert Read +# 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 " % (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 index 0000000..6c30416 --- /dev/null +++ b/lustre/utils/Lustre/error.py @@ -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 index 0000000..14be906 --- /dev/null +++ b/lustre/utils/Lustre/lustredb.py @@ -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 index 0000000..6fd5815 --- /dev/null +++ b/lustre/utils/lactive @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# +# Copyright (C) 2002 Cluster File Systems, Inc. +# Author: Robert Read +# 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 index 0000000..531d385 --- /dev/null +++ b/lustre/utils/load_ldap.sh @@ -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 +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