Whamcloud - gitweb
initial version
[fs/lustre-release.git] / lustre / utils / lmc
1 #!/usr/bin/env python
2 #
3 # lmc - lustre configurtion data  manager
4 #
5 import sys, getopt
6 import xml.dom.minidom
7
8
9 def usage():
10     print """usage: lmc [--ost | --mtpt | --lov] cmd args
11 Commands:
12 --ost "device" "host" [size]
13    Creates an OBD/OST/OSC configuration triplet for a new device.
14    When used on "host", the device will be initialized and the OST
15    will be enabled. On client nodes, the OSC will be avaiable.
16
17 --mtpt "mds" "ost/lov-name" /mnt/point
18    Creates a client mount point.
19
20 --lov "mds" "lov name < "all-ost.xml"
21    Produces a logical volum striped over the OSTs found in all-ost.xml.
22    (Not sure how all-ost.xml is created, exactly.)
23
24 Options:
25 --merge="xml file"  Add the new objects to an existing file
26 --format            Format the partitions if unformated
27 --reformat          Reformat partitions (this should be an lconf arg,
28                     I think)
29 (SCRIPT STILL UNDER DEVELOPMENT, MOST COMMANDS/OPTIONS UNIMPLEMENTED)
30 """
31
32 #
33 # manage names and uuids
34 # need to initialize this by walking tree to ensure
35 # no duplicate names or uuids are created.
36 # this are just place holders for now.
37 # consider changing this to be like OBD-dev-host
38 name_ctr = 1
39 def new_name(base):
40     global name_ctr
41     name = "%s_%d" % (base, name_ctr)
42     name_ctr += 1
43     return name
44
45 def get_uuid(name):
46     return "%s_UUID" % (name)
47
48 #
49 # Create a new empty lustre document 
50 def new_Lustre():
51     str = """<lustre>
52 </lustre>"""
53     dom = xml.dom.minidom.parseString(str)
54     return dom
55
56 #
57 # Create a new object the "correct" way by using the DOM api.
58 #
59 def new_OBD(dom, name, fs, devname, format, dev_size=0, dev_file=""):
60     uuid = get_uuid(name)
61     
62     obd = dom.createElement("obd")
63     obd.setAttribute("name", name)
64     obd.setAttribute("uuid", uuid)
65
66     fstype = dom.createElement("fstype")
67     txt= dom.createTextNode(fs)
68     fstype.appendChild(txt)
69     obd.appendChild(fstype)
70     
71     dev = dom.createElement("device")
72     if (dev_size):
73         dev.setAttribute("size", "%s" % (dev_size))
74     txt = dom.createTextNode(devname)
75     dev.appendChild(txt)
76     obd.appendChild(dev)
77
78     fmt = dom.createElement("autoformat")
79     txt = dom.createTextNode(format)
80     fmt.appendChild(txt)
81     obd.appendChild(fmt)
82
83     return obd
84
85 #
86 # Create new object the fast and easy way
87 # (note: dom is not needed for this way)
88 def new_OSC(dom, osc, obd):
89     osc_uuid = get_uuid(osc)
90     obd_uuid = get_uuid(obd)
91
92     osc_str ="""
93 <osc name="%s" uuid="%s">
94    <service_id num="1" name="%s" uuid="%s"/>
95 </osc> """ % (osc, osc_uuid, obd, obd_uuid)
96     osc = xml.dom.minidom.parseString(osc_str)
97     return osc.getElementsByTagName("osc")[0]
98
99 #
100 # Create new object the fast and easy way
101 #
102 def new_OST(dom, ost, host, port, obd):
103     ost_uuid = get_uuid(ost)
104     obd_uuid = get_uuid(obd)
105
106     str ="""
107 <ost name="%s" uuid="%s">
108    <network type="tcp">
109       <server>%s</server>
110       <port>%d</port>
111    </network>
112    <server_id num="1" name="%s" uuid="%s"/>
113 </ost> """ % (ost, ost_uuid, host, port, obd, obd_uuid)
114     node = xml.dom.minidom.parseString(str)
115     return node.getElementsByTagName("ost")[0]
116
117 #
118 # Create a new obd, osc, and ost. Add them to the DOM.
119 #
120 def add_OST(dom, options, args):
121     # XXX need some error checking
122     devname = args[0]
123     host = args[1]
124     size = args[2]
125
126     obdname = new_name("obd")
127     oscname = new_name("osc")
128     ostname = new_name("ost")
129     
130     obd = new_OBD(dom, obdname, "extN", devname, "no", size)
131     osc = new_OSC(dom, oscname, obdname)
132     ost = new_OST(dom, ostname, host, 2020, obdname)
133     
134     dom.getElementsByTagName("lustre")[0].appendChild(obd)
135     dom.getElementsByTagName("lustre")[0].appendChild(osc)
136     dom.getElementsByTagName("lustre")[0].appendChild(ost)
137
138
139 #
140 # Command line processing
141 #
142
143 def cmdline(argv):
144     short_opts = "ho:"
145     long_opts = ["ost", "mtpt", "lov",
146                  "merge=", "format", "reformat", "output=",
147                  "help"]
148     opts = []
149     args = []
150     options = {}
151     try:
152         opts, args = getopt.getopt(argv, short_opts, long_opts)
153     except getopt.GetoptError:
154         print "invalid opt"
155         usage()
156         sys.exit(2)
157
158     for o, a in opts:
159         if o in ("-h", "--help"):
160             usage()
161             sys.exit()
162         if o in ("-o", "--output"):
163             options['output'] = a
164         if o == "--ost":
165             options['ost'] = 1
166         if o == "--merge":
167             options['merge'] = a
168         if o == "--format":
169             options['format'] = 1
170         if o  == "--reformat":
171             options['reformat'] = 1
172             
173     return options, args
174
175 def main():
176     options, args = cmdline(sys.argv[1:])
177     outFile = '-'
178
179     if options.has_key('merge'):
180         outFile = options['merge']
181         dom = xml.dom.minidom.parse(outFile)
182     else:
183         dom = new_Lustre()
184
185     if options.has_key('output'):
186         outFile = options['output']
187
188     if options.has_key('ost'):
189         add_OST(dom, options, args)
190     elif options.has_key('mtpt'):
191         print "--mtpt not implemented"
192     elif options.has_key('lov'):
193         print "--lov not implemented"
194     else:
195         print "Missing command"
196         usage()
197         sys.exit(1)
198         
199
200     if outFile == '-':
201         print dom.toxml()
202     else:
203         dom.writexml(open(outFile,"w"))
204     
205 if __name__ == "__main__":
206     main()
207