#!/usr/bin/env python # # Copyright (C) 2002 Cluster File Systems, Inc. # Author: Robert Read # This file is part of Lustre, http://www.lustre.org. # # Lustre is free software; you can redistribute it and/or # modify it under the terms of version 2 of the GNU General Public # License as published by the Free Software Foundation. # # Lustre is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Lustre; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # lmc - lustre configurtion data manager # import sys, getopt import xml.dom.minidom def usage(): print """usage: lmc [--ost | --mtpt | --lov] cmd args Commands: --ost "device" "host" [size] Creates an OBD/OST/OSC configuration triplet for a new device. When used on "host", the device will be initialized and the OST will be enabled. On client nodes, the OSC will be avaiable. --mtpt "mds" "ost/lov-name" /mnt/point Creates a client mount point. --lov "mds" "lov name" < "all-ost.xml" Produces a logical volum striped over the OSTs found in all-ost.xml. (Not sure how all-ost.xml is created, exactly.) Options: --merge="xml file" Add the new objects to an existing file --format Format the partitions if unformated --reformat Reformat partitions (this should be an lconf arg, I think) (SCRIPT STILL UNDER DEVELOPMENT, MOST COMMANDS/OPTIONS UNIMPLEMENTED) """ # # manage names and uuids # need to initialize this by walking tree to ensure # no duplicate names or uuids are created. # this are just place holders for now. # consider changing this to be like OBD-dev-host name_ctr = 1 def new_name(base): global name_ctr name = "%s_%d" % (base, name_ctr) name_ctr += 1 return name def get_uuid(name): return "%s_UUID" % (name) # # Create a new empty lustre document def new_Lustre(): str = """ """ dom = xml.dom.minidom.parseString(str) return dom # # Create a new object the "correct" way by using the DOM api. # def new_OBD(dom, name, fs, devname, format, dev_size=0, dev_file=""): uuid = get_uuid(name) obd = dom.createElement("obd") obd.setAttribute("name", name) obd.setAttribute("uuid", uuid) fstype = dom.createElement("fstype") txt= dom.createTextNode(fs) fstype.appendChild(txt) obd.appendChild(fstype) dev = dom.createElement("device") if (dev_size): dev.setAttribute("size", "%s" % (dev_size)) txt = dom.createTextNode(devname) dev.appendChild(txt) obd.appendChild(dev) fmt = dom.createElement("autoformat") txt = dom.createTextNode(format) fmt.appendChild(txt) obd.appendChild(fmt) return obd # # Create new object the fast and easy way # (note: dom is not needed for this way) def new_OSC(dom, osc, obd): osc_uuid = get_uuid(osc) obd_uuid = get_uuid(obd) osc_str =""" """ % (osc, osc_uuid, obd, obd_uuid) osc = xml.dom.minidom.parseString(osc_str) return osc.getElementsByTagName("osc")[0] # # Create new object the fast and easy way # def new_OST(dom, ost, host, port, obd): ost_uuid = get_uuid(ost) obd_uuid = get_uuid(obd) str =""" %s %d """ % (ost, ost_uuid, host, port, obd, obd_uuid) node = xml.dom.minidom.parseString(str) return node.getElementsByTagName("ost")[0] # # Create a new obd, osc, and ost. Add them to the DOM. # def add_OST(dom, options, args): # XXX need some error checking devname = args[0] host = args[1] size = args[2] obdname = new_name("obd") oscname = new_name("osc") ostname = new_name("ost") obd = new_OBD(dom, obdname, "extN", devname, "no", size) osc = new_OSC(dom, oscname, obdname) ost = new_OST(dom, ostname, host, 2020, obdname) dom.getElementsByTagName("lustre")[0].appendChild(obd) dom.getElementsByTagName("lustre")[0].appendChild(osc) dom.getElementsByTagName("lustre")[0].appendChild(ost) # # Command line processing # def parse_cmdline(argv): short_opts = "ho:" long_opts = ["ost", "mtpt", "lov", "merge=", "format", "reformat", "output=", "help"] opts = [] args = [] options = {} try: opts, args = getopt.getopt(argv, short_opts, long_opts) except getopt.GetoptError: print "invalid opt" usage() sys.exit(2) for o, a in opts: if o in ("-h", "--help"): usage() sys.exit() if o in ("-o", "--output"): options['output'] = a if o == "--ost": options['ost'] = 1 if o == "--merge": options['merge'] = a if o == "--format": options['format'] = 1 if o == "--reformat": options['reformat'] = 1 return options, args def main(): options, args = parse_cmdline(sys.argv[1:]) outFile = '-' if options.has_key('merge'): outFile = options['merge'] dom = xml.dom.minidom.parse(outFile) else: dom = new_Lustre() if options.has_key('output'): outFile = options['output'] if options.has_key('ost'): add_OST(dom, options, args) elif options.has_key('mtpt'): print "--mtpt not implemented" elif options.has_key('lov'): print "--lov not implemented" else: print "Missing command" usage() sys.exit(1) if outFile == '-': print dom.toxml() else: dom.writexml(open(outFile,"w")) if __name__ == "__main__": main()