Whamcloud - gitweb
Add note to --format help that the autoformat feature is currently disabled
[fs/lustre-release.git] / lustre / utils / lmc
1 #!/usr/bin/env python
2 # Copyright (C) 2002 Cluster File Systems, Inc.
3 # Author: Robert Read <rread@clusterfs.com>
4
5 #   This file is part of Lustre, http://www.lustre.org.
6 #
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.
10 #
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.
15 #
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.
19 #
20
21 """
22 lmc - lustre configurtion data  manager
23  
24  Basic plan for lmc usage:
25 # create nodes
26 ./lmc --output config.xml --node server --net server1 tcp 
27 ./lmc --merge config.xml  --node client --net client1 tcp
28 ./lmc --merge config.xml  --node client --route gw lo [hi]
29 ./lmc --merge config.xml --router --node gw1 --net gw1 tcp
30 ./lmc --merge config.xml --node gw1 --net 1 elan
31
32 ./lmc --merge config.xml --route elan 1 1 100
33 ./lmc --merge config.xml --route tcp gw1 ba1
34
35
36
37 # configure server
38 ./lmc --merge config.xml  --node server --mds mds1 /tmp/mds1 50000
39
40 # create lov
41 ./lmc --merge config.xml  --lov lov1 mds1 65536 0 0
42 ./lmc --merge config.xml  --node server --lov lov1 --ost /tmp/ost1 100000
43 ./lmc --merge config.xml  --node server --lov lov1 --ost /tmp/ost2 100000
44
45 # create client config
46 ./lmc --merge config.xml  --node client --mtpt /mnt/lustre mds1 lov1
47
48 """
49
50 import sys, os, getopt, string
51 import xml.dom.minidom
52 from xml.dom.ext import PrettyPrint
53
54
55 DEFAULT_PORT = 988 # XXX What is the right default acceptor port to use?
56
57 def usage():
58     print """usage: lmc [--node --ost | --mtpt | --lov] args
59 Commands:
60 --node node_name 
61    Node_name by itself it will create a new node. If the --router
62    option is used when creating a new node, then that node will also
63    be configured as a router. When used with other commands it
64    specifies the node to modify.
65
66 --net hostname nettype [port, recv_buf, send_buf]
67    Nettype is either tcp, elan, or gm.
68    Requires --node
69
70 --route net gw lo [hi]
71    This command is used to create  routes.  NET is the
72    network type this route will be used on.  The GW is an address of
73    one of the local interfaces. LO and HI represent a range of
74    addresses that can be reached through the gateway. If HI is not
75    set, then a route to the specific host in LO is created.
76
77 --mds device [size]
78    Create a MDS using the device
79    Requires --node 
80
81 --lov lov_name [mdc_name stripe_sz stripe_off pattern]
82    Creates a logical volume
83    When used with other commands, it specifics the lov to modify
84
85 --mdc mdc_name
86    Configures a MDC for a node.
87    Requires --node 
88
89 --ost device [size]
90    Creates an OBD/OST/OSC configuration triplet for a new device.
91    When used on "host", the device will be initialized and the OST
92    will be enabled. On client nodes, the OSC will be avaiable.
93    Requires --node
94    If --lov lov_name is used, this device is added to lov. 
95
96 --mtpt /mnt/point mds_name lov_name|osc_name 
97    Creates a client mount point.
98    Requires --node
99
100 Options:
101 --merge="xml file"  Add the new objects to an existing file
102 --format            Format the partitions if unformated
103                     NB: The autoformat option has been disabled until a safe
104                     method is implemented to determine if a block device has a
105                     filesystem.
106 --reformat          Reformat partitions (this should be an lconf arg,
107                     I think)
108 --obdtype="obdtype" Specifiy obdtype: valid ones are obdecho and obdfilter.
109                     This is only useful for the --ost command.
110                     The device parameters are ignored for the obdecho type.
111 """
112     sys.exit(1)
113
114 def error(*args):
115     msg = string.join(map(str,args))
116     print msg
117     sys.exit(1)
118     
119 #
120 # manage names and uuids
121 # need to initialize this by walking tree to ensure
122 # no duplicate names or uuids are created.
123 # this are just place holders for now.
124 # consider changing this to be like OBD-dev-host
125 def new_name(base):
126     ctr = 2
127     ret = base
128     while names.has_key(ret):
129         ret = "%s_%d" % (base, ctr)
130         ctr = 1 + ctr
131     names[ret] = 1
132     return ret
133
134 def new_uuid(name):
135     return "%s_UUID" % (name)
136
137 ldlm_name = 'ldlm'
138 ldlm_uuid = 'ldlm_UUID'
139 def new_lustre(dom):
140     """Create a new empty lustre document"""
141     # adding ldlm here is a bit of a hack, but one is enough.
142     str = """<lustre>
143     <ldlm name="%s" uuid="%s"/>
144     </lustre>""" % (ldlm_name, ldlm_uuid)
145     return dom.parseString(str)
146
147 names = {}
148 uuids = {}
149
150 def init_names(doc):
151     """initialize auto-name generation tables"""
152     global names, uuids
153     # get all elements that contain a name attribute
154     for n in doc.childNodes:
155         if n.nodeType == n.ELEMENT_NODE:
156             if getName(n):
157                 names[getName(n)] = 1
158                 uuids[getUUID(n)] = 1
159             init_names(n)
160
161 def get_format_flag(options):
162     if options.has_key('format'):
163         if options['format']:
164             return 'yes'
165     return 'no'
166
167 ############################################################
168 # Build config objects using DOM
169 #
170 class GenConfig:
171     doc = None
172     dom = None
173     def __init__(self, doc):
174         self.doc = doc
175
176     def ref(self, type, uuid):
177         """ generate <[type]_ref uuidref="[uuid]"/> """
178         tag = "%s_ref" % (type)
179         ref = self.doc.createElement(tag)
180         ref.setAttribute("uuidref", uuid)
181         return ref
182     
183     def newService(self, tag, name, uuid):
184         """ create a new  service elmement, which requires name and uuid attributes """
185         new = self.doc.createElement(tag)
186         new.setAttribute("name", name);
187         new.setAttribute("uuid", uuid);
188         return new
189     
190     def addText(self, node, str):
191         txt = self.doc.createTextNode(str)
192         node.appendChild(txt)
193
194     def addElement(self, node, tag, str=None):
195         """ create a new element and add it as a child to node. If str is passed,
196             a text node is created for the new element"""
197         new = self.doc.createElement(tag)
198         if str:
199             self.addText(new, str)
200         node.appendChild(new)
201         return new
202
203     def network(self, name, uuid, hostname, net, port=0, tcpbuf=0):
204         """create <network> node"""
205         network = self.newService("network", name, uuid)
206         network.setAttribute("type", net);
207         self.addElement(network, "server", hostname)
208         if port:
209             self.addElement(network, "port", "%d" %(port))
210         if tcpbuf:
211             self.addElement(network, "send_mem", "%d" %(tcpbuf))
212             self.addElement(network, "recv_mem", "%d" %(tcpbuf))
213             
214         return network
215
216     def route(self, net_type, gw, lo, hi):
217         """ create one entry for the route table """
218         ref = self.doc.createElement('route')
219         ref.setAttribute("type", net_type)
220         ref.setAttribute("gw", gw)
221         ref.setAttribute("lo", lo)
222         if hi:
223             ref.setAttribute("hi", hi)
224         return ref
225     
226     def node(self, name, uuid):
227         """ create a host """
228         node = self.newService("node", name, uuid)
229         self.addElement(node, 'profile')
230         return node
231
232     def ldlm(self, name, uuid):
233         """ create a ldlm """
234         ldlm = self.newService("ldlm", name, uuid)
235         return ldlm
236
237     def obd(self, name, uuid, fs, obdtype, devname, format, dev_size=0):
238         obd = self.newService("obd", name, uuid)
239         obd.setAttribute('type', obdtype)
240         if fs:
241             self.addElement(obd, "fstype", fs)
242         if devname:
243             dev = self.addElement(obd, "device", devname)
244             if (dev_size):
245                 dev.setAttribute("size", "%s" % (dev_size))
246             self.addElement(obd, "autoformat", format)
247         return obd
248
249     def osc(self, name, uuid, obd_uuid, net_uuid):
250         osc = self.newService("osc", name, uuid)
251         osc.appendChild(self.ref("ost", net_uuid))
252         osc.appendChild(self.ref("obd", obd_uuid))
253         return osc
254
255     def ost(self, name, uuid, obd_uuid, net_uuid):
256         ost = self.newService("ost", name, uuid)
257         ost.appendChild(self.ref("network", net_uuid))
258         ost.appendChild(self.ref("obd", obd_uuid))
259         return ost
260
261     def lov(self, name, uuid, mds_uuid, stripe_sz, stripe_off, pattern):
262         lov = self.newService("lov", name, uuid)
263         lov.appendChild(self.ref("mds", mds_uuid))
264         devs = self.addElement(lov, "devices" )
265         devs.setAttribute("stripesize", stripe_sz)
266         devs.setAttribute("stripeoffset", stripe_off)
267         devs.setAttribute("pattern", pattern)
268         return lov
269
270     def mds(self, name, uuid, fs, devname, format, net_uuid, node_uuid,
271             failover_uuid = "", dev_size=0 ):
272         mds = self.newService("mds", name, uuid)
273         self.addElement(mds, "fstype", fs)
274         dev = self.addElement(mds, "device", devname)
275         if dev_size:
276             dev.setAttribute("size", "%s" % (dev_size))
277         self.addElement(mds, "autoformat", format)
278         mds.appendChild(self.ref("network", net_uuid))
279         mds.appendChild(self.ref("node", node_uuid))
280         if failover_uuid:
281             mds.appendChild(self.ref("failover", failover_uuid))
282         return mds
283
284     def mdc(self, name, uuid, mds_uuid):
285         mdc = self.newService("mdc", name, uuid)
286         mdc.appendChild(self.ref("mds", mds_uuid))
287         return mdc
288
289     def mountpoint(self, name, uuid, mdc_uuid, osc_uuid, path):
290         mtpt = self.newService("mountpoint", name, uuid)
291         mtpt.appendChild(self.ref("mdc", mdc_uuid))
292         mtpt.appendChild(self.ref("osc", osc_uuid))
293         self.addElement(mtpt, "path", path)
294         return mtpt
295
296 ############################################################
297 # Utilities to query a DOM tree
298 # Using this functions we can treat use config information
299 # directly as a database.
300 def getName(n):
301     return n.getAttribute('name')
302
303 def getUUID(node):
304     return node.getAttribute('uuid')
305
306
307 def findByName(lustre, name, tag = ""):
308     for n in lustre.childNodes:
309         if n.nodeType == n.ELEMENT_NODE:
310             if tag and n.nodeName != tag:
311                 continue
312             if getName(n) == name:
313                 return n
314             else:
315                 n = findByName(n, name)
316                 if n: return n
317     return None
318
319
320 def lookup(node, uuid):
321     for n in node.childNodes:
322         if n.nodeType == n.ELEMENT_NODE:
323             if getUUID(n) == uuid:
324                 return n
325             else:
326                 n = lookup(n, uuid)
327                 if n: return n
328     return None
329             
330
331 def mds2node(lustre, mds_name):
332     """ Find the node a MDS is configured on """
333     mds = findByName(lustre, mds_name, 'mds')
334     ref = mds.getElementsByTagName('node_ref')
335     if not ref:
336         error("no node found for:", mds_name)
337     node_uuid = ref[0].getAttribute('uuidref')
338     node = lookup(lustre, node_uuid)
339     if not node:
340         error("no node found for :", mds_name)
341     return node
342
343
344 def name2uuid(lustre, name, tag="",  fatal=1):
345     ret = findByName(lustre, name, tag)
346     if not ret:
347         if fatal:
348             error('name2uuid:', name, "not found.")
349         else:
350             return ""
351     return getUUID(ret)
352     
353
354 # XXX: assumes only one network element per node. will fix this
355 # as soon as support for routers is added
356 def get_net_uuid(lustre, node_name):
357     """ get a network uuid for a node_name """
358     node = findByName(lustre, node_name, "node")
359     if not node:
360         error ("node not found:", node_name)
361     net = node.getElementsByTagName('network')
362     if net:
363         return getUUID(net[0])
364     return None
365
366
367 def lov_add_osc(gen, lov, osc_uuid):
368     devs = lov.getElementsByTagName('devices')
369     if len(devs) == 1:
370         devs[0].appendChild(gen.ref("osc", osc_uuid))
371     else:
372         error("No devices element found for LOV:", lov)
373
374                             
375 def node_add_profile(gen, node, ref, uuid):
376     ret = node.getElementsByTagName('profile')
377     if not ret:
378         error('node has no profile:', node)
379     ret[0].appendChild(gen.ref(ref, uuid))
380     
381 def get_attr(dom_node, attr, default=""):
382     v = dom_node.getAttribute(attr)
383     if v:
384         return v
385     return default
386
387 ############################################################
388 # Top level commands
389 #
390 def do_add_node(gen, lustre,  options, node_name):
391     uuid = new_uuid(node_name)
392     node = gen.node(node_name, uuid)
393     node_add_profile(gen, node, 'ldlm', ldlm_uuid)
394     if options.has_key('router'):
395         node.setAttribute('router', '1')
396     lustre.appendChild(node)
397     return node
398
399     
400 def add_node(gen, lustre, options, args):
401     """ create a node with a network config """
402     if len(args) > 1:
403         usage()
404
405     node_name = options['node']
406
407     ret = findByName(lustre, node_name, "node")
408     if ret:
409         print "Node:", node_name, "exists."
410         return
411     do_add_node(gen, lustre, options, node_name)
412
413
414 def add_net(gen, lustre, options, args):
415     """ create a node with a network config """
416     if len(args) < 2:
417         usage()
418
419     node_name = options['node']
420     nid = args[0]
421     net_type = args[1]
422     port = 0
423     tcpbuf = 0
424
425     if net_type == 'tcp':
426         if len(args) > 2:
427             port = int(args[2])
428         else:
429             port = DEFAULT_PORT
430         if options.has_key('tcpbuf'):
431             tcpbuf = int(options['tcpbuf'])
432     elif net_type in ('elan', 'gm'):
433         port = 0
434     else:
435         print "Unknown net_type: ", net_type
436         sys.exit(2)
437
438     ret = findByName(lustre, node_name, "node")
439     if not ret:
440         node = do_add_node(gen, lustre, options, node_name)
441     else:
442         node = ret
443     net_name = new_name('NET_'+ node_name +'_'+ net_type)
444     net_uuid = new_uuid(net_name)
445     node.appendChild(gen.network(net_name, net_uuid, nid, net_type, port, tcpbuf))
446     node_add_profile(gen, node, "network", net_uuid)
447
448
449 def add_route(gen, lustre, options, args):
450     """ create a node with a network config """
451     if len(args) < 3:
452         usage()
453
454     node_name = options['node']
455     net_type= args[0]
456     gw = args[1]
457     lo = args[2]
458     hi = ''
459
460     if len(args) > 3:
461         hi = args[3]
462
463     node = findByName(lustre, node_name, "node")
464     if not node:
465         error (node_name, " not found.")
466     
467     netlist = node.getElementsByTagName('network')
468     net = netlist[0]
469     rlist = net.getElementsByTagName('route_tbl')
470     if len(rlist) > 0:
471         rtbl = rlist[0]
472     else:
473         rtbl = gen.addElement(net, 'route_tbl')
474     rtbl.appendChild(gen.route(net_type, gw, lo, hi))
475
476
477 def add_mds(gen, lustre, options, args):
478     if len(args) < 1:
479         usage()
480
481     if options.has_key('node'):
482         node_name = options['node']
483     else:
484         error("--mds requires a --node argument")
485
486     mds_name = new_name(options['mds'])
487     devname = args[0]
488     if len(args) > 1:
489         size = args[1]
490     else:
491         size = 0
492
493     mdc_name = 'MDC_' + mds_name
494     mds_uuid = new_uuid(mds_name)
495     mdc_uuid = new_uuid(mdc_name)
496
497     node_uuid = name2uuid(lustre, node_name)
498
499     node = findByName(lustre, node_name, "node")
500     node_add_profile(gen, node, "mds", mds_uuid)
501     net_uuid = get_net_uuid(lustre, node_name)
502     if not net_uuid:
503         error("NODE: ", node_name, "not found")
504
505
506     mds = gen.mds(mds_name, mds_uuid, "extN", devname, get_format_flag(options),
507                   net_uuid, node_uuid, dev_size=size)
508     mdc = gen.mdc(mdc_name, mdc_uuid, mds_uuid)
509     lustre.appendChild(mds)
510     lustre.appendChild(mdc)
511                    
512
513 def add_mdc(gen, lustre, options, args):
514     """ create mtpt on a node """
515     if len(args) < 1:
516         usage()
517
518     if options.has_key('node'):
519         node_name = options['node']
520     else:
521         error("--mdc requires a --node argument")
522
523     mdc_name = args[0]
524     mdc_uuid = name2uuid(lustre, mdc_name)
525
526     node = findByName(lustre, node_name, "node")
527     if not node:
528             error('node:',  node_name, "not found.")
529     node_add_profile(gen, node, "mdc", mdc_uuid)
530
531
532 def add_ost(gen, lustre, options, args):
533     lovname = ''
534     obdtype = 'obdfilter'
535     devname = ''
536     size = 0
537     fstype = 'extN'
538     
539     if options.has_key('node'):
540         node_name = options['node']
541     else:
542         error("--ost requires a --node argument")
543
544     if options.has_key('lov'):
545         lovname = options['lov']
546
547     if options.has_key('obdtype'):
548         obdtype = options['obdtype']
549
550     if obdtype == 'obdecho':
551         fstype = ''
552     else:
553         if len(args) < 1:
554             usage()
555         devname = args[0]
556         if len(args) > 1:
557             size = args[1]
558         
559     obdname = new_name('OBD_'+ node_name)
560     oscname = new_name('OSC_'+ node_name)
561     ostname = new_name('OST_'+ node_name)
562     obd_uuid = new_uuid(obdname)
563     ost_uuid = new_uuid(ostname)
564     osc_uuid = new_uuid(oscname)
565
566     net_uuid = get_net_uuid(lustre, node_name)
567     if not net_uuid:
568         error("NODE: ", node_name, "not found")
569     
570     obd = gen.obd(obdname, obd_uuid, fstype, obdtype, devname, get_format_flag(options), size)
571     ost = gen.ost(ostname, ost_uuid, obd_uuid, net_uuid)
572     osc = gen.osc(oscname, osc_uuid, obd_uuid, ost_uuid)
573     
574     if lovname:
575         lov = findByName(lustre, lovname, "lov")
576         if not lov:
577             error("LOV:", lovname, "not found.")
578         lov_add_osc(gen, lov, osc_uuid)
579
580     node = findByName(lustre, node_name, "node")
581     node_add_profile(gen, node, 'obd', obd_uuid)
582     node_add_profile(gen, node, 'ost', ost_uuid)
583
584     lustre.appendChild(obd)
585     lustre.appendChild(osc)
586     lustre.appendChild(ost)
587
588                    
589 # this is generally only used by llecho.sh
590 def add_osc(gen, lustre, options, args):
591     """ add the osc to the profile for this node. """
592     if len(args) < 1:
593         usage()
594     osc_name = args[0]
595     if options.has_key('node'):
596         node_name = options['node']
597     else:
598         error("--osc requires a --node argument")
599     osc_uuid = name2uuid(lustre, osc_name)
600     node = findByName(lustre, node_name, "node")
601     node_add_profile(gen, node, 'osc', osc_uuid)
602
603
604 def add_lov(gen, lustre, options, args):
605     """ create a lov """
606     if len(args) < 4:
607         usage()
608
609     name = options['lov']
610     mds_name = args[0]
611     stripe_sz = args[1]
612     stripe_off = args[2]
613     pattern = args[3]
614     uuid = new_uuid(name)
615
616     ret = findByName(lustre, name, "lov")
617     if ret:
618         error("LOV: ", name, " already exists.")
619
620     mds_uuid = name2uuid(lustre, mds_name)
621
622     node = mds2node(lustre, mds_name)
623     node_add_profile(gen, node, "lov", uuid)
624     lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_off, pattern)
625     lustre.appendChild(lov)
626
627
628 def add_mtpt(gen, lustre, options, args):
629     """ create mtpt on a node """
630     if len(args) < 3:
631         usage()
632
633     if options.has_key('node'):
634         node_name = options['node']
635     else:
636         error("--mtpt requires a --node argument")
637
638     path = args[0]
639     mds_name = args[1]
640     lov_name = args[2]
641     mdc_name = 'MDC_' + mds_name
642
643     name = new_name('MNT_'+ node_name)
644
645     ret = findByName(lustre, name, "mountpoint")
646     if ret:
647         error("MOUNTPOINT: ", name, " already exists.")
648
649     mdc_uuid = name2uuid(lustre, mdc_name)
650     lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
651     if not lov_uuid:
652         lov_uuid = name2uuid(lustre, lov_name, tag='osc', fatal=1)
653
654     uuid = new_uuid(name)
655     mtpt = gen.mountpoint(name, uuid, mdc_uuid, lov_uuid, path)
656     node = findByName(lustre, node_name, "node")
657     if not node:
658             error('node:',  node_name, "not found.")
659     node_add_profile(gen, node, "mountpoint", uuid)
660     node_add_profile(gen, node, "mdc", mdc_uuid)
661     lustre.appendChild(mtpt)
662
663
664 ############################################################
665 # Command line processing
666 #
667 def parse_cmdline(argv):
668     short_opts = "ho:i:m:"
669     long_opts = ["ost", "osc", "mtpt", "lov=", "node=", "mds=", "net", "tcpbuf=",
670                  "mdc", "route", "router", "merge=", "format", "reformat", "output=",
671                  "obdtype=", "in=", "help"]
672     opts = []
673     args = []
674     options = {}
675     try:
676         opts, args = getopt.getopt(argv, short_opts, long_opts)
677     except getopt.error:
678         print "invalid opt"
679         usage()
680
681     for o, a in opts:
682         if o in ("-h", "--help"):
683             usage()
684         if o in ("-o", "--output"):
685             options['output'] = a
686         if o == "--ost":
687             options['ost'] = 1
688         if o == "--osc":
689             options['osc'] = 1
690         if o == "--mds":
691             options['mds'] = a
692         if o == "--mdc":
693             options['mdc'] = 1
694         if o == "--net":
695             options['net'] = 1
696         if o == "--mtpt":
697             options['mtpt'] = 1
698         if o == "--node":
699             options['node'] = a
700         if o == "--route":
701             options['route'] = 1
702         if o == "--router":
703             options['router'] = 1
704         if o == "--lov":
705             options['lov'] = a
706         if o in ("-m", "--merge"):
707             options['merge'] = a
708         if o == "--obdtype":
709             options['obdtype'] = a
710         if o == "--tcpbuf":
711             options['tcpbuf'] = a
712         if o == "--format":
713             options['format'] = 1
714         if o  == "--reformat":
715             options['reformat'] = 1
716         if o  in ("--in" , "-i"):
717             options['in'] = a
718             
719     return options, args
720
721
722 # simple class for profiling
723 import time
724 class chrono:
725     def __init__(self):
726         self._start = 0
727     def start(self):
728         self._stop = 0
729         self._start = time.time()
730     def stop(self, msg=''):
731         self._stop = time.time()
732         if msg:
733             self.display(msg)
734     def dur(self):
735         return self._stop - self._start
736     def display(self, msg):
737         d = self.dur()
738         str = '%s: %g secs' % (msg, d)
739         print str
740
741 ############################################################
742 # Main
743 #
744 def main():
745     options, args = parse_cmdline(sys.argv[1:])
746     outFile = '-'
747
748     if options.has_key('merge'):
749         outFile = options['merge']
750         if os.access(outFile, os.R_OK):
751             doc = xml.dom.minidom.parse(outFile)
752         else:
753             doc = new_lustre(xml.dom.minidom)
754     elif options.has_key('in'):
755         doc = xml.dom.minidom.parse(options['in'])
756     else:
757         doc = new_lustre(xml.dom.minidom)
758
759     if options.has_key('output'):
760         outFile = options['output']
761
762     lustre = doc.documentElement
763     init_names(lustre)
764     if lustre.tagName != "lustre":
765         print "Existing config not valid."
766         sys.exit(1)
767
768     gen = GenConfig(doc)
769     if options.has_key('ost'):
770         add_ost(gen, lustre, options, args)
771     elif options.has_key('osc'):
772         add_osc(gen, lustre, options, args)
773     elif options.has_key('mtpt'):
774         add_mtpt(gen, lustre, options, args)
775     elif options.has_key('mds'):
776         add_mds(gen, lustre, options, args)
777     elif options.has_key('mdc'):
778         add_mdc(gen, lustre, options, args)
779     elif options.has_key('net'):
780         add_net(gen, lustre, options, args)
781     elif options.has_key('lov'):
782         add_lov(gen, lustre, options, args)
783     elif options.has_key('route'):
784         add_route(gen, lustre, options, args)
785     elif options.has_key('node'):
786         add_node(gen, lustre, options, args)
787     else:
788         print "Missing command"
789         usage()
790
791     if outFile == '-':
792         PrettyPrint(doc)
793     else:
794         PrettyPrint(doc, open(outFile,"w"))
795
796 if __name__ == "__main__":
797     main()
798
799