Whamcloud - gitweb
We need an mdc_ref for a mountpoint, and not an mds_ref.
[fs/lustre-release.git] / lustre / utils / lconf
index b39a302..9a9a077 100755 (executable)
@@ -32,8 +32,8 @@ import xml.dom.minidom
 
 # Global parameters
 TCP_ACCEPTOR = 'acceptor'
-LCTL = './lctl' # fix this...
 options = {}
+
 #
 # Maximum number of devices to search for.
 # (the /dev/loop* nodes need to be created beforehand)
@@ -41,24 +41,25 @@ MAX_LOOP_DEVICES = 256
 
 
 def usage():
-    print """usage: lconf --ldap server | config.xml
+    print """usage: lconf config.xml
 
 config.xml          Lustre configuration in xml format.
+-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
-
-Options:
--v|--verbose           
---debug             Don't send lctl commenads           
 --reformat         Reformat all devices (will confirm)
 --lustre="src dir"  Base directory of lustre sources. Used to search
                     for modules.
 --portals=src       Portals source 
 --makeldiff         Translate xml source to LDIFF 
---cleanup          Cleans up config. (Shutdown)
 --iam myname       ??
-
-(SCRIPT STILL UNDER DEVELOPMENT, MOST FUNCTIONALITY UNIMPLEMENTED)
 """
+    sys.exit()
 
 # ============================================================ 
 # debugging and error funcs
@@ -96,6 +97,104 @@ class CommandError (exceptions.Exception):
         self.args = args
 
 # ============================================================
+# handle lctl interface
+class LCTLInterface:
+    """
+    Manage communication with lctl
+    """
+
+    def __init__(self, cmd):
+        """
+        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
+        if not self.lctl:
+            raise RuntimeError,  "unable to find lctl binary."
+            
+    def run(self, cmds):
+        """
+        run lctl
+        the cmds are written to stdin of lctl
+        lctl doesn't return errors when run in script mode, so
+        stderr is checked
+        should modify command line to accept multiple commands, or
+        create complex command line options
+        """
+        debug("+", self.lctl, cmds)
+        if isnotouch(): return ([], 0)
+        p = popen2.Popen3(self.lctl, 1)
+        p.tochild.write(cmds + "\n")
+        p.tochild.close()
+        out = p.fromchild.readlines()
+        ret = p.poll()
+        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 =  """
+  network %s
+  mynid %s
+  quit""" % (net, nid)
+        self.run(cmds)
+
+    # create a new connection 
+    def connect(self, net, nid, port, servuuid):
+        cmds =  """
+  network %s
+  connect %s %d
+  add_uuid %s %s
+  quit""" % (net, nid, port,  servuuid, nid)
+        self.run(cmds)
+                
+    # create a new device with lctl
+    def disconnect(self, net, nid, port, servuuid):
+        cmds =  """
+  network %s
+  disconnect %s 
+  quit""" % (net, nid)
+        self.run(cmds)
+
+    # create a new device with lctl
+    def newdev(self, attach, setup):
+        cmds = """
+  newdev
+  attach %s
+  setup %s
+  quit""" % (attach, setup)
+        self.run(cmds)
+
+    # cleanup a device
+    def cleanup(self, name, uuid):
+        cmds = """
+  device $%s
+  cleanup
+  detach
+  quit""" % (name)
+        self.run(cmds)
+
+    # create an lov
+    def lovconfig(self, uuid, mdcuuid, stripe_cnt, stripe_sz, pattern, devlist):
+        cmds = """
+  device $%s
+  probe
+  lovconfig %s %d %d %s %s
+  quit""" % (mdcuuid, uuid, stripe_cnt, stripe_sz, pattern, devlist)
+        self.run(cmds)
+
+# ============================================================
 # Various system-level functions
 # (ideally moved to their own module)
 
@@ -115,27 +214,6 @@ def run(*args):
         ret = 0
     return (ret, out)
 
-# run lctl
-# the cmds are written to stdin of lctl
-# lctl doesn't return errors when run in script mode, so
-#  stderr is checked
-# should modify command line to accept multiple commands, or
-#  create complex command line options
-def run_lctl(cmds):
-    debug("+", LCTL, cmds)
-    if isnotouch(): return ([], 0)
-    p = popen2.Popen3(LCTL, 1)
-    p.tochild.write(cmds + "\n")
-    p.tochild.close()
-    out = p.fromchild.readlines()
-    ret = p.poll()
-    err = p.childerr.readlines()
-    if ret or len(err):
-        log (LCTL, "error:", ret)
-        logall(err)
-        raise CommandError, err
-    return ret, out
-
 
 # is the path a block device?
 def is_block(path):
@@ -150,9 +228,9 @@ def is_block(path):
 # fixme: dangerous
 def mkfs(fstype, dev):
     if(fstype == 'ext3'):
-        mkfs = 'mkfs.ext2 -j'
+        mkfs = 'mkfs.ext2 -j -b 4096'
     elif (fstype == 'extN'):
-        mkfs = 'mkfs.ext2 -j'
+        mkfs = 'mkfs.ext2 -j -b 4096'
     else:
         print 'unsupported fs type: ', fstype
     if not is_block(dev):
@@ -227,78 +305,28 @@ def block_dev(dev, size, fstype, format):
         mkfs(fstype, dev)
     return dev
 
-# create a new device with lctl
-def lctl_network(net, nid):
-    cmds =  """
-  network %s
-  mynid %s
-  quit""" % (net, nid)
-    run_lctl(cmds)
-
-# create a new connection 
-def lctl_connect(net, nid, port, servuuid):
-    cmds =  """
-  network %s
-  connect %s %d
-  add_uuid %s %s
-  quit""" % (net, nid, port,  servuuid, nid)
-    run_lctl(cmds)
-
-# create a new device with lctl
-def lctl_disconnect(net, nid, port, servuuid):
-    cmds =  """
-  network %s
-  disconnect %s 
-  quit""" % (net, nid)
-    run_lctl(cmds)
-
-# create a new device with lctl
-def lctl_newdev(attach, setup):
-    cmds = """
-  newdev
-  attach %s
-  setup %s
-  quit""" % (attach, setup)
-    run_lctl(cmds)
-
-# cleanup a device
-def lctl_cleanup(name, uuid):
-    cmds = """
-  device $%s
-  cleanup
-  detach
-  quit""" % (name)
-    run_lctl(cmds)
-
-# create an lov
-def lctl_lovconfig(uuid, mdcuuid, stripe_cnt, stripe_sz, pattern, devlist):
-    cmds = """
-  device $%s
-  probe
-  lovconfig %s %d %d %s %s
-  quit""" % (mdcuuid, uuid, stripe_cnt, stripe_sz, pattern, devlist)
-    run_lctl(cmds)
-
 # ============================================================
 # 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),
+    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)
+    (name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist, mdsname) = getLOVInfo(node)
+    print 'LOV:', name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist, mdsname
+    lctl.lovconfig(uuid, mdsname, stripe_cnt, strip_sz, pattern, devlist)
+    lctl.newdev(attach="lov %s %s" % (name, uuid),
+                setup ="%s" % (mdcuuid))
 
 def prepare_network(node):
     (name, uuid, type, nid, port) = getNetworkInfo(node)
-    print 'NETWORK:', type, nid, port
+    print 'NETWORK:', name, uuid, type, nid, port
     if type == 'tcp':
         run(TCP_ACCEPTOR, port)
-    lctl_network(type, nid)
+    lctl.network(type, nid)
 
 
 # need to check /proc/mounts and /etc/mtab before
@@ -306,44 +334,51 @@ def prepare_network(node):
 # 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
+    print 'OBD:', name, uuid, obdtype, dev, size, fstype, format
     dev = block_dev(dev, size, fstype, format)
-    lctl_newdev(attach="%s %s %s" % (obdtype, name, uuid),
+    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),
+    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
+    print 'MDS:', name, uuid, dev, size, fstype
     # setup network for mds, too
     dev = block_dev(dev, size, fstype, format)
-    lctl_newdev(attach="mds %s %s" % (name, uuid),
+    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)
+    (name, uuid, obduuid, ostuuid) = getOSCInfo(node)
+    print 'OSC:', name, uuid, obduuid, ostuuid
+    net = lookup(node.parentNode, ostuuid)
     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))
+    lctl.connect(net, server, port, ostuuid)
+    lctl.newdev(attach="osc %s %s" % (name, uuid),
+                setup ="%s %s" %(obduuid, ostuuid))
 
 def prepare_mdc(node):
     (name, uuid, mdsuuid, netuuid) = getMDCInfo(node)
     print 'MDC:', name, uuid, mdsuuid, netuuid
-    lctl_newdev(attach="mdc %s %s" % (name, uuid),
+    net = lookup(node.parentNode, netuuid)
+    srvname, srvuuid, net, server, port = getNetworkInfo(net)
+    lctl.connect(net, server, port, netuuid)
+    lctl.newdev(attach="mdc %s %s" % (name, uuid),
                 setup ="%s %s" %(mdsuuid, netuuid))
 
 def prepare_mountpoint(node):
-    print 'MTPT:'
-
+    name, uuid, oscuuid, mdcuuid, mtpt = getMTPTInfo(node)
+    print 'MTPT:', name, uuid, oscuuid, mdcuuid, mtpt
+    cmd = "mount -t lustre_lite -o ost=%s,mds=%s none %s" % \
+          (oscuuid, mdcuuid, mtpt)
+    run("mkdir", mtpt)
+    run(cmd)
 # ============================================================
 # Functions to cleanup the various objects
 
@@ -351,20 +386,22 @@ def cleanup_ldlm(node):
     (name, uuid) = getNodeAttr(node)
     print 'LDLM:', name, uuid
     try:
-        lctl_cleanup(name, uuid)
+        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)
+    (name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist, mdsname) = getLOVInfo(node)
+    print 'LOV:', name, uuid, mdcuuid, stripe_cnt, strip_sz, pattern, devlist, mdsname
+    try:
+        lctl.cleanup(name, uuid)
+    except CommandError:
+        print "cleanup failed: ", name
 
 def cleanup_network(node):
     (name, uuid, type, nid, port) = getNetworkInfo(node)
-    print 'NETWORK:', type, nid, port
-    #lctl_network(type, nid)
+    print 'NETWORK:', name, uuid, type, nid, port
+    #lctl.network(type, nid)
 
 # need to check /proc/mounts and /etc/mtab before
 # formatting anything.
@@ -373,7 +410,7 @@ 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)
+        lctl.cleanup(name, uuid)
     except CommandError:
         print "cleanup failed: ", name
     clean_loop(dev)
@@ -382,7 +419,7 @@ def cleanup_ost(ost):
     name, uuid, obd = getOSTInfo(ost)
     print "OST: ", name, uuid, obd
     try:
-        lctl_cleanup(name, uuid)
+        lctl.cleanup(name, uuid)
     except CommandError:
         print "cleanup failed: ", name
 
@@ -390,7 +427,7 @@ def cleanup_mds(node):
     (name, uuid, dev, size, fstype, format) = getMDSInfo(node)
     print "MDS: ", name, dev, size, fstype
     try:
-        lctl_cleanup(name, uuid)
+        lctl.cleanup(name, uuid)
     except CommandError:
         print "cleanup failed: ", name
     clean_loop(dev)
@@ -399,25 +436,30 @@ def cleanup_mds(node):
 def cleanup_mdc(node):
     (name, uuid, mdsuuid, netuuid) = getMDCInfo(node)
     print 'MDC:', name, uuid, mdsuuid, netuuid
+    net = lookup(node.parentNode, netuuid)
+    srvname, srvuuid, net, server, port = getNetworkInfo(net)
     try:
-        lctl_cleanup(name, uuid)
+        lctl.disconnect(net, server, port, netuuid)
+        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)
+    (name, uuid, obduuid, ostuuid) = getOSCInfo(node)
+    print 'OSC:', name, uuid, obduuid, ostuuid
+    net = lookup(node.parentNode, ostuuid)
+    srvname, srvuuid, net, server, port = getNetworkInfo(net)
     try:
-        lctl_disconnect(net, server, port, srvuuid)
-        lctl_cleanup(name, uuid)
+        lctl.disconnect(net, server, port, ostuuid)
+        lctl.cleanup(name, uuid)
     except CommandError:
         print "cleanup failed: ", name
 
 def cleanup_mountpoint(node):
-    print 'MTPT:'
+    name, uuid, oscuuid, mdcuuid, mtpt = getMTPTInfo(node)
+    print 'MTPT:', name, uuid, oscuuid, mdcuuid, mtpt
+    run("umount", mtpt)
 
 # ============================================================
 # XML processing and query
@@ -462,14 +504,17 @@ def getLOVInfo(node):
     mdcref =  node.getElementsByTagName('mdc_ref')[0]
     mdcuuid = mdcref.getAttribute('uuidref')
     mdc= lookup(node.parentNode, mdcuuid)
-    mdcname = getName(mdc)
+    mdsref =  mdc.getElementsByTagName('mds_ref')[0]
+    mdsuuid = mdsref.getAttribute('uuidref')
+    mds= lookup(node.parentNode, mdsuuid)
+    mdsname = getName(mds)
     devlist = ""
     stripe_cnt = 0
     for child in devs.childNodes:
-        if child.nodeName == 'obd_ref':
+        if child.nodeName == 'osc_ref':
             devlist = devlist +  child.getAttribute('uuidref') + " "
             strip_cnt = stripe_cnt + 1
-    return (name, uuid, mdcname, stripe_cnt, stripe_sz, pattern, devlist)
+    return (name, uuid, mdcuuid, stripe_cnt, stripe_sz, pattern, devlist, mdsname)
     
 # extract device attributes for an obd
 def getMDSInfo(node):
@@ -510,6 +555,16 @@ def getOSCInfo(node):
     ostuuid = ref.getAttribute('uuidref')
     return (name, uuid, obduuid, ostuuid)
 
+# extract device attributes for an obd
+def getMTPTInfo(node):
+    name, uuid = getNodeAttr(node)
+    path = getText(node, 'path')
+    ref = node.getElementsByTagName('mdc_ref')[0]
+    mdcuuid = ref.getAttribute('uuidref')
+    ref = node.getElementsByTagName('osc_ref')[0]
+    lovuuid = ref.getAttribute('uuidref')
+    return (name, uuid, lovuuid, mdcuuid, path)
+
     
 # Get the text content from the first matching child
 def getText(node, tag, default=""):
@@ -554,7 +609,7 @@ 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'):
@@ -586,12 +641,13 @@ def getServices(lustreNode, profileNode):
     list.sort()
     return list
 
-def getProfile(lustreNode, profile):
-    profList = lustreNode.getElementsByTagName('profile')
-    for prof in profList:
-        if getName(prof) == profile:
-            return prof
+def getByName(lustreNode, tag, name):
+    ndList = lustreNode.getElementsByTagName(tag)
+    for nd in ndList:
+        if getName(nd) == name:
+            return nd
     return None
+    
 
 # ============================================================
 # lconf type level logic
@@ -630,8 +686,7 @@ 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, profile):
-    profileNode = getProfile(lustreNode, profile)
+def startProfile(lustreNode, profileNode):
     if not profileNode:
         panic("profile:", profile, "not found.")
     services = getServices(lustreNode, profileNode)
@@ -664,8 +719,7 @@ def stopService(node):
         cleanup_mountpoint(node)
 
 # Shutdown services in reverse order than they were started
-def cleanupProfile(lustreNode, profile):
-    profileNode = getProfile(lustreNode, profile)
+def cleanupProfile(lustreNode, profileNode):
     if not profileNode:
         panic("profile:", profile, "not found.")
     services = getServices(lustreNode, profileNode)
@@ -673,14 +727,30 @@ def cleanupProfile(lustreNode, profile):
     for s in services:
         stopService(s[1])
 
+
+#
+# Load profile for 
+def doHost(lustreNode, hosts, cleanFlag):
+    for h in hosts:
+        node = getByName(lustreNode, 'node', h)
+        if node:
+            break
+        
+    reflist = node.getElementsByTagName('profile_ref')
+    for r in reflist:
+        if cleanFlag:
+            cleanupProfile(lustreNode, lookup(lustreNode, getRef(r)))
+        else:
+            startProfile(lustreNode,  lookup(lustreNode, getRef(r)))
+
 #
 # Command line processing
 #
 def parse_cmdline(argv):
-    short_opts = "hv"
+    short_opts = "hdv"
     long_opts = ["ldap", "reformat", "lustre=",
                  "portals=", "makeldiff", "cleanup", "iam=",
-                 "help", "debug"]
+                 "help", "debug", "host="]
     opts = []
     args = []
     global options
@@ -689,24 +759,25 @@ def parse_cmdline(argv):
     except getopt.GetoptError:
         print "invalid opt"
         usage()
-        sys.exit(2)
 
     for o, a in opts:
         if o in ("-h", "--help"):
             usage()
-            sys.exit()
         if o == "--cleanup":
             options['cleanup'] = 1
-        if o in ("-v",  "--verbose"):
+        if o in ("-v", "--verbose"):
             options['verbose'] = 1
-        if o == "--debug":
+        if o in ("-d", "--debug"):
             options['debug'] = 1
+            options['verbose'] = 1
         if o == "--portals":
             options['portals'] = a
         if o == "--lustre":
             options['lustre'] = a
         if o  == "--reformat":
             options['reformat'] = 1
+        if o  == "--host":
+            options['hostname'] = [a]
     return args
 
 #
@@ -715,6 +786,7 @@ def parse_cmdline(argv):
 #   * configure devices with lctl
 # Shutdown does steps in reverse
 #
+lctl = LCTLInterface('lctl')
 def main():
     global options
     args = parse_cmdline(sys.argv[1:])
@@ -722,33 +794,17 @@ def main():
         dom = xml.dom.minidom.parse(args[0])
     else:
         usage()
-        fixme("ldap not implemented yet")
 
-    if options.has_key('cleanup'):
-        cleanupProfile(dom.childNodes[0], 'local-profile')
-    else:
-        startProfile(dom.childNodes[0], 'local-profile')
-    
-# 
-# try a different traceback style. (dare ya to try this in java)
-def my_traceback(file=None):
-    """Print the list of tuples as returned by extract_tb() or
-    extract_stack() as a formatted stack trace to the given file."""
-    import traceback
-    (t,v, tb) = sys.exc_info()
-    list = traceback.extract_tb(tb)
-    if not file:
-        file = sys.stderr
-    for filename, lineno, name, line in list:
-        if line:
-            print '%s:%04d %-14s %s' % (filename,lineno, name, line.strip())
+    if not options.has_key('hostname'):
+        ret, host = run('hostname')
+        if ret:
+            print "unable to determine hostname"
         else:
-            print '%s:%04d %s' % (filename,lineno, name)
-    print '%s: %s' % (t, v)
+            options['hostname'] = [host]
+        options['hostname'].append('localhost')
+    doHost(dom.childNodes[0], options['hostname'], options.has_key('cleanup') )
 
 if __name__ == "__main__":
-    try:
-        main()
-    except:
-        my_traceback()
-        
+    main()
+
+