2 # Copyright (C) 2002 Cluster File Systems, Inc.
3 # Author: Robert Read <rread@clusterfs.com>
5 # This file is part of Lustre, http://www.lustre.org.
7 # Lustre is free software; you can redistribute it and/or
8 # modify it under the terms of version 2 of the GNU General Public
9 # License as published by the Free Software Foundation.
11 # Lustre is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Lustre; if not, write to the Free Software
18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 lmc - lustre configuration data manager
24 See Lustre book (http://www.lustre.org/docs/lustre.pdf) for documentation on lmc.
28 import sys, os, getopt, string, exceptions, re
29 import xml.dom.minidom
31 def printDoc(doc, stream=sys.stdout):
33 from xml.dom.ext import PrettyPrint
34 PrettyPrint(doc, stream)
36 stream.write(doc.toxml())
40 PYMOD_DIR = "/usr/lib/lustre/python"
42 def development_mode():
43 base = os.path.dirname(sys.argv[0])
44 if os.access(base+"/Makefile.am", os.R_OK):
48 if not development_mode():
49 sys.path.append(PYMOD_DIR)
54 DEFAULT_STRIPE_SZ = 1048576
55 DEFAULT_STRIPE_CNT = 1
56 DEFAULT_STRIPE_PATTERN = 0
60 print """usage: lmc --add object [object parameters]
62 Object creation command summary:
70 --ptldebug debug_level
71 --subsystem subsystem_name
91 --backfstype ldiskfs|ext3|tmpfs
98 --mountfsoptions options
117 --fstype ldiskfs|ext3
118 --backfstype ldiskfs|ext3|tmpfs
121 --osdtype obdecho|obdfilter
123 --mkfsoptions options
124 --mountfsoptions options
135 --add mtpt - Mountpoint
140 --ost ost_name OR --lov lov_name
141 --clientoptions options
147 --gateway_cluster_id nid
148 --target_cluster_id nid
155 --add mgmt - Management/monitoring service
157 --mgmt mgmt_service_name
169 --master_dev obd_name
172 --commit - Close a configuration version, and start a new one
175 PARAM = Lustre.Options.PARAM
177 # lmc input/output options
178 ('reference', "Print short reference for commands."),
179 ('verbose,v', "Print system commands as they are run."),
180 ('merge,m', "Append to the specified config file.", PARAM),
181 ('output,o', "Write XML configuration into given output file. Overwrite existing content.", PARAM),
182 ('input,i', "", PARAM),
183 ('batch', "Used to execute lmc commands in batch mode.", PARAM),
187 ('delete', "", PARAM),
188 ('deactivate', "", PARAM),
189 ('commit', "Commit all config changes and start a new version"),
192 ('node', "Add a new node in the cluster configuration.", PARAM),
193 ('timeout', "Set timeout to initiate recovery.", PARAM),
194 ('upcall', "Set both lustre and portals upcall scripts.", PARAM),
195 ('lustre_upcall', "Set location of lustre upcall script.", PARAM),
196 ('portals_upcall', "Set location of portals upcall script.", PARAM),
197 ('ptldebug', "Set the portals debug level", PARAM),
198 ('subsystem', "Specify which Lustre subsystems have debug output recorded in the log", PARAM),
201 ('nettype', "Specify the network type. This can be tcp/elan/gm.", PARAM),
202 ('nid', "Give the network ID, e.g ElanID/IP Address as used by portals.", PARAM),
203 ('tcpbuf', "Optional argument to specify the TCP buffer size.", PARAM, "0"),
204 ('port', "Optional argument to specify the TCP port number.", PARAM, DEFAULT_PORT),
205 ('irq_affinity', "Optional argument.", PARAM, 0),
206 ('hostaddr', "", PARAM,""),
207 ('cluster_id', "Specify the cluster ID", PARAM, "0"),
210 ('route', "Add a new route for the cluster.", PARAM),
211 ('router', "Optional flag to mark a node as router."),
212 ('gw', "Specify the nid of the gateway for a route.", PARAM),
213 ('gateway_cluster_id', "", PARAM, "0"),
214 ('target_cluster_id', "", PARAM, "0"),
215 ('lo', "For a range route, this is the low value nid.", PARAM),
216 ('hi', "For a range route, this is a hi value nid.", PARAM,""),
218 # servers: mds and ost
219 ('mds', "Specify MDS name.", PARAM,""),
220 ('ost', "Specify the OST name.", PARAM,""),
221 ('osdtype', "This could obdfilter or obdecho.", PARAM, "obdfilter"),
222 ('failover', "Enable failover support on OSTs or MDS?"),
223 ('group', "", PARAM),
224 ('dev', "Path of the device on local system.", PARAM,""),
225 ('backdev', "Path of the device for backing storage on local system.", PARAM,""),
226 ('size', "Specify the size of the device if needed.", PARAM,"0"),
227 ('journal_size', "Specify new journal size for underlying file system.", PARAM,"0"),
228 ('inode_size', "Specify new inode size for underlying file system.", PARAM,"0"),
229 ('fstype', "Optional argument to specify the filesystem type.", PARAM, "ext3"),
230 ('backfstype', "Optional argument to specify the backing filesystem type.", PARAM, "ext3"),
231 ('mkfsoptions', "Optional argument to mkfs.", PARAM, ""),
232 ('mountfsoptions', "Optional argument to mount fs.", PARAM, ""),
233 ('ostuuid', "", PARAM,""),
234 ('nspath', "Local mount point of server namespace.", PARAM,""),
236 ('migrate', "used for offline migrate of an ost in conjunctio with add/delete"),
238 # clients: mountpoint and echo
239 ('echo_client', "", PARAM),
240 ('path', "Specify the mountpoint for Lustre.", PARAM),
241 ('filesystem', "Lustre filesystem name", PARAM,""),
242 ('clientoptions', "Specify the options for Lustre, such as async.", PARAM, ""),
245 ('lov', "Specify LOV name.", PARAM,""),
246 ('index', "Specify index for OBD in LOV target table.", PARAM),
247 ('stripe_sz', "Specify the stripe size in bytes.", PARAM),
248 ('stripe_cnt', "Specify the number of OSTs each file should be striped on.", PARAM, 0),
249 ('stripe_pattern', "Specify the stripe pattern. RAID 0 is the only one currently supported.", PARAM, 0),
253 ('real_obd', "Specify the real device for the cache obd system.", PARAM),
254 ('cache_obd', "Specify the cache device for the cache obd system.", PARAM),
255 ('cobd', "Specify COBD name", PARAM),
258 ('master_dev', "Specify the master device for the cmobd system.", PARAM),
259 ('cache_dev', "Specify the cache device for the cmobd obd system.", PARAM),
260 ('cmobd', "Specify COBD name", PARAM),
263 ('mgmt', "Specify management/monitoring service name.", PARAM, ""),
266 ('lmv', "Specify LMV name.", PARAM,""),
270 msg = string.join(map(str,args))
271 raise OptionError("Error: " + msg)
280 msg = string.join(map(str,args))
281 print "Warning: ", msg
284 # manage names and uuids
285 # need to initialize this by walking tree to ensure
286 # no duplicate names or uuids are created.
287 # this are just place holders for now.
288 # consider changing this to be like OBD-dev-host
292 while names.has_key(ret):
293 ret = "%s_%d" % (base, ctr)
300 ret = "%s_UUID" % (name)
301 if len(ret) > UUID_MAX_LENGTH:
302 ret = ret[-UUID_MAX_LENGTH:]
303 while uuids.has_key(ret):
304 ret = "%s_UUID_%d" % (name, ctr)
306 if len(ret) > UUID_MAX_LENGTH:
307 ret = ret[-UUID_MAX_LENGTH:]
313 ldlm_uuid = 'ldlm_UUID'
316 """Create a new empty lustre document"""
317 # adding ldlm here is a bit of a hack, but one is enough.
318 str = """<lustre version="%s">
319 <ldlm name="%s" uuid="%s"/>
320 </lustre>""" % (Lustre.CONFIG_VERSION, ldlm_name, ldlm_uuid)
321 return dom.parseString(str)
327 """initialize auto-name generation tables"""
329 # get all elements that contain a name attribute
330 for n in doc.childNodes:
331 if n.nodeType == n.ELEMENT_NODE:
333 names[getName(n)] = 1
334 uuids[getUUID(n)] = 1
337 def get_format_flag(options):
342 ############################################################
343 # Build config objects using DOM
348 def __init__(self, doc):
351 def ref(self, type, uuid):
352 """ generate <[type]_ref uuidref="[uuid]"/> """
353 tag = "%s_ref" % (type)
354 ref = self.doc.createElement(tag)
355 ref.setAttribute("uuidref", uuid)
358 def dev(self, devname):
359 """ generate <dev devpath="[devname]"/> """
360 tgt = self.doc.createElement('dev')
361 tgt.setAttribute("dev", devname)
364 def newService(self, tag, name, uuid):
365 """ create a new service elmement, which requires name and uuid attributes """
366 new = self.doc.createElement(tag)
367 new.setAttribute("uuid", uuid);
368 new.setAttribute("name", name);
371 def addText(self, node, str):
372 txt = self.doc.createTextNode(str)
373 node.appendChild(txt)
375 def addElement(self, node, tag, str=None):
376 """ create a new element and add it as a child to node. If str is passed,
377 a text node is created for the new element"""
378 new = self.doc.createElement(tag)
380 self.addText(new, str)
381 node.appendChild(new)
384 def network(self, name, uuid, nid, cluster_id, net, hostaddr="",
385 port=0, tcpbuf=0, irq_aff=0):
386 """create <network> node"""
387 network = self.newService("network", name, uuid)
388 network.setAttribute("nettype", net);
389 self.addElement(network, "nid", nid)
390 self.addElement(network, "clusterid", cluster_id)
392 self.addElement(network, "hostaddr", hostaddr)
394 self.addElement(network, "port", "%d" %(port))
396 self.addElement(network, "sendmem", "%d" %(tcpbuf))
397 self.addElement(network, "recvmem", "%d" %(tcpbuf))
399 self.addElement(network, "irqaffinity", "%d" %(irq_aff))
403 def routetbl(self, name, uuid):
404 """create <routetbl> node"""
405 rtbl = self.newService("routetbl", name, uuid)
408 def route(self, gw_net_type, gw, gw_cluster_id, tgt_cluster_id, lo, hi):
409 """ create one entry for the route table """
410 ref = self.doc.createElement('route')
411 ref.setAttribute("type", gw_net_type)
412 ref.setAttribute("gw", gw)
413 ref.setAttribute("gwclusterid", gw_cluster_id)
414 ref.setAttribute("tgtclusterid", tgt_cluster_id)
415 ref.setAttribute("lo", lo)
417 ref.setAttribute("hi", hi)
420 def profile(self, name, uuid):
421 """ create a host """
422 profile = self.newService("profile", name, uuid)
425 def node(self, name, uuid, prof_uuid):
426 """ create a host """
427 node = self.newService("node", name, uuid)
428 node.appendChild(self.ref("profile", prof_uuid))
431 def ldlm(self, name, uuid):
432 """ create a ldlm """
433 ldlm = self.newService("ldlm", name, uuid)
436 def osd(self, name, uuid, fstype, osdtype, devname, format, ost_uuid,
437 node_uuid, dev_size=0, journal_size=0, inode_size=0, nspath="",
438 mkfsoptions="", mountfsoptions="", backfstype="", backdevname=""):
439 osd = self.newService("osd", name, uuid)
440 osd.setAttribute('osdtype', osdtype)
441 osd.appendChild(self.ref("target", ost_uuid))
442 osd.appendChild(self.ref("node", node_uuid))
443 osd.appendChild(self.dev(devname))
446 self.addElement(osd, "fstype", fstype)
448 self.addElement(osd, "backfstype", backfstype)
450 self.addElement(osd, "backdevpath", backdevname)
452 dev = self.addElement(osd, "devpath", devname)
453 self.addElement(osd, "autoformat", format)
455 self.addElement(osd, "devsize", "%s" % (dev_size))
457 self.addElement(osd, "journalsize", "%s" % (journal_size))
459 self.addElement(osd, "inodesize", "%s" % (inode_size))
461 self.addElement(osd, "mkfsoptions", mkfsoptions)
463 self.addElement(osd, "mountfsoptions", mountfsoptions)
465 self.addElement(osd, "nspath", nspath)
468 def cobd(self, name, uuid, real_uuid, cache_uuid):
469 cobd = self.newService("cobd", name, uuid)
470 cobd.appendChild(self.ref("realobd",real_uuid))
471 cobd.appendChild(self.ref("cacheobd",cache_uuid))
474 def cmobd(self, name, uuid, real_uuid, cache_uuid):
475 cmobd = self.newService("cmobd", name, uuid)
476 cmobd.appendChild(self.ref("masterobd",real_uuid))
477 cmobd.appendChild(self.ref("cacheobd",cache_uuid))
480 def ost(self, name, uuid, osd_uuid, group=""):
481 ost = self.newService("ost", name, uuid)
482 ost.appendChild(self.ref("active", osd_uuid))
484 self.addElement(ost, "group", group)
487 def oss(self, name, uuid):
488 oss = self.newService("oss", name, uuid)
491 def lov(self, name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern):
492 lov = self.newService("lov", name, uuid)
493 lov.appendChild(self.ref("mds", mds_uuid))
494 lov.setAttribute("stripesize", str(stripe_sz))
495 lov.setAttribute("stripecount", str(stripe_cnt))
496 lov.setAttribute("stripepattern", str(pattern))
499 def lov_tgt(self, obd_uuid, index, generation):
500 tgt = self.doc.createElement('lov_tgt')
501 tgt.setAttribute("uuidref", obd_uuid)
502 tgt.setAttribute("index", index)
503 tgt.setAttribute("generation", generation)
504 tgt.setAttribute("active", '1')
507 def lovconfig(self, name, uuid, lov_uuid):
508 lovconfig = self.newService("lovconfig", name, uuid)
509 lovconfig.appendChild(self.ref("lov", lov_uuid))
512 def lmv(self, name, uuid):
513 lmv = self.newService("lmv", name, uuid)
516 def mds(self, name, uuid, mdd_uuid, group="", lmv=""):
517 mds = self.newService("mds", name, uuid)
518 mds.appendChild(self.ref("active",mdd_uuid))
520 self.addElement(mds, "group", group)
523 def mdsdev(self, name, uuid, fstype, devname, format, node_uuid,
524 mds_uuid, dev_size=0, journal_size=0, inode_size=256,
525 nspath="", mkfsoptions="", mountfsoptions="", backfstype="",
526 backdevname="", lmv_uuid=""):
527 mdd = self.newService("mdsdev", name, uuid)
528 self.addElement(mdd, "fstype", fstype)
530 self.addElement(mdd, "backfstype", backfstype)
531 dev = self.addElement(mdd, "devpath", devname)
533 self.addElement(mdd, "backdevpath", backdevname)
534 self.addElement(mdd, "autoformat", format)
536 self.addElement(mdd, "devsize", "%s" % (dev_size))
538 self.addElement(mdd, "journalsize", "%s" % (journal_size))
540 self.addElement(mdd, "inodesize", "%s" % (inode_size))
542 self.addElement(mdd, "nspath", nspath)
544 self.addElement(mdd, "mkfsoptions", mkfsoptions)
546 self.addElement(mdd, "mountfsoptions", mountfsoptions)
548 mdd.appendChild(self.ref("node", node_uuid))
549 mdd.appendChild(self.ref("target", mds_uuid))
550 mdd.appendChild(self.dev(devname))
553 mdd.appendChild(self.ref("lmv", lmv_uuid))
554 self.addElement(mdd, "lmv", lmv_uuid)
558 def mgmt(self, mgmt_name, mgmt_uuid, node_uuid):
559 mgmt = self.newService("mgmt", mgmt_name, mgmt_uuid)
560 mgmt.appendChild(self.ref("node", node_uuid))
561 # Placeholder until mgmt-service failover.
562 mgmt.appendChild(self.ref("active", mgmt_uuid))
565 def mountpoint(self, name, uuid, fs_uuid, path, clientoptions):
566 mtpt = self.newService("mountpoint", name, uuid)
567 mtpt.appendChild(self.ref("filesystem", fs_uuid))
568 self.addElement(mtpt, "path", path)
570 self.addElement(mtpt, "clientoptions", clientoptions)
573 def filesystem(self, name, uuid, mds_uuid, obd_uuid, mgmt_uuid):
574 fs = self.newService("filesystem", name, uuid)
575 fs.appendChild(self.ref("mds", mds_uuid))
576 fs.appendChild(self.ref("obd", obd_uuid))
578 fs.appendChild(self.ref("mgmt", mgmt_uuid))
581 def echo_client(self, name, uuid, osc_uuid):
582 ec = self.newService("echoclient", name, uuid)
583 ec.appendChild(self.ref("obd", osc_uuid))
586 def update(self, version):
587 new = self.doc.createElement("update")
588 new.setAttribute("version", version)
591 def add(self, lov, ost, index, gen):
592 new = self.doc.createElement("add")
593 new.setAttribute("lov_uuidref", lov)
594 new.setAttribute("ost_uuidref", ost)
595 new.setAttribute("index", index)
596 new.setAttribute("generation", gen)
599 def delete(self, lov, ost, index, gen, options):
601 new = self.doc.createElement("delete")
603 new = self.doc.createElement("deactivate")
604 new.setAttribute("lov_uuidref", lov)
605 new.setAttribute("ost_uuidref", ost)
606 new.setAttribute("index", index)
607 new.setAttribute("generation", gen)
610 ############################################################
611 # Utilities to query a DOM tree
612 # Using this functions we can treat use config information
613 # directly as a database.
615 return n.getAttribute('name')
618 return node.getAttribute('uuid')
620 def findLastUpdate(lustre):
623 for n in lustre.childNodes:
624 if n.nodeType == n.ELEMENT_NODE:
625 if n.nodeName != 'update':
627 tmp = int(n.getAttribute('version'))
629 error('malformed XML: update tag without a version attribute')
630 if tmp != version + 1:
631 error('malformed XML: expecting update record '+str(version + 1)+', found '+str(tmp)+'.')
636 def addUpdate(gen, lustre, node):
637 update = findLastUpdate(lustre)
640 #add_record = update.getElementsByTagName('add')
642 # add_record = gen.add()
643 # update.appendChild(add_record)
645 # add_record = add_record[0]
646 #add_record.appendChild(node)
647 update.appendChild(node)
649 def delUpdate(gen, lustre, node):
650 update = findLastUpdate(lustre)
653 update.appendChild(node)
655 def findByName(lustre, name, tag = ""):
656 for n in lustre.childNodes:
657 if n.nodeType == n.ELEMENT_NODE:
658 if tag and n.nodeName != tag:
660 if getName(n) == name:
663 n = findByName(n, name)
668 def lookup(node, uuid):
669 for n in node.childNodes:
670 if n.nodeType == n.ELEMENT_NODE:
671 if getUUID(n) == uuid:
679 def name2uuid(lustre, name, tag="", fatal=1):
680 ret = findByName(lustre, name, tag)
683 error('name2uuid:', '"'+name+'"', tag, 'element not found.')
688 def lookup_filesystem(lustre, mds_uuid, ost_uuid):
689 for n in lustre.childNodes:
690 if n.nodeType == n.ELEMENT_NODE and n.nodeName == 'filesystem':
691 if ref_exists(n, mds_uuid) and ref_exists(n, ost_uuid):
695 # XXX: assumes only one network element per node. will fix this
696 # as soon as support for routers is added
697 def get_net_uuid(lustre, node_name):
698 """ get a network uuid for a node_name """
699 node = findByName(lustre, node_name, "node")
701 error ('get_net_uuid:', '"'+node_name+'"', "node element not found.")
702 net = node.getElementsByTagName('network')
704 return getUUID(net[0])
707 def lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options):
708 tgt.setAttribute('uuidref', osc_uuid)
710 gener = int(tgt.getAttribute('generation'))
712 gener = int(tgt.getAttribute('generation')) + 1
713 tgt.setAttribute('generation', str(gener))
714 tgt.setAttribute('active', '1')
715 lov_index = int(tgt.getAttribute('index'))
716 addUpdate(gen, lustre, gen.add(getUUID(lov), osc_uuid, str(lov_index),
720 def lov_add_obd(gen, lustre, lov, osc_uuid, options):
721 lov_name = getName(lov)
723 lov_index = get_option_int(options, 'index')
724 for tgt in lustre.getElementsByTagName('lov_tgt'):
725 if str(lov_index) == tgt.getAttribute('index'):
726 uuidref = tgt.getAttribute('uuidref')
728 raise OptionError("%s --index %d is still in use: %s" %
729 (lov_name, lov_index, uuidref))
730 lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
734 for tgt in lustre.getElementsByTagName('lov_tgt'):
735 uuidref = tgt.getAttribute('uuidref')
736 tmp = int(tgt.getAttribute('index'))
738 error('malformed xml: LOV targets are not ordered; found index '+str(tmp)+', expected '+str(lov_index)+'.')
739 uuidref = tgt.getAttribute('uuidref')
741 lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
743 lov_index = lov_index + 1
745 lov.appendChild(gen.lov_tgt(osc_uuid, str(lov_index), '1'))
746 addUpdate(gen, lustre, gen.add(getUUID(lov), osc_uuid, str(lov_index), '1'))
748 def lov_del_obd(gen, lustre, lov, osc_uuid, options):
749 lov_name = getName(lov)
751 lov_index = get_option_int(options, 'index')
752 for tgt in lustre.getElementsByTagName('lov_tgt'):
753 index = tgt.getAttribute('index')
754 if index == lov_index:
755 uuidref = tgt.getAttribute('uuidref')
756 if uuidref != osc_uuid:
757 raise OptionError("%s --index %d contains %s, not %s" %
758 (lov_name, lov_index, osc_uuid, uuidref))
760 tgt.setAttribute('uuidref', '')
762 # bump the generation just in case...
764 gen = int(tgt.getAttribute('generation'))
766 gen = int(tgt.getAttribute('generation')) + 1
768 tgt.setAttribute('active', '0')
769 tgt.setAttribute('generation', str(gen))
771 raise OptionError("%s --index %d not in use by %s." %
772 (lov_name, lov_index, osc_uuid))
774 for tgt in lustre.getElementsByTagName('lov_tgt'):
775 uuidref = tgt.getAttribute('uuidref')
776 if uuidref == osc_uuid:
777 genera = int(tgt.getAttribute('generation'))
778 delete_rec = gen.delete(getUUID(lov),
779 osc_uuid,tgt.getAttribute('index'),
780 str(genera), options)
781 delUpdate(gen, lustre, delete_rec)
784 tgt.setAttribute('uuidref', '')
785 if not options.migrate:
787 tgt.setAttribute('active', '0')
788 tgt.setAttribute('generation', str(genera))
790 def lmv_add_obd(gen, lmv, mdc_uuid):
791 lmv.appendChild(gen.ref("mds", mdc_uuid))
793 def ref_exists(profile, uuid):
794 elist = profile.childNodes
796 if e.nodeType == e.ELEMENT_NODE:
797 ref = e.getAttribute('uuidref')
802 # ensure that uuid is not already in the profile
803 # return true if uuid is added
804 def node_add_profile(gen, node, ref, uuid):
805 refname = "%s_ref" % "profile"
806 ret = node.getElementsByTagName(refname)
808 error('node has no profile ref:', node)
809 prof_uuid = ret[0].getAttribute('uuidref')
810 profile = lookup(node.parentNode, prof_uuid)
812 error("no profile found:", prof_uuid)
813 if ref_exists(profile, uuid):
815 profile.appendChild(gen.ref(ref, uuid))
818 # ensure that uuid is not already in the profile
819 # return true if uuid is added
820 def node_found_target_by_dev(gen, lustre, node, devname):
821 refname = "%s_ref" % "profile"
822 ret = node.getElementsByTagName(refname)
824 error('node has no profile ref:', node)
825 prof_uuid = ret[0].getAttribute('uuidref')
826 profile = lookup(node.parentNode, prof_uuid)
828 error("no profile found:", prof_uuid)
830 osd_list = lustre.getElementsByTagName('osd')
833 obd_dev = osd.getElementsByTagName('dev')
834 if obd_dev and obd_dev[0].getAttribute('dev') == devname:
835 for ost in lustre.getElementsByTagName('ost'):
836 active_ret = ost.getElementsByTagName('active_ref')
837 if active_ret[0].getAttribute('uuidref') == osd.getAttribute('uuid'):
838 return ost.getAttribute('uuid')
840 mdsdev_list = lustre.getElementsByTagName('mdsdev')
842 for mdsdev in mdsdev_list:
843 obd_dev = mdsdev.getElementsByTagName('dev')
844 if obd_dev and obd_dev[0].getAttribute('dev') == devname:
845 for mds in lustre.getElementsByTagName('mds'):
846 active_ret = mds.getElementsByTagName('active_ref')
847 if active_ret[0].getAttribute('uuidref') == mdsdev.getAttribute('uuid'):
848 return mds.getAttribute('uuid')
852 def get_attr(dom_node, attr, default=""):
853 v = dom_node.getAttribute(attr)
858 ############################################################
861 def set_node_options(gen, node, options):
863 node.setAttribute('router', '1')
865 gen.addElement(node, "timeout", get_option(options, 'timeout'))
867 default_upcall = get_option(options, 'upcall')
870 if default_upcall or options.lustre_upcall:
871 if options.lustre_upcall:
872 gen.addElement(node, 'lustreUpcall', options.lustre_upcall)
874 gen.addElement(node, 'lustreUpcall', default_upcall)
875 if default_upcall or options.portals_upcall:
876 if options.portals_upcall:
877 gen.addElement(node, 'portalsUpcall', options.portals_upcall)
879 gen.addElement(node, 'portalsUpcall', default_upcall)
881 gen.addElement(node, "ptldebug", get_option(options, 'ptldebug'))
882 if options.subsystem:
883 gen.addElement(node, "subsystem", get_option(options, 'subsystem'))
886 def do_add_node(gen, lustre, options, node_name):
887 uuid = new_uuid(node_name)
888 prof_name = new_name("PROFILE_" + node_name)
889 prof_uuid = new_uuid(prof_name)
890 profile = gen.profile(prof_name, prof_uuid)
891 node = gen.node(node_name, uuid, prof_uuid)
892 lustre.appendChild(node)
893 lustre.appendChild(profile)
895 node_add_profile(gen, node, 'ldlm', ldlm_uuid)
896 set_node_options(gen, node, options)
901 def add_node(gen, lustre, options):
902 """ create a node with a network config """
904 node_name = get_option(options, 'node')
905 ret = findByName(lustre, node_name, "node")
907 print "Node:", node_name, "exists."
909 do_add_node(gen, lustre, options, node_name)
912 def add_net(gen, lustre, options):
913 """ create a node with a network config """
915 node_name = get_option(options, 'node')
916 nid = get_option(options, 'nid')
917 cluster_id = get_option(options, 'cluster_id')
918 hostaddr = get_option(options, 'hostaddr')
919 net_type = get_option(options, 'nettype')
921 if net_type in ('tcp',):
922 port = get_option_int(options, 'port')
923 tcpbuf = get_option_int(options, 'tcpbuf')
924 irq_aff = get_option_int(options, 'irq_affinity')
925 elif net_type in ('elan', 'gm'):
930 print "Unknown net_type: ", net_type
933 ret = findByName(lustre, node_name, "node")
935 node = do_add_node(gen, lustre, options, node_name)
938 set_node_options(gen, node, options)
940 net_name = new_name('NET_'+ node_name +'_'+ net_type)
941 net_uuid = new_uuid(net_name)
942 node.appendChild(gen.network(net_name, net_uuid, nid, cluster_id, net_type,
943 hostaddr, port, tcpbuf, irq_aff))
944 node_add_profile(gen, node, "network", net_uuid)
947 def add_route(gen, lustre, options):
948 """ create a node with a network config """
950 node_name = get_option(options, 'node')
951 gw_net_type = get_option(options, 'nettype')
952 gw = get_option(options, 'gw')
953 gw_cluster_id = get_option(options, 'gateway_cluster_id')
954 tgt_cluster_id = get_option(options, 'target_cluster_id')
955 lo = get_option(options, 'lo')
956 hi = get_option(options, 'hi')
960 node = findByName(lustre, node_name, "node")
962 error (node_name, " not found.")
964 rlist = node.getElementsByTagName('routetbl')
968 rtbl_name = new_name("RTBL_" + node_name)
969 rtbl_uuid = new_uuid(rtbl_name)
970 rtbl = gen.routetbl(rtbl_name, rtbl_uuid)
971 node.appendChild(rtbl)
972 node_add_profile(gen, node, "routetbl", rtbl_uuid)
973 rtbl.appendChild(gen.route(gw_net_type, gw, gw_cluster_id, tgt_cluster_id,
977 def add_mds(gen, lustre, options):
978 node_name = get_option(options, 'node')
979 mds_name = get_option(options, 'mds')
980 lmv_name = get_option(options, 'lmv')
981 mdd_name = new_name("MDD_" + mds_name +"_" + node_name)
982 mdd_uuid = new_uuid(mdd_name)
986 lmv = findByName(lustre, lmv_name, "lmv")
988 error('add_mds:', '"' + lmv_name + '"', "lmv element not found.")
989 lmv_uuid = name2uuid(lustre, lmv_name, fatal=0)
991 mds_uuid = name2uuid(lustre, mds_name, 'mds', fatal=0)
993 mds_uuid = new_uuid(mds_name)
994 mds = gen.mds(mds_name, mds_uuid, mdd_uuid, options.group)
995 lustre.appendChild(mds)
997 lmv_add_obd(gen, lmv, mds_uuid)
999 mds = lookup(lustre, mds_uuid)
1001 if options.failover:
1002 mds.setAttribute('failover', "1")
1004 devname = get_option(options, 'dev')
1005 backdevname = get_option(options, 'backdev')
1006 size = get_option(options, 'size')
1007 fstype = get_option(options, 'fstype')
1008 backfstype = get_option(options, 'backfstype')
1009 journal_size = get_option(options, 'journal_size')
1010 inode_size = get_option(options, 'inode_size')
1011 nspath = get_option(options, 'nspath')
1012 mkfsoptions = get_option(options, 'mkfsoptions')
1013 mountfsoptions = get_option(options, 'mountfsoptions')
1015 node_uuid = name2uuid(lustre, node_name, 'node')
1017 node = findByName(lustre, node_name, "node")
1018 node_add_profile(gen, node, "mdsdev", mdd_uuid)
1019 net_uuid = get_net_uuid(lustre, node_name)
1021 error("NODE: ", node_name, "not found")
1024 mds.appendChild(gen.ref("lmv", lmv_uuid))
1026 mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname,
1027 get_format_flag(options), node_uuid, mds_uuid,
1028 size, journal_size, inode_size, nspath, mkfsoptions,
1029 mountfsoptions, backfstype, backdevname, lmv_uuid)
1030 lustre.appendChild(mdd)
1033 def add_mgmt(gen, lustre, options):
1034 node_name = get_option(options, 'node')
1035 node_uuid = name2uuid(lustre, node_name, 'node')
1036 mgmt_name = get_option(options, 'mgmt')
1038 mgmt_name = new_name('MGMT_' + node_name)
1039 mgmt_uuid = name2uuid(lustre, mgmt_name, 'mgmt', fatal=0)
1041 mgmt_uuid = new_uuid(mgmt_name)
1042 mgmt = gen.mgmt(mgmt_name, mgmt_uuid, node_uuid)
1043 lustre.appendChild(mgmt)
1045 mgmt = lookup(lustre, mgmt_uuid)
1047 node = findByName(lustre, node_name, "node")
1048 node_add_profile(gen, node, 'mgmt', mgmt_uuid)
1050 def add_ost(gen, lustre, options):
1051 node_name = get_option(options, 'node')
1052 lovname = get_option(options, 'lov')
1053 osdtype = get_option(options, 'osdtype')
1055 node_uuid = name2uuid(lustre, node_name, 'node')
1057 if osdtype == 'obdecho':
1068 devname = get_option(options, 'dev') # can be unset for bluearcs
1069 backdevname = get_option(options, 'backdev')
1070 size = get_option(options, 'size')
1071 fstype = get_option(options, 'fstype')
1072 backfstype = get_option(options, 'backfstype')
1073 journal_size = get_option(options, 'journal_size')
1074 inode_size = get_option(options, 'inode_size')
1075 mkfsoptions = get_option(options, 'mkfsoptions')
1076 mountfsoptions = get_option(options, 'mountfsoptions')
1078 nspath = get_option(options, 'nspath')
1080 ostname = get_option(options, 'ost')
1082 ostname = new_name('OST_'+ node_name)
1084 osdname = new_name("OSD_" + ostname + "_" + node_name)
1085 osd_uuid = new_uuid(osdname)
1087 ost_uuid = name2uuid(lustre, ostname, 'ost', fatal=0)
1089 ost_uuid = get_option(options, 'ostuuid')
1091 if lookup(lustre, ost_uuid):
1092 error("Duplicate OST UUID:", ost_uuid)
1094 ost_uuid = new_uuid(ostname)
1096 ost = gen.ost(ostname, ost_uuid, osd_uuid, options.group)
1097 lustre.appendChild(ost)
1099 ost = lookup(lustre, ost_uuid)
1102 lov = findByName(lustre, lovname, "lov")
1104 error('add_ost:', '"'+lovname+'"', "lov element not found.")
1105 lov_add_obd(gen, lustre, lov, ost_uuid, options)
1107 if options.failover:
1108 ost.setAttribute('failover', "1")
1111 osd = gen.osd(osdname, osd_uuid, fstype, osdtype, devname,
1112 get_format_flag(options), ost_uuid, node_uuid, size,
1113 journal_size, inode_size, nspath, mkfsoptions,
1114 mountfsoptions, backfstype, backdevname)
1116 node = findByName(lustre, node_name, "node")
1118 ## if node_add_profile(gen, node, 'oss', oss_uuid):
1120 ## oss_uuid = new_uuid(ossname)
1121 ## oss = gen.oss(ossname, oss_uuid)
1122 ## lustre.appendChild(oss)
1124 node_add_profile(gen, node, 'osd', osd_uuid)
1125 lustre.appendChild(osd)
1127 def del_ost(gen, lustre, options):
1128 ostname = get_option(options, 'ost')
1130 raise OptionError("del_ost: --ost requires a <ost name>")
1131 ost = findByName(lustre, ostname, "ost")
1133 error('del_ost: ', 'Unable to find ', ostname)
1134 ost_uuid = name2uuid(lustre, ostname, fatal=0)
1136 error('del_ost: ', 'Unable to find uuid for ', ostname)
1137 lovname = get_option(options, 'lov')
1139 lov = findByName(lustre, lovname, "lov")
1141 error('del_ost:', '"'+lovname+'"', "lov element not found.")
1142 lov_del_obd(gen, lustre, lov, ost_uuid, options)
1143 # if the user specified a speficic LOV don't delete the OST itself
1146 # remove OSD references from all LOVs
1147 for n in lustre.getElementsByTagName('lov'):
1148 lov_del_obd(gen, lustre, n, ost_uuid, options)
1149 if not options.migrate:
1152 for osd in lustre.getElementsByTagName('osd'):
1153 if ref_exists(osd, ost_uuid):
1154 osd_uuid = osd.getAttribute('uuid')
1155 # delete all profile references to this OSD
1156 for profile in lustre.getElementsByTagName('profile'):
1157 for osd_ref in profile.getElementsByTagName('osd_ref'):
1158 if osd_uuid == osd_ref.getAttribute('uuidref'):
1159 profile.removeChild(osd_ref)
1160 lustre.removeChild(osd)
1163 lustre.removeChild(ost)
1165 def add_cmobd(gen, lustre, options):
1166 node_name = get_option(options, 'node')
1167 name = get_option(options, 'cmobd')
1168 uuid = new_uuid(name)
1170 real_name = get_option(options, 'master_dev')
1171 cache_name = get_option(options, 'cache_dev')
1173 node = findByName(lustre, node_name, "node")
1174 node_add_profile(gen, node, "cmobd", uuid)
1175 real_uuid = node_found_target_by_dev(gen, lustre, node, real_name)
1176 cache_uuid = node_found_target_by_dev(gen, lustre, node, cache_name)
1178 panic("add_cmobd", "can not find real_uuid")
1180 panic("add_cmobd", "can not find cache_uuid")
1181 cmobd = gen.cmobd(name, uuid, real_uuid, cache_uuid)
1182 lustre.appendChild(cmobd)
1184 def add_cobd(gen, lustre, options):
1185 node_name = get_option(options, 'node')
1186 name = get_option(options, 'cobd')
1187 uuid = new_uuid(name)
1189 real_name = get_option(options, 'real_obd')
1190 cache_name = get_option(options, 'cache_obd')
1192 real_uuid = name2uuid(lustre, real_name, tag='lov', fatal=0)
1193 cache_uuid = name2uuid(lustre, cache_name, tag='lov', fatal=0)
1196 node = lookup(lustre, real_uuid)
1197 rets = node.getElementsByTagName('lov_tgt')
1199 ost_uuid = ret.getAttribute('uuidref')
1200 ost_node = lookup(lustre, ost_uuid)
1201 ret = ost_node.getElementsByTagName('active_ref')
1203 osd_uuid = ret[0].getAttribute('uuidref')
1204 osd_node = lookup(lustre, osd_uuid)
1205 gen.addElement(osd_node, 'cachetype', 'master')
1208 node = lookup(lustre, cache_uuid)
1209 rets = node.getElementsByTagName('lov_tgt')
1211 ost_uuid = ret.getAttribute('uuidref')
1212 ost_node = lookup(lustre, ost_uuid)
1213 ret = ost_node.getElementsByTagName('active_ref')
1215 osd_uuid = ret[0].getAttribute('uuidref')
1216 osd_node = lookup(lustre, osd_uuid)
1217 gen.addElement(osd_node, 'cachetype', 'cache')
1219 if not real_uuid or not cache_uuid:
1220 real_uuid = name2uuid(lustre,real_name, tag='mds')
1221 cache_uuid = name2uuid(lustre,cache_name, tag='mds')
1223 mds_node = lookup(lustre, real_uuid)
1224 ret = mds_node.getElementsByTagName('active_ref')
1226 mdsdev_uuid = ret[0].getAttribute('uuidref')
1227 mdsdev_node = lookup(lustre, mdsdev_uuid)
1228 gen.addElement(mdsdev_node, 'cachetype', 'master')
1230 mds_node = lookup(lustre, cache_uuid)
1231 ret = mds_node.getElementsByTagName('active_ref')
1233 mdsdev_uuid = ret[0].getAttribute('uuidref')
1234 mdsdev_node = lookup(lustre, mdsdev_uuid)
1235 gen.addElement(mdsdev_node, 'cachetype', 'cache')
1237 node = findByName(lustre, node_name, "node")
1238 cobd = gen.cobd(name, uuid, real_uuid, cache_uuid)
1239 lustre.appendChild(cobd)
1242 def add_echo_client(gen, lustre, options):
1243 """ add an echo client to the profile for this node. """
1244 node_name = get_option(options, 'node')
1245 lov_name = get_option(options, 'ost')
1247 node = findByName(lustre, node_name, 'node')
1249 echoname = new_name('ECHO_'+ node_name)
1250 echo_uuid = new_uuid(echoname)
1251 node_add_profile(gen, node, 'echoclient', echo_uuid)
1253 lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
1255 lov_uuid = name2uuid(lustre, lov_name, tag='ost', fatal=1)
1257 echo = gen.echo_client(echoname, echo_uuid, lov_uuid)
1258 lustre.appendChild(echo)
1261 def add_lov(gen, lustre, options):
1262 """ create a lov """
1264 lmv_name = get_option(options, 'lmv')
1265 lov_orig = get_option(options, 'lov')
1266 name = new_name(lov_orig)
1267 if name != lov_orig:
1268 warning("name:", lov_orig, "already used. using:", name)
1270 mds_name = get_option(options, 'mds')
1273 error("LOV: MDS or LMV must be specified.");
1275 stripe_sz = get_option_int(options, 'stripe_sz')
1276 stripe_cnt = get_option_int(options, 'stripe_cnt')
1277 pattern = get_option_int(options, 'stripe_pattern')
1278 uuid = new_uuid(name)
1280 ret = findByName(lustre, name, "lov")
1282 error("LOV: ", name, " already exists.")
1285 mds_uuid = name2uuid(lustre, lmv_name, 'lmv')
1287 mds_uuid = name2uuid(lustre, mds_name, 'mds')
1289 lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
1290 lustre.appendChild(lov)
1292 # add an lovconfig entry to the active mdsdev profile
1293 lovconfig_name = new_name('LVCFG_' + name)
1294 lovconfig_uuid = new_uuid(lovconfig_name)
1296 mds = findByName(lustre, mds_name, "mds")
1297 mds.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1299 lmv = findByName(lustre, lmv_name, "lmv")
1300 lmv.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1301 lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
1302 lustre.appendChild(lovconfig)
1304 def add_default_lov(gen, lustre, mds_name, lov_name):
1305 """ create a default lov """
1307 stripe_sz = DEFAULT_STRIPE_SZ
1308 stripe_cnt = DEFAULT_STRIPE_CNT
1309 pattern = DEFAULT_STRIPE_PATTERN
1310 uuid = new_uuid(lov_name)
1312 ret = findByName(lustre, lov_name, "lov")
1314 error("LOV: ", lov_name, " already exists.")
1316 mds_uuid = name2uuid(lustre, mds_name, 'mds')
1317 lov = gen.lov(lov_name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
1318 lustre.appendChild(lov)
1320 # add an lovconfig entry to the active mdsdev profile
1321 lovconfig_name = new_name('LVCFG_' + lov_name)
1322 lovconfig_uuid = new_uuid(lovconfig_name)
1323 mds = findByName(lustre, mds_name)
1324 mds.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1325 lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
1326 lustre.appendChild(lovconfig)
1328 def add_lmv(gen, lustre, options):
1329 """ create a lmv """
1331 lmv_orig = get_option(options, 'lmv')
1332 name = new_name(lmv_orig)
1333 if name != lmv_orig:
1334 warning("name:", lmv_orig, "already used. using:", name)
1336 uuid = new_uuid(name)
1337 ret = findByName(lustre, name, "lmv")
1339 error("LMV: ", name, " already exists.")
1341 lmv = gen.lmv(name, uuid)
1342 lustre.appendChild(lmv)
1344 def new_filesystem(gen, lustre, mds_uuid, obd_uuid, mgmt_uuid):
1345 fs_name = new_name("FS_fsname")
1346 fs_uuid = new_uuid(fs_name)
1347 cobd = lookup(lustre, mds_uuid)
1348 #SHOULD appendChild filesystem to real mds not cobd
1349 ret = cobd.getElementsByTagName("cacheobd_ref")
1351 cacheobd_uuid = ret[0].getAttribute('uuidref')
1352 cacheobd = lookup(lustre, cacheobd_uuid)
1353 cacheobd.appendChild(gen.ref("filesystem", fs_uuid))
1354 ret = cobd.getElementsByTagName("realobd_ref")
1356 realobd_uuid = ret[0].getAttribute('uuidref')
1357 realobd = lookup(lustre, realobd_uuid)
1358 realobd.appendChild(gen.ref("filesystem", fs_uuid))
1360 cobd.appendChild(gen.ref("filesystem", fs_uuid))
1361 fs = gen.filesystem(fs_name, fs_uuid, mds_uuid, obd_uuid, mgmt_uuid)
1362 lustre.appendChild(fs)
1365 def get_fs_uuid(gen, lustre, mds_name, obd_name, mgmt_name):
1366 mds_uuid = name2uuid(lustre, mds_name, tag='mds', fatal=0)
1368 mds_uuid = name2uuid(lustre, mds_name, tag='lmv', fatal=0)
1370 mds_uuid = name2uuid(lustre, mds_name, tag='cobd', fatal=1)
1371 obd_uuid = name2uuid(lustre, obd_name, tag='lov', fatal=0)
1373 obd_uuid = name2uuid(lustre, obd_name, tag='cobd')
1375 mgmt_uuid = name2uuid(lustre, mgmt_name, tag='mgmt', fatal=1)
1378 fs_uuid = lookup_filesystem(lustre, mds_uuid, obd_uuid)
1380 fs_uuid = new_filesystem(gen, lustre, mds_uuid, obd_uuid, mgmt_uuid)
1383 def add_mtpt(gen, lustre, options):
1384 """ create mtpt on a node """
1385 node_name = get_option(options, 'node')
1387 path = get_option(options, 'path')
1388 clientoptions = get_option(options, "clientoptions")
1389 fs_name = get_option(options, 'filesystem')
1391 lov_name = get_option(options, 'lov')
1392 ost_name = get_option(options, 'ost')
1393 mds_name = get_option(options, 'mds')
1395 mds_name = get_option(options, 'lmv')
1397 error("--add mtpt requires either --mds or --lmv.")
1400 error("--add mtpt requires --lov lov_name or --ost ost_name")
1402 warning("use default value for lov, due no --lov lov_name provided")
1403 lov_name = new_name("lov_default")
1404 add_default_lov(gen, lustre, mds_name, lov_name)
1405 ost_uuid = name2uuid(lustre, ost_name, 'ost', fatal=0)
1407 error('add_mtpt:', '"'+ost_name+'"', "ost element not found.")
1408 lov = findByName(lustre, lov_name, "lov")
1409 lov_add_obd(gen, lustre, lov, ost_uuid, options)
1412 mgmt_name = get_option(options, 'mgmt')
1413 fs_uuid = get_fs_uuid(gen, lustre, mds_name, lov_name, mgmt_name)
1415 fs_uuid = name2uuid(lustre, fs_name, tag='filesystem')
1417 name = new_name('MNT_'+ node_name)
1419 ret = findByName(lustre, name, "mountpoint")
1421 # this can't happen, because new_name creates unique names
1422 error("MOUNTPOINT: ", name, " already exists.")
1424 uuid = new_uuid(name)
1425 mtpt = gen.mountpoint(name, uuid, fs_uuid, path, clientoptions)
1426 node = findByName(lustre, node_name, "node")
1428 error('node:', node_name, "not found.")
1429 node_add_profile(gen, node, "mountpoint", uuid)
1430 lustre.appendChild(mtpt)
1432 def commit_version(gen, lustre):
1433 update = findLastUpdate(lustre)
1435 version = int(update.getAttribute("version")) + 1
1439 new = gen.update(str(version))
1440 lustre.appendChild(new)
1443 ############################################################
1444 # Command line processing
1446 class OptionError (exceptions.Exception):
1447 def __init__(self, args):
1450 def get_option(options, tag):
1451 """Look for tag in options hash and return the value if set. If not
1452 set, then if return default it is set, otherwise exception."""
1453 if options.__getattr__(tag) != None:
1454 return options.__getattr__(tag)
1456 raise OptionError("--add %s requires --%s <value>" % (options.add, tag))
1458 def get_option_int(options, tag):
1459 """Return an integer option. Raise exception if the value is not an int"""
1460 val = get_option(options, tag)
1464 raise OptionError("--%s <num> (value must be integer)" % (tag))
1467 # simple class for profiling
1474 self._start = time.time()
1475 def stop(self, msg=''):
1476 self._stop = time.time()
1480 return self._stop - self._start
1481 def display(self, msg):
1483 str = '%s: %g secs' % (msg, d)
1486 #################################################################
1487 # function cmdlinesplit used to split cmd line from batch file
1489 def cmdlinesplit(cmdline):
1491 double_quote = re.compile(r'"(([^"\\]|\\.)*)"')
1492 single_quote = re.compile(r"'(.*?)'")
1493 escaped = re.compile(r'\\(.)')
1494 esc_quote = re.compile(r'\\([\\"])')
1495 outside = re.compile(r"""([^\s\\'"]+)""") #" fucking emacs.
1499 while i < len(cmdline):
1502 match = double_quote.match(cmdline, i)
1504 print "Unmatched double quote:", cmdline
1507 if arg is None: arg = esc_quote.sub(r'\1', match.group(1))
1508 else: arg = arg + esc_quote.sub(r'\1', match.group(1))
1511 match = single_quote.match(cmdline, i)
1513 print "Unmatched single quote:", cmdline
1516 if arg is None: arg = match.group(1)
1517 else: arg = arg + match.group(1)
1520 match = escaped.match(cmdline, i)
1522 print "Unmatched backslash", cmdline
1525 if arg is None: arg = match.group(1)
1526 else: arg = arg + match.group(1)
1528 elif c in string.whitespace:
1530 arg_list.append(str(arg))
1532 while i < len(cmdline) and cmdline[i] in string.whitespace:
1535 match = outside.match(cmdline, i)
1538 if arg is None: arg = match.group()
1539 else: arg = arg + match.group()
1541 if arg != None: arg_list.append(str(arg))
1545 ############################################################
1549 def add(devtype, gen, lustre, options):
1550 if devtype == 'net':
1551 add_net(gen, lustre, options)
1552 elif devtype == 'mtpt':
1553 add_mtpt(gen, lustre, options)
1554 elif devtype == 'mds':
1555 add_mds(gen, lustre, options)
1556 elif devtype == 'ost':
1557 add_ost(gen, lustre, options)
1558 elif devtype == 'lov':
1559 add_lov(gen, lustre, options)
1560 elif devtype == 'route':
1561 add_route(gen, lustre, options)
1562 elif devtype == 'node':
1563 add_node(gen, lustre, options)
1564 elif devtype == 'echo_client':
1565 add_echo_client(gen, lustre, options)
1566 elif devtype == 'cobd':
1567 add_cobd(gen, lustre, options)
1568 elif devtype == 'cmobd':
1569 add_cmobd(gen, lustre, options)
1570 elif devtype == 'mgmt':
1571 add_mgmt(gen, lustre, options)
1572 elif devtype == 'lmv':
1573 add_lmv(gen, lustre, options)
1575 error("unknown device type:", devtype)
1577 def delete(devtype, gen, lustre, options):
1578 if devtype == 'ost':
1579 del_ost(gen, lustre, options)
1580 elif options.delete:
1581 error("delete not supported for device type:", devtype)
1582 elif options.deactivate:
1583 error("deactivate not supported for device type:", devtype)
1585 error("in delete(), but neither .delete nor .deactivate are set. Tell CFS.")
1587 def commit(gen, lustre):
1588 commit_version(gen, lustre)
1590 def do_command(gen, lustre, options, args):
1592 add(options.add, gen, lustre, options)
1593 elif options.delete:
1594 delete(options.delete, gen, lustre, options)
1595 elif options.deactivate:
1596 delete(options.deactivate, gen, lustre, options)
1597 elif options.commit:
1600 error("Missing command")
1603 cl = Lustre.Options("lmc", "", lmc_options)
1605 options, args = cl.parse(sys.argv[1:])
1606 except Lustre.OptionError, e:
1610 panic(string.join(sys.argv), "Unexpected extra arguments on command line: " + string.join(args))
1612 if options.reference:
1619 outFile = options.merge
1620 if os.access(outFile, os.R_OK):
1621 doc = xml.dom.minidom.parse(outFile)
1623 doc = new_lustre(xml.dom.minidom)
1625 doc = xml.dom.minidom.parse(options.input)
1627 doc = new_lustre(xml.dom.minidom)
1630 outFile = options.output
1632 lustre = doc.documentElement
1634 if lustre.tagName != "lustre":
1635 print "Existing config not valid."
1638 gen = GenConfig(doc)
1641 fp = open(options.batch)
1642 batchCommands = fp.readlines()
1644 for cmd in batchCommands:
1646 options, args = cl.parse(cmdlinesplit(cmd))
1647 if options.merge or options.input or options.output:
1648 print "The batchfile should not contain --merge, --input or --output."
1650 do_command(gen, lustre, options, args)
1651 except OptionError, e:
1653 except Lustre.OptionError, e:
1657 do_command(gen, lustre, options, args)
1658 except OptionError, e:
1659 panic(string.join(sys.argv),e)
1660 except Lustre.OptionError, e:
1666 printDoc(doc, open(outFile,"w"))
1668 if __name__ == "__main__":