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]
95 --backfstype ldiskfs|ext3|tmpfs
102 --mkfsoptions options
103 --mountfsoptions options
104 --root_squash uid:gid
105 --no_root_squash ptl_nid
108 --mds_deny_sec flavor[,flavor[...]]
109 --filesystem filesystem name
115 --aware one or few mds/lmv names separated by comma
129 --fstype ldiskfs|ext3
130 --backfstype ldiskfs|ext3|tmpfs
133 --osdtype obdecho|obdfilter
135 --mkfsoptions options
136 --mountfsoptions options
138 --ost_deny_sec flavor[,flavor[...]]
139 --filesystem filesystem name
149 --add mtpt - Mountpoint
154 --ost ost_name OR --lov lov_name
155 --clientoptions options
163 --gateway_cluster_id nid
164 --target_cluster_id nid
171 --add mgmt - Management/monitoring service
173 --mgmt mgmt_service_name
180 --master_obd obd_name
185 --master_obd obd_name
191 --commit - Close a configuration version, and start a new one
194 PARAM = Lustre.Options.PARAM
195 PARAMLIST = Lustre.Options.PARAMLIST
197 # lmc input/output options
198 ('reference', "Print short reference for commands."),
199 ('verbose,v', "Print system commands as they are run."),
200 ('merge,m', "Append to the specified config file.", PARAM),
201 ('output,o', "Write XML configuration into given output file. Overwrite existing content.", PARAM),
202 ('input,i', "", PARAM),
203 ('batch', "Used to execute lmc commands in batch mode.", PARAM),
207 ('delete', "", PARAM),
208 ('deactivate', "", PARAM),
209 ('commit', "Commit all config changes and start a new version"),
212 ('node', "Add a new node in the cluster configuration.", PARAM),
213 ('timeout', "Set timeout to initiate recovery.", PARAM),
214 ('upcall', "Set both lustre and portals upcall scripts.", PARAM),
215 ('lustre_upcall', "Set location of lustre upcall script.", PARAM),
216 ('portals_upcall', "Set location of portals upcall script.", PARAM),
217 ('ptldebug', "Set the portals debug level", PARAM),
218 ('subsystem', "Specify which Lustre subsystems have debug output recorded in the log", PARAM),
221 ('nettype', "Specify the network type. This can be tcp/elan/gm/openib/iib/vib/ra.", PARAM),
222 ('nid', "Give the network ID, e.g ElanID/IP Address as used by portals.", PARAM),
223 ('port', "Optional argument to specify the TCP port number.", PARAM, DEFAULT_PORT),
224 ('hostaddr', "Optional argument to specify the host address.", PARAMLIST),
225 ('cluster_id', "Specify the cluster ID", PARAM, "0"),
228 ('route', "Add a new route for the cluster.", PARAM),
229 ('router', "Optional flag to mark a node as router."),
230 ('gw', "Specify the nid of the gateway for a route.", PARAM),
231 ('gateway_cluster_id', "", PARAM, "0"),
232 ('target_cluster_id', "", PARAM, "0"),
233 ('lo', "For a range route, this is the low value nid.", PARAM),
234 ('hi', "For a range route, this is a hi value nid.", PARAM,""),
236 # servers: mds and ost
237 ('mds', "Specify MDS name.", PARAM,""),
238 ('ost', "Specify the OST name.", PARAM,""),
239 ('osdtype', "This could obdfilter or obdecho.", PARAM, "obdfilter"),
240 ('failover', "Enable failover support on OSTs or MDS?"),
241 ('group', "", PARAM),
242 ('dev', "Path of the device on local system.", PARAM,""),
243 ('backdev', "Path of the device for backing storage on local system.", PARAM,""),
244 ('size', "Specify the size of the device if needed.", PARAM,"0"),
245 ('journal_size', "Specify new journal size for underlying file system.", PARAM,"0"),
246 ('inode_size', "Specify new inode size for underlying file system.", PARAM,"0"),
247 ('fstype', "Optional argument to specify the filesystem type.", PARAM, "ext3"),
248 ('backfstype', "Optional argument to specify the backing filesystem type.", PARAM, "ext3"),
249 ('mkfsoptions', "Optional argument to mkfs.", PARAM, ""),
250 ('mountfsoptions', "Optional argument to mount fs.", PARAM, ""),
251 ('ostuuid', "Optional argument to specify OST UUID", PARAM,""),
252 ('mdsuuid', "Optional argument to specify MDS UUID", PARAM,""),
253 ('root_squash', "MDS squash root to appointed uid.", PARAM, ""),
254 ('no_root_squash', "Don't squash root for appointed nid.", PARAM, ""),
255 ('nspath', "Local mount point of server namespace.", PARAM,""),
256 ('mds_mds_sec', "Specify the secure flavor for connection from this mds to other mds.", PARAM, ""),
257 ('mds_oss_sec', "Specify the secure flavor for connection from this mds to ost.", PARAM, ""),
258 ('mds_deny_sec', "Specify the secure flavor which is denied from remote to this mds.", PARAM, ""),
259 ('ost_deny_sec', "Specify the secure flavor which is denied from remote to this ost.", PARAM, ""),
260 ('filesystem', "Specify the filesystem name device belong to.", PARAM, ""),
262 ('migrate', "used for offline migrate of an ost in conjunctio with add/delete"),
264 # clients: mountpoint and echo
265 ('echo_client', "", PARAM),
266 ('path', "Specify the mountpoint for Lustre.", PARAM),
267 ('filesystem', "Lustre filesystem name", PARAM,""),
268 ('clientoptions', "Specify the options for Lustre, such as async.", PARAM, ""),
269 ('mds_sec', "Specify the secure flavor for connection from this client to mds.", PARAM, ""),
270 ('oss_sec', "Specify the secure flavor for connection from this client to ost.", PARAM, ""),
273 ('lov', "Specify LOV name.", PARAM,""),
274 ('mds/lmv', "Specify MDS/LMV name using this LOV.", PARAM,""),
275 ('aware', "Specify MDS/LMV aware of this LOV.", PARAM,""),
276 ('index', "Specify index for OBD in LOV target table.", PARAM),
277 ('stripe_sz', "Specify the stripe size in bytes.", PARAM),
278 ('stripe_cnt', "Specify the number of OSTs each file should be striped on.", PARAM, 0),
279 ('stripe_pattern', "Specify the stripe pattern. RAID 0 is the only one currently supported.", PARAM, 0),
282 ('master_obd', "Specify the real device for the cache obd system.", PARAM),
283 ('cache_obd', "Specify the cache device for the cache obd system.", PARAM),
284 ('cobd', "Specify COBD name", PARAM),
287 ('master_obd', "Specify the master device for the cmobd system.", PARAM),
288 ('cache_obd', "Specify the cache device for the cmobd obd system.", PARAM),
289 ('cmobd', "Specify COBD name", PARAM),
291 ('mgmt', "Specify management/monitoring service name.", PARAM, ""),
294 ('lmv', "Specify LMV name.", PARAM,""),
297 ('gks', "Specify gks name.", PARAM,""),
302 msg = string.join(map(str,args))
303 raise OptionError("Error: " + msg)
312 msg = string.join(map(str,args))
313 print "Warning: ", msg
316 # manage names and uuids
317 # need to initialize this by walking tree to ensure
318 # no duplicate names or uuids are created.
319 # this are just place holders for now.
320 # consider changing this to be like OBD-dev-host
324 while names.has_key(ret):
325 ret = "%s_%d" % (base, ctr)
332 ret = "%s_UUID" % (name)
333 if len(ret) > UUID_MAX_LENGTH:
334 ret = ret[-UUID_MAX_LENGTH:]
335 while uuids.has_key(ret):
336 ret = "%s_UUID_%d" % (name, ctr)
338 if len(ret) > UUID_MAX_LENGTH:
339 ret = ret[-UUID_MAX_LENGTH:]
345 ldlm_uuid = 'ldlm_UUID'
348 """Create a new empty lustre document"""
349 # adding ldlm here is a bit of a hack, but one is enough.
350 str = """<lustre version="%s">
351 <ldlm name="%s" uuid="%s"/>
352 </lustre>""" % (Lustre.CONFIG_VERSION, ldlm_name, ldlm_uuid)
353 return dom.parseString(str)
359 """initialize auto-name generation tables"""
361 # get all elements that contain a name attribute
362 for n in doc.childNodes:
363 if n.nodeType == n.ELEMENT_NODE:
365 names[getName(n)] = 1
366 uuids[getUUID(n)] = 1
369 def get_format_flag(options):
374 ############################################################
375 # Build config objects using DOM
380 def __init__(self, doc):
383 def ref(self, type, uuid):
384 """ generate <[type]_ref uuidref="[uuid]"/> """
385 tag = "%s_ref" % (type)
386 ref = self.doc.createElement(tag)
387 ref.setAttribute("uuidref", uuid)
390 def dev(self, devname):
391 """ generate <dev devpath="[devname]"/> """
392 tgt = self.doc.createElement('dev')
393 tgt.setAttribute("dev", devname)
396 def newService(self, tag, name, uuid):
397 """ create a new service elmement, which requires name and uuid attributes """
398 new = self.doc.createElement(tag)
399 new.setAttribute("uuid", uuid);
400 new.setAttribute("name", name);
403 def addText(self, node, str):
404 txt = self.doc.createTextNode(str)
405 node.appendChild(txt)
407 def addElement(self, node, tag, str=None):
408 """ create a new element and add it as a child to node. If str is passed,
409 a text node is created for the new element"""
410 new = self.doc.createElement(tag)
412 self.addText(new, str)
413 node.appendChild(new)
416 def network(self, name, uuid, nid, cluster_id, net, hostaddr="",
418 """create <network> node"""
419 network = self.newService("network", name, uuid)
420 network.setAttribute("nettype", net);
421 self.addElement(network, "nid", nid)
422 self.addElement(network, "clusterid", cluster_id)
423 for host in hostaddr:
424 self.addElement(network, "hostaddr", host)
426 self.addElement(network, "port", "%d" %(port))
430 def routetbl(self, name, uuid):
431 """create <routetbl> node"""
432 rtbl = self.newService("routetbl", name, uuid)
435 def route(self, gw_net_type, gw, gw_cluster_id, tgt_cluster_id, lo, hi):
436 """ create one entry for the route table """
437 ref = self.doc.createElement('route')
438 ref.setAttribute("type", gw_net_type)
439 ref.setAttribute("gw", gw)
440 ref.setAttribute("gwclusterid", gw_cluster_id)
441 ref.setAttribute("tgtclusterid", tgt_cluster_id)
442 ref.setAttribute("lo", lo)
444 ref.setAttribute("hi", hi)
447 def profile(self, name, uuid):
448 """ create a host """
449 profile = self.newService("profile", name, uuid)
452 def node(self, name, uuid, prof_uuid):
453 """ create a host """
454 node = self.newService("node", name, uuid)
455 node.appendChild(self.ref("profile", prof_uuid))
458 def ldlm(self, name, uuid):
459 """ create a ldlm """
460 ldlm = self.newService("ldlm", name, uuid)
463 def osd(self, name, uuid, fstype, osdtype, devname, format, ost_uuid,
464 node_uuid, dev_size=0, journal_size=0, inode_size=0, nspath="",
465 mkfsoptions="", mountfsoptions="", backfstype="", backdevname="",
466 deny_sec="", fs_uuid=""):
467 osd = self.newService("osd", name, uuid)
468 osd.setAttribute('osdtype', osdtype)
469 osd.appendChild(self.ref("target", ost_uuid))
470 osd.appendChild(self.ref("node", node_uuid))
473 osd.appendChild(self.dev(devname))
475 self.addElement(osd, "fstype", fstype)
477 self.addElement(osd, "backfstype", backfstype)
479 self.addElement(osd, "backdevpath", backdevname)
481 dev = self.addElement(osd, "devpath", devname)
482 self.addElement(osd, "autoformat", format)
484 self.addElement(osd, "devsize", "%s" % (dev_size))
486 self.addElement(osd, "journalsize", "%s" % (journal_size))
488 self.addElement(osd, "inodesize", "%s" % (inode_size))
490 self.addElement(osd, "mkfsoptions", mkfsoptions)
492 self.addElement(osd, "mountfsoptions", mountfsoptions)
494 self.addElement(osd, "deny_sec", deny_sec)
496 osd.appendChild(self.ref("filesystem", fs_uuid))
498 self.addElement(osd, "nspath", nspath)
501 def cobd(self, name, uuid, master_uuid, cache_uuid):
502 cobd = self.newService("cobd", name, uuid)
503 cobd.appendChild(self.ref("masterobd",master_uuid))
504 cobd.appendChild(self.ref("cacheobd",cache_uuid))
507 def cmobd(self, name, uuid, master_uuid, cache_uuid):
508 cmobd = self.newService("cmobd", name, uuid)
509 cmobd.appendChild(self.ref("masterobd",master_uuid))
510 cmobd.appendChild(self.ref("cacheobd",cache_uuid))
513 def ost(self, name, uuid, osd_uuid, group=""):
514 ost = self.newService("ost", name, uuid)
515 ost.appendChild(self.ref("active", osd_uuid))
517 self.addElement(ost, "group", group)
520 def oss(self, name, uuid):
521 oss = self.newService("oss", name, uuid)
524 def lov(self, name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern):
525 lov = self.newService("lov", name, uuid)
526 lov.appendChild(self.ref("mds", mds_uuid))
527 lov.setAttribute("stripesize", str(stripe_sz))
528 lov.setAttribute("stripecount", str(stripe_cnt))
529 lov.setAttribute("stripepattern", str(pattern))
532 def lov_tgt(self, obd_uuid, lov_uuid, index, generation):
533 tgt = self.doc.createElement('lov_tgt')
534 tgt.setAttribute("uuidref", obd_uuid)
535 tgt.setAttribute("lov_uuid", lov_uuid)
536 tgt.setAttribute("index", index)
537 tgt.setAttribute("generation", generation)
538 tgt.setAttribute("active", '1')
541 def lovconfig(self, name, uuid, lov_uuid):
542 lovconfig = self.newService("lovconfig", name, uuid)
543 lovconfig.appendChild(self.ref("lov", lov_uuid))
546 def lmv_tgt(self, mdt_uuid):
547 tgt = self.doc.createElement('lmv_tgt')
548 tgt.setAttribute("uuidref", mdt_uuid)
551 def lmv(self, name, uuid):
552 lmv = self.newService("lmv", name, uuid)
555 def gks(self, name, uuid, gkd_uuid):
556 gks = self.newService("gks", name, uuid)
557 gks.appendChild(self.ref("active", gkd_uuid))
560 def gkd(self, name, uuid, node_uuid, gks_uuid):
561 gkd = self.newService("gkd", name, uuid)
562 gkd.appendChild(self.ref("node", node_uuid))
563 gkd.appendChild(self.ref("target", gks_uuid))
566 def mds(self, name, uuid, mdd_uuid, group="", lmv=""):
567 mds = self.newService("mds", name, uuid)
568 mds.appendChild(self.ref("active", mdd_uuid))
570 self.addElement(mds, "group", group)
573 def mdsdev(self, name, uuid, fstype, devname, format, node_uuid,
574 mds_uuid, dev_size=0, journal_size=0, inode_size=256,
575 nspath="", mkfsoptions="", mountfsoptions="", backfstype="",
576 backdevname="",lmv_uuid="", root_squash="", no_root_squash="",
577 mds_sec="", oss_sec="", deny_sec="", fs_uuid=""):
578 mdd = self.newService("mdsdev", name, uuid)
579 self.addElement(mdd, "fstype", fstype)
581 self.addElement(mdd, "backfstype", backfstype)
582 dev = self.addElement(mdd, "devpath", devname)
584 self.addElement(mdd, "backdevpath", backdevname)
585 self.addElement(mdd, "autoformat", format)
587 self.addElement(mdd, "devsize", "%s" % (dev_size))
589 self.addElement(mdd, "journalsize", "%s" % (journal_size))
591 self.addElement(mdd, "inodesize", "%s" % (inode_size))
593 self.addElement(mdd, "nspath", nspath)
595 self.addElement(mdd, "mkfsoptions", mkfsoptions)
597 self.addElement(mdd, "mountfsoptions", mountfsoptions)
599 self.addElement(mdd, "root_squash", root_squash)
601 self.addElement(mdd, "no_root_squash", no_root_squash)
603 self.addElement(mdd, "mds_sec", mds_sec)
605 self.addElement(mdd, "oss_sec", oss_sec)
607 self.addElement(mdd, "deny_sec", deny_sec)
609 mdd.appendChild(self.ref("filesystem", fs_uuid))
610 mdd.appendChild(self.ref("node", node_uuid))
611 mdd.appendChild(self.ref("target", mds_uuid))
613 dev = self.dev(devname)
618 mdd.appendChild(self.ref("lmv", lmv_uuid))
622 def mgmt(self, mgmt_name, mgmt_uuid, node_uuid):
623 mgmt = self.newService("mgmt", mgmt_name, mgmt_uuid)
624 mgmt.appendChild(self.ref("node", node_uuid))
625 # Placeholder until mgmt-service failover.
626 mgmt.appendChild(self.ref("active", mgmt_uuid))
629 def mountpoint(self, name, uuid, fs_uuid, path, clientoptions,
631 mtpt = self.newService("mountpoint", name, uuid)
632 mtpt.appendChild(self.ref("filesystem", fs_uuid))
633 self.addElement(mtpt, "path", path)
635 self.addElement(mtpt, "clientoptions", clientoptions)
637 self.addElement(mtpt, "mds_sec", mds_sec)
639 self.addElement(mtpt, "oss_sec", oss_sec)
642 def filesystem(self, name, uuid, mds_uuid, obd_uuid, mgmt_uuid, gks_uuid):
643 fs = self.newService("filesystem", name, uuid)
646 fs.appendChild(self.ref("mds", mds_uuid))
648 fs.appendChild(self.ref("obd", obd_uuid))
650 fs.appendChild(self.ref("gks", gks_uuid))
652 fs.appendChild(self.ref("mgmt", mgmt_uuid))
655 def echo_client(self, name, uuid, osc_uuid):
656 ec = self.newService("echoclient", name, uuid)
657 ec.appendChild(self.ref("obd", osc_uuid))
660 def update(self, version):
661 new = self.doc.createElement("update")
662 new.setAttribute("version", version)
666 new = self.doc.createElement("info")
669 def lmv_add(self, lmv, mdt):
670 new = self.doc.createElement("lmv_add")
671 new.setAttribute("lmv_uuidref", lmv)
672 new.setAttribute("mdt_uuidref", mdt)
675 def lov_add(self, lov, ost, index, gen):
676 new = self.doc.createElement("lov_add")
677 new.setAttribute("lov_uuidref", lov)
678 new.setAttribute("ost_uuidref", ost)
679 new.setAttribute("index", index)
680 new.setAttribute("generation", gen)
683 def lov_delete(self, lov, ost, index, gen, options):
685 new = self.doc.createElement("lov_delete")
687 new = self.doc.createElement("lov_deactivate")
688 new.setAttribute("lov_uuidref", lov)
689 new.setAttribute("ost_uuidref", ost)
690 new.setAttribute("index", index)
691 new.setAttribute("generation", gen)
694 ############################################################
695 # Utilities to query a DOM tree
696 # Using this functions we can treat use config information
697 # directly as a database.
699 return n.getAttribute('name')
702 return node.getAttribute('uuid')
704 def findLastUpdate(lustre):
707 for n in lustre.childNodes:
708 if n.nodeType == n.ELEMENT_NODE:
709 if n.nodeName != 'update':
711 tmp = int(n.getAttribute('version'))
713 error('malformed XML: update tag without a version attribute')
714 if tmp != version + 1:
715 error('malformed XML: expecting update record '+str(version + 1)+', found '+str(tmp)+'.')
720 def addUpdate(gen, lustre, node):
721 update = findLastUpdate(lustre)
724 update.appendChild(node)
726 def findByName(lustre, name, tag = ""):
727 for n in lustre.childNodes:
728 if n.nodeType == n.ELEMENT_NODE:
729 if tag and n.nodeName != tag:
731 if getName(n) == name:
734 n = findByName(n, name)
739 def lookup(node, uuid):
740 for n in node.childNodes:
741 if n.nodeType == n.ELEMENT_NODE:
742 if getUUID(n) == uuid:
750 def name2uuid(lustre, name, tag="", fatal=1):
751 ret = findByName(lustre, name, tag)
754 error('name2uuid:', '"'+name+'"', tag, 'element not found.')
759 def lookup_filesystem(lustre, fs_name):
760 for n in lustre.childNodes:
761 if n.nodeType == n.ELEMENT_NODE and n.nodeName == 'filesystem':
762 if getName(n) == fs_name:
766 # XXX: assumes only one network element per node. will fix this
767 # as soon as support for routers is added
768 def get_net_uuid(lustre, node_name):
769 """ get a network uuid for a node_name """
770 node = findByName(lustre, node_name, "node")
772 error ('get_net_uuid:', '"'+node_name+'"', "node element not found.")
773 net = node.getElementsByTagName('network')
775 return getUUID(net[0])
778 def lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options):
779 tgt.setAttribute('uuidref', osc_uuid)
780 gener = int(tgt.getAttribute('generation'))
781 if not options.migrate:
782 gener = str(int(gener) + 1)
783 tgt.setAttribute('generation', str(gener))
784 tgt.setAttribute('active', '1')
785 lov_index = int(tgt.getAttribute('index'))
786 add_rec = gen.lov_add(getUUID(lov), osc_uuid, str(lov_index), str(gener))
787 addUpdate(gen, lustre, add_rec)
790 def lov_add_osc(gen, lustre, lov, osc_uuid, options):
791 lov_name = getName(lov)
792 lov_uuid = getUUID(lov)
794 lov_index = get_option_int(options, 'index')
795 for tgt in lov.getElementsByTagName('lov_tgt'):
796 if str(lov_index) == tgt.getAttribute('index'):
797 uuidref = tgt.getAttribute('uuidref')
799 raise OptionError("%s --index %d is still in use: %s" %
800 (lov_name, lov_index, uuidref))
801 lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
805 for tgt in lov.getElementsByTagName('lov_tgt'):
806 uuidref = tgt.getAttribute('uuidref')
807 tmp = int(tgt.getAttribute('index'))
808 own_lov_uuid = tgt.getAttribute('lov_uuid')
809 if lov_uuid != own_lov_uuid:
812 lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
814 lov_index = lov_index + 1
816 lov.appendChild(gen.lov_tgt(osc_uuid, lov_uuid, str(lov_index), '1'))
817 addrec = gen.lov_add(lov_uuid, osc_uuid, str(lov_index), '1')
818 addUpdate(gen, lustre, addrec)
820 def lov_del_osc(gen, lustre, lov, osc_uuid, options):
821 lov_name = getName(lov)
823 lov_index = get_option_int(options, 'index')
824 for tgt in lov.getElementsByTagName('lov_tgt'):
825 index = tgt.getAttribute('index')
826 if index == lov_index:
827 uuidref = tgt.getAttribute('uuidref')
828 if uuidref != osc_uuid:
829 raise OptionError("%s --index %d contains %s, not %s" %
830 (lov_name, lov_index, osc_uuid, uuidref))
832 tgt.setAttribute('uuidref', '')
834 gener = tgt.getAttribute('generation')
835 if not options.migrate:
836 # bump the generation just in case...
837 gener = str(int(gener) + 1)
839 tgt.setAttribute('active', '0')
840 tgt.setAttribute('generation', gener)
842 raise OptionError("%s --index %d not in use by %s." %
843 (lov_name, lov_index, osc_uuid))
845 for tgt in lov.getElementsByTagName('lov_tgt'):
846 uuidref = tgt.getAttribute('uuidref')
847 if uuidref == osc_uuid:
848 index = tgt.getAttribute('index')
849 gener = tgt.getAttribute('generation')
850 delete_rec = gen.lov_delete(getUUID(lov), osc_uuid, index, gener,
852 addUpdate(gen, lustre, delete_rec)
855 tgt.setAttribute('uuidref', '')
856 if not options.migrate:
857 gener = str(int(gener) + 1)
858 tgt.setAttribute('active', '0')
859 tgt.setAttribute('generation', gener)
861 def lmv_add_mdc(gen, lustre, lmv, mdc_uuid):
862 lmv.appendChild(gen.lmv_tgt(mdc_uuid))
863 addrec = gen.lmv_add(getUUID(lmv), mdc_uuid)
864 addUpdate(gen, lustre, addrec)
866 def ref_exists(profile, uuid):
867 elist = profile.childNodes
869 if e.nodeType == e.ELEMENT_NODE:
870 ref = e.getAttribute('uuidref')
875 # ensure that uuid is not already in the profile
876 # return true if uuid is added
877 def node_add_profile(gen, node, ref, uuid):
878 refname = "%s_ref" % "profile"
879 ret = node.getElementsByTagName(refname)
881 error('node has no profile ref:', node)
882 prof_uuid = ret[0].getAttribute('uuidref')
883 profile = lookup(node.parentNode, prof_uuid)
885 error("no profile found:", prof_uuid)
886 if ref_exists(profile, uuid):
888 profile.appendChild(gen.ref(ref, uuid))
891 def get_attr(dom_node, attr, default=""):
892 v = dom_node.getAttribute(attr)
897 ############################################################
900 def set_node_options(gen, node, options):
902 node.setAttribute('router', '1')
904 gen.addElement(node, "timeout", get_option(options, 'timeout'))
906 default_upcall = get_option(options, 'upcall')
909 if default_upcall or options.lustre_upcall:
910 if options.lustre_upcall:
911 gen.addElement(node, 'lustreUpcall', options.lustre_upcall)
913 gen.addElement(node, 'lustreUpcall', default_upcall)
914 if default_upcall or options.portals_upcall:
915 if options.portals_upcall:
916 gen.addElement(node, 'portalsUpcall', options.portals_upcall)
918 gen.addElement(node, 'portalsUpcall', default_upcall)
920 gen.addElement(node, "ptldebug", get_option(options, 'ptldebug'))
921 if options.subsystem:
922 gen.addElement(node, "subsystem", get_option(options, 'subsystem'))
925 def do_add_node(gen, lustre, options, node_name):
926 uuid = new_uuid(node_name)
927 prof_name = new_name("PROFILE_" + node_name)
928 prof_uuid = new_uuid(prof_name)
929 profile = gen.profile(prof_name, prof_uuid)
930 node = gen.node(node_name, uuid, prof_uuid)
931 lustre.appendChild(node)
932 lustre.appendChild(profile)
934 node_add_profile(gen, node, 'ldlm', ldlm_uuid)
935 set_node_options(gen, node, options)
939 def add_node(gen, lustre, options):
940 """ create a node with a network config """
942 node_name = get_option(options, 'node')
943 ret = findByName(lustre, node_name, "node")
945 print "Node:", node_name, "exists."
947 do_add_node(gen, lustre, options, node_name)
950 def add_net(gen, lustre, options):
951 """ create a node with a network config """
953 node_name = get_option(options, 'node')
954 nid = get_option(options, 'nid')
955 cluster_id = get_option(options, 'cluster_id')
956 hostaddr = get_option(options, 'hostaddr')
957 net_type = get_option(options, 'nettype')
959 if net_type in ('tcp','openib','ra'):
960 port = get_option_int(options, 'port')
961 elif net_type in ('elan', 'gm', 'iib', 'vib', 'lo', 'cray_kern_nal'):
964 print "Unknown net_type: ", net_type
967 ret = findByName(lustre, node_name, "node")
969 node = do_add_node(gen, lustre, options, node_name)
972 set_node_options(gen, node, options)
974 net_name = new_name('NET_'+ node_name +'_'+ net_type)
975 net_uuid = new_uuid(net_name)
976 node.appendChild(gen.network(net_name, net_uuid, nid, cluster_id, net_type,
978 node_add_profile(gen, node, "network", net_uuid)
981 def add_route(gen, lustre, options):
982 """ create a node with a network config """
984 node_name = get_option(options, 'node')
985 gw_net_type = get_option(options, 'nettype')
986 gw = get_option(options, 'gw')
987 gw_cluster_id = get_option(options, 'gateway_cluster_id')
988 tgt_cluster_id = get_option(options, 'target_cluster_id')
989 lo = get_option(options, 'lo')
990 hi = get_option(options, 'hi')
994 node = findByName(lustre, node_name, "node")
996 error (node_name, " not found.")
998 rlist = node.getElementsByTagName('routetbl')
1002 rtbl_name = new_name("RTBL_" + node_name)
1003 rtbl_uuid = new_uuid(rtbl_name)
1004 rtbl = gen.routetbl(rtbl_name, rtbl_uuid)
1005 node.appendChild(rtbl)
1006 node_add_profile(gen, node, "routetbl", rtbl_uuid)
1007 rtbl.appendChild(gen.route(gw_net_type, gw, gw_cluster_id, tgt_cluster_id,
1010 def add_gks(gen, lustre, options):
1011 """ create a gks """
1012 node_name = get_option(options, 'node')
1013 gks_name = get_option(options, 'gks')
1015 gks_name = new_name('GKS_'+ node_name)
1017 gkd_name = new_name("GKD_" + gks_name + "_" + node_name)
1018 gkd_uuid = new_uuid(gkd_name)
1020 gks_uuid = name2uuid(lustre, gks_name, 'gks', fatal=0)
1023 gks_uuid = new_uuid(gks_name)
1024 gks = gen.gks(gks_name, gks_uuid, gkd_uuid)
1025 lustre.appendChild(gks)
1027 gks = lookup(lustre, gks_uuid)
1030 node_uuid = name2uuid(lustre, node_name, 'node')
1031 node = findByName(lustre, node_name, "node")
1032 node_add_profile(gen, node, "gkd", gkd_uuid)
1033 net_uuid = get_net_uuid(lustre, node_name)
1035 error("NODE: ", node_name, "not found")
1037 gkd = gen.gkd(gkd_name, gkd_uuid, node_uuid, gks_uuid)
1038 lustre.appendChild(gkd)
1041 def add_mds(gen, lustre, options):
1042 node_name = get_option(options, 'node')
1043 mds_name = get_option(options, 'mds')
1045 mds_name = new_name('MDS_'+ node_name)
1046 lmv_name = get_option(options, 'lmv')
1047 mdd_name = new_name("MDD_" + mds_name +"_" + node_name)
1048 mdd_uuid = new_uuid(mdd_name)
1050 mds_uuid = name2uuid(lustre, mds_name, 'mds', fatal=0)
1052 mds_uuid = get_option(options, 'mdsuuid')
1054 if lookup(lustre, mds_uuid):
1055 error("Duplicate MDS UUID:", mds_uuid)
1057 mds_uuid = new_uuid(mds_name)
1058 mds = gen.mds(mds_name, mds_uuid, mdd_uuid, options.group)
1059 lustre.appendChild(mds)
1061 mds = lookup(lustre, mds_uuid)
1065 lmv = findByName(lustre, lmv_name, "lmv")
1067 error('add_mds:', '"' + lmv_name + '"', "lmv element not found.")
1068 lmv_add_mdc(gen, lustre, lmv, mds_uuid)
1069 lmv_uuid = name2uuid(lustre, lmv_name, fatal=0)
1071 mds.appendChild(gen.ref("lmv", lmv_uuid))
1073 if options.failover:
1074 mds.setAttribute('failover', "1")
1076 devname = get_option(options, 'dev')
1077 backdevname = get_option(options, 'backdev')
1078 size = get_option(options, 'size')
1079 fstype = get_option(options, 'fstype')
1080 backfstype = get_option(options, 'backfstype')
1081 journal_size = get_option(options, 'journal_size')
1082 inode_size = get_option(options, 'inode_size')
1083 nspath = get_option(options, 'nspath')
1084 mkfsoptions = get_option(options, 'mkfsoptions')
1085 mountfsoptions = get_option(options, 'mountfsoptions')
1086 root_squash = get_option(options, 'root_squash')
1087 no_root_squash = get_option(options, 'no_root_squash')
1088 mds_sec = get_option(options, 'mds_mds_sec')
1089 oss_sec = get_option(options, 'mds_oss_sec')
1090 deny_sec = get_option(options, 'mds_deny_sec')
1091 fs_name = get_option(options, 'filesystem')
1093 node_uuid = name2uuid(lustre, node_name, 'node')
1095 node = findByName(lustre, node_name, "node")
1096 node_add_profile(gen, node, "mdsdev", mdd_uuid)
1097 net_uuid = get_net_uuid(lustre, node_name)
1099 error("NODE: ", node_name, "not found")
1102 fs_uuid = name2uuid(lustre, fs_name, 'filesystem', fatal=1)
1106 mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname,
1107 get_format_flag(options), node_uuid, mds_uuid,
1108 size, journal_size, inode_size, nspath, mkfsoptions,
1109 mountfsoptions, backfstype, backdevname,lmv_uuid,
1110 root_squash, no_root_squash, mds_sec, oss_sec, deny_sec,
1112 lustre.appendChild(mdd)
1114 def add_mgmt(gen, lustre, options):
1115 node_name = get_option(options, 'node')
1116 node_uuid = name2uuid(lustre, node_name, 'node')
1117 mgmt_name = get_option(options, 'mgmt')
1119 mgmt_name = new_name('MGMT_' + node_name)
1120 mgmt_uuid = name2uuid(lustre, mgmt_name, 'mgmt', fatal=0)
1122 mgmt_uuid = new_uuid(mgmt_name)
1123 mgmt = gen.mgmt(mgmt_name, mgmt_uuid, node_uuid)
1124 lustre.appendChild(mgmt)
1126 mgmt = lookup(lustre, mgmt_uuid)
1128 node = findByName(lustre, node_name, "node")
1129 node_add_profile(gen, node, 'mgmt', mgmt_uuid)
1131 def add_ost(gen, lustre, options):
1132 node_name = get_option(options, 'node')
1133 lovname = get_option(options, 'lov')
1134 osdtype = get_option(options, 'osdtype')
1136 node_uuid = name2uuid(lustre, node_name, 'node')
1138 if osdtype == 'obdecho':
1150 devname = get_option(options, 'dev') # can be unset for bluearcs
1151 backdevname = get_option(options, 'backdev')
1152 size = get_option(options, 'size')
1153 fstype = get_option(options, 'fstype')
1154 backfstype = get_option(options, 'backfstype')
1155 journal_size = get_option(options, 'journal_size')
1156 inode_size = get_option(options, 'inode_size')
1157 mkfsoptions = get_option(options, 'mkfsoptions')
1158 mountfsoptions = get_option(options, 'mountfsoptions')
1159 deny_sec = get_option(options, 'ost_deny_sec')
1161 fs_name = get_option(options, 'filesystem')
1162 nspath = get_option(options, 'nspath')
1164 ostname = get_option(options, 'ost')
1166 ostname = new_name('OST_'+ node_name)
1168 osdname = new_name("OSD_" + ostname + "_" + node_name)
1169 osd_uuid = new_uuid(osdname)
1171 ost_uuid = name2uuid(lustre, ostname, 'ost', fatal=0)
1173 ost_uuid = get_option(options, 'ostuuid')
1175 if lookup(lustre, ost_uuid):
1176 error("Duplicate OST UUID:", ost_uuid)
1178 ost_uuid = new_uuid(ostname)
1180 ost = gen.ost(ostname, ost_uuid, osd_uuid, options.group)
1181 lustre.appendChild(ost)
1183 ost = lookup(lustre, ost_uuid)
1186 lov = findByName(lustre, lovname, "lov")
1188 error('add_ost:', '"'+lovname+'"', "lov element not found.")
1189 lov_add_osc(gen, lustre, lov, ost_uuid, options)
1191 if options.failover:
1192 ost.setAttribute('failover', "1")
1195 fs_uuid = name2uuid(lustre, fs_name, 'filesystem', fatal=1)
1199 osd = gen.osd(osdname, osd_uuid, fstype, osdtype, devname,
1200 get_format_flag(options), ost_uuid, node_uuid, size,
1201 journal_size, inode_size, nspath, mkfsoptions,
1202 mountfsoptions, backfstype, backdevname, deny_sec,
1205 node = findByName(lustre, node_name, "node")
1206 node_add_profile(gen, node, 'osd', osd_uuid)
1207 lustre.appendChild(osd)
1209 def del_ost(gen, lustre, options):
1210 ostname = get_option(options, 'ost')
1212 raise OptionError("del_ost: --ost requires a <ost name>")
1213 ost = findByName(lustre, ostname, "ost")
1215 error('del_ost: ', 'Unable to find ', ostname)
1216 ost_uuid = name2uuid(lustre, ostname, fatal=0)
1218 error('del_ost: ', 'Unable to find uuid for ', ostname)
1219 lovname = get_option(options, 'lov')
1221 lov = findByName(lustre, lovname, "lov")
1223 error('del_ost:', '"'+lovname+'"', "lov element not found.")
1224 lov_del_osc(gen, lustre, lov, ost_uuid, options)
1225 # if the user specified a speficic LOV don't delete the OST itself
1228 # remove OSD references from all LOVs
1229 for lov in lustre.getElementsByTagName('lov'):
1230 lov_del_osc(gen, lustre, lov, ost_uuid, options)
1234 # move the OST description to the update record
1235 lustre.removeChild(ost)
1236 info.appendChild(ost)
1238 active_ref = ost.getElementsByTagName('active_ref')
1240 error('ost has no osd ref:', ostname)
1242 # move the OSD description to the update record
1243 osd_uuid = active_ref[0].getAttribute('uuidref')
1244 osd = lookup(lustre, osd_uuid)
1245 lustre.removeChild(osd)
1246 info.appendChild(osd)
1248 # make a copy of the OSS description in the update record
1249 # XXX - should check to make sure one doesn't already exist.
1250 node_ref = osd.getElementsByTagName('node_ref')
1252 error('osd has no node ref:', ostname)
1253 node_uuid = node_ref[0].getAttribute('uuidref')
1254 node = lookup(lustre, node_uuid)
1256 error('unable to locate node for node ref:', node_uuid)
1258 node_rec = node.cloneNode(1)
1259 info.appendChild(node_rec)
1261 prof_ref = node.getElementsByTagName('profile_ref')
1263 error('node has no profile ref:', node)
1264 profile_uuid = prof_ref[0].getAttribute('uuidref')
1266 # make a copy of the OSS's profile in the update record
1267 # XXX - should check to make sure one doesn't already exist.
1268 profile = lookup(lustre, profile_uuid)
1269 profile_rec = profile.cloneNode(1)
1270 info.appendChild(profile_rec)
1272 # delete all references to this OSD in the OSS's current profile
1273 for osd_ref in profile.getElementsByTagName('osd_ref'):
1274 if osd_uuid == osd_ref.getAttribute('uuidref'):
1275 profile.removeChild(osd_ref)
1277 # XXX - We should cleanup the node and profile elements if they
1278 # no longer serve a purpose.
1279 addUpdate(gen, lustre, info)
1281 def add_cmobd(gen, lustre, options):
1282 node_name = get_option(options, 'node')
1283 name = get_option(options, 'cmobd')
1284 uuid = new_uuid(name)
1286 master_name = get_option(options, 'master_obd')
1287 cache_name = get_option(options, 'cache_obd')
1289 master_uuid = name2uuid(lustre, master_name, tag='lov', fatal=0)
1290 cache_uuid = name2uuid(lustre, cache_name, tag='lov', fatal=0)
1292 if not master_uuid or not cache_uuid:
1294 master_uuid = name2uuid(lustre, master_name, tag='ost', fatal=0)
1296 cache_uuid = name2uuid(lustre, cache_name, tag='ost', fatal=0)
1298 if not master_uuid or not cache_uuid:
1300 master_uuid = name2uuid(lustre, master_name, tag='lmv', fatal=0)
1302 cache_uuid = name2uuid(lustre, cache_name, tag='lmv', fatal=0)
1304 if not master_uuid or not cache_uuid:
1306 master_uuid = name2uuid(lustre, master_name, tag='mds', fatal=0)
1308 cache_uuid = name2uuid(lustre, cache_name, tag='mds', fatal=0)
1311 error("cannot find master_uuid by name '" + master_name + "'")
1313 error("cannot find cache_uuid by name '" + cache_name + "'")
1315 node = findByName(lustre, node_name, "node")
1316 node_add_profile(gen, node, "cmobd", uuid)
1318 master_node = lookup(lustre, master_uuid)
1319 cache_node = lookup(lustre, cache_uuid)
1321 error("cannot find master node by its uuid " + master_uuid);
1323 error("cannot find cache node by its uuid " + cache_uuid);
1325 active = master_node.getElementsByTagName('active_ref')
1327 active_uuid = active[0].getAttribute('uuidref')
1328 active_node = lookup(lustre, active_uuid)
1329 if not active_node.getElementsByTagName('obdtype'):
1330 gen.addElement(active_node, 'obdtype', 'master')
1332 active = cache_node.getElementsByTagName('active_ref')
1334 active_uuid = active[0].getAttribute('uuidref')
1335 active_node = lookup(lustre, active_uuid)
1336 if not active_node.getElementsByTagName('obdtype'):
1337 gen.addElement(active_node, 'obdtype', 'cache')
1339 cmobd = gen.cmobd(name, uuid, master_uuid, cache_uuid)
1340 lustre.appendChild(cmobd)
1342 def add_cobd(gen, lustre, options):
1343 node_name = get_option(options, 'node')
1344 name = get_option(options, 'cobd')
1345 uuid = new_uuid(name)
1347 master_name = get_option(options, 'master_obd')
1348 cache_name = get_option(options, 'cache_obd')
1351 master_uuid = name2uuid(lustre, master_name, tag='lov', fatal=0)
1353 master_uuid = name2uuid(lustre, master_name, tag='ost', fatal=0)
1356 node = lookup(lustre, master_uuid)
1357 rets = node.getElementsByTagName('lov_tgt')
1359 ost_uuid = ret.getAttribute('uuidref')
1360 ost_node = lookup(lustre, ost_uuid)
1361 active = ost_node.getElementsByTagName('active_ref')
1363 osd_uuid = active[0].getAttribute('uuidref')
1364 osd_node = lookup(lustre, osd_uuid)
1365 if not osd_node.getElementsByTagName('obdtype'):
1366 gen.addElement(osd_node, 'obdtype', 'master')
1369 cache_uuid = name2uuid(lustre, cache_name, tag='lov', fatal=0)
1371 cache_uuid = name2uuid(lustre, cache_name, tag='ost', fatal=0)
1374 node = lookup(lustre, cache_uuid)
1375 rets = node.getElementsByTagName('lov_tgt')
1377 ost_uuid = ret.getAttribute('uuidref')
1378 ost_node = lookup(lustre, ost_uuid)
1379 active = ost_node.getElementsByTagName('active_ref')
1381 osd_uuid = active[0].getAttribute('uuidref')
1382 osd_node = lookup(lustre, osd_uuid)
1383 if not osd_node.getElementsByTagName('obdtype'):
1384 gen.addElement(osd_node, 'obdtype', 'cache')
1386 if not master_uuid or not cache_uuid:
1387 master_uuid = name2uuid(lustre, master_name, tag='lmv', fatal=0)
1389 master_uuid = name2uuid(lustre, master_name, tag='mds', fatal=0)
1392 mds_node = lookup(lustre, master_uuid)
1393 ret = mds_node.getElementsByTagName('active_ref')
1395 mdsdev_uuid = ret[0].getAttribute('uuidref')
1396 mdsdev_node = lookup(lustre, mdsdev_uuid)
1397 if not mdsdev_node.getElementsByTagName('obdtype'):
1398 gen.addElement(mdsdev_node, 'obdtype', 'master')
1400 cache_uuid = name2uuid(lustre, cache_name, tag='lmv', fatal=0)
1402 cache_uuid = name2uuid(lustre, cache_name, tag='mds', fatal=0)
1405 mds_node = lookup(lustre, cache_uuid)
1406 ret = mds_node.getElementsByTagName('active_ref')
1408 mdsdev_uuid = ret[0].getAttribute('uuidref')
1409 mdsdev_node = lookup(lustre, mdsdev_uuid)
1410 if not mdsdev_node.getElementsByTagName('obdtype'):
1411 gen.addElement(mdsdev_node, 'obdtype', 'cache')
1413 if not master_uuid or not cache_uuid:
1414 panic("add_cobd", "cannot find master or cache by names '" +
1415 master_name + "' and '" + cache_name + "'")
1417 node = findByName(lustre, node_name, "node")
1418 cobd = gen.cobd(name, uuid, master_uuid, cache_uuid)
1419 lustre.appendChild(cobd)
1421 def add_echo_client(gen, lustre, options):
1422 """ add an echo client to the profile for this node. """
1423 node_name = get_option(options, 'node')
1424 lov_name = get_option(options, 'ost')
1426 node = findByName(lustre, node_name, 'node')
1428 echoname = new_name('ECHO_'+ node_name)
1429 echo_uuid = new_uuid(echoname)
1430 node_add_profile(gen, node, 'echoclient', echo_uuid)
1432 lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
1434 lov_uuid = name2uuid(lustre, lov_name, tag='ost', fatal=1)
1436 echo = gen.echo_client(echoname, echo_uuid, lov_uuid)
1437 lustre.appendChild(echo)
1439 def add_lov(gen, lustre, options):
1440 """ create a lov """
1442 lov_orig = get_option(options, 'lov')
1443 name = new_name(lov_orig)
1444 if name != lov_orig:
1445 warning("name:", lov_orig, "already used. using:", name)
1447 lmv_name = get_option(options, 'lmv')
1448 mds_name = get_option(options, 'mds')
1449 aware = get_option(options, 'aware')
1451 if not mds_name and not lmv_name:
1452 error("LOV: either MDS or LMV must be specified.");
1453 if mds_name and lmv_name:
1454 error("LOV: either MDS or LMV must be specified.");
1456 stripe_sz = get_option_int(options, 'stripe_sz')
1457 stripe_cnt = get_option_int(options, 'stripe_cnt')
1458 pattern = get_option_int(options, 'stripe_pattern')
1459 uuid = new_uuid(name)
1461 ret = findByName(lustre, name, "lov")
1463 error("LOV: ", name, " already exists.")
1466 mds_uuid = name2uuid(lustre, lmv_name, 'lmv')
1468 mds_uuid = name2uuid(lustre, mds_name, 'mds')
1470 lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
1471 lustre.appendChild(lov)
1473 # add an lovconfig entry to the active mdsdev profile
1474 lovconfig_name = new_name('LVCFG_' + name)
1475 lovconfig_uuid = new_uuid(lovconfig_name)
1478 md_tgt = findByName(lustre, mds_name, "mds")
1480 error("can't find MDS '" + mds_name + "'")
1482 md_tgt = findByName(lustre, lmv_name, "lmv")
1484 error("can't find LMV '" + lmv_name + "'")
1486 md_tgt.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1487 md_tgt.appendChild(gen.ref("client", uuid))
1489 # adding lovconfig and client to aware MD targets
1491 md_names = string.split(aware, ',');
1492 for md_name in md_names:
1494 md_tgt = findByName(lustre, md_name, "mds")
1496 md_tgt = findByName(lustre, md_name, "lmv")
1499 error("can't find '" + mds_name + "'")
1501 md_tgt.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1502 md_tgt.appendChild(gen.ref("client", uuid))
1504 lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
1505 lustre.appendChild(lovconfig)
1507 def add_default_lov(gen, lustre, mds_name, lov_name):
1508 """ create a default lov """
1510 stripe_sz = DEFAULT_STRIPE_SZ
1511 stripe_cnt = DEFAULT_STRIPE_CNT
1512 pattern = DEFAULT_STRIPE_PATTERN
1513 uuid = new_uuid(lov_name)
1515 ret = findByName(lustre, lov_name, "lov")
1517 error("LOV: ", lov_name, " already exists.")
1519 mds_uuid = name2uuid(lustre, mds_name, 'mds')
1520 lov = gen.lov(lov_name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
1521 lustre.appendChild(lov)
1523 # add an lovconfig entry to the active mdsdev profile
1524 lovconfig_name = new_name('LVCFG_' + lov_name)
1525 lovconfig_uuid = new_uuid(lovconfig_name)
1526 mds = findByName(lustre, mds_name)
1527 mds.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1528 lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
1529 lustre.appendChild(lovconfig)
1531 def add_lmv(gen, lustre, options):
1532 """ create a lmv """
1534 lmv_orig = get_option(options, 'lmv')
1535 name = new_name(lmv_orig)
1536 if name != lmv_orig:
1537 warning("name:", lmv_orig, "already used. using:", name)
1539 uuid = new_uuid(name)
1540 ret = findByName(lustre, name, "lmv")
1542 error("LMV: ", name, " already exists.")
1544 lmv = gen.lmv(name, uuid)
1545 lustre.appendChild(lmv)
1547 def new_filesystem(gen, lustre, fs_name, mds_uuid, obd_uuid,
1548 mgmt_uuid, gks_uuid):
1549 fs_uuid = new_uuid(fs_name)
1550 fs = gen.filesystem(fs_name, fs_uuid, mds_uuid, obd_uuid,
1551 mgmt_uuid, gks_uuid)
1552 lustre.appendChild(fs)
1555 def get_fs_uuid(gen, lustre, fs_name, mds_name, obd_name,
1556 mgmt_name, gks_name):
1557 mds_uuid = name2uuid(lustre, mds_name, tag='mds', fatal=0)
1559 mds_uuid = name2uuid(lustre, mds_name, tag='lmv', fatal=0)
1561 mds_uuid = name2uuid(lustre, mds_name, tag='cobd', fatal=0)
1563 error("mds '" + mds_name + "' is not found")
1565 obd_uuid = name2uuid(lustre, obd_name, tag='ost', fatal=0)
1567 obd_uuid = name2uuid(lustre, obd_name, tag='lov', fatal=0)
1569 obd_uuid = name2uuid(lustre, obd_name, tag='cobd', fatal=0)
1571 error("ost '" + obd_name + "' is not found")
1574 mgmt_uuid = name2uuid(lustre, mgmt_name, tag='mgmt', fatal=1)
1579 gks_uuid = name2uuid(lustre, gks_name, tag='gks', fatal=1)
1583 fs_uuid = lookup_filesystem(lustre, fs_name)
1585 fs = lookup(lustre, fs_uuid)
1586 if not ref_exists(fs, mds_uuid):
1587 fs.appendChild(gen.ref("mds", mds_uuid))
1588 if not ref_exists(fs, obd_uuid):
1589 fs.appendChild(gen.ref("obd", obd_uuid))
1590 if gks_uuid and not ref_exists(fs, gks_uuid):
1591 fs.appendChild(gen.ref("gks", gks_uuid))
1593 fs_uuid = new_filesystem(gen, lustre, fs_name,
1595 mgmt_uuid, gks_uuid)
1598 def add_filesystem(gen, lustre, options):
1599 """ create filesytem """
1600 fs_orig = get_option(options, 'filesystem')
1601 name = new_name(fs_orig)
1603 warning("name:", fs_orig, "already used. using:", name)
1605 uuid = new_uuid(name)
1606 ret = findByName(lustre, name, "filesystem")
1608 error("FS: ", name, " already exists.")
1610 gks_name = get_option(options, 'gks')
1612 gks_uuid = name2uuid(lustre, gks_name, tag='gks', fatal=1)
1615 fs = gen.filesystem(name, uuid, "", "", "", gks_uuid)
1616 lustre.appendChild(fs)
1618 def add_mtpt(gen, lustre, options):
1619 """ create mtpt on a node """
1620 node_name = get_option(options, 'node')
1622 path = get_option(options, 'path')
1623 clientoptions = get_option(options, "clientoptions")
1624 mds_sec = get_option(options, "mds_sec")
1625 oss_sec = get_option(options, "oss_sec")
1626 fs_name = get_option(options, 'filesystem')
1628 lov_name = get_option(options, 'lov')
1629 ost_name = get_option(options, 'ost')
1630 mds_name = get_option(options, 'mds')
1631 gks_name = get_option(options, 'gks')
1633 mds_name = get_option(options, 'lmv')
1635 error("--add mtpt requires either --mds or --lmv.")
1638 error("--add mtpt requires --lov lov_name or --ost ost_name")
1640 warning("use default value for lov, due no --lov lov_name provided")
1641 lov_name = new_name("lov_default")
1642 add_default_lov(gen, lustre, mds_name, lov_name)
1643 ost_uuid = name2uuid(lustre, ost_name, 'ost', fatal=0)
1645 error('add_mtpt:', '"'+ost_name+'"', "ost element not found.")
1646 lov = findByName(lustre, lov_name, "lov")
1647 lov_add_osc(gen, lustre, lov, ost_uuid, options)
1650 fs_name = new_name("FS_fsname")
1651 mgmt_name = get_option(options, 'mgmt')
1655 fs_uuid = get_fs_uuid(gen, lustre, fs_name,
1656 mds_name, lov_name, mgmt_name, gks_name)
1658 name = new_name('MNT_'+ node_name)
1660 ret = findByName(lustre, name, "mountpoint")
1662 # this can't happen, because new_name creates unique names
1663 error("MOUNTPOINT: ", name, " already exists.")
1665 uuid = new_uuid(name)
1666 mtpt = gen.mountpoint(name, uuid, fs_uuid, path,
1667 clientoptions, mds_sec, oss_sec)
1668 node = findByName(lustre, node_name, "node")
1670 error('node:', node_name, "not found.")
1671 node_add_profile(gen, node, "mountpoint", uuid)
1672 lustre.appendChild(mtpt)
1674 def commit_version(gen, lustre):
1675 update = findLastUpdate(lustre)
1677 version = int(update.getAttribute("version")) + 1
1681 new = gen.update(str(version))
1682 lustre.appendChild(new)
1685 ############################################################
1686 # Command line processing
1688 class OptionError (exceptions.Exception):
1689 def __init__(self, args):
1692 def get_option(options, tag):
1693 """Look for tag in options hash and return the value if set. If not
1694 set, then if return default it is set, otherwise exception."""
1695 if options.__getattr__(tag) != None:
1696 return options.__getattr__(tag)
1698 raise OptionError("--add %s requires --%s <value>" % (options.add, tag))
1700 def get_option_int(options, tag):
1701 """Return an integer option. Raise exception if the value is not an int"""
1702 val = get_option(options, tag)
1706 raise OptionError("--%s <num> (value must be integer)" % (tag))
1709 # simple class for profiling
1716 self._start = time.time()
1717 def stop(self, msg=''):
1718 self._stop = time.time()
1722 return self._stop - self._start
1723 def display(self, msg):
1725 str = '%s: %g secs' % (msg, d)
1728 #################################################################
1729 # function cmdlinesplit used to split cmd line from batch file
1731 def cmdlinesplit(cmdline):
1733 double_quote = re.compile(r'"(([^"\\]|\\.)*)"')
1734 single_quote = re.compile(r"'(.*?)'")
1735 escaped = re.compile(r'\\(.)')
1736 esc_quote = re.compile(r'\\([\\"])')
1737 outside = re.compile(r"""([^\s\\'"]+)""") #" fucking emacs.
1741 while i < len(cmdline):
1744 match = double_quote.match(cmdline, i)
1746 print "Unmatched double quote:", cmdline
1749 if arg is None: arg = esc_quote.sub(r'\1', match.group(1))
1750 else: arg = arg + esc_quote.sub(r'\1', match.group(1))
1753 match = single_quote.match(cmdline, i)
1755 print "Unmatched single quote:", cmdline
1758 if arg is None: arg = match.group(1)
1759 else: arg = arg + match.group(1)
1762 match = escaped.match(cmdline, i)
1764 print "Unmatched backslash", cmdline
1767 if arg is None: arg = match.group(1)
1768 else: arg = arg + match.group(1)
1770 elif c in string.whitespace:
1772 arg_list.append(str(arg))
1774 while i < len(cmdline) and cmdline[i] in string.whitespace:
1777 match = outside.match(cmdline, i)
1780 if arg is None: arg = match.group()
1781 else: arg = arg + match.group()
1783 if arg != None: arg_list.append(str(arg))
1787 ############################################################
1791 def add(devtype, gen, lustre, options):
1792 if devtype == 'net':
1793 add_net(gen, lustre, options)
1794 elif devtype == 'mtpt':
1795 add_mtpt(gen, lustre, options)
1796 elif devtype == 'mds':
1797 add_mds(gen, lustre, options)
1798 elif devtype == 'ost':
1799 add_ost(gen, lustre, options)
1800 elif devtype == 'lov':
1801 add_lov(gen, lustre, options)
1802 elif devtype == 'route':
1803 add_route(gen, lustre, options)
1804 elif devtype == 'node':
1805 add_node(gen, lustre, options)
1806 elif devtype == 'echo_client':
1807 add_echo_client(gen, lustre, options)
1808 elif devtype == 'cobd':
1809 add_cobd(gen, lustre, options)
1810 elif devtype == 'cmobd':
1811 add_cmobd(gen, lustre, options)
1812 elif devtype == 'mgmt':
1813 add_mgmt(gen, lustre, options)
1814 elif devtype == 'lmv':
1815 add_lmv(gen, lustre, options)
1816 elif devtype == 'filesystem':
1817 add_filesystem(gen, lustre, options)
1818 elif devtype == 'gks':
1819 add_gks(gen, lustre, options)
1821 error("unknown device type:", devtype)
1823 def delete(devtype, gen, lustre, options):
1824 if devtype == 'ost':
1825 del_ost(gen, lustre, options)
1826 elif options.delete:
1827 error("delete not supported for device type:", devtype)
1828 elif options.deactivate:
1829 error("deactivate not supported for device type:", devtype)
1831 error("in delete(), but neither .delete nor .deactivate are set. Tell CFS.")
1833 def commit(gen, lustre):
1834 commit_version(gen, lustre)
1836 def do_command(gen, lustre, options, args):
1838 add(options.add, gen, lustre, options)
1839 elif options.delete:
1840 delete(options.delete, gen, lustre, options)
1841 elif options.deactivate:
1842 delete(options.deactivate, gen, lustre, options)
1843 elif options.commit:
1846 error("Missing command")
1849 cl = Lustre.Options("lmc", "", lmc_options)
1851 options, args = cl.parse(sys.argv[1:])
1852 except Lustre.OptionError, e:
1856 panic(string.join(sys.argv), "Unexpected extra arguments on command line: " + string.join(args))
1858 if options.reference:
1865 outFile = options.merge
1866 if os.access(outFile, os.R_OK):
1867 doc = xml.dom.minidom.parse(outFile)
1869 doc = new_lustre(xml.dom.minidom)
1871 doc = xml.dom.minidom.parse(options.input)
1873 doc = new_lustre(xml.dom.minidom)
1876 outFile = options.output
1878 lustre = doc.documentElement
1880 if lustre.tagName != "lustre":
1881 print "Existing config not valid."
1884 gen = GenConfig(doc)
1887 fp = open(options.batch)
1888 batchCommands = fp.readlines()
1890 for cmd in batchCommands:
1892 options, args = cl.parse(cmdlinesplit(cmd))
1893 if options.merge or options.input or options.output:
1894 print "The batchfile should not contain --merge, --input or --output."
1896 do_command(gen, lustre, options, args)
1897 except OptionError, e:
1899 except Lustre.OptionError, e:
1903 do_command(gen, lustre, options, args)
1904 except OptionError, e:
1905 panic(string.join(sys.argv),e)
1906 except Lustre.OptionError, e:
1912 printDoc(doc, open(outFile,"w"))
1914 if __name__ == "__main__":