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]
96 --backfstype ldiskfs|ext3|tmpfs
103 --mkfsoptions options
104 --mountfsoptions options
105 --root_squash uid:gid
106 --no_root_squash ptl_nid
109 --mds_deny_sec flavor[,flavor[...]]
110 --filesystem filesystem name
116 --aware one or few mds/lmv names separated by comma
130 --fstype ldiskfs|ext3
131 --backfstype ldiskfs|ext3|tmpfs
134 --osdtype obdecho|obdfilter
136 --mkfsoptions options
137 --mountfsoptions options
139 --ost_deny_sec flavor[,flavor[...]]
140 --filesystem filesystem name
150 --add mtpt - Mountpoint
155 --ost ost_name OR --lov lov_name
156 --clientoptions options
164 --gateway_cluster_id nid
165 --target_cluster_id nid
172 --add mgmt - Management/monitoring service
174 --mgmt mgmt_service_name
181 --master_obd obd_name
186 --master_obd obd_name
192 --commit - Close a configuration version, and start a new one
195 PARAM = Lustre.Options.PARAM
196 PARAMLIST = Lustre.Options.PARAMLIST
198 # lmc input/output options
199 ('reference', "Print short reference for commands."),
200 ('verbose,v', "Print system commands as they are run."),
201 ('merge,m', "Append to the specified config file.", PARAM),
202 ('output,o', "Write XML configuration into given output file. Overwrite existing content.", PARAM),
203 ('input,i', "", PARAM),
204 ('batch', "Used to execute lmc commands in batch mode.", PARAM),
208 ('delete', "", PARAM),
209 ('deactivate', "", PARAM),
210 ('commit', "Commit all config changes and start a new version"),
213 ('node', "Add a new node in the cluster configuration.", PARAM),
214 ('timeout', "Set timeout to initiate recovery.", PARAM),
215 ('upcall', "Set both lustre and portals upcall scripts.", PARAM),
216 ('lustre_upcall', "Set location of lustre upcall script.", PARAM),
217 ('portals_upcall', "Set location of portals upcall script.", PARAM),
218 ('ptldebug', "Set the portals debug level", PARAM),
219 ('subsystem', "Specify which Lustre subsystems have debug output recorded in the log", PARAM),
222 ('nettype', "Specify the network type. This can be tcp/elan/gm/openib/iib/vib/ra.", PARAM),
223 ('nid', "Give the network ID, e.g ElanID/IP Address as used by portals.", PARAM),
224 ('port', "Optional argument to specify the TCP port number.", PARAM, DEFAULT_PORT),
225 ('hostaddr', "Optional argument to specify the host address.", PARAMLIST),
226 ('cluster_id', "Specify the cluster ID", PARAM, "0"),
229 ('route', "Add a new route for the cluster.", PARAM),
230 ('router', "Optional flag to mark a node as router."),
231 ('gw', "Specify the nid of the gateway for a route.", PARAM),
232 ('gateway_cluster_id', "", PARAM, "0"),
233 ('target_cluster_id', "", PARAM, "0"),
234 ('lo', "For a range route, this is the low value nid.", PARAM),
235 ('hi', "For a range route, this is a hi value nid.", PARAM,""),
237 # servers: mds and ost
238 ('mds', "Specify MDS name.", PARAM,""),
239 ('ost', "Specify the OST name.", PARAM,""),
240 ('osdtype', "This could obdfilter or obdecho.", PARAM, "obdfilter"),
241 ('failover', "Enable failover support on OSTs or MDS?"),
242 ('inactive', "Enable inactive support on failover MDS?"),
243 ('group', "", PARAM),
244 ('dev', "Path of the device on local system.", PARAM,""),
245 ('backdev', "Path of the device for backing storage on local system.", PARAM,""),
246 ('size', "Specify the size of the device if needed.", PARAM,"0"),
247 ('journal_size', "Specify new journal size for underlying file system.", PARAM,"0"),
248 ('inode_size', "Specify new inode size for underlying file system.", PARAM,"0"),
249 ('fstype', "Optional argument to specify the filesystem type.", PARAM, "ext3"),
250 ('backfstype', "Optional argument to specify the backing filesystem type.", PARAM, "ext3"),
251 ('mkfsoptions', "Optional argument to mkfs.", PARAM, ""),
252 ('mountfsoptions', "Optional argument to mount fs.", PARAM, ""),
253 ('ostuuid', "Optional argument to specify OST UUID", PARAM,""),
254 ('mdsuuid', "Optional argument to specify MDS UUID", PARAM,""),
255 ('root_squash', "MDS squash root to appointed uid.", PARAM, ""),
256 ('no_root_squash', "Don't squash root for appointed nid.", PARAM, ""),
257 ('nspath', "Local mount point of server namespace.", PARAM,""),
258 ('mds_mds_sec', "Specify the secure flavor for connection from this mds to other mds.", PARAM, ""),
259 ('mds_oss_sec', "Specify the secure flavor for connection from this mds to ost.", PARAM, ""),
260 ('mds_deny_sec', "Specify the secure flavor which is denied from remote to this mds.", PARAM, ""),
261 ('ost_deny_sec', "Specify the secure flavor which is denied from remote to this ost.", PARAM, ""),
262 ('filesystem', "Specify the filesystem name device belong to.", PARAM, ""),
264 ('migrate', "used for offline migrate of an ost in conjunctio with add/delete"),
266 # clients: mountpoint and echo
267 ('echo_client', "", PARAM),
268 ('path', "Specify the mountpoint for Lustre.", PARAM),
269 ('filesystem', "Lustre filesystem name", PARAM,""),
270 ('clientoptions', "Specify the options for Lustre, such as async.", PARAM, ""),
271 ('mds_sec', "Specify the secure flavor for connection from this client to mds.", PARAM, ""),
272 ('oss_sec', "Specify the secure flavor for connection from this client to ost.", PARAM, ""),
275 ('lov', "Specify LOV name.", PARAM,""),
276 ('mds/lmv', "Specify MDS/LMV name using this LOV.", PARAM,""),
277 ('aware', "Specify MDS/LMV aware of this LOV.", PARAM,""),
278 ('index', "Specify index for OBD in LOV target table.", PARAM),
279 ('stripe_sz', "Specify the stripe size in bytes.", PARAM),
280 ('stripe_cnt', "Specify the number of OSTs each file should be striped on.", PARAM, 0),
281 ('stripe_pattern', "Specify the stripe pattern. RAID 0 is the only one currently supported.", PARAM, 0),
284 ('master_obd', "Specify the real device for the cache obd system.", PARAM),
285 ('cache_obd', "Specify the cache device for the cache obd system.", PARAM),
286 ('cobd', "Specify COBD name", PARAM),
289 ('master_obd', "Specify the master device for the cmobd system.", PARAM),
290 ('cache_obd', "Specify the cache device for the cmobd obd system.", PARAM),
291 ('cmobd', "Specify COBD name", PARAM),
293 ('mgmt', "Specify management/monitoring service name.", PARAM, ""),
296 ('lmv', "Specify LMV name.", PARAM,""),
299 ('gks', "Specify gks name.", PARAM,""),
304 msg = string.join(map(str,args))
305 raise OptionError("Error: " + msg)
314 msg = string.join(map(str,args))
315 print "Warning: ", msg
318 # manage names and uuids
319 # need to initialize this by walking tree to ensure
320 # no duplicate names or uuids are created.
321 # this are just place holders for now.
322 # consider changing this to be like OBD-dev-host
326 while names.has_key(ret):
327 ret = "%s_%d" % (base, ctr)
334 ret = "%s_UUID" % (name)
335 if len(ret) > UUID_MAX_LENGTH:
336 ret = ret[-UUID_MAX_LENGTH:]
337 while uuids.has_key(ret):
338 ret = "%s_UUID_%d" % (name, ctr)
340 if len(ret) > UUID_MAX_LENGTH:
341 ret = ret[-UUID_MAX_LENGTH:]
347 ldlm_uuid = 'ldlm_UUID'
350 """Create a new empty lustre document"""
351 # adding ldlm here is a bit of a hack, but one is enough.
352 str = """<lustre version="%s">
353 <ldlm name="%s" uuid="%s"/>
354 </lustre>""" % (Lustre.CONFIG_VERSION, ldlm_name, ldlm_uuid)
355 return dom.parseString(str)
361 """initialize auto-name generation tables"""
363 # get all elements that contain a name attribute
364 for n in doc.childNodes:
365 if n.nodeType == n.ELEMENT_NODE:
367 names[getName(n)] = 1
368 uuids[getUUID(n)] = 1
371 def get_format_flag(options):
376 ############################################################
377 # Build config objects using DOM
382 def __init__(self, doc):
385 def ref(self, type, uuid):
386 """ generate <[type]_ref uuidref="[uuid]"/> """
387 tag = "%s_ref" % (type)
388 ref = self.doc.createElement(tag)
389 ref.setAttribute("uuidref", uuid)
392 def dev(self, devname):
393 """ generate <dev devpath="[devname]"/> """
394 tgt = self.doc.createElement('dev')
395 tgt.setAttribute("dev", devname)
398 def newService(self, tag, name, uuid):
399 """ create a new service elmement, which requires name and uuid attributes """
400 new = self.doc.createElement(tag)
401 new.setAttribute("uuid", uuid);
402 new.setAttribute("name", name);
405 def addText(self, node, str):
406 txt = self.doc.createTextNode(str)
407 node.appendChild(txt)
409 def addElement(self, node, tag, str=None):
410 """ create a new element and add it as a child to node. If str is passed,
411 a text node is created for the new element"""
412 new = self.doc.createElement(tag)
414 self.addText(new, str)
415 node.appendChild(new)
418 def network(self, name, uuid, nid, cluster_id, net, hostaddr="",
420 """create <network> node"""
421 network = self.newService("network", name, uuid)
422 network.setAttribute("nettype", net);
423 self.addElement(network, "nid", nid)
424 self.addElement(network, "clusterid", cluster_id)
425 for host in hostaddr:
426 self.addElement(network, "hostaddr", host)
428 self.addElement(network, "port", "%d" %(port))
432 def routetbl(self, name, uuid):
433 """create <routetbl> node"""
434 rtbl = self.newService("routetbl", name, uuid)
437 def route(self, gw_net_type, gw, gw_cluster_id, tgt_cluster_id, lo, hi):
438 """ create one entry for the route table """
439 ref = self.doc.createElement('route')
440 ref.setAttribute("type", gw_net_type)
441 ref.setAttribute("gw", gw)
442 ref.setAttribute("gwclusterid", gw_cluster_id)
443 ref.setAttribute("tgtclusterid", tgt_cluster_id)
444 ref.setAttribute("lo", lo)
446 ref.setAttribute("hi", hi)
449 def profile(self, name, uuid):
450 """ create a host """
451 profile = self.newService("profile", name, uuid)
454 def node(self, name, uuid, prof_uuid):
455 """ create a host """
456 node = self.newService("node", name, uuid)
457 node.appendChild(self.ref("profile", prof_uuid))
460 def ldlm(self, name, uuid):
461 """ create a ldlm """
462 ldlm = self.newService("ldlm", name, uuid)
465 def osd(self, name, uuid, fstype, osdtype, devname, format, ost_uuid,
466 node_uuid, dev_size=0, journal_size=0, inode_size=0, nspath="",
467 mkfsoptions="", mountfsoptions="", backfstype="", backdevname="",
468 deny_sec="", fs_uuid=""):
469 osd = self.newService("osd", name, uuid)
470 osd.setAttribute('osdtype', osdtype)
471 osd.appendChild(self.ref("target", ost_uuid))
472 osd.appendChild(self.ref("node", node_uuid))
475 osd.appendChild(self.dev(devname))
477 self.addElement(osd, "fstype", fstype)
479 self.addElement(osd, "backfstype", backfstype)
481 self.addElement(osd, "backdevpath", backdevname)
483 dev = self.addElement(osd, "devpath", devname)
484 self.addElement(osd, "autoformat", format)
486 self.addElement(osd, "devsize", "%s" % (dev_size))
488 self.addElement(osd, "journalsize", "%s" % (journal_size))
490 self.addElement(osd, "inodesize", "%s" % (inode_size))
492 self.addElement(osd, "mkfsoptions", mkfsoptions)
494 self.addElement(osd, "mountfsoptions", mountfsoptions)
496 self.addElement(osd, "deny_sec", deny_sec)
498 osd.appendChild(self.ref("filesystem", fs_uuid))
500 self.addElement(osd, "nspath", nspath)
503 def cobd(self, name, uuid, master_uuid, cache_uuid):
504 cobd = self.newService("cobd", name, uuid)
505 cobd.appendChild(self.ref("masterobd",master_uuid))
506 cobd.appendChild(self.ref("cacheobd",cache_uuid))
509 def cmobd(self, name, uuid, master_uuid, cache_uuid):
510 cmobd = self.newService("cmobd", name, uuid)
511 cmobd.appendChild(self.ref("masterobd",master_uuid))
512 cmobd.appendChild(self.ref("cacheobd",cache_uuid))
515 def ost(self, name, uuid, osd_uuid, group=""):
516 ost = self.newService("ost", name, uuid)
517 ost.appendChild(self.ref("active", osd_uuid))
519 self.addElement(ost, "group", group)
522 def oss(self, name, uuid):
523 oss = self.newService("oss", name, uuid)
526 def lov(self, name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern):
527 lov = self.newService("lov", name, uuid)
528 lov.appendChild(self.ref("mds", mds_uuid))
529 lov.setAttribute("stripesize", str(stripe_sz))
530 lov.setAttribute("stripecount", str(stripe_cnt))
531 lov.setAttribute("stripepattern", str(pattern))
534 def lov_tgt(self, obd_uuid, lov_uuid, index, generation):
535 tgt = self.doc.createElement('lov_tgt')
536 tgt.setAttribute("uuidref", obd_uuid)
537 tgt.setAttribute("lov_uuid", lov_uuid)
538 tgt.setAttribute("index", index)
539 tgt.setAttribute("generation", generation)
540 tgt.setAttribute("active", '1')
543 def lovconfig(self, name, uuid, lov_uuid):
544 lovconfig = self.newService("lovconfig", name, uuid)
545 lovconfig.appendChild(self.ref("lov", lov_uuid))
548 def lmv_tgt(self, mdt_uuid):
549 tgt = self.doc.createElement('lmv_tgt')
550 tgt.setAttribute("uuidref", mdt_uuid)
553 def lmv(self, name, uuid):
554 lmv = self.newService("lmv", name, uuid)
557 def gks(self, name, uuid, gkd_uuid):
558 gks = self.newService("gks", name, uuid)
559 gks.appendChild(self.ref("active", gkd_uuid))
562 def gkd(self, name, uuid, node_uuid, gks_uuid):
563 gkd = self.newService("gkd", name, uuid)
564 gkd.appendChild(self.ref("node", node_uuid))
565 gkd.appendChild(self.ref("target", gks_uuid))
568 def mds(self, name, uuid, mdd_uuid, group="", lmv=""):
569 mds = self.newService("mds", name, uuid)
570 #mds.appendChild(self.ref("active", mdd_uuid))
572 self.addElement(mds, "group", group)
575 def mdsdev(self, name, uuid, fstype, devname, format, node_uuid,
576 mds_uuid, dev_size=0, journal_size=0, inode_size=256,
577 nspath="", mkfsoptions="", mountfsoptions="", backfstype="",
578 backdevname="",lmv_uuid="", root_squash="", no_root_squash="",
579 mds_sec="", oss_sec="", deny_sec="", fs_uuid=""):
580 mdd = self.newService("mdsdev", name, uuid)
581 self.addElement(mdd, "fstype", fstype)
583 self.addElement(mdd, "backfstype", backfstype)
584 dev = self.addElement(mdd, "devpath", devname)
586 self.addElement(mdd, "backdevpath", backdevname)
587 self.addElement(mdd, "autoformat", format)
589 self.addElement(mdd, "devsize", "%s" % (dev_size))
591 self.addElement(mdd, "journalsize", "%s" % (journal_size))
593 self.addElement(mdd, "inodesize", "%s" % (inode_size))
595 self.addElement(mdd, "nspath", nspath)
597 self.addElement(mdd, "mkfsoptions", mkfsoptions)
599 self.addElement(mdd, "mountfsoptions", mountfsoptions)
601 self.addElement(mdd, "root_squash", root_squash)
603 self.addElement(mdd, "no_root_squash", no_root_squash)
605 self.addElement(mdd, "mds_sec", mds_sec)
607 self.addElement(mdd, "oss_sec", oss_sec)
609 self.addElement(mdd, "deny_sec", deny_sec)
611 mdd.appendChild(self.ref("filesystem", fs_uuid))
612 mdd.appendChild(self.ref("node", node_uuid))
613 mdd.appendChild(self.ref("target", mds_uuid))
615 dev = self.dev(devname)
620 mdd.appendChild(self.ref("lmv", lmv_uuid))
624 def mgmt(self, mgmt_name, mgmt_uuid, node_uuid):
625 mgmt = self.newService("mgmt", mgmt_name, mgmt_uuid)
626 mgmt.appendChild(self.ref("node", node_uuid))
627 # Placeholder until mgmt-service failover.
628 mgmt.appendChild(self.ref("active", mgmt_uuid))
631 def mountpoint(self, name, uuid, fs_uuid, path, clientoptions,
633 mtpt = self.newService("mountpoint", name, uuid)
634 mtpt.appendChild(self.ref("filesystem", fs_uuid))
635 self.addElement(mtpt, "path", path)
637 self.addElement(mtpt, "clientoptions", clientoptions)
639 self.addElement(mtpt, "mds_sec", mds_sec)
641 self.addElement(mtpt, "oss_sec", oss_sec)
644 def filesystem(self, name, uuid, mds_uuid, obd_uuid, mgmt_uuid, gks_uuid):
645 fs = self.newService("filesystem", name, uuid)
648 fs.appendChild(self.ref("mds", mds_uuid))
650 fs.appendChild(self.ref("obd", obd_uuid))
652 fs.appendChild(self.ref("gks", gks_uuid))
654 fs.appendChild(self.ref("mgmt", mgmt_uuid))
657 def echo_client(self, name, uuid, osc_uuid):
658 ec = self.newService("echoclient", name, uuid)
659 ec.appendChild(self.ref("obd", osc_uuid))
662 def update(self, version):
663 new = self.doc.createElement("update")
664 new.setAttribute("version", version)
668 new = self.doc.createElement("info")
671 def lmv_add(self, lmv, mdt):
672 new = self.doc.createElement("lmv_add")
673 new.setAttribute("lmv_uuidref", lmv)
674 new.setAttribute("mdt_uuidref", mdt)
677 def lov_add(self, lov, ost, index, gen):
678 new = self.doc.createElement("lov_add")
679 new.setAttribute("lov_uuidref", lov)
680 new.setAttribute("ost_uuidref", ost)
681 new.setAttribute("index", index)
682 new.setAttribute("generation", gen)
685 def lov_delete(self, lov, ost, index, gen, options):
687 new = self.doc.createElement("lov_delete")
689 new = self.doc.createElement("lov_deactivate")
690 new.setAttribute("lov_uuidref", lov)
691 new.setAttribute("ost_uuidref", ost)
692 new.setAttribute("index", index)
693 new.setAttribute("generation", gen)
696 ############################################################
697 # Utilities to query a DOM tree
698 # Using this functions we can treat use config information
699 # directly as a database.
701 return n.getAttribute('name')
704 return node.getAttribute('uuid')
706 def findLastUpdate(lustre):
709 for n in lustre.childNodes:
710 if n.nodeType == n.ELEMENT_NODE:
711 if n.nodeName != 'update':
713 tmp = int(n.getAttribute('version'))
715 error('malformed XML: update tag without a version attribute')
716 if tmp != version + 1:
717 error('malformed XML: expecting update record '+str(version + 1)+', found '+str(tmp)+'.')
722 def addUpdate(gen, lustre, node):
723 update = findLastUpdate(lustre)
726 update.appendChild(node)
728 def findByName(lustre, name, tag = ""):
729 for n in lustre.childNodes:
730 if n.nodeType == n.ELEMENT_NODE:
731 if tag and n.nodeName != tag:
733 if getName(n) == name:
736 n = findByName(n, name)
741 def lookup(node, uuid):
742 for n in node.childNodes:
743 if n.nodeType == n.ELEMENT_NODE:
744 if getUUID(n) == uuid:
752 def name2uuid(lustre, name, tag="", fatal=1):
753 ret = findByName(lustre, name, tag)
756 error('name2uuid:', '"'+name+'"', tag, 'element not found.')
761 def lookup_filesystem(lustre, fs_name):
762 for n in lustre.childNodes:
763 if n.nodeType == n.ELEMENT_NODE and n.nodeName == 'filesystem':
764 if getName(n) == fs_name:
768 # XXX: assumes only one network element per node. will fix this
769 # as soon as support for routers is added
770 def get_net_uuid(lustre, node_name):
771 """ get a network uuid for a node_name """
772 node = findByName(lustre, node_name, "node")
774 error ('get_net_uuid:', '"'+node_name+'"', "node element not found.")
775 net = node.getElementsByTagName('network')
777 return getUUID(net[0])
780 def lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options):
781 tgt.setAttribute('uuidref', osc_uuid)
782 gener = int(tgt.getAttribute('generation'))
783 if not options.migrate:
784 gener = str(int(gener) + 1)
785 tgt.setAttribute('generation', str(gener))
786 tgt.setAttribute('active', '1')
787 lov_index = int(tgt.getAttribute('index'))
788 add_rec = gen.lov_add(getUUID(lov), osc_uuid, str(lov_index), str(gener))
789 addUpdate(gen, lustre, add_rec)
792 def lov_add_osc(gen, lustre, lov, osc_uuid, options):
793 lov_name = getName(lov)
794 lov_uuid = getUUID(lov)
796 lov_index = get_option_int(options, 'index')
797 for tgt in lov.getElementsByTagName('lov_tgt'):
798 if str(lov_index) == tgt.getAttribute('index'):
799 uuidref = tgt.getAttribute('uuidref')
801 raise OptionError("%s --index %d is still in use: %s" %
802 (lov_name, lov_index, uuidref))
803 lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
807 for tgt in lov.getElementsByTagName('lov_tgt'):
808 uuidref = tgt.getAttribute('uuidref')
809 tmp = int(tgt.getAttribute('index'))
810 own_lov_uuid = tgt.getAttribute('lov_uuid')
811 if lov_uuid != own_lov_uuid:
814 lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
816 lov_index = lov_index + 1
818 lov.appendChild(gen.lov_tgt(osc_uuid, lov_uuid, str(lov_index), '1'))
819 addrec = gen.lov_add(lov_uuid, osc_uuid, str(lov_index), '1')
820 addUpdate(gen, lustre, addrec)
822 def lov_del_osc(gen, lustre, lov, osc_uuid, options):
823 lov_name = getName(lov)
825 lov_index = get_option_int(options, 'index')
826 for tgt in lov.getElementsByTagName('lov_tgt'):
827 index = tgt.getAttribute('index')
828 if index == lov_index:
829 uuidref = tgt.getAttribute('uuidref')
830 if uuidref != osc_uuid:
831 raise OptionError("%s --index %d contains %s, not %s" %
832 (lov_name, lov_index, osc_uuid, uuidref))
834 tgt.setAttribute('uuidref', '')
836 gener = tgt.getAttribute('generation')
837 if not options.migrate:
838 # bump the generation just in case...
839 gener = str(int(gener) + 1)
841 tgt.setAttribute('active', '0')
842 tgt.setAttribute('generation', gener)
844 raise OptionError("%s --index %d not in use by %s." %
845 (lov_name, lov_index, osc_uuid))
847 for tgt in lov.getElementsByTagName('lov_tgt'):
848 uuidref = tgt.getAttribute('uuidref')
849 if uuidref == osc_uuid:
850 index = tgt.getAttribute('index')
851 gener = tgt.getAttribute('generation')
852 delete_rec = gen.lov_delete(getUUID(lov), osc_uuid, index, gener,
854 addUpdate(gen, lustre, delete_rec)
857 tgt.setAttribute('uuidref', '')
858 if not options.migrate:
859 gener = str(int(gener) + 1)
860 tgt.setAttribute('active', '0')
861 tgt.setAttribute('generation', gener)
863 def lmv_add_mdc(gen, lustre, lmv, mdc_uuid):
864 lmv.appendChild(gen.lmv_tgt(mdc_uuid))
865 addrec = gen.lmv_add(getUUID(lmv), mdc_uuid)
866 addUpdate(gen, lustre, addrec)
868 def ref_exists(profile, uuid):
869 elist = profile.childNodes
871 if e.nodeType == e.ELEMENT_NODE:
872 ref = e.getAttribute('uuidref')
877 # ensure that uuid is not already in the profile
878 # return true if uuid is added
879 def node_add_profile(gen, node, ref, uuid):
880 refname = "%s_ref" % "profile"
881 ret = node.getElementsByTagName(refname)
883 error('node has no profile ref:', node)
884 prof_uuid = ret[0].getAttribute('uuidref')
885 profile = lookup(node.parentNode, prof_uuid)
887 error("no profile found:", prof_uuid)
888 if ref_exists(profile, uuid):
890 profile.appendChild(gen.ref(ref, uuid))
893 def get_attr(dom_node, attr, default=""):
894 v = dom_node.getAttribute(attr)
899 ############################################################
902 def set_node_options(gen, node, options):
904 node.setAttribute('router', '1')
906 gen.addElement(node, "timeout", get_option(options, 'timeout'))
908 default_upcall = get_option(options, 'upcall')
911 if default_upcall or options.lustre_upcall:
912 if options.lustre_upcall:
913 gen.addElement(node, 'lustreUpcall', options.lustre_upcall)
915 gen.addElement(node, 'lustreUpcall', default_upcall)
916 if default_upcall or options.portals_upcall:
917 if options.portals_upcall:
918 gen.addElement(node, 'portalsUpcall', options.portals_upcall)
920 gen.addElement(node, 'portalsUpcall', default_upcall)
922 gen.addElement(node, "ptldebug", get_option(options, 'ptldebug'))
923 if options.subsystem:
924 gen.addElement(node, "subsystem", get_option(options, 'subsystem'))
927 def do_add_node(gen, lustre, options, node_name):
928 uuid = new_uuid(node_name)
929 prof_name = new_name("PROFILE_" + node_name)
930 prof_uuid = new_uuid(prof_name)
931 profile = gen.profile(prof_name, prof_uuid)
932 node = gen.node(node_name, uuid, prof_uuid)
933 lustre.appendChild(node)
934 lustre.appendChild(profile)
936 node_add_profile(gen, node, 'ldlm', ldlm_uuid)
937 set_node_options(gen, node, options)
941 def add_node(gen, lustre, options):
942 """ create a node with a network config """
944 node_name = get_option(options, 'node')
945 ret = findByName(lustre, node_name, "node")
947 print "Node:", node_name, "exists."
949 do_add_node(gen, lustre, options, node_name)
952 def add_net(gen, lustre, options):
953 """ create a node with a network config """
955 node_name = get_option(options, 'node')
956 nid = get_option(options, 'nid')
957 cluster_id = get_option(options, 'cluster_id')
958 hostaddr = get_option(options, 'hostaddr')
959 net_type = get_option(options, 'nettype')
961 if net_type in ('tcp','openib','ra'):
962 port = get_option_int(options, 'port')
963 elif net_type in ('elan', 'gm', 'iib', 'vib', 'lo', 'cray_kern_nal'):
966 print "Unknown net_type: ", net_type
969 ret = findByName(lustre, node_name, "node")
971 node = do_add_node(gen, lustre, options, node_name)
974 set_node_options(gen, node, options)
976 net_name = new_name('NET_'+ node_name +'_'+ net_type)
977 net_uuid = new_uuid(net_name)
978 node.appendChild(gen.network(net_name, net_uuid, nid, cluster_id, net_type,
980 node_add_profile(gen, node, "network", net_uuid)
983 def add_route(gen, lustre, options):
984 """ create a node with a network config """
986 node_name = get_option(options, 'node')
987 gw_net_type = get_option(options, 'nettype')
988 gw = get_option(options, 'gw')
989 gw_cluster_id = get_option(options, 'gateway_cluster_id')
990 tgt_cluster_id = get_option(options, 'target_cluster_id')
991 lo = get_option(options, 'lo')
992 hi = get_option(options, 'hi')
996 node = findByName(lustre, node_name, "node")
998 error (node_name, " not found.")
1000 rlist = node.getElementsByTagName('routetbl')
1004 rtbl_name = new_name("RTBL_" + node_name)
1005 rtbl_uuid = new_uuid(rtbl_name)
1006 rtbl = gen.routetbl(rtbl_name, rtbl_uuid)
1007 node.appendChild(rtbl)
1008 node_add_profile(gen, node, "routetbl", rtbl_uuid)
1009 rtbl.appendChild(gen.route(gw_net_type, gw, gw_cluster_id, tgt_cluster_id,
1012 def add_gks(gen, lustre, options):
1013 """ create a gks """
1014 node_name = get_option(options, 'node')
1015 gks_name = get_option(options, 'gks')
1017 gks_name = new_name('GKS_'+ node_name)
1019 gkd_name = new_name("GKD_" + gks_name + "_" + node_name)
1020 gkd_uuid = new_uuid(gkd_name)
1022 gks_uuid = name2uuid(lustre, gks_name, 'gks', fatal=0)
1025 gks_uuid = new_uuid(gks_name)
1026 gks = gen.gks(gks_name, gks_uuid, gkd_uuid)
1027 lustre.appendChild(gks)
1029 gks = lookup(lustre, gks_uuid)
1032 node_uuid = name2uuid(lustre, node_name, 'node')
1033 node = findByName(lustre, node_name, "node")
1034 node_add_profile(gen, node, "gkd", gkd_uuid)
1035 net_uuid = get_net_uuid(lustre, node_name)
1037 error("NODE: ", node_name, "not found")
1039 gkd = gen.gkd(gkd_name, gkd_uuid, node_uuid, gks_uuid)
1040 lustre.appendChild(gkd)
1043 def add_mds(gen, lustre, options):
1044 node_name = get_option(options, 'node')
1045 mds_name = get_option(options, 'mds')
1047 mds_name = new_name('MDS_'+ node_name)
1048 lmv_name = get_option(options, 'lmv')
1049 mdd_name = new_name("MDD_" + mds_name +"_" + node_name)
1050 mdd_uuid = new_uuid(mdd_name)
1054 lmv_uuid = name2uuid(lustre, lmv_name, fatal=0)
1056 mds_uuid = name2uuid(lustre, mds_name, 'mds', fatal=0)
1058 mds_uuid = get_option(options, 'mdsuuid')
1060 if lookup(lustre, mds_uuid):
1061 error("Duplicate MDS UUID:", mds_uuid)
1063 mds_uuid = new_uuid(mds_name)
1064 mds = gen.mds(mds_name, mds_uuid, mdd_uuid, options.group)
1065 lustre.appendChild(mds)
1067 lmv = findByName(lustre,lmv_name, "lmv")
1069 error('add_mds:', '"' + lmv_name + '"', "lmv element not found.")
1070 lmv_add_mdc(gen, lustre, lmv, mds_uuid)
1072 mds.appendChild(gen.ref("lmv", lmv_uuid))
1074 mds = lookup(lustre, mds_uuid)
1076 if not options.inactive:
1077 mds.appendChild(gen.ref("active", mdd_uuid))
1079 if options.failover:
1080 mds.setAttribute('failover', "1")
1082 devname = get_option(options, 'dev')
1083 backdevname = get_option(options, 'backdev')
1084 size = get_option(options, 'size')
1085 fstype = get_option(options, 'fstype')
1086 backfstype = get_option(options, 'backfstype')
1087 journal_size = get_option(options, 'journal_size')
1088 inode_size = get_option(options, 'inode_size')
1089 nspath = get_option(options, 'nspath')
1090 mkfsoptions = get_option(options, 'mkfsoptions')
1091 mountfsoptions = get_option(options, 'mountfsoptions')
1092 root_squash = get_option(options, 'root_squash')
1093 no_root_squash = get_option(options, 'no_root_squash')
1094 mds_sec = get_option(options, 'mds_mds_sec')
1095 oss_sec = get_option(options, 'mds_oss_sec')
1096 deny_sec = get_option(options, 'mds_deny_sec')
1097 fs_name = get_option(options, 'filesystem')
1099 node_uuid = name2uuid(lustre, node_name, 'node')
1101 node = findByName(lustre, node_name, "node")
1102 node_add_profile(gen, node, "mdsdev", mdd_uuid)
1103 net_uuid = get_net_uuid(lustre, node_name)
1105 error("NODE: ", node_name, "not found")
1108 fs_uuid = name2uuid(lustre, fs_name, 'filesystem', fatal=1)
1112 mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname,
1113 get_format_flag(options), node_uuid, mds_uuid,
1114 size, journal_size, inode_size, nspath, mkfsoptions,
1115 mountfsoptions, backfstype, backdevname,lmv_uuid,
1116 root_squash, no_root_squash, mds_sec, oss_sec, deny_sec,
1118 lustre.appendChild(mdd)
1120 def add_mgmt(gen, lustre, options):
1121 node_name = get_option(options, 'node')
1122 node_uuid = name2uuid(lustre, node_name, 'node')
1123 mgmt_name = get_option(options, 'mgmt')
1125 mgmt_name = new_name('MGMT_' + node_name)
1126 mgmt_uuid = name2uuid(lustre, mgmt_name, 'mgmt', fatal=0)
1128 mgmt_uuid = new_uuid(mgmt_name)
1129 mgmt = gen.mgmt(mgmt_name, mgmt_uuid, node_uuid)
1130 lustre.appendChild(mgmt)
1132 mgmt = lookup(lustre, mgmt_uuid)
1134 node = findByName(lustre, node_name, "node")
1135 node_add_profile(gen, node, 'mgmt', mgmt_uuid)
1137 def add_ost(gen, lustre, options):
1138 node_name = get_option(options, 'node')
1139 lovname = get_option(options, 'lov')
1140 osdtype = get_option(options, 'osdtype')
1142 node_uuid = name2uuid(lustre, node_name, 'node')
1144 if osdtype == 'obdecho':
1156 devname = get_option(options, 'dev') # can be unset for bluearcs
1157 backdevname = get_option(options, 'backdev')
1158 size = get_option(options, 'size')
1159 fstype = get_option(options, 'fstype')
1160 backfstype = get_option(options, 'backfstype')
1161 journal_size = get_option(options, 'journal_size')
1162 inode_size = get_option(options, 'inode_size')
1163 mkfsoptions = get_option(options, 'mkfsoptions')
1164 mountfsoptions = get_option(options, 'mountfsoptions')
1165 deny_sec = get_option(options, 'ost_deny_sec')
1167 fs_name = get_option(options, 'filesystem')
1168 nspath = get_option(options, 'nspath')
1170 ostname = get_option(options, 'ost')
1172 ostname = new_name('OST_'+ node_name)
1174 osdname = new_name("OSD_" + ostname + "_" + node_name)
1175 osd_uuid = new_uuid(osdname)
1177 ost_uuid = name2uuid(lustre, ostname, 'ost', fatal=0)
1179 ost_uuid = get_option(options, 'ostuuid')
1181 if lookup(lustre, ost_uuid):
1182 error("Duplicate OST UUID:", ost_uuid)
1184 ost_uuid = new_uuid(ostname)
1186 ost = gen.ost(ostname, ost_uuid, osd_uuid, options.group)
1187 lustre.appendChild(ost)
1189 ost = lookup(lustre, ost_uuid)
1192 lov = findByName(lustre, lovname, "lov")
1194 error('add_ost:', '"'+lovname+'"', "lov element not found.")
1195 lov_add_osc(gen, lustre, lov, ost_uuid, options)
1197 if options.failover:
1198 ost.setAttribute('failover', "1")
1201 fs_uuid = name2uuid(lustre, fs_name, 'filesystem', fatal=1)
1205 osd = gen.osd(osdname, osd_uuid, fstype, osdtype, devname,
1206 get_format_flag(options), ost_uuid, node_uuid, size,
1207 journal_size, inode_size, nspath, mkfsoptions,
1208 mountfsoptions, backfstype, backdevname, deny_sec,
1211 node = findByName(lustre, node_name, "node")
1212 node_add_profile(gen, node, 'osd', osd_uuid)
1213 lustre.appendChild(osd)
1215 def del_ost(gen, lustre, options):
1216 ostname = get_option(options, 'ost')
1218 raise OptionError("del_ost: --ost requires a <ost name>")
1219 ost = findByName(lustre, ostname, "ost")
1221 error('del_ost: ', 'Unable to find ', ostname)
1222 ost_uuid = name2uuid(lustre, ostname, fatal=0)
1224 error('del_ost: ', 'Unable to find uuid for ', ostname)
1225 lovname = get_option(options, 'lov')
1227 lov = findByName(lustre, lovname, "lov")
1229 error('del_ost:', '"'+lovname+'"', "lov element not found.")
1230 lov_del_osc(gen, lustre, lov, ost_uuid, options)
1231 # if the user specified a speficic LOV don't delete the OST itself
1234 # remove OSD references from all LOVs
1235 for lov in lustre.getElementsByTagName('lov'):
1236 lov_del_osc(gen, lustre, lov, ost_uuid, options)
1240 # move the OST description to the update record
1241 lustre.removeChild(ost)
1242 info.appendChild(ost)
1244 active_ref = ost.getElementsByTagName('active_ref')
1246 error('ost has no osd ref:', ostname)
1248 # move the OSD description to the update record
1249 osd_uuid = active_ref[0].getAttribute('uuidref')
1250 osd = lookup(lustre, osd_uuid)
1251 lustre.removeChild(osd)
1252 info.appendChild(osd)
1254 # make a copy of the OSS description in the update record
1255 # XXX - should check to make sure one doesn't already exist.
1256 node_ref = osd.getElementsByTagName('node_ref')
1258 error('osd has no node ref:', ostname)
1259 node_uuid = node_ref[0].getAttribute('uuidref')
1260 node = lookup(lustre, node_uuid)
1262 error('unable to locate node for node ref:', node_uuid)
1264 node_rec = node.cloneNode(1)
1265 info.appendChild(node_rec)
1267 prof_ref = node.getElementsByTagName('profile_ref')
1269 error('node has no profile ref:', node)
1270 profile_uuid = prof_ref[0].getAttribute('uuidref')
1272 # make a copy of the OSS's profile in the update record
1273 # XXX - should check to make sure one doesn't already exist.
1274 profile = lookup(lustre, profile_uuid)
1275 profile_rec = profile.cloneNode(1)
1276 info.appendChild(profile_rec)
1278 # delete all references to this OSD in the OSS's current profile
1279 for osd_ref in profile.getElementsByTagName('osd_ref'):
1280 if osd_uuid == osd_ref.getAttribute('uuidref'):
1281 profile.removeChild(osd_ref)
1283 # XXX - We should cleanup the node and profile elements if they
1284 # no longer serve a purpose.
1285 addUpdate(gen, lustre, info)
1287 def add_cmobd(gen, lustre, options):
1288 node_name = get_option(options, 'node')
1289 name = get_option(options, 'cmobd')
1290 uuid = new_uuid(name)
1292 master_name = get_option(options, 'master_obd')
1293 cache_name = get_option(options, 'cache_obd')
1295 master_uuid = name2uuid(lustre, master_name, tag='lov', fatal=0)
1296 cache_uuid = name2uuid(lustre, cache_name, tag='lov', fatal=0)
1298 if not master_uuid or not cache_uuid:
1300 master_uuid = name2uuid(lustre, master_name, tag='ost', fatal=0)
1302 cache_uuid = name2uuid(lustre, cache_name, tag='ost', fatal=0)
1304 if not master_uuid or not cache_uuid:
1306 master_uuid = name2uuid(lustre, master_name, tag='lmv', fatal=0)
1308 cache_uuid = name2uuid(lustre, cache_name, tag='lmv', fatal=0)
1310 if not master_uuid or not cache_uuid:
1312 master_uuid = name2uuid(lustre, master_name, tag='mds', fatal=0)
1314 cache_uuid = name2uuid(lustre, cache_name, tag='mds', fatal=0)
1317 error("cannot find master_uuid by name '" + master_name + "'")
1319 error("cannot find cache_uuid by name '" + cache_name + "'")
1321 node = findByName(lustre, node_name, "node")
1322 node_add_profile(gen, node, "cmobd", uuid)
1324 master_node = lookup(lustre, master_uuid)
1325 cache_node = lookup(lustre, cache_uuid)
1327 error("cannot find master node by its uuid " + master_uuid);
1329 error("cannot find cache node by its uuid " + cache_uuid);
1331 active = master_node.getElementsByTagName('active_ref')
1333 active_uuid = active[0].getAttribute('uuidref')
1334 active_node = lookup(lustre, active_uuid)
1335 if not active_node.getElementsByTagName('obdtype'):
1336 gen.addElement(active_node, 'obdtype', 'master')
1338 active = cache_node.getElementsByTagName('active_ref')
1340 active_uuid = active[0].getAttribute('uuidref')
1341 active_node = lookup(lustre, active_uuid)
1342 if not active_node.getElementsByTagName('obdtype'):
1343 gen.addElement(active_node, 'obdtype', 'cache')
1345 cmobd = gen.cmobd(name, uuid, master_uuid, cache_uuid)
1346 lustre.appendChild(cmobd)
1348 def add_cobd(gen, lustre, options):
1349 node_name = get_option(options, 'node')
1350 name = get_option(options, 'cobd')
1351 uuid = new_uuid(name)
1353 master_name = get_option(options, 'master_obd')
1354 cache_name = get_option(options, 'cache_obd')
1357 master_uuid = name2uuid(lustre, master_name, tag='lov', fatal=0)
1359 master_uuid = name2uuid(lustre, master_name, tag='ost', fatal=0)
1362 node = lookup(lustre, master_uuid)
1363 rets = node.getElementsByTagName('lov_tgt')
1365 ost_uuid = ret.getAttribute('uuidref')
1366 ost_node = lookup(lustre, ost_uuid)
1367 active = ost_node.getElementsByTagName('active_ref')
1369 osd_uuid = active[0].getAttribute('uuidref')
1370 osd_node = lookup(lustre, osd_uuid)
1371 if not osd_node.getElementsByTagName('obdtype'):
1372 gen.addElement(osd_node, 'obdtype', 'master')
1375 cache_uuid = name2uuid(lustre, cache_name, tag='lov', fatal=0)
1377 cache_uuid = name2uuid(lustre, cache_name, tag='ost', fatal=0)
1380 node = lookup(lustre, cache_uuid)
1381 rets = node.getElementsByTagName('lov_tgt')
1383 ost_uuid = ret.getAttribute('uuidref')
1384 ost_node = lookup(lustre, ost_uuid)
1385 active = ost_node.getElementsByTagName('active_ref')
1387 osd_uuid = active[0].getAttribute('uuidref')
1388 osd_node = lookup(lustre, osd_uuid)
1389 if not osd_node.getElementsByTagName('obdtype'):
1390 gen.addElement(osd_node, 'obdtype', 'cache')
1392 if not master_uuid or not cache_uuid:
1393 master_uuid = name2uuid(lustre, master_name, tag='lmv', fatal=0)
1395 master_uuid = name2uuid(lustre, master_name, tag='mds', fatal=0)
1398 mds_node = lookup(lustre, master_uuid)
1399 ret = mds_node.getElementsByTagName('active_ref')
1401 mdsdev_uuid = ret[0].getAttribute('uuidref')
1402 mdsdev_node = lookup(lustre, mdsdev_uuid)
1403 if not mdsdev_node.getElementsByTagName('obdtype'):
1404 gen.addElement(mdsdev_node, 'obdtype', 'master')
1406 cache_uuid = name2uuid(lustre, cache_name, tag='lmv', fatal=0)
1408 cache_uuid = name2uuid(lustre, cache_name, tag='mds', fatal=0)
1411 mds_node = lookup(lustre, cache_uuid)
1412 ret = mds_node.getElementsByTagName('active_ref')
1414 mdsdev_uuid = ret[0].getAttribute('uuidref')
1415 mdsdev_node = lookup(lustre, mdsdev_uuid)
1416 if not mdsdev_node.getElementsByTagName('obdtype'):
1417 gen.addElement(mdsdev_node, 'obdtype', 'cache')
1419 if not master_uuid or not cache_uuid:
1420 panic("add_cobd", "cannot find master or cache by names '" +
1421 master_name + "' and '" + cache_name + "'")
1423 node = findByName(lustre, node_name, "node")
1424 cobd = gen.cobd(name, uuid, master_uuid, cache_uuid)
1425 lustre.appendChild(cobd)
1427 def add_echo_client(gen, lustre, options):
1428 """ add an echo client to the profile for this node. """
1429 node_name = get_option(options, 'node')
1430 lov_name = get_option(options, 'ost')
1432 node = findByName(lustre, node_name, 'node')
1434 echoname = new_name('ECHO_'+ node_name)
1435 echo_uuid = new_uuid(echoname)
1436 node_add_profile(gen, node, 'echoclient', echo_uuid)
1438 lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
1440 lov_uuid = name2uuid(lustre, lov_name, tag='ost', fatal=1)
1442 echo = gen.echo_client(echoname, echo_uuid, lov_uuid)
1443 lustre.appendChild(echo)
1445 def add_lov(gen, lustre, options):
1446 """ create a lov """
1448 lov_orig = get_option(options, 'lov')
1449 name = new_name(lov_orig)
1450 if name != lov_orig:
1451 warning("name:", lov_orig, "already used. using:", name)
1453 lmv_name = get_option(options, 'lmv')
1454 mds_name = get_option(options, 'mds')
1455 aware = get_option(options, 'aware')
1457 if not mds_name and not lmv_name:
1458 error("LOV: either MDS or LMV must be specified.");
1459 if mds_name and lmv_name:
1460 error("LOV: either MDS or LMV must be specified.");
1462 stripe_sz = get_option_int(options, 'stripe_sz')
1463 stripe_cnt = get_option_int(options, 'stripe_cnt')
1464 pattern = get_option_int(options, 'stripe_pattern')
1465 uuid = new_uuid(name)
1467 ret = findByName(lustre, name, "lov")
1469 error("LOV: ", name, " already exists.")
1472 mds_uuid = name2uuid(lustre, lmv_name, 'lmv')
1474 mds_uuid = name2uuid(lustre, mds_name, 'mds')
1476 lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
1477 lustre.appendChild(lov)
1479 # add an lovconfig entry to the active mdsdev profile
1480 lovconfig_name = new_name('LVCFG_' + name)
1481 lovconfig_uuid = new_uuid(lovconfig_name)
1484 md_tgt = findByName(lustre, mds_name, "mds")
1486 error("can't find MDS '" + mds_name + "'")
1488 md_tgt = findByName(lustre, lmv_name, "lmv")
1490 error("can't find LMV '" + lmv_name + "'")
1492 md_tgt.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1493 md_tgt.appendChild(gen.ref("client", uuid))
1495 # adding lovconfig and client to aware MD targets
1497 md_names = string.split(aware, ',');
1498 for md_name in md_names:
1500 md_tgt = findByName(lustre, md_name, "mds")
1502 md_tgt = findByName(lustre, md_name, "lmv")
1505 error("can't find '" + mds_name + "'")
1507 md_tgt.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1508 md_tgt.appendChild(gen.ref("client", uuid))
1510 lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
1511 lustre.appendChild(lovconfig)
1513 def add_default_lov(gen, lustre, mds_name, lov_name):
1514 """ create a default lov """
1516 stripe_sz = DEFAULT_STRIPE_SZ
1517 stripe_cnt = DEFAULT_STRIPE_CNT
1518 pattern = DEFAULT_STRIPE_PATTERN
1519 uuid = new_uuid(lov_name)
1521 ret = findByName(lustre, lov_name, "lov")
1523 error("LOV: ", lov_name, " already exists.")
1525 mds_uuid = name2uuid(lustre, mds_name, 'mds')
1526 lov = gen.lov(lov_name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
1527 lustre.appendChild(lov)
1529 # add an lovconfig entry to the active mdsdev profile
1530 lovconfig_name = new_name('LVCFG_' + lov_name)
1531 lovconfig_uuid = new_uuid(lovconfig_name)
1532 mds = findByName(lustre, mds_name)
1533 mds.appendChild(gen.ref("lovconfig", lovconfig_uuid))
1534 lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
1535 lustre.appendChild(lovconfig)
1537 def add_lmv(gen, lustre, options):
1538 """ create a lmv """
1540 lmv_orig = get_option(options, 'lmv')
1541 name = new_name(lmv_orig)
1542 if name != lmv_orig:
1543 warning("name:", lmv_orig, "already used. using:", name)
1545 uuid = new_uuid(name)
1546 ret = findByName(lustre, name, "lmv")
1548 error("LMV: ", name, " already exists.")
1550 lmv = gen.lmv(name, uuid)
1551 lustre.appendChild(lmv)
1553 def new_filesystem(gen, lustre, fs_name, mds_uuid, obd_uuid,
1554 mgmt_uuid, gks_uuid):
1555 fs_uuid = new_uuid(fs_name)
1556 fs = gen.filesystem(fs_name, fs_uuid, mds_uuid, obd_uuid,
1557 mgmt_uuid, gks_uuid)
1558 lustre.appendChild(fs)
1561 def get_fs_uuid(gen, lustre, fs_name, mds_name, obd_name,
1562 mgmt_name, gks_name):
1563 mds_uuid = name2uuid(lustre, mds_name, tag='mds', fatal=0)
1565 mds_uuid = name2uuid(lustre, mds_name, tag='lmv', fatal=0)
1567 mds_uuid = name2uuid(lustre, mds_name, tag='cobd', fatal=0)
1569 error("mds '" + mds_name + "' is not found")
1571 obd_uuid = name2uuid(lustre, obd_name, tag='ost', fatal=0)
1573 obd_uuid = name2uuid(lustre, obd_name, tag='lov', fatal=0)
1575 obd_uuid = name2uuid(lustre, obd_name, tag='cobd', fatal=0)
1577 error("ost '" + obd_name + "' is not found")
1580 mgmt_uuid = name2uuid(lustre, mgmt_name, tag='mgmt', fatal=1)
1585 gks_uuid = name2uuid(lustre, gks_name, tag='gks', fatal=1)
1589 fs_uuid = lookup_filesystem(lustre, fs_name)
1591 fs = lookup(lustre, fs_uuid)
1592 if not ref_exists(fs, mds_uuid):
1593 fs.appendChild(gen.ref("mds", mds_uuid))
1594 if not ref_exists(fs, obd_uuid):
1595 fs.appendChild(gen.ref("obd", obd_uuid))
1596 if gks_uuid and not ref_exists(fs, gks_uuid):
1597 fs.appendChild(gen.ref("gks", gks_uuid))
1599 fs_uuid = new_filesystem(gen, lustre, fs_name,
1601 mgmt_uuid, gks_uuid)
1604 def add_filesystem(gen, lustre, options):
1605 """ create filesytem """
1606 fs_orig = get_option(options, 'filesystem')
1607 name = new_name(fs_orig)
1609 warning("name:", fs_orig, "already used. using:", name)
1611 uuid = new_uuid(name)
1612 ret = findByName(lustre, name, "filesystem")
1614 error("FS: ", name, " already exists.")
1616 gks_name = get_option(options, 'gks')
1618 gks_uuid = name2uuid(lustre, gks_name, tag='gks', fatal=1)
1621 fs = gen.filesystem(name, uuid, "", "", "", gks_uuid)
1622 lustre.appendChild(fs)
1624 def add_mtpt(gen, lustre, options):
1625 """ create mtpt on a node """
1626 node_name = get_option(options, 'node')
1628 path = get_option(options, 'path')
1629 clientoptions = get_option(options, "clientoptions")
1630 mds_sec = get_option(options, "mds_sec")
1631 oss_sec = get_option(options, "oss_sec")
1632 fs_name = get_option(options, 'filesystem')
1634 lov_name = get_option(options, 'lov')
1635 ost_name = get_option(options, 'ost')
1636 mds_name = get_option(options, 'mds')
1637 gks_name = get_option(options, 'gks')
1639 mds_name = get_option(options, 'lmv')
1641 error("--add mtpt requires either --mds or --lmv.")
1644 error("--add mtpt requires --lov lov_name or --ost ost_name")
1646 warning("use default value for lov, due no --lov lov_name provided")
1647 lov_name = new_name("lov_default")
1648 add_default_lov(gen, lustre, mds_name, lov_name)
1649 ost_uuid = name2uuid(lustre, ost_name, 'ost', fatal=0)
1651 error('add_mtpt:', '"'+ost_name+'"', "ost element not found.")
1652 lov = findByName(lustre, lov_name, "lov")
1653 lov_add_osc(gen, lustre, lov, ost_uuid, options)
1656 fs_name = new_name("FS_fsname")
1657 mgmt_name = get_option(options, 'mgmt')
1661 fs_uuid = get_fs_uuid(gen, lustre, fs_name,
1662 mds_name, lov_name, mgmt_name, gks_name)
1664 name = new_name('MNT_'+ node_name)
1666 ret = findByName(lustre, name, "mountpoint")
1668 # this can't happen, because new_name creates unique names
1669 error("MOUNTPOINT: ", name, " already exists.")
1671 uuid = new_uuid(name)
1672 mtpt = gen.mountpoint(name, uuid, fs_uuid, path,
1673 clientoptions, mds_sec, oss_sec)
1674 node = findByName(lustre, node_name, "node")
1676 error('node:', node_name, "not found.")
1677 node_add_profile(gen, node, "mountpoint", uuid)
1678 lustre.appendChild(mtpt)
1680 def commit_version(gen, lustre):
1681 update = findLastUpdate(lustre)
1683 version = int(update.getAttribute("version")) + 1
1687 new = gen.update(str(version))
1688 lustre.appendChild(new)
1691 ############################################################
1692 # Command line processing
1694 class OptionError (exceptions.Exception):
1695 def __init__(self, args):
1698 def get_option(options, tag):
1699 """Look for tag in options hash and return the value if set. If not
1700 set, then if return default it is set, otherwise exception."""
1701 if options.__getattr__(tag) != None:
1702 return options.__getattr__(tag)
1704 raise OptionError("--add %s requires --%s <value>" % (options.add, tag))
1706 def get_option_int(options, tag):
1707 """Return an integer option. Raise exception if the value is not an int"""
1708 val = get_option(options, tag)
1712 raise OptionError("--%s <num> (value must be integer)" % (tag))
1715 # simple class for profiling
1722 self._start = time.time()
1723 def stop(self, msg=''):
1724 self._stop = time.time()
1728 return self._stop - self._start
1729 def display(self, msg):
1731 str = '%s: %g secs' % (msg, d)
1734 #################################################################
1735 # function cmdlinesplit used to split cmd line from batch file
1737 def cmdlinesplit(cmdline):
1739 double_quote = re.compile(r'"(([^"\\]|\\.)*)"')
1740 single_quote = re.compile(r"'(.*?)'")
1741 escaped = re.compile(r'\\(.)')
1742 esc_quote = re.compile(r'\\([\\"])')
1743 outside = re.compile(r"""([^\s\\'"]+)""") #" fucking emacs.
1747 while i < len(cmdline):
1750 match = double_quote.match(cmdline, i)
1752 print "Unmatched double quote:", cmdline
1755 if arg is None: arg = esc_quote.sub(r'\1', match.group(1))
1756 else: arg = arg + esc_quote.sub(r'\1', match.group(1))
1759 match = single_quote.match(cmdline, i)
1761 print "Unmatched single quote:", cmdline
1764 if arg is None: arg = match.group(1)
1765 else: arg = arg + match.group(1)
1768 match = escaped.match(cmdline, i)
1770 print "Unmatched backslash", cmdline
1773 if arg is None: arg = match.group(1)
1774 else: arg = arg + match.group(1)
1776 elif c in string.whitespace:
1778 arg_list.append(str(arg))
1780 while i < len(cmdline) and cmdline[i] in string.whitespace:
1783 match = outside.match(cmdline, i)
1786 if arg is None: arg = match.group()
1787 else: arg = arg + match.group()
1789 if arg != None: arg_list.append(str(arg))
1793 ############################################################
1797 def add(devtype, gen, lustre, options):
1798 if devtype == 'net':
1799 add_net(gen, lustre, options)
1800 elif devtype == 'mtpt':
1801 add_mtpt(gen, lustre, options)
1802 elif devtype == 'mds':
1803 add_mds(gen, lustre, options)
1804 elif devtype == 'ost':
1805 add_ost(gen, lustre, options)
1806 elif devtype == 'lov':
1807 add_lov(gen, lustre, options)
1808 elif devtype == 'route':
1809 add_route(gen, lustre, options)
1810 elif devtype == 'node':
1811 add_node(gen, lustre, options)
1812 elif devtype == 'echo_client':
1813 add_echo_client(gen, lustre, options)
1814 elif devtype == 'cobd':
1815 add_cobd(gen, lustre, options)
1816 elif devtype == 'cmobd':
1817 add_cmobd(gen, lustre, options)
1818 elif devtype == 'mgmt':
1819 add_mgmt(gen, lustre, options)
1820 elif devtype == 'lmv':
1821 add_lmv(gen, lustre, options)
1822 elif devtype == 'filesystem':
1823 add_filesystem(gen, lustre, options)
1824 elif devtype == 'gks':
1825 add_gks(gen, lustre, options)
1827 error("unknown device type:", devtype)
1829 def delete(devtype, gen, lustre, options):
1830 if devtype == 'ost':
1831 del_ost(gen, lustre, options)
1832 elif options.delete:
1833 error("delete not supported for device type:", devtype)
1834 elif options.deactivate:
1835 error("deactivate not supported for device type:", devtype)
1837 error("in delete(), but neither .delete nor .deactivate are set. Tell CFS.")
1839 def commit(gen, lustre):
1840 commit_version(gen, lustre)
1842 def do_command(gen, lustre, options, args):
1844 add(options.add, gen, lustre, options)
1845 elif options.delete:
1846 delete(options.delete, gen, lustre, options)
1847 elif options.deactivate:
1848 delete(options.deactivate, gen, lustre, options)
1849 elif options.commit:
1852 error("Missing command")
1855 cl = Lustre.Options("lmc", "", lmc_options)
1857 options, args = cl.parse(sys.argv[1:])
1858 except Lustre.OptionError, e:
1862 panic(string.join(sys.argv), "Unexpected extra arguments on command line: " + string.join(args))
1864 if options.reference:
1871 outFile = options.merge
1872 if os.access(outFile, os.R_OK):
1873 doc = xml.dom.minidom.parse(outFile)
1875 doc = new_lustre(xml.dom.minidom)
1877 doc = xml.dom.minidom.parse(options.input)
1879 doc = new_lustre(xml.dom.minidom)
1882 outFile = options.output
1884 lustre = doc.documentElement
1886 if lustre.tagName != "lustre":
1887 print "Existing config not valid."
1890 gen = GenConfig(doc)
1893 fp = open(options.batch)
1894 batchCommands = fp.readlines()
1896 for cmd in batchCommands:
1898 options, args = cl.parse(cmdlinesplit(cmd))
1899 if options.merge or options.input or options.output:
1900 print "The batchfile should not contain --merge, --input or --output."
1902 do_command(gen, lustre, options, args)
1903 except OptionError, e:
1905 except Lustre.OptionError, e:
1909 do_command(gen, lustre, options, args)
1910 except OptionError, e:
1911 panic(string.join(sys.argv),e)
1912 except Lustre.OptionError, e:
1918 printDoc(doc, open(outFile,"w"))
1920 if __name__ == "__main__":