- lconf gets a new option, --recover and will do recovery for a connection on the client
- fix bug reported by Morrone where a client would use the elan nid even
when it wanted to use tcp. (untested)
- And the bulk of this patch is a consolidation of the command line processing
for the python tools. Now all options are displayed in the usage string,
and includes the defaults if any. It's also trivial to add new options now.
__all__ = ["lustredb"]
from lustredb import LustreDB, LustreDB_XML, LustreDB_LDAP
-from error import LconfError
+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
+ 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) == Options.PARAM:
+ 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
+ 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) == Options.PARAM:
+ 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.PARAM, 100),
+
+ ])
+
+ conf, args = cl.parse(sys.argv[1:])
+
+ for key in conf.values.keys():
+ print "%-10s = %s" % (key, conf.values[key])
def __init__(self, args):
self.args = args
+class OptionError (exceptions.Exception):
+ def __init__(self, args):
+ self.args = args
+
# Find the target_device for target on a node
# node->profiles->device_refs->target
- def get_target_device(self, target_uuid, node_name):
+ def get_node_tgt_dev(self, node_name, target_uuid):
node_db = self.lookup_name(node_name)
if not node_db:
return None
- prof_list = node_db.get_refs('profile')
- for prof_uuid in prof_list:
- prof_db = node_db.lookup(prof_uuid)
- ref_list = prof_db.get_all_refs()
- for ref in ref_list:
- dev = self.lookup(ref[1])
- if dev and dev.get_first_ref('target') == target_uuid:
- return ref[1]
- return None
+ return self.get_tgt_dev(target_uuid)
# get all network uuids for this node
def get_networks(self):
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)
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):
for n in self.dom_node.childNodes:
if n.nodeType == n.ELEMENT_NODE:
ref_uuid = self.xml_get_ref(n)
- ref_class = n.nodeName
+ ref_class = self.get_ref_type(n.nodeName)
list.append((ref_class, ref_uuid))
list.sort()
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):
for k in self._attrs.keys():
if re.search('.*Ref', k):
for uuid in self._attrs[k]:
- list.append((k, uuid))
+ ref_class = self.get_ref_type(k)
+ list.append((ref_class, uuid))
return list
def _get_refs(self, tag):
ret = []
uuids = []
try:
- print tgtuuid, newuuid
self.l.modify_s(dn, [(ldap.MOD_REPLACE, "activeRef", newuuid)])
except ldap.NO_SUCH_OBJECT, e:
print e
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),
+ ]
-def usage():
- print """usage: lactive --ldapurl <ldapurl> --old <name> --new <name>"""
- sys.exit(1)
-
-def parse_cmdline(argv):
- short_opts = "h"
- long_opts = ["help", "new=", "old=", "ldapurl=",]
- opts = []
- args = []
- config = {}
+cl = Lustre.Options("lactive","", lactive_options)
+config, args = cl.parse(sys.argv[1:])
- try:
- opts, args = getopt.getopt(argv, short_opts, long_opts)
- except getopt.error:
- print "invalid opt"
- usage()
-
- for o, a in opts:
- if o in ("-h", "--help"):
- usage()
- if o in ("--old",):
- config['old'] = a
- if o in ("--new",):
- config['new'] = a
- if o in ("--ldapurl",):
- config['ldapurl'] = a
+base = "config=%s,fs=lustre" % (config.config,)
+db = Lustre.LustreDB_LDAP('', {}, base=base, url = config.ldapurl)
- return config
-
-def get_active(db, tgtuuid):
- tgt = db.lookup(tgtuuid)
- tgt_dev_uuid =tgt.get_first_ref('active')
- return tgt_dev_uuid
-
-def get_inactive(db, tgtuuid):
- prof_list = db.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 ('osdRef', 'mdsdevRef'):
- devdb = db.lookup(ref_uuid)
- uuid = devdb.get_first_ref('target')
- if tgtuuid == uuid:
- return ref_uuid
- return None
-
-
-config = parse_cmdline(sys.argv[1:])
-
-db = Lustre.LustreDB_LDAP('', {}, base="config=test23,fs=lustre",
- url = config['ldapurl'])
-
-old = db.lookup_name(config['old'])
-new = db.lookup_name(config['new'])
+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.
+# 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 ('osdRef', 'mdsdevRef'):
+ if ref_class in ('osd', 'mdsdev'):
devdb = db.lookup(ref_uuid)
tgtuuid = devdb.get_first_ref('target')
- active_uuid = get_active(old, tgtuuid)
+ active_uuid = old.get_active_dev(tgtuuid)
if ref_uuid != active_uuid:
continue
- inactive_uuid = get_inactive(new, tgtuuid)
+ 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))
+ % (tgtuuid, config.old, active_uuid,
+ config.new, inactive_uuid))
db.update_active(tgtuuid, inactive_uuid)