Whamcloud - gitweb
- add network element
[fs/lustre-release.git] / lustre / utils / lmc
1 #!/usr/bin/env python
2 #
3 #  Copyright (C) 2002 Cluster File Systems, Inc.
4 #   Author: Robert Read <rread@clusterfs.com>
5
6 #   This file is part of Lustre, http://www.lustre.org.
7 #
8 #   Lustre is free software; you can redistribute it and/or
9 #   modify it under the terms of version 2 of the GNU General Public
10 #   License as published by the Free Software Foundation.
11 #
12 #   Lustre is distributed in the hope that it will be useful,
13 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #   GNU General Public License for more details.
16 #
17 #   You should have received a copy of the GNU General Public License
18 #   along with Lustre; if not, write to the Free Software
19 #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #
21
22 # lmc - lustre configurtion data  manager
23 #
24 import sys, getopt
25 import xml.dom.minidom
26
27
28 def usage():
29     print """usage: lmc [--ost | --mtpt | --lov] cmd args
30 Commands:
31 --ost "device" "host" [size]
32    Creates an OBD/OST/OSC configuration triplet for a new device.
33    When used on "host", the device will be initialized and the OST
34    will be enabled. On client nodes, the OSC will be avaiable.
35
36 --mtpt "mds" "ost/lov-name" /mnt/point
37    Creates a client mount point.
38
39 --lov "mds" "lov name" < "all-ost.xml"
40    Produces a logical volum striped over the OSTs found in all-ost.xml.
41    (Not sure how all-ost.xml is created, exactly.)
42
43 Options:
44 --merge="xml file"  Add the new objects to an existing file
45 --format            Format the partitions if unformated
46 --reformat          Reformat partitions (this should be an lconf arg,
47                     I think)
48 (SCRIPT STILL UNDER DEVELOPMENT, MOST COMMANDS/OPTIONS UNIMPLEMENTED)
49 """  
50
51 #
52 # manage names and uuids
53 # need to initialize this by walking tree to ensure
54 # no duplicate names or uuids are created.
55 # this are just place holders for now.
56 # consider changing this to be like OBD-dev-host
57 name_ctr = 1
58 def new_name(base):
59     global name_ctr
60     name = "%s_%d" % (base, name_ctr)
61     name_ctr += 1
62     return name
63
64 def get_uuid(name):
65     return "%s_UUID" % (name)
66
67 # simple pretty print XML
68 def newline(dom, node, ind = ""):
69     node.appendChild(dom.createTextNode("\n" + ind))
70 def indent(dom, node, ind = "   "):
71     node.appendChild(dom.createTextNode(ind))
72
73 #
74 # Create a new empty lustre document 
75 def new_Lustre():
76     str = """<lustre>
77 </lustre>"""
78     dom = xml.dom.minidom.parseString(str)
79     return dom
80
81 def new_network(dom, net, hostname, port):
82     name = new_name('net')
83     uuid = get_uuid(name)
84     str = """
85    <network name = "%s" uuid = "%s" type="%s" >
86       <server>%s</server>
87       <port>%d</port>
88    </network> """ % (name, uuid, net, hostname, port)
89     node = xml.dom.minidom.parseString(str)
90     return node.getElementsByTagName("network")[0]
91
92 #
93 # Create new object the fast and easy way
94 # (note: dom is not needed for this way)
95 def new_node(dom, net, hostname, port):
96     uuid = get_uuid(hostname)
97     str ="""
98 <node name="%s" uuid="%s">
99 </node> """ % (hostname, uuid)
100     node = xml.dom.minidom.parseString(str)
101     node = node.getElementsByTagName("node")[0]
102     indent(dom, node)
103     node.appendChild(new_network(dom, net, hostname, port))
104     newline(dom, node)
105     return node
106 #
107 # Create a new object the "correct" way by using the DOM api.
108 #
109 def new_OBD(dom, name, fs, devname, format, dev_size=0, dev_file=""):
110     uuid = get_uuid(name)
111     
112     obd = dom.createElement("obd")
113     obd.setAttribute("name", name)
114     obd.setAttribute("uuid", uuid)
115     obd.setAttribute('type', 'obdfilter')
116     obd.appendChild(dom.createTextNode("\n  "))
117
118     fstype = dom.createElement("fstype")
119     txt= dom.createTextNode(fs)
120     fstype.appendChild(txt)
121     obd.appendChild(fstype)
122     
123     dev = dom.createElement("device")
124     if (dev_size):
125         dev.setAttribute("size", "%s" % (dev_size))
126     txt = dom.createTextNode(devname)
127     dev.appendChild(txt)
128     newline(dom, obd, "  ")
129     obd.appendChild(dev)
130     newline(dom, obd, "   ")
131     fmt = dom.createElement("autoformat")
132     txt = dom.createTextNode(format)
133     fmt.appendChild(txt)
134     obd.appendChild(fmt)
135     newline(dom, obd)
136
137     return obd
138
139 #
140 # Create new object the fast and easy way
141 # (note: dom is not needed for this way)
142 def new_OSC(dom, osc, obd):
143     osc_uuid = get_uuid(osc)
144     obd_uuid = get_uuid(obd)
145
146     osc_str ="""
147 <osc name="%s" uuid="%s">
148    <service_id num="1" name="%s" uuid="%s"/>
149 </osc> """ % (osc, osc_uuid, obd, obd_uuid)
150     osc = xml.dom.minidom.parseString(osc_str)
151     return osc.getElementsByTagName("osc")[0]
152
153 #
154 # Create new object the fast and easy way
155 #
156 def new_OST(dom, ost, host, port, obd):
157     ost_uuid = get_uuid(ost)
158     obd_uuid = get_uuid(obd)
159
160     str ="""
161 <ost name="%s" uuid="%s">
162    <network type="tcp">
163       <server>%s</server>
164       <port>%d</port>
165    </network>
166    <server_id num="1" name="%s" uuid="%s"/>
167 </ost> """ % (ost, ost_uuid, host, port, obd, obd_uuid)
168     node = xml.dom.minidom.parseString(str)
169     return node.getElementsByTagName("ost")[0]
170
171 #
172 # Create a new obd, osc, and ost. Add them to the DOM.
173 #
174 def add_OST(dom, options, args):
175     # XXX need some error checking
176     devname = args[0]
177     host = args[1]
178     size = args[2]
179
180     obdname = new_name("obd")
181     oscname = new_name("osc")
182     ostname = new_name("ost")
183     
184     node = new_node(dom, "tcp", host, 2436)
185     obd = new_OBD(dom, obdname, "extN", devname, "no", size)
186     osc = new_OSC(dom, oscname, obdname)
187     ost = new_OST(dom, ostname, host, 2020, obdname)
188     
189     lustre = dom.getElementsByTagName("lustre")[0]
190     lustre.appendChild(node)
191     newline(dom, lustre)
192     lustre.appendChild(obd)
193     newline(dom, lustre)    
194     lustre.appendChild(osc)
195     newline(dom, lustre)    
196     lustre.appendChild(ost)
197     newline(dom, lustre)    
198
199 #
200 # Command line processing
201 #
202
203 def parse_cmdline(argv):
204     short_opts = "ho:"
205     long_opts = ["ost", "mtpt", "lov",
206                  "merge=", "format", "reformat", "output=",
207                  "help"]
208     opts = []
209     args = []
210     options = {}
211     try:
212         opts, args = getopt.getopt(argv, short_opts, long_opts)
213     except getopt.GetoptError:
214         print "invalid opt"
215         usage()
216         sys.exit(2)
217
218     for o, a in opts:
219         if o in ("-h", "--help"):
220             usage()
221             sys.exit()
222         if o in ("-o", "--output"):
223             options['output'] = a
224         if o == "--ost":
225             options['ost'] = 1
226         if o == "--merge":
227             options['merge'] = a
228         if o == "--format":
229             options['format'] = 1
230         if o  == "--reformat":
231             options['reformat'] = 1
232             
233     return options, args
234
235 def main():
236     options, args = parse_cmdline(sys.argv[1:])
237     outFile = '-'
238
239     if options.has_key('merge'):
240         outFile = options['merge']
241         dom = xml.dom.minidom.parse(outFile)
242     else:
243         dom = new_Lustre()
244
245     if options.has_key('output'):
246         outFile = options['output']
247
248     if options.has_key('ost'):
249         add_OST(dom, options, args)
250     elif options.has_key('mtpt'):
251         print "--mtpt not implemented"
252     elif options.has_key('lov'):
253         print "--lov not implemented"
254     else:
255         print "Missing command"
256         usage()
257         sys.exit(1)
258         
259
260     if outFile == '-':
261         print dom.toxml()
262     else:
263         dom.writexml(open(outFile,"w"))
264     
265 if __name__ == "__main__":
266     main()
267