Whamcloud - gitweb
* attempt to return proper exit codes when errors occur
[fs/lustre-release.git] / lustre / utils / lconf
1 #!/usr/bin/env python
2 #
3 #  Copyright (C) 2002 Cluster File Systems, Inc.
4 #   Author: Robert Read <rread@clusterfs.com>
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 # lconf - lustre configuration tool
21 #
22 # lconf is the main driver script for starting and stopping
23 # lustre filesystem services.
24 #
25 # Based in part on the XML obdctl modifications done by Brian Behlendorf 
26
27 import sys, getopt
28 import string, os, stat, popen2, socket, time
29 import re, exceptions
30 import xml.dom.minidom
31
32 # Global parameters
33 TCP_ACCEPTOR = ''
34 MAXTCPBUF = 1048576
35 DEFAULT_TCPBUF = 1048576
36 #
37 # Maximum number of devices to search for.
38 # (the /dev/loop* nodes need to be created beforehand)
39 MAX_LOOP_DEVICES = 256
40
41 first_cleanup_error = 0
42 def cleanup_error(rc):
43     global first_cleanup_error
44     if not first_cleanup_error:
45         first_cleanup_error = rc
46
47
48 def usage():
49     print """usage: lconf config.xml
50
51 config.xml          Lustre configuration in xml format.
52 --get <url>         URL to fetch a config file
53 --node <nodename>   Load config for <nodename>
54 -d | --cleanup      Cleans up config. (Shutdown)
55 -v | --verbose      Print system commands as they are run
56 -h | --help         Print this help 
57 --gdb               Prints message after creating gdb module script
58                     and sleeps for 5 seconds.
59 -n | --noexec       Prints the commands and steps that will be run for a
60                     config without executing them. This can used to check if a
61                     config file is doing what it should be doing. (Implies -v)
62 --nomod             Skip load/unload module step.
63 --nosetup           Skip device setup/cleanup step.
64 --reformat          Reformat all devices (without question)
65 --dump              Dump the kernel debug log before portals is unloaded
66 """
67     TODO = """
68 --ldap server       LDAP server with lustre config database
69 --makeldiff         Translate xml source to LDIFF 
70 This are perhaps not needed:
71 --lustre="src dir"  Base directory of lustre sources. Used to search
72                     for modules.
73 --portals=src       Portals source 
74 """
75     sys.exit()
76
77 # ============================================================
78 # Config parameters, encapsulated in a class
79 class Config:
80     def __init__(self):
81         # flags
82         self._noexec = 0
83         self._verbose = 0
84         self._reformat = 0
85         self._cleanup = 0
86         self._gdb = 0
87         self._nomod = 0
88         self._nosetup = 0
89         # parameters
90         self._modules = None
91         self._node = None
92         self._url = None
93         self._gdb_script = '/tmp/ogdb'
94         self._debug_path = '/tmp/lustre-log'
95         self._dump_file = None
96         self._src_dir = None
97
98     def verbose(self, flag = None):
99         if flag: self._verbose = flag
100         return self._verbose
101
102     def noexec(self, flag = None):
103         if flag: self._noexec = flag
104         return self._noexec
105
106     def reformat(self, flag = None):
107         if flag: self._reformat = flag
108         return self._reformat
109
110     def cleanup(self, flag = None):
111         if flag: self._cleanup = flag
112         return self._cleanup
113
114     def gdb(self, flag = None):
115         if flag: self._gdb = flag
116         return self._gdb
117
118     def nomod(self, flag = None):
119         if flag: self._nomod = flag
120         return self._nomod
121
122     def nosetup(self, flag = None):
123         if flag: self._nosetup = flag
124         return self._nosetup
125
126     def node(self, val = None):
127         if val: self._node = val
128         return self._node
129
130     def url(self, val = None):
131         if val: self._url = val
132         return self._url
133
134     def gdb_script(self):
135         if os.path.isdir('/r'):
136             return '/r' + self._gdb_script
137         else:
138             return self._gdb_script
139
140     def debug_path(self):
141         if os.path.isdir('/r'):
142             return '/r' + self._debug_path
143         else:
144             return self._debug_path
145
146     def src_dir(self, val = None):
147         if val: self._src_dir = val
148         return self._src_dir
149
150     def dump_file(self, val = None):
151         if val: self._dump_file = val
152         return self._dump_file
153
154 config = Config()
155
156 # ============================================================ 
157 # debugging and error funcs
158
159 def fixme(msg = "this feature"):
160     raise LconfError, msg + ' not implmemented yet.'
161
162 def panic(*args):
163     msg = string.join(map(str,args))
164     if not config.noexec():
165         raise LconfError(msg)
166     else:
167         print "! " + msg
168
169 def log(*args):
170     msg = string.join(map(str,args))
171     print msg
172
173 def logall(msgs):
174     for s in msgs:
175         print string.strip(s)
176
177 def debug(*args):
178     if config.verbose():
179         msg = string.join(map(str,args))
180         print msg
181
182 # ============================================================
183 # locally defined exceptions
184 class CommandError (exceptions.Exception):
185     def __init__(self, cmd_name, cmd_err, rc=None):
186         self.cmd_name = cmd_name
187         self.cmd_err = cmd_err
188         self.rc = rc
189
190     def dump(self):
191         import types
192         if type(self.cmd_err) == types.StringType:
193             if self.rc:
194                 print "! %s (%d): %s" % (self.cmd_name, self.rc, self.cmd_err)
195             else:
196                 print "! %s: %s" % (self.cmd_name, self.cmd_err)
197         elif type(self.cmd_err) == types.ListType:
198             if self.rc:
199                 print "! %s (error %d):" % (self.cmd_name, self.rc)
200             else:
201                 print "! %s:" % (self.cmd_name)
202             for s in self.cmd_err:
203                 print "> %s" %(string.strip(s))
204         else:
205             print self.cmd_err
206
207 class LconfError (exceptions.Exception):
208     def __init__(self, args):
209         self.args = args
210
211
212 # ============================================================
213 # handle lctl interface
214 class LCTLInterface:
215     """
216     Manage communication with lctl
217     """
218
219     def __init__(self, cmd):
220         """
221         Initialize close by finding the lctl binary.
222         """
223         self.lctl = find_prog(cmd)
224         if not self.lctl:
225             if config.noexec():
226                 debug('! lctl not found')
227                 self.lctl = 'lctl'
228             else:
229                 raise CommandError('lctl', "unable to find lctl binary.")
230             
231     def run(self, cmds):
232         """
233         run lctl
234         the cmds are written to stdin of lctl
235         lctl doesn't return errors when run in script mode, so
236         stderr is checked
237         should modify command line to accept multiple commands, or
238         create complex command line options
239         """
240         debug("+", self.lctl, cmds)
241         if config.noexec(): return (0, [])
242         p = popen2.Popen3(self.lctl, 1)
243         p.tochild.write(cmds + "\n")
244         p.tochild.close()
245         out = p.fromchild.readlines()
246         err = p.childerr.readlines()
247         ret = p.wait()
248         if ret or len(err):
249             raise CommandError(self.lctl, err, ret)
250         return ret, out
251
252             
253     def network(self, net, nid):
254         """ initialized network and add "self" """
255         # Idea: "mynid" could be used for all network types to add "self," and then
256         # this special case would be gone and the "self" hack would be hidden.
257         if net  == 'tcp':
258             cmds =  """
259   network %s
260   mynid %s
261   add_uuid self %s
262   quit""" % (net, nid, nid)
263         else:
264             cmds =  """
265   network %s
266   add_uuid self %s
267   quit""" % (net, nid)
268             
269         self.run(cmds)
270
271     # create a new connection
272     def connect(self, net, nid, port, servuuid, send_mem, recv_mem):
273         if net == 'tcp':
274             cmds =  """
275   network %s
276   add_uuid %s %s
277   send_mem %d
278   recv_mem %d
279   connect %s %d
280   quit""" % (net, servuuid, nid, send_mem, recv_mem, nid, port,  )
281         else:
282             cmds =  """
283   network %s
284   add_uuid %s %s
285   connect %s %d
286   quit""" % (net, servuuid, nid, nid, port,  )
287             
288         self.run(cmds)
289                 
290     # add a route to a range
291     def add_route(self, net, gw, lo, hi):
292         cmds =  """
293   network %s
294   add_route %s %s %s
295   quit  """ % (net, gw, lo, hi)
296         self.run(cmds)
297
298                 
299     # add a route to a range
300     def del_route(self, net, gw, lo, hi):
301         cmds =  """
302   network %s
303   del_route %s
304   quit  """ % (net, lo)
305         self.run(cmds)
306
307     # add a route to a host
308     def add_route_host(self, net, uuid, gw, tgt):
309         cmds =  """
310   network %s
311   add_uuid %s %s
312   add_route %s %s
313   quit """ % (net, uuid, tgt, gw, tgt)
314         self.run(cmds)
315
316     # add a route to a range
317     def del_route_host(self, net, uuid, gw, tgt):
318         cmds =  """
319   network %s
320   del_uuid %s
321   del_route %s
322   quit  """ % (net, uuid, tgt)
323         self.run(cmds)
324
325     # disconnect one connection
326     def disconnect(self, net, nid, port, servuuid):
327         cmds =  """
328   network %s
329   disconnect %s 
330   del_uuid %s
331   quit""" % (net, nid, servuuid)
332         self.run(cmds)
333
334     # disconnect all
335     def disconnectAll(self, net):
336         cmds =  """
337   network %s
338   del_uuid self
339   disconnect
340   quit""" % (net)
341         self.run(cmds)
342
343     # create a new device with lctl
344     def newdev(self, attach, setup = ""):
345         cmds = """
346   newdev
347   attach %s
348   setup %s
349   quit""" % (attach, setup)
350         self.run(cmds)
351
352     # cleanup a device
353     def cleanup(self, name, uuid):
354         cmds = """
355   device $%s
356   cleanup
357   detach
358   quit""" % (name)
359         self.run(cmds)
360
361     # create an lov
362     def lovconfig(self, uuid, mdsuuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist):
363         cmds = """
364   device $%s
365   probe
366   lovconfig %s %d %d %d %s %s
367   quit""" % (mdsuuid, uuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist)
368         self.run(cmds)
369
370     # cleanup a device
371     def dump(self, dump_file):
372         cmds = """
373   debug_kernel %s 1
374   quit""" % (dump_file)
375         self.run(cmds)
376
377 # ============================================================
378 # Various system-level functions
379 # (ideally moved to their own module)
380
381 # Run a command and return the output and status.
382 # stderr is sent to /dev/null, could use popen3 to
383 # save it if necessary
384 def run(*args):
385     cmd = string.join(map(str,args))
386     debug ("+", cmd)
387     if config.noexec(): return (0, [])
388     f = os.popen(cmd + ' 2>&1')
389     out = f.readlines()
390     ret = f.close()
391     if ret:
392         ret = ret >> 8
393     else:
394         ret = 0
395     return (ret, out)
396
397 # Run a command in the background.
398 def run_daemon(*args):
399     cmd = string.join(map(str,args))
400     debug ("+", cmd)
401     if config.noexec(): return 0
402     f = os.popen(cmd + ' 2>&1')
403     ret = f.close()
404     if ret:
405         ret = ret >> 8
406     else:
407         ret = 0
408     return ret
409
410 # Determine full path to use for an external command
411 # searches dirname(argv[0]) first, then PATH
412 def find_prog(cmd):
413     syspath = string.split(os.environ['PATH'], ':')
414     cmdpath = os.path.dirname(sys.argv[0])
415     syspath.insert(0, cmdpath);
416     syspath.insert(0, os.path.join(cmdpath, '../../portals/linux/utils/'))
417     for d in syspath:
418         prog = os.path.join(d,cmd)
419         if os.access(prog, os.X_OK):
420             return prog
421     return ''
422
423 # Recursively look for file starting at base dir
424 def do_find_file(base, mod):
425     fullname = os.path.join(base, mod)
426     if os.access(fullname, os.R_OK):
427         return fullname
428     for d in os.listdir(base):
429         dir = os.path.join(base,d)
430         if os.path.isdir(dir):
431             module = do_find_file(dir, mod)
432             if module:
433                 return module
434
435 def find_module(src_dir, dev_dir, modname):
436     mod = '%s.o' % (modname)
437     module = src_dir +'/'+ dev_dir +'/'+ mod
438     try: 
439        if os.access(module, os.R_OK):
440             return module
441     except OSError:
442         pass
443     return None
444
445 # is the path a block device?
446 def is_block(path):
447     s = ()
448     try:
449         s =  os.stat(path)
450     except OSError:
451         return 0
452     return stat.S_ISBLK(s[stat.ST_MODE])
453
454 # build fs according to type
455 # fixme: dangerous
456 def mkfs(fstype, dev):
457     if(fstype in ('ext3', 'extN')):
458         mkfs = 'mkfs.ext2 -j -b 4096'
459     else:
460         print 'unsupported fs type: ', fstype
461     if not is_block(dev):
462         force = '-F'
463     else:
464         force = ''
465     (ret, out) = run (mkfs, force, dev)
466     if ret:
467         panic("Unable to build fs:", dev)
468     # enable hash tree indexing on fs
469     if fstype == 'extN':
470         htree = 'echo "feature FEATURE_C5" | debugfs -w'
471         (ret, out) = run (htree, dev)
472         if ret:
473             panic("Unable to enable htree:", dev)
474
475 # some systems use /dev/loopN, some /dev/loop/N
476 def loop_base():
477     import re
478     loop = '/dev/loop'
479     if not os.access(loop + str(0), os.R_OK):
480         loop = loop + '/'
481         if not os.access(loop + str(0), os.R_OK):
482             panic ("can't access loop devices")
483     return loop
484     
485 # find loop device assigned to thefile
486 def find_loop(file):
487     loop = loop_base()
488     for n in xrange(0, MAX_LOOP_DEVICES):
489         dev = loop + str(n)
490         if os.access(dev, os.R_OK):
491             (stat, out) = run('losetup', dev)
492             if (out and stat == 0):
493                 m = re.search(r'\((.*)\)', out[0])
494                 if m and file == m.group(1):
495                     return dev
496         else:
497             break
498     return ''
499
500 # create file if necessary and assign the first free loop device
501 def init_loop(file, size, fstype):
502     dev = find_loop(file)
503     if dev:
504         print 'WARNING file:', file, 'already mapped to', dev
505         return dev
506     if config.reformat()  or not os.access(file, os.R_OK | os.W_OK):
507         run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size,  file))
508     loop = loop_base()
509     # find next free loop
510     for n in xrange(0, MAX_LOOP_DEVICES):
511         dev = loop + str(n)
512         if os.access(dev, os.R_OK):
513             (stat, out) = run('losetup', dev)
514             if (stat):
515                 run('losetup', dev, file)
516                 return dev
517         else:
518             print "out of loop devices"
519             return ''
520     print "out of loop devices"
521     return ''
522
523 # undo loop assignment
524 def clean_loop(file):
525     dev = find_loop(file)
526     if dev:
527         ret, out = run('losetup -d', dev)
528         if ret:
529             log('unable to clean loop device:', dev, 'for file:', file)
530             logall(out)
531
532 # determine if dev is formatted as a <fstype> filesystem
533 def need_format(fstype, dev):
534     # FIXME don't know how to implement this    
535     return 0
536
537 # initialize a block device if needed
538 def block_dev(dev, size, fstype, format):
539     if config.noexec(): return dev
540     if not is_block(dev):
541         dev = init_loop(dev, size, fstype)
542     if config.reformat() or (need_format(fstype, dev) and format == 'yes'):
543         mkfs(fstype, dev)
544
545 #    else:
546 #        panic("device:", dev,
547 #              "not prepared, and autoformat is not set.\n",
548 #              "Rerun with --reformat option to format ALL filesystems")
549         
550     return dev
551
552 def if2addr(iface):
553     """lookup IP address for an interface"""
554     rc, out = run("/sbin/ifconfig", iface)
555     if rc or not out:
556        return None
557     addr = string.split(out[1])[1]
558     ip = string.split(addr, ':')[1]
559     return ip
560
561 def get_local_address(net_type, wildcard):
562     """Return the local address for the network type."""
563     local = ""
564     if net_type == 'tcp':
565         if  ':' in wildcard:
566             iface, star = string.split(wildcard, ':')
567             local = if2addr(iface)
568             if not local:
569                 panic ("unable to determine ip for:", wildcard)
570         else:
571             host = socket.gethostname()
572             local = socket.gethostbyname(host)
573     elif net_type == 'elan':
574         # awk '/NodeId/ { print $2 }' '/proc/elan/device0/position'
575         try:
576             fp = open('/proc/elan/device0/position', 'r')
577             lines = fp.readlines()
578             fp.close()
579             for l in lines:
580                 a = string.split(l)
581                 if a[0] == 'NodeId':
582                     local = a[1]
583                     break
584         except IOError, e:
585             log(e)
586     elif net_type == 'gm':
587         fixme("automatic local address for GM")
588     return local
589         
590         
591
592 # ============================================================
593 # Classes to prepare and cleanup the various objects
594 #
595 class Module:
596     """ Base class for the rest of the modules. The default cleanup method is
597     defined here, as well as some utilitiy funcs.
598     """
599     def __init__(self, module_name, dom_node):
600         self.dom_node = dom_node
601         self.module_name = module_name
602         self.name = get_attr(dom_node, 'name')
603         self.uuid = get_attr(dom_node, 'uuid')
604         self.kmodule_list = []
605         self._server = None
606         self._connected = 0
607         
608     def info(self, *args):
609         msg = string.join(map(str,args))
610         print self.module_name + ":", self.name, self.uuid, msg
611
612
613     def lookup_server(self, srv_uuid):
614         """ Lookup a server's network information """
615         net = get_ost_net(self.dom_node.parentNode, srv_uuid)
616         if not net:
617             panic ("Unable to find a server for:", srv_uuid)
618         self._server = Network(net)
619
620     def get_server(self):
621         return self._server
622
623     def cleanup(self):
624         """ default cleanup, used for most modules """
625         self.info()
626         srv = self.get_server()
627         if srv and local_net(srv):
628             try:
629                 lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
630             except CommandError, e:
631                 log(self.module_name, "disconnect failed: ", self.name)
632                 e.dump()
633                 cleanup_error(e.rc)
634         try:
635             lctl.cleanup(self.name, self.uuid)
636         except CommandError, e:
637             log(self.module_name, "cleanup failed: ", self.name)
638             e.dump()
639             cleanup_error(e.rc)
640
641     def add_module(self, dev_dir, modname):
642         """Append a module to list of modules to load."""
643         self.kmodule_list.append((dev_dir, modname))
644
645     def mod_loaded(self, modname):
646         """Check if a module is already loaded. Look in /proc/modules for it."""
647         fp = open('/proc/modules')
648         lines = fp.readlines()
649         fp.close()
650         # please forgive my tired fingers for this one
651         ret = filter(lambda word, mod=modname: word == mod,
652                      map(lambda line: string.split(line)[0], lines))
653         return ret
654
655     def load_module(self):
656         """Load all the modules in the list in the order they appear."""
657         for dev_dir, mod in self.kmodule_list:
658             #  (rc, out) = run ('/sbin/lsmod | grep -s', mod)
659             if self.mod_loaded(mod) and not config.noexec():
660                 continue
661             log ('loading module:', mod)
662             if config.src_dir():
663                 module = find_module(config.src_dir(),dev_dir,  mod)
664                 if not module:
665                     panic('module not found:', mod)
666                 (rc, out)  = run('/sbin/insmod', module)
667                 if rc:
668                     raise CommandError('insmod', out, rc)
669             else:
670                 (rc, out) = run('/sbin/modprobe', mod)
671                 if rc:
672                     raise CommandError('modprobe', out, rc)
673             
674     def cleanup_module(self):
675         """Unload the modules in the list in reverse order."""
676         rev = self.kmodule_list
677         rev.reverse()
678         for dev_dir, mod in rev:
679             if not self.mod_loaded(mod):
680                 continue
681             # debug hack
682             if mod == 'portals' and config.dump_file():
683                 lctl.dump(config.dump_file())
684             log('unloading module:', mod)
685             if config.noexec():
686                 continue
687             (rc, out) = run('/sbin/rmmod', mod)
688             if rc:
689                 log('! unable to unload module:', mod)
690                 logall(out)
691         
692
693 class Network(Module):
694     def __init__(self,dom_node):
695         Module.__init__(self, 'NETWORK', dom_node)
696         self.net_type = get_attr(dom_node,'type')
697         self.nid = get_text(dom_node, 'server', '*')
698         self.port = get_text_int(dom_node, 'port', 0)
699         self.send_mem = get_text_int(dom_node, 'send_mem', DEFAULT_TCPBUF)
700         self.recv_mem = get_text_int(dom_node, 'recv_mem', DEFAULT_TCPBUF)
701         if '*' in self.nid:
702             self.nid = get_local_address(self.net_type, self.nid)
703             if not self.nid:
704                 panic("unable to set nid for", self.net_type, self.nid)
705             debug("nid:", self.nid)
706
707         self.add_module('portals/linux/oslib/', 'portals')
708         if node_needs_router():
709             self.add_module('portals/linux/router', 'kptlrouter')
710         if self.net_type == 'tcp':
711             self.add_module('portals/linux/socknal', 'ksocknal')
712         if self.net_type == 'elan':
713             self.add_module('portals/linux/rqswnal', 'kqswnal')
714         if self.net_type == 'gm':
715             self.add_module('portals/linux/gmnal', 'kgmnal')
716         self.add_module('lustre/obdclass', 'obdclass')
717         self.add_module('lustre/ptlrpc', 'ptlrpc')
718
719     def prepare(self):
720         self.info(self.net_type, self.nid, self.port)
721         if self.net_type == 'tcp':
722             ret, out = run(TCP_ACCEPTOR, '-s', self.send_mem, '-r', self.recv_mem, self.port)
723             if ret:
724                 raise CommandError(TCP_ACCEPTOR, out, ret)
725         ret = self.dom_node.getElementsByTagName('route_tbl')
726         for a in ret:
727             for r in a.getElementsByTagName('route'):
728                 net_type = get_attr(r, 'type')
729                 gw = get_attr(r, 'gw')
730                 lo = get_attr(r, 'lo')
731                 hi = get_attr(r,'hi', '')
732                 lctl.add_route(net_type, gw, lo, hi)
733                 if net_type == 'tcp' and net_type == self.net_type and hi == '':
734                     srv = nid2server(self.dom_node.parentNode.parentNode, lo)
735                     if not srv:
736                         panic("no server for nid", lo)
737                     else:
738                         lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
739
740             
741         lctl.network(self.net_type, self.nid)
742         lctl.newdev(attach = "ptlrpc RPCDEV")
743
744     def cleanup(self):
745         self.info(self.net_type, self.nid, self.port)
746         ret = self.dom_node.getElementsByTagName('route_tbl')
747         for a in ret:
748             for r in a.getElementsByTagName('route'):
749                 lo = get_attr(r, 'lo')
750                 hi = get_attr(r,'hi', '')
751                 if self.net_type == 'tcp' and hi == '':
752                     srv = nid2server(self.dom_node.parentNode.parentNode, lo)
753                     if not srv:
754                         panic("no server for nid", lo)
755                     else:
756                         try:
757                             lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
758                         except CommandError, e:
759                             print "disconnect failed: ", self.name
760                             e.dump()
761                             cleanup_error(e.rc)
762                 try:
763                     lctl.del_route(self.net_type, self.nid, lo, hi)
764                 except CommandError, e:
765                     print "del_route failed: ", self.name
766                     e.dump()
767                     cleanup_error(e.rc)
768               
769         try:
770             lctl.cleanup("RPCDEV", "")
771         except CommandError, e:
772             print "cleanup failed: ", self.name
773             e.dump()
774             cleanup_error(e.rc)
775         try:
776             lctl.disconnectAll(self.net_type)
777         except CommandError, e:
778             print "disconnectAll failed: ", self.name
779             e.dump()
780             cleanup_error(e.rc)
781         if self.net_type == 'tcp':
782             # yikes, this ugly! need to save pid in /var/something
783             run("killall acceptor")
784
785 class LDLM(Module):
786     def __init__(self,dom_node):
787         Module.__init__(self, 'LDLM', dom_node)
788         self.add_module('lustre/ldlm', 'ldlm')
789     def prepare(self):
790         self.info()
791         lctl.newdev(attach="ldlm %s %s" % (self.name, self.uuid),
792                     setup ="")
793
794 class LOV(Module):
795     def __init__(self,dom_node):
796         Module.__init__(self, 'LOV', dom_node)
797         self.mds_uuid = get_first_ref(dom_node, 'mds')
798         mds= lookup(dom_node.parentNode, self.mds_uuid)
799         self.mds_name = getName(mds)
800         devs = dom_node.getElementsByTagName('devices')
801         if len(devs) > 0:
802             dev_node = devs[0]
803             self.stripe_sz = get_attr_int(dev_node, 'stripesize', 65536)
804             self.stripe_off = get_attr_int(dev_node, 'stripeoffset', 0)
805             self.pattern = get_attr_int(dev_node, 'pattern', 0)
806             self.devlist = get_all_refs(dev_node, 'osc')
807             self.stripe_cnt = get_attr_int(dev_node, 'stripecount', len(self.devlist))
808         self.add_module('lustre/mdc', 'mdc')
809         self.add_module('lustre/lov', 'lov')
810
811     def prepare(self):
812         for osc_uuid in self.devlist:
813             osc = lookup(self.dom_node.parentNode, osc_uuid)
814             if osc:
815                 n = OSC(osc)
816                 n.prepare()
817             else:
818                 panic('osc not found:', osc_uuid)
819         mdc_uuid = prepare_mdc(self.dom_node.parentNode, self.mds_uuid)
820         self.info(self.mds_uuid, self.stripe_cnt, self.stripe_sz,
821                   self.stripe_off, self.pattern, self.devlist, self.mds_name)
822         lctl.newdev(attach="lov %s %s" % (self.name, self.uuid),
823                     setup ="%s" % (mdc_uuid))
824
825     def cleanup(self):
826         for osc_uuid in self.devlist:
827             osc = lookup(self.dom_node.parentNode, osc_uuid)
828             if osc:
829                 n = OSC(osc)
830                 n.cleanup()
831             else:
832                 panic('osc not found:', osc_uuid)
833         Module.cleanup(self)
834         cleanup_mdc(self.dom_node.parentNode, self.mds_uuid)
835
836
837     def load_module(self):
838         for osc_uuid in self.devlist:
839             osc = lookup(self.dom_node.parentNode, osc_uuid)
840             if osc:
841                 n = OSC(osc)
842                 n.load_module()
843                 break
844             else:
845                 panic('osc not found:', osc_uuid)
846         Module.load_module(self)
847
848
849     def cleanup_module(self):
850         Module.cleanup_module(self)
851         for osc_uuid in self.devlist:
852             osc = lookup(self.dom_node.parentNode, osc_uuid)
853             if osc:
854                 n = OSC(osc)
855                 n.cleanup_module()
856                 break
857             else:
858                 panic('osc not found:', osc_uuid)
859
860 class LOVConfig(Module):
861     def __init__(self,dom_node):
862         Module.__init__(self, 'LOVConfig', dom_node)
863         self.lov_uuid = get_first_ref(dom_node, 'lov')
864         l = lookup(dom_node.parentNode, self.lov_uuid)
865         self.lov = LOV(l)
866         
867     def prepare(self):
868         lov = self.lov
869         self.info(lov.mds_uuid, lov.stripe_cnt, lov.stripe_sz, lov.stripe_off,
870                   lov.pattern, lov.devlist, lov.mds_name)
871         lctl.lovconfig(lov.uuid, lov.mds_name, lov.stripe_cnt,
872                        lov.stripe_sz, lov.stripe_off, lov.pattern,
873                        string.join(lov.devlist))
874
875     def cleanup(self):
876         #nothing to do here
877         pass
878
879
880 class MDS(Module):
881     def __init__(self,dom_node):
882         Module.__init__(self, 'MDS', dom_node)
883         self.devname, self.size = get_device(dom_node)
884         self.fstype = get_text(dom_node, 'fstype')
885         self.format = get_text(dom_node, 'autoformat', "no")
886         if self.fstype == 'extN':
887             self.add_module('lustre/extN', 'extN') 
888         self.add_module('lustre/mds', 'mds')
889         self.add_module('lustre/mds', 'mds_%s' % (self.fstype))
890             
891     def prepare(self):
892         self.info(self.devname, self.fstype, self.format)
893         blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
894         lctl.newdev(attach="mds %s %s" % (self.name, self.uuid),
895                     setup ="%s %s" %(blkdev, self.fstype))
896     def cleanup(self):
897         Module.cleanup(self)
898         clean_loop(self.devname)
899
900 # Very unusual case, as there is no MDC element in the XML anymore
901 # Builds itself from an MDS node
902 class MDC(Module):
903     def __init__(self,dom_node):
904         self.mds = MDS(dom_node)
905         self.dom_node = dom_node
906         self.module_name = 'MDC'
907         self.kmodule_list = []
908         self._server = None
909         self._connected = 0
910
911         host = socket.gethostname()
912         self.name = 'MDC_'+host
913         self.uuid = self.name+'_UUID'
914
915         self.lookup_server(self.mds.uuid)
916         self.add_module('lustre/mdc', 'mdc')
917
918     def prepare(self):
919         self.info(self.mds.uuid)
920         srv = self.get_server()
921         lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
922         lctl.newdev(attach="mdc %s %s" % (self.name, self.uuid),
923                         setup ="%s %s" %(self.mds.uuid, srv.uuid))
924             
925 class OBD(Module):
926     def __init__(self, dom_node):
927         Module.__init__(self, 'OBD', dom_node)
928         self.obdtype = get_attr(dom_node, 'type')
929         self.devname, self.size = get_device(dom_node)
930         self.fstype = get_text(dom_node, 'fstype')
931         self.format = get_text(dom_node, 'autoformat', 'yes')
932         if self.fstype == 'extN':
933             self.add_module('lustre/extN', 'extN') 
934         self.add_module('lustre/' + self.obdtype, self.obdtype)
935
936     # need to check /proc/mounts and /etc/mtab before
937     # formatting anything.
938     # FIXME: check if device is already formatted.
939     def prepare(self):
940         self.info(self.obdtype, self.devname, self.size, self.fstype, self.format)
941         if self.obdtype == 'obdecho':
942             blkdev = ''
943         else:
944             blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
945         lctl.newdev(attach="%s %s %s" % (self.obdtype, self.name, self.uuid),
946                     setup ="%s %s" %(blkdev, self.fstype))
947     def cleanup(self):
948         Module.cleanup(self)
949         if not self.obdtype == 'obdecho':
950             clean_loop(self.devname)
951
952 class OST(Module):
953     def __init__(self,dom_node):
954         Module.__init__(self, 'OST', dom_node)
955         self.obd_uuid = get_first_ref(dom_node, 'obd')
956         self.add_module('lustre/ost', 'ost')
957
958     def prepare(self):
959         self.info(self.obd_uuid)
960         lctl.newdev(attach="ost %s %s" % (self.name, self.uuid),
961                     setup ="%s" % (self.obd_uuid))
962
963
964 # virtual interface for  OSC and LOV
965 class VOSC(Module):
966     def __init__(self,dom_node):
967         Module.__init__(self, 'VOSC', dom_node)
968         if dom_node.nodeName == 'lov':
969             self.osc = LOV(dom_node)
970         else:
971             self.osc = OSC(dom_node)
972     def prepare(self):
973         self.osc.prepare()
974     def cleanup(self):
975         self.osc.cleanup()
976     def load_module(self):
977         self.osc.load_module()
978     def cleanup_module(self):
979         self.osc.cleanup_module()
980         
981
982 class OSC(Module):
983     def __init__(self,dom_node):
984         Module.__init__(self, 'OSC', dom_node)
985         self.obd_uuid = get_first_ref(dom_node, 'obd')
986         self.ost_uuid = get_first_ref(dom_node, 'ost')
987         self.lookup_server(self.ost_uuid)
988         self.add_module('lustre/osc', 'osc')
989
990     def prepare(self):
991         self.info(self.obd_uuid, self.ost_uuid)
992         srv = self.get_server()
993         if local_net(srv):
994             lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
995         else:
996             r =  find_route(srv)
997             if r:
998                 lctl.add_route_host(r[0], srv.uuid, r[1], r[2])
999             else:
1000                 panic ("no route to",  srv.nid)
1001             
1002         lctl.newdev(attach="osc %s %s" % (self.name, self.uuid),
1003                     setup ="%s %s" %(self.obd_uuid, srv.uuid))
1004
1005     def cleanup(self):
1006         srv = self.get_server()
1007         if local_net(srv):
1008             Module.cleanup(self)
1009         else:
1010             self.info(self.obd_uuid, self.ost_uuid)
1011             r =  find_route(srv)
1012             if r:
1013                 try:
1014                     lctl.del_route_host(r[0], srv.uuid, r[1], r[2])
1015                 except CommandError, e:
1016                     print "del_route failed: ", self.name
1017                     e.dump()
1018                     cleanup_error(e.rc)
1019             Module.cleanup(self)
1020             
1021
1022 class Mountpoint(Module):
1023     def __init__(self,dom_node):
1024         Module.__init__(self, 'MTPT', dom_node)
1025         self.path = get_text(dom_node, 'path')
1026         self.mds_uuid = get_first_ref(dom_node, 'mds')
1027         self.lov_uuid = get_first_ref(dom_node, 'osc')
1028         self.add_module('lustre/mdc', 'mdc')
1029         self.add_module('lustre/llite', 'llite')
1030         l = lookup(self.dom_node.parentNode, self.lov_uuid)
1031         self.osc = VOSC(l)
1032
1033     def prepare(self):
1034         self.osc.prepare()
1035         mdc_uuid = prepare_mdc(self.dom_node.parentNode, self.mds_uuid)
1036
1037         self.info(self.path, self.mds_uuid,self.lov_uuid)
1038         cmd = "mount -t lustre_lite -o osc=%s,mdc=%s none %s" % \
1039               (self.lov_uuid, mdc_uuid, self.path)
1040         run("mkdir", self.path)
1041         ret, val = run(cmd)
1042         if ret:
1043             panic("mount failed:", self.path)
1044
1045     def cleanup(self):
1046         self.info(self.path, self.mds_uuid,self.lov_uuid)
1047         (rc, out) = run("umount", self.path)
1048         if rc:
1049             log("umount failed, cleanup will most likely not work.")
1050         l = lookup(self.dom_node.parentNode, self.lov_uuid)
1051         self.osc.cleanup()
1052         cleanup_mdc(self.dom_node.parentNode, self.mds_uuid)
1053
1054     def load_module(self):
1055         self.osc.load_module()
1056         Module.load_module(self)
1057     def cleanup_module(self):
1058         Module.cleanup_module(self)
1059         self.osc.cleanup_module()
1060
1061
1062 # ============================================================
1063 # XML processing and query
1064 # TODO: Change query funcs to use XPath, which is muc cleaner
1065
1066 def get_device(obd):
1067     list = obd.getElementsByTagName('device')
1068     if len(list) > 0:
1069         dev = list[0]
1070         dev.normalize();
1071         size = get_attr_int(dev, 'size', 0)
1072         return dev.firstChild.data, size
1073     return '', 0
1074
1075 # Get the text content from the first matching child
1076 # If there is no content (or it is all whitespace), return
1077 # the default
1078 def get_text(dom_node, tag, default=""):
1079     list = dom_node.getElementsByTagName(tag)
1080     if len(list) > 0:
1081         dom_node = list[0]
1082         dom_node.normalize()
1083         if dom_node.firstChild:
1084             txt = string.strip(dom_node.firstChild.data)
1085             if txt:
1086                 return txt
1087     return default
1088
1089 def get_text_int(dom_node, tag, default=0):
1090     list = dom_node.getElementsByTagName(tag)
1091     n = default
1092     if len(list) > 0:
1093         dom_node = list[0]
1094         dom_node.normalize()
1095         if dom_node.firstChild:
1096             txt = string.strip(dom_node.firstChild.data)
1097             if txt:
1098                 try:
1099                     n = int(txt)
1100                 except ValueError:
1101                     panic("text value is not integer:", txt)
1102     return n
1103
1104 def get_attr(dom_node, attr, default=""):
1105     v = dom_node.getAttribute(attr)
1106     if v:
1107         return v
1108     return default
1109
1110 def get_attr_int(dom_node, attr, default=0):
1111     n = default
1112     v = dom_node.getAttribute(attr)
1113     if v:
1114         try:
1115             n = int(v)
1116         except ValueError:
1117             panic("attr value is not integer", v)
1118     return n
1119
1120 def get_first_ref(dom_node, tag):
1121     """ Get the first uuidref of the type TAG. Used one only
1122     one is expected.  Returns the uuid."""
1123     uuid = None
1124     refname = '%s_ref' % tag
1125     list = dom_node.getElementsByTagName(refname)
1126     if len(list) > 0:
1127         uuid = getRef(list[0])
1128     return uuid
1129     
1130 def get_all_refs(dom_node, tag):
1131     """ Get all the refs of type TAG.  Returns list of uuids. """
1132     uuids = []
1133     refname = '%s_ref' % tag
1134     list = dom_node.getElementsByTagName(refname)
1135     if len(list) > 0:
1136         for i in list:
1137             uuids.append(getRef(i))
1138     return uuids
1139
1140 def get_ost_net(dom_node, uuid):
1141     ost = lookup(dom_node, uuid)
1142     uuid = get_first_ref(ost, 'network')
1143     if not uuid:
1144         return None
1145     return lookup(dom_node, uuid)
1146
1147 def nid2server(dom_node, nid):
1148     netlist = dom_node.getElementsByTagName('network')
1149     for net_node in netlist:
1150         if get_text(net_node, 'server') == nid:
1151             return Network(net_node)
1152     return None
1153     
1154 def lookup(dom_node, uuid):
1155     for n in dom_node.childNodes:
1156         if n.nodeType == n.ELEMENT_NODE:
1157             if getUUID(n) == uuid:
1158                 return n
1159             else:
1160                 n = lookup(n, uuid)
1161                 if n: return n
1162     return None
1163             
1164 # Get name attribute of dom_node
1165 def getName(dom_node):
1166     return dom_node.getAttribute('name')
1167
1168 def getRef(dom_node):
1169     return dom_node.getAttribute('uuidref')
1170
1171 # Get name attribute of dom_node
1172 def getUUID(dom_node):
1173     return dom_node.getAttribute('uuid')
1174
1175 # the tag name is the service type
1176 # fixme: this should do some checks to make sure the dom_node is a service
1177 def getServiceType(dom_node):
1178     return dom_node.nodeName
1179
1180 #
1181 # determine what "level" a particular node is at.
1182 # the order of iniitailization is based on level. 
1183 def getServiceLevel(dom_node):
1184     type = getServiceType(dom_node)
1185     if type in ('network',):
1186         return 10
1187     elif type in ('device', 'ldlm'):
1188         return 20
1189     elif type in ('obd', 'mdd'):
1190         return 30
1191     elif type in ('mds','ost'):
1192         return 40
1193     elif type in ('mdc','osc'):
1194         return 50
1195     elif type in ('lov', 'lovconfig'):
1196         return 60
1197     elif type in ('mountpoint',):
1198         return 70
1199     return 0
1200
1201 #
1202 # return list of services in a profile. list is a list of tuples
1203 # [(level, dom_node),]
1204 def getServices(lustreNode, profileNode):
1205     list = []
1206     for n in profileNode.childNodes:
1207         if n.nodeType == n.ELEMENT_NODE:
1208             servNode = lookup(lustreNode, getRef(n))
1209             if not servNode:
1210                 print n
1211                 panic('service not found: ' + getRef(n))
1212             level = getServiceLevel(servNode)
1213             list.append((level, servNode))
1214     list.sort()
1215     return list
1216
1217 def getByName(lustreNode, name, tag):
1218     ndList = lustreNode.getElementsByTagName(tag)
1219     for nd in ndList:
1220         if getName(nd) == name:
1221             return nd
1222     return None
1223     
1224
1225 ############################################################
1226 # MDC UUID hack - 
1227 # FIXME: clean this mess up!
1228 #
1229 mdc_uuid = None
1230 def prepare_mdc(dom_node, mds_uuid):
1231     global mdc_uuid
1232     mds_node = lookup(dom_node, mds_uuid);
1233     if not mds_node:
1234         panic("no mds:", mds_uuid)
1235     if mdc_uuid:
1236         return mdc_uuid
1237     mdc = MDC(mds_node)
1238     mdc.prepare()
1239     mdc_uuid = mdc.uuid
1240     return mdc_uuid
1241
1242 mdc_cleaned = None
1243 def cleanup_mdc(dom_node, mds_uuid):
1244     global mdc_cleaned
1245     mds_node = lookup(dom_node, mds_uuid);
1246     if not mds_node:
1247         panic("no mds:", mds_uuid)
1248     if not mdc_cleaned:
1249         mdc = MDC(mds_node)
1250         mdc.cleanup()
1251         mdc_uuid = None
1252         mdc_cleaned = 'yes'
1253         
1254
1255 ############################################################
1256 # routing ("rooting")
1257 #
1258 routes = []
1259 local_node = []
1260 router_flag = 0
1261
1262 def init_node(dom_node):
1263     global local_node, router_flag
1264     netlist = dom_node.getElementsByTagName('network')
1265     for dom_net in netlist:
1266         type = get_attr(dom_net, 'type')
1267         gw = get_text(dom_net, 'server')
1268         local_node.append((type, gw))
1269
1270 def node_needs_router():
1271     return router_flag
1272
1273 def get_routes(type, gw, dom_net):
1274     """ Return the routes as a list of tuples of the form:
1275         [(type, gw, lo, hi),]"""
1276     res = []
1277     tbl = dom_net.getElementsByTagName('route_tbl')
1278     for t in tbl:
1279         routes = t.getElementsByTagName('route')
1280         for r in routes:
1281             lo = get_attr(r, 'lo')
1282             hi = get_attr(r, 'hi', '')
1283             res.append((type, gw, lo, hi))
1284     return res
1285     
1286
1287 def init_route_config(lustre):
1288     """ Scan the lustre config looking for routers.  Build list of
1289     routes. """
1290     global routes, router_flag
1291     routes = []
1292     list = lustre.getElementsByTagName('node')
1293     for node in list:
1294         if get_attr(node, 'router'):
1295             router_flag = 1
1296             for (local_type, local_nid) in local_node:
1297                 gw = None
1298                 netlist = node.getElementsByTagName('network')
1299                 for dom_net in netlist:
1300                     if local_type == get_attr(dom_net, 'type'):
1301                         gw = get_text(dom_net, 'server')
1302                         break
1303                 if not gw:
1304                     continue
1305                 for dom_net in netlist:
1306                     if local_type != get_attr(dom_net, 'type'):
1307                         for route in get_routes(local_type, gw, dom_net):
1308                             routes.append(route)
1309     
1310
1311 def local_net(net):
1312     global local_node
1313     for iface in local_node:
1314         if net.net_type == iface[0]:
1315             return 1
1316     return 0
1317
1318 def find_route(net):
1319     global local_node, routes
1320     frm_type = local_node[0][0]
1321     to_type = net.net_type
1322     to = net.nid
1323     debug ('looking for route to', to_type,to)
1324     for r in routes:
1325         if  r[2] == to:
1326             return r
1327     return None
1328            
1329     
1330         
1331
1332 ############################################################
1333 # lconf level logic
1334 # Start a service.
1335 def startService(dom_node, module_flag):
1336     type = getServiceType(dom_node)
1337     debug('Service:', type, getName(dom_node), getUUID(dom_node))
1338     # there must be a more dynamic way of doing this...
1339     n = None
1340     if type == 'ldlm':
1341         n = LDLM(dom_node)
1342     elif type == 'lov':
1343         n = LOV(dom_node)
1344     elif type == 'lovconfig':
1345         n = LOVConfig(dom_node)
1346     elif type == 'network':
1347         n = Network(dom_node)
1348     elif type == 'obd':
1349         n = OBD(dom_node)
1350     elif type == 'ost':
1351         n = OST(dom_node)
1352     elif type == 'mds':
1353         n = MDS(dom_node)
1354     elif type == 'osc':
1355         n = VOSC(dom_node)
1356     elif type == 'mdc':
1357         n = MDC(dom_node)
1358     elif type == 'mountpoint':
1359         n = Mountpoint(dom_node)
1360     else:
1361         panic ("unknown service type:", type)
1362
1363     if module_flag:
1364         if config.nomod():
1365             return
1366         if config.cleanup():
1367             n.cleanup_module()
1368         else:
1369             n.load_module()
1370     else:
1371         if config.nosetup():
1372             return
1373         if config.cleanup():
1374             n.cleanup()
1375         else:
1376             n.prepare()
1377
1378 #
1379 # Prepare the system to run lustre using a particular profile
1380 # in a the configuration. 
1381 #  * load & the modules
1382 #  * setup networking for the current node
1383 #  * make sure partitions are in place and prepared
1384 #  * initialize devices with lctl
1385 # Levels is important, and needs to be enforced.
1386 def startProfile(lustreNode, profileNode, module_flag):
1387     if not profileNode:
1388         panic("profile:", profile, "not found.")
1389     services = getServices(lustreNode, profileNode)
1390     if config.cleanup():
1391         services.reverse()
1392     for s in services:
1393         startService(s[1], module_flag)
1394
1395
1396 #
1397 # Load profile for 
1398 def doHost(lustreNode, hosts):
1399     global routes
1400     dom_node = None
1401     for h in hosts:
1402         dom_node = getByName(lustreNode, h, 'node')
1403         if dom_node:
1404             break
1405
1406     if not dom_node:
1407         print 'No host entry found.'
1408         return
1409
1410     if not get_attr(dom_node, 'router'):
1411         init_node(dom_node)
1412         init_route_config(lustreNode)
1413     else:
1414         global router_flag 
1415         router_flag = 1
1416
1417     # Two step process: (1) load modules, (2) setup lustre
1418     # if not cleaning, load modules first.
1419     module_flag = not config.cleanup()
1420     reflist = dom_node.getElementsByTagName('profile')
1421     for profile in reflist:
1422             startProfile(lustreNode,  profile, module_flag)
1423
1424     if not config.cleanup():
1425         sys_set_debug_path()
1426         script = config.gdb_script()
1427         run(lctl.lctl, ' modules >', script)
1428         if config.gdb():
1429             # dump /tmp/ogdb and sleep/pause here
1430             log ("The GDB module script is in", script)
1431             time.sleep(5)
1432             
1433     module_flag = not module_flag
1434     for profile in reflist:
1435             startProfile(lustreNode,  profile, module_flag)
1436
1437 ############################################################
1438 # Command line processing
1439 #
1440 def parse_cmdline(argv):
1441     short_opts = "hdnv"
1442     long_opts = ["ldap", "reformat", "lustre=", "verbose", "gdb",
1443                  "portals=", "makeldiff", "cleanup", "noexec",
1444                  "help", "node=", "nomod", "nosetup",
1445                  "dump="]
1446     opts = []
1447     args = []
1448     try:
1449         opts, args = getopt.getopt(argv, short_opts, long_opts)
1450     except getopt.error:
1451         print "invalid opt"
1452         usage()
1453
1454     for o, a in opts:
1455         if o in ("-h", "--help"):
1456             usage()
1457         if o in ("-d","--cleanup"):
1458             config.cleanup(1)
1459         if o in ("-v", "--verbose"):
1460             config.verbose(1)
1461         if o in ("-n", "--noexec"):
1462             config.noexec(1)
1463             config.verbose(1)
1464         if o == "--portals":
1465             config.portals =  a
1466         if o == "--lustre":
1467             config.lustre  = a
1468         if o  == "--reformat":
1469             config.reformat(1)
1470         if o  == "--node":
1471             config.node(a)
1472         if o  == "--gdb":
1473             config.gdb(1)
1474         if o  == "--nomod":
1475             config.nomod(1)
1476         if o  == "--nosetup":
1477             config.nosetup(1)
1478         if o  == "--dump":
1479             config.dump_file(a)
1480     return args
1481
1482 def fetch(url):
1483     import urllib
1484     data = ""
1485     try:
1486         s = urllib.urlopen(url)
1487         data = s.read()
1488     except:
1489         usage()
1490     return data
1491
1492 def setupModulePath(cmd):
1493     base = os.path.dirname(cmd)
1494     if os.access(base+"/Makefile", os.R_OK):
1495         config.src_dir(base + "/../../")
1496
1497 def sys_set_debug_path():
1498     debug("debug path: ", config.debug_path())
1499     if config.noexec():
1500         return
1501     try:
1502         fp = open('/proc/sys/portals/debug_path', 'w')
1503         fp.write(config.debug_path())
1504         fp.close()
1505     except IOError, e:
1506         print e
1507              
1508 #/proc/sys/net/core/rmem_max
1509 #/proc/sys/net/core/wmem_max
1510 def sys_set_netmem_max(path, max):
1511     debug("setting", path, "to at least", max)
1512     if config.noexec():
1513         return
1514     fp = open(path)
1515     str = fp.readline()
1516     fp.close
1517     cur = int(str)
1518     if max > cur:
1519         fp = open(path, 'w')
1520         fp.write('%d\n' %(max))
1521         fp.close()
1522     
1523     
1524 def sys_make_devices():
1525     if not os.access('/dev/portals', os.R_OK):
1526         run('mknod /dev/portals c 10 240')
1527     if not os.access('/dev/obd', os.R_OK):
1528         run('mknod /dev/obd c 10 241')
1529
1530 # Initialize or shutdown lustre according to a configuration file
1531 #   * prepare the system for lustre
1532 #   * configure devices with lctl
1533 # Shutdown does steps in reverse
1534 #
1535 def main():
1536     global TCP_ACCEPTOR, lctl, MAXTCPBUF
1537     host = socket.gethostname()
1538
1539     args = parse_cmdline(sys.argv[1:])
1540     if len(args) > 0:
1541         if not os.access(args[0], os.R_OK | os.W_OK):
1542             print 'File not found:', args[0]
1543             sys.exit(1)
1544         dom = xml.dom.minidom.parse(args[0])
1545     elif config.url():
1546         xmldata = fetch(config.url())
1547         dom = xml.dom.minidom.parseString(xmldata)
1548     else:
1549         usage()
1550
1551     node_list = []
1552     if config.node():
1553         node_list.append(config.node())
1554     else:
1555         if len(host) > 0:
1556             node_list.append(host)
1557         node_list.append('localhost')
1558     debug("configuring for host: ", node_list)
1559
1560     if len(host) > 0:
1561         config._debug_path = config._debug_path + '-' + host
1562         config._gdb_script = config._gdb_script + '-' + host
1563
1564     TCP_ACCEPTOR = find_prog('acceptor')
1565     if not TCP_ACCEPTOR:
1566         if config.noexec():
1567             TCP_ACCEPTOR = 'acceptor'
1568             debug('! acceptor not found')
1569         else:
1570             panic('acceptor not found')
1571
1572     lctl = LCTLInterface('lctl')
1573
1574     setupModulePath(sys.argv[0])
1575     sys_make_devices()
1576     sys_set_netmem_max('/proc/sys/net/core/rmem_max', MAXTCPBUF)
1577     sys_set_netmem_max('/proc/sys/net/core/wmem_max', MAXTCPBUF)
1578     doHost(dom.documentElement, node_list)
1579
1580 if __name__ == "__main__":
1581     try:
1582         main()
1583     except LconfError, e:
1584         print e
1585     except CommandError, e:
1586         e.dump()
1587         sys.exit(e.rc)
1588
1589     if first_cleanup_error:
1590         sys.exit(first_cleanup_error)
1591 2