Whamcloud - gitweb
- lmc refactored for impending enhancments
[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 from xml.dom.ext import PrettyPrint
27
28
29 def usage():
30     print """usage: lmc [--ost | --mtpt | --lov] cmd args
31 Commands:
32 --ost "device" "host" [size]
33    Creates an OBD/OST/OSC configuration triplet for a new device.
34    When used on "host", the device will be initialized and the OST
35    will be enabled. On client nodes, the OSC will be avaiable.
36
37 --osc "device" "host" [lov_name]
38    Create an osc, and optionally add it to an lov.
39
40 --mtpt "mds" "ost/lov-name" /mnt/point
41    Creates a client mount point.
42
43 --lov lov_name mdc_name stripe_sz stripe_off pattern
44    Produces a logical volum striped over the OSTs found in all-ost.xml.
45
46 Options:
47 --merge="xml file"  Add the new objects to an existing file
48 --format            Format the partitions if unformated
49 --reformat          Reformat partitions (this should be an lconf arg,
50                     I think)
51 (SCRIPT STILL UNDER DEVELOPMENT, MOST COMMANDS/OPTIONS UNIMPLEMENTED)
52 """  
53
54 #
55 # manage names and uuids
56 # need to initialize this by walking tree to ensure
57 # no duplicate names or uuids are created.
58 # this are just place holders for now.
59 # consider changing this to be like OBD-dev-host
60 name_ctr = 1
61 def new_name(base):
62     global name_ctr
63     name = "%s_%d" % (base, name_ctr)
64     name_ctr += 1
65     return name
66
67 def get_uuid(name):
68     return "%s_UUID" % (name)
69
70 def new_lustre(dom):
71     """Create a new empty lustre document"""
72     str = """<lustre> </lustre>"""
73     return dom.parseString(str)
74
75
76 class GenConfig:
77     doc = None
78     dom = None
79     def __init__(self, doc):
80         self.doc = doc
81
82     def ref(self, type, uuid):
83         """ generate <[type]_ref uuidref="[uuid]"/> """
84         tag = "%s_ref" % (type)
85         ref = self.doc.createElement(tag)
86         ref.setAttribute("uuidref", uuid)
87         return ref
88     
89     def newService(self, tag, name, uuid):
90         """ create a new  service elmement, which requires name and uuid attributes """
91         new = self.doc.createElement(tag)
92         new.setAttribute("name", name);
93         new.setAttribute("uuid", uuid);
94         return new
95     
96     def addText(self, node, str):
97         txt = self.doc.createTextNode(str)
98         node.appendChild(txt)
99
100     def addElement(self, node, tag, str=None):
101         """ create a new element and add it as a child to node. If str is passed,
102             a text node is created for the new element"""
103         new = self.doc.createElement(tag)
104         if str:
105             self.addText(new, str)
106         node.appendChild(new)
107         return new
108
109     def network(self, name, uuid, net, hostname, port=0):
110         """create <network> node"""
111         network = self.newService("network", name, uuid)
112         network.setAttribute("type", net);
113         self.addElement(network, "server", hostname)
114         if port:
115             self.addElement(network, "port", "%d" %(port))
116         return network
117
118     def node(self, name, uuid):
119         """ create a host """
120         node = self.newService("node", name, uuid)
121         return node
122
123     def obd(self, name, uuid, fs, devname, format, dev_size=0, dev_file=""):
124         obd = self.newService("obd", name, uuid)
125         obd.setAttribute('type', 'obdfilter')
126         self.addElement(obd, "fstype", fs)
127         dev = self.addElement(obd, "device", devname)
128         if (dev_size):
129             dev.setAttribute("size", "%s" % (dev_size))
130         self.addElement(obd, "autoformat", format)
131         return obd
132
133     def osc(self, name, uuid, obd_uuid, net_uuid):
134         osc = self.newService("osc", name, uuid)
135         osc.appendChild(self.ref("network", net_uuid))
136         osc.appendChild(self.ref("obd", obd_uuid))
137         return osc
138
139     def ost(self, name, uuid, obd_uuid, net_uuid):
140         ost = self.newService("ost", name, uuid)
141         ost.appendChild(self.ref("network", net_uuid))
142         ost.appendChild(self.ref("obd", obd_uuid))
143         return ost
144
145 #
146 # Create a new obd, osc, and ost. Add them to the DOM.
147 #
148 def add_OST(doc, options, args):
149     # XXX need some error checking
150     gen = GenConfig(doc)
151     devname = args[0]
152     host = args[1]
153     if len(args) > 2:
154         size = args[2]
155     else:
156         size = 0
157
158     lustre = doc.getElementsByTagName("lustre")[0]
159
160     obdname = new_name("obd")
161     oscname = new_name("osc")
162     ostname = new_name("ost")
163     node_uuid = get_uuid(host)
164     net_uuid = get_uuid("net")
165     obd_uuid = get_uuid(obdname)
166     ost_uuid = get_uuid(ostname)
167     osc_uuid = get_uuid(oscname)
168
169     node = gen.node(host, node_uuid)
170     node.appendChild(gen.network(host, net_uuid, "tcp", host, port=2436))
171     obd = gen.obd(obdname, obd_uuid,  "extN", devname, "no", size)
172     ost = gen.ost(ostname, ost_uuid, obd_uuid, net_uuid)
173     osc = gen.osc(oscname, osc_uuid, obd_uuid, net_uuid)
174     
175     lustre.appendChild(node)
176     lustre.appendChild(obd)
177     lustre.appendChild(osc)
178     lustre.appendChild(ost)
179                    
180
181 #
182 # Command line processing
183 #
184
185 def parse_cmdline(argv):
186     short_opts = "ho:"
187     long_opts = ["ost", "mtpt", "lov",
188                  "merge=", "format", "reformat", "output=",
189                  "help"]
190     opts = []
191     args = []
192     options = {}
193     try:
194         opts, args = getopt.getopt(argv, short_opts, long_opts)
195     except getopt.GetoptError:
196         print "invalid opt"
197         usage()
198         sys.exit(2)
199
200     for o, a in opts:
201         if o in ("-h", "--help"):
202             usage()
203             sys.exit()
204         if o in ("-o", "--output"):
205             options['output'] = a
206         if o == "--ost":
207             options['ost'] = 1
208         if o == "--merge":
209             options['merge'] = a
210         if o == "--format":
211             options['format'] = 1
212         if o  == "--reformat":
213             options['reformat'] = 1
214             
215     return options, args
216
217 def main():
218     options, args = parse_cmdline(sys.argv[1:])
219     outFile = '-'
220
221     if options.has_key('merge'):
222         outFile = options['merge']
223         doc = xml.dom.minidom.parse(outFile)
224     else:
225         doc = new_lustre(xml.dom.minidom)
226
227     if options.has_key('output'):
228         outFile = options['output']
229
230     if options.has_key('ost'):
231         add_OST(doc, options, args)
232     elif options.has_key('mtpt'):
233         print "--mtpt not implemented"
234     elif options.has_key('lov'):
235         print "--lov not implemented"
236     else:
237         print "Missing command"
238         usage()
239         sys.exit(1)
240
241     if outFile == '-':
242         PrettyPrint(doc)
243     else:
244         PrettyPrint(doc, open(outFile,"w"))
245 if __name__ == "__main__":
246     main()
247
248