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