3 # Copyright (C) 2002 Cluster File Systems, Inc.
4 # Author: Robert Read <rread@clusterfs.com>
6 # This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
21 # lconf - lustre configuration tool
23 # lconf is the main driver script for starting and stopping
24 # lustre filesystem services.
26 # Based in part on the XML obdctl modifications done by Brian Behlendorf
29 import string, os, stat, popen2, socket, time
31 import xml.dom.minidom
37 # Maximum number of devices to search for.
38 # (the /dev/loop* nodes need to be created beforehand)
39 MAX_LOOP_DEVICES = 256
43 print """usage: lconf config.xml
45 config.xml Lustre configuration in xml format.
46 --get <url> URL to fetch a config file
47 -v | --verbose Print system commands as they are run
48 -d | --debug Print system commands, but does not run them
49 --node <nodename> Load config for <nodename>
50 --cleanup Cleans up config. (Shutdown)
51 -h | --help Print this help
52 --gdb Create a gdb script to load the modules. Prints message
53 after creating script and sleeps for 5 seconds.
56 --ldap server LDAP server with lustre config database
57 --reformat Reformat all devices (will confirm)
58 --lustre="src dir" Base directory of lustre sources. Used to search
60 --portals=src Portals source
61 --makeldiff Translate xml source to LDIFF
65 # ============================================================
66 # Config parameters, encapsulated in a class
81 self._gdb_script = '/tmp/ogdb'
82 self._debug_path = '/tmp/lustre-log'
85 def verbose(self, flag = None):
86 if flag: self._verbose = flag
89 def noexec(self, flag = None):
90 if flag: self._noexec = flag
93 def reformat(self, flag = None):
94 if flag: self._reformat = flag
97 def cleanup(self, flag = None):
98 if flag: self._cleanup = flag
101 def gdb(self, flag = None):
102 if flag: self._gdb = flag
105 def nomod(self, flag = None):
106 if flag: self._nomod = flag
109 def nosetup(self, flag = None):
110 if flag: self._nosetup = flag
113 def node(self, val = None):
114 if val: self._node = val
117 def url(self, val = None):
118 if val: self._url = val
121 def gdb_script(self):
122 if os.path.isdir('/r'):
123 return '/r' + self._gdb_script
125 return self._gdb_script
127 def debug_path(self):
128 if os.path.isdir('/r'):
129 return '/r' + self._debug_path
131 return self._debug_path
133 def src_dir(self, val = None):
134 if val: self._url = val
139 # ============================================================
140 # debugging and error funcs
142 def fixme(msg = "this feature"):
143 raise RuntimeError, msg + ' not implmemented yet.'
146 msg = string.join(map(str,args))
148 if not config.noexec():
149 raise RuntimeError, msg
152 msg = string.join(map(str,args))
157 print string.strip(s)
161 msg = string.join(map(str,args))
164 # ============================================================
165 # locally defined exceptions
166 class CommandError (exceptions.Exception):
167 def __init__(self, args=None):
170 # ============================================================
171 # handle lctl interface
174 Manage communication with lctl
177 def __init__(self, cmd):
179 Initialize close by finding the lctl binary.
181 self.lctl = find_prog(cmd)
184 debug('! lctl not found')
187 raise CommandError, "unable to find lctl binary."
192 the cmds are written to stdin of lctl
193 lctl doesn't return errors when run in script mode, so
195 should modify command line to accept multiple commands, or
196 create complex command line options
198 debug("+", self.lctl, cmds)
199 if config.noexec(): return (0, [])
200 p = popen2.Popen3(self.lctl, 1)
201 p.tochild.write(cmds + "\n")
204 out = p.fromchild.readlines()
206 debug('lctl:',string.strip(l))
207 err = p.childerr.readlines()
209 log (self.lctl, "error:", ret)
211 raise CommandError, err
214 def network(self, net, nid):
215 """ initialized network and add "self" """
216 # Idea: "mynid" could be used for all network types to add "self," and then
217 # this special case would be gone and the "self" hack would be hidden.
223 quit""" % (net, nid, nid)
232 # create a new connection
233 def connect(self, net, nid, port, servuuid, send_buf, read_buf):
234 # XXX: buf size params not used yet
239 quit""" % (net, nid, port, servuuid, nid)
242 # create a new connection
243 def add_route(self, net, to, via):
248 # disconnect one connection
249 def disconnect(self, net, nid, port, servuuid):
254 quit""" % (net, nid, servuuid)
257 # disconnect all connections
258 def disconnectAll(self, net):
266 # create a new device with lctl
267 def newdev(self, attach, setup = ""):
272 quit""" % (attach, setup)
276 def cleanup(self, name, uuid):
285 def lovconfig(self, uuid, mdsuuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist):
289 lovconfig %s %d %d %d %s %s
290 quit""" % (mdsuuid, uuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist)
293 # ============================================================
294 # Various system-level functions
295 # (ideally moved to their own module)
297 # Run a command and return the output and status.
298 # stderr is sent to /dev/null, could use popen3 to
299 # save it if necessary
301 cmd = string.join(map(str,args))
303 if config.noexec(): return (0, [])
304 f = os.popen(cmd + ' 2>&1')
313 # Run a command in the background.
314 def run_daemon(*args):
315 cmd = string.join(map(str,args))
317 if config.noexec(): return 0
318 f = os.popen(cmd + ' 2>&1')
326 # Determine full path to use for an external command
327 # searches dirname(argv[0]) first, then PATH
329 syspath = string.split(os.environ['PATH'], ':')
330 cmdpath = os.path.dirname(sys.argv[0])
331 syspath.insert(0, cmdpath);
332 syspath.insert(0, os.path.join(cmdpath, '../../portals/linux/utils/'))
334 prog = os.path.join(d,cmd)
335 if os.access(prog, os.X_OK):
339 # Recursively look for file starting at base dir
340 def do_find_file(base, mod):
341 fullname = os.path.join(base, mod)
342 if os.access(fullname, os.R_OK):
344 for d in os.listdir(base):
345 dir = os.path.join(base,d)
346 if os.path.isdir(dir):
347 module = do_find_file(dir, mod)
351 def find_module(src_dir, modname):
352 mod = '%s.o' % (modname)
353 search = (src_dir + "/lustre", src_dir + "/portals/linux")
356 module = do_find_file(d, mod)
363 # is the path a block device?
370 return stat.S_ISBLK(s[stat.ST_MODE])
372 # build fs according to type
374 def mkfs(fstype, dev):
375 if(fstype in ('ext3', 'extN')):
376 mkfs = 'mkfs.ext2 -j -b 4096'
378 print 'unsupported fs type: ', fstype
379 if not is_block(dev):
383 (ret, out) = run (mkfs, force, dev)
385 panic("Unable to build fs:", dev)
386 # enable hash tree indexing on fs
388 htree = 'echo "feature FEATURE_C5" | debugfs -w'
389 (ret, out) = run (htree, dev)
391 panic("Unable to enable htree:", dev)
393 # some systems use /dev/loopN, some /dev/loop/N
397 if not os.access(loop + str(0), os.R_OK):
399 if not os.access(loop + str(0), os.R_OK):
400 panic ("can't access loop devices")
403 # find loop device assigned to thefile
406 for n in xrange(0, MAX_LOOP_DEVICES):
408 if os.access(dev, os.R_OK):
409 (stat, out) = run('losetup', dev)
410 if (out and stat == 0):
411 m = re.search(r'\((.*)\)', out[0])
412 if m and file == m.group(1):
418 # create file if necessary and assign the first free loop device
419 def init_loop(file, size, fstype):
420 dev = find_loop(file)
422 print 'WARNING file:', file, 'already mapped to', dev
424 if not os.access(file, os.R_OK | os.W_OK):
425 run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size, file))
427 # find next free loop
428 for n in xrange(0, MAX_LOOP_DEVICES):
430 if os.access(dev, os.R_OK):
431 (stat, out) = run('losetup', dev)
433 run('losetup', dev, file)
436 print "out of loop devices"
438 print "out of loop devices"
441 # undo loop assignment
442 def clean_loop(file):
443 dev = find_loop(file)
445 ret, out = run('losetup -d', dev)
447 log('unable to clean loop device:', dev, 'for file:', file)
450 # initialize a block device if needed
451 def block_dev(dev, size, fstype, format):
452 if config.noexec(): return dev
453 if not is_block(dev):
454 dev = init_loop(dev, size, fstype)
455 if (format == 'yes'):
459 # ============================================================
460 # Classes to prepare and cleanup the various objects
463 """ Base class for the rest of the modules. The default cleanup method is
464 defined here, as well as some utilitiy funcs.
466 def __init__(self, tag_name, node):
468 self.tag_name = tag_name
469 self.name = node.getAttribute('name')
470 self.uuid = node.getAttribute('uuid')
471 self.kmodule_list = []
473 def info(self, *args):
474 msg = string.join(map(str,args))
475 print self.tag_name + ":", self.name, self.uuid, msg
478 """ default cleanup, used for most modules """
481 lctl.cleanup(self.name, self.uuid)
483 print "cleanup failed: ", self.name
485 def add_module(self, modname):
486 """Append a module to list of modules to load."""
487 self.kmodule_list.append(modname)
489 def mod_loaded(self, modname):
490 """Check if a module is already loaded. Look in /proc/modules for it."""
491 fp = open('/proc/modules')
492 lines = fp.readlines()
494 # please forgive my tired fingers for this one
495 ret = filter(lambda word, mod=modname: word == mod,
496 map(lambda line: string.split(line)[0], lines))
499 def load_module(self):
500 """Load all the modules in the list in the order they appear."""
501 for mod in self.kmodule_list:
502 # (rc, out) = run ('/sbin/lsmod | grep -s', mod)
503 if self.mod_loaded(mod) and not config.noexec():
506 module = find_module(config.src_dir(), mod)
508 panic('module not found:', mod)
509 (rc, out) = run('/sbin/insmod', module)
511 raise CommandError, "insmod failed: %s" %(module)
513 (rc, out) = run('/sbin/modprobe', mod)
515 raise CommandError, "modprobe failed: %s" %(module)
517 def cleanup_module(self):
518 """Unload the modules in the list in reverse order."""
519 rev = self.kmodule_list
525 run('/sbin/rmmod', mod)
528 class Network(Module):
529 def __init__(self,node):
530 Module.__init__(self, 'NETWORK', node)
531 self.net_type = node.getAttribute('type')
532 self.nid = getText(node, 'server', "")
533 self.port = int(getText(node, 'port', 0))
534 self.send_buf = int(getText(node, 'send_buf', 0))
535 self.read_buf = int(getText(node, 'read_buf', 0))
537 self.add_module('portals')
538 if self.net_type == 'tcp':
539 self.add_module('ksocknal')
540 if self.net_type == 'elan':
541 self.add_module('kqswnal')
542 if self.net_type == 'gm':
543 self.add_module('kgmnal')
544 self.add_module('obdclass')
545 self.add_module('ptlrpc')
548 self.info(self.net_type, self.nid, self.port)
549 if self.net_type == 'tcp':
550 ret = run_daemon(TCP_ACCEPTOR, self.port)
553 raise CommandError, "cannot run acceptor"
554 lctl.network(self.net_type, self.nid)
555 lctl.newdev(attach = "ptlrpc RPCDEV")
558 self.info(self.net_type, self.nid, self.port)
560 lctl.cleanup("RPCDEV", "")
561 lctl.disconnectAll(self.net_type)
563 print "cleanup failed: ", self.name
564 if self.net_type == 'tcp':
565 # yikes, this ugly! need to save pid in /var/something
566 run("killall acceptor")
569 def __init__(self,node):
570 Module.__init__(self, 'LDLM', node)
571 self.add_module('ldlm')
572 self.add_module('extN') # yuck, fix dupe handling and move this
575 lctl.newdev(attach="ldlm %s %s" % (self.name, self.uuid),
579 def __init__(self,node):
580 Module.__init__(self, 'LOV', node)
581 devs = node.getElementsByTagName('devices')[0]
582 self.stripe_sz = int(devs.getAttribute('stripesize'))
583 self.stripe_off = int(devs.getAttribute('stripeoffset'))
584 self.pattern = int(devs.getAttribute('pattern'))
585 mdsref = node.getElementsByTagName('mds_ref')[0]
586 self.mdsuuid = mdsref.getAttribute('uuidref')
587 mds= lookup(node.parentNode, self.mdsuuid)
588 self.mdsname = getName(mds)
591 for child in devs.childNodes:
592 if child.nodeName == 'osc_ref':
593 devlist = devlist + child.getAttribute('uuidref') + " "
594 stripe_cnt = stripe_cnt + 1
595 self.devlist = devlist
596 self.stripe_cnt = stripe_cnt
597 self.add_module('osc')
598 self.add_module('lov')
601 self.info(self.mdsuuid, self.stripe_cnt, self.stripe_sz, self.stripe_off, self.pattern,
602 self.devlist, self.mdsname)
603 lctl.lovconfig(self.uuid, self.mdsname, self.stripe_cnt,
604 self.stripe_sz, self.stripe_off, self.pattern,
611 def __init__(self,node):
612 Module.__init__(self, 'MDS', node)
613 self.devname, self.size = getDevice(node)
614 self.fstype = getText(node, 'fstype')
615 self.format = getText(node, 'autoformat', "no")
616 self.add_module('mds')
617 self.add_module('mds_%s' % (self.fstype))
620 self.info(self.devname, self.fstype, self.format)
621 blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
622 lctl.newdev(attach="mds %s %s" % (self.name, self.uuid),
623 setup ="%s %s" %(blkdev, self.fstype))
626 clean_loop(self.devname)
629 def __init__(self,node):
630 Module.__init__(self, 'MDC', node)
631 ref = node.getElementsByTagName('mds_ref')[0]
632 self.mds_uuid = ref.getAttribute('uuidref')
633 self.add_module('mdc')
636 self.info(self.mds_uuid)
637 mds = lookup(self.dom_node.parentNode, self.mds_uuid)
639 panic(self.mdsuuid, "not found.")
640 net = get_ost_net(self.dom_node.parentNode, self.mds_uuid)
642 lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_buf, srv.read_buf)
643 lctl.newdev(attach="mdc %s %s" % (self.name, self.uuid),
644 setup ="%s %s" %(self.mds_uuid, srv.uuid))
647 self.info(self.mds_uuid)
648 net = get_ost_net(self.dom_node.parentNode, self.mds_uuid)
651 lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
652 lctl.cleanup(self.name, self.uuid)
654 print "cleanup failed: ", self.name
657 def __init__(self, node):
658 Module.__init__(self, 'OBD', node)
659 self.obdtype = node.getAttribute('type')
660 self.devname, self.size = getDevice(node)
661 self.fstype = getText(node, 'fstype')
662 self.format = getText(node, 'autoformat', 'yes')
663 self.add_module(self.obdtype)
665 # need to check /proc/mounts and /etc/mtab before
666 # formatting anything.
667 # FIXME: check if device is already formatted.
669 self.info(self.obdtype, self.devname, self.size, self.fstype, self.format)
670 blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
671 lctl.newdev(attach="%s %s %s" % (self.obdtype, self.name, self.uuid),
672 setup ="%s %s" %(blkdev, self.fstype))
675 clean_loop(self.devname)
678 def __init__(self,node):
679 Module.__init__(self, 'OST', node)
680 ref = node.getElementsByTagName('obd_ref')[0]
681 self.obd_uuid = ref.getAttribute('uuidref')
682 self.add_module('ost')
685 self.info(self.obd_uuid)
686 lctl.newdev(attach="ost %s %s" % (self.name, self.uuid),
687 setup ="%s" % (self.obd_uuid))
690 def __init__(self,node):
691 Module.__init__(self, 'OSC', node)
692 ref = node.getElementsByTagName('obd_ref')[0]
693 self.obd_uuid = ref.getAttribute('uuidref')
694 ref = node.getElementsByTagName('ost_ref')[0]
695 self.ost_uuid = ref.getAttribute('uuidref')
696 self.add_module('osc')
699 self.info(self.obd_uuid, self.ost_uuid)
700 net = get_ost_net(self.dom_node.parentNode, self.ost_uuid)
702 lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_buf, srv.read_buf)
703 lctl.newdev(attach="osc %s %s" % (self.name, self.uuid),
704 setup ="%s %s" %(self.obd_uuid, srv.uuid))
707 self.info(self.obd_uuid, self.ost_uuid)
708 net_uuid = get_ost_net(self.dom_node.parentNode, self.ost_uuid)
709 srv = Network(net_uuid)
711 lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
712 lctl.cleanup(self.name, self.uuid)
714 print "cleanup failed: ", self.name
716 class Mountpoint(Module):
717 def __init__(self,node):
718 Module.__init__(self, 'MTPT', node)
719 self.path = getText(node, 'path')
720 ref = node.getElementsByTagName('mdc_ref')[0]
721 self.mdc_uuid = ref.getAttribute('uuidref')
722 ref = node.getElementsByTagName('osc_ref')[0]
723 self.lov_uuid = ref.getAttribute('uuidref')
724 self.add_module('osc')
725 self.add_module('llite')
728 l = lookup(self.dom_node.parentNode, self.lov_uuid)
729 if l.nodeName == 'lov':
731 for osc_uuid in string.split(lov.devlist):
732 osc = lookup(self.dom_node.parentNode, osc_uuid)
737 panic('osc not found:', osc_uuid)
738 lctl.newdev(attach="lov %s %s" % (lov.name, lov.uuid),
739 setup ="%s" % (self.mdc_uuid))
744 self.info(self.path, self.mdc_uuid,self.lov_uuid)
745 cmd = "mount -t lustre_lite -o osc=%s,mdc=%s none %s" % \
746 (self.lov_uuid, self.mdc_uuid, self.path)
747 run("mkdir", self.path)
750 panic("mount failed:", self.path)
752 self.info(self.path, self.mdc_uuid,self.lov_uuid)
753 run("umount", self.path)
754 l = lookup(self.dom_node.parentNode, self.lov_uuid)
755 if l.nodeName == 'lov':
757 for osc_uuid in string.split(lov.devlist):
758 osc = lookup(self.dom_node.parentNode, osc_uuid)
763 panic('osc not found:', osc_uuid)
769 # ============================================================
770 # XML processing and query
771 # TODO: Change query funcs to use XPath, which is muc cleaner
774 dev = obd.getElementsByTagName('device')[0]
777 size = int(dev.getAttribute('size'))
780 return dev.firstChild.data, size
782 # Get the text content from the first matching child
783 def getText(node, tag, default=""):
784 list = node.getElementsByTagName(tag)
788 return node.firstChild.data
792 def get_ost_net(node, uuid):
793 ost = lookup(node, uuid)
794 list = ost.getElementsByTagName('network_ref')
796 uuid = list[0].getAttribute('uuidref')
799 return lookup(node, uuid)
801 def lookup(node, uuid):
802 for n in node.childNodes:
803 if n.nodeType == n.ELEMENT_NODE:
804 if getUUID(n) == uuid:
811 # Get name attribute of node
813 return node.getAttribute('name')
816 return node.getAttribute('uuidref')
818 # Get name attribute of node
820 return node.getAttribute('uuid')
822 # the tag name is the service type
823 # fixme: this should do some checks to make sure the node is a service
824 def getServiceType(node):
828 # determine what "level" a particular node is at.
829 # the order of iniitailization is based on level. objects
830 # are assigned a level based on type:
831 # net,devices,ldlm:1, obd, mdd:2 mds,ost:3 osc,mdc:4 mounts:5
832 def getServiceLevel(node):
833 type = getServiceType(node)
834 if type in ('network',):
836 if type in ('device', 'ldlm'):
838 elif type in ('obd', 'mdd'):
840 elif type in ('mds','ost'):
842 elif type in ('mdc','osc'):
844 elif type in ('lov',):
846 elif type in ('mountpoint',):
851 # return list of services in a profile. list is a list of tuples
853 def getServices(lustreNode, profileNode):
855 for n in profileNode.childNodes:
856 if n.nodeType == n.ELEMENT_NODE:
857 servNode = lookup(lustreNode, getRef(n))
860 panic('service not found: ' + getRef(n))
861 level = getServiceLevel(servNode)
862 list.append((level, servNode))
866 def getByName(lustreNode, tag, name):
867 ndList = lustreNode.getElementsByTagName(tag)
869 if getName(nd) == name:
874 # ============================================================
877 def startService(node, clean_flag, module_flag):
878 type = getServiceType(node)
879 debug('Service:', type, getName(node), getUUID(node))
880 # there must be a more dynamic way of doing this...
886 elif type == 'network':
898 elif type == 'mountpoint':
901 panic ("unknown service type:", type)
919 # Prepare the system to run lustre using a particular profile
920 # in a the configuration.
921 # * load & the modules
922 # * setup networking for the current node
923 # * make sure partitions are in place and prepared
924 # * initialize devices with lctl
925 # Levels is important, and needs to be enforced.
926 def startProfile(lustreNode, profileNode, clean_flag, module_flag):
928 panic("profile:", profile, "not found.")
929 services = getServices(lustreNode, profileNode)
933 startService(s[1], clean_flag, module_flag)
937 def doHost(lustreNode, hosts, clean_flag):
940 node = getByName(lustreNode, 'node', h)
945 print 'No host entry found.'
948 # Two step process: (1) load modules, (2) setup lustre
949 # if not cleaning, load modules first.
950 module_flag = not clean_flag
951 reflist = node.getElementsByTagName('profile')
952 for profile in reflist:
953 startProfile(lustreNode, profile, clean_flag, module_flag)
957 script = config.gdb_script()
958 run(lctl.lctl, ' modules >', script)
960 # dump /tmp/ogdb and sleep/pause here
961 log ("The GDB module script is in", script)
964 module_flag = not module_flag
965 for profile in reflist:
966 startProfile(lustreNode, profile, clean_flag, module_flag)
968 # Command line processing
970 def parse_cmdline(argv):
972 long_opts = ["ldap", "reformat", "lustre=", "verbose", "gdb",
973 "portals=", "makeldiff", "cleanup",
974 "help", "debug", "node=", "get=", "nomod", "nosetup"]
978 opts, args = getopt.getopt(argv, short_opts, long_opts)
979 except getopt.GetoptError:
984 if o in ("-h", "--help"):
988 if o in ("-v", "--verbose"):
990 if o in ("-d", "--debug"):
997 if o == "--reformat":
1007 if o == "--nosetup":
1015 s = urllib.urlopen(url)
1021 def setupModulePath(cmd):
1022 base = os.path.dirname(cmd)
1023 if os.access(base+"/Makefile", os.R_OK):
1024 config.src_dir(base + "/../../")
1027 debug("debug path: ", config.debug_path())
1030 fp = open('/proc/sys/portals/debug_path', 'w')
1031 fp.write(config.debug_path())
1036 if not os.access('/dev/portals', os.R_OK):
1037 run('mknod /dev/portals c 10 240')
1038 if not os.access('/dev/obd', os.R_OK):
1039 run('mknod /dev/obd c 10 241')
1041 # Initialize or shutdown lustre according to a configuration file
1042 # * prepare the system for lustre
1043 # * configure devices with lctl
1044 # Shutdown does steps in reverse
1047 global TCP_ACCEPTOR, lctl
1048 args = parse_cmdline(sys.argv[1:])
1050 if not os.access(args[0], os.R_OK | os.W_OK):
1051 print 'File not found:', args[0]
1053 dom = xml.dom.minidom.parse(args[0])
1055 xmldata = fetch(config.url())
1056 dom = xml.dom.minidom.parseString(xmldata)
1062 node_list.append(config.node())
1064 host = socket.gethostname()
1066 node_list.append(host)
1067 node_list.append('localhost')
1068 print "configuring for host: ", node_list
1070 TCP_ACCEPTOR = find_prog('acceptor')
1071 if not TCP_ACCEPTOR:
1073 TCP_ACCEPTOR = 'acceptor'
1074 debug('! acceptor not found')
1076 panic('acceptor not found')
1078 lctl = LCTLInterface('lctl')
1080 setupModulePath(sys.argv[0])
1082 doHost(dom.documentElement, node_list, config.cleanup())
1084 if __name__ == "__main__":
1087 except RuntimeError:
1089 except CommandError:
1090 print 'FIXME: insert exception data here'