Whamcloud - gitweb
landing b_cmobd_merge on HEAD
[fs/lustre-release.git] / lustre / utils / lconf
index a1d13a7..687ea05 100755 (executable)
@@ -39,11 +39,13 @@ PYMOD_DIR = "/usr/lib/lustre/python"
 
 def development_mode():
     base = os.path.dirname(sys.argv[0])
-    if os.access(base+"/Makefile.am", os.R_OK):
+    if os.access(base+"/Makefile", os.R_OK):
         return 1
     return 0
 
-if not development_mode():
+if development_mode():
+    sys.path.append('../utils')
+else:
     sys.path.append(PYMOD_DIR)
 
 import Lustre
@@ -536,7 +538,7 @@ class LCTLInterface:
   quit""" % (type, name, uuid)
         self.run(cmds)
         
-    def setup(self,  name, setup = ""):
+    def setup(self, name, setup = ""):
         cmds = """
   cfg_device %s
   setup %s
@@ -706,13 +708,14 @@ def do_find_file(base, mod):
                 return module
 
 def find_module(src_dir, dev_dir, modname):
-    mod = '%s.o' % (modname)
-    module = src_dir +'/'+ dev_dir +'/'+ mod
-    try: 
-       if os.access(module, os.R_OK):
-            return module
-    except OSError:
-        pass
+    modbase = src_dir +'/'+ dev_dir +'/'+ modname
+    for modext in '.ko', '.o':
+        module = modbase + modext
+        try: 
+            if os.access(module, os.R_OK):
+                return module
+        except OSError:
+            pass
     return None
 
 # is the path a block device?
@@ -723,7 +726,7 @@ def is_block(path):
     except OSError:
         return 0
     return stat.S_ISBLK(s[stat.ST_MODE])
-
+    
 # build fs according to type
 # fixme: dangerous
 def mkfs(dev, devsize, fstype, jsize, isize, mkfsoptions, isblock=1):
@@ -737,7 +740,7 @@ def mkfs(dev, devsize, fstype, jsize, isize, mkfsoptions, isblock=1):
         # devsize is in 1k, and fs block count is in 4k
         block_cnt = devsize/4
 
-    if fstype in ('ext3', 'extN'):
+    if fstype in ('ext3', 'extN', 'ldiskfs'):
         # ext3 journal size is in megabytes
         if jsize == 0:
             if devsize == 0:
@@ -771,7 +774,7 @@ def mkfs(dev, devsize, fstype, jsize, isize, mkfsoptions, isblock=1):
     if ret:
         panic("Unable to build fs:", dev, string.join(out))
     # enable hash tree indexing on fsswe
-    if fstype in ('ext3', 'extN'):
+    if fstype in ('ext3', 'extN', 'ldiskfs'):
         htree = 'echo "feature FEATURE_C5" | debugfs -w'
         (ret, out) = run (htree, dev)
         if ret:
@@ -787,8 +790,8 @@ def loop_base():
             panic ("can't access loop devices")
     return loop
     
-# find loop device assigned to thefile
-def find_loop(file):
+# find loop device assigned to the file
+def find_assigned_loop(file):
     loop = loop_base()
     for n in xrange(0, MAX_LOOP_DEVICES):
         dev = loop + str(n)
@@ -803,19 +806,33 @@ def find_loop(file):
     return ''
 
 # create file if necessary and assign the first free loop device
-def init_loop(file, size, fstype, journal_size, inode_size, mkfsoptions, reformat):
-    dev = find_loop(file)
+def init_loop(file, size, fstype, journal_size, inode_size, 
+              mkfsoptions, reformat, autoformat, backfstype, backfile):
+    if fstype == 'smfs':
+        realfile = backfile
+        realfstype = backfstype
+        if is_block(backfile):
+            if reformat or (need_format(realfstype, backfile) and autoformat == 'yes'):
+                mkfs(realfile, size, realfstype, journal_size, inode_size, mkfsoptions, isblock=0)
+            return realfile
+    else:
+        realfile = file
+        realfstype = fstype
+            
+    dev = find_assigned_loop(realfile)
     if dev:
-        print 'WARNING file:', file, 'already mapped to', dev
+        print 'WARNING file:', realfile, 'already mapped to', dev
         return dev
-    if reformat or not os.access(file, os.R_OK | os.W_OK):
+            
+    if reformat or not os.access(realfile, os.R_OK | os.W_OK):
         if size < 8000:
-            panic("size of loopback file '%s' must be larger than 8MB, but is set to %s" % (file,size))
-        (ret, out) = run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size,
-                                                                         file))
+            panic("size of loopback file '%s' must be larger than 8MB, but is set to %s" % (realfile, size))
+        (ret, out) = run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size, realfile))
         if ret:
-            panic("Unable to create backing store:", file)
-        mkfs(file, size, fstype, journal_size, inode_size, mkfsoptions, isblock=0)
+            panic("Unable to create backing store:", realfile)
+            
+        mkfs(realfile, size, realfstype, journal_size, inode_size, 
+             mkfsoptions, isblock=0)
 
     loop = loop_base()
     # find next free loop
@@ -824,7 +841,7 @@ def init_loop(file, size, fstype, journal_size, inode_size, mkfsoptions, reforma
         if os.access(dev, os.R_OK):
             (stat, out) = run('losetup', dev)
             if stat:
-                run('losetup', dev, file)
+                run('losetup', dev, realfile)
                 return dev
         else:
             print "out of loop devices"
@@ -834,7 +851,7 @@ def init_loop(file, size, fstype, journal_size, inode_size, mkfsoptions, reforma
 
 # undo loop assignment
 def clean_loop(file):
-    dev = find_loop(file)
+    dev = find_assigned_loop(file)
     if dev:
         ret, out = run('losetup -d', dev)
         if ret:
@@ -848,11 +865,13 @@ def need_format(fstype, dev):
 
 # initialize a block device if needed
 def block_dev(dev, size, fstype, reformat, autoformat, journal_size,
-              inode_size, mkfsoptions):
-    if config.noexec: return dev
-    if not is_block(dev):
+              inode_size, mkfsoptions, backfstype, backdev):
+    if config.noexec: 
+        return dev
+        
+    if fstype == 'smfs' or not is_block(dev):
         dev = init_loop(dev, size, fstype, journal_size, inode_size,
-                        mkfsoptions, reformat)
+                        mkfsoptions, reformat, autoformat, backfstype, backdev)
     elif reformat or (need_format(fstype, dev) and autoformat == 'yes'):
         mkfs(dev, size, fstype, journal_size, inode_size, mkfsoptions,
              isblock=0)
@@ -872,6 +891,15 @@ def if2addr(iface):
     ip = string.split(addr, ':')[1]
     return ip
 
+def def_mount_options(fstype, target):
+    """returns deafult mount options for passed fstype and target (mds, ost)"""
+    if fstype == 'ext3' or fstype == 'ldiskfs':
+        mountfsoptions = "errors=remount-ro"
+        if target == 'ost' and sys_get_branch() == '2.4':
+            mountfsoptions = "%s,asyncdel" % (mountfsoptions)
+        return mountfsoptions
+    return ""
+        
 def sys_get_elan_position_file():
     procfiles = ["/proc/elan/device0/position",
                  "/proc/qsnet/elan4/device0/position",
@@ -925,18 +953,25 @@ def sys_get_local_address(net_type, wildcard, cluster_id):
             log(e)
     elif net_type == 'gm':
         fixme("automatic local address for GM")
-    elif net_type == 'scimac':
-        scinode="/opt/scali/sbin/scinode"
-        if os.path.exists(scinode):
-            (rc,local) = run(scinode)
-        else:
-            panic (scinode, " not found on node with scimac networking")
-        if rc:
-            panic (scinode, " failed")
-        local=string.rstrip(local[0])
 
     return local
 
+def sys_get_branch():
+    """Returns kernel release"""
+    try:
+        fp = open('/proc/sys/kernel/osrelease')
+        lines = fp.readlines()
+        fp.close()
+        
+        for l in lines:
+            version = string.split(l)
+            a = string.split(version[0], '.')
+            return a[0] + '.' + a[1]
+    except IOError, e:
+        log(e)
+    return ""
+
+
 def mod_loaded(modname):
     """Check if a module is already loaded. Look in /proc/modules for it."""
     try:
@@ -1130,8 +1165,6 @@ class Network(Module):
             self.add_portals_module("knals/qswnal", 'kqswnal')
         if self.net_type == 'gm':
             self.add_portals_module("knals/gmnal", 'kgmnal')
-        if self.net_type == 'scimac':
-            self.add_portals_module("knals/scimacnal", 'kscimacnal')
 
     def nid_to_uuid(self, nid):
         return "NID_%s_UUID" %(nid,)
@@ -1303,7 +1336,7 @@ class LOV(Module):
             self.name = "lov_%s" % name_override
         self.add_lustre_module('lov', 'lov')
         self.mds_uuid = self.db.get_first_ref('mds')
-        self.stripe_sz = self.db.get_val_int('stripesize', 65536)
+        self.stripe_sz = self.db.get_val_int('stripesize', 1048576)
         self.stripe_off = self.db.get_val_int('stripeoffset', 0)
         self.pattern = self.db.get_val_int('stripepattern', 0)
         self.devlist = self.db.get_refs('obd')
@@ -1325,7 +1358,10 @@ class LOV(Module):
                 self.osclist.append(osc)
             else:
                 panic('osc not found:', obd_uuid)
-            
+    def get_uuid(self):
+        return self.uuid
+    def get_name(self):
+        return self.name
     def prepare(self):
         if is_prepared(self.name):
             return
@@ -1434,17 +1470,22 @@ class MDSDEV(Module):
     def __init__(self,db):
         Module.__init__(self, 'MDSDEV', db)
         self.devpath = self.db.get_val('devpath','')
+        self.backdevpath = self.db.get_val('backdevpath','')
         self.size = self.db.get_val_int('devsize', 0)
         self.journal_size = self.db.get_val_int('journalsize', 0)
         self.fstype = self.db.get_val('fstype', '')
+        self.backfstype = self.db.get_val('backfstype', '')
         self.nspath = self.db.get_val('nspath', '')
         self.mkfsoptions = self.db.get_val('mkfsoptions', '')
-        # overwrite the orignal MDSDEV name and uuid with the MDS name and uuid
+        self.mountfsoptions = self.db.get_val('mountfsoptions', '')
+        self.cachetype = self.db.get_val('cachetype', '')
+       # overwrite the orignal MDSDEV name and uuid with the MDS name and uuid
         target_uuid = self.db.get_first_ref('target')
         mds = self.db.lookup(target_uuid)
         self.name = mds.getName()
         self.filesystem_uuids = mds.get_refs('filesystem')
        self.lmv_uuid = ''
+       self.lmv = ''
         self.master_mds = ""
        if not self.filesystem_uuids:
            self.lmv_uuid = self.db.get_first_ref('lmv')
@@ -1479,6 +1520,10 @@ class MDSDEV(Module):
             if not lovconfig_uuid:
                 if not self.lmv_uuid:
                     panic("No LOV found for lovconfig ", lovconfig.name)
+
+               if not self.lmv:
+                   panic("No LMV initialized and not lovconfig_uuid found")
+                   
                 lovconfig_uuid = self.lmv.get_first_ref('lovconfig')
                 lovconfig = self.lmv.lookup(lovconfig_uuid)
                 lov_uuid = lovconfig.get_first_ref('lov')
@@ -1489,9 +1534,11 @@ class MDSDEV(Module):
                 lov_uuid = lovconfig.get_first_ref('lov')
                 if not lov_uuid:
                     panic("No LOV found for lovconfig ", lovconfig.name)
-                lovconfig_uuid = self.lmv.get_first_ref('lovconfig')
-                lovconfig = self.lmv.lookup(lovconfig_uuid)
-                lov_uuid = lovconfig.get_first_ref('lov')
+
+               if self.lmv:
+                   lovconfig_uuid = self.lmv.get_first_ref('lovconfig')
+                   lovconfig = self.lmv.lookup(lovconfig_uuid)
+                   lov_uuid = lovconfig.get_first_ref('lov')
 
             lov = LOV(self.db.lookup(lov_uuid), lov_uuid, 'FS_name', config_only = 1)
 
@@ -1516,6 +1563,7 @@ class MDSDEV(Module):
            client_uuid = self.name + "_lmv_" + "UUID"
            self.master = LMV(self.db.lookup(self.lmv_uuid), client_uuid, self.name, self.name)
            self.master_mds = self.master.name
+
         # modules
         self.add_lustre_module('mdc', 'mdc')
         self.add_lustre_module('osc', 'osc')
@@ -1523,8 +1571,20 @@ class MDSDEV(Module):
         self.add_lustre_module('lmv', 'lmv')
         self.add_lustre_module('ost', 'ost')
         self.add_lustre_module('mds', 'mds')
+
+        if self.fstype == 'smfs':
+            self.add_lustre_module('smfs', 'smfs')
+        
+        if self.fstype == 'ldiskfs':
+            self.add_lustre_module('ldiskfs', 'ldiskfs')
+
         if self.fstype:
             self.add_lustre_module('lvfs', 'fsfilt_%s' % (self.fstype))
+            
+        # if fstype is smfs, then we should also take care about backing 
+        # store fs.
+        if self.fstype == 'smfs':
+            self.add_lustre_module('lvfs', 'fsfilt_%s' % (self.backfstype))
 
     def load_module(self):
         if self.active:
@@ -1547,13 +1607,50 @@ class MDSDEV(Module):
         # never reformat here
         blkdev = block_dev(self.devpath, self.size, self.fstype, 0,
                            self.format, self.journal_size, self.inode_size,
-                           self.mkfsoptions)
+                           self.mkfsoptions, self.backfstype, self.backdevpath)
+        
         if not is_prepared('MDT'):
             lctl.newdev("mdt", 'MDT', 'MDT_UUID', setup ="")
         try: 
-            lctl.newdev("mds", self.name, self.uuid,
-                        setup ="%s %s %s %s"
-                               %(blkdev, self.fstype, self.name, self.master_mds))
+            mountfsoptions = def_mount_options(self.fstype, 'mds')
+            
+            if config.mountfsoptions:
+                if mountfsoptions:
+                    mountfsoptions = mountfsoptions + ',' + config.mountfsoptions
+                else:
+                    mountfsoptions = config.mountfsoptions
+                if self.mountfsoptions:
+                    mountfsoptions = mountfsoptions + ',' + self.mountfsoptions
+            else:
+                if self.mountfsoptions:
+                    if mountfsoptions:
+                        mountfsoptions = mountfsoptions + ',' + self.mountfsoptions
+                    else:
+                        mountfsoptions = self.mountfsoptions
+            
+            if self.fstype == 'smfs':
+                realdev = self.fstype
+                
+                if mountfsoptions:
+                    mountfsoptions = "%s,type=%s,dev=%s" % (mountfsoptions, 
+                                                            self.backfstype, 
+                                                            blkdev)
+                else:
+                    mountfsoptions = "type=%s,dev=%s" % (self.backfstype, 
+                                                         blkdev)
+            else:
+                realdev = blkdev
+                
+            print 'MDS mount options: ' + mountfsoptions
+            
+           if not self.master_mds:
+                self.master_mds = 'dumb'           
+            if not self.cachetype:
+                self.cachetype = 'dumb'
+           lctl.newdev("mds", self.name, self.uuid,
+                        setup ="%s %s %s %s %s %s" %(realdev, self.fstype, 
+                                               self.name, mountfsoptions,
+                                               self.master_mds, self.cachetype))
         except CommandError, e:
             if e.rc == 2:
                 panic("MDS is missing the config log. Need to run " +
@@ -1565,17 +1662,72 @@ class MDSDEV(Module):
         if is_prepared(self.name):
             return
         self.info(self.devpath, self.fstype, self.format)
+
         blkdev = block_dev(self.devpath, self.size, self.fstype,
                            config.reformat, self.format, self.journal_size,
-                           self.inode_size, self.mkfsoptions)
+                           self.inode_size, self.mkfsoptions, self.backfstype,
+                           self.backdevpath)
+
+       # Even for writing logs we mount mds with supplied mount options
+       # because it will not mount smfs (if used) otherwise.
+       
+        mountfsoptions = def_mount_options(self.fstype, 'mds')
+            
+        if config.mountfsoptions:
+            if mountfsoptions:
+                mountfsoptions = mountfsoptions + ',' + config.mountfsoptions
+            else:
+                mountfsoptions = config.mountfsoptions
+            if self.mountfsoptions:
+                mountfsoptions = mountfsoptions + ',' + self.mountfsoptions
+        else:
+            if self.mountfsoptions:
+                if mountfsoptions:
+                    mountfsoptions = mountfsoptions + ',' + self.mountfsoptions
+                else:
+                    mountfsoptions = self.mountfsoptions
+            
+        if self.fstype == 'smfs':
+            realdev = self.fstype
+                
+            if mountfsoptions:
+                mountfsoptions = "%s,type=%s,dev=%s" % (mountfsoptions, 
+                                                        self.backfstype, 
+                                                        blkdev)
+            else:
+                mountfsoptions = "type=%s,dev=%s" % (self.backfstype, 
+                                                     blkdev)
+        else:
+            realdev = blkdev
+       
+        print 'MDS mount options: ' + mountfsoptions
+        
+       # As mount options are passed by 4th param to config tool, we need 
+       # to pass something in 3rd param. But we do not want this 3rd param
+       # be counted as a profile name for reading log on MDS setup, thus,
+       # we pass there some predefined sign like 'dumb', which will be 
+        # checked in MDS code and skipped. Probably there is more nice way
+        # like pass empty string and check it in config tool and pass null
+        # as 4th param.
         lctl.newdev("mds", self.name, self.uuid,
-                    setup ="%s %s" %(blkdev, self.fstype))
+                    setup ="%s %s %s %s" %(realdev, self.fstype, 
+                                           'dumb', mountfsoptions))
         # record logs for the MDS lov
         for uuid in self.filesystem_uuids:
             log("recording clients for filesystem:", uuid)
             fs = self.db.lookup(uuid)
-            obd_uuid = fs.get_first_ref('obd')
+
+            # this is ugly, should be organized nice later.
+            target_uuid = self.db.get_first_ref('target')
+            mds = self.db.lookup(target_uuid)
+            
+            lovconfig_uuid = mds.get_first_ref('lovconfig')
+            if lovconfig_uuid:
+                lovconfig = mds.lookup(lovconfig_uuid)
+                obd_uuid = lovconfig.get_first_ref('lov')
+            else:
+                obd_uuid = fs.get_first_ref('obd')
+                
             client_uuid = generate_client_uuid(self.name)
             client = VOSC(self.db.lookup(obd_uuid), client_uuid, self.name,
                           self.name)
@@ -1638,8 +1790,12 @@ class MDSDEV(Module):
             log(self.module_name, "cleanup failed: ", self.name)
             e.dump()
             cleanup_error(e.rc)
-           Module.cleanup(self)
-       clean_loop(self.devpath)
+            Module.cleanup(self)
+        
+        if self.fstype == 'smfs':
+            clean_loop(self.backdevpath)
+        else:
+            clean_loop(self.devpath)
 
     def msd_remaining(self):
         out = lctl.device_list()
@@ -1678,7 +1834,11 @@ class MDSDEV(Module):
                 print "cleanup failed: ", self.name
                 e.dump()
                 cleanup_error(e.rc)
-        clean_loop(self.devpath)
+        
+        if self.fstype == 'smfs':
+            clean_loop(self.backdevpath)
+        else:
+            clean_loop(self.devpath)
 
     def correct_level(self, level, op=None):
        #if self.master_mds:
@@ -1690,11 +1850,14 @@ class OSD(Module):
         Module.__init__(self, 'OSD', db)
         self.osdtype = self.db.get_val('osdtype')
         self.devpath = self.db.get_val('devpath', '')
+        self.backdevpath = self.db.get_val('backdevpath', '')
         self.size = self.db.get_val_int('devsize', 0)
         self.journal_size = self.db.get_val_int('journalsize', 0)
         self.inode_size = self.db.get_val_int('inodesize', 0)
         self.mkfsoptions = self.db.get_val('mkfsoptions', '')
+        self.mountfsoptions = self.db.get_val('mountfsoptions', '')
         self.fstype = self.db.get_val('fstype', '')
+        self.backfstype = self.db.get_val('backfstype', '')
         self.nspath = self.db.get_val('nspath', '')
         target_uuid = self.db.get_first_ref('target')
         ost = self.db.lookup(target_uuid)
@@ -1719,9 +1882,16 @@ class OSD(Module):
         self.uuid = target_uuid
         # modules
         self.add_lustre_module('ost', 'ost')
+        if self.fstype == 'smfs':
+            self.add_lustre_module('smfs', 'smfs')
         # FIXME: should we default to ext3 here?
+        if self.fstype == 'ldiskfs':
+            self.add_lustre_module('ldiskfs', 'ldiskfs')
         if self.fstype:
             self.add_lustre_module('lvfs' , 'fsfilt_%s' % (self.fstype))
+        if self.fstype == 'smfs':
+            self.add_lustre_module('lvfs' , 'fsfilt_%s' % (self.backfstype))
+
         self.add_lustre_module(self.osdtype, self.osdtype)
 
     def load_module(self):
@@ -1745,10 +1915,44 @@ class OSD(Module):
         else:
             blkdev = block_dev(self.devpath, self.size, self.fstype,
                                config.reformat, self.format, self.journal_size,
-                               self.inode_size, self.mkfsoptions)
+                               self.inode_size, self.mkfsoptions, self.backfstype,
+                               self.backdevpath)
+
+        mountfsoptions = def_mount_options(self.fstype, 'ost')
+            
+        if config.mountfsoptions:
+            if mountfsoptions:
+                mountfsoptions = mountfsoptions + ',' + config.mountfsoptions
+            else:
+                mountfsoptions = config.mountfsoptions
+            if self.mountfsoptions:
+                mountfsoptions = mountfsoptions + ',' + self.mountfsoptions
+        else:
+            if self.mountfsoptions:
+                if mountfsoptions:
+                    mountfsoptions = mountfsoptions + ',' + self.mountfsoptions
+                else:
+                    mountfsoptions = self.mountfsoptions
+            
+        if self.fstype == 'smfs':
+            realdev = self.fstype
+                
+            if mountfsoptions:
+                mountfsoptions = "%s,type=%s,dev=%s" % (mountfsoptions, 
+                                                        self.backfstype, 
+                                                        blkdev)
+            else:
+                mountfsoptions = "type=%s,dev=%s" % (self.backfstype, 
+                                                     blkdev)
+        else:
+            realdev = blkdev
+                
+        print 'OSD mount options: ' + mountfsoptions
+        
         lctl.newdev(self.osdtype, self.name, self.uuid,
-                    setup ="%s %s %s" %(blkdev, self.fstype,
-                                           self.failover_ost))
+                    setup ="%s %s %s %s" %(realdev, self.fstype,
+                                           self.failover_ost, 
+                                           mountfsoptions))
         if not is_prepared('OSS'):
             lctl.newdev("ost", 'OSS', 'OSS_UUID', setup ="")
 
@@ -1786,7 +1990,10 @@ class OSD(Module):
                 e.dump()
                 cleanup_error(e.rc)
         if not self.osdtype == 'obdecho':
-            clean_loop(self.devpath)
+            if self.fstype == 'smfs':
+                clean_loop(self.backdevpath)
+            else:
+                clean_loop(self.devpath)
 
     def correct_level(self, level, op=None):
         return level
@@ -1794,9 +2001,9 @@ class OSD(Module):
 def mgmt_uuid_for_fs(mtpt_name):
     if not mtpt_name:
         return ''
-    mtpt_db = toplevel.lookup_name(mtpt_name)
+    mtpt_db = toplustreDB.lookup_name(mtpt_name)
     fs_uuid = mtpt_db.get_first_ref('filesystem')
-    fs = toplevel.lookup(fs_uuid)
+    fs = toplustreDB.lookup(fs_uuid)
     if not fs:
         return ''
     return fs.get_first_ref('mgmt')
@@ -1812,7 +2019,7 @@ class Client(Module):
         self.tgt_dev_uuid = get_active_target(tgtdb)
         if not self.tgt_dev_uuid:
             panic("No target device found for target(1):", self.target_name)
-        
+
         self.kmod = kmod(config.lustre, config.portals)
         self._server = None
         self._connected = 0
@@ -1841,7 +2048,8 @@ class Client(Module):
         self._server_nets = get_ost_net(self.db, srv_uuid)
         if len(self._server_nets) == 0:
             panic ("Unable to find a server for:", srv_uuid)
-
+    def get_name(self):
+        return self.name
     def get_servers(self):
         return self._server_nets
 
@@ -1916,37 +2124,73 @@ class ManagementClient(Client):
                         module_dir = 'mgmt')
             
 class COBD(Module):
-    def __init__(self, db):
+    def __init__(self, db, uuid, name, type, name_override = None):
         Module.__init__(self, 'COBD', db)
+        self.name = self.db.getName(); 
+        self.uuid = generate_client_uuid(self.name)
         self.real_uuid = self.db.get_first_ref('realobd')
         self.cache_uuid = self.db.get_first_ref('cacheobd')
-        self.add_lustre_module('cobd' , 'cobd')
-
+        self.add_lustre_module('cobd', 'cobd')
+        real_obd = self.db.lookup(self.real_uuid)
+        if not real_obd:
+            panic('real obd not found:', self.real_uuid)
+        cache_obd = self.db.lookup(self.cache_uuid)
+        if not cache_obd:
+            panic('cache obd not found:', self.cache_uuid)
+        if type == 'obd':
+            self.real = LOV(real_obd, self.real_uuid, name, 
+                            "%s_real" % (self.name));
+            self.cache = LOV(cache_obd, self.cache_uuid, name, 
+                            "%s_cache" % (self.name));
+        else:
+            self.real = get_mdc(db, uuid, name, self.real_uuid) 
+            self.cache = get_mdc(db, uuid, name, self.cache_uuid) 
     # need to check /proc/mounts and /etc/mtab before
     # formatting anything.
     # FIXME: check if device is already formatted.
+    def get_uuid(self):
+        return self.uuid
+    def get_name(self):
+        return self.name
+    def get_real_name(self):
+        return self.real.name
+    def get_cache_name(self):
+        return self.cache.name
     def prepare(self):
+        self.real.prepare()
+        self.cache.prepare()
         if is_prepared(self.name):
             return
         self.info(self.real_uuid, self.cache_uuid)
         lctl.newdev("cobd", self.name, self.uuid,
-                    setup ="%s %s" %(self.real_uuid, self.cache_uuid))
-
-    def correct_level(self, level, op=None):
-        return level
+                    setup ="%s %s" %(self.real.name,
+                                     self.cache.name))
+    def cleanup(self):
+        if is_prepared(self.name):
+            Module.cleanup(self)
+        self.real.cleanup()
+        self.cache.cleanup()
+    def load_module(self):
+        self.real.load_module()
+        Module.load_module(self)
+    def cleanup_module(self):
+        Module.cleanup_module(self)
+        self.real.cleanup_module()
 
 # virtual interface for  OSC and LOV
 class VOSC(Module):
-    def __init__(self, db, uuid, fs_name, name_override = None):
+    def __init__(self, db, client_uuid, name, name_override = None):
         Module.__init__(self, 'VOSC', db)
         if db.get_class() == 'lov':
-            self.osc = LOV(db, uuid, fs_name, name_override)
-        else:
-            self.osc = get_osc(db, uuid, fs_name)
+            self.osc = LOV(db, client_uuid, name, name_override)
+            self.type = 'lov'
+        elif db.get_class() == 'cobd':
+            self.osc = COBD(db, client_uuid, name, 'obd')
+            self.type = 'cobd'
     def get_uuid(self):
-        return self.osc.uuid
+        return self.osc.get_uuid()
     def get_name(self):
-        return self.osc.name
+        return self.osc.get_name()
     def prepare(self):
         self.osc.prepare()
     def cleanup(self):
@@ -1964,6 +2208,8 @@ class VMDC(Module):
         Module.__init__(self, 'VMDC', db)
         if db.get_class() == 'lmv':
             self.mdc = LMV(db, uuid, fs_name)
+        elif db.get_class() == 'cobd':
+            self.mdc = COBD(db, uuid, fs_name, 'mds')
         else:
             self.mdc = MDC(db, uuid, fs_name)
     def get_uuid(self):
@@ -1979,8 +2225,7 @@ class VMDC(Module):
     def cleanup_module(self):
         self.mdc.cleanup_module()
     def correct_level(self, level, op=None):
-        return self.osc.correct_level(level, op)
-
+        return self.mdc.correct_level(level, op)
 
 class ECHO_CLIENT(Module):
     def __init__(self,db):
@@ -2036,12 +2281,15 @@ class Mountpoint(Module):
            self.mds_uuid = fs.get_first_ref('mds')
         self.obd_uuid = fs.get_first_ref('obd')
         self.mgmt_uuid = fs.get_first_ref('mgmt')
-        obd = self.db.lookup(self.obd_uuid)
         client_uuid = generate_client_uuid(self.name)
-        self.vosc = VOSC(obd, client_uuid, self.name)
+
+        ost = self.db.lookup(self.obd_uuid)
+        self.vosc = VOSC(ost, client_uuid, self.name)
+
         self.mds = self.db.lookup(self.mds_uuid)
        if not self.mds:
            panic("no mds: ", self.mds_uuid)
+       
         self.add_lustre_module('mdc', 'mdc')
         self.add_lustre_module('lmv', 'lmv')
        self.vmdc = VMDC(self.mds, client_uuid, self.name, self.mds_uuid)
@@ -2061,19 +2309,19 @@ class Mountpoint(Module):
         if self.mgmtcli:
             self.mgmtcli.prepare()
         self.vosc.prepare()
-        self.mdc.prepare()
-        mdc_name = self.mdc.name
+        self.vmdc.prepare()
+        vmdc_name = self.vmdc.get_name()
 
         self.info(self.path, self.mds_uuid, self.obd_uuid)
         if config.record or config.lctl_dump:
-            lctl.mount_option(local_node_name, self.vosc.get_name(), mdc_name)
+            lctl.mount_option(local_node_name, self.vosc.get_name(), vmdc_name)
             return
         cmd = "mount -t lustre_lite -o osc=%s,mdc=%s %s %s" % \
-              (self.vosc.get_name(), mdc_name, config.config, self.path)
+              (self.vosc.get_name(), vmdc_name, config.config, self.path)
         run("mkdir", self.path)
         ret, val = run(cmd)
         if ret:
-            self.mdc.cleanup()            
+            self.vmdc.cleanup()            
             self.vosc.cleanup()
             panic("mount failed:", self.path, ":", string.join(val))
 
@@ -2094,7 +2342,7 @@ class Mountpoint(Module):
             if fs_is_mounted(self.path):
                 panic("fs is still mounted:", self.path)
 
-        self.mdc.cleanup()
+        self.vmdc.cleanup()
         self.vosc.cleanup()
         if self.mgmtcli:
             self.mgmtcli.cleanup()
@@ -2324,7 +2572,7 @@ def newService(db):
     elif type == 'osd':
         n = OSD(db)
     elif type == 'cobd':
-        n = COBD(db)
+        n = COBD(db, "YOU_SHOULD_NEVER_SEE_THIS_UUID")
     elif type == 'mdsdev':
         n = MDSDEV(db)
     elif type == 'mountpoint':
@@ -2442,6 +2690,7 @@ def doHost(lustreDB, hosts):
     prof_list = node_db.get_refs('profile')
 
     if config.write_conf:
+        lustreDB.close()
         for_each_profile(node_db, prof_list, doModules)
         sys_make_devices()
         for_each_profile(node_db, prof_list, doWriteconf)
@@ -2470,6 +2719,7 @@ def doHost(lustreDB, hosts):
 
         for_each_profile(node_db, prof_list, doCleanup)
         for_each_profile(node_db, prof_list, doUnloadModules)
+        lustreDB.close()
 
     else:
         # ugly hack, only need to run lctl commands for --dump
@@ -2500,22 +2750,24 @@ def doHost(lustreDB, hosts):
         sys_set_portals_upcall(portals_upcall)
 
         for_each_profile(node_db, prof_list, doSetup)
+        lustreDB.close()
 
-def doRecovery(db, lctl, tgt_uuid, client_uuid, nid_uuid):
-    tgt = db.lookup(tgt_uuid)
+def doRecovery(lustreDB, lctl, tgt_uuid, client_uuid, nid_uuid):
+    tgt = lustreDB.lookup(tgt_uuid)
     if not tgt:
         raise Lustre.LconfError("doRecovery: "+ tgt_uuid +" not found.")
     new_uuid = get_active_target(tgt)
     if not new_uuid:
         raise Lustre.LconfError("doRecovery: no active target found for: " +
                                 tgt_uuid)
-    net = choose_local_server(get_ost_net(db, new_uuid))
+    net = choose_local_server(get_ost_net(lustreDB, new_uuid))
     if not net:
         raise Lustre.LconfError("Unable to find a connection to:" + new_uuid)
 
     log("Reconnecting", tgt_uuid, " to ",  net.nid_uuid);
     try:
-        oldnet = get_server_by_nid_uuid(db, nid_uuid)
+        oldnet = get_server_by_nid_uuid(lustreDB, nid_uuid)
+        lustreDB.close()
         if oldnet:
             lctl.disconnect(oldnet)
     except CommandError, e:
@@ -2535,6 +2787,7 @@ def setupModulePath(cmd, portals_dir = PORTALS_DIR):
     base = os.path.dirname(cmd)
     if development_mode():
         if not config.lustre:
+            debug('using objdir module paths')            
             config.lustre = (os.path.join(base, ".."))
         # normalize the portals dir, using command line arg if set
         if config.portals:
@@ -2718,6 +2971,7 @@ lconf_options = [
     ('nosetup', "Skip device setup/cleanup step."),
     ('reformat', "Reformat all devices (without question)"),
     ('mkfsoptions', "Additional options for the mk*fs command line", PARAM),
+    ('mountfsoptions', "Additional options for mount fs command line", PARAM),
     ('dump',  "Dump the kernel debug log to file before portals is unloaded",
                PARAM),
     ('write_conf', "Save all the client config information on mds."),
@@ -2761,7 +3015,7 @@ lconf_options = [
     ]      
 
 def main():
-    global lctl, config, toplevel, CONFIG_FILE
+    global lctl, config, toplustreDB, CONFIG_FILE
 
     # in the upcall this is set to SIG_IGN
     signal.signal(signal.SIGCHLD, signal.SIG_DFL)
@@ -2792,16 +3046,30 @@ def main():
     init_select(config.select)
 
     if len(args) > 0:
-        if not os.access(args[0], os.R_OK):
+        # allow config to be fetched via HTTP, but only with python2
+        if sys.version[0] != '1' and args[0].startswith('http://'):
+            import urllib2
+            try:
+                config_file = urllib2.urlopen(args[0])
+            except (urllib2.URLError, socket.error), err:
+                if hasattr(err, 'args'):
+                    err = err.args[1]
+                print "Could not access '%s': %s" %(args[0], err)
+                sys.exit(1)
+        elif not os.access(args[0], os.R_OK):
             print 'File not found or readable:', args[0]
             sys.exit(1)
+        else:
+            # regular file
+            config_file = open(args[0], 'r')
         try:
-            dom = xml.dom.minidom.parse(args[0])
+            dom = xml.dom.minidom.parse(config_file)
         except Exception:
             panic("%s does not appear to be a config file." % (args[0]))
             sys.exit(1) # make sure to die here, even in debug mode.
+        config_file.close()
         CONFIG_FILE = args[0]
-        db = Lustre.LustreDB_XML(dom.documentElement, dom.documentElement)
+        lustreDB = Lustre.LustreDB_XML(dom.documentElement, dom.documentElement)
         if not config.config:
             config.config = os.path.basename(args[0])# use full path?
             if config.config[-4:] == '.xml':
@@ -2810,7 +3078,7 @@ def main():
         if not config.config:
             panic("--ldapurl requires --config name")
         dn = "config=%s,fs=lustre" % (config.config)
-        db = Lustre.LustreDB_LDAP('', {}, base=dn, url = config.ldapurl)
+        lustreDB = Lustre.LustreDB_LDAP('', {}, base=dn, url = config.ldapurl)
     elif config.ptldebug or config.subsystem:
         sys_set_ptldebug(None)
         sys_set_subsystem(None)
@@ -2820,9 +3088,9 @@ def main():
         print 'see lconf --help for command summary'
         sys.exit(1)
 
-    toplevel = db
+    toplustreDB = lustreDB
 
-    ver = db.get_version()
+    ver = lustreDB.get_version()
     if not ver:
         panic("No version found in config data, please recreate.")
     if ver != Lustre.CONFIG_VERSION:
@@ -2854,7 +3122,7 @@ def main():
         lctl.clear_log(config.record_device, config.record_log)
         lctl.record(config.record_device, config.record_log)
 
-    doHost(db, node_list)
+    doHost(lustreDB, node_list)
 
     if config.record:
         lctl.end_record()