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