From 438f2621a21a54ba92694a9f6fa49c4f7947488b Mon Sep 17 00:00:00 2001 From: rread Date: Tue, 6 Aug 2002 07:55:06 +0000 Subject: [PATCH] - auto-naming is now smarter - most basic features implemented, except for profile --- lustre/utils/lmc | 316 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 268 insertions(+), 48 deletions(-) diff --git a/lustre/utils/lmc b/lustre/utils/lmc index 7e251db..d088153 100755 --- a/lustre/utils/lmc +++ b/lustre/utils/lmc @@ -19,50 +19,71 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # -# lmc - lustre configurtion data manager -# -import sys, getopt +""" +lmc - lustre configurtion data manager + + Basic plan for lmc usage: + lmc --output config.xml --node nodename nid nettype [port=2346] + lmc --merge config.xml --lov lovname stripsize stripeoffset + lmc --merge config.xml --ost /dev/name nodename lovname [size=9999] + lmc --merge config.xml --mtpt /mnt/lustre lovname nodename +""" + +import sys, getopt, string import xml.dom.minidom from xml.dom.ext import PrettyPrint +from xml.xpath import Evaluate +DEFAULT_PORT = 888 # XXX What is the right default acceptor port to use? def usage(): - print """usage: lmc [--ost | --mtpt | --lov] cmd args + print """usage: lmc [--node --ost | --mtpt | --lov] args Commands: ---ost "device" "host" [size] +--node node_name hostname nettype [port] + Node_name is used to refer to this node during the configure process. + Nettype is either tcp, elan, or gm. + +--lov lov_name mdc_name stripe_sz stripe_off pattern + Creates a logical volume + +--mds node_name device [size] + +--ost device node_name lov_name [size] Creates an OBD/OST/OSC configuration triplet for a new device. When used on "host", the device will be initialized and the OST will be enabled. On client nodes, the OSC will be avaiable. + If lov_name is used, this device is added to lov. ---osc "device" "host" [lov_name] - Create an osc, and optionally add it to an lov. - ---mtpt "mds" "ost/lov-name" /mnt/point +--mtpt node_name mds_name lov_name /mnt/point Creates a client mount point. ---lov lov_name mdc_name stripe_sz stripe_off pattern - Produces a logical volum striped over the OSTs found in all-ost.xml. - Options: --merge="xml file" Add the new objects to an existing file --format Format the partitions if unformated --reformat Reformat partitions (this should be an lconf arg, I think) -(SCRIPT STILL UNDER DEVELOPMENT, MOST COMMANDS/OPTIONS UNIMPLEMENTED) -""" +""" + sys.exit(1) +def error(*args): + msg = string.join(map(str,args)) + print msg + sys.exit(1) + # # manage names and uuids # need to initialize this by walking tree to ensure # no duplicate names or uuids are created. # this are just place holders for now. # consider changing this to be like OBD-dev-host -name_ctr = 1 def new_name(base): - global name_ctr - name = "%s_%d" % (base, name_ctr) - name_ctr += 1 - return name + ctr = 2 + ret = base + while names.has_key(ret): + ret = "%s_%d" % (base, ctr) + ctr = 1 + ctr + names[ret] = 1 + return ret def get_uuid(name): return "%s_UUID" % (name) @@ -72,6 +93,15 @@ def new_lustre(dom): str = """ """ return dom.parseString(str) +names = {} +uuids = {} +def init_names(lustre): + """initialize auto-name generation tables""" + global names, uuids + # get all elements that contain a name attribute + for n in Evaluate("//@name/..", lustre): + names[n.getAttribute("name")] = 1 + uuids[n.getAttribute("uuid")] = 1 class GenConfig: doc = None @@ -106,7 +136,7 @@ class GenConfig: node.appendChild(new) return new - def network(self, name, uuid, net, hostname, port=0): + def network(self, name, uuid, hostname, net, port=0): """create node""" network = self.newService("network", name, uuid) network.setAttribute("type", net); @@ -120,7 +150,7 @@ class GenConfig: node = self.newService("node", name, uuid) return node - def obd(self, name, uuid, fs, devname, format, dev_size=0, dev_file=""): + def obd(self, name, uuid, fs, devname, format, dev_size=0): obd = self.newService("obd", name, uuid) obd.setAttribute('type', 'obdfilter') self.addElement(obd, "fstype", fs) @@ -132,7 +162,7 @@ class GenConfig: def osc(self, name, uuid, obd_uuid, net_uuid): osc = self.newService("osc", name, uuid) - osc.appendChild(self.ref("network", net_uuid)) + osc.appendChild(self.ref("ost", net_uuid)) osc.appendChild(self.ref("obd", obd_uuid)) return osc @@ -142,51 +172,220 @@ class GenConfig: ost.appendChild(self.ref("obd", obd_uuid)) return ost + def lov(self, name, uuid, stripe_sz, stripe_off, pattern): + lov = self.newService("lov", name, uuid) + devs = self.addElement(lov, "devices" ) + devs.setAttribute("stripesize", stripe_sz) + devs.setAttribute("stripeoffset", stripe_off) + devs.setAttribute("pattern", pattern) + return lov + + def mds(self, name, uuid, fs, devname, format, net_uuid, failover_uuid = "", dev_size=0 ): + mds = self.newService("mds", name, uuid) + self.addElement(mds, "fstype", fs) + dev = self.addElement(mds, "device", devname) + if dev_size: + dev.setAttribute("size", "%s" % (dev_size)) + self.addElement(mds, "autoformat", format) + mds.appendChild(self.ref("network", net_uuid)) + if failover_uuid: + mds.appendChild(self.ref("failover", failover_uuid)) + return mds + + def mdc(self, name, uuid, mds_uuid): + mdc = self.newService("mdc", name, uuid) + mdc.appendChild(self.ref("mds", mds_uuid)) + return mdc + + def mountpoint(self, name, uuid, mdc_uuid, osc_uuid, path): + mtpt = self.newService("mtpt", name, uuid) + mtpt.appendChild(self.ref("mdc", mdc_uuid)) + mtpt.appendChild(self.ref("osc", osc_uuid)) + self.addElement(mtpt, "path", path) + return mtpt + +def findByName(lustre, name, tag = "*"): + path = '//%s[@name="%s"]' % (tag, name) + ret = Evaluate(path, lustre) + if ret: + return ret[0] + return None + +# XXX: assumes only one network element per node. will fix this +# as soon as support for routers is added +def get_net_uuid(lustre, node_name): + """ get a network uuid for a node_name """ + node = findByName(lustre, node_name, "node") + if not node: + error ("node not found:", node_name) + net = Evaluate("./network", node) + if net: + return net[0].getAttribute("uuid") + return None + +def lov_add_osc(gen, lov, osc_uuid): + devs = Evaluate("devices", lov) + if len(devs) == 1: + devs[0].appendChild(gen.ref("osc", osc_uuid)) + else: + error("No devices element found for LOV:", lov) + + # # Create a new obd, osc, and ost. Add them to the DOM. # -def add_OST(doc, options, args): - # XXX need some error checking - gen = GenConfig(doc) +def add_ost(gen, lustre, options, args): + if len(args) < 3: + usage() + devname = args[0] - host = args[1] - if len(args) > 2: - size = args[2] + node_name = args[1] + lovname = args[2] + if len(args) > 3: + size = args[3] else: size = 0 - lustre = doc.getElementsByTagName("lustre")[0] - - obdname = new_name("obd") - oscname = new_name("osc") - ostname = new_name("ost") - node_uuid = get_uuid(host) - net_uuid = get_uuid("net") + obdname = new_name(node_name+"_" + "obd") + oscname = new_name(node_name+"_"+"osc") + ostname = new_name(node_name+"_"+"ost") obd_uuid = get_uuid(obdname) ost_uuid = get_uuid(ostname) osc_uuid = get_uuid(oscname) - node = gen.node(host, node_uuid) - node.appendChild(gen.network(host, net_uuid, "tcp", host, port=2436)) + net_uuid = get_net_uuid(lustre, node_name) + if not net_uuid: + error("NODE: ", node_name, "not found") + + lov = findByName(lustre, lovname, "lov") + if not lov: + error("LOV:", lovname, "not found.") + obd = gen.obd(obdname, obd_uuid, "extN", devname, "no", size) ost = gen.ost(ostname, ost_uuid, obd_uuid, net_uuid) - osc = gen.osc(oscname, osc_uuid, obd_uuid, net_uuid) + osc = gen.osc(oscname, osc_uuid, obd_uuid, ost_uuid) - lustre.appendChild(node) + lov_add_osc(gen, lov, osc_uuid) lustre.appendChild(obd) lustre.appendChild(osc) lustre.appendChild(ost) +def add_node(gen, lustre, options, args): + """ create a node with a network config """ + if len(args) < 3: + usage() + + name = args[0] + nid = args[1] + nettype = args[2] + + if nettype == 'tcp': + if len(args) > 3: + port = int(args[3]) + else: + port = DEFAULT_PORT + + elif nettype in ('elan', 'gm'): + port = 0 + else: + print "Unknown nettype: ", nettype + sys.exit(2) + + uuid = get_uuid(name) + node = gen.node(name, uuid) + net_name = name+"_net" + net_uuid = get_uuid(net_name) + node.appendChild(gen.network(net_name, net_uuid, nid, nettype, port)) + lustre.appendChild(node) + + +def add_lov(gen, lustre, options, args): + """ create a lov """ + if len(args) < 4: + usage() + + name = args[0] + stripe_sz = args[1] + stripe_off = args[2] + pattern = args[3] + + ret = findByName(lustre, name, "lov") + if ret: + error("LOV: ", name, " already exists.") + + uuid = get_uuid(name) + lov = gen.lov(name,uuid,stripe_sz, stripe_off, pattern) + lustre.appendChild(lov) + +def add_mtpt(gen, lustre, options, args): + """ create mtpt on a node """ + if len(args) < 4: + usage() + + node_name = args[0] + mdc_name = args[1] + lov_name = args[2] + path = args[3] + + name = new_name(node_name + "_mtpt") + + ret = findByName(lustre, name, "mountpoint") + if ret: + error("MOUNTPOINT: ", name, " already exists.") + + ret = findByName(lustre, lov_name, "lov") + if not ret: + error("LOV: ", lov_name, " not found.") + lov_uuid = ret.getAttribute("uuid") + + ret = findByName(lustre, mdc_name, "mdc") + if not ret: + error("MDC: ", mdc_name, " not found.") + mdc_uuid = ret.getAttribute("uuid") + + uuid = get_uuid(name) + mtpt = gen.mountpoint(name, uuid, mdc_uuid, lov_uuid, path) + lustre.appendChild(mtpt) + + +def add_mds(gen, lustre, options, args): + if len(args) < 3: + usage() + + node_name = args[0] + devname = args[1] + if len(args) > 3: + size = args[3] + else: + size = 0 + + ret = findByName(lustre, node_name, "node") + + mds_name = new_name(node_name+"_" + "mds") + mdc_name = new_name(node_name+"_"+"mdc") + mds_uuid = get_uuid(mds_name) + mdc_uuid = get_uuid(mdc_name) + + net_uuid = get_net_uuid(lustre, node_name) + if not net_uuid: + error("NODE: ", node_name, "not found") + + + mds = gen.mds(mds_name, mds_uuid, "extN", devname, "no", net_uuid) + mdc = gen.mdc(mdc_name, mdc_uuid, mds_uuid) + lustre.appendChild(mds) + lustre.appendChild(mdc) + # # Command line processing # def parse_cmdline(argv): - short_opts = "ho:" - long_opts = ["ost", "mtpt", "lov", + short_opts = "ho:i:" + long_opts = ["ost", "mtpt", "lov", "node", "mds", "merge=", "format", "reformat", "output=", - "help"] + "in=", "help"] opts = [] args = [] options = {} @@ -195,22 +394,30 @@ def parse_cmdline(argv): except getopt.GetoptError: print "invalid opt" usage() - sys.exit(2) for o, a in opts: if o in ("-h", "--help"): usage() - sys.exit() if o in ("-o", "--output"): options['output'] = a if o == "--ost": options['ost'] = 1 + if o == "--mds": + options['mds'] = 1 + if o == "--node": + options['node'] = 1 + if o == "--lov": + options['lov'] = 1 + if o == "--mtpt": + options['mtpt'] = 1 if o == "--merge": options['merge'] = a if o == "--format": options['format'] = 1 if o == "--reformat": options['reformat'] = 1 + if o in ("--in" , "-i"): + options['in'] = a return options, args @@ -221,22 +428,35 @@ def main(): if options.has_key('merge'): outFile = options['merge'] doc = xml.dom.minidom.parse(outFile) + elif options.has_key('in'): + doc = xml.dom.minidom.parse(options['in']) else: doc = new_lustre(xml.dom.minidom) if options.has_key('output'): outFile = options['output'] + lustre = doc.documentElement + init_names(lustre) + lustre = doc.documentElement + if lustre.tagName != "lustre": + print "Existing config not valid." + sys.exit(1) + + gen = GenConfig(doc) if options.has_key('ost'): - add_OST(doc, options, args) + add_ost(gen, lustre, options, args) + elif options.has_key('node'): + add_node(gen, lustre, options, args) elif options.has_key('mtpt'): - print "--mtpt not implemented" + add_mtpt(gen, lustre, options, args) elif options.has_key('lov'): - print "--lov not implemented" + add_lov(gen, lustre, options, args) + elif options.has_key('mds'): + add_mds(gen, lustre, options, args) else: print "Missing command" usage() - sys.exit(1) if outFile == '-': PrettyPrint(doc) -- 1.8.3.1