Whamcloud - gitweb
- allow lconf to continue to run in debug mode even if acceptor and lctl
[fs/lustre-release.git] / lustre / utils / lconf
index 43a3a2a..d8b278a 100755 (executable)
 # Based in part on the XML obdctl modifications done by Brian Behlendorf 
 
 import sys, getopt
-import string, os, stat, popen2
+import string, os, stat, popen2, socket
 import re, exceptions
 import xml.dom.minidom
 
 # Global parameters
-TCP_ACCEPTOR = 'acceptor'
+TCP_ACCEPTOR = ''
 options = {}
 
 #
@@ -44,9 +44,12 @@ def usage():
     print """usage: lconf config.xml
 
 config.xml          Lustre configuration in xml format.
+--get <url>         URL to fetch a config file
 -v | --verbose      Print system commands as they are run
 -d | --debug        Print system commands, but does not run them
+--host <hostname>   Load config for <hostname>
 --cleanup          Cleans up config. (Shutdown)
+-h | --help         Print this help 
 """
     TODO = """
 --ldap server      LDAP server with lustre config database
@@ -105,16 +108,13 @@ class LCTLInterface:
         """
         Initialize close by finding the lctl binary.
         """
-        syspath = string.split(os.environ['PATH'], ':')
-        syspath.insert(0, "../utils");
-        self.lctlcmd = None
-        for d in syspath:
-            lctl = os.path.join(d,cmd)
-            if os.access(lctl, os.X_OK):
-                self.lctl = lctl
-                break
+        self.lctl = find_prog(cmd)
         if not self.lctl:
-            raise RuntimeError,  "unable to find lctl binary."
+            if isnotouch():
+                debug('! lctl not found')
+                self.lctl = 'lctl'
+            else:
+                raise CommandError,  "unable to find lctl binary."
             
     def run(self, cmds):
         """
@@ -132,24 +132,36 @@ class LCTLInterface:
         p.tochild.close()
         out = p.fromchild.readlines()
         ret = p.poll()
+        for l in out:
+            debug('lctl:',string.strip(l))
         err = p.childerr.readlines()
         if ret or len(err):
             log (self.lctl, "error:", ret)
             logall(err)
             raise CommandError, err
         return ret, out
-        
-        
-    # create a new device with lctl
+
     def network(self, net, nid):
-        cmds =  """
+        """ initialized network and add "self" """
+        # Idea: "mynid" could be used for all network types to add "self," and then
+        # this special case would be gone and the "self" hack would be hidden.
+        if net  == 'tcp':
+            cmds =  """
   network %s
   mynid %s
+  add_uuid self %s
+  quit""" % (net, nid, nid)
+        else:
+            cmds =  """
+  network %s
+  add_uuid self %s
   quit""" % (net, nid)
+            
         self.run(cmds)
 
     # create a new connection 
-    def connect(self, net, nid, port, servuuid):
+    def connect(self, net, nid, port, servuuid, send_buf, read_buf):
+        # XXX: buf size params not used yet
         cmds =  """
   network %s
   connect %s %d
@@ -157,6 +169,12 @@ class LCTLInterface:
   quit""" % (net, nid, port,  servuuid, nid)
         self.run(cmds)
                 
+    # create a new connection 
+    def add_route(self, net, to, via):
+        cmds =  """
+        """ 
+        #self.run(cmds)
+
     # create a new device with lctl
     def disconnect(self, net, nid, port, servuuid):
         cmds =  """
@@ -166,7 +184,7 @@ class LCTLInterface:
         self.run(cmds)
 
     # create a new device with lctl
-    def newdev(self, attach, setup):
+    def newdev(self, attach, setup = ""):
         cmds = """
   newdev
   attach %s
@@ -184,12 +202,12 @@ class LCTLInterface:
         self.run(cmds)
 
     # create an lov
-    def lovconfig(self, uuid, mdcuuid, stripe_cnt, stripe_sz, pattern, devlist):
+    def lovconfig(self, uuid, mdsuuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist):
         cmds = """
   device $%s
   probe
-  lovconfig %s %d %d %s %s
-  quit""" % (mdcuuid, uuid, stripe_cnt, stripe_sz, pattern, devlist)
+  lovconfig %s %d %d %d %s %s
+  quit""" % (mdsuuid, uuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist)
         self.run(cmds)
 
 # ============================================================
@@ -202,7 +220,7 @@ class LCTLInterface:
 def run(*args):
     cmd = string.join(map(str,args))
     debug ("+", cmd)
-    if isnotouch(): return ([], 0)
+    if isnotouch(): return (0, [])
     f = os.popen(cmd + ' 2>&1')
     out = f.readlines()
     ret = f.close()
@@ -212,6 +230,33 @@ def run(*args):
         ret = 0
     return (ret, out)
 
+# Run a command in the background.
+def run_daemon(*args):
+    cmd = string.join(map(str,args))
+    debug ("+", cmd)
+    if isnotouch(): return 0
+    f = os.popen(cmd + ' 2>&1')
+    ret = f.close()
+    if ret:
+        ret = ret >> 8
+    else:
+        ret = 0
+    return ret
+
+
+# Determine full path to use for an external command
+# searches dirname(argv[0]) first, then PATH
+def find_prog(cmd):
+    syspath = string.split(os.environ['PATH'], ':')
+    cmdpath = os.path.dirname(sys.argv[0])
+    syspath.insert(0, cmdpath);
+    syspath.insert(0, os.path.join(cmdpath, '../../portals/linux/utils/'))
+    for d in syspath:
+        prog = os.path.join(d,cmd)
+        if os.access(prog, os.X_OK):
+            return prog
+    return ''
+
 
 # is the path a block device?
 def is_block(path):
@@ -225,17 +270,23 @@ def is_block(path):
 # build fs according to type
 # fixme: dangerous
 def mkfs(fstype, dev):
-    if(fstype == 'ext3'):
-        mkfs = 'mkfs.ext2 -j'
-    elif (fstype == 'extN'):
-        mkfs = 'mkfs.ext2 -j'
+    if(fstype in ('ext3', 'extN')):
+        mkfs = 'mkfs.ext2 -j -b 4096'
     else:
         print 'unsupported fs type: ', fstype
     if not is_block(dev):
         force = '-F'
     else:
         force = ''
-    run (mkfs, force, dev)
+    (ret, out) = run (mkfs, force, dev)
+    if ret:
+        panic("Unable to build fs:", dev)
+    # enable hash tree indexing on fs
+    if fstype == 'extN':
+        htree = 'echo "feature FEATURE_C5" | debugfs -w'
+        (ret, out) = run (htree, dev)
+        if ret:
+            panic("Unable to enable htree:", dev)
 
 # some systems use /dev/loopN, some /dev/loop/N
 def loop_base():
@@ -304,147 +355,237 @@ def block_dev(dev, size, fstype, format):
     return dev
 
 # ============================================================
-# Functions to prepare the various objects
-
-def prepare_ldlm(node):
-    (name, uuid) = getNodeAttr(node)
-    print 'LDLM:', name, uuid
-    lctl.newdev(attach="ldlm %s %s" % (name, uuid),
-                setup ="")
-    
-def prepare_lov(node):
-    (name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist) = getLOVInfo(node)
-    print 'LOV:', name, uuid
-    lctl.lovconfig(uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist)
-
-def prepare_network(node):
-    (name, uuid, type, nid, port) = getNetworkInfo(node)
-    print 'NETWORK:', type, nid, port
-    if type == 'tcp':
-        run(TCP_ACCEPTOR, port)
-    lctl.network(type, nid)
-
-
-# need to check /proc/mounts and /etc/mtab before
-# formatting anything.
-# FIXME: check if device is already formatted.
-def prepare_obd(obd):
-    (name, uuid, obdtype, dev, size, fstype, format) = getOBDInfo(obd)
-    print "OBD: ", name, obdtype, dev, size, fstype, format
-    dev = block_dev(dev, size, fstype, format)
-    lctl.newdev(attach="%s %s %s" % (obdtype, name, uuid),
-                setup ="%s %s" %(dev, fstype))
-    
-
-def prepare_ost(ost):
-    name, uuid, obd = getOSTInfo(ost)
-    print "OST: ", name, uuid, obd
-    lctl.newdev(attach="ost %s %s" % (name, uuid),
-                setup ="$%s" % (obd))
-
-def prepare_mds(node):
-    (name, uuid, dev, size, fstype, format) = getMDSInfo(node)
-    print "MDS: ", name, dev, size, fstype
-    # setup network for mds, too
-    dev = block_dev(dev, size, fstype, format)
-    lctl.newdev(attach="mds %s %s" % (name, uuid),
-                setup ="%s %s" %(dev, fstype))
-
-def prepare_osc(node):
-    (name, uuid, obduuid, srvuuid) = getOSCInfo(node)
-    print 'OSC:', name, uuid, obduuid, srvuuid
-    net = lookup(node.parentNode, srvuuid)
-    srvname, srvuuid, net, server, port = getNetworkInfo(net)
-    lctl.connect(net, server, port, srvuuid)
-    lctl.newdev(attach="osc %s %s" % (name, uuid),
-                setup ="%s %s" %(obduuid, srvuuid))
-
-def prepare_mdc(node):
-    (name, uuid, mdsuuid, netuuid) = getMDCInfo(node)
-    print 'MDC:', name, uuid, mdsuuid, netuuid
-    lctl.newdev(attach="mdc %s %s" % (name, uuid),
-                setup ="%s %s" %(mdsuuid, netuuid))
-
-def prepare_mountpoint(node):
-    print 'MTPT:'
-
-# ============================================================
-# Functions to cleanup the various objects
-
-def cleanup_ldlm(node):
-    (name, uuid) = getNodeAttr(node)
-    print 'LDLM:', name, uuid
-    try:
-        lctl.cleanup(name, uuid)
-    except CommandError:
-        print "cleanup failed: ", name
-
-def cleanup_lov(node):
-    (name, uuid) = getNodeAttr(node)
-    print 'LOV:', name, uuid
-
-    #lctl.cleanup(name, uuid)
-
-def cleanup_network(node):
-    (name, uuid, type, nid, port) = getNetworkInfo(node)
-    print 'NETWORK:', type, nid, port
-    #lctl.network(type, nid)
-
-# need to check /proc/mounts and /etc/mtab before
-# formatting anything.
-# FIXME: check if device is already formatted.
-def cleanup_obd(obd):
-    (name, uuid, obdtype, dev, size, fstype, format) = getOBDInfo(obd)
-    print "OBD: ", name, obdtype, dev, size, fstype, format
-    try:
-        lctl.cleanup(name, uuid)
-    except CommandError:
-        print "cleanup failed: ", name
-    clean_loop(dev)
-
-def cleanup_ost(ost):
-    name, uuid, obd = getOSTInfo(ost)
-    print "OST: ", name, uuid, obd
-    try:
-        lctl.cleanup(name, uuid)
-    except CommandError:
-        print "cleanup failed: ", name
-
-def cleanup_mds(node):
-    (name, uuid, dev, size, fstype, format) = getMDSInfo(node)
-    print "MDS: ", name, dev, size, fstype
-    try:
-        lctl.cleanup(name, uuid)
-    except CommandError:
-        print "cleanup failed: ", name
-    clean_loop(dev)
-        
-
-def cleanup_mdc(node):
-    (name, uuid, mdsuuid, netuuid) = getMDCInfo(node)
-    print 'MDC:', name, uuid, mdsuuid, netuuid
-    try:
-        lctl.cleanup(name, uuid)
-    except CommandError:
-        print "cleanup failed: ", name
-
-
-def cleanup_osc(node):
-    (name, uuid, obduuid, srvuuid) = getOSCInfo(node)
-    print 'OSC:', name, uuid, obduuid, srvuuid
-    net = lookup(node.parentNode, srvuuid)
-    netname, netuuid, net, server, port = getNetworkInfo(net)
-    try:
-        lctl.disconnect(net, server, port, srvuuid)
-        lctl.cleanup(name, uuid)
-    except CommandError:
-        print "cleanup failed: ", name
-
-def cleanup_mountpoint(node):
-    print 'MTPT:'
+# Classes to prepare and cleanup the various objects
+#
+class Module:
+    """ Base class for the rest of the modules. The default cleanup method is
+    defined here, as well as some utilitiy funcs.
+    """
+    def __init__(self, tag_name, node):
+        self.dom_node = node
+        self.tag_name = tag_name
+        self.name = node.getAttribute('name')
+        self.uuid = node.getAttribute('uuid')
+
+    def info(self, *args):
+        msg = string.join(map(str,args))
+        print self.tag_name + ":", self.name, self.uuid, msg
+
+    def cleanup(self):
+        """ default cleanup, used for most modules """
+        self.info()
+        try:
+            lctl.cleanup(self.name, self.uuid)
+        except CommandError:
+            print "cleanup failed: ", self.name
+
+class Network(Module):
+    def __init__(self,node):
+        Module.__init__(self, 'NETWORK', node)
+        self.net_type = node.getAttribute('type')
+        self.nid = getText(node, 'server', "")
+        self.port = int(getText(node, 'port', 0))
+        self.send_buf = int(getText(node, 'send_buf', 0))
+        self.read_buf = int(getText(node, 'read_buf', 0))
+
+    def prepare(self):
+        self.info(self.net_type, self.nid, self.port)
+        if self.net_type == 'tcp':
+            ret = run_daemon(TCP_ACCEPTOR, self.port)
+            if ret:
+                print "error:", ret
+                raise CommandError, "cannot run acceptor"
+        lctl.network(self.net_type, self.nid)
+        lctl.newdev(attach = "ptlrpc RPCDEV")
+
+    def cleanup(self):
+        self.info(self.net_type, self.nid, self.port)
+        try:
+            lctl.cleanup("RPCDEV", "")
+        except CommandError:
+            print "cleanup failed: ", self.name
+        if self.net_type == 'tcp':
+            # yikes, this ugly! need to save pid in /var/something
+            run("killall acceptor")
+
+class LDLM(Module):
+    def __init__(self,node):
+        Module.__init__(self, 'LDLM', node)
+    def prepare(self):
+        self.info()
+        lctl.newdev(attach="ldlm %s %s" % (self.name, self.uuid),
+                    setup ="")
+
+class LOV(Module):
+    def __init__(self,node):
+        Module.__init__(self, 'LOV', node)
+        devs = node.getElementsByTagName('devices')[0]
+        self.stripe_sz = int(devs.getAttribute('stripesize'))
+        self.stripe_off = int(devs.getAttribute('stripeoffset'))
+        self.pattern = int(devs.getAttribute('pattern'))
+        mdsref =  node.getElementsByTagName('mds_ref')[0]
+        self.mdsuuid = mdsref.getAttribute('uuidref')
+        mds= lookup(node.parentNode, self.mdsuuid)
+        self.mdsname = getName(mds)
+        devlist = ""
+        stripe_cnt = 0
+        for child in devs.childNodes:
+            if child.nodeName == 'osc_ref':
+                devlist = devlist +  child.getAttribute('uuidref') + " "
+                stripe_cnt = stripe_cnt + 1
+        self.devlist = devlist
+        self.stripe_cnt = stripe_cnt
+
+    def prepare(self):
+        self.info(self.mdsuuid, self.stripe_cnt, self.stripe_sz, self.stripe_off, self.pattern,
+        self.devlist, self.mdsname)
+        lctl.lovconfig(self.uuid, self.mdsname, self.stripe_cnt,
+                       self.stripe_sz, self.stripe_off, self.pattern,
+                       self.devlist)
+
+    def cleanup(self):
+        pass
+
+class MDS(Module):
+    def __init__(self,node):
+        Module.__init__(self, 'MDS', node)
+        self.devname, self.size = getDevice(node)
+        self.fstype = getText(node, 'fstype')
+        self.format = getText(node, 'autoformat', "no")
+
+    def prepare(self):
+        self.info(self.devname, self.fstype, self.format)
+        blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
+        lctl.newdev(attach="mds %s %s" % (self.name, self.uuid),
+                    setup ="%s %s" %(blkdev, self.fstype))
+    def cleanup(self):
+        Module.cleanup(self)
+        clean_loop(self.devname)
+
+class MDC(Module):
+    def __init__(self,node):
+        Module.__init__(self, 'MDC', node)
+        ref = node.getElementsByTagName('mds_ref')[0]
+        self.mds_uuid = ref.getAttribute('uuidref')
+
+    def prepare(self):
+        self.info(self.mds_uuid)
+        mds = lookup(self.dom_node.parentNode, self.mds_uuid)
+        if mds == None:
+            panic(self.mdsuuid, "not found.")
+        net = get_ost_net(self.dom_node.parentNode, self.mds_uuid)
+        srv = Network(net)
+        lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_buf, srv.read_buf)
+        lctl.newdev(attach="mdc %s %s" % (self.name, self.uuid),
+                        setup ="%s %s" %(self.mds_uuid, srv.uuid))
+            
+    def cleanup(self):
+        self.info(self.mds_uuid)
+        net = get_ost_net(self.dom_node.parentNode, self.mds_uuid)
+        srv = Network(net)
+        try:
+            lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
+            lctl.cleanup(self.name, self.uuid)
+        except CommandError:
+            print "cleanup failed: ", self.name
+
+class OBD(Module):
+    def __init__(self, node):
+        Module.__init__(self, 'OBD', node)
+        self.obdtype = node.getAttribute('type')
+        self.devname, self.size = getDevice(node)
+        self.fstype = getText(node, 'fstype')
+        self.format = getText(node, 'autoformat', 'yes')
+
+    # need to check /proc/mounts and /etc/mtab before
+    # formatting anything.
+    # FIXME: check if device is already formatted.
+    def prepare(self):
+        self.info(self.obdtype, self.devname, self.size, self.fstype, self.format)
+        blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
+        lctl.newdev(attach="%s %s %s" % (self.obdtype, self.name, self.uuid),
+                    setup ="%s %s" %(blkdev, self.fstype))
+    def cleanup(self):
+        Module.cleanup(self)
+        clean_loop(self.devname)
+
+class OST(Module):
+    def __init__(self,node):
+        Module.__init__(self, 'OST', node)
+        ref = node.getElementsByTagName('obd_ref')[0]
+        self.obd_uuid = ref.getAttribute('uuidref')
+
+    def prepare(self):
+        self.info(self.obd_uuid)
+        lctl.newdev(attach="ost %s %s" % (self.name, self.uuid),
+                    setup ="%s" % (self.obd_uuid))
+
+class OSC(Module):
+    def __init__(self,node):
+        Module.__init__(self, 'OSC', node)
+        ref = node.getElementsByTagName('obd_ref')[0]
+        self.obd_uuid = ref.getAttribute('uuidref')
+        ref = node.getElementsByTagName('ost_ref')[0]
+        self.ost_uuid = ref.getAttribute('uuidref')
+
+    def prepare(self):
+        self.info(self.obd_uuid, self.ost_uuid)
+        net = get_ost_net(self.dom_node.parentNode, self.ost_uuid)
+        srv = Network(net)
+        lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_buf, srv.read_buf)
+        lctl.newdev(attach="osc %s %s" % (self.name, self.uuid),
+                    setup ="%s %s" %(self.obd_uuid, srv.uuid))
+
+    def cleanup(self):
+        self.info(self.obd_uuid, self.ost_uuid)
+        net_uuid = get_ost_net(self.dom_node.parentNode, self.ost_uuid)
+        srv = Network(net)
+        try:
+            lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
+            lctl.cleanup(self.name, self.uuid)
+        except CommandError:
+            print "cleanup failed: ", self.name
+
+class Mountpoint(Module):
+    def __init__(self,node):
+        Module.__init__(self, 'MTPT', node)
+        self.path = getText(node, 'path')
+        ref = node.getElementsByTagName('mdc_ref')[0]
+        self.mdc_uuid = ref.getAttribute('uuidref')
+        ref = node.getElementsByTagName('osc_ref')[0]
+        self.lov_uuid = ref.getAttribute('uuidref')
+
+    def prepare(self):
+        l = lookup(self.dom_node.parentNode, self.lov_uuid)
+        if l.nodeName == 'lov':
+            dev = LOV(l)
+            for osc_uuid in string.split(dev.devlist):
+                osc = lookup(self.dom_node.parentNode, osc_uuid)
+                if osc:
+                    n = OSC(osc)
+                    n.prepare()
+                else:
+                    panic('osc not found:', osc_uuid)
+        else:
+            dev = OSC(l)
+            dev.prepare()
+            
+        self.info(self.path, self.mdc_uuid,self.lov_uuid)
+        lctl.newdev(attach="lov %s %s" % (dev.name, dev.uuid),
+                    setup ="%s" % (self.mdc_uuid))
+        cmd = "mount -t lustre_lite -o osc=%s,mdc=%s none %s" % \
+              (self.lov_uuid, self.mdc_uuid, self.path)
+        run("mkdir", self.path)
+        ret, val = run(cmd)
+        if ret:
+            panic("mount failed:", self.path)
+    def cleanup(self):
+        self.info(self.path, self.mdc_uuid,self.lov_uuid)
+        run("umount", self.path)
 
 # ============================================================
 # XML processing and query
+# TODO: Change query funcs to use XPath, which is muc cleaner
 
 def getDevice(obd):
     dev = obd.getElementsByTagName('device')[0]
@@ -454,87 +595,7 @@ def getDevice(obd):
     except ValueError:
         size = 0
     return dev.firstChild.data, size
-    
 
-def getNetworkInfo(node):
-    name, uuid = getNodeAttr(node);
-    type = node.getAttribute('type')
-    nid = getText(node, 'server', "")
-    port = int(getText(node, 'port', 0))
-    return name, uuid, type, nid, port
-    
-# extract device attributes for an obd
-def getNodeAttr(node):
-    name = node.getAttribute('name')
-    uuid = node.getAttribute('uuid')
-    return name, uuid
-
-def getOBDInfo(obd):
-    name, uuid = getNodeAttr(obd);
-    obdtype = obd.getAttribute('type')
-    devname, size = getDevice(obd)
-    fstype = getText(obd, 'fstype')
-    format = getText(obd, 'autoformat')
-    return (name, uuid, obdtype, devname, size, fstype, format)
-    
-# extract LOV
-def getLOVInfo(node):
-    name, uuid = getNodeAttr(node)
-    devs = node.getElementsByTagName('devices')[0]
-    stripe_sz = int(devs.getAttribute('stripesize'))
-    pattern = int(devs.getAttribute('pattern'))
-    mdcref =  node.getElementsByTagName('mdc_ref')[0]
-    mdcuuid = mdcref.getAttribute('uuidref')
-    mdc= lookup(node.parentNode, mdcuuid)
-    mdcname = getName(mdc)
-    devlist = ""
-    stripe_cnt = 0
-    for child in devs.childNodes:
-        if child.nodeName == 'obd_ref':
-            devlist = devlist +  child.getAttribute('uuidref') + " "
-            strip_cnt = stripe_cnt + 1
-    return (name, uuid, mdcname, stripe_cnt, stripe_sz, pattern, devlist)
-    
-# extract device attributes for an obd
-def getMDSInfo(node):
-    name, uuid = getNodeAttr(node)
-    devname, size = getDevice(node)
-    fstype = getText(node, 'fstype')
-    format = getText(node, 'autoformat', "no")
-    return (name, uuid, devname, size, fstype, format)
-
-# extract device attributes for an obd
-def getMDCInfo(node):
-    name, uuid = getNodeAttr(node)
-    ref = node.getElementsByTagName('mds_ref')[0]
-    mdsuuid = ref.getAttribute('uuidref')
-    ref = node.getElementsByTagName('network_ref')[0]
-    netuuid = ref.getAttribute('uuidref')
-    return (name, uuid, mdsuuid, netuuid)
-
-    
-# extract device attributes for an obd
-def getOSTInfo(node):
-    name, uuid = getNodeAttr(node)
-    ref = node.getElementsByTagName('obd_ref')[0]
-    uuid = ref.getAttribute('uuidref')
-    obd = lookup(node.parentNode, uuid)
-    if obd:
-         obdname = getOBDInfo(obd)[0]
-    else:
-        obdname = "OBD NOT FOUND"
-    return (name, uuid, obdname)
-
-# extract device attributes for an obd
-def getOSCInfo(node):
-    name, uuid = getNodeAttr(node)
-    ref = node.getElementsByTagName('obd_ref')[0]
-    obduuid = ref.getAttribute('uuidref')
-    ref = node.getElementsByTagName('network_ref')[0]
-    ostuuid = ref.getAttribute('uuidref')
-    return (name, uuid, obduuid, ostuuid)
-
-    
 # Get the text content from the first matching child
 def getText(node, tag, default=""):
     list = node.getElementsByTagName(tag)
@@ -545,11 +606,17 @@ def getText(node, tag, default=""):
     else:
         return default
 
-# Recusively search from node for a uuid
+def get_ost_net(node, uuid):
+    ost = lookup(node, uuid)
+    list = ost.getElementsByTagName('network_ref')
+    if list:
+        uuid = list[0].getAttribute('uuidref')
+    else:
+        return None
+    return lookup(node, uuid)
+    
 def lookup(node, uuid):
     for n in node.childNodes:
-        # this service_id check is ugly. need some other way to
-        # differentiate between definitions and references
         if n.nodeType == n.ELEMENT_NODE:
             if getUUID(n) == uuid:
                 return n
@@ -557,7 +624,7 @@ def lookup(node, uuid):
                 n = lookup(n, uuid)
                 if n: return n
     return None
-
+            
 # Get name attribute of node
 def getName(node):
     return node.getAttribute('name')
@@ -578,21 +645,23 @@ def getServiceType(node):
 # determine what "level" a particular node is at.
 # the order of iniitailization is based on level.  objects
 # are assigned a level based on type:
-#  net,devices:1, obd, mdd:2  mds,ost:3 osc,mdc:4 mounts:5
+#  net,devices,ldlm:1, obd, mdd:2  mds,ost:3 osc,mdc:4 mounts:5
 def getServiceLevel(node):
     type = getServiceType(node)
-    if type in ('network', 'device', 'ldlm'):
+    if type in ('network',):
         return 1
-    elif type in ('obd', 'mdd'):
+    if type in ('device', 'ldlm'):
         return 2
-    elif type in ('mds','ost'):
+    elif type in ('obd', 'mdd'):
         return 3
-    elif type in ('mdc','osc'):
+    elif type in ('mds','ost'):
         return 4
-    elif type in ('lov',):
+    elif type in ('mdc','osc'):
         return 5
-    elif type in ('mountpoint',):
+    elif type in ('lov',):
         return 6
+    elif type in ('mountpoint',):
+        return 7
     return 0
 
 #
@@ -604,7 +673,8 @@ def getServices(lustreNode, profileNode):
         if n.nodeType == n.ELEMENT_NODE:
             servNode = lookup(lustreNode, getRef(n))
             if not servNode:
-                panic('service not found: ' + getName(n))
+                print n
+                panic('service not found: ' + getRef(n))
             level = getServiceLevel(servNode)
             list.append((level, servNode))
     list.sort()
@@ -619,33 +689,38 @@ def getByName(lustreNode, tag, name):
     
 
 # ============================================================
-# lconf type level logic
-#
-
-#
+# lconf level logic
 # Start a service.
-def startService(node):
+def startService(node, cleanFlag):
     type = getServiceType(node)
     debug('Starting service:', type, getName(node), getUUID(node))
     # there must be a more dynamic way of doing this...
+    n = None
     if type == 'ldlm':
-        prepare_ldlm(node)
+        n = LDLM(node)
     elif type == 'lov':
-        prepare_lov(node)
+        n = LOV(node)
     elif type == 'network':
-        prepare_network(node)
+        n = Network(node)
     elif type == 'obd':
-        prepare_obd(node)
+        n = OBD(node)
     elif type == 'ost':
-        prepare_ost(node)
+        n = OST(node)
     elif type == 'mds':
-        prepare_mds(node)
+        n = MDS(node)
     elif type == 'osc':
-        prepare_osc(node)
+        n = OSC(node)
     elif type == 'mdc':
-        prepare_mdc(node)
+        n = MDC(node)
     elif type == 'mountpoint':
-        prepare_mountpoint(node)
+        n = Mountpoint(node)
+    else:
+        panic ("unknown service type:", type)
+
+    if cleanFlag:
+        n.cleanup()
+    else:
+        n.prepare()
 
 #
 # Prepare the system to run lustre using a particular profile
@@ -655,69 +730,39 @@ def startService(node):
 #  * make sure partitions are in place and prepared
 #  * initialize devices with lctl
 # Levels is important, and needs to be enforced.
-def startProfile(lustreNode, profileNode):
-    if not profileNode:
-        panic("profile:", profile, "not found.")
-    services = getServices(lustreNode, profileNode)
-    for s in services:
-        startService(s[1])
-
-
-# Stop a service.
-def stopService(node):
-    type = getServiceType(node)
-    debug('Stopping service:', type, getName(node), getUUID(node))
-    # there must be a more dynamic way of doing this...
-    if type == 'ldlm':
-        cleanup_ldlm(node)
-    elif type == 'lov':
-        cleanup_lov(node)
-    elif type == 'network':
-        cleanup_network(node)
-    elif type == 'obd':
-        cleanup_obd(node)
-    elif type == 'ost':
-        cleanup_ost(node)
-    elif type == 'mds':
-        cleanup_mds(node)
-    elif type == 'osc':
-        cleanup_osc(node)
-    elif type == 'mdc':
-        cleanup_mdc(node)
-    elif type == 'mountpoint':
-        cleanup_mountpoint(node)
-
-# Shutdown services in reverse order than they were started
-def cleanupProfile(lustreNode, profileNode):
+def startProfile(lustreNode, profileNode, cleanFlag):
     if not profileNode:
         panic("profile:", profile, "not found.")
     services = getServices(lustreNode, profileNode)
-    services.reverse()
+    if cleanFlag:
+        services.reverse()
     for s in services:
-        stopService(s[1])
+        startService(s[1], cleanFlag)
 
+#
+# Load profile for 
+def doHost(lustreNode, hosts, cleanFlag):
+    node = None
+    for h in hosts:
+        node = getByName(lustreNode, 'node', h)
+        if node:
+            break
 
-def doHost(lustreNode, hostname, cleanFlag):
-    node = getByName(lustreNode, 'node', hostname)
     if not node:
-        node = getByName(lustreNode, 'node', 'localhost')
-        if not node:
-            panic("no node for ", hostname)
-    reflist = node.getElementsByTagName('profile_ref')
-    for r in reflist:
-        if cleanFlag:
-            cleanupProfile(lustreNode, lookup(lustreNode, getRef(r)))
-        else:
-            startProfile(lustreNode,  lookup(lustreNode, getRef(r)))
+        print 'No host entry found.'
+        return
+
+    reflist = node.getElementsByTagName('profile')
+    for profile in reflist:
+            startProfile(lustreNode,  profile, cleanFlag)
 
-#
 # Command line processing
 #
 def parse_cmdline(argv):
     short_opts = "hdv"
-    long_opts = ["ldap", "reformat", "lustre=",
+    long_opts = ["ldap", "reformat", "lustre=", "verbose",
                  "portals=", "makeldiff", "cleanup", "iam=",
-                 "help", "debug"]
+                 "help", "debug", "host=", "get="]
     opts = []
     args = []
     global options
@@ -743,30 +788,68 @@ def parse_cmdline(argv):
             options['lustre'] = a
         if o  == "--reformat":
             options['reformat'] = 1
+        if o  == "--host":
+            options['hostname'] = [a]
+        if o  == "--get":
+            options['url'] = a
     return args
 
-#
+def fetch(url):
+    import urllib
+    data = ""
+    try:
+        s = urllib.urlopen(url)
+        data = s.read()
+    except:
+        usage()
+    return data
+
 # Initialize or shutdown lustre according to a configuration file
 #   * prepare the system for lustre
 #   * configure devices with lctl
 # Shutdown does steps in reverse
 #
-lctl = LCTLInterface('lctl')
 def main():
-    global options
+    global options, TCP_ACCEPTOR, lctl
     args = parse_cmdline(sys.argv[1:])
     if len(args) > 0:
+        if not os.access(args[0], os.R_OK | os.W_OK):
+            print 'File not found:', args[0]
+            sys.exit(1)
         dom = xml.dom.minidom.parse(args[0])
+    elif options.has_key('url'):
+        xmldata = fetch(options['url'])
+        dom = xml.dom.minidom.parseString(xmldata)
     else:
         usage()
 
     if not options.has_key('hostname'):
-        ret, host = run('hostname')
-        if ret:
-            panic("unable to determine hostname")
-        options['hostname'] = host
-    doHost(dom.childNodes[0], options['hostname'], options.has_key('cleanup') )
+        options['hostname'] = []
+        host = socket.gethostname()
+        if len(host) > 0:
+            options['hostname'].append(host)
+        options['hostname'].append('localhost')
+    print "configuring for host: ", options['hostname']
+
+    TCP_ACCEPTOR = find_prog('acceptor')
+    if not TCP_ACCEPTOR:
+        if isnotouch():
+            TCP_ACCEPTOR = 'acceptor'
+            debug('! acceptor not found')
+        else:
+            panic('acceptor not found')
+
+    lctl = LCTLInterface('lctl')
+
+    doHost(dom.documentElement, options['hostname'], options.has_key('cleanup') )
 
 if __name__ == "__main__":
-    main()
+    try:
+        main()
+    except RuntimeError:
+        pass
+    except CommandError:
+        print '<insert exception data here>'
+        pass
+