Whamcloud - gitweb
* Removed toenal
[fs/lustre-release.git] / lustre / utils / lmc
index 65f8fc2..62afbbc 100755 (executable)
 #
 
 """
-lmc - lustre configurtion data  manager
+lmc - lustre configuration data manager
 
-  See lustre book for documentation for lmc.
+  See Lustre book (http://www.lustre.org/docs/lustre.pdf) for documentation on lmc.
 
 """
 
-import sys, os, getopt, string, exceptions
+import sys, os, getopt, string, exceptions, random
 import xml.dom.minidom
 from xml.dom.ext import PrettyPrint
 
@@ -60,12 +60,11 @@ Object creation command summary:
   --node node_name
   --nid nid
   --cluster_id 
-  --nettype tcp|elan|toe|gm|scimac
+  --nettype tcp|elan|gm|scimac
   --hostaddr addr
   --port port
   --tcpbuf size
   --irq_affinity 0|1
-  --nid_exchange 0|1
   --router
 
 --add mds
@@ -75,6 +74,7 @@ Object creation command summary:
   --fstype extN|ext3
   --size size
   --nspath
+  --journal_size size
 
 --add lov
   --lov lov_name
@@ -83,90 +83,107 @@ Object creation command summary:
   --stripe_cnt num
   --stripe_pattern num
 
--add ost
+--add ost
   --node node_name
   --ost ost_name 
   --lov lov_name 
   --dev path
   --size size
   --fstype extN|ext3
+  --journal_size size
+  --obdtype obdecho|obdfilter
   --ostuuid uuid
-  --nspath
-  
 --add mtpt  - Mountpoint
   --node node_name
   --path /mnt/point
   --mds mds_name
   --ost ost_name OR --lov lov_name
+
+--add route
+  --node nodename
+  --gw nid
+  --tgt nid
+  --lo nid
+  --hi nid
+
+--add echo_client
+  --node nodename
+
+--add mgmt  - Management/monitoring service
+  --node node_name
+  --mgmt mgmt_service_name
 """
 
 PARAM = Lustre.Options.PARAM
 lmc_options = [
     # lmc input/output options
-    ('reference', "Print short reference for commands"), 
-    ('verbose,v', "Print system commands as they are run"),
-    ('merge,m', "", PARAM),
-    ('output,o', "", PARAM),
+    ('reference', "Print short reference for commands."), 
+    ('verbose,v', "Print system commands as they are run."),
+    ('merge,m', "Append to the specified config file.", PARAM),
+    ('output,o', "Write XML configuration into given output file. Overwrite existing content.", PARAM),
     ('input,i', "", PARAM),
-    ('batch', "", PARAM),
+    ('batch', "Used to execute lmc commands in batch mode.", PARAM),
 
     # commands
     ('add', "", PARAM),
     
     # node options
-    ('node', "", PARAM),
-    ('timeout', "", PARAM),
+    ('node', "Add a new node in the cluster configuration.", PARAM),
+    ('timeout', "Set timeout to initiate recovery.", PARAM),
     ('upcall', "Set both lustre and portals upcall scripts.", PARAM),
     ('lustre_upcall', "Set location of lustre upcall script.", PARAM),
     ('portals_upcall', "Set location of portals upcall script.", PARAM),
 
     # network 
-    ('nettype', "", PARAM),
-    ('nid', "", PARAM),
-    ('tcpbuf', "", PARAM, 0),
-    ('port', "", PARAM, DEFAULT_PORT),
-    ('nid_exchange', "", PARAM, 0),
-    ('irq_affinity', "", PARAM, 0),
-    ('hostaddr', "", PARAM, ""),
-    ('cluster_id', "", PARAM, "0"),
+    ('nettype', "Specify the network type. This can be tcp/elan/gm/scimac.", PARAM),
+    ('nid', "Give the network ID, e.g ElanID/IP Address as used by portals.", PARAM),
+    ('tcpbuf', "Optional argument to specify the TCP buffer size.", PARAM, "0"),
+    ('port', "Optional argument to specify the TCP port number.", PARAM, DEFAULT_PORT),
+    ('irq_affinity', "Optional argument.", PARAM, 0),
+    ('hostaddr', "", PARAM,""),
+    ('cluster_id', "Specify the cluster ID", PARAM, "0"),
 
     # routes
-    ('route', "", PARAM),
-    ('router', ""),
-    ('gw', "", PARAM),
-    ('gw_cluster_id', "", PARAM, "0"),
+    ('route', "Add a new route for the cluster.", PARAM),
+    ('router', "Optional flag to mark a node as router."),
+    ('gw', "Specify the nid of the gateway for a route.", PARAM),
+    ('gateway_cluster_id', "", PARAM, "0"),
     ('target_cluster_id', "", PARAM, "0"),
-    ('lo', "", PARAM),
-    ('hi', "", PARAM, ""),
+    ('lo', "For a range route, this is the low value nid.", PARAM),
+    ('hi', "For a range route, this is a hi value nid.", PARAM,""),
 
     # servers: mds and ost
-    ('mds', "", PARAM),
-    ('ost', "", PARAM, ""),
-    ('osdtype', "", PARAM, "obdfilter"),
-    ('failover', ""),
+    ('mds', "Specify MDS name.", PARAM),
+    ('ost', "Specify the OST name.", PARAM,""),
+    ('osdtype', "This could obdfilter or obdecho.", PARAM, "obdfilter"),
+    ('failover', "Enable failover support on OSTs or MDS?"),
     ('group', "", PARAM),
-    ('dev', "", PARAM, ""),
-    ('size', "", PARAM, 0),
-    ('journal_size', "", PARAM, 0),
-    ('fstype', "", PARAM, "ext3"),
-    ('ostuuid', "", PARAM, ""),
-    ('nspath', "Local mount point of server namespace.", PARAM, ""),
+    ('dev', "Path of the device on local system.", PARAM,""),
+    ('size', "Specify the size of the device if needed.", PARAM,"0"),
+    ('journal_size', "Specify new journal size for underlying ext3 file system.", PARAM,"0"),
+    ('fstype', "Optional argument to specify the filesystem type.", PARAM, "ext3"),
+    ('mkfsoptions', "Optional argument to mkfs.", PARAM, ""),
+    ('ostuuid', "", PARAM,""),
+    ('nspath', "Local mount point of server namespace.", PARAM,""),
     ('format', ""),
 
     # clients: mountpoint and echo
     ('echo_client', "", PARAM),
-    ('path', "", PARAM),
-    ('filesystem', "Lustre filesystem name", PARAM, ''),
+    ('path', "Specify the mountpoint for Lustre.", PARAM),
+    ('filesystem', "Lustre filesystem name", PARAM,""),
 
     # lov
-    ('lov', "", PARAM, ''),
-    ('stripe_sz', "", PARAM),
-    ('stripe_cnt', "", PARAM, 0),
-    ('stripe_pattern', "", PARAM, 0),
+    ('lov', "Specify LOV name.", PARAM,""),
+    ('stripe_sz', "Specify the stripe size in bytes.", PARAM),
+    ('stripe_cnt', "Specify the number of OSTs each file should be striped on.", PARAM, 0),
+    ('stripe_pattern', "Specify the stripe pattern. RAID 0 is the only one currently supported.", PARAM, 0),
 
     # cobd
     ('real_obd', "", PARAM),
     ('cache_obd', "", PARAM),
+
+    ('mgmt', "Specify management/monitoring service name.", PARAM, ""),
     ]
 
 def error(*args):
@@ -199,7 +216,11 @@ def new_name(base):
     return ret
 
 def new_uuid(name):
-    return "%s_UUID" % (name)
+    ret_uuid = '%05x_%.19s_%05x%05x' % (int(random.random() * 1048576),
+                                        name,
+                                        int(random.random() * 1048576),
+                                        int(random.random() * 1048576))
+    return ret_uuid[:36]
 
 ldlm_name = 'ldlm'
 ldlm_uuid = 'ldlm_UUID'
@@ -268,7 +289,7 @@ class GenConfig:
         return new
 
     def network(self, name, uuid, nid, cluster_id, net, hostaddr="",
-                port=0, tcpbuf=0, irq_aff=0, nid_xchg=0):
+                port=0, tcpbuf=0, irq_aff=0):
         """create <network> node"""
         network = self.newService("network", name, uuid)
         network.setAttribute("nettype", net);
@@ -283,8 +304,6 @@ class GenConfig:
             self.addElement(network, "recvmem", "%d" %(tcpbuf))
         if irq_aff:
             self.addElement(network, "irqaffinity", "%d" %(irq_aff))
-        if nid_xchg:
-            self.addElement(network, "nidexchange", "%d" %(nid_xchg))
             
         return network
 
@@ -378,7 +397,7 @@ class GenConfig:
         return mds
 
     def mdsdev(self, name, uuid, fs, devname, format, node_uuid,
-            mds_uuid, dev_size=0, journal_size=0, nspath=""):
+            mds_uuid, dev_size=0, journal_size=0, nspath="", mkfsoptions=""):
         mdd = self.newService("mdsdev", name, uuid)
         self.addElement(mdd, "fstype", fs)
         dev = self.addElement(mdd, "devpath", devname)
@@ -389,20 +408,31 @@ class GenConfig:
             self.addElement(mdd, "journalsize", "%s" % (journal_size))
         if nspath:
             self.addElement(mdd, "nspath", nspath)
+        if mkfsoptions:
+            self.addElement(mdd, "mkfsoptions", mkfsoptions)
         mdd.appendChild(self.ref("node", node_uuid))
         mdd.appendChild(self.ref("target", mds_uuid))
         return mdd
 
+    def mgmt(self, mgmt_name, mgmt_uuid, node_uuid):
+        mgmt = self.newService("mgmt", mgmt_name, mgmt_uuid)
+        mgmt.appendChild(self.ref("node", node_uuid))
+        # Placeholder until mgmt-service failover.
+        mgmt.appendChild(self.ref("active", mgmt_uuid))
+        return mgmt
+
     def mountpoint(self, name, uuid, fs_uuid, path):
         mtpt = self.newService("mountpoint", name, uuid)
         mtpt.appendChild(self.ref("filesystem", fs_uuid))
         self.addElement(mtpt, "path", path)
         return mtpt
 
-    def filesystem(self, name, uuid, mds_uuid, obd_uuid):
+    def filesystem(self, name, uuid, mds_uuid, obd_uuid, mgmt_uuid):
         fs = self.newService("filesystem", name, uuid)
         fs.appendChild(self.ref("mds", mds_uuid))
         fs.appendChild(self.ref("obd", obd_uuid))
+        if mgmt_uuid:
+            fs.appendChild(self.ref("mgmt", mgmt_uuid))
         return fs
         
     def echo_client(self, name, uuid, osc_uuid):
@@ -566,16 +596,14 @@ def add_net(gen, lustre, options):
     hostaddr = get_option(options, 'hostaddr')
     net_type = get_option(options, 'nettype')
 
-    if net_type in ('tcp', 'toe'):
+    if net_type in ('tcp',):
         port = get_option_int(options, 'port')
         tcpbuf = get_option_int(options, 'tcpbuf')
         irq_aff = get_option_int(options, 'irq_affinity')
-        nid_xchg = get_option_int(options, 'nid_exchange')
     elif net_type in ('elan', 'gm', 'scimac'):
         port = 0
         tcpbuf = 0
         irq_aff = 0
-        nid_xchg = 0
     else:
         print "Unknown net_type: ", net_type
         sys.exit(2)
@@ -590,7 +618,7 @@ def add_net(gen, lustre, options):
     net_name = new_name('NET_'+ node_name +'_'+ net_type)
     net_uuid = new_uuid(net_name)
     node.appendChild(gen.network(net_name, net_uuid, nid, cluster_id, net_type,
-                                 hostaddr, port, tcpbuf, irq_aff, nid_xchg))
+                                 hostaddr, port, tcpbuf, irq_aff))
     node_add_profile(gen, node, "network", net_uuid)
 
 
@@ -600,7 +628,7 @@ def add_route(gen, lustre, options):
     node_name = get_option(options, 'node')
     gw_net_type = get_option(options, 'nettype')
     gw = get_option(options, 'gw')
-    gw_cluster_id = get_option(options, 'gw_cluster_id')
+    gw_cluster_id = get_option(options, 'gateway_cluster_id')
     tgt_cluster_id = get_option(options, 'target_cluster_id')
     lo = get_option(options, 'lo')
     hi = get_option(options, 'hi')
@@ -645,6 +673,7 @@ def add_mds(gen, lustre, options):
     fstype = get_option(options, 'fstype')
     journal_size = get_option(options, 'journal_size')
     nspath = get_option(options, 'nspath')
+    mkfsoptions = get_option(options, 'mkfsoptions')
 
     node_uuid = name2uuid(lustre, node_name, 'node')
 
@@ -656,10 +685,27 @@ def add_mds(gen, lustre, options):
 
     mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname,
                      get_format_flag(options), node_uuid, mds_uuid,
-                     size, journal_size, nspath)
+                     size, journal_size, nspath, mkfsoptions)
     lustre.appendChild(mdd)
                    
 
+def add_mgmt(gen, lustre, options):
+    node_name = get_option(options, 'node')
+    node_uuid = name2uuid(lustre, node_name)
+    mgmt_name = get_option(options, 'mgmt')
+    if not mgmt_name:
+        mgmt_name = new_name('MGMT_' + node_name)
+    mgmt_uuid = name2uuid(lustre, mgmt_name, fatal=0)
+    if not mgmt_uuid:
+        mgmt_uuid = new_uuid(mgmt_name)
+        mgmt = gen.mgmt(mgmt_name, mgmt_uuid, node_uuid)
+        lustre.appendChild(mgmt)
+    else:
+        mgmt = lookup(lustre, mgmt_uuid)
+
+    node = findByName(lustre, node_name, "node")
+    node_add_profile(gen, node, 'mgmt', mgmt_uuid)
+
 def add_ost(gen, lustre, options):
     node_name = get_option(options, 'node')
     lovname = get_option(options, 'lov')
@@ -793,23 +839,27 @@ def add_lov(gen, lustre, options):
     lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
     lustre.appendChild(lovconfig)
 
-def new_filesystem(gen, lustre, mds_uuid, obd_uuid):
+def new_filesystem(gen, lustre, mds_uuid, obd_uuid, mgmt_uuid):
     fs_name = new_name("FS_fsname")
     fs_uuid = new_uuid(fs_name)
     mds = lookup(lustre, mds_uuid)
     mds.appendChild(gen.ref("filesystem", fs_uuid))
-    fs = gen.filesystem(fs_name, fs_uuid, mds_uuid, obd_uuid)
+    fs = gen.filesystem(fs_name, fs_uuid, mds_uuid, obd_uuid, mgmt_uuid)
     lustre.appendChild(fs)
     return fs_uuid
 
-def get_fs_uuid(gen, lustre, mds_name, obd_name):
+def get_fs_uuid(gen, lustre, mds_name, obd_name, mgmt_name):
     mds_uuid = name2uuid(lustre, mds_name, tag='mds')
     obd_uuid = name2uuid(lustre, obd_name, tag='lov', fatal=0)
     if not obd_uuid:
         obd_uuid = name2uuid(lustre, obd_name, tag='ost', fatal=1)
+    if mgmt_name:
+        mgmt_uuid = name2uuid(lustre, mgmt_name, tag='mgmt', fatal=1)
+    else:
+        mgmt_uuid = ''
     fs_uuid = lookup_filesystem(lustre, mds_uuid, obd_uuid)
     if not fs_uuid:
-        fs_uuid = new_filesystem(gen, lustre, mds_uuid, obd_uuid)
+        fs_uuid = new_filesystem(gen, lustre, mds_uuid, obd_uuid, mgmt_uuid)
     return fs_uuid
     
 def add_mtpt(gen, lustre, options):
@@ -825,7 +875,8 @@ def add_mtpt(gen, lustre, options):
             lov_name = get_option(options, 'ost')
             if lov_name == '':
                 error("--add mtpt requires either --filesystem or --mds with an  --lov lov_name or --ost ost_name")
-        fs_uuid = get_fs_uuid(gen, lustre, mds_name, lov_name)
+        mgmt_name = get_option(options, 'mgmt')
+        fs_uuid = get_fs_uuid(gen, lustre, mds_name, lov_name, mgmt_name)
     else:
         fs_uuid = name2uuid(lustre, fs_name, tag='filesystem')
 
@@ -910,6 +961,8 @@ def add(devtype, gen, lustre, options):
         add_echo_client(gen, lustre, options)
     elif devtype == 'cobd':
         add_cobd(gen, lustre, options)
+    elif devtype == 'mgmt':
+        add_mgmt(gen, lustre, options)
     else:
         error("unknown device type:", devtype)
     
@@ -957,6 +1010,15 @@ def main():
 
     gen = GenConfig(doc)
 
+    # the PRNG is normally seeded with time(), which is not so good for starting    # time-synchronized clusters
+    input = open('/dev/urandom', 'r')
+    if not input:
+        print 'Unable to open /dev/urandom!'
+        sys.exit(1)
+    seed = input.read(32)
+    input.close()
+    random.seed(seed)
+
     if options.batch:
         fp = open(options.batch)
         batchCommands = fp.readlines()