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