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
77 --nettype tcp|elan|gm|openib|iib|vib|ra
78 --hostaddr ip[/netmask]
91 --backfstype ldiskfs|ext3|tmpfs
99 --mountfsoptions options
100 --root_squash uid:gid
101 --no_root_squash ptl_nid
120 --fstype ldiskfs|ext3
121 --backfstype ldiskfs|ext3|tmpfs
124 --osdtype obdecho|obdfilter
126 --mkfsoptions options
127 --mountfsoptions options
138 --add mtpt - Mountpoint
143 --ost ost_name OR --lov lov_name
144 --clientoptions options
150 --gateway_cluster_id nid
151 --target_cluster_id nid
158 --add mgmt - Management/monitoring service
160 --mgmt mgmt_service_name
167 --master_obd obd_name
172 --master_obd obd_name
175 --commit - Close a configuration version, and start a new one
178 PARAM = Lustre.Options.PARAM
179 PARAMLIST = Lustre.Options.PARAMLIST
181 # lmc input/output options
182 ('reference', "Print short reference for commands."),
183 ('verbose,v', "Print system commands as they are run."),
184 ('merge,m', "Append to the specified config file.", PARAM),
185 ('output,o', "Write XML configuration into given output file. Overwrite existing content.", PARAM),
186 ('input,i', "", PARAM),
187 ('batch', "Used to execute lmc commands in batch mode.", PARAM),
191 ('delete', "", PARAM),
192 ('deactivate', "", PARAM),
193 ('commit', "Commit all config changes and start a new version"),
196 ('node', "Add a new node in the cluster configuration.", PARAM),
197 ('timeout', "Set timeout to initiate recovery.", PARAM),
198 ('upcall', "Set both lustre and portals upcall scripts.", PARAM),
199 ('lustre_upcall', "Set location of lustre upcall script.", PARAM),
200 ('portals_upcall', "Set location of portals upcall script.", PARAM),
201 ('ptldebug', "Set the portals debug level", PARAM),
202 ('subsystem', "Specify which Lustre subsystems have debug output recorded in the log", PARAM),
205 ('nettype', "Specify the network type. This can be tcp/elan/gm/openib/iib/vib/ra.", PARAM),
206 ('nid', "Give the network ID, e.g ElanID/IP Address as used by portals.", PARAM),
207 ('port', "Optional argument to specify the TCP port number.", PARAM, DEFAULT_PORT),
208 ('hostaddr', "Optional argument to specify the host address.", PARAMLIST),
209 ('cluster_id', "Specify the cluster ID", PARAM, "0"),
212 ('route', "Add a new route for the cluster.", PARAM),
213 ('router', "Optional flag to mark a node as router."),
214 ('gw', "Specify the nid of the gateway for a route.", PARAM),
215 ('gateway_cluster_id', "", PARAM, "0"),
216 ('target_cluster_id', "", PARAM, "0"),
217 ('lo', "For a range route, this is the low value nid.", PARAM),
218 ('hi', "For a range route, this is a hi value nid.", PARAM,""),
220 # servers: mds and ost
221 ('mds', "Specify MDS name.", PARAM,""),
222 ('ost', "Specify the OST name.", PARAM,""),
223 ('osdtype', "This could obdfilter or obdecho.", PARAM, "obdfilter"),
224 ('failover', "Enable failover support on OSTs or MDS?"),
225 ('group', "", PARAM),
226 ('dev', "Path of the device on local system.", PARAM,""),
227 ('backdev', "Path of the device for backing storage on local system.", PARAM,""),
228 ('size', "Specify the size of the device if needed.", PARAM,"0"),
229 ('journal_size', "Specify new journal size for underlying file system.", PARAM,"0"),
230 ('inode_size', "Specify new inode size for underlying file system.", PARAM,"0"),
231 ('fstype', "Optional argument to specify the filesystem type.", PARAM, "ext3"),
232 ('backfstype', "Optional argument to specify the backing filesystem type.", PARAM, "ext3"),
233 ('mkfsoptions', "Optional argument to mkfs.", PARAM, ""),
234 ('mountfsoptions', "Optional argument to mount fs.", PARAM, ""),
235 ('ostuuid', "Optional argument to specify OST UUID", PARAM,""),
236 ('mdsuuid', "Optional argument to specify MDS UUID", PARAM,""),
237 ('root_squash', "MDS squash root to appointed uid.", PARAM, ""),
238 ('no_root_squash', "Don't squash root for appointed nid.", PARAM, ""),
239 ('nspath', "Local mount point of server namespace.", PARAM,""),
241 ('migrate', "used for offline migrate of an ost in conjunctio with add/delete"),
243 # clients: mountpoint and echo
244 ('echo_client', "", PARAM),
245 ('path', "Specify the mountpoint for Lustre.", PARAM),
246 ('filesystem', "Lustre filesystem name", PARAM,""),
247 ('clientoptions', "Specify the options for Lustre, such as async.", PARAM, ""),
250 ('lov', "Specify LOV name.", PARAM,""),
251 ('index', "Specify index for OBD in LOV target table.", PARAM),
252 ('stripe_sz', "Specify the stripe size in bytes.", PARAM),
253 ('stripe_cnt', "Specify the number of OSTs each file should be striped on.", PARAM, 0),
254 ('stripe_pattern', "Specify the stripe pattern. RAID 0 is the only one currently supported.", PARAM, 0),
258 ('master_obd', "Specify the real device for the cache obd system.", PARAM),
259 ('cache_obd', "Specify the cache device for the cache obd system.", PARAM),
260 ('cobd', "Specify COBD name", PARAM),
263 ('master_obd', "Specify the master device for the cmobd system.", PARAM),
264 ('cache_obd', "Specify the cache device for the cmobd obd system.", PARAM),
265 ('cmobd', "Specify COBD name", PARAM),
268 ('mgmt', "Specify management/monitoring service name.", PARAM, ""),
271 ('lmv', "Specify LMV name.", PARAM,""),
275 msg = string.join(map(str,args))
276 raise OptionError("Error: " + msg)
285 msg = string.join(map(str,args))
286 print "Warning: ", msg
289 # manage names and uuids
290 # need to initialize this by walking tree to ensure
291 # no duplicate names or uuids are created.
292 # this are just place holders for now.
293 # consider changing this to be like OBD-dev-host
297 while names.has_key(ret):
298 ret = "%s_%d" % (base, ctr)
305 ret = "%s_UUID" % (name)
306 if len(ret) > UUID_MAX_LENGTH:
307 ret = ret[-UUID_MAX_LENGTH:]
308 while uuids.has_key(ret):
309 ret = "%s_UUID_%d" % (name, ctr)
311 if len(ret) > UUID_MAX_LENGTH:
312 ret = ret[-UUID_MAX_LENGTH:]
318 ldlm_uuid = 'ldlm_UUID'
321 """Create a new empty lustre document"""
322 # adding ldlm here is a bit of a hack, but one is enough.
323 str = """<lustre version="%s">
324 <ldlm name="%s" uuid="%s"/>
325 </lustre>""" % (Lustre.CONFIG_VERSION, ldlm_name, ldlm_uuid)
326 return dom.parseString(str)
332 """initialize auto-name generation tables"""
334 # get all elements that contain a name attribute
335 for n in doc.childNodes:
336 if n.nodeType == n.ELEMENT_NODE:
338 names[getName(n)] = 1
339 uuids[getUUID(n)] = 1
342 def get_format_flag(options):
347 ############################################################
348 # Build config objects using DOM
353 def __init__(self, doc):
356 def ref(self, type, uuid):
357 """ generate <[type]_ref uuidref="[uuid]"/> """
358 tag = "%s_ref" % (type)
359 ref = self.doc.createElement(tag)
360 ref.setAttribute("uuidref", uuid)
363 def dev(self, devname):
364 """ generate <dev devpath="[devname]"/> """
365 tgt = self.doc.createElement('dev')
366 tgt.setAttribute("dev", devname)
369 def newService(self, tag, name, uuid):
370 """ create a new service elmement, which requires name and uuid attributes """
371 new = self.doc.createElement(tag)
372 new.setAttribute("uuid", uuid);
373 new.setAttribute("name", name);
376 def addText(self, node, str):
377 txt = self.doc.createTextNode(str)
378 node.appendChild(txt)
380 def addElement(self, node, tag, str=None):
381 """ create a new element and add it as a child to node. If str is passed,
382 a text node is created for the new element"""
383 new = self.doc.createElement(tag)
385 self.addText(new, str)
386 node.appendChild(new)
389 def network(self, name, uuid, nid, cluster_id, net, hostaddr="",
391 """create <network> node"""
392 network = self.newService("network", name, uuid)
393 network.setAttribute("nettype", net);
394 self.addElement(network, "nid", nid)
395 self.addElement(network, "clusterid", cluster_id)
396 for host in hostaddr:
397 self.addElement(network, "hostaddr", host)
399 self.addElement(network, "port", "%d" %(port))
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, master_uuid, cache_uuid):
469 cobd = self.newService("cobd", name, uuid)
470 cobd.appendChild(self.ref("masterobd",master_uuid))
471 cobd.appendChild(self.ref("cacheobd",cache_uuid))
474 def cmobd(self, name, uuid, master_uuid, cache_uuid):
475 cmobd = self.newService("cmobd", name, uuid)
476 cmobd.appendChild(self.ref("masterobd",master_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_tgt(self, mdt_uuid):
513 tgt = self.doc.createElement('lmv_tgt')
514 tgt.setAttribute("uuidref", mdt_uuid)
517 def lmv(self, name, uuid):
518 lmv = self.newService("lmv", name, uuid)
521 def mds(self, name, uuid, mdd_uuid, group="", lmv=""):
522 mds = self.newService("mds", name, uuid)
523 mds.appendChild(self.ref("active", mdd_uuid))
525 self.addElement(mds, "group", group)
528 def mdsdev(self, name, uuid, fstype, devname, format, node_uuid,
529 mds_uuid, dev_size=0, journal_size=0, inode_size=256,
530 nspath="", mkfsoptions="", mountfsoptions="", backfstype="",
531 backdevname="",lmv_uuid="", root_squash="", no_root_squash=""):
532 mdd = self.newService("mdsdev", name, uuid)
533 self.addElement(mdd, "fstype", fstype)
535 self.addElement(mdd, "backfstype", backfstype)
536 dev = self.addElement(mdd, "devpath", devname)
538 self.addElement(mdd, "backdevpath", backdevname)
539 self.addElement(mdd, "autoformat", format)
541 self.addElement(mdd, "devsize", "%s" % (dev_size))
543 self.addElement(mdd, "journalsize", "%s" % (journal_size))
545 self.addElement(mdd, "inodesize", "%s" % (inode_size))
547 self.addElement(mdd, "nspath", nspath)
549 self.addElement(mdd, "mkfsoptions", mkfsoptions)
551 self.addElement(mdd, "mountfsoptions", mountfsoptions)
553 self.addElement(mdd, "root_squash", root_squash)
555 self.addElement(mdd, "no_root_squash", no_root_squash)
556 mdd.appendChild(self.ref("node", node_uuid))
557 mdd.appendChild(self.ref("target", mds_uuid))
559 dev = self.dev(devname)
564 mdd.appendChild(self.ref("lmv", lmv_uuid))
565 self.addElement(mdd, "lmv", lmv_uuid)
569 def mgmt(self, mgmt_name, mgmt_uuid, node_uuid):
570 mgmt = self.newService("mgmt", mgmt_name, mgmt_uuid)
571 mgmt.appendChild(self.ref("node", node_uuid))
572 # Placeholder until mgmt-service failover.
573 mgmt.appendChild(self.ref("active", mgmt_uuid))
576 def mountpoint(self, name, uuid, fs_uuid, path, clientoptions):
577 mtpt = self.newService("mountpoint", name, uuid)
578 mtpt.appendChild(self.ref("filesystem", fs_uuid))
579 self.addElement(mtpt, "path", path)
581 self.addElement(mtpt, "clientoptions", clientoptions)
584 def filesystem(self, name, uuid, mds_uuid, obd_uuid, mgmt_uuid):
585 fs = self.newService("filesystem", name, uuid)
586 fs.appendChild(self.ref("mds", mds_uuid))
587 fs.appendChild(self.ref("obd", obd_uuid))
589 fs.appendChild(self.ref("mgmt", mgmt_uuid))
592 def echo_client(self, name, uuid, osc_uuid):
593 ec = self.newService("echoclient", name, uuid)
594 ec.appendChild(self.ref("obd", osc_uuid))
597 def update(self, version):
598 new = self.doc.createElement("update")
599 new.setAttribute("version", version)
602 def add(self, lov, ost, index, gen):
603 new = self.doc.createElement("add")
604 new.setAttribute("lov_uuidref", lov)
605 new.setAttribute("ost_uuidref", ost)
606 new.setAttribute("index", index)
607 new.setAttribute("generation", gen)
610 def delete(self, lov, ost, index, gen, options):
612 new = self.doc.createElement("delete")
614 new = self.doc.createElement("deactivate")
615 new.setAttribute("lov_uuidref", lov)
616 new.setAttribute("ost_uuidref", ost)
617 new.setAttribute("index", index)
618 new.setAttribute("generation", gen)
621 ############################################################
622 # Utilities to query a DOM tree
623 # Using this functions we can treat use config information
624 # directly as a database.
626 return n.getAttribute('name')
629 return node.getAttribute('uuid')
631 def findLastUpdate(lustre):
634 for n in lustre.childNodes:
635 if n.nodeType == n.ELEMENT_NODE:
636 if n.nodeName != 'update':
638 tmp = int(n.getAttribute('version'))
640 error('malformed XML: update tag without a version attribute')
641 if tmp != version + 1:
642 error('malformed XML: expecting update record '+str(version + 1)+', found '+str(tmp)+'.')
647 def addUpdate(gen, lustre, node):
648 update = findLastUpdate(lustre)
651 #add_record = update.getElementsByTagName('add')
653 # add_record = gen.add()
654 # update.appendChild(add_record)
656 # add_record = add_record[0]
657 #add_record.appendChild(node)
658 update.appendChild(node)
660 def delUpdate(gen, lustre, node):
661 update = findLastUpdate(lustre)
664 update.appendChild(node)
666 def findByName(lustre, name, tag = ""):
667 for n in lustre.childNodes:
668 if n.nodeType == n.ELEMENT_NODE:
669 if tag and n.nodeName != tag:
671 if getName(n) == name:
674 n = findByName(n, name)
679 def lookup(node, uuid):
680 for n in node.childNodes:
681 if n.nodeType == n.ELEMENT_NODE:
682 if getUUID(n) == uuid:
690 def name2uuid(lustre, name, tag="", fatal=1):
691 ret = findByName(lustre, name, tag)
694 error('name2uuid:', '"'+name+'"', tag, 'element not found.')
699 def lookup_filesystem(lustre, mds_uuid, ost_uuid):
700 for n in lustre.childNodes:
701 if n.nodeType == n.ELEMENT_NODE and n.nodeName == 'filesystem':
702 if ref_exists(n, mds_uuid) and ref_exists(n, ost_uuid):
706 # XXX: assumes only one network element per node. will fix this
707 # as soon as support for routers is added
708 def get_net_uuid(lustre, node_name):
709 """ get a network uuid for a node_name """
710 node = findByName(lustre, node_name, "node")
712 error ('get_net_uuid:', '"'+node_name+'"', "node element not found.")
713 net = node.getElementsByTagName('network')
715 return getUUID(net[0])
718 def lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options):
719 tgt.setAttribute('uuidref', osc_uuid)
721 gener = int(tgt.getAttribute('generation'))
723 gener = int(tgt.getAttribute('generation')) + 1
724 tgt.setAttribute('generation', str(gener))
725 tgt.setAttribute('active', '1')
726 lov_index = int(tgt.getAttribute('index'))
727 addUpdate(gen, lustre, gen.add(getUUID(lov), osc_uuid, str(lov_index),
731 def lov_add_obd(gen, lustre, lov, osc_uuid, options):
732 lov_name = getName(lov)
734 lov_index = get_option_int(options, 'index')
735 for tgt in lustre.getElementsByTagName('lov_tgt'):
736 if str(lov_index) == tgt.getAttribute('index'):
737 uuidref = tgt.getAttribute('uuidref')
739 raise OptionError("%s --index %d is still in use: %s" %
740 (lov_name, lov_index, uuidref))
741 lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
745 for tgt in lustre.getElementsByTagName('lov_tgt'):
746 uuidref = tgt.getAttribute('uuidref')
747 tmp = int(tgt.getAttribute('index'))
749 error('malformed xml: LOV targets are not ordered; found index '+str(tmp)+', expected '+str(lov_index)+'.')
750 uuidref = tgt.getAttribute('uuidref')
752 lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
754 lov_index = lov_index + 1
756 lov.appendChild(gen.lov_tgt(osc_uuid, str(lov_index), '1'))
757 addUpdate(gen, lustre, gen.add(getUUID(lov), osc_uuid, str(lov_index), '1'))
759 def lov_del_obd(gen, lustre, lov, osc_uuid, options):
760 lov_name = getName(lov)
762 lov_index = get_option_int(options, 'index')
763 for tgt in lustre.getElementsByTagName('lov_tgt'):
764 index = tgt.getAttribute('index')
765 if index == lov_index:
766 uuidref = tgt.getAttribute('uuidref')
767 if uuidref != osc_uuid:
768 raise OptionError("%s --index %d contains %s, not %s" %
769 (lov_name, lov_index, osc_uuid, uuidref))
771 tgt.setAttribute('uuidref', '')
773 # bump the generation just in case...
775 gen = int(tgt.getAttribute('generation'))
777 gen = int(tgt.getAttribute('generation')) + 1
779 tgt.setAttribute('active', '0')
780 tgt.setAttribute('generation', str(gen))
782 raise OptionError("%s --index %d not in use by %s." %
783 (lov_name, lov_index, osc_uuid))
785 for tgt in lustre.getElementsByTagName('lov_tgt'):
786 uuidref = tgt.getAttribute('uuidref')
787 if uuidref == osc_uuid:
788 genera = int(tgt.getAttribute('generation'))
789 delete_rec = gen.delete(getUUID(lov),
790 osc_uuid,tgt.getAttribute('index'),
791 str(genera), options)
792 delUpdate(gen, lustre, delete_rec)
795 tgt.setAttribute('uuidref', '')
796 if not options.migrate:
798 tgt.setAttribute('active', '0')
799 tgt.setAttribute('generation', str(genera))
801 def lmv_add_obd(gen, lmv, mdc_uuid):
802 lmv.appendChild(gen.lmv_tgt(mdc_uuid))
804 def ref_exists(profile, uuid):
805 elist = profile.childNodes
807 if e.nodeType == e.ELEMENT_NODE:
808 ref = e.getAttribute('uuidref')
813 # ensure that uuid is not already in the profile
814 # return true if uuid is added
815 def node_add_profile(gen, node, ref, uuid):
816 refname = "%s_ref" % "profile"
817 ret = node.getElementsByTagName(refname)
819 error('node has no profile ref:', node)
820 prof_uuid = ret[0].getAttribute('uuidref')
821 profile = lookup(node.parentNode, prof_uuid)
823 error("no profile found:", prof_uuid)
824 if ref_exists(profile, uuid):
826 profile.appendChild(gen.ref(ref, uuid))
829 def get_attr(dom_node, attr, default=""):
830 v = dom_node.getAttribute(attr)
835 ############################################################
838 def set_node_options(gen, node, options):
840 node.setAttribute('router', '1')
842 gen.addElement(node, "timeout", get_option(options, 'timeout'))
844 default_upcall = get_option(options, 'upcall')
847 if default_upcall or options.lustre_upcall:
848 if options.lustre_upcall:
849 gen.addElement(node, 'lustreUpcall', options.lustre_upcall)
851 gen.addElement(node, 'lustreUpcall', default_upcall)
852 if default_upcall or options.portals_upcall:
853 if options.portals_upcall:
854 gen.addElement(node, 'portalsUpcall', options.portals_upcall)
856 gen.addElement(node, 'portalsUpcall', default_upcall)
858 gen.addElement(node, "ptldebug", get_option(options, 'ptldebug'))
859 if options.subsystem:
860 gen.addElement(node, "subsystem", get_option(options, 'subsystem'))
863 def do_add_node(gen, lustre, options, node_name):
864 uuid = new_uuid(node_name)
865 prof_name = new_name("PROFILE_" + node_name)
866 prof_uuid = new_uuid(prof_name)
867 profile = gen.profile(prof_name, prof_uuid)
868 node = gen.node(node_name, uuid, prof_uuid)
869 lustre.appendChild(node)
870 lustre.appendChild(profile)
872 node_add_profile(gen, node, 'ldlm', ldlm_uuid)
873 set_node_options(gen, node, options)
878 def add_node(gen, lustre, options):
879 """ create a node with a network config """
881 node_name = get_option(options, 'node')
882 ret = findByName(lustre, node_name, "node")
884 print "Node:", node_name, "exists."
886 do_add_node(gen, lustre, options, node_name)
889 def add_net(gen, lustre, options):
890 """ create a node with a network config """
892 node_name = get_option(options, 'node')
893 nid = get_option(options, 'nid')
894 cluster_id = get_option(options, 'cluster_id')
895 hostaddr = get_option(options, 'hostaddr')
896 net_type = get_option(options, 'nettype')
898 if net_type in ('tcp','openib','ra'):
899 port = get_option_int(options, 'port')
900 elif net_type in ('elan','gm','iib','vib','lo'):
903 print "Unknown net_type: ", net_type
906 ret = findByName(lustre, node_name, "node")
908 node = do_add_node(gen, lustre, options, node_name)
911 set_node_options(gen, node, options)
913 net_name = new_name('NET_'+ node_name +'_'+ net_type)
914 net_uuid = new_uuid(net_name)
915 node.appendChild(gen.network(net_name, net_uuid, nid, cluster_id, net_type,
917 node_add_profile(gen, node, "network", net_uuid)
920 def add_route(gen, lustre, options):
921 """ create a node with a network config """
923 node_name = get_option(options, 'node')
924 gw_net_type = get_option(options, 'nettype')
925 gw = get_option(options, 'gw')
926 gw_cluster_id = get_option(options, 'gateway_cluster_id')
927 tgt_cluster_id = get_option(options, 'target_cluster_id')
928 lo = get_option(options, 'lo')
929 hi = get_option(options, 'hi')
933 node = findByName(lustre, node_name, "node")
935 error (node_name, " not found.")
937 rlist = node.getElementsByTagName('routetbl')
941 rtbl_name = new_name("RTBL_" + node_name)
942 rtbl_uuid = new_uuid(rtbl_name)
943 rtbl = gen.routetbl(rtbl_name, rtbl_uuid)
944 node.appendChild(rtbl)
945 node_add_profile(gen, node, "routetbl", rtbl_uuid)
946 rtbl.appendChild(gen.route(gw_net_type, gw, gw_cluster_id, tgt_cluster_id,
949 def add_mds(gen, lustre, options):
950 node_name = get_option(options, 'node')
951 mds_name = get_option(options, 'mds')
953 mds_name = new_name('MDS_'+ node_name)
954 lmv_name = get_option(options, 'lmv')
955 mdd_name = new_name("MDD_" + mds_name +"_" + node_name)
956 mdd_uuid = new_uuid(mdd_name)
960 lmv = findByName(lustre, lmv_name, "lmv")
962 error('add_mds:', '"' + lmv_name + '"', "lmv element not found.")
963 lmv_uuid = name2uuid(lustre, lmv_name, fatal=0)
965 mds_uuid = name2uuid(lustre, mds_name, 'mds', fatal=0)
967 mds_uuid = get_option(options, 'mdsuuid')
969 if lookup(lustre, mds_uuid):
970 error("Duplicate MDS UUID:", mds_uuid)
972 mds_uuid = new_uuid(mds_name)
973 mds = gen.mds(mds_name, mds_uuid, mdd_uuid, options.group)
974 lustre.appendChild(mds)
976 lmv_add_obd(gen, lmv, mds_uuid)
978 mds = lookup(lustre, mds_uuid)
981 mds.setAttribute('failover', "1")
983 devname = get_option(options, 'dev')
984 backdevname = get_option(options, 'backdev')
985 size = get_option(options, 'size')
986 fstype = get_option(options, 'fstype')
987 backfstype = get_option(options, 'backfstype')
988 journal_size = get_option(options, 'journal_size')
989 inode_size = get_option(options, 'inode_size')
990 nspath = get_option(options, 'nspath')
991 mkfsoptions = get_option(options, 'mkfsoptions')
992 mountfsoptions = get_option(options, 'mountfsoptions')
993 root_squash = get_option(options, 'root_squash')
994 no_root_squash = get_option(options, 'no_root_squash')
996 node_uuid = name2uuid(lustre, node_name, 'node')
998 node = findByName(lustre, node_name, "node")
999 node_add_profile(gen, node, "mdsdev", mdd_uuid)
1000 net_uuid = get_net_uuid(lustre, node_name)
1002 error("NODE: ", node_name, "not found")
1005 mds.appendChild(gen.ref("lmv", lmv_uuid))
1007 mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname,
1008 get_format_flag(options), node_uuid, mds_uuid,
1009 size, journal_size, inode_size, nspath, mkfsoptions,
1010 mountfsoptions, backfstype, backdevname,lmv_uuid,
1011 root_squash, no_root_squash)
1012 lustre.appendChild(mdd)
1015 def add_mgmt(gen, lustre, options):
1016 node_name = get_option(options, 'node')
1017 node_uuid = name2uuid(lustre, node_name, 'node')
1018 mgmt_name = get_option(options, 'mgmt')
1020 mgmt_name = new_name('MGMT_' + node_name)
1021 mgmt_uuid = name2uuid(lustre, mgmt_name, 'mgmt', fatal=0)
1023 mgmt_uuid = new_uuid(mgmt_name)
1024 mgmt = gen.mgmt(mgmt_name, mgmt_uuid, node_uuid)
1025 lustre.appendChild(mgmt)
1027 mgmt = lookup(lustre, mgmt_uuid)
1029 node = findByName(lustre, node_name, "node")
1030 node_add_profile(gen, node, 'mgmt', mgmt_uuid)
1032 def add_ost(gen, lustre, options):
1033 node_name = get_option(options, 'node')
1034 lovname = get_option(options, 'lov')
1035 osdtype = get_option(options, 'osdtype')
1037 node_uuid = name2uuid(lustre, node_name, 'node')
1039 if osdtype == 'obdecho':
1050 devname = get_option(options, 'dev') # can be unset for bluearcs
1051 backdevname = get_option(options, 'backdev')
1052 size = get_option(options, 'size')
1053 fstype = get_option(options, 'fstype')
1054 backfstype = get_option(options, 'backfstype')
1055 journal_size = get_option(options, 'journal_size')
1056 inode_size = get_option(options, 'inode_size')
1057 mkfsoptions = get_option(options, 'mkfsoptions')
1058 mountfsoptions = get_option(options, 'mountfsoptions')
1060 nspath = get_option(options, 'nspath')
1062 ostname = get_option(options, 'ost')
1064 ostname = new_name('OST_'+ node_name)
1066 osdname = new_name("OSD_" + ostname + "_" + node_name)
1067 osd_uuid = new_uuid(osdname)
1069 ost_uuid = name2uuid(lustre, ostname, 'ost', fatal=0)
1071 ost_uuid = get_option(options, 'ostuuid')
1073 if lookup(lustre, ost_uuid):
1074 error("Duplicate OST UUID:", ost_uuid)
1076 ost_uuid = new_uuid(ostname)
1078 ost = gen.ost(ostname, ost_uuid, osd_uuid, options.group)
1079 lustre.appendChild(ost)
1081 ost = lookup(lustre, ost_uuid)
1084 lov = findByName(lustre, lovname, "lov")
1086 error('add_ost:', '"'+lovname+'"', "lov element not found.")
1087 lov_add_obd(gen, lustre, lov, ost_uuid, options)
1089 if options.failover:
1090 ost.setAttribute('failover', "1")
1093 osd = gen.osd(osdname, osd_uuid, fstype, osdtype, devname,
1094 get_format_flag(options), ost_uuid, node_uuid, size,
1095 journal_size, inode_size, nspath, mkfsoptions,
1096 mountfsoptions, backfstype, backdevname)
1098 node = findByName(lustre, node_name, "node")
1100 ## if node_add_profile(gen, node, 'oss', oss_uuid):
1102 ## oss_uuid = new_uuid(ossname)
1103 ## oss = gen.oss(ossname, oss_uuid)
1104 ## lustre.appendChild(oss)
1106 node_add_profile(gen, node, 'osd', osd_uuid)
1107 lustre.appendChild(osd)
1109 def del_ost(gen, lustre, options):
1110 ostname = get_option(options, 'ost')
1112 raise OptionError("del_ost: --ost requires a <ost name>")
1113 ost = findByName(lustre, ostname, "ost")
1115 error('del_ost: ', 'Unable to find ', ostname)
1116 ost_uuid = name2uuid(lustre, ostname, fatal=0)
1118 error('del_ost: ', 'Unable to find uuid for ', ostname)
1119 lovname = get_option(options, 'lov')
1121 lov = findByName(lustre, lovname, "lov")
1123 error('del_ost:', '"'+lovname+'"', "lov element not found.")
1124 lov_del_obd(gen, lustre, lov, ost_uuid, options)
1125 # if the user specified a speficic LOV don't delete the OST itself
1128 # remove OSD references from all LOVs
1129 for n in lustre.getElementsByTagName('lov'):
1130 lov_del_obd(gen, lustre, n, ost_uuid, options)
1131 if not options.migrate:
1134 for osd in lustre.getElementsByTagName('osd'):
1135 if ref_exists(osd, ost_uuid):
1136 osd_uuid = osd.getAttribute('uuid')
1137 # delete all profile references to this OSD
1138 for profile in lustre.getElementsByTagName('profile'):
1139 for osd_ref in profile.getElementsByTagName('osd_ref'):
1140 if osd_uuid == osd_ref.getAttribute('uuidref'):
1141 profile.removeChild(osd_ref)
1142 lustre.removeChild(osd)
1145 lustre.removeChild(ost)
1147 def add_cmobd(gen, lustre, options):
1148 node_name = get_option(options, 'node')
1149 name = get_option(options, 'cmobd')
1150 uuid = new_uuid(name)
1152 master_name = get_option(options, 'master_obd')
1153 cache_name = get_option(options, 'cache_obd')
1155 master_uuid = name2uuid(lustre, master_name, tag='lov', fatal=0)
1156 cache_uuid = name2uuid(lustre, cache_name, tag='lov', fatal=0)
1158 if not master_uuid or not cache_uuid:
1160 master_uuid = name2uuid(lustre, master_name, tag='ost', fatal=0)
1162 cache_uuid = name2uuid(lustre, cache_name, tag='ost', fatal=0)
1164 if not master_uuid or not cache_uuid:
1166 master_uuid = name2uuid(lustre, master_name, tag='lmv', fatal=0)
1168 cache_uuid = name2uuid(lustre, cache_name, tag='lmv', fatal=0)
1170 if not master_uuid or not cache_uuid:
1172 master_uuid = name2uuid(lustre, master_name, tag='mds', fatal=0)
1174 cache_uuid = name2uuid(lustre, cache_name, tag='mds', fatal=0)
1177 panic("add_cmobd", "cannot find master_uuid by name '" +
1180 panic("add_cmobd", "cannot find cache_uuid by name '" +
1183 node = findByName(lustre, node_name, "node")
1184 node_add_profile(gen, node, "cmobd", uuid)
1186 master_node = lookup(lustre, master_uuid)
1187 cache_node = lookup(lustre, cache_uuid)
1189 panic("cmobd_add", "cannot find master node by its uuid " +
1192 panic("cmobd_add", "cannot find cache node by its uuid " +
1195 active = master_node.getElementsByTagName('active_ref')
1197 active_uuid = active[0].getAttribute('uuidref')
1198 active_node = lookup(lustre, active_uuid)
1199 if not active_node.getElementsByTagName('obdtype'):
1200 gen.addElement(active_node, 'obdtype', 'master')
1202 active = cache_node.getElementsByTagName('active_ref')
1204 active_uuid = active[0].getAttribute('uuidref')
1205 active_node = lookup(lustre, active_uuid)
1206 if not active_node.getElementsByTagName('obdtype'):
1207 gen.addElement(active_node, 'obdtype', 'cache')
1209 cmobd = gen.cmobd(name, uuid, master_uuid, cache_uuid)
1210 lustre.appendChild(cmobd)
1212 def add_cobd(gen, lustre, options):
1213 node_name = get_option(options, 'node')
1214 name = get_option(options, 'cobd')
1215 uuid = new_uuid(name)
1217 master_name = get_option(options, 'master_obd')
1218 cache_name = get_option(options, 'cache_obd')
1220 master_uuid = name2uuid(lustre, master_name, tag='lov', fatal=0)
1221 cache_uuid = name2uuid(lustre, cache_name, tag='lov', fatal=0)
1223 if not master_uuid or not cache_uuid:
1224 master_uuid = name2uuid(lustre, master_name, tag='ost', fatal=0)
1225 cache_uuid = name2uuid(lustre, cache_name, tag='ost', fatal=0)
1228 node = lookup(lustre, master_uuid)
1229 rets = node.getElementsByTagName('lov_tgt')
1231 ost_uuid = ret.getAttribute('uuidref')
1232 ost_node = lookup(lustre, ost_uuid)
1233 active = ost_node.getElementsByTagName('active_ref')
1235 osd_uuid = active[0].getAttribute('uuidref')
1236 osd_node = lookup(lustre, osd_uuid)
1237 if not osd_node.getElementsByTagName('obdtype'):
1238 gen.addElement(osd_node, 'obdtype', 'master')
1241 node = lookup(lustre, cache_uuid)
1242 rets = node.getElementsByTagName('lov_tgt')
1244 ost_uuid = ret.getAttribute('uuidref')
1245 ost_node = lookup(lustre, ost_uuid)
1246 active = ost_node.getElementsByTagName('active_ref')
1248 osd_uuid = active[0].getAttribute('uuidref')
1249 osd_node = lookup(lustre, osd_uuid)
1250 if not osd_node.getElementsByTagName('obdtype'):
1251 gen.addElement(osd_node, 'obdtype', 'cache')
1253 if not master_uuid or not cache_uuid:
1254 master_uuid = name2uuid(lustre,master_name, tag='mds')
1255 cache_uuid = name2uuid(lustre,cache_name, tag='mds')
1257 mds_node = lookup(lustre, master_uuid)
1258 ret = mds_node.getElementsByTagName('active_ref')
1260 mdsdev_uuid = ret[0].getAttribute('uuidref')
1261 mdsdev_node = lookup(lustre, mdsdev_uuid)
1262 if not mdsdev_node.getElementsByTagName('obdtype'):
1263 gen.addElement(mdsdev_node, 'obdtype', 'master')
1265 mds_node = lookup(lustre, cache_uuid)
1266 ret = mds_node.getElementsByTagName('active_ref')
1268 mdsdev_uuid = ret[0].getAttribute('uuidref')
1269 mdsdev_node = lookup(lustre, mdsdev_uuid)
1270 if not mdsdev_node.getElementsByTagName('obdtype'):
1271 gen.addElement(mdsdev_node, 'obdtype', 'cache')
1273 node = findByName(lustre, node_name, "node")
1274 cobd = gen.cobd(name, uuid, master_uuid, cache_uuid)
1275 lustre.appendChild(cobd)
1277 def add_echo_client(gen, lustre, options):
1278 """ add an echo client to the profile for this node. """
1279 node_name = get_option(options, 'node')
1280 lov_name = get_option(options, 'ost')
1282 node = findByName(lustre, node_name, 'node')
1284 echoname = new_name('ECHO_'+ node_name)
1285 echo_uuid = new_uuid(echoname)
1286 node_add_profile(gen, node, 'echoclient', echo_uuid)
1288 lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
1290 lov_uuid = name2uuid(lustre, lov_name, tag='ost', fatal=1)
1292 echo = gen.echo_client(echoname, echo_uuid, lov_uuid)
1293 lustre.appendChild(echo)
1296 def add_lov(gen, lustre, options):
1297 """ create a lov """
1299 lmv_name = get_option(options, 'lmv')
1300 lov_orig = get_option(options, 'lov')
1301 name = new_name(lov_orig)
1302 if name != lov_orig:
1303 warning("name:", lov_orig, "already used. using:", name)
1305 mds_name = get_option(options, 'mds')
1306 if not mds_name and not lmv_name:
1307 error("LOV: MDS or LMV must be specified.");
1309 stripe_sz = get_option_int(options, 'stripe_sz')
1310 stripe_cnt = get_option_int(options, 'stripe_cnt')
1311 pattern = get_option_int(options, 'stripe_pattern')
1312 uuid = new_uuid(name)
1314 ret = findByName(lustre, name, "lov")
1316 error("LOV: ", name, " already exists.")
1319 mds_uuid = name2uuid(lustre, lmv_name, 'lmv')
1321 mds_uuid = name2uuid(lustre, mds_name, 'mds')
1323 lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
1324 lustre.appendChild(lov)
1326 # add an lovconfig entry to the active mdsdev profile
1327 lovconfig_name = new_name('LVCFG_' + name)
1328 lovconfig_uuid = new_uuid(lovconfig_name)
1330 mds = findByName(lustre, mds_name, "mds")
1331 mds.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1332 mds.appendChild(gen.ref("client", uuid))
1335 lmv = findByName(lustre, lmv_name, "lmv")
1336 lmv.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1337 lmv.appendChild(gen.ref("client", uuid))
1339 lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
1340 lustre.appendChild(lovconfig)
1342 def add_default_lov(gen, lustre, mds_name, lov_name):
1343 """ create a default lov """
1345 stripe_sz = DEFAULT_STRIPE_SZ
1346 stripe_cnt = DEFAULT_STRIPE_CNT
1347 pattern = DEFAULT_STRIPE_PATTERN
1348 uuid = new_uuid(lov_name)
1350 ret = findByName(lustre, lov_name, "lov")
1352 error("LOV: ", lov_name, " already exists.")
1354 mds_uuid = name2uuid(lustre, mds_name, 'mds')
1355 lov = gen.lov(lov_name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
1356 lustre.appendChild(lov)
1358 # add an lovconfig entry to the active mdsdev profile
1359 lovconfig_name = new_name('LVCFG_' + lov_name)
1360 lovconfig_uuid = new_uuid(lovconfig_name)
1361 mds = findByName(lustre, mds_name)
1362 mds.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1363 lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
1364 lustre.appendChild(lovconfig)
1366 def add_lmv(gen, lustre, options):
1367 """ create a lmv """
1369 lmv_orig = get_option(options, 'lmv')
1370 name = new_name(lmv_orig)
1371 if name != lmv_orig:
1372 warning("name:", lmv_orig, "already used. using:", name)
1374 uuid = new_uuid(name)
1375 ret = findByName(lustre, name, "lmv")
1377 error("LMV: ", name, " already exists.")
1379 lmv = gen.lmv(name, uuid)
1380 lustre.appendChild(lmv)
1382 def find_client(lustre, mds_uuid, client_uuid):
1383 mds = lookup(lustre, mds_uuid)
1384 clients = mds.getElementsByTagName('client_ref')
1387 for client in clients:
1388 if client.getAttribute("uuidref") == client_uuid:
1392 def new_filesystem(gen, lustre, mds_uuid, obd_uuid, mgmt_uuid):
1393 fs_name = new_name("FS_fsname")
1394 fs_uuid = new_uuid(fs_name)
1396 mds = lookup(lustre, mds_uuid)
1397 clients = mds.getElementsByTagName('client_ref')
1399 if find_client(lustre, mds_uuid, obd_uuid) == 0:
1400 mds.appendChild(gen.ref("client", obd_uuid))
1402 fs = gen.filesystem(fs_name, fs_uuid, mds_uuid,
1403 obd_uuid, mgmt_uuid)
1405 lustre.appendChild(fs)
1408 def get_fs_uuid(gen, lustre, mds_name, obd_name, mgmt_name):
1409 mds_uuid = name2uuid(lustre, mds_name, tag='mds', fatal=0)
1411 mds_uuid = name2uuid(lustre, mds_name, tag='lmv', fatal=0)
1413 mds_uuid = name2uuid(lustre, mds_name, tag='cobd', fatal=1)
1415 obd_uuid = name2uuid(lustre, obd_name, tag='ost', fatal=0)
1417 obd_uuid = name2uuid(lustre, obd_name, tag='lov', fatal=0)
1419 obd_uuid = name2uuid(lustre, obd_name, tag='cobd', fatal=1)
1421 mgmt_uuid = name2uuid(lustre, mgmt_name, tag='mgmt', fatal=1)
1425 fs_uuid = lookup_filesystem(lustre, mds_uuid, obd_uuid)
1427 fs_uuid = new_filesystem(gen, lustre, mds_uuid,
1428 obd_uuid, mgmt_uuid)
1431 def add_mtpt(gen, lustre, options):
1432 """ create mtpt on a node """
1433 node_name = get_option(options, 'node')
1435 path = get_option(options, 'path')
1436 clientoptions = get_option(options, "clientoptions")
1437 fs_name = get_option(options, 'filesystem')
1439 lov_name = get_option(options, 'lov')
1440 ost_name = get_option(options, 'ost')
1441 mds_name = get_option(options, 'mds')
1443 mds_name = get_option(options, 'lmv')
1445 error("--add mtpt requires either --mds or --lmv.")
1448 error("--add mtpt requires --lov lov_name or --ost ost_name")
1450 warning("use default value for lov, due no --lov lov_name provided")
1451 lov_name = new_name("lov_default")
1452 add_default_lov(gen, lustre, mds_name, lov_name)
1453 ost_uuid = name2uuid(lustre, ost_name, 'ost', fatal=0)
1455 error('add_mtpt:', '"'+ost_name+'"', "ost element not found.")
1456 lov = findByName(lustre, lov_name, "lov")
1457 lov_add_obd(gen, lustre, lov, ost_uuid, options)
1460 mgmt_name = get_option(options, 'mgmt')
1461 fs_uuid = get_fs_uuid(gen, lustre, mds_name, lov_name, mgmt_name)
1463 fs_uuid = name2uuid(lustre, fs_name, tag='filesystem')
1465 name = new_name('MNT_'+ node_name)
1467 ret = findByName(lustre, name, "mountpoint")
1469 # this can't happen, because new_name creates unique names
1470 error("MOUNTPOINT: ", name, " already exists.")
1472 uuid = new_uuid(name)
1473 mtpt = gen.mountpoint(name, uuid, fs_uuid, path, clientoptions)
1474 node = findByName(lustre, node_name, "node")
1476 error('node:', node_name, "not found.")
1477 node_add_profile(gen, node, "mountpoint", uuid)
1478 lustre.appendChild(mtpt)
1480 def commit_version(gen, lustre):
1481 update = findLastUpdate(lustre)
1483 version = int(update.getAttribute("version")) + 1
1487 new = gen.update(str(version))
1488 lustre.appendChild(new)
1491 ############################################################
1492 # Command line processing
1494 class OptionError (exceptions.Exception):
1495 def __init__(self, args):
1498 def get_option(options, tag):
1499 """Look for tag in options hash and return the value if set. If not
1500 set, then if return default it is set, otherwise exception."""
1501 if options.__getattr__(tag) != None:
1502 return options.__getattr__(tag)
1504 raise OptionError("--add %s requires --%s <value>" % (options.add, tag))
1506 def get_option_int(options, tag):
1507 """Return an integer option. Raise exception if the value is not an int"""
1508 val = get_option(options, tag)
1512 raise OptionError("--%s <num> (value must be integer)" % (tag))
1515 # simple class for profiling
1522 self._start = time.time()
1523 def stop(self, msg=''):
1524 self._stop = time.time()
1528 return self._stop - self._start
1529 def display(self, msg):
1531 str = '%s: %g secs' % (msg, d)
1534 #################################################################
1535 # function cmdlinesplit used to split cmd line from batch file
1537 def cmdlinesplit(cmdline):
1539 double_quote = re.compile(r'"(([^"\\]|\\.)*)"')
1540 single_quote = re.compile(r"'(.*?)'")
1541 escaped = re.compile(r'\\(.)')
1542 esc_quote = re.compile(r'\\([\\"])')
1543 outside = re.compile(r"""([^\s\\'"]+)""") #" fucking emacs.
1547 while i < len(cmdline):
1550 match = double_quote.match(cmdline, i)
1552 print "Unmatched double quote:", cmdline
1555 if arg is None: arg = esc_quote.sub(r'\1', match.group(1))
1556 else: arg = arg + esc_quote.sub(r'\1', match.group(1))
1559 match = single_quote.match(cmdline, i)
1561 print "Unmatched single quote:", cmdline
1564 if arg is None: arg = match.group(1)
1565 else: arg = arg + match.group(1)
1568 match = escaped.match(cmdline, i)
1570 print "Unmatched backslash", cmdline
1573 if arg is None: arg = match.group(1)
1574 else: arg = arg + match.group(1)
1576 elif c in string.whitespace:
1578 arg_list.append(str(arg))
1580 while i < len(cmdline) and cmdline[i] in string.whitespace:
1583 match = outside.match(cmdline, i)
1586 if arg is None: arg = match.group()
1587 else: arg = arg + match.group()
1589 if arg != None: arg_list.append(str(arg))
1593 ############################################################
1597 def add(devtype, gen, lustre, options):
1598 if devtype == 'net':
1599 add_net(gen, lustre, options)
1600 elif devtype == 'mtpt':
1601 add_mtpt(gen, lustre, options)
1602 elif devtype == 'mds':
1603 add_mds(gen, lustre, options)
1604 elif devtype == 'ost':
1605 add_ost(gen, lustre, options)
1606 elif devtype == 'lov':
1607 add_lov(gen, lustre, options)
1608 elif devtype == 'route':
1609 add_route(gen, lustre, options)
1610 elif devtype == 'node':
1611 add_node(gen, lustre, options)
1612 elif devtype == 'echo_client':
1613 add_echo_client(gen, lustre, options)
1614 elif devtype == 'cobd':
1615 add_cobd(gen, lustre, options)
1616 elif devtype == 'cmobd':
1617 add_cmobd(gen, lustre, options)
1618 elif devtype == 'mgmt':
1619 add_mgmt(gen, lustre, options)
1620 elif devtype == 'lmv':
1621 add_lmv(gen, lustre, options)
1623 error("unknown device type:", devtype)
1625 def delete(devtype, gen, lustre, options):
1626 if devtype == 'ost':
1627 del_ost(gen, lustre, options)
1628 elif options.delete:
1629 error("delete not supported for device type:", devtype)
1630 elif options.deactivate:
1631 error("deactivate not supported for device type:", devtype)
1633 error("in delete(), but neither .delete nor .deactivate are set. Tell CFS.")
1635 def commit(gen, lustre):
1636 commit_version(gen, lustre)
1638 def do_command(gen, lustre, options, args):
1640 add(options.add, gen, lustre, options)
1641 elif options.delete:
1642 delete(options.delete, gen, lustre, options)
1643 elif options.deactivate:
1644 delete(options.deactivate, gen, lustre, options)
1645 elif options.commit:
1648 error("Missing command")
1651 cl = Lustre.Options("lmc", "", lmc_options)
1653 options, args = cl.parse(sys.argv[1:])
1654 except Lustre.OptionError, e:
1658 panic(string.join(sys.argv), "Unexpected extra arguments on command line: " + string.join(args))
1660 if options.reference:
1667 outFile = options.merge
1668 if os.access(outFile, os.R_OK):
1669 doc = xml.dom.minidom.parse(outFile)
1671 doc = new_lustre(xml.dom.minidom)
1673 doc = xml.dom.minidom.parse(options.input)
1675 doc = new_lustre(xml.dom.minidom)
1678 outFile = options.output
1680 lustre = doc.documentElement
1682 if lustre.tagName != "lustre":
1683 print "Existing config not valid."
1686 gen = GenConfig(doc)
1689 fp = open(options.batch)
1690 batchCommands = fp.readlines()
1692 for cmd in batchCommands:
1694 options, args = cl.parse(cmdlinesplit(cmd))
1695 if options.merge or options.input or options.output:
1696 print "The batchfile should not contain --merge, --input or --output."
1698 do_command(gen, lustre, options, args)
1699 except OptionError, e:
1701 except Lustre.OptionError, e:
1705 do_command(gen, lustre, options, args)
1706 except OptionError, e:
1707 panic(string.join(sys.argv),e)
1708 except Lustre.OptionError, e:
1714 printDoc(doc, open(outFile,"w"))
1716 if __name__ == "__main__":