Whamcloud - gitweb
revert configure.in
[fs/lustre-release.git] / lustre / utils / lconf
1 #!/usr/bin/env python
2 #
3 #  Copyright (C) 2002 Cluster File Systems, Inc.
4 #   Author: Robert Read <rread@clusterfs.com>
5
6 #   This file is part of Lustre, http://www.lustre.org.
7 #
8 #   Lustre is free software; you can redistribute it and/or
9 #   modify it under the terms of version 2 of the GNU General Public
10 #   License as published by the Free Software Foundation.
11 #
12 #   Lustre is distributed in the hope that it will be useful,
13 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #   GNU General Public License for more details.
16 #
17 #   You should have received a copy of the GNU General Public License
18 #   along with Lustre; if not, write to the Free Software
19 #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #
21 # lconf - lustre configuration tool
22 #
23 # lconf is the main driver script for starting and stopping
24 # lustre filesystem services.
25 #
26 # Based in part on the XML obdctl modifications done by Brian Behlendorf 
27
28 import sys, getopt
29 import string, os, stat, popen2
30 import re, exceptions
31 import xml.dom.minidom
32
33 # Global parameters
34 TCP_ACCEPTOR = 'acceptor'
35 options = {}
36
37 #
38 # Maximum number of devices to search for.
39 # (the /dev/loop* nodes need to be created beforehand)
40 MAX_LOOP_DEVICES = 256
41
42
43 def usage():
44     print """usage: lconf config.xml
45
46 config.xml          Lustre configuration in xml format.
47 -v | --verbose      Print system commands as they are run
48 -d | --debug        Print system commands, but does not run them
49 --host <hostname>   Load config for <hostname>
50 --cleanup           Cleans up config. (Shutdown)
51 -h | --help         Print this help 
52 """
53     TODO = """
54 --ldap server       LDAP server with lustre config database
55 --reformat          Reformat all devices (will confirm)
56 --lustre="src dir"  Base directory of lustre sources. Used to search
57                     for modules.
58 --portals=src       Portals source 
59 --makeldiff         Translate xml source to LDIFF 
60 --iam myname        ??
61 """
62     sys.exit()
63
64 # ============================================================ 
65 # debugging and error funcs
66
67 def fixme(msg = "this feature"):
68     raise RuntimeError, msg + ' not implmemented yet.'
69
70 def panic(*args):
71     msg = string.join(map(str,args))
72     print msg
73     raise RuntimeError, msg
74
75 def log(*args):
76     msg = string.join(map(str,args))
77     print msg
78
79 def logall(msgs):
80     for s in msgs:
81         print string.strip(s)
82
83 def debug(*args):
84     msg = string.join(map(str,args))
85     if isverbose(): print msg
86
87 def isverbose():
88     return options.has_key('verbose') and  options['verbose'] == 1
89
90 def isnotouch():
91     return options.has_key('debug') and options['debug'] == 1
92
93 # ============================================================
94 # locally defined exceptions
95 class CommandError (exceptions.Exception):
96     def __init__(self, args=None):
97         self.args = args
98
99 # ============================================================
100 # handle lctl interface
101 class LCTLInterface:
102     """
103     Manage communication with lctl
104     """
105
106     def __init__(self, cmd):
107         """
108         Initialize close by finding the lctl binary.
109         """
110         syspath = string.split(os.environ['PATH'], ':')
111         syspath.insert(0, "../utils");
112         self.lctlcmd = None
113         for d in syspath:
114             lctl = os.path.join(d,cmd)
115             if os.access(lctl, os.X_OK):
116                 self.lctl = lctl
117                 break
118         if not self.lctl:
119             raise RuntimeError,  "unable to find lctl binary."
120             
121     def run(self, cmds):
122         """
123         run lctl
124         the cmds are written to stdin of lctl
125         lctl doesn't return errors when run in script mode, so
126         stderr is checked
127         should modify command line to accept multiple commands, or
128         create complex command line options
129         """
130         debug("+", self.lctl, cmds)
131         if isnotouch(): return ([], 0)
132         p = popen2.Popen3(self.lctl, 1)
133         p.tochild.write(cmds + "\n")
134         p.tochild.close()
135         out = p.fromchild.readlines()
136         ret = p.poll()
137         err = p.childerr.readlines()
138         if ret or len(err):
139             log (self.lctl, "error:", ret)
140             logall(err)
141             raise CommandError, err
142         return ret, out
143         
144         
145     # create a new device with lctl
146     def network(self, net, nid):
147         cmds =  """
148   network %s
149   mynid %s
150   quit""" % (net, nid)
151         self.run(cmds)
152
153     # create a new connection 
154     def connect(self, net, nid, port, servuuid):
155         cmds =  """
156   network %s
157   connect %s %d
158   add_uuid %s %s
159   quit""" % (net, nid, port,  servuuid, nid)
160         self.run(cmds)
161                 
162     # create a new device with lctl
163     def disconnect(self, net, nid, port, servuuid):
164         cmds =  """
165   network %s
166   disconnect %s 
167   quit""" % (net, nid)
168         self.run(cmds)
169
170     # create a new device with lctl
171     def newdev(self, attach, setup):
172         cmds = """
173   newdev
174   attach %s
175   setup %s
176   quit""" % (attach, setup)
177         self.run(cmds)
178
179     # cleanup a device
180     def cleanup(self, name, uuid):
181         cmds = """
182   device $%s
183   cleanup
184   detach
185   quit""" % (name)
186         self.run(cmds)
187
188     # create an lov
189     def lovconfig(self, uuid, mdcuuid, stripe_cnt, stripe_sz, pattern, devlist):
190         cmds = """
191   device $%s
192   probe
193   lovconfig %s %d %d %s %s
194   quit""" % (mdcuuid, uuid, stripe_cnt, stripe_sz, pattern, devlist)
195         self.run(cmds)
196
197 # ============================================================
198 # Various system-level functions
199 # (ideally moved to their own module)
200
201 # Run a command and return the output and status.
202 # stderr is sent to /dev/null, could use popen3 to
203 # save it if necessary
204 def run(*args):
205     cmd = string.join(map(str,args))
206     debug ("+", cmd)
207     if isnotouch(): return ([], 0)
208     f = os.popen(cmd + ' 2>&1')
209     out = f.readlines()
210     ret = f.close()
211     if ret:
212         ret = ret >> 8
213     else:
214         ret = 0
215     return (ret, out)
216
217
218 # is the path a block device?
219 def is_block(path):
220     s = ()
221     try:
222         s =  os.stat(path)
223     except OSError:
224         return 0
225     return stat.S_ISBLK(s[stat.ST_MODE])
226
227 # build fs according to type
228 # fixme: dangerous
229 def mkfs(fstype, dev):
230     if(fstype == 'ext3'):
231         mkfs = 'mkfs.ext2 -j'
232     elif (fstype == 'extN'):
233         mkfs = 'mkfs.ext2 -j'
234     else:
235         print 'unsupported fs type: ', fstype
236     if not is_block(dev):
237         force = '-F'
238     else:
239         force = ''
240     run (mkfs, force, dev)
241
242 # some systems use /dev/loopN, some /dev/loop/N
243 def loop_base():
244     import re
245     loop = '/dev/loop'
246     if not os.access(loop + str(0), os.R_OK):
247         loop = loop + '/'
248         if not os.access(loop + str(0), os.R_OK):
249             panic ("can't access loop devices")
250     return loop
251     
252 # find loop device assigned to thefile
253 def find_loop(file):
254     loop = loop_base()
255     for n in xrange(0, MAX_LOOP_DEVICES):
256         dev = loop + str(n)
257         if os.access(dev, os.R_OK):
258             (stat, out) = run('losetup', dev)
259             if (out and stat == 0):
260                 m = re.search(r'\((.*)\)', out[0])
261                 if m and file == m.group(1):
262                     return dev
263         else:
264             break
265     return ''
266
267 # create file if necessary and assign the first free loop device
268 def init_loop(file, size, fstype):
269     dev = find_loop(file)
270     if dev:
271         print 'WARNING file:', file, 'already mapped to', dev
272         return dev
273     if not os.access(file, os.R_OK | os.W_OK):
274         run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size,  file))
275     loop = loop_base()
276     # find next free loop
277     for n in xrange(0, MAX_LOOP_DEVICES):
278         dev = loop + str(n)
279         if os.access(dev, os.R_OK):
280             (stat, out) = run('losetup', dev)
281             if (stat):
282                 run('losetup', dev, file)
283                 return dev
284         else:
285             print "out of loop devices"
286             return ''
287     print "out of loop devices"
288     return ''
289
290 # undo loop assignment
291 def clean_loop(file):
292     dev = find_loop(file)
293     if dev:
294         ret, out = run('losetup -d', dev)
295         if ret:
296             log('unable to clean loop device:', dev, 'for file:', file)
297             logall(out)
298
299 # initialize a block device if needed
300 def block_dev(dev, size, fstype, format):
301     if isnotouch(): return dev
302     if not is_block(dev):
303         dev = init_loop(dev, size, fstype)
304     if (format == 'yes'):
305         mkfs(fstype, dev)
306     return dev
307
308 # ============================================================
309 # Functions to prepare the various objects
310
311 def prepare_ldlm(node):
312     (name, uuid) = getNodeAttr(node)
313     print 'LDLM:', name, uuid
314     lctl.newdev(attach="ldlm %s %s" % (name, uuid),
315                 setup ="")
316     
317 def prepare_lov(node):
318     (name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist, mdsname) = getLOVInfo(node)
319     print 'LOV:', name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist, mdsname
320     lctl.lovconfig(uuid, mdsname, stripe_cnt, strip_sz, pattern, devlist)
321     lctl.newdev(attach="lov %s %s" % (name, uuid),
322                 setup ="%s" % (mdcuuid))
323
324 def prepare_network(node):
325     (name, uuid, type, nid, port) = getNetworkInfo(node)
326     print 'NETWORK:', type, nid, port
327     if type == 'tcp':
328         run(TCP_ACCEPTOR, port)
329     lctl.network(type, nid)
330
331
332 # need to check /proc/mounts and /etc/mtab before
333 # formatting anything.
334 # FIXME: check if device is already formatted.
335 def prepare_obd(obd):
336     (name, uuid, obdtype, dev, size, fstype, format) = getOBDInfo(obd)
337     print "OBD: ", name, obdtype, dev, size, fstype, format
338     dev = block_dev(dev, size, fstype, format)
339     lctl.newdev(attach="%s %s %s" % (obdtype, name, uuid),
340                 setup ="%s %s" %(dev, fstype))
341     
342
343 def prepare_ost(ost):
344     name, uuid, obd = getOSTInfo(ost)
345     print "OST: ", name, uuid, obd
346     lctl.newdev(attach="ost %s %s" % (name, uuid),
347                 setup ="$%s" % (obd))
348
349 def prepare_mds(node):
350     (name, uuid, dev, size, fstype, format) = getMDSInfo(node)
351     print "MDS: ", name, dev, size, fstype
352     # setup network for mds, too
353     dev = block_dev(dev, size, fstype, format)
354     lctl.newdev(attach="mds %s %s" % (name, uuid),
355                 setup ="%s %s" %(dev, fstype))
356
357 def prepare_osc(node):
358     (name, uuid, obduuid, srvuuid) = getOSCInfo(node)
359     print 'OSC:', name, uuid, obduuid, srvuuid
360     net = lookup(node.parentNode, srvuuid)
361     srvname, srvuuid, net, server, port = getNetworkInfo(net)
362     lctl.connect(net, server, port, srvuuid)
363     lctl.newdev(attach="osc %s %s" % (name, uuid),
364                 setup ="%s %s" %(obduuid, srvuuid))
365
366 def prepare_mdc(node):
367     (name, uuid, mdsuuid, netuuid) = getMDCInfo(node)
368     print 'MDC:', name, uuid, mdsuuid, netuuid
369     lctl.newdev(attach="mdc %s %s" % (name, uuid),
370                 setup ="%s %s" %(mdsuuid, netuuid))
371
372 def prepare_mountpoint(node):
373     name, uuid, oscuuid, mdcuuid, mtpt = getMTPTInfo(node)
374     print 'MTPT:', name, uuid, oscuuid, mdcuuid, mtpt
375     cmd = "mount -t lustre_lite -o ost=%s,mds=%s none %s" % \
376           (oscuuid, mdcuuid, mtpt)
377     run("mkdir", mtpt)
378     run(cmd)
379 # ============================================================
380 # Functions to cleanup the various objects
381
382 def cleanup_ldlm(node):
383     (name, uuid) = getNodeAttr(node)
384     print 'LDLM:', name, uuid
385     try:
386         lctl.cleanup(name, uuid)
387     except CommandError:
388         print "cleanup failed: ", name
389
390 def cleanup_lov(node):
391     (name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist, mdsname) = getLOVInfo(node)
392     print 'LOV:', name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist, mdsname
393     try:
394         lctl.cleanup(name, uuid)
395     except CommandError:
396         print "cleanup failed: ", name
397
398 def cleanup_network(node):
399     (name, uuid, type, nid, port) = getNetworkInfo(node)
400     print 'NETWORK:', type, nid, port
401     #lctl.network(type, nid)
402
403 # need to check /proc/mounts and /etc/mtab before
404 # formatting anything.
405 # FIXME: check if device is already formatted.
406 def cleanup_obd(obd):
407     (name, uuid, obdtype, dev, size, fstype, format) = getOBDInfo(obd)
408     print "OBD: ", name, obdtype, dev, size, fstype, format
409     try:
410         lctl.cleanup(name, uuid)
411     except CommandError:
412         print "cleanup failed: ", name
413     clean_loop(dev)
414
415 def cleanup_ost(ost):
416     name, uuid, obd = getOSTInfo(ost)
417     print "OST: ", name, uuid, obd
418     try:
419         lctl.cleanup(name, uuid)
420     except CommandError:
421         print "cleanup failed: ", name
422
423 def cleanup_mds(node):
424     (name, uuid, dev, size, fstype, format) = getMDSInfo(node)
425     print "MDS: ", name, dev, size, fstype
426     try:
427         lctl.cleanup(name, uuid)
428     except CommandError:
429         print "cleanup failed: ", name
430     clean_loop(dev)
431         
432
433 def cleanup_mdc(node):
434     (name, uuid, mdsuuid, netuuid) = getMDCInfo(node)
435     print 'MDC:', name, uuid, mdsuuid, netuuid
436     try:
437         lctl.cleanup(name, uuid)
438     except CommandError:
439         print "cleanup failed: ", name
440
441
442 def cleanup_osc(node):
443     (name, uuid, obduuid, srvuuid) = getOSCInfo(node)
444     print 'OSC:', name, uuid, obduuid, srvuuid
445     net = lookup(node.parentNode, srvuuid)
446     netname, netuuid, net, server, port = getNetworkInfo(net)
447     try:
448         lctl.disconnect(net, server, port, srvuuid)
449         lctl.cleanup(name, uuid)
450     except CommandError:
451         print "cleanup failed: ", name
452
453 def cleanup_mountpoint(node):
454     name, uuid, oscuuid, mdcuuid, mtpt = getMTPTInfo(node)
455     print 'MTPT:', name, uuid, oscuuid, mdcuuid, mtpt
456     run("umount", mtpt)
457
458 # ============================================================
459 # XML processing and query
460
461 def getDevice(obd):
462     dev = obd.getElementsByTagName('device')[0]
463     dev.normalize();
464     try:
465         size = int(dev.getAttribute('size'))
466     except ValueError:
467         size = 0
468     return dev.firstChild.data, size
469     
470
471 def getNetworkInfo(node):
472     name, uuid = getNodeAttr(node);
473     type = node.getAttribute('type')
474     nid = getText(node, 'server', "")
475     port = int(getText(node, 'port', 0))
476     return name, uuid, type, nid, port
477     
478 # extract device attributes for an obd
479 def getNodeAttr(node):
480     name = node.getAttribute('name')
481     uuid = node.getAttribute('uuid')
482     return name, uuid
483
484 def getOBDInfo(obd):
485     name, uuid = getNodeAttr(obd);
486     obdtype = obd.getAttribute('type')
487     devname, size = getDevice(obd)
488     fstype = getText(obd, 'fstype')
489     format = getText(obd, 'autoformat')
490     return (name, uuid, obdtype, devname, size, fstype, format)
491     
492 # extract LOV
493 def getLOVInfo(node):
494     name, uuid = getNodeAttr(node)
495     devs = node.getElementsByTagName('devices')[0]
496     stripe_sz = int(devs.getAttribute('stripesize'))
497     pattern = int(devs.getAttribute('pattern'))
498     mdcref =  node.getElementsByTagName('mdc_ref')[0]
499     mdcuuid = mdcref.getAttribute('uuidref')
500     mdc= lookup(node.parentNode, mdcuuid)
501     mdsref =  mdc.getElementsByTagName('mds_ref')[0]
502     mdsuuid = mdsref.getAttribute('uuidref')
503     mds= lookup(node.parentNode, mdsuuid)
504     mdsname = getName(mds)
505     devlist = ""
506     stripe_cnt = 0
507     for child in devs.childNodes:
508         if child.nodeName == 'osc_ref':
509             devlist = devlist +  child.getAttribute('uuidref') + " "
510             strip_cnt = stripe_cnt + 1
511     return (name, uuid, mdcuuid, stripe_cnt, stripe_sz, pattern, devlist, mdsname)
512     
513 # extract device attributes for an obd
514 def getMDSInfo(node):
515     name, uuid = getNodeAttr(node)
516     devname, size = getDevice(node)
517     fstype = getText(node, 'fstype')
518     format = getText(node, 'autoformat', "no")
519     return (name, uuid, devname, size, fstype, format)
520
521 # extract device attributes for an obd
522 def getMDCInfo(node):
523     name, uuid = getNodeAttr(node)
524     ref = node.getElementsByTagName('mds_ref')[0]
525     mdsuuid = ref.getAttribute('uuidref')
526     ref = node.getElementsByTagName('network_ref')[0]
527     netuuid = ref.getAttribute('uuidref')
528     return (name, uuid, mdsuuid, netuuid)
529
530     
531 # extract device attributes for an obd
532 def getOSTInfo(node):
533     name, uuid = getNodeAttr(node)
534     ref = node.getElementsByTagName('obd_ref')[0]
535     uuid = ref.getAttribute('uuidref')
536     obd = lookup(node.parentNode, uuid)
537     if obd:
538          obdname = getOBDInfo(obd)[0]
539     else:
540         obdname = "OBD NOT FOUND"
541     return (name, uuid, obdname)
542
543 # extract device attributes for an obd
544 def getOSCInfo(node):
545     name, uuid = getNodeAttr(node)
546     ref = node.getElementsByTagName('obd_ref')[0]
547     obduuid = ref.getAttribute('uuidref')
548     ref = node.getElementsByTagName('network_ref')[0]
549     ostuuid = ref.getAttribute('uuidref')
550     return (name, uuid, obduuid, ostuuid)
551
552 # extract device attributes for an obd
553 def getMTPTInfo(node):
554     name, uuid = getNodeAttr(node)
555     path = getText(node, 'path')
556     ref = node.getElementsByTagName('mdc_ref')[0]
557     mdcuuid = ref.getAttribute('uuidref')
558     ref = node.getElementsByTagName('lov_ref')[0]
559     lovuuid = ref.getAttribute('uuidref')
560     return (name, uuid, lovuuid, mdcuuid, path)
561
562     
563 # Get the text content from the first matching child
564 def getText(node, tag, default=""):
565     list = node.getElementsByTagName(tag)
566     if len(list) > 0:
567         node = list[0]
568         node.normalize()
569         return node.firstChild.data
570     else:
571         return default
572
573 # Recusively search from node for a uuid
574 def lookup(node, uuid):
575     for n in node.childNodes:
576         # this service_id check is ugly. need some other way to
577         # differentiate between definitions and references
578         if n.nodeType == n.ELEMENT_NODE:
579             if getUUID(n) == uuid:
580                 return n
581             else:
582                 n = lookup(n, uuid)
583                 if n: return n
584     return None
585
586 # Get name attribute of node
587 def getName(node):
588     return node.getAttribute('name')
589
590 def getRef(node):
591     return node.getAttribute('uuidref')
592
593 # Get name attribute of node
594 def getUUID(node):
595     return node.getAttribute('uuid')
596
597 # the tag name is the service type
598 # fixme: this should do some checks to make sure the node is a service
599 def getServiceType(node):
600     return node.nodeName
601
602 #
603 # determine what "level" a particular node is at.
604 # the order of iniitailization is based on level.  objects
605 # are assigned a level based on type:
606 #  net,devices:1, obd, mdd:2  mds,ost:3 osc,mdc:4 mounts:5
607 def getServiceLevel(node):
608     type = getServiceType(node)
609     if type in ('network', 'device', 'ldlm'):
610         return 1
611     elif type in ('obd', 'mdd'):
612         return 2
613     elif type in ('mds','ost'):
614         return 3
615     elif type in ('mdc','osc'):
616         return 4
617     elif type in ('lov',):
618         return 5
619     elif type in ('mountpoint',):
620         return 6
621     return 0
622
623 #
624 # return list of services in a profile. list is a list of tuples
625 # [(level, node),]
626 def getServices(lustreNode, profileNode):
627     list = []
628     for n in profileNode.childNodes:
629         if n.nodeType == n.ELEMENT_NODE:
630             servNode = lookup(lustreNode, getRef(n))
631             if not servNode:
632                 panic('service not found: ' + getName(n))
633             level = getServiceLevel(servNode)
634             list.append((level, servNode))
635     list.sort()
636     return list
637
638 def getByName(lustreNode, tag, name):
639     ndList = lustreNode.getElementsByTagName(tag)
640     for nd in ndList:
641         if getName(nd) == name:
642             return nd
643     return None
644     
645
646 # ============================================================
647 # lconf type level logic
648 #
649
650 #
651 # Start a service.
652 def startService(node):
653     type = getServiceType(node)
654     debug('Starting service:', type, getName(node), getUUID(node))
655     # there must be a more dynamic way of doing this...
656     if type == 'ldlm':
657         prepare_ldlm(node)
658     elif type == 'lov':
659         prepare_lov(node)
660     elif type == 'network':
661         prepare_network(node)
662     elif type == 'obd':
663         prepare_obd(node)
664     elif type == 'ost':
665         prepare_ost(node)
666     elif type == 'mds':
667         prepare_mds(node)
668     elif type == 'osc':
669         prepare_osc(node)
670     elif type == 'mdc':
671         prepare_mdc(node)
672     elif type == 'mountpoint':
673         prepare_mountpoint(node)
674
675 #
676 # Prepare the system to run lustre using a particular profile
677 # in a the configuration. 
678 #  * load & the modules
679 #  * setup networking for the current node
680 #  * make sure partitions are in place and prepared
681 #  * initialize devices with lctl
682 # Levels is important, and needs to be enforced.
683 def startProfile(lustreNode, profileNode):
684     if not profileNode:
685         panic("profile:", profile, "not found.")
686     services = getServices(lustreNode, profileNode)
687     for s in services:
688         startService(s[1])
689
690
691 # Stop a service.
692 def stopService(node):
693     type = getServiceType(node)
694     debug('Stopping service:', type, getName(node), getUUID(node))
695     # there must be a more dynamic way of doing this...
696     if type == 'ldlm':
697         cleanup_ldlm(node)
698     elif type == 'lov':
699         cleanup_lov(node)
700     elif type == 'network':
701         cleanup_network(node)
702     elif type == 'obd':
703         cleanup_obd(node)
704     elif type == 'ost':
705         cleanup_ost(node)
706     elif type == 'mds':
707         cleanup_mds(node)
708     elif type == 'osc':
709         cleanup_osc(node)
710     elif type == 'mdc':
711         cleanup_mdc(node)
712     elif type == 'mountpoint':
713         cleanup_mountpoint(node)
714
715 # Shutdown services in reverse order than they were started
716 def cleanupProfile(lustreNode, profileNode):
717     if not profileNode:
718         panic("profile:", profile, "not found.")
719     services = getServices(lustreNode, profileNode)
720     services.reverse()
721     for s in services:
722         stopService(s[1])
723
724
725 #
726 # Load profile for 
727 def doHost(lustreNode, hosts, cleanFlag):
728     for h in hosts:
729         node = getByName(lustreNode, 'node', h)
730         if node:
731             break
732         
733     reflist = node.getElementsByTagName('profile_ref')
734     for r in reflist:
735         if cleanFlag:
736             cleanupProfile(lustreNode, lookup(lustreNode, getRef(r)))
737         else:
738             startProfile(lustreNode,  lookup(lustreNode, getRef(r)))
739
740 #
741 # Command line processing
742 #
743 def parse_cmdline(argv):
744     short_opts = "hdv"
745     long_opts = ["ldap", "reformat", "lustre=",
746                  "portals=", "makeldiff", "cleanup", "iam=",
747                  "help", "debug", "host="]
748     opts = []
749     args = []
750     global options
751     try:
752         opts, args = getopt.getopt(argv, short_opts, long_opts)
753     except getopt.GetoptError:
754         print "invalid opt"
755         usage()
756
757     for o, a in opts:
758         if o in ("-h", "--help"):
759             usage()
760         if o == "--cleanup":
761             options['cleanup'] = 1
762         if o in ("-v", "--verbose"):
763             options['verbose'] = 1
764         if o in ("-d", "--debug"):
765             options['debug'] = 1
766             options['verbose'] = 1
767         if o == "--portals":
768             options['portals'] = a
769         if o == "--lustre":
770             options['lustre'] = a
771         if o  == "--reformat":
772             options['reformat'] = 1
773         if o  == "--host":
774             options['hostname'] = [a]
775     return args
776
777 #
778 # Initialize or shutdown lustre according to a configuration file
779 #   * prepare the system for lustre
780 #   * configure devices with lctl
781 # Shutdown does steps in reverse
782 #
783 lctl = LCTLInterface('lctl')
784 def main():
785     global options
786     args = parse_cmdline(sys.argv[1:])
787     if len(args) > 0:
788         dom = xml.dom.minidom.parse(args[0])
789     else:
790         usage()
791
792     if not options.has_key('hostname'):
793         ret, host = run('hostname')
794         if ret:
795             print "unable to determine hostname"
796         else:
797             options['hostname'] = [host]
798         options['hostname'].append('localhost')
799     doHost(dom.childNodes[0], options['hostname'], options.has_key('cleanup') )
800
801 if __name__ == "__main__":
802     main()
803
804