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