#!/usr/bin/env python
-#
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Robert Read <rread@clusterfs.com>
+# Copyright (C) 2002 Cluster File Systems, Inc.
+# Author: Robert Read <rread@clusterfs.com>
# This file is part of Lustre, http://www.lustre.org.
#
# 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:
+# create nodes
+./lmc --output config.xml --node server --net server1 tcp
+./lmc --merge config.xml --node client --net client1 tcp
+./lmc --merge config.xml --node client --route gw lo [hi]
+./lmc --merge config.xml --router --node gw1 --net gw1 tcp
+./lmc --merge config.xml --node gw1 --net 1 elan
+
+./lmc --merge config.xml --route elan 1 1 100
+./lmc --merge config.xml --route tcp gw1 ba1
+
+
+
+# configure server
+./lmc --merge config.xml --node server --mds mds1 /tmp/mds1 50000
+
+# create lov
+./lmc --merge config.xml --lov lov1 mds1 65536 0 0
+./lmc --merge config.xml --node server --lov lov1 --ost /tmp/ost1 100000
+./lmc --merge config.xml --node server --lov lov1 --ost /tmp/ost2 100000
+
+# create client config
+./lmc --merge config.xml --node client --mtpt /mnt/lustre mds1 lov1
+
+"""
+
+import sys, os, getopt, string
import xml.dom.minidom
+from xml.dom.ext import PrettyPrint
+DEFAULT_PORT = 988 # 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
+ Node_name by itself it will create a new node. If the --router
+ option is used when creating a new node, then that node will also
+ be configured as a router. When used with other commands it
+ specifies the node to modify.
+
+--net hostname nettype [port, recv_buf, send_buf]
+ Nettype is either tcp, toe, elan, or gm.
+ Requires --node
+
+--route net gw lo [hi]
+ This command is used to create routes. NET is the
+ network type this route will be used on. The GW is an address of
+ one of the local interfaces. LO and HI represent a range of
+ addresses that can be reached through the gateway. If HI is not
+ set, then a route to the specific host in LO is created.
+
+--mds device [size]
+ Create a MDS using the device
+ Requires --node
+
+--lov lov_name [mds_name stripe_sz sub_stripe_count pattern]
+ Creates a logical volume
+ When used with other commands, it specifics the lov to modify
+
+--ost device [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.
+ Requires --node
+ Optional --obduuid Specifies the UUID used for the obd.
+ If --lov lov_name is used, this device is added to lov.
---mtpt "mds" "ost/lov-name" /mnt/point
+--mtpt /mnt/point mds_name lov_name|osc_name
Creates a client mount point.
-
---lov "mds" "lov name" < "all-ost.xml"
- Produces a logical volum striped over the OSTs found in all-ost.xml.
- (Not sure how all-ost.xml is created, exactly.)
+ Requires --node
Options:
--merge="xml file" Add the new objects to an existing file
--format Format the partitions if unformated
+ NB: The autoformat option has been disabled until a safe
+ method is implemented to determine if a block device has a
+ filesystem.
--reformat Reformat partitions (this should be an lconf arg,
I think)
-(SCRIPT STILL UNDER DEVELOPMENT, MOST COMMANDS/OPTIONS UNIMPLEMENTED)
-"""
+--obdtype="obdtype" Specifiy obdtype: valid ones are obdecho and obdfilter.
+ This is only useful for the --ost command.
+ The device parameters are ignored for the obdecho type.
+"""
+ sys.exit(1)
+def error(*args):
+ msg = string.join(map(str,args))
+ print "Error: ", msg
+ sys.exit(1)
+
+def warning(*args):
+ msg = string.join(map(str,args))
+ print "Warning: ", msg
+
#
# 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):
+def new_uuid(name):
return "%s_UUID" % (name)
-#
-# Create a new empty lustre document
-def new_Lustre():
+ldlm_name = 'ldlm'
+ldlm_uuid = 'ldlm_UUID'
+def new_lustre(dom):
+ """Create a new empty lustre document"""
+ # adding ldlm here is a bit of a hack, but one is enough.
str = """<lustre>
-</lustre>"""
- dom = xml.dom.minidom.parseString(str)
- return dom
+ <ldlm name="%s" uuid="%s"/>
+ </lustre>""" % (ldlm_name, ldlm_uuid)
+ return dom.parseString(str)
+names = {}
+uuids = {}
+
+def init_names(doc):
+ """initialize auto-name generation tables"""
+ global names, uuids
+ # get all elements that contain a name attribute
+ for n in doc.childNodes:
+ if n.nodeType == n.ELEMENT_NODE:
+ if getName(n):
+ names[getName(n)] = 1
+ uuids[getUUID(n)] = 1
+ init_names(n)
+
+def get_format_flag(options):
+ if options.has_key('format'):
+ if options['format']:
+ return 'yes'
+ return 'no'
+
+############################################################
+# Build config objects using DOM
#
-# Create a new object the "correct" way by using the DOM api.
-#
-def new_OBD(dom, name, fs, devname, format, dev_size=0, dev_file=""):
- uuid = get_uuid(name)
+class GenConfig:
+ doc = None
+ dom = None
+ def __init__(self, doc):
+ self.doc = doc
+
+ def ref(self, type, uuid):
+ """ generate <[type]_ref uuidref="[uuid]"/> """
+ tag = "%s_ref" % (type)
+ ref = self.doc.createElement(tag)
+ ref.setAttribute("uuidref", uuid)
+ return ref
- obd = dom.createElement("obd")
- obd.setAttribute("name", name)
- obd.setAttribute("uuid", uuid)
-
- fstype = dom.createElement("fstype")
- txt= dom.createTextNode(fs)
- fstype.appendChild(txt)
- obd.appendChild(fstype)
+ def newService(self, tag, name, uuid):
+ """ create a new service elmement, which requires name and uuid attributes """
+ new = self.doc.createElement(tag)
+ new.setAttribute("name", name);
+ new.setAttribute("uuid", uuid);
+ return new
- dev = dom.createElement("device")
- if (dev_size):
- dev.setAttribute("size", "%s" % (dev_size))
- txt = dom.createTextNode(devname)
- dev.appendChild(txt)
- obd.appendChild(dev)
+ def addText(self, node, str):
+ txt = self.doc.createTextNode(str)
+ node.appendChild(txt)
- fmt = dom.createElement("autoformat")
- txt = dom.createTextNode(format)
- fmt.appendChild(txt)
- obd.appendChild(fmt)
+ def addElement(self, node, tag, str=None):
+ """ create a new element and add it as a child to node. If str is passed,
+ a text node is created for the new element"""
+ new = self.doc.createElement(tag)
+ if str:
+ self.addText(new, str)
+ node.appendChild(new)
+ return new
- return obd
+ def network(self, name, uuid, hostname, net, port=0, tcpbuf=0):
+ """create <network> node"""
+ network = self.newService("network", name, uuid)
+ network.setAttribute("type", net);
+ self.addElement(network, "server", hostname)
+ if port:
+ self.addElement(network, "port", "%d" %(port))
+ if tcpbuf:
+ self.addElement(network, "send_mem", "%d" %(tcpbuf))
+ self.addElement(network, "recv_mem", "%d" %(tcpbuf))
+
+ return network
-#
-# Create new object the fast and easy way
-# (note: dom is not needed for this way)
-def new_OSC(dom, osc, obd):
- osc_uuid = get_uuid(osc)
- obd_uuid = get_uuid(obd)
-
- osc_str ="""
-<osc name="%s" uuid="%s">
- <service_id num="1" name="%s" uuid="%s"/>
-</osc> """ % (osc, osc_uuid, obd, obd_uuid)
- osc = xml.dom.minidom.parseString(osc_str)
- return osc.getElementsByTagName("osc")[0]
+ def route(self, net_type, gw, lo, hi):
+ """ create one entry for the route table """
+ ref = self.doc.createElement('route')
+ ref.setAttribute("type", net_type)
+ ref.setAttribute("gw", gw)
+ ref.setAttribute("lo", lo)
+ if hi:
+ ref.setAttribute("hi", hi)
+ return ref
+
+ def node(self, name, uuid):
+ """ create a host """
+ node = self.newService("node", name, uuid)
+ self.addElement(node, 'profile')
+ return node
-#
-# Create new object the fast and easy way
-#
-def new_OST(dom, ost, host, port, obd):
- ost_uuid = get_uuid(ost)
- obd_uuid = get_uuid(obd)
-
- str ="""
-<ost name="%s" uuid="%s">
- <network type="tcp">
- <server>%s</server>
- <port>%d</port>
- </network>
- <server_id num="1" name="%s" uuid="%s"/>
-</ost> """ % (ost, ost_uuid, host, port, obd, obd_uuid)
- node = xml.dom.minidom.parseString(str)
- return node.getElementsByTagName("ost")[0]
+ def ldlm(self, name, uuid):
+ """ create a ldlm """
+ ldlm = self.newService("ldlm", name, uuid)
+ return ldlm
+ def obd(self, name, uuid, fs, obdtype, devname, format, dev_size=0):
+ obd = self.newService("obd", name, uuid)
+ obd.setAttribute('type', obdtype)
+ if fs:
+ self.addElement(obd, "fstype", fs)
+ if devname:
+ dev = self.addElement(obd, "device", devname)
+ if (dev_size):
+ dev.setAttribute("size", "%s" % (dev_size))
+ self.addElement(obd, "autoformat", format)
+ return obd
+
+ def osc(self, name, uuid, obd_uuid, net_uuid):
+ osc = self.newService("osc", name, uuid)
+ osc.appendChild(self.ref("ost", net_uuid))
+ osc.appendChild(self.ref("obd", obd_uuid))
+ return osc
+
+ def ost(self, name, uuid, obd_uuid, net_uuid):
+ ost = self.newService("ost", name, uuid)
+ ost.appendChild(self.ref("network", net_uuid))
+ ost.appendChild(self.ref("obd", obd_uuid))
+ return ost
+
+ def lov(self, name, uuid, mds_uuid, stripe_sz, stripe_count, pattern):
+ lov = self.newService("lov", name, uuid)
+ lov.appendChild(self.ref("mds", mds_uuid))
+ devs = self.addElement(lov, "devices" )
+ devs.setAttribute("stripesize", stripe_sz)
+ devs.setAttribute("stripecount", stripe_count)
+ devs.setAttribute("pattern", pattern)
+ return lov
+
+ def lovconfig(self, name, uuid, lov_uuid):
+ lovconfig = self.newService("lovconfig", name, uuid)
+ lovconfig.appendChild(self.ref("lov", lov_uuid))
+ return lovconfig
+
+ def mds(self, name, uuid, fs, devname, format, net_uuid, node_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))
+ mds.appendChild(self.ref("node", node_uuid))
+ if failover_uuid:
+ mds.appendChild(self.ref("failover", failover_uuid))
+ return mds
+
+ def mountpoint(self, name, uuid, mds_uuid, osc_uuid, path):
+ mtpt = self.newService("mountpoint", name, uuid)
+ mtpt.appendChild(self.ref("mds", mds_uuid))
+ mtpt.appendChild(self.ref("osc", osc_uuid))
+ self.addElement(mtpt, "path", path)
+ return mtpt
+
+############################################################
+# Utilities to query a DOM tree
+# Using this functions we can treat use config information
+# directly as a database.
+def getName(n):
+ return n.getAttribute('name')
+
+def getUUID(node):
+ return node.getAttribute('uuid')
+
+
+def findByName(lustre, name, tag = ""):
+ for n in lustre.childNodes:
+ if n.nodeType == n.ELEMENT_NODE:
+ if tag and n.nodeName != tag:
+ continue
+ if getName(n) == name:
+ return n
+ else:
+ n = findByName(n, name)
+ if n: return n
+ return None
+
+
+def lookup(node, uuid):
+ for n in node.childNodes:
+ if n.nodeType == n.ELEMENT_NODE:
+ if getUUID(n) == uuid:
+ return n
+ else:
+ n = lookup(n, uuid)
+ if n: return n
+ return None
+
+
+def mds2node(lustre, mds_name):
+ """ Find the node a MDS is configured on """
+ mds = findByName(lustre, mds_name, 'mds')
+ ref = mds.getElementsByTagName('node_ref')
+ if not ref:
+ error("mds2node:", "no node_ref found for", '"'+mds_name+'"')
+ node_uuid = ref[0].getAttribute('uuidref')
+ node = lookup(lustre, node_uuid)
+ if not node:
+ error('mds2node:', "no node found for :", '"'+mds_name+'"')
+ return node
+
+
+def name2uuid(lustre, name, tag="", fatal=1):
+ ret = findByName(lustre, name, tag)
+ if not ret:
+ if fatal:
+ error('name2uuid:', '"'+name+'"', tag, 'element not found.')
+ else:
+ return ""
+ return getUUID(ret)
+
+
+# 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 ('get_net_uuid:', '"'+node_name+'"', "node element not found.")
+ net = node.getElementsByTagName('network')
+ if net:
+ return getUUID(net[0])
+ return None
+
+
+def lov_add_osc(gen, lov, osc_uuid):
+ devs = lov.getElementsByTagName('devices')
+ if len(devs) == 1:
+ devs[0].appendChild(gen.ref("osc", osc_uuid))
+ else:
+ error("No devices element found for LOV:", lov)
+
+
+def node_add_profile(gen, node, ref, uuid):
+ ret = node.getElementsByTagName('profile')
+ if not ret:
+ error('node has no profile:', node)
+ ret[0].appendChild(gen.ref(ref, uuid))
+
+def get_attr(dom_node, attr, default=""):
+ v = dom_node.getAttribute(attr)
+ if v:
+ return v
+ return default
+
+############################################################
+# Top level commands
#
-# Create a new obd, osc, and ost. Add them to the DOM.
-#
-def add_OST(dom, options, args):
- # XXX need some error checking
+def do_add_node(gen, lustre, options, node_name):
+ uuid = new_uuid(node_name)
+ node = gen.node(node_name, uuid)
+ node_add_profile(gen, node, 'ldlm', ldlm_uuid)
+ if options.has_key('router'):
+ node.setAttribute('router', '1')
+ lustre.appendChild(node)
+ return node
+
+
+def add_node(gen, lustre, options, args):
+ """ create a node with a network config """
+ if len(args) > 1:
+ usage()
+
+ node_name = options['node']
+
+ ret = findByName(lustre, node_name, "node")
+ if ret:
+ print "Node:", node_name, "exists."
+ return
+ do_add_node(gen, lustre, options, node_name)
+
+
+def add_net(gen, lustre, options, args):
+ """ create a node with a network config """
+ if len(args) < 2:
+ usage()
+
+ node_name = options['node']
+ nid = args[0]
+ net_type = args[1]
+ port = 0
+ tcpbuf = 0
+
+ if net_type in ('tcp', 'toe'):
+ if len(args) > 2:
+ port = int(args[2])
+ else:
+ port = DEFAULT_PORT
+ if options.has_key('tcpbuf'):
+ tcpbuf = int(options['tcpbuf'])
+ elif net_type in ('elan', 'gm'):
+ port = 0
+ else:
+ print "Unknown net_type: ", net_type
+ sys.exit(2)
+
+ ret = findByName(lustre, node_name, "node")
+ if not ret:
+ node = do_add_node(gen, lustre, options, node_name)
+ else:
+ node = ret
+ net_name = new_name('NET_'+ node_name +'_'+ net_type)
+ net_uuid = new_uuid(net_name)
+ node.appendChild(gen.network(net_name, net_uuid, nid, net_type, port, tcpbuf))
+ node_add_profile(gen, node, "network", net_uuid)
+
+
+def add_route(gen, lustre, options, args):
+ """ create a node with a network config """
+ if len(args) < 3:
+ usage()
+
+ node_name = options['node']
+ net_type= args[0]
+ gw = args[1]
+ lo = args[2]
+ hi = ''
+
+ if len(args) > 3:
+ hi = args[3]
+
+ node = findByName(lustre, node_name, "node")
+ if not node:
+ error (node_name, " not found.")
+
+ netlist = node.getElementsByTagName('network')
+ net = netlist[0]
+ rlist = net.getElementsByTagName('route_tbl')
+ if len(rlist) > 0:
+ rtbl = rlist[0]
+ else:
+ rtbl = gen.addElement(net, 'route_tbl')
+ rtbl.appendChild(gen.route(net_type, gw, lo, hi))
+
+
+def add_mds(gen, lustre, options, args):
+ if len(args) < 1:
+ usage()
+
+ if options.has_key('node'):
+ node_name = options['node']
+ else:
+ error("--mds requires a --node argument")
+
+ mds_name = new_name(options['mds'])
+ if mds_name != options['mds']:
+ warning("name:", options['mds'], "already used. using:", mds_name)
devname = args[0]
- host = args[1]
- size = args[2]
+ if len(args) > 1:
+ size = args[1]
+ else:
+ size = 0
+
+ mds_uuid = new_uuid(mds_name)
+
+ node_uuid = name2uuid(lustre, node_name, 'node')
+
+ node = findByName(lustre, node_name, "node")
+ node_add_profile(gen, node, "mds", mds_uuid)
+ net_uuid = get_net_uuid(lustre, node_name)
+ if not net_uuid:
+ error("NODE: ", node_name, "not found")
- obdname = new_name("obd")
- oscname = new_name("osc")
- ostname = new_name("ost")
+
+ mds = gen.mds(mds_name, mds_uuid, "extN", devname, get_format_flag(options),
+ net_uuid, node_uuid, dev_size=size)
+ lustre.appendChild(mds)
+
+
+def add_ost(gen, lustre, options, args):
+ lovname = ''
+ obdtype = 'obdfilter'
+ devname = ''
+ size = 0
+ fstype = 'extN'
- obd = new_OBD(dom, obdname, "extN", devname, "no", size)
- osc = new_OSC(dom, oscname, obdname)
- ost = new_OST(dom, ostname, host, 2020, obdname)
+ if options.has_key('node'):
+ node_name = options['node']
+ else:
+ error("--ost requires a --node argument")
+
+ if options.has_key('lov'):
+ lovname = options['lov']
+
+ if options.has_key('obdtype'):
+ obdtype = options['obdtype']
+ if obdtype == 'obdecho':
+ fstype = ''
+ else:
+ if len(args) < 1:
+ usage()
+ devname = args[0]
+ if len(args) > 1:
+ size = args[1]
+
+ obdname = new_name('OBD_'+ node_name)
+ oscname = new_name('OSC_'+ node_name)
+ ostname = new_name('OST_'+ node_name)
+ if options.has_key('obduuid'):
+ obd_uuid = options['obduuid']
+ obd = lookup(lustre, obd_uuid)
+ if obd:
+ error("Duplicate OBD UUID:", obd_uuid)
+ else:
+ obd_uuid = new_uuid(obdname)
+ ost_uuid = new_uuid(ostname)
+ osc_uuid = new_uuid(oscname)
+
+ net_uuid = get_net_uuid(lustre, node_name)
+ if not net_uuid:
+ error("NODE: ", node_name, "not found")
- dom.getElementsByTagName("lustre")[0].appendChild(obd)
- dom.getElementsByTagName("lustre")[0].appendChild(osc)
- dom.getElementsByTagName("lustre")[0].appendChild(ost)
+ obd = gen.obd(obdname, obd_uuid, fstype, obdtype, devname, get_format_flag(options), size)
+ ost = gen.ost(ostname, ost_uuid, obd_uuid, net_uuid)
+ osc = gen.osc(oscname, osc_uuid, obd_uuid, ost_uuid)
+
+ if lovname:
+ lov = findByName(lustre, lovname, "lov")
+ if not lov:
+ error('add_ost:', '"'+lovname+'"', "lov element not found.")
+ lov_add_osc(gen, lov, osc_uuid)
+ node = findByName(lustre, node_name, "node")
+ node_add_profile(gen, node, 'obd', obd_uuid)
+ node_add_profile(gen, node, 'ost', ost_uuid)
-#
+ lustre.appendChild(obd)
+ lustre.appendChild(osc)
+ lustre.appendChild(ost)
+
+
+# this is generally only used by llecho.sh
+def add_osc(gen, lustre, options, args):
+ """ add the osc to the profile for this node. """
+ if len(args) < 1:
+ usage()
+ osc_name = args[0]
+ if options.has_key('node'):
+ node_name = options['node']
+ else:
+ error("--osc requires a --node argument")
+ osc_uuid = name2uuid(lustre, osc_name) # either 'osc' or 'lov'
+ node = findByName(lustre, node_name, "node")
+ node_add_profile(gen, node, 'osc', osc_uuid)
+
+
+def add_lov(gen, lustre, options, args):
+ """ create a lov """
+ if len(args) < 4:
+ usage()
+
+ name = new_name(options['lov'])
+ if name != options['lov']:
+ warning("name:", options['lov'], "already used. using:", name)
+
+ mds_name = args[0]
+ stripe_sz = args[1]
+ stripe_count = args[2]
+ pattern = args[3]
+ uuid = new_uuid(name)
+
+ ret = findByName(lustre, name, "lov")
+ if ret:
+ error("LOV: ", name, " already exists.")
+
+ mds_uuid = name2uuid(lustre, mds_name, 'mds')
+ lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_count, pattern)
+ lustre.appendChild(lov)
+
+ # add an lovconfig entry to the mds profile
+ lovconfig_name = new_name('LVCFG_' + name)
+ lovconfig_uuid = new_uuid(lovconfig_name)
+ node = mds2node(lustre, mds_name)
+ node_add_profile(gen, node, "lovconfig", lovconfig_uuid)
+ lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
+ lustre.appendChild(lovconfig)
+
+
+
+def add_mtpt(gen, lustre, options, args):
+ """ create mtpt on a node """
+ if len(args) < 3:
+ usage()
+
+ if options.has_key('node'):
+ node_name = options['node']
+ else:
+ error("--mtpt requires a --node argument")
+
+ path = args[0]
+ mds_name = args[1]
+ lov_name = args[2]
+
+ name = new_name('MNT_'+ node_name)
+
+ ret = findByName(lustre, name, "mountpoint")
+ if ret:
+ error("MOUNTPOINT: ", name, " already exists.")
+
+ mds_uuid = name2uuid(lustre, mds_name, tag='mds')
+ lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
+ if not lov_uuid:
+ lov_uuid = name2uuid(lustre, lov_name, tag='osc', fatal=1)
+
+ uuid = new_uuid(name)
+ mtpt = gen.mountpoint(name, uuid, mds_uuid, lov_uuid, path)
+ node = findByName(lustre, node_name, "node")
+ if not node:
+ error('node:', node_name, "not found.")
+ node_add_profile(gen, node, "mountpoint", uuid)
+ lustre.appendChild(mtpt)
+
+
+############################################################
# Command line processing
#
-
def parse_cmdline(argv):
- short_opts = "ho:"
- long_opts = ["ost", "mtpt", "lov",
- "merge=", "format", "reformat", "output=",
- "help"]
+ short_opts = "ho:i:m:"
+ long_opts = ["ost", "osc", "mtpt", "lov=", "node=", "mds=", "net", "tcpbuf=",
+ "route", "router", "merge=", "format", "reformat", "output=",
+ "obdtype=", "obduuid=", "in=", "help", "batch="]
opts = []
args = []
options = {}
try:
opts, args = getopt.getopt(argv, short_opts, long_opts)
- except getopt.GetoptError:
+ except getopt.error:
print "invalid opt"
usage()
- sys.exit(2)
for o, a in opts:
+ # Commands to create new devices
+ if o == "--ost":
+ options['ost'] = 1
+ if o == "--osc":
+ options['osc'] = 1
+ if o == "--mds":
+ options['mds'] = a
+ if o == "--net":
+ options['net'] = 1
+ if o == "--mtpt":
+ options['mtpt'] = 1
+ if o == "--node":
+ options['node'] = a
+ if o == "--route":
+ options['route'] = 1
+ if o == "--router":
+ options['router'] = 1
+ if o == "--lov":
+ options['lov'] = a
+
+ # Options for commands
+ if o == "--obdtype":
+ options['obdtype'] = a
+ if o == "--obduuid":
+ options['obduuid'] = a
+ if o == "--tcpbuf":
+ options['tcpbuf'] = a
+
+ # lmc options
if o in ("-h", "--help"):
usage()
- sys.exit()
if o in ("-o", "--output"):
options['output'] = a
- if o == "--ost":
- options['ost'] = 1
- if o == "--merge":
+ if o in ("-m", "--merge"):
options['merge'] = a
if o == "--format":
options['format'] = 1
if o == "--reformat":
options['reformat'] = 1
+ if o == "--batch":
+ options['batch'] = a
+ if o in ("--in" , "-i"):
+ options['in'] = a
return options, args
+
+# simple class for profiling
+import time
+class chrono:
+ def __init__(self):
+ self._start = 0
+ def start(self):
+ self._stop = 0
+ self._start = time.time()
+ def stop(self, msg=''):
+ self._stop = time.time()
+ if msg:
+ self.display(msg)
+ def dur(self):
+ return self._stop - self._start
+ def display(self, msg):
+ d = self.dur()
+ str = '%s: %g secs' % (msg, d)
+ print str
+
+############################################################
+# Main
+#
+def do_command(gen, lustre, options, args):
+ if options.has_key('ost'):
+ add_ost(gen, lustre, options, args)
+ elif options.has_key('osc'):
+ add_osc(gen, lustre, options, args)
+ elif options.has_key('mtpt'):
+ add_mtpt(gen, lustre, options, args)
+ elif options.has_key('mds'):
+ add_mds(gen, lustre, options, args)
+ elif options.has_key('net'):
+ add_net(gen, lustre, options, args)
+ elif options.has_key('lov'):
+ add_lov(gen, lustre, options, args)
+ elif options.has_key('route'):
+ add_route(gen, lustre, options, args)
+ elif options.has_key('node'):
+ add_node(gen, lustre, options, args)
+ else:
+ print "Missing command"
+ usage()
+
def main():
options, args = parse_cmdline(sys.argv[1:])
outFile = '-'
if options.has_key('merge'):
outFile = options['merge']
- dom = xml.dom.minidom.parse(outFile)
+ if os.access(outFile, os.R_OK):
+ doc = xml.dom.minidom.parse(outFile)
+ else:
+ doc = new_lustre(xml.dom.minidom)
+ elif options.has_key('in'):
+ doc = xml.dom.minidom.parse(options['in'])
else:
- dom = new_Lustre()
+ doc = new_lustre(xml.dom.minidom)
if options.has_key('output'):
outFile = options['output']
- if options.has_key('ost'):
- add_OST(dom, options, args)
- elif options.has_key('mtpt'):
- print "--mtpt not implemented"
- elif options.has_key('lov'):
- print "--lov not implemented"
- else:
- print "Missing command"
- usage()
+ lustre = doc.documentElement
+ init_names(lustre)
+ if lustre.tagName != "lustre":
+ print "Existing config not valid."
sys.exit(1)
-
+
+ gen = GenConfig(doc)
+
+ if options.has_key('batch'):
+ fp = open(options['batch'])
+ batchCommands = fp.readlines()
+ fp.close()
+ for cmd in batchCommands:
+ options, args = parse_cmdline(string.split(cmd))
+ do_command(gen, lustre, options, args)
+ else:
+ do_command(gen, lustre, options, args)
if outFile == '-':
- print dom.toxml()
+ PrettyPrint(doc)
else:
- dom.writexml(open(outFile,"w"))
-
+ PrettyPrint(doc, open(outFile,"w"))
+
if __name__ == "__main__":
main()
+