"""
-import sys, os, getopt, string, exceptions, random
+import sys, os, getopt, string, exceptions, re
import xml.dom.minidom
-from xml.dom.ext import PrettyPrint
+
+def printDoc(doc, stream=sys.stdout):
+ try:
+ from xml.dom.ext import PrettyPrint
+ PrettyPrint(doc, stream)
+ except ImportError:
+ stream.write(doc.toxml())
+ stream.write("\n")
+
PYMOD_DIR = "/usr/lib/lustre/python"
import Lustre
-DEFAULT_PORT = 988
-DEFAULT_STRIPE_SZ = 65536
+DEFAULT_PORT = 988
+DEFAULT_STRIPE_SZ = 1048576
DEFAULT_STRIPE_CNT = 1
DEFAULT_STRIPE_PATTERN = 0
+UUID_MAX_LENGTH = 31
def reference():
print """usage: lmc --add object [object parameters]
--add net
--node node_name
--nid nid
- --cluster_id
- --nettype tcp|elan|gm|scimac
+ --cluster_id
+ --nettype tcp|elan|gm
--hostaddr addr
--port port
--tcpbuf size
--add mds
--node node_name
--mds mds_name
+ --failover
--dev path
- --fstype extN|ext3
+ --backdev path
+ --fstype ldiskfs|ext3
+ --backfstype ldiskfs|ext3|tmpfs
--size size
--nspath
--journal_size size
--inode_size size
+ --lmv lmv_name
+ --mkfsoptions options
+ --mountfsoptions options
--add lov
--lov lov_name
--stripe_sz num
--stripe_cnt num
--stripe_pattern num
+ --lmv lmv_name
--add ost
--node node_name
--ost ost_name
+ --failover
--lov lov_name
+ --index index
--dev path
+ --backdev path
--size size
- --fstype extN|ext3
+ --fstype ldiskfs|ext3
+ --backfstype ldiskfs|ext3|tmpfs
--journal_size size
--inode_size size
- --obdtype obdecho|obdfilter
+ --osdtype obdecho|obdfilter
--ostuuid uuid
+ --mkfsoptions options
+ --mountfsoptions options
+ --nspath
+--delete ost
+ --node node_name
+ --ost ost_name
+ --migrate
+--deactivate ost
+ --node node_name
+ --ost ost_name
+
--add mtpt - Mountpoint
--node node_name
--path /mnt/point
--mds mds_name
+ --lmv lmv_name
--ost ost_name OR --lov lov_name
+ --clientoptions options
--add route
--node nodename
+ --router
--gw nid
- --tgt nid
+ --gateway_cluster_id nid
+ --target_cluster_id nid
--lo nid
--hi nid
--add mgmt - Management/monitoring service
--node node_name
--mgmt mgmt_service_name
+
+--add lmv
+ --lmv lmv_name
+
+--add cobd
+ --node node_name
+ --real_obd obd_name
+ --cache_obd obd_name
+
+--add cmobd
+ --node node_name
+ --master_dev obd_name
+ --cache_dev obd_name
+
+--commit - Close a configuration version, and start a new one
"""
PARAM = Lustre.Options.PARAM
lmc_options = [
# lmc input/output options
- ('reference', "Print short reference for commands."),
+ ('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),
# commands
('add', "", PARAM),
-
+ ('delete', "", PARAM),
+ ('deactivate', "", PARAM),
+ ('commit', "Commit all config changes and start a new version"),
+
# node options
('node', "Add a new node in the cluster configuration.", PARAM),
('timeout', "Set timeout to initiate recovery.", PARAM),
('ptldebug', "Set the portals debug level", PARAM),
('subsystem', "Specify which Lustre subsystems have debug output recorded in the log", PARAM),
- # network
- ('nettype', "Specify the network type. This can be tcp/elan/gm/scimac.", PARAM),
+ # network
+ ('nettype', "Specify the network type. This can be tcp/elan/gm.", 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),
('hi', "For a range route, this is a hi value nid.", PARAM,""),
# servers: mds and ost
- ('mds', "Specify MDS name.", PARAM),
+ ('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', "Path of the device on local system.", PARAM,""),
+ ('backdev', "Path of the device for backing storage 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"),
- ('inode_size', "Specify new inode size for underlying ext3 file system.", PARAM,"0"),
+ ('journal_size', "Specify new journal size for underlying file system.", PARAM,"0"),
+ ('inode_size', "Specify new inode size for underlying file system.", PARAM,"0"),
('fstype', "Optional argument to specify the filesystem type.", PARAM, "ext3"),
+ ('backfstype', "Optional argument to specify the backing filesystem type.", PARAM, "ext3"),
('mkfsoptions', "Optional argument to mkfs.", PARAM, ""),
+ ('mountfsoptions', "Optional argument to mount fs.", PARAM, ""),
('ostuuid', "", PARAM,""),
('nspath', "Local mount point of server namespace.", PARAM,""),
('format', ""),
+ ('migrate', "used for offline migrate of an ost in conjunctio with add/delete"),
# clients: mountpoint and echo
('echo_client', "", PARAM),
('path', "Specify the mountpoint for Lustre.", PARAM),
('filesystem', "Lustre filesystem name", PARAM,""),
+ ('clientoptions', "Specify the options for Lustre, such as async.", PARAM, ""),
# lov
('lov', "Specify LOV name.", PARAM,""),
+ ('index', "Specify index for OBD in LOV target table.", 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),
+
+ ('real_obd', "Specify the real device for the cache obd system.", PARAM),
+ ('cache_obd', "Specify the cache device for the cache obd system.", PARAM),
+ ('cobd', "Specify COBD name", PARAM),
+
+ # cmobd
+ ('master_dev', "Specify the master device for the cmobd system.", PARAM),
+ ('cache_dev', "Specify the cache device for the cmobd obd system.", PARAM),
+ ('cmobd', "Specify COBD name", PARAM),
+
('mgmt', "Specify management/monitoring service name.", PARAM, ""),
+
+ # lmv
+ ('lmv', "Specify LMV name.", PARAM,""),
]
def error(*args):
print msg
sys.exit(1)
-
+
def warning(*args):
msg = string.join(map(str,args))
print "Warning: ", msg
-
+
#
# manage names and uuids
# need to initialize this by walking tree to ensure
return ret
def new_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]
+ ctr = 2
+ ret = "%s_UUID" % (name)
+ if len(ret) > UUID_MAX_LENGTH:
+ ret = ret[-UUID_MAX_LENGTH:]
+ while uuids.has_key(ret):
+ ret = "%s_UUID_%d" % (name, ctr)
+ ctr = 1 + ctr
+ if len(ret) > UUID_MAX_LENGTH:
+ ret = ret[-UUID_MAX_LENGTH:]
+ uuids[ret] = 1
+ return ret
+
ldlm_name = 'ldlm'
ldlm_uuid = 'ldlm_UUID'
ref = self.doc.createElement(tag)
ref.setAttribute("uuidref", uuid)
return ref
-
+
+ def dev(self, devname):
+ """ generate <dev devpath="[devname]"/> """
+ tgt = self.doc.createElement('dev')
+ tgt.setAttribute("dev", devname)
+ return tgt
+
def newService(self, tag, name, uuid):
""" create a new service elmement, which requires name and uuid attributes """
new = self.doc.createElement(tag)
new.setAttribute("uuid", uuid);
new.setAttribute("name", name);
return new
-
+
def addText(self, node, str):
txt = self.doc.createTextNode(str)
node.appendChild(txt)
self.addElement(network, "recvmem", "%d" %(tcpbuf))
if irq_aff:
self.addElement(network, "irqaffinity", "%d" %(irq_aff))
-
+
return network
def routetbl(self, name, uuid):
"""create <routetbl> node"""
rtbl = self.newService("routetbl", name, uuid)
return rtbl
-
+
def route(self, gw_net_type, gw, gw_cluster_id, tgt_cluster_id, lo, hi):
""" create one entry for the route table """
ref = self.doc.createElement('route')
if hi:
ref.setAttribute("hi", hi)
return ref
-
+
def profile(self, name, uuid):
""" create a host """
profile = self.newService("profile", name, uuid)
ldlm = self.newService("ldlm", name, uuid)
return ldlm
- def osd(self, name, uuid, fs, osdtype, devname, format, ost_uuid,
- node_uuid, dev_size=0, journal_size=0, inode_size=0, nspath=""):
+ def osd(self, name, uuid, fstype, osdtype, devname, format, ost_uuid,
+ node_uuid, dev_size=0, journal_size=0, inode_size=0, nspath="",
+ mkfsoptions="", mountfsoptions="", backfstype="", backdevname=""):
osd = self.newService("osd", name, uuid)
osd.setAttribute('osdtype', osdtype)
osd.appendChild(self.ref("target", ost_uuid))
osd.appendChild(self.ref("node", node_uuid))
- if fs:
- self.addElement(osd, "fstype", fs)
+ osd.appendChild(self.dev(devname))
+
+ if fstype:
+ self.addElement(osd, "fstype", fstype)
+ if backfstype:
+ self.addElement(osd, "backfstype", backfstype)
+ if backdevname:
+ self.addElement(osd, "backdevpath", backdevname)
if devname:
dev = self.addElement(osd, "devpath", devname)
self.addElement(osd, "autoformat", format)
self.addElement(osd, "journalsize", "%s" % (journal_size))
if inode_size:
self.addElement(osd, "inodesize", "%s" % (inode_size))
+ if mkfsoptions:
+ self.addElement(osd, "mkfsoptions", mkfsoptions)
+ if mountfsoptions:
+ self.addElement(osd, "mountfsoptions", mountfsoptions)
if nspath:
self.addElement(osd, "nspath", nspath)
return osd
cobd.appendChild(self.ref("cacheobd",cache_uuid))
return cobd
+ def cmobd(self, name, uuid, real_uuid, cache_uuid):
+ cmobd = self.newService("cmobd", name, uuid)
+ cmobd.appendChild(self.ref("masterobd",real_uuid))
+ cmobd.appendChild(self.ref("cacheobd",cache_uuid))
+ return cmobd
+
def ost(self, name, uuid, osd_uuid, group=""):
ost = self.newService("ost", name, uuid)
ost.appendChild(self.ref("active", osd_uuid))
lov.setAttribute("stripepattern", str(pattern))
return lov
+ def lov_tgt(self, obd_uuid, index, generation):
+ tgt = self.doc.createElement('lov_tgt')
+ tgt.setAttribute("uuidref", obd_uuid)
+ tgt.setAttribute("index", index)
+ tgt.setAttribute("generation", generation)
+ tgt.setAttribute("active", '1')
+ return tgt
+
def lovconfig(self, name, uuid, lov_uuid):
lovconfig = self.newService("lovconfig", name, uuid)
lovconfig.appendChild(self.ref("lov", lov_uuid))
return lovconfig
- def mds(self, name, uuid, mdd_uuid, group=""):
+ def lmv(self, name, uuid):
+ lmv = self.newService("lmv", name, uuid)
+ return lmv
+
+ def mds(self, name, uuid, mdd_uuid, group="", lmv=""):
mds = self.newService("mds", name, uuid)
mds.appendChild(self.ref("active",mdd_uuid))
if group:
self.addElement(mds, "group", group)
return mds
- def mdsdev(self, name, uuid, fs, devname, format, node_uuid,
+ def mdsdev(self, name, uuid, fstype, devname, format, node_uuid,
mds_uuid, dev_size=0, journal_size=0, inode_size=256,
- nspath="", mkfsoptions=""):
+ nspath="", mkfsoptions="", mountfsoptions="", backfstype="",
+ backdevname="", lmv_uuid=""):
mdd = self.newService("mdsdev", name, uuid)
- self.addElement(mdd, "fstype", fs)
+ self.addElement(mdd, "fstype", fstype)
+ if backfstype:
+ self.addElement(mdd, "backfstype", backfstype)
dev = self.addElement(mdd, "devpath", devname)
+ if backdevname:
+ self.addElement(mdd, "backdevpath", backdevname)
self.addElement(mdd, "autoformat", format)
if dev_size:
self.addElement(mdd, "devsize", "%s" % (dev_size))
self.addElement(mdd, "nspath", nspath)
if mkfsoptions:
self.addElement(mdd, "mkfsoptions", mkfsoptions)
+ if mountfsoptions:
+ self.addElement(mdd, "mountfsoptions", mountfsoptions)
+
mdd.appendChild(self.ref("node", node_uuid))
mdd.appendChild(self.ref("target", mds_uuid))
+ mdd.appendChild(self.dev(devname))
+
+ if lmv_uuid:
+ mdd.appendChild(self.ref("lmv", lmv_uuid))
+ self.addElement(mdd, "lmv", lmv_uuid)
+
return mdd
def mgmt(self, mgmt_name, mgmt_uuid, node_uuid):
mgmt.appendChild(self.ref("active", mgmt_uuid))
return mgmt
- def mountpoint(self, name, uuid, fs_uuid, path):
+ def mountpoint(self, name, uuid, fs_uuid, path, clientoptions):
mtpt = self.newService("mountpoint", name, uuid)
mtpt.appendChild(self.ref("filesystem", fs_uuid))
self.addElement(mtpt, "path", path)
+ if clientoptions:
+ self.addElement(mtpt, "clientoptions", clientoptions)
return mtpt
def filesystem(self, name, uuid, mds_uuid, obd_uuid, mgmt_uuid):
if mgmt_uuid:
fs.appendChild(self.ref("mgmt", mgmt_uuid))
return fs
-
+
def echo_client(self, name, uuid, osc_uuid):
ec = self.newService("echoclient", name, uuid)
ec.appendChild(self.ref("obd", osc_uuid))
return ec
+ def update(self, version):
+ new = self.doc.createElement("update")
+ new.setAttribute("version", version)
+ return new
+
+ def add(self, lov, ost, index, gen):
+ new = self.doc.createElement("add")
+ new.setAttribute("lov_uuidref", lov)
+ new.setAttribute("ost_uuidref", ost)
+ new.setAttribute("index", index)
+ new.setAttribute("generation", gen)
+ return new
+
+ def delete(self, lov, ost, index, gen, options):
+ if options.delete:
+ new = self.doc.createElement("delete")
+ else:
+ new = self.doc.createElement("deactivate")
+ new.setAttribute("lov_uuidref", lov)
+ new.setAttribute("ost_uuidref", ost)
+ new.setAttribute("index", index)
+ new.setAttribute("generation", gen)
+ return new
+
############################################################
# Utilities to query a DOM tree
# Using this functions we can treat use config information
def getUUID(node):
return node.getAttribute('uuid')
+def findLastUpdate(lustre):
+ node = None
+ version = 0
+ for n in lustre.childNodes:
+ if n.nodeType == n.ELEMENT_NODE:
+ if n.nodeName != 'update':
+ continue
+ tmp = int(n.getAttribute('version'))
+ if not tmp:
+ error('malformed XML: update tag without a version attribute')
+ if tmp != version + 1:
+ error('malformed XML: expecting update record '+str(version + 1)+', found '+str(tmp)+'.')
+ version = tmp
+ node = n
+ return node
+
+def addUpdate(gen, lustre, node):
+ update = findLastUpdate(lustre)
+ if not update:
+ return
+ #add_record = update.getElementsByTagName('add')
+ #if not add_record:
+ # add_record = gen.add()
+ # update.appendChild(add_record)
+ #else:
+ # add_record = add_record[0]
+ #add_record.appendChild(node)
+ update.appendChild(node)
+
+def delUpdate(gen, lustre, node):
+ update = findLastUpdate(lustre)
+ if not update:
+ return
+ update.appendChild(node)
def findByName(lustre, name, tag = ""):
for n in lustre.childNodes:
else:
return ""
return getUUID(ret)
-
+
def lookup_filesystem(lustre, mds_uuid, ost_uuid):
for n in lustre.childNodes:
if n.nodeType == n.ELEMENT_NODE and n.nodeName == 'filesystem':
return getUUID(net[0])
return None
-
-def lov_add_obd(gen, lov, osc_uuid):
- lov.appendChild(gen.ref("obd", osc_uuid))
+def lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options):
+ tgt.setAttribute('uuidref', osc_uuid)
+ if options.migrate:
+ gener = int(tgt.getAttribute('generation'))
+ else:
+ gener = int(tgt.getAttribute('generation')) + 1
+ tgt.setAttribute('generation', str(gener))
+ tgt.setAttribute('active', '1')
+ lov_index = int(tgt.getAttribute('index'))
+ addUpdate(gen, lustre, gen.add(getUUID(lov), osc_uuid, str(lov_index),
+ str(gener)))
+ return
+
+def lov_add_obd(gen, lustre, lov, osc_uuid, options):
+ lov_name = getName(lov)
+ if options.index:
+ lov_index = get_option_int(options, 'index')
+ for tgt in lustre.getElementsByTagName('lov_tgt'):
+ if str(lov_index) == tgt.getAttribute('index'):
+ uuidref = tgt.getAttribute('uuidref')
+ if uuidref != '':
+ raise OptionError("%s --index %d is still in use: %s" %
+ (lov_name, lov_index, uuidref))
+ lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
+ return
+ else:
+ lov_index = 0
+ for tgt in lustre.getElementsByTagName('lov_tgt'):
+ uuidref = tgt.getAttribute('uuidref')
+ tmp = int(tgt.getAttribute('index'))
+ if tmp != lov_index:
+ error('malformed xml: LOV targets are not ordered; found index '+str(tmp)+', expected '+str(lov_index)+'.')
+ uuidref = tgt.getAttribute('uuidref')
+ if uuidref == '':
+ lov_mod_obd(gen, lustre, lov, tgt, osc_uuid, options)
+ return
+ lov_index = lov_index + 1
+
+ lov.appendChild(gen.lov_tgt(osc_uuid, str(lov_index), '1'))
+ addUpdate(gen, lustre, gen.add(getUUID(lov), osc_uuid, str(lov_index), '1'))
+
+def lov_del_obd(gen, lustre, lov, osc_uuid, options):
+ lov_name = getName(lov)
+ if options.index:
+ lov_index = get_option_int(options, 'index')
+ for tgt in lustre.getElementsByTagName('lov_tgt'):
+ index = tgt.getAttribute('index')
+ if index == lov_index:
+ uuidref = tgt.getAttribute('uuidref')
+ if uuidref != osc_uuid:
+ raise OptionError("%s --index %d contains %s, not %s" %
+ (lov_name, lov_index, osc_uuid, uuidref))
+ if options.delete:
+ tgt.setAttribute('uuidref', '')
+
+ # bump the generation just in case...
+ if options.migrate:
+ gen = int(tgt.getAttribute('generation'))
+ else:
+ gen = int(tgt.getAttribute('generation')) + 1
+
+ tgt.setAttribute('active', '0')
+ tgt.setAttribute('generation', str(gen))
+ return
+ raise OptionError("%s --index %d not in use by %s." %
+ (lov_name, lov_index, osc_uuid))
+
+ for tgt in lustre.getElementsByTagName('lov_tgt'):
+ uuidref = tgt.getAttribute('uuidref')
+ if uuidref == osc_uuid:
+ genera = int(tgt.getAttribute('generation'))
+ delete_rec = gen.delete(getUUID(lov),
+ osc_uuid,tgt.getAttribute('index'),
+ str(genera), options)
+ delUpdate(gen, lustre, delete_rec)
+
+ if options.delete:
+ tgt.setAttribute('uuidref', '')
+ if not options.migrate:
+ genera = genera + 1
+ tgt.setAttribute('active', '0')
+ tgt.setAttribute('generation', str(genera))
+
+def lmv_add_obd(gen, lmv, mdc_uuid):
+ lmv.appendChild(gen.ref("mds", mdc_uuid))
def ref_exists(profile, uuid):
elist = profile.childNodes
if ref == uuid:
return 1
return 0
-
+
# ensure that uuid is not already in the profile
# return true if uuid is added
def node_add_profile(gen, node, ref, uuid):
return 0
profile.appendChild(gen.ref(ref, uuid))
return 1
-
+
+# ensure that uuid is not already in the profile
+# return true if uuid is added
+def node_found_target_by_dev(gen, lustre, node, devname):
+ refname = "%s_ref" % "profile"
+ ret = node.getElementsByTagName(refname)
+ if not ret:
+ error('node has no profile ref:', node)
+ prof_uuid = ret[0].getAttribute('uuidref')
+ profile = lookup(node.parentNode, prof_uuid)
+ if not profile:
+ error("no profile found:", prof_uuid)
+
+ osd_list = lustre.getElementsByTagName('osd')
+
+ for osd in osd_list:
+ obd_dev = osd.getElementsByTagName('dev')
+ if obd_dev and obd_dev[0].getAttribute('dev') == devname:
+ for ost in lustre.getElementsByTagName('ost'):
+ active_ret = ost.getElementsByTagName('active_ref')
+ if active_ret[0].getAttribute('uuidref') == osd.getAttribute('uuid'):
+ return ost.getAttribute('uuid')
+
+ mdsdev_list = lustre.getElementsByTagName('mdsdev')
+
+ for mdsdev in mdsdev_list:
+ obd_dev = mdsdev.getElementsByTagName('dev')
+ if obd_dev and obd_dev[0].getAttribute('dev') == devname:
+ for mds in lustre.getElementsByTagName('mds'):
+ active_ret = mds.getElementsByTagName('active_ref')
+ if active_ret[0].getAttribute('uuidref') == mdsdev.getAttribute('uuid'):
+ return mds.getAttribute('uuid')
+
+ return ""
+
def get_attr(dom_node, attr, default=""):
v = dom_node.getAttribute(attr)
if v:
if default_upcall or options.lustre_upcall:
if options.lustre_upcall:
gen.addElement(node, 'lustreUpcall', options.lustre_upcall)
- else:
+ else:
gen.addElement(node, 'lustreUpcall', default_upcall)
if default_upcall or options.portals_upcall:
if options.portals_upcall:
node_add_profile(gen, node, 'ldlm', ldlm_uuid)
set_node_options(gen, node, options)
+
return node
-
+
def add_node(gen, lustre, options):
""" create a node with a network config """
port = get_option_int(options, 'port')
tcpbuf = get_option_int(options, 'tcpbuf')
irq_aff = get_option_int(options, 'irq_affinity')
- elif net_type in ('elan', 'gm', 'scimac'):
+ elif net_type in ('elan', 'gm'):
port = 0
tcpbuf = 0
irq_aff = 0
node = findByName(lustre, node_name, "node")
if not node:
error (node_name, " not found.")
-
+
rlist = node.getElementsByTagName('routetbl')
if len(rlist) > 0:
rtbl = rlist[0]
def add_mds(gen, lustre, options):
node_name = get_option(options, 'node')
mds_name = get_option(options, 'mds')
+ lmv_name = get_option(options, 'lmv')
mdd_name = new_name("MDD_" + mds_name +"_" + node_name)
mdd_uuid = new_uuid(mdd_name)
+ lmv_uuid = ""
+ if lmv_name:
+ lmv = findByName(lustre, lmv_name, "lmv")
+ if not lmv:
+ error('add_mds:', '"' + lmv_name + '"', "lmv element not found.")
+ lmv_uuid = name2uuid(lustre, lmv_name, fatal=0)
+
mds_uuid = name2uuid(lustre, mds_name, 'mds', fatal=0)
if not mds_uuid:
mds_uuid = new_uuid(mds_name)
mds = gen.mds(mds_name, mds_uuid, mdd_uuid, options.group)
lustre.appendChild(mds)
+ if lmv_name:
+ lmv_add_obd(gen, lmv, mds_uuid)
else:
mds = lookup(lustre, mds_uuid)
+
if options.failover:
mds.setAttribute('failover', "1")
devname = get_option(options, 'dev')
+ backdevname = get_option(options, 'backdev')
size = get_option(options, 'size')
fstype = get_option(options, 'fstype')
+ backfstype = get_option(options, 'backfstype')
journal_size = get_option(options, 'journal_size')
inode_size = get_option(options, 'inode_size')
nspath = get_option(options, 'nspath')
mkfsoptions = get_option(options, 'mkfsoptions')
+ mountfsoptions = get_option(options, 'mountfsoptions')
node_uuid = name2uuid(lustre, node_name, 'node')
if not net_uuid:
error("NODE: ", node_name, "not found")
+ if lmv_name:
+ mds.appendChild(gen.ref("lmv", lmv_uuid))
+
mdd = gen.mdsdev(mdd_name, mdd_uuid, fstype, devname,
get_format_flag(options), node_uuid, mds_uuid,
- size, journal_size, inode_size, nspath, mkfsoptions)
+ size, journal_size, inode_size, nspath, mkfsoptions,
+ mountfsoptions, backfstype, backdevname, lmv_uuid)
lustre.appendChild(mdd)
-
+
def add_mgmt(gen, lustre, options):
node_name = get_option(options, 'node')
if osdtype == 'obdecho':
fstype = ''
+ backfstype = ''
devname = ''
+ backdevname = ''
size = 0
- fstype = ''
journal_size = ''
inode_size = ''
+ mkfsoptions = ''
+ mountfsoptions = ''
else:
devname = get_option(options, 'dev') # can be unset for bluearcs
+ backdevname = get_option(options, 'backdev')
size = get_option(options, 'size')
fstype = get_option(options, 'fstype')
+ backfstype = get_option(options, 'backfstype')
journal_size = get_option(options, 'journal_size')
inode_size = get_option(options, 'inode_size')
-
+ mkfsoptions = get_option(options, 'mkfsoptions')
+ mountfsoptions = get_option(options, 'mountfsoptions')
+
nspath = get_option(options, 'nspath')
ostname = get_option(options, 'ost')
ost = gen.ost(ostname, ost_uuid, osd_uuid, options.group)
lustre.appendChild(ost)
- if lovname:
- lov = findByName(lustre, lovname, "lov")
- if not lov:
- error('add_ost:', '"'+lovname+'"', "lov element not found.")
- lov_add_obd(gen, lov, ost_uuid)
else:
ost = lookup(lustre, ost_uuid)
+ if lovname:
+ lov = findByName(lustre, lovname, "lov")
+ if not lov:
+ error('add_ost:', '"'+lovname+'"', "lov element not found.")
+ lov_add_obd(gen, lustre, lov, ost_uuid, options)
+
if options.failover:
ost.setAttribute('failover', "1")
-
+
osd = gen.osd(osdname, osd_uuid, fstype, osdtype, devname,
get_format_flag(options), ost_uuid, node_uuid, size,
- journal_size, inode_size, nspath)
+ journal_size, inode_size, nspath, mkfsoptions,
+ mountfsoptions, backfstype, backdevname)
node = findByName(lustre, node_name, "node")
node_add_profile(gen, node, 'osd', osd_uuid)
lustre.appendChild(osd)
-
+def del_ost(gen, lustre, options):
+ ostname = get_option(options, 'ost')
+ if not ostname:
+ raise OptionError("del_ost: --ost requires a <ost name>")
+ ost = findByName(lustre, ostname, "ost")
+ if not ost:
+ error('del_ost: ', 'Unable to find ', ostname)
+ ost_uuid = name2uuid(lustre, ostname, fatal=0)
+ if not ost_uuid:
+ error('del_ost: ', 'Unable to find uuid for ', ostname)
+ lovname = get_option(options, 'lov')
+ if lovname:
+ lov = findByName(lustre, lovname, "lov")
+ if not lov:
+ error('del_ost:', '"'+lovname+'"', "lov element not found.")
+ lov_del_obd(gen, lustre, lov, ost_uuid, options)
+ # if the user specified a speficic LOV don't delete the OST itself
+ return
+
+ # remove OSD references from all LOVs
+ for n in lustre.getElementsByTagName('lov'):
+ lov_del_obd(gen, lustre, n, ost_uuid, options)
+ if not options.migrate:
+ return
+ # delete the OSDs
+ for osd in lustre.getElementsByTagName('osd'):
+ if ref_exists(osd, ost_uuid):
+ osd_uuid = osd.getAttribute('uuid')
+ # delete all profile references to this OSD
+ for profile in lustre.getElementsByTagName('profile'):
+ for osd_ref in profile.getElementsByTagName('osd_ref'):
+ if osd_uuid == osd_ref.getAttribute('uuidref'):
+ profile.removeChild(osd_ref)
+ lustre.removeChild(osd)
+
+ # delete the OST
+ lustre.removeChild(ost)
+
+def add_cmobd(gen, lustre, options):
+ node_name = get_option(options, 'node')
+ name = get_option(options, 'cmobd')
+ uuid = new_uuid(name)
+
+ real_name = get_option(options, 'master_dev')
+ cache_name = get_option(options, 'cache_dev')
+
+ node = findByName(lustre, node_name, "node")
+ node_add_profile(gen, node, "cmobd", uuid)
+ real_uuid = node_found_target_by_dev(gen, lustre, node, real_name)
+ cache_uuid = node_found_target_by_dev(gen, lustre, node, cache_name)
+ if not real_uuid:
+ panic("add_cmobd", "can not find real_uuid")
+ if not cache_uuid:
+ panic("add_cmobd", "can not find cache_uuid")
+ cmobd = gen.cmobd(name, uuid, real_uuid, cache_uuid)
+ lustre.appendChild(cmobd)
+
def add_cobd(gen, lustre, options):
node_name = get_option(options, 'node')
- name = new_name('COBD_' + node_name)
+ name = get_option(options, 'cobd')
uuid = new_uuid(name)
real_name = get_option(options, 'real_obd')
cache_name = get_option(options, 'cache_obd')
-
- real_uuid = name2uuid(lustre, real_name, tag='obd')
- cache_uuid = name2uuid(lustre, cache_name, tag='obd')
+
+ real_uuid = name2uuid(lustre, real_name, tag='lov', fatal=0)
+ cache_uuid = name2uuid(lustre, cache_name, tag='lov', fatal=0)
+
+ if real_uuid:
+ node = lookup(lustre, real_uuid)
+ rets = node.getElementsByTagName('lov_tgt')
+ for ret in rets:
+ ost_uuid = ret.getAttribute('uuidref')
+ ost_node = lookup(lustre, ost_uuid)
+ ret = ost_node.getElementsByTagName('active_ref')
+ if ret:
+ osd_uuid = ret[0].getAttribute('uuidref')
+ osd_node = lookup(lustre, osd_uuid)
+ gen.addElement(osd_node, 'cachetype', 'master')
+
+ if cache_uuid:
+ node = lookup(lustre, cache_uuid)
+ rets = node.getElementsByTagName('lov_tgt')
+ for ret in rets:
+ ost_uuid = ret.getAttribute('uuidref')
+ ost_node = lookup(lustre, ost_uuid)
+ ret = ost_node.getElementsByTagName('active_ref')
+ if ret:
+ osd_uuid = ret[0].getAttribute('uuidref')
+ osd_node = lookup(lustre, osd_uuid)
+ gen.addElement(osd_node, 'cachetype', 'cache')
+
+ if not real_uuid or not cache_uuid:
+ real_uuid = name2uuid(lustre,real_name, tag='mds')
+ cache_uuid = name2uuid(lustre,cache_name, tag='mds')
+ if real_uuid:
+ mds_node = lookup(lustre, real_uuid)
+ ret = mds_node.getElementsByTagName('active_ref')
+ if ret:
+ mdsdev_uuid = ret[0].getAttribute('uuidref')
+ mdsdev_node = lookup(lustre, mdsdev_uuid)
+ gen.addElement(mdsdev_node, 'cachetype', 'master')
+ if cache_uuid:
+ mds_node = lookup(lustre, cache_uuid)
+ ret = mds_node.getElementsByTagName('active_ref')
+ if ret:
+ mdsdev_uuid = ret[0].getAttribute('uuidref')
+ mdsdev_node = lookup(lustre, mdsdev_uuid)
+ gen.addElement(mdsdev_node, 'cachetype', 'cache')
node = findByName(lustre, node_name, "node")
- node_add_profile(gen, node, "cobd", uuid)
cobd = gen.cobd(name, uuid, real_uuid, cache_uuid)
lustre.appendChild(cobd)
def add_lov(gen, lustre, options):
""" create a lov """
+ lmv_name = get_option(options, 'lmv')
lov_orig = get_option(options, 'lov')
name = new_name(lov_orig)
if name != lov_orig:
warning("name:", lov_orig, "already used. using:", name)
mds_name = get_option(options, 'mds')
+ if not mds_name:
+ if not lmv_name:
+ error("LOV: MDS or LMV must be specified.");
+
stripe_sz = get_option_int(options, 'stripe_sz')
stripe_cnt = get_option_int(options, 'stripe_cnt')
pattern = get_option_int(options, 'stripe_pattern')
if ret:
error("LOV: ", name, " already exists.")
- mds_uuid = name2uuid(lustre, mds_name, 'mds')
+ if not mds_name:
+ mds_uuid = name2uuid(lustre, lmv_name, 'lmv')
+ else:
+ mds_uuid = name2uuid(lustre, mds_name, 'mds')
+
lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
lustre.appendChild(lov)
-
+
# add an lovconfig entry to the active mdsdev profile
lovconfig_name = new_name('LVCFG_' + name)
lovconfig_uuid = new_uuid(lovconfig_name)
- mds = findByName(lustre, mds_name)
- mds.appendChild(gen.ref("lovconfig", lovconfig_uuid))
+ if mds_name:
+ mds = findByName(lustre, mds_name, "mds")
+ mds.appendChild(gen.ref("lovconfig", lovconfig_uuid))
+ if lmv_name:
+ lmv = findByName(lustre, lmv_name, "lmv")
+ lmv.appendChild(gen.ref("lovconfig", lovconfig_uuid))
lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
lustre.appendChild(lovconfig)
def add_default_lov(gen, lustre, mds_name, lov_name):
""" create a default lov """
-
+
stripe_sz = DEFAULT_STRIPE_SZ
stripe_cnt = DEFAULT_STRIPE_CNT
pattern = DEFAULT_STRIPE_PATTERN
uuid = new_uuid(lov_name)
-
+
ret = findByName(lustre, lov_name, "lov")
if ret:
error("LOV: ", lov_name, " already exists.")
-
+
mds_uuid = name2uuid(lustre, mds_name, 'mds')
lov = gen.lov(lov_name, uuid, mds_uuid, stripe_sz, stripe_cnt, pattern)
lustre.appendChild(lov)
-
+
# add an lovconfig entry to the active mdsdev profile
lovconfig_name = new_name('LVCFG_' + lov_name)
lovconfig_uuid = new_uuid(lovconfig_name)
lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
lustre.appendChild(lovconfig)
+def add_lmv(gen, lustre, options):
+ """ create a lmv """
+
+ lmv_orig = get_option(options, 'lmv')
+ name = new_name(lmv_orig)
+ if name != lmv_orig:
+ warning("name:", lmv_orig, "already used. using:", name)
+
+ uuid = new_uuid(name)
+ ret = findByName(lustre, name, "lmv")
+ if ret:
+ error("LMV: ", name, " already exists.")
+
+ lmv = gen.lmv(name, uuid)
+ lustre.appendChild(lmv)
+
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))
+ cobd = lookup(lustre, mds_uuid)
+ #SHOULD appendChild filesystem to real mds not cobd
+ ret = cobd.getElementsByTagName("cacheobd_ref")
+ if ret:
+ cacheobd_uuid = ret[0].getAttribute('uuidref')
+ cacheobd = lookup(lustre, cacheobd_uuid)
+ cacheobd.appendChild(gen.ref("filesystem", fs_uuid))
+ ret = cobd.getElementsByTagName("realobd_ref")
+ if ret:
+ realobd_uuid = ret[0].getAttribute('uuidref')
+ realobd = lookup(lustre, realobd_uuid)
+ realobd.appendChild(gen.ref("filesystem", fs_uuid))
+ else:
+ cobd.appendChild(gen.ref("filesystem", fs_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, mgmt_name):
- mds_uuid = name2uuid(lustre, mds_name, tag='mds')
+ mds_uuid = name2uuid(lustre, mds_name, tag='mds', fatal=0)
+ if not mds_uuid:
+ mds_uuid = name2uuid(lustre, mds_name, tag='lmv', fatal=0)
+ if not mds_uuid:
+ mds_uuid = name2uuid(lustre, mds_name, tag='cobd', fatal=1)
obd_uuid = name2uuid(lustre, obd_name, tag='lov', fatal=0)
+ if obd_uuid == '':
+ obd_uuid = name2uuid(lustre, obd_name, tag='cobd')
if mgmt_name:
mgmt_uuid = name2uuid(lustre, mgmt_name, tag='mgmt', fatal=1)
else:
if not fs_uuid:
fs_uuid = new_filesystem(gen, lustre, mds_uuid, obd_uuid, mgmt_uuid)
return fs_uuid
-
+
def add_mtpt(gen, lustre, options):
""" create mtpt on a node """
node_name = get_option(options, 'node')
path = get_option(options, 'path')
+ clientoptions = get_option(options, "clientoptions")
fs_name = get_option(options, 'filesystem')
lov_name = get_option(options, 'lov')
ost_name = get_option(options, 'ost')
mds_name = get_option(options, 'mds')
+ if mds_name == '':
+ mds_name = get_option(options, 'lmv')
+ if mds_name == '':
+ error("--add mtpt requires either --mds or --lmv.")
if lov_name == '':
if ost_name == '':
error("--add mtpt requires --lov lov_name or --ost ost_name")
if not ost_uuid:
error('add_mtpt:', '"'+ost_name+'"', "ost element not found.")
lov = findByName(lustre, lov_name, "lov")
- lov_add_obd(gen, lov, ost_uuid)
+ lov_add_obd(gen, lustre, lov, ost_uuid, options)
if fs_name == '':
mgmt_name = get_option(options, 'mgmt')
error("MOUNTPOINT: ", name, " already exists.")
uuid = new_uuid(name)
- mtpt = gen.mountpoint(name, uuid, fs_uuid, path)
+ mtpt = gen.mountpoint(name, uuid, fs_uuid, path, clientoptions)
node = findByName(lustre, node_name, "node")
if not node:
error('node:', node_name, "not found.")
node_add_profile(gen, node, "mountpoint", uuid)
lustre.appendChild(mtpt)
+def commit_version(gen, lustre):
+ update = findLastUpdate(lustre)
+ if update:
+ version = int(update.getAttribute("version")) + 1
+ else:
+ version = 1
+
+ new = gen.update(str(version))
+ lustre.appendChild(new)
+
+
############################################################
# Command line processing
#
try:
n = int(val)
except ValueError:
- raise OptionError("--%s <num> (value must be integer)" % (tag))
+ raise OptionError("--%s <num> (value must be integer)" % (tag))
return n
# simple class for profiling
str = '%s: %g secs' % (msg, d)
print str
+#################################################################
+# function cmdlinesplit used to split cmd line from batch file
+#
+def cmdlinesplit(cmdline):
+
+ double_quote = re.compile(r'"(([^"\\]|\\.)*)"')
+ single_quote = re.compile(r"'(.*?)'")
+ escaped = re.compile(r'\\(.)')
+ esc_quote = re.compile(r'\\([\\"])')
+ outside = re.compile(r"""([^\s\\'"]+)""") #" fucking emacs.
+
+ arg_list = []
+ i = 0; arg = None
+ while i < len(cmdline):
+ c = cmdline[i]
+ if c == '"':
+ match = double_quote.match(cmdline, i)
+ if not match:
+ print "Unmatched double quote:", cmdline
+ sys.exit(1)
+ i = match.end()
+ if arg is None: arg = esc_quote.sub(r'\1', match.group(1))
+ else: arg = arg + esc_quote.sub(r'\1', match.group(1))
+
+ elif c == "'":
+ match = single_quote.match(cmdline, i)
+ if not match:
+ print "Unmatched single quote:", cmdline
+ sys.exit(1)
+ i = match.end()
+ if arg is None: arg = match.group(1)
+ else: arg = arg + match.group(1)
+
+ elif c == "\\":
+ match = escaped.match(cmdline, i)
+ if not match:
+ print "Unmatched backslash", cmdline
+ sys.exit(1)
+ i = match.end()
+ if arg is None: arg = match.group(1)
+ else: arg = arg + match.group(1)
+
+ elif c in string.whitespace:
+ if arg != None:
+ arg_list.append(str(arg))
+ arg = None
+ while i < len(cmdline) and cmdline[i] in string.whitespace:
+ i = i + 1
+ else:
+ match = outside.match(cmdline, i)
+ assert match
+ i = match.end()
+ if arg is None: arg = match.group()
+ else: arg = arg + match.group()
+
+ if arg != None: arg_list.append(str(arg))
+
+ return arg_list
+
############################################################
# Main
#
add_echo_client(gen, lustre, options)
elif devtype == 'cobd':
add_cobd(gen, lustre, options)
+ elif devtype == 'cmobd':
+ add_cmobd(gen, lustre, options)
elif devtype == 'mgmt':
add_mgmt(gen, lustre, options)
+ elif devtype == 'lmv':
+ add_lmv(gen, lustre, options)
else:
error("unknown device type:", devtype)
-
+
+def delete(devtype, gen, lustre, options):
+ if devtype == 'ost':
+ del_ost(gen, lustre, options)
+ elif options.delete:
+ error("delete not supported for device type:", devtype)
+ elif options.deactivate:
+ error("deactivate not supported for device type:", devtype)
+ else:
+ error("in delete(), but neither .delete nor .deactivate are set. Tell CFS.")
+
+def commit(gen, lustre):
+ commit_version(gen, lustre)
+
def do_command(gen, lustre, options, args):
if options.add:
add(options.add, gen, lustre, options)
+ elif options.delete:
+ delete(options.delete, gen, lustre, options)
+ elif options.deactivate:
+ delete(options.deactivate, gen, lustre, options)
+ elif options.commit:
+ commit(gen, lustre)
else:
error("Missing command")
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()
fp.close()
for cmd in batchCommands:
try:
- options, args = cl.parse(string.split(cmd))
+ options, args = cl.parse(cmdlinesplit(cmd))
if options.merge or options.input or options.output:
print "The batchfile should not contain --merge, --input or --output."
sys.exit(1)
panic("lmc", e)
if outFile == '-':
- PrettyPrint(doc)
+ printDoc(doc)
else:
- PrettyPrint(doc, open(outFile,"w"))
+ printDoc(doc, open(outFile,"w"))
if __name__ == "__main__":
main()