Whamcloud - gitweb
3ea526559e6a404fcf1e96593e1be405b6b7973d
[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   See lustre book for documentation for lmc.
25
26 """
27
28 import sys, os, getopt, string, exceptions
29 import xml.dom.minidom
30 from xml.dom.ext import PrettyPrint
31
32 DEFAULT_PORT = 988 
33
34 def usage():
35     print """usage: lmc --add object [object parameters]
36
37 Object creation command summary:
38
39 --add node
40   --node node_name
41   --timeout num
42   --recovery_upcall path
43
44 --add net
45   --node node_name
46   --nid addr
47   --nettype tcp|elan|toe|gm
48   --port port
49   --tcpbuf size
50   --router
51
52 --add mds
53   --node node_name
54   --mds mds_name
55   --dev path
56   --size size
57
58 --add lov
59   --lov lov_name
60   --mds mds_name
61   --stripe_sz num
62   --stripe_cnt num
63   --stripe_pattern num
64
65 -add ost
66   --node node_name
67   --obd obd_name 
68   --lov lov_name 
69   --dev path
70   --size size
71   --obduuid uuid
72   
73 --add mtpt  - Mountpoint
74   --node node_name
75   --path /mnt/point
76   --mds mds_name
77   --obd obd_name OR --lov lovname
78 """
79     sys.exit(1)
80
81 def error(*args):
82     msg = string.join(map(str,args))
83     raise OptionError("Error: " +  msg)
84
85 def panic(cmd, msg):
86     print "! " + cmd
87     print msg
88     sys.exit(1)
89
90     
91 def warning(*args):
92     msg = string.join(map(str,args))
93     print "Warning: ", msg
94     
95 #
96 # manage names and uuids
97 # need to initialize this by walking tree to ensure
98 # no duplicate names or uuids are created.
99 # this are just place holders for now.
100 # consider changing this to be like OBD-dev-host
101 def new_name(base):
102     ctr = 2
103     ret = base
104     while names.has_key(ret):
105         ret = "%s_%d" % (base, ctr)
106         ctr = 1 + ctr
107     names[ret] = 1
108     return ret
109
110 def new_uuid(name):
111     return "%s_UUID" % (name)
112
113 ldlm_name = 'ldlm'
114 ldlm_uuid = 'ldlm_UUID'
115 def new_lustre(dom):
116     """Create a new empty lustre document"""
117     # adding ldlm here is a bit of a hack, but one is enough.
118     str = """<lustre>
119     <ldlm name="%s" uuid="%s"/>
120     </lustre>""" % (ldlm_name, ldlm_uuid)
121     return dom.parseString(str)
122
123 names = {}
124 uuids = {}
125
126 def init_names(doc):
127     """initialize auto-name generation tables"""
128     global names, uuids
129     # get all elements that contain a name attribute
130     for n in doc.childNodes:
131         if n.nodeType == n.ELEMENT_NODE:
132             if getName(n):
133                 names[getName(n)] = 1
134                 uuids[getUUID(n)] = 1
135             init_names(n)
136
137 def get_format_flag(options):
138     if options.has_key('format'):
139         if options['format']:
140             return 'yes'
141     return 'no'
142
143 ############################################################
144 # Build config objects using DOM
145 #
146 class GenConfig:
147     doc = None
148     dom = None
149     def __init__(self, doc):
150         self.doc = doc
151
152     def ref(self, type, uuid):
153         """ generate <[type]_ref uuidref="[uuid]"/> """
154         tag = "%s_ref" % (type)
155         ref = self.doc.createElement(tag)
156         ref.setAttribute("uuidref", uuid)
157         return ref
158     
159     def newService(self, tag, name, uuid):
160         """ create a new  service elmement, which requires name and uuid attributes """
161         new = self.doc.createElement(tag)
162         new.setAttribute("uuid", uuid);
163         new.setAttribute("name", name);
164         return new
165     
166     def addText(self, node, str):
167         txt = self.doc.createTextNode(str)
168         node.appendChild(txt)
169
170     def addElement(self, node, tag, str=None):
171         """ create a new element and add it as a child to node. If str is passed,
172             a text node is created for the new element"""
173         new = self.doc.createElement(tag)
174         if str:
175             self.addText(new, str)
176         node.appendChild(new)
177         return new
178
179     def network(self, name, uuid, hostname, net, port=0, tcpbuf=0):
180         """create <network> node"""
181         network = self.newService("network", name, uuid)
182         network.setAttribute("type", net);
183         self.addElement(network, "server", hostname)
184         if port:
185             self.addElement(network, "port", "%d" %(port))
186         if tcpbuf:
187             self.addElement(network, "send_mem", "%d" %(tcpbuf))
188             self.addElement(network, "recv_mem", "%d" %(tcpbuf))
189             
190         return network
191
192     def route(self, net_type, gw, lo, hi):
193         """ create one entry for the route table """
194         ref = self.doc.createElement('route')
195         ref.setAttribute("type", net_type)
196         ref.setAttribute("gw", gw)
197         ref.setAttribute("lo", lo)
198         if hi:
199             ref.setAttribute("hi", hi)
200         return ref
201     
202     def node(self, name, uuid):
203         """ create a host """
204         node = self.newService("node", name, uuid)
205         self.addElement(node, 'profile')
206         return node
207
208     def ldlm(self, name, uuid):
209         """ create a ldlm """
210         ldlm = self.newService("ldlm", name, uuid)
211         return ldlm
212
213     def obd(self, name, uuid, fs, obdtype, devname, format, ost_uuid, dev_size=0):
214         obd = self.newService("obd", name, uuid)
215         obd.setAttribute('type', obdtype)
216         self.addElement(obd, 'active_target', ost_uuid)
217         if fs:
218             self.addElement(obd, "fstype", fs)
219         if devname:
220             dev = self.addElement(obd, "device", devname)
221             if (dev_size):
222                 dev.setAttribute("size", "%s" % (dev_size))
223             self.addElement(obd, "autoformat", format)
224         return obd
225
226 #    def osc(self, name, uuid, obd_uuid, net_uuid):
227 #        osc = self.newService("osc", name, uuid)
228 #        osc.appendChild(self.ref("ost", net_uuid))
229 #        osc.appendChild(self.ref("obd", obd_uuid))
230 #        return osc
231
232     def cobd(self, name, uuid, real_uuid, cache_uuid):
233         cobd = self.newService("cobd", name, uuid)
234         cobd.appendChild(self.ref("real_obd",real_uuid))
235         cobd.appendChild(self.ref("cache_obd",cache_uuid))
236         return cobd
237
238     def ost(self, name, uuid, obd_uuid, net_uuid):
239         ost = self.newService("ost", name, uuid)
240         ost.appendChild(self.ref("network", net_uuid))
241         ost.appendChild(self.ref("obd", obd_uuid))
242         return ost
243
244     def lov(self, name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern):
245         lov = self.newService("lov", name, uuid)
246         lov.appendChild(self.ref("mds", mds_uuid))
247         devs = self.addElement(lov, "devices" )
248         devs.setAttribute("stripesize", stripe_sz)
249         devs.setAttribute("stripecount", stripe_cnt)
250         devs.setAttribute("pattern", pattern)
251         return lov
252
253     def lovconfig(self, name, uuid, lov_uuid):
254         lovconfig = self.newService("lovconfig", name, uuid)
255         lovconfig.appendChild(self.ref("lov", lov_uuid))
256         return lovconfig
257
258     def mds(self, name, uuid, fs, devname, format, net_uuid, node_uuid,
259             failover_uuid = "", dev_size=0 ):
260         mds = self.newService("mds", name, uuid)
261         self.addElement(mds, "fstype", fs)
262         dev = self.addElement(mds, "device", devname)
263         if dev_size:
264             dev.setAttribute("size", "%s" % (dev_size))
265         self.addElement(mds, "autoformat", format)
266         mds.appendChild(self.ref("network", net_uuid))
267         mds.appendChild(self.ref("node", node_uuid))
268         if failover_uuid:
269             mds.appendChild(self.ref("failover", failover_uuid))
270         return mds
271
272     def mountpoint(self, name, uuid, mds_uuid, osc_uuid, path):
273         mtpt = self.newService("mountpoint", name, uuid)
274         mtpt.appendChild(self.ref("mds", mds_uuid))
275         mtpt.appendChild(self.ref("obd", osc_uuid))
276         self.addElement(mtpt, "path", path)
277         return mtpt
278
279     def echo_client(self, name, uuid, osc_uuid):
280         ec = self.newService("echo_client", name, uuid)
281         ec.appendChild(self.ref("obd", osc_uuid))
282         return ec
283
284 ############################################################
285 # Utilities to query a DOM tree
286 # Using this functions we can treat use config information
287 # directly as a database.
288 def getName(n):
289     return n.getAttribute('name')
290
291 def getUUID(node):
292     return node.getAttribute('uuid')
293
294
295 def findByName(lustre, name, tag = ""):
296     for n in lustre.childNodes:
297         if n.nodeType == n.ELEMENT_NODE:
298             if tag and n.nodeName != tag:
299                 continue
300             if getName(n) == name:
301                 return n
302             else:
303                 n = findByName(n, name)
304                 if n: return n
305     return None
306
307
308 def lookup(node, uuid):
309     for n in node.childNodes:
310         if n.nodeType == n.ELEMENT_NODE:
311             if getUUID(n) == uuid:
312                 return n
313             else:
314                 n = lookup(n, uuid)
315                 if n: return n
316     return None
317             
318
319 def mds2node(lustre, mds_name):
320     """ Find the node a MDS is configured on """
321     mds = findByName(lustre, mds_name, 'mds')
322     ref = mds.getElementsByTagName('node_ref')
323     if not ref:
324         error("mds2node:", "no node_ref found for", '"'+mds_name+'"')
325     node_uuid = ref[0].getAttribute('uuidref')
326     node = lookup(lustre, node_uuid)
327     if not node:
328         error('mds2node:', "no node found for :", '"'+mds_name+'"')
329     return node
330
331
332 def name2uuid(lustre, name, tag="",  fatal=1):
333     ret = findByName(lustre, name, tag)
334     if not ret:
335         if fatal:
336             error('name2uuid:', '"'+name+'"', tag, 'element not found.')
337         else:
338             return ""
339     return getUUID(ret)
340     
341
342 # XXX: assumes only one network element per node. will fix this
343 # as soon as support for routers is added
344 def get_net_uuid(lustre, node_name):
345     """ get a network uuid for a node_name """
346     node = findByName(lustre, node_name, "node")
347     if not node:
348         error ('get_net_uuid:', '"'+node_name+'"', "node element not found.")
349     net = node.getElementsByTagName('network')
350     if net:
351         return getUUID(net[0])
352     return None
353
354
355 def lov_add_obd(gen, lov, osc_uuid):
356     devs = lov.getElementsByTagName('devices')
357     if len(devs) == 1:
358         devs[0].appendChild(gen.ref("obd", osc_uuid))
359     else:
360         error("No devices element found for LOV:", lov)
361
362                             
363 def node_add_profile(gen, node, ref, uuid):
364     ret = node.getElementsByTagName('profile')
365     if not ret:
366         error('node has no profile:', node)
367     ret[0].appendChild(gen.ref(ref, uuid))
368     
369 def get_attr(dom_node, attr, default=""):
370     v = dom_node.getAttribute(attr)
371     if v:
372         return v
373     return default
374
375 ############################################################
376 # Top level commands
377 #
378 def do_add_node(gen, lustre,  options, node_name):
379     uuid = new_uuid(node_name)
380     node = gen.node(node_name, uuid)
381     node_add_profile(gen, node, 'ldlm', ldlm_uuid)
382     if has_option(options, 'router'):
383         node.setAttribute('router', '1')
384     if has_option(options, 'timeout'):
385         node.setAttribute('timeout', get_option(options, 'timeout'))
386     if has_option(options, 'recovery_upcall'):
387         node.setAttribute('recovery_upcall', get_option(options, 'recovery_upcall'))
388     lustre.appendChild(node)
389     return node
390
391     
392 def add_node(gen, lustre, options):
393     """ create a node with a network config """
394
395     node_name = get_option(options, 'node')
396
397     ret = findByName(lustre, node_name, "node")
398     if ret:
399         print "Node:", node_name, "exists."
400         return
401     do_add_node(gen, lustre, options, node_name)
402
403
404 def add_net(gen, lustre, options):
405     """ create a node with a network config """
406
407     node_name = get_option(options, 'node')
408     nid = get_option(options, 'nid')
409     net_type = get_option(options, 'nettype')
410
411     if net_type == 'tcp':
412         port = get_option_int(options, 'port', DEFAULT_PORT)
413         tcpbuf = get_option_int(options, 'tcpbuf', 0)
414     elif net_type in ('elan', 'gm'):
415         port = 0
416         tcpbuf = 0
417     else:
418         print "Unknown net_type: ", net_type
419         sys.exit(2)
420
421     ret = findByName(lustre, node_name, "node")
422     if not ret:
423         node = do_add_node(gen, lustre, options, node_name)
424     else:
425         node = ret
426     net_name = new_name('NET_'+ node_name +'_'+ net_type)
427     net_uuid = new_uuid(net_name)
428     node.appendChild(gen.network(net_name, net_uuid, nid, net_type, port, tcpbuf))
429     node_add_profile(gen, node, "network", net_uuid)
430
431
432 def add_route(gen, lustre, options):
433     """ create a node with a network config """
434
435     node_name = get_option(options, 'node')
436     net_type = get_option(options, 'nettype')
437     gw = get_option(options, 'gw')
438     lo = get_option(options, 'lo')
439     hi = get_option(options, 'hi', '')
440
441     node = findByName(lustre, node_name, "node")
442     if not node:
443         error (node_name, " not found.")
444     
445     netlist = node.getElementsByTagName('network')
446     net = netlist[0]
447     rlist = net.getElementsByTagName('route_tbl')
448     if len(rlist) > 0:
449         rtbl = rlist[0]
450     else:
451         rtbl = gen.addElement(net, 'route_tbl')
452     rtbl.appendChild(gen.route(net_type, gw, lo, hi))
453
454
455 def add_mds(gen, lustre, options):
456     node_name = get_option(options, 'node')
457     mds_orig = get_option(options, 'mds')
458     mds_name = new_name(mds_orig)
459     if mds_name != mds_orig:
460         warning("name:", mds_orig, "already used. using:", mds_name)
461     devname = get_option(options, 'dev')
462     size = get_option(options, 'size', 0)
463     fstype = get_option(options, 'fstype', 'extN')
464
465     mds_uuid = new_uuid(mds_name)
466
467     node_uuid = name2uuid(lustre, node_name, 'node')
468
469     node = findByName(lustre, node_name, "node")
470     node_add_profile(gen, node, "mds", mds_uuid)
471     net_uuid = get_net_uuid(lustre, node_name)
472     if not net_uuid:
473         error("NODE: ", node_name, "not found")
474
475     mds = gen.mds(mds_name, mds_uuid, fstype, devname, get_format_flag(options),
476                   net_uuid, node_uuid, dev_size=size)
477     lustre.appendChild(mds)
478                    
479
480 def add_ost(gen, lustre, options):
481     node_name = get_option(options, 'node')
482     lovname = get_option(options, 'lov', '')
483     obdtype = get_option(options, 'obdtype', 'obdfilter')
484
485     if obdtype == 'obdecho':
486         fstype = ''
487         devname = ''
488         size = 0
489         fstype = ''
490     else:
491         devname = get_option(options, 'dev', '') # can be unset for bluearcs
492         size = get_option(options, 'size', 0)
493         fstype = get_option(options, 'fstype', 'extN')
494         
495     obdname = get_option(options, 'obd', 'OBD_'+ node_name)
496     obdname = new_name(obdname)
497     ostname = new_name('OST_'+ obdname)
498     if options.has_key('obduuid'):
499         obd_uuid = options['obduuid']
500         obd = lookup(lustre, obd_uuid)
501         if obd:
502             error("Duplicate OBD UUID:", obd_uuid)
503     else:
504         obd_uuid = new_uuid(obdname)
505     ost_uuid = new_uuid(ostname)
506
507     net_uuid = get_net_uuid(lustre, node_name)
508     if not net_uuid:
509         error("NODE: ", node_name, "not found")
510     
511     obd = gen.obd(obdname, obd_uuid, fstype, obdtype, devname, get_format_flag(options), ost_uuid,
512                   size)
513     ost = gen.ost(ostname, ost_uuid, obd_uuid, net_uuid)
514     
515     if lovname:
516         lov = findByName(lustre, lovname, "lov")
517         if not lov:
518             error('add_ost:', '"'+lovname+'"', "lov element not found.")
519         lov_add_obd(gen, lov, obd_uuid)
520
521     node = findByName(lustre, node_name, "node")
522     node_add_profile(gen, node, 'obd', obd_uuid)
523     node_add_profile(gen, node, 'ost', ost_uuid)
524
525     lustre.appendChild(obd)
526     lustre.appendChild(ost)
527
528                    
529 def add_cobd(gen, lustre, options):
530     node_name = get_option(options, 'node')
531     name = new_name('COBD_' + node_name)
532     uuid = new_uuid(name)
533
534     real_name = get_option(options, 'real_obd')
535     cache_name = get_option(options, 'cache_obd')
536     
537     real_uuid = name2uuid(lustre, real_name, tag='obd')
538     cache_uuid = name2uuid(lustre, cache_name, tag='obd')
539
540     node = findByName(lustre, node_name, "node")
541     node_add_profile(gen, node, "cobd", uuid)
542     cobd = gen.cobd(name, uuid, real_uuid, cache_uuid)
543     lustre.appendChild(cobd)
544
545
546 def add_echo_client(gen, lustre, options):
547     """ add an echo client to the profile for this node. """
548     node_name = get_option(options, 'node')
549     lov_name = get_option(options, 'obd')
550
551     node = findByName(lustre, node_name, 'node')
552
553     echoname = new_name('ECHO_'+ node_name)
554     echo_uuid = new_uuid(echoname)
555     node_add_profile(gen, node, 'echo_client', echo_uuid)
556
557     lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
558     if not lov_uuid:
559         lov_uuid = name2uuid(lustre, lov_name, tag='obd', fatal=1)
560
561     echo = gen.echo_client(echoname, echo_uuid, lov_uuid)
562     lustre.appendChild(echo)
563
564
565 def add_lov(gen, lustre, options):
566     """ create a lov """
567
568     lov_orig = get_option(options, 'lov')
569     name = new_name(lov_orig)
570     if name != lov_orig:
571         warning("name:", lov_orig, "already used. using:", name)
572
573     mds_name = get_option(options, 'mds')
574     stripe_sz = get_option(options, 'stripe_sz')
575     stripe_cnt = get_option(options, 'stripe_cnt', 0)
576     pattern = get_option(options, 'stripe_pattern', 0)
577     uuid = new_uuid(name)
578
579     ret = findByName(lustre, name, "lov")
580     if ret:
581         error("LOV: ", name, " already exists.")
582
583     mds_uuid = name2uuid(lustre, mds_name, 'mds')
584     lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
585     lustre.appendChild(lov)
586     
587     # add an lovconfig entry to the mds profile
588     lovconfig_name = new_name('LVCFG_' + name)
589     lovconfig_uuid = new_uuid(lovconfig_name)
590     node = mds2node(lustre, mds_name)
591     node_add_profile(gen, node, "lovconfig", lovconfig_uuid)
592     lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
593     lustre.appendChild(lovconfig)
594
595
596 def add_mtpt(gen, lustre, options):
597     """ create mtpt on a node """
598     node_name = get_option(options, 'node')
599
600     path = get_option(options, 'path')
601     mds_name = get_option(options, 'mds')
602     lov_name = get_option(options, 'lov', '')
603     if lov_name == '':
604         lov_name = get_option(options, 'obd', '')
605         if lov_name == '':
606             error("--add mtpt requires either --lov lov_name or --obd obd_name")
607
608     name = new_name('MNT_'+ node_name)
609
610     ret = findByName(lustre, name, "mountpoint")
611     if ret:
612         error("MOUNTPOINT: ", name, " already exists.")
613
614     mds_uuid = name2uuid(lustre, mds_name, tag='mds')
615     lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
616     if not lov_uuid:
617         lov_uuid = name2uuid(lustre, lov_name, tag='obd', fatal=1)
618
619     uuid = new_uuid(name)
620     mtpt = gen.mountpoint(name, uuid, mds_uuid, lov_uuid, path)
621     node = findByName(lustre, node_name, "node")
622     if not node:
623             error('node:',  node_name, "not found.")
624     node_add_profile(gen, node, "mountpoint", uuid)
625     lustre.appendChild(mtpt)
626
627 def add_oscref(gen, lustre, options):
628     """ create mtpt on a node """
629     node_name = get_option(options, 'node')
630     osc_name = get_option(options, 'osc')
631
632     osc_uuid = name2uuid(lustre, osc_name, tag='osc')
633     node = findByName(lustre, node_name, "node")
634     if not node:
635             error('node:', node_name, "not found")
636     node_add_profile(gen, node, "osc",osc_uuid)
637
638 ############################################################
639 # Command line processing
640 #
641 class OptionError (exceptions.Exception):
642     def __init__(self, args):
643         self.args = args
644
645 def has_option(options, tag):
646     """Look for tag in options hash and return the true if set"""
647     if options.has_key(tag):
648         return 1
649     return 0
650
651 def get_option(options, tag, default = None):
652     """Look for tag in options hash and return the value if set. If not
653     set, then if return default it is set, otherwise exception."""
654     if options.has_key(tag):
655         return options[tag]
656     elif default != None:
657         return default
658     else:
659         raise OptionError("--add %s requires --%s value" % (options['add'], tag))
660         # this exception should print an error like '--add blah requires --<tag> value'
661
662 def get_option_int(options, tag, default = None):
663     """Return an integer option.  Raise exception if the value is not an int"""
664     val = get_option(options, tag, default)
665     return int(val)
666
667 def parse_cmdline(argv):
668     short_opts = "ho:i:m:"
669     long_opts = ["add=", "node=", "nettype=", "nid=", "tcpbuf=", "port=",
670                  "echo_client=", "stripe_sz=", "stripe_cnt=", "stripe_pattern=",
671                  "mds=", "route", "router", "merge=", "format", "reformat", "output=",
672                  "dev=", "size=", "obd=", "obdtype=", "obduuid=", "in=",
673                  "path=", "help", "batch=", "lov=", "gw=", "lo=", "hi=",
674                  "oscref", "osc=", "real_obd=", "cache_obd=", "fstype=",
675                  "timeout=", "recovery_upcall="]
676     opts = []
677     args = []
678     options = {}
679     try:
680         opts, args = getopt.getopt(argv, short_opts, long_opts)
681     except getopt.error, e:
682         panic(string.join(sys.argv), e)
683
684     for o, a in opts:
685         # Commands to create new devices
686         if o == "--add":
687             options['add'] = a
688
689         if o == "--node":
690             options['node'] = a
691
692         # devices names
693         if o == "--lov":
694             options['lov'] = a
695         if o == "--mds":
696             options['mds'] = a
697         if o == "--obd":
698             options['obd'] = a
699
700         # node options
701         if o == "--timeout":
702             options['timeout'] = a
703         if o == "--recovery_upcall":
704             options['recovery_upcall'] = a
705         if o == "--router":
706             options['router'] = 1
707         
708         # network options
709         if o == "--nid":
710             options['nid'] = a
711         if o == "--nettype":
712             options['nettype'] = a
713         if o == "--net":
714             options[''] = a
715         if o == "--tcpbuf":
716             options['tcpbuf'] = a
717         if o == "--port":
718             options['port'] = a
719         if o == "--mtpt":
720             options['mtpt'] = 1
721         if o == "--route":
722             options['route'] = 1
723
724         # ost options
725         if o == "--dev":
726             options['dev'] = a
727         if o == "--size":
728             options['size'] = a
729         if o == "--path":
730             options['path'] = a
731         if o == "--osc":
732             options['osc'] = a
733         if o == "--obdtype":
734             options['obdtype'] = a
735         if o == "--fstype":
736             options['fstype'] = a
737         if o == "--obduuid":
738             options['obduuid'] = a
739
740         # lov options
741         if o == "--stripe_sz":
742             options['stripe_sz'] = a
743         if o == "--stripe_cnt":
744             options['stripe_cnt'] = a
745         if o == "--stripe_pattern":
746             options['stripe_pattern'] = a
747         if o == "--gw":
748             options['gw'] = a
749         if o == "--lo":
750             options['lo'] = a
751         if o == "--hi":
752             options['hi'] = a
753
754         # cobd
755         if o == "--cache_obd":
756             options['cache_obd'] = a
757         if o == "--real_obd":
758             options['real_obd'] = a
759
760         # lmc options
761         if o in ("-h", "--help"):
762             usage()
763         if o in ("-o", "--output"):
764             options['output'] = a
765         if o in ("-m", "--merge"):
766             options['merge'] = a
767         if o == "--format":
768             options['format'] = 1
769         if o  == "--reformat":
770             options['reformat'] = 1
771         if o  == "--batch":
772             options['batch'] = a
773         if o  in ("--in" , "-i"):
774             options['in'] = a
775             
776     return options, args
777
778
779 # simple class for profiling
780 import time
781 class chrono:
782     def __init__(self):
783         self._start = 0
784     def start(self):
785         self._stop = 0
786         self._start = time.time()
787     def stop(self, msg=''):
788         self._stop = time.time()
789         if msg:
790             self.display(msg)
791     def dur(self):
792         return self._stop - self._start
793     def display(self, msg):
794         d = self.dur()
795         str = '%s: %g secs' % (msg, d)
796         print str
797
798
799
800 ############################################################
801 # Main
802 #
803
804 def add(devtype, gen, lustre, options):
805     if devtype == 'net':
806         add_net(gen, lustre, options)
807     elif devtype =='osc':
808         add_osc(gen, lustre, options)
809     elif devtype == 'mtpt':
810         add_mtpt(gen, lustre, options)
811     elif devtype == 'mds':
812         add_mds(gen, lustre, options)
813     elif devtype == 'ost':
814         add_ost(gen, lustre, options)
815     elif devtype == 'lov':
816         add_lov(gen, lustre, options)
817     elif devtype == 'route':
818         add_route(gen, lustre, options)
819     elif devtype == 'node':
820         add_node(gen, lustre, options)
821     elif devtype == 'echo_client':
822         add_echo_client(gen, lustre, options)
823     elif devtype == 'oscref':
824         add_oscref(gen, lustre, options)
825     elif devtype == 'cobd':
826         add_cobd(gen, lustre, options)
827     else:
828         error("unknown device type:", devtype)
829     
830 def do_command(gen, lustre, options, args):
831     if options.has_key('add'):
832         add(options['add'], gen, lustre, options)
833     else:
834         error("Missing command")
835
836 def main():
837     options, args = parse_cmdline(sys.argv[1:])
838     outFile = '-'
839
840     if options.has_key('merge'):
841         outFile = options['merge']
842         if os.access(outFile, os.R_OK):
843             doc = xml.dom.minidom.parse(outFile)
844         else:
845             doc = new_lustre(xml.dom.minidom)
846     elif options.has_key('in'):
847         doc = xml.dom.minidom.parse(options['in'])
848     else:
849         doc = new_lustre(xml.dom.minidom)
850
851     if options.has_key('output'):
852         outFile = options['output']
853
854     lustre = doc.documentElement
855     init_names(lustre)
856     if lustre.tagName != "lustre":
857         print "Existing config not valid."
858         sys.exit(1)
859
860     gen = GenConfig(doc)
861
862     if options.has_key('batch'):
863         fp = open(options['batch'])
864         batchCommands = fp.readlines()
865         fp.close()
866         for cmd in batchCommands:
867             options, args = parse_cmdline(string.split(cmd))
868             try:
869                 do_command(gen, lustre, options, args)
870             except OptionError, e:
871                 panic(cmd, e)
872     else:
873         try:
874             do_command(gen, lustre, options, args)
875         except OptionError, e:
876             panic(string.join(sys.argv),e)
877
878     if outFile == '-':
879         PrettyPrint(doc)
880     else:
881         PrettyPrint(doc, open(outFile,"w"))
882
883 if __name__ == "__main__":
884     main()
885
886