#
"""
-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
--upcall path
--lustre_upcall path
--portals_upcall path
+ --ptldebug debug_level
+ --subsystem subsystem_name
--add net
--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
--dev path
--fstype extN|ext3
--size size
+ --nspath
+ --journal_size size
--add lov
--lov lov_name
--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
-
+
--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),
+ ('ptldebug', "Set the portals debug level", PARAM),
+ ('subsystem', "Specify which Lustre subsystems have debug output recorded in the log", 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, ""),
+ ('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):
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'
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);
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
return ldlm
def osd(self, name, uuid, fs, osdtype, devname, format, ost_uuid,
- node_uuid, dev_size=0, journal_size=0):
+ node_uuid, dev_size=0, journal_size=0, nspath=""):
osd = self.newService("osd", name, uuid)
osd.setAttribute('osdtype', osdtype)
osd.appendChild(self.ref("target", ost_uuid))
self.addElement(osd, "devsize", "%s" % (dev_size))
if journal_size:
self.addElement(osd, "journalsize", "%s" % (journal_size))
+ if nspath:
+ self.addElement(osd, "nspath", nspath)
return osd
def cobd(self, name, uuid, real_uuid, cache_uuid):
return mds
def mdsdev(self, name, uuid, fs, devname, format, node_uuid,
- mds_uuid, dev_size=0, journal_size=0):
+ 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)
self.addElement(mdd, "devsize", "%s" % (dev_size))
if journal_size:
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):
gen.addElement(node, 'portalsUpcall', options.portals_upcall)
else:
gen.addElement(node, 'portalsUpcall', default_upcall)
+ if options.ptldebug:
+ gen.addElement(node, "ptldebug", get_option(options, 'ptldebug'))
+ if options.subsystem:
+ gen.addElement(node, "subsystem", get_option(options, 'subsystem'))
return node
def do_add_node(gen, lustre, options, node_name):
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)
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)
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')
size = get_option(options, 'size')
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')
mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname,
get_format_flag(options), node_uuid, mds_uuid,
- dev_size=size, journal_size=journal_size)
+ 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')
fstype = get_option(options, 'fstype')
journal_size = get_option(options, 'journal_size')
+ nspath = get_option(options, 'nspath')
+
ostname = get_option(options, 'ost')
if not ostname:
ostname = new_name('OST_'+ node_name)
osd = gen.osd(osdname, osd_uuid, fstype, osdtype, devname,
get_format_flag(options), ost_uuid, node_uuid, size,
- journal_size)
+ journal_size, nspath)
node = findByName(lustre, node_name, "node")
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):
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')
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)
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()