root / scripts / gnt-instance @ 79f7be7b
History | View | Annotate | Download (18.8 kB)
1 | a8083063 | Iustin Pop | #!/usr/bin/python |
---|---|---|---|
2 | a8083063 | Iustin Pop | # |
3 | a8083063 | Iustin Pop | |
4 | a8083063 | Iustin Pop | # Copyright (C) 2006, 2007 Google Inc. |
5 | a8083063 | Iustin Pop | # |
6 | a8083063 | Iustin Pop | # This program is free software; you can redistribute it and/or modify |
7 | a8083063 | Iustin Pop | # it under the terms of the GNU General Public License as published by |
8 | a8083063 | Iustin Pop | # the Free Software Foundation; either version 2 of the License, or |
9 | a8083063 | Iustin Pop | # (at your option) any later version. |
10 | a8083063 | Iustin Pop | # |
11 | a8083063 | Iustin Pop | # This program is distributed in the hope that it will be useful, but |
12 | a8083063 | Iustin Pop | # WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | a8083063 | Iustin Pop | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | a8083063 | Iustin Pop | # General Public License for more details. |
15 | a8083063 | Iustin Pop | # |
16 | a8083063 | Iustin Pop | # You should have received a copy of the GNU General Public License |
17 | a8083063 | Iustin Pop | # along with this program; if not, write to the Free Software |
18 | a8083063 | Iustin Pop | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
19 | a8083063 | Iustin Pop | # 02110-1301, USA. |
20 | a8083063 | Iustin Pop | |
21 | a8083063 | Iustin Pop | |
22 | a8083063 | Iustin Pop | import sys |
23 | a8083063 | Iustin Pop | import os |
24 | a8083063 | Iustin Pop | from optparse import make_option |
25 | a8083063 | Iustin Pop | import textwrap |
26 | a8083063 | Iustin Pop | from cStringIO import StringIO |
27 | a8083063 | Iustin Pop | |
28 | a8083063 | Iustin Pop | from ganeti.cli import * |
29 | a8083063 | Iustin Pop | from ganeti import opcodes |
30 | a8083063 | Iustin Pop | from ganeti import logger |
31 | a8083063 | Iustin Pop | from ganeti import constants |
32 | a8083063 | Iustin Pop | from ganeti import utils |
33 | a8083063 | Iustin Pop | |
34 | a8083063 | Iustin Pop | |
35 | a8083063 | Iustin Pop | def ListInstances(opts, args): |
36 | a8083063 | Iustin Pop | """List nodes and their properties. |
37 | a8083063 | Iustin Pop | |
38 | a8083063 | Iustin Pop | """ |
39 | a8083063 | Iustin Pop | if opts.output is None: |
40 | a8083063 | Iustin Pop | selected_fields = ["name", "os", "pnode", "admin_state", |
41 | a8083063 | Iustin Pop | "oper_state", "oper_ram"] |
42 | a8083063 | Iustin Pop | else: |
43 | a8083063 | Iustin Pop | selected_fields = opts.output.split(",") |
44 | a8083063 | Iustin Pop | |
45 | a8083063 | Iustin Pop | op = opcodes.OpQueryInstances(output_fields=selected_fields) |
46 | a8083063 | Iustin Pop | output = SubmitOpCode(op) |
47 | a8083063 | Iustin Pop | |
48 | a8083063 | Iustin Pop | mlens = [0 for name in selected_fields] |
49 | a8083063 | Iustin Pop | |
50 | a8083063 | Iustin Pop | format_fields = [] |
51 | a8083063 | Iustin Pop | unitformat_fields = ("admin_ram", "oper_ram") |
52 | a8083063 | Iustin Pop | for field in selected_fields: |
53 | a8083063 | Iustin Pop | if field in ("admin_ram", "oper_ram"): |
54 | a8083063 | Iustin Pop | format_fields.append("%*s") |
55 | a8083063 | Iustin Pop | else: |
56 | a8083063 | Iustin Pop | format_fields.append("%-*s") |
57 | a8083063 | Iustin Pop | separator = opts.separator |
58 | a8083063 | Iustin Pop | if "%" in separator: |
59 | a8083063 | Iustin Pop | separator = separator.replace("%", "%%") |
60 | a8083063 | Iustin Pop | format = separator.join(format_fields) |
61 | a8083063 | Iustin Pop | |
62 | a8083063 | Iustin Pop | for row in output: |
63 | a8083063 | Iustin Pop | for idx, val in enumerate(row): |
64 | a8083063 | Iustin Pop | if opts.human_readable and selected_fields[idx] in unitformat_fields: |
65 | a8083063 | Iustin Pop | try: |
66 | a8083063 | Iustin Pop | val = int(val) |
67 | a8083063 | Iustin Pop | except ValueError: |
68 | a8083063 | Iustin Pop | pass |
69 | a8083063 | Iustin Pop | else: |
70 | a8083063 | Iustin Pop | val = row[idx] = utils.FormatUnit(val) |
71 | a8083063 | Iustin Pop | mlens[idx] = max(mlens[idx], len(val)) |
72 | a8083063 | Iustin Pop | |
73 | a8083063 | Iustin Pop | if not opts.no_headers: |
74 | a8083063 | Iustin Pop | header_list = {"name": "Instance", "os": "OS", "pnode": "Primary_node", |
75 | a8083063 | Iustin Pop | "snodes": "Secondary_Nodes", "admin_state": "Autostart", |
76 | a8083063 | Iustin Pop | "oper_state": "Status", "admin_ram": "Configured_memory", |
77 | a8083063 | Iustin Pop | "oper_ram": "Memory", "disk_template": "Disk_template", |
78 | a8083063 | Iustin Pop | "ip": "IP Address", "mac": "MAC Address", |
79 | a8083063 | Iustin Pop | "bridge": "Bridge"} |
80 | a8083063 | Iustin Pop | args = [] |
81 | a8083063 | Iustin Pop | for idx, name in enumerate(selected_fields): |
82 | a8083063 | Iustin Pop | hdr = header_list[name] |
83 | a8083063 | Iustin Pop | mlens[idx] = max(mlens[idx], len(hdr)) |
84 | a8083063 | Iustin Pop | args.append(mlens[idx]) |
85 | a8083063 | Iustin Pop | args.append(hdr) |
86 | a8083063 | Iustin Pop | logger.ToStdout(format % tuple(args)) |
87 | a8083063 | Iustin Pop | |
88 | a8083063 | Iustin Pop | for line in output: |
89 | a8083063 | Iustin Pop | args = [] |
90 | a8083063 | Iustin Pop | for idx in range(len(selected_fields)): |
91 | a8083063 | Iustin Pop | args.append(mlens[idx]) |
92 | a8083063 | Iustin Pop | args.append(line[idx]) |
93 | a8083063 | Iustin Pop | logger.ToStdout(format % tuple(args)) |
94 | a8083063 | Iustin Pop | |
95 | a8083063 | Iustin Pop | return 0 |
96 | a8083063 | Iustin Pop | |
97 | a8083063 | Iustin Pop | |
98 | a8083063 | Iustin Pop | def AddInstance(opts, args): |
99 | a8083063 | Iustin Pop | """Add an instance to the cluster. |
100 | a8083063 | Iustin Pop | |
101 | a8083063 | Iustin Pop | Args: |
102 | a8083063 | Iustin Pop | opts - class with options as members |
103 | a8083063 | Iustin Pop | args - list with a single element, the instance name |
104 | a8083063 | Iustin Pop | Opts used: |
105 | a8083063 | Iustin Pop | mem - amount of memory to allocate to instance (MiB) |
106 | a8083063 | Iustin Pop | size - amount of disk space to allocate to instance (MiB) |
107 | a8083063 | Iustin Pop | os - which OS to run on instance |
108 | a8083063 | Iustin Pop | node - node to run new instance on |
109 | a8083063 | Iustin Pop | |
110 | a8083063 | Iustin Pop | """ |
111 | a8083063 | Iustin Pop | |
112 | a8083063 | Iustin Pop | instance = args[0] |
113 | a8083063 | Iustin Pop | |
114 | a8083063 | Iustin Pop | op = opcodes.OpCreateInstance(instance_name=instance, mem_size=opts.mem, |
115 | a8083063 | Iustin Pop | disk_size=opts.size, swap_size=opts.swap, |
116 | a8083063 | Iustin Pop | disk_template=opts.disk_template, |
117 | a8083063 | Iustin Pop | mode=constants.INSTANCE_CREATE, |
118 | a8083063 | Iustin Pop | os_type=opts.os, pnode=opts.node, |
119 | a8083063 | Iustin Pop | snode=opts.snode, vcpus=opts.vcpus, |
120 | a8083063 | Iustin Pop | ip=opts.ip, bridge=opts.bridge, start=True, |
121 | a8083063 | Iustin Pop | wait_for_sync=opts.wait_for_sync) |
122 | a8083063 | Iustin Pop | SubmitOpCode(op) |
123 | a8083063 | Iustin Pop | return 0 |
124 | a8083063 | Iustin Pop | |
125 | a8083063 | Iustin Pop | |
126 | a8083063 | Iustin Pop | def RemoveInstance(opts, args): |
127 | a8083063 | Iustin Pop | """Remove an instance. |
128 | a8083063 | Iustin Pop | |
129 | a8083063 | Iustin Pop | Args: |
130 | a8083063 | Iustin Pop | opts - class with options as members |
131 | a8083063 | Iustin Pop | args - list containing a single element, the instance name |
132 | a8083063 | Iustin Pop | |
133 | a8083063 | Iustin Pop | """ |
134 | a8083063 | Iustin Pop | instance_name = args[0] |
135 | a8083063 | Iustin Pop | force = opts.force |
136 | a8083063 | Iustin Pop | |
137 | a8083063 | Iustin Pop | if not force: |
138 | a8083063 | Iustin Pop | usertext = ("This will remove the volumes of the instance %s" |
139 | a8083063 | Iustin Pop | " (including mirrors), thus removing all the data" |
140 | a8083063 | Iustin Pop | " of the instance. Continue?") % instance_name |
141 | a8083063 | Iustin Pop | if not opts._ask_user(usertext): |
142 | a8083063 | Iustin Pop | return 1 |
143 | a8083063 | Iustin Pop | |
144 | a8083063 | Iustin Pop | op = opcodes.OpRemoveInstance(instance_name=instance_name) |
145 | a8083063 | Iustin Pop | SubmitOpCode(op) |
146 | a8083063 | Iustin Pop | return 0 |
147 | a8083063 | Iustin Pop | |
148 | a8083063 | Iustin Pop | |
149 | a8083063 | Iustin Pop | def ActivateDisks(opts, args): |
150 | a8083063 | Iustin Pop | """Activate an instance's disks. |
151 | a8083063 | Iustin Pop | |
152 | a8083063 | Iustin Pop | This serves two purposes: |
153 | a8083063 | Iustin Pop | - it allows one (as long as the instance is not running) to mount |
154 | a8083063 | Iustin Pop | the disks and modify them from the node |
155 | a8083063 | Iustin Pop | - it repairs inactive secondary drbds |
156 | a8083063 | Iustin Pop | |
157 | a8083063 | Iustin Pop | """ |
158 | a8083063 | Iustin Pop | instance_name = args[0] |
159 | a8083063 | Iustin Pop | op = opcodes.OpActivateInstanceDisks(instance_name=instance_name) |
160 | a8083063 | Iustin Pop | disks_info = SubmitOpCode(op) |
161 | a8083063 | Iustin Pop | for host, iname, nname in disks_info: |
162 | a8083063 | Iustin Pop | print "%s:%s:%s" % (host, iname, nname) |
163 | a8083063 | Iustin Pop | return 0 |
164 | a8083063 | Iustin Pop | |
165 | a8083063 | Iustin Pop | |
166 | a8083063 | Iustin Pop | def DeactivateDisks(opts, args): |
167 | a8083063 | Iustin Pop | """Command-line interface for _ShutdownInstanceBlockDevices. |
168 | a8083063 | Iustin Pop | |
169 | a8083063 | Iustin Pop | This function takes the instance name, looks for its primary node |
170 | a8083063 | Iustin Pop | and the tries to shutdown its block devices on that node. |
171 | a8083063 | Iustin Pop | |
172 | a8083063 | Iustin Pop | """ |
173 | a8083063 | Iustin Pop | instance_name = args[0] |
174 | a8083063 | Iustin Pop | op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name) |
175 | a8083063 | Iustin Pop | SubmitOpCode(op) |
176 | a8083063 | Iustin Pop | return 0 |
177 | a8083063 | Iustin Pop | |
178 | a8083063 | Iustin Pop | |
179 | a8083063 | Iustin Pop | def StartupInstance(opts, args): |
180 | a8083063 | Iustin Pop | """Shutdown an instance. |
181 | a8083063 | Iustin Pop | |
182 | a8083063 | Iustin Pop | Args: |
183 | a8083063 | Iustin Pop | opts - class with options as members |
184 | a8083063 | Iustin Pop | args - list containing a single element, the instance name |
185 | a8083063 | Iustin Pop | |
186 | a8083063 | Iustin Pop | """ |
187 | a8083063 | Iustin Pop | instance_name = args[0] |
188 | a8083063 | Iustin Pop | op = opcodes.OpStartupInstance(instance_name=instance_name, force=opts.force, |
189 | a8083063 | Iustin Pop | extra_args=opts.extra_args) |
190 | a8083063 | Iustin Pop | SubmitOpCode(op) |
191 | a8083063 | Iustin Pop | return 0 |
192 | a8083063 | Iustin Pop | |
193 | a8083063 | Iustin Pop | |
194 | a8083063 | Iustin Pop | def ShutdownInstance(opts, args): |
195 | a8083063 | Iustin Pop | """Shutdown an instance. |
196 | a8083063 | Iustin Pop | |
197 | a8083063 | Iustin Pop | Args: |
198 | a8083063 | Iustin Pop | opts - class with options as members |
199 | a8083063 | Iustin Pop | args - list containing a single element, the instance name |
200 | a8083063 | Iustin Pop | |
201 | a8083063 | Iustin Pop | """ |
202 | a8083063 | Iustin Pop | instance_name = args[0] |
203 | a8083063 | Iustin Pop | op = opcodes.OpShutdownInstance(instance_name=instance_name) |
204 | a8083063 | Iustin Pop | SubmitOpCode(op) |
205 | a8083063 | Iustin Pop | return 0 |
206 | a8083063 | Iustin Pop | |
207 | a8083063 | Iustin Pop | |
208 | a8083063 | Iustin Pop | def AddMDDRBDComponent(opts, args): |
209 | a8083063 | Iustin Pop | """Add a new component to a remote_raid1 disk. |
210 | a8083063 | Iustin Pop | |
211 | a8083063 | Iustin Pop | Args: |
212 | a8083063 | Iustin Pop | opts - class with options as members |
213 | a8083063 | Iustin Pop | args - list with a single element, the instance name |
214 | a8083063 | Iustin Pop | |
215 | a8083063 | Iustin Pop | """ |
216 | a8083063 | Iustin Pop | op = opcodes.OpAddMDDRBDComponent(instance_name=args[0], |
217 | a8083063 | Iustin Pop | disk_name=opts.disk, |
218 | a8083063 | Iustin Pop | remote_node=opts.node) |
219 | a8083063 | Iustin Pop | SubmitOpCode(op) |
220 | a8083063 | Iustin Pop | return 0 |
221 | a8083063 | Iustin Pop | |
222 | a8083063 | Iustin Pop | |
223 | a8083063 | Iustin Pop | def RemoveMDDRBDComponent(opts, args): |
224 | a8083063 | Iustin Pop | """Connect to the console of an instance |
225 | a8083063 | Iustin Pop | |
226 | a8083063 | Iustin Pop | Args: |
227 | a8083063 | Iustin Pop | opts - class with options as members |
228 | a8083063 | Iustin Pop | args - list with a single element, the instance name |
229 | a8083063 | Iustin Pop | |
230 | a8083063 | Iustin Pop | """ |
231 | a8083063 | Iustin Pop | op = opcodes.OpRemoveMDDRBDComponent(instance_name=args[0], |
232 | a8083063 | Iustin Pop | disk_name=opts.disk, |
233 | a8083063 | Iustin Pop | disk_id=opts.port) |
234 | a8083063 | Iustin Pop | SubmitOpCode(op) |
235 | a8083063 | Iustin Pop | return 0 |
236 | a8083063 | Iustin Pop | |
237 | a8083063 | Iustin Pop | |
238 | a8083063 | Iustin Pop | def ReplaceDisks(opts, args): |
239 | a8083063 | Iustin Pop | """Replace the disks of an instance |
240 | a8083063 | Iustin Pop | |
241 | a8083063 | Iustin Pop | Args: |
242 | a8083063 | Iustin Pop | opts - class with options as members |
243 | a8083063 | Iustin Pop | args - list with a single element, the instance name |
244 | a8083063 | Iustin Pop | |
245 | a8083063 | Iustin Pop | """ |
246 | a8083063 | Iustin Pop | instance_name = args[0] |
247 | a8083063 | Iustin Pop | new_secondary = opts.new_secondary |
248 | a8083063 | Iustin Pop | op = opcodes.OpReplaceDisks(instance_name=args[0], |
249 | a8083063 | Iustin Pop | remote_node=opts.new_secondary) |
250 | a8083063 | Iustin Pop | SubmitOpCode(op) |
251 | a8083063 | Iustin Pop | return 0 |
252 | a8083063 | Iustin Pop | |
253 | a8083063 | Iustin Pop | |
254 | a8083063 | Iustin Pop | def FailoverInstance(opts, args): |
255 | a8083063 | Iustin Pop | """Failover an instance. |
256 | a8083063 | Iustin Pop | |
257 | a8083063 | Iustin Pop | The failover is done by shutting it down on its present node and |
258 | a8083063 | Iustin Pop | starting it on the secondary. |
259 | a8083063 | Iustin Pop | |
260 | a8083063 | Iustin Pop | Args: |
261 | a8083063 | Iustin Pop | opts - class with options as members |
262 | a8083063 | Iustin Pop | args - list with a single element, the instance name |
263 | a8083063 | Iustin Pop | Opts used: |
264 | a8083063 | Iustin Pop | force - whether to failover without asking questions. |
265 | a8083063 | Iustin Pop | |
266 | a8083063 | Iustin Pop | """ |
267 | a8083063 | Iustin Pop | instance_name = args[0] |
268 | a8083063 | Iustin Pop | force = opts.force |
269 | a8083063 | Iustin Pop | |
270 | a8083063 | Iustin Pop | if not force: |
271 | a8083063 | Iustin Pop | usertext = ("Failover will happen to image %s." |
272 | a8083063 | Iustin Pop | " This requires a shutdown of the instance. Continue?" % |
273 | a8083063 | Iustin Pop | (instance_name,)) |
274 | a8083063 | Iustin Pop | usertext = textwrap.fill(usertext) |
275 | a8083063 | Iustin Pop | if not opts._ask_user(usertext): |
276 | a8083063 | Iustin Pop | return 1 |
277 | a8083063 | Iustin Pop | |
278 | a8083063 | Iustin Pop | op = opcodes.OpFailoverInstance(instance_name=instance_name, |
279 | a8083063 | Iustin Pop | ignore_consistency=opts.ignore_consistency) |
280 | a8083063 | Iustin Pop | SubmitOpCode(op) |
281 | a8083063 | Iustin Pop | return 0 |
282 | a8083063 | Iustin Pop | |
283 | a8083063 | Iustin Pop | |
284 | a8083063 | Iustin Pop | def ConnectToInstanceConsole(opts, args): |
285 | a8083063 | Iustin Pop | """Connect to the console of an instance. |
286 | a8083063 | Iustin Pop | |
287 | a8083063 | Iustin Pop | Args: |
288 | a8083063 | Iustin Pop | opts - class with options as members |
289 | a8083063 | Iustin Pop | args - list with a single element, the instance name |
290 | a8083063 | Iustin Pop | |
291 | a8083063 | Iustin Pop | """ |
292 | a8083063 | Iustin Pop | instance_name = args[0] |
293 | a8083063 | Iustin Pop | |
294 | a8083063 | Iustin Pop | op = opcodes.OpConnectConsole(instance_name=instance_name) |
295 | a8083063 | Iustin Pop | node, console_cmd = SubmitOpCode(op) |
296 | a8083063 | Iustin Pop | # drop lock and exec so other commands can run while we have console |
297 | a8083063 | Iustin Pop | utils.Unlock("cmd") |
298 | a8083063 | Iustin Pop | try: |
299 | a8083063 | Iustin Pop | os.execv("/usr/bin/ssh", ["ssh", "-qt", node, console_cmd]) |
300 | a8083063 | Iustin Pop | finally: |
301 | a8083063 | Iustin Pop | sys.stderr.write("Can't run console command %s on node %s" % |
302 | a8083063 | Iustin Pop | (console_cmd, node)) |
303 | a8083063 | Iustin Pop | os._exit(1) |
304 | a8083063 | Iustin Pop | |
305 | a8083063 | Iustin Pop | |
306 | a8083063 | Iustin Pop | def _FormatBlockDevInfo(buf, dev, indent_level): |
307 | a8083063 | Iustin Pop | """Show block device information. |
308 | a8083063 | Iustin Pop | |
309 | a8083063 | Iustin Pop | This is only used by ShowInstanceConfig(), but it's too big to be |
310 | a8083063 | Iustin Pop | left for an inline definition. |
311 | a8083063 | Iustin Pop | |
312 | a8083063 | Iustin Pop | """ |
313 | a8083063 | Iustin Pop | def helper(buf, dtype, status): |
314 | a8083063 | Iustin Pop | """Format one line for phsyical device status.""" |
315 | a8083063 | Iustin Pop | if not status: |
316 | a8083063 | Iustin Pop | buf.write("not active\n") |
317 | a8083063 | Iustin Pop | else: |
318 | a8083063 | Iustin Pop | (path, major, minor, syncp, estt, degr) = status |
319 | a8083063 | Iustin Pop | buf.write("%s (%d:%d)" % (path, major, minor)) |
320 | a8083063 | Iustin Pop | if dtype in ("md_raid1", "drbd"): |
321 | a8083063 | Iustin Pop | if syncp is not None: |
322 | a8083063 | Iustin Pop | sync_text = "*RECOVERING* %5.2f%%," % syncp |
323 | a8083063 | Iustin Pop | if estt: |
324 | a8083063 | Iustin Pop | sync_text += " ETA %ds" % estt |
325 | a8083063 | Iustin Pop | else: |
326 | a8083063 | Iustin Pop | sync_text += " ETA unknown" |
327 | a8083063 | Iustin Pop | else: |
328 | a8083063 | Iustin Pop | sync_text = "in sync" |
329 | a8083063 | Iustin Pop | if degr: |
330 | a8083063 | Iustin Pop | degr_text = "*DEGRADED*" |
331 | a8083063 | Iustin Pop | else: |
332 | a8083063 | Iustin Pop | degr_text = "ok" |
333 | a8083063 | Iustin Pop | buf.write(" %s, status %s" % (sync_text, degr_text)) |
334 | a8083063 | Iustin Pop | buf.write("\n") |
335 | a8083063 | Iustin Pop | |
336 | a8083063 | Iustin Pop | if dev["iv_name"] is not None: |
337 | a8083063 | Iustin Pop | data = " - %s, " % dev["iv_name"] |
338 | a8083063 | Iustin Pop | else: |
339 | a8083063 | Iustin Pop | data = " - " |
340 | a8083063 | Iustin Pop | data += "type: %s" % dev["dev_type"] |
341 | a8083063 | Iustin Pop | if dev["logical_id"] is not None: |
342 | a8083063 | Iustin Pop | data += ", logical_id: %s" % (dev["logical_id"],) |
343 | a8083063 | Iustin Pop | elif dev["physical_id"] is not None: |
344 | a8083063 | Iustin Pop | data += ", physical_id: %s" % (dev["physical_id"],) |
345 | a8083063 | Iustin Pop | buf.write("%*s%s\n" % (2*indent_level, "", data)) |
346 | a8083063 | Iustin Pop | buf.write("%*s primary: " % (2*indent_level, "")) |
347 | a8083063 | Iustin Pop | helper(buf, dev["dev_type"], dev["pstatus"]) |
348 | a8083063 | Iustin Pop | |
349 | a8083063 | Iustin Pop | if dev["sstatus"]: |
350 | a8083063 | Iustin Pop | buf.write("%*s secondary: " % (2*indent_level, "")) |
351 | a8083063 | Iustin Pop | helper(buf, dev["dev_type"], dev["sstatus"]) |
352 | a8083063 | Iustin Pop | |
353 | a8083063 | Iustin Pop | if dev["children"]: |
354 | a8083063 | Iustin Pop | for child in dev["children"]: |
355 | a8083063 | Iustin Pop | _FormatBlockDevInfo(buf, child, indent_level+1) |
356 | a8083063 | Iustin Pop | |
357 | a8083063 | Iustin Pop | |
358 | a8083063 | Iustin Pop | def ShowInstanceConfig(opts, args): |
359 | a8083063 | Iustin Pop | """Compute instance run-time status. |
360 | a8083063 | Iustin Pop | |
361 | a8083063 | Iustin Pop | """ |
362 | a8083063 | Iustin Pop | |
363 | a8083063 | Iustin Pop | retcode = 0 |
364 | a8083063 | Iustin Pop | op = opcodes.OpQueryInstanceData(instances=args) |
365 | a8083063 | Iustin Pop | result = SubmitOpCode(op) |
366 | a8083063 | Iustin Pop | |
367 | a8083063 | Iustin Pop | if not result: |
368 | a8083063 | Iustin Pop | logger.ToStdout("No instances.") |
369 | a8083063 | Iustin Pop | return 1 |
370 | a8083063 | Iustin Pop | |
371 | a8083063 | Iustin Pop | buf = StringIO() |
372 | a8083063 | Iustin Pop | retcode = 0 |
373 | a8083063 | Iustin Pop | for instance_name in result: |
374 | a8083063 | Iustin Pop | instance = result[instance_name] |
375 | a8083063 | Iustin Pop | buf.write("Instance name: %s\n" % instance["name"]) |
376 | a8083063 | Iustin Pop | buf.write("State: configured to be %s, actual state is %s\n" % |
377 | a8083063 | Iustin Pop | (instance["config_state"], instance["run_state"])) |
378 | a8083063 | Iustin Pop | buf.write(" Nodes:\n") |
379 | a8083063 | Iustin Pop | buf.write(" - primary: %s\n" % instance["pnode"]) |
380 | a8083063 | Iustin Pop | buf.write(" - secondaries: %s\n" % ", ".join(instance["snodes"])) |
381 | a8083063 | Iustin Pop | buf.write(" Operating system: %s\n" % instance["os"]) |
382 | a8083063 | Iustin Pop | buf.write(" Hardware:\n") |
383 | a8083063 | Iustin Pop | buf.write(" - memory: %dMiB\n" % instance["memory"]) |
384 | a8083063 | Iustin Pop | buf.write(" - NICs: %s\n" % |
385 | a8083063 | Iustin Pop | ", ".join(["{MAC: %s, IP: %s, bridge: %s}" % |
386 | a8083063 | Iustin Pop | (mac, ip, bridge) |
387 | a8083063 | Iustin Pop | for mac, ip, bridge in instance["nics"]])) |
388 | a8083063 | Iustin Pop | buf.write(" Block devices:\n") |
389 | a8083063 | Iustin Pop | |
390 | a8083063 | Iustin Pop | for device in instance["disks"]: |
391 | a8083063 | Iustin Pop | _FormatBlockDevInfo(buf, device, 1) |
392 | a8083063 | Iustin Pop | |
393 | a8083063 | Iustin Pop | logger.ToStdout(buf.getvalue().rstrip('\n')) |
394 | a8083063 | Iustin Pop | return retcode |
395 | a8083063 | Iustin Pop | |
396 | a8083063 | Iustin Pop | |
397 | a8083063 | Iustin Pop | def SetInstanceParms(opts, args): |
398 | a8083063 | Iustin Pop | """Modifies an instance. |
399 | a8083063 | Iustin Pop | |
400 | a8083063 | Iustin Pop | All parameters take effect only at the next restart of the instance. |
401 | a8083063 | Iustin Pop | |
402 | a8083063 | Iustin Pop | Args: |
403 | a8083063 | Iustin Pop | opts - class with options as members |
404 | a8083063 | Iustin Pop | args - list with a single element, the instance name |
405 | a8083063 | Iustin Pop | Opts used: |
406 | a8083063 | Iustin Pop | memory - the new memory size |
407 | a8083063 | Iustin Pop | vcpus - the new number of cpus |
408 | a8083063 | Iustin Pop | |
409 | a8083063 | Iustin Pop | """ |
410 | a8083063 | Iustin Pop | if not opts.mem and not opts.vcpus and not opts.ip and not opts.bridge: |
411 | a8083063 | Iustin Pop | logger.ToStdout("Please give at least one of the parameters.") |
412 | a8083063 | Iustin Pop | return 1 |
413 | a8083063 | Iustin Pop | |
414 | a8083063 | Iustin Pop | op = opcodes.OpSetInstanceParms(instance_name=args[0], mem=opts.mem, |
415 | a8083063 | Iustin Pop | vcpus=opts.vcpus, ip=opts.ip, |
416 | a8083063 | Iustin Pop | bridge=opts.bridge) |
417 | a8083063 | Iustin Pop | result = SubmitOpCode(op) |
418 | a8083063 | Iustin Pop | |
419 | a8083063 | Iustin Pop | if result: |
420 | a8083063 | Iustin Pop | logger.ToStdout("Modified instance %s" % args[0]) |
421 | a8083063 | Iustin Pop | for param, data in result: |
422 | a8083063 | Iustin Pop | logger.ToStdout(" - %-5s -> %s" % (param, data)) |
423 | a8083063 | Iustin Pop | logger.ToStdout("Please don't forget that these parameters take effect" |
424 | a8083063 | Iustin Pop | " only at the next start of the instance.") |
425 | a8083063 | Iustin Pop | return 0 |
426 | a8083063 | Iustin Pop | |
427 | a8083063 | Iustin Pop | |
428 | a8083063 | Iustin Pop | # options used in more than one cmd |
429 | a8083063 | Iustin Pop | node_opt = make_option("-n", "--node", dest="node", help="Target node", |
430 | a8083063 | Iustin Pop | metavar="<node>") |
431 | a8083063 | Iustin Pop | force_opt = make_option("-f", "--force", dest="force", action="store_true", |
432 | a8083063 | Iustin Pop | default=False, help="Force the operation") |
433 | a8083063 | Iustin Pop | |
434 | a8083063 | Iustin Pop | # this is defined separately due to readability only |
435 | a8083063 | Iustin Pop | add_opts = [ |
436 | a8083063 | Iustin Pop | DEBUG_OPT, |
437 | a8083063 | Iustin Pop | node_opt, |
438 | a8083063 | Iustin Pop | cli_option("-s", "--os-size", dest="size", help="Disk size", |
439 | a8083063 | Iustin Pop | default=20 * 1024, type="unit", metavar="<size>"), |
440 | a8083063 | Iustin Pop | cli_option("--swap-size", dest="swap", help="Swap size", |
441 | a8083063 | Iustin Pop | default=4 * 1024, type="unit", metavar="<size>"), |
442 | a8083063 | Iustin Pop | cli_option("-o", "--os-type", dest="os", help="What OS to run", |
443 | a8083063 | Iustin Pop | metavar="<os>"), |
444 | a8083063 | Iustin Pop | cli_option("-m", "--memory", dest="mem", help="Memory size", |
445 | a8083063 | Iustin Pop | default=128, type="unit", metavar="<mem>"), |
446 | a8083063 | Iustin Pop | make_option("-p", "--cpu", dest="vcpus", help="Number of virtual CPUs", |
447 | a8083063 | Iustin Pop | default=1, type="int", metavar="<PROC>"), |
448 | a8083063 | Iustin Pop | make_option("-t", "--disk-template", dest="disk_template", |
449 | a8083063 | Iustin Pop | help="Custom disk setup (diskless, plain, local_raid1 or" |
450 | a8083063 | Iustin Pop | " remote_raid1)", default=None, metavar="TEMPL"), |
451 | a8083063 | Iustin Pop | make_option("-i", "--ip", dest="ip", |
452 | a8083063 | Iustin Pop | help="IP address ('none' [default], 'auto', or specify address)", |
453 | a8083063 | Iustin Pop | default='none', type="string", metavar="<ADDRESS>"), |
454 | a8083063 | Iustin Pop | make_option("--no-wait-for-sync", dest="wait_for_sync", default=True, |
455 | a8083063 | Iustin Pop | action="store_false", help="Don't wait for sync (DANGEROUS!)"), |
456 | a8083063 | Iustin Pop | make_option("--secondary-node", dest="snode", |
457 | a8083063 | Iustin Pop | help="Secondary node for remote_raid1 disk layout", |
458 | a8083063 | Iustin Pop | metavar="<node>"), |
459 | a8083063 | Iustin Pop | make_option("-b", "--bridge", dest="bridge", |
460 | a8083063 | Iustin Pop | help="Bridge to connect this instance to", |
461 | a8083063 | Iustin Pop | default=None, metavar="<bridge>") |
462 | a8083063 | Iustin Pop | ] |
463 | a8083063 | Iustin Pop | |
464 | a8083063 | Iustin Pop | |
465 | a8083063 | Iustin Pop | commands = { |
466 | a8083063 | Iustin Pop | 'add': (AddInstance, ARGS_ONE, add_opts, |
467 | a8083063 | Iustin Pop | "[opts...] <name>", |
468 | a8083063 | Iustin Pop | "Creates and adds a new instance to the cluster"), |
469 | a8083063 | Iustin Pop | 'add-mirror': (AddMDDRBDComponent, ARGS_ONE, |
470 | a8083063 | Iustin Pop | [DEBUG_OPT, node_opt, |
471 | a8083063 | Iustin Pop | make_option("-b", "--disk", dest="disk", metavar="sdX", |
472 | a8083063 | Iustin Pop | help=("The name of the instance disk for which to" |
473 | a8083063 | Iustin Pop | " add the mirror"))], |
474 | a8083063 | Iustin Pop | "-n node -b disk <instance>", |
475 | a8083063 | Iustin Pop | "Creates a new mirror for the instance"), |
476 | a8083063 | Iustin Pop | 'console': (ConnectToInstanceConsole, ARGS_ONE, [DEBUG_OPT], |
477 | a8083063 | Iustin Pop | "<instance>", |
478 | a8083063 | Iustin Pop | "Opens a console on the specified instance"), |
479 | a8083063 | Iustin Pop | 'failover': (FailoverInstance, ARGS_ONE, |
480 | a8083063 | Iustin Pop | [DEBUG_OPT, force_opt, |
481 | a8083063 | Iustin Pop | make_option("--ignore-consistency", dest="ignore_consistency", |
482 | a8083063 | Iustin Pop | action="store_true", default=False, |
483 | a8083063 | Iustin Pop | help="Ignore the consistency of the disks on" |
484 | a8083063 | Iustin Pop | " the secondary"), |
485 | a8083063 | Iustin Pop | ], |
486 | a8083063 | Iustin Pop | "[-f] <instance>", |
487 | a8083063 | Iustin Pop | "Stops the instance and starts it on the backup node, using" |
488 | a8083063 | Iustin Pop | " the remote mirror (only for instances of type remote_raid1)"), |
489 | a8083063 | Iustin Pop | 'info': (ShowInstanceConfig, ARGS_ANY, [DEBUG_OPT], "[<instance>...]", |
490 | a8083063 | Iustin Pop | "Show information on the specified instance"), |
491 | a8083063 | Iustin Pop | 'list': (ListInstances, ARGS_NONE, |
492 | a8083063 | Iustin Pop | [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, |
493 | a8083063 | Iustin Pop | make_option("-o", "--output", dest="output", action="store", |
494 | a8083063 | Iustin Pop | type="string", help="Select output fields", |
495 | a8083063 | Iustin Pop | metavar="FIELDS") |
496 | a8083063 | Iustin Pop | ], |
497 | a8083063 | Iustin Pop | "", "Lists the instances and their status"), |
498 | a8083063 | Iustin Pop | 'remove': (RemoveInstance, ARGS_ONE, [DEBUG_OPT, force_opt], |
499 | a8083063 | Iustin Pop | "[-f] <instance>", "Shuts down the instance and removes it"), |
500 | a8083063 | Iustin Pop | 'remove-mirror': (RemoveMDDRBDComponent, ARGS_ONE, |
501 | a8083063 | Iustin Pop | [DEBUG_OPT, node_opt, |
502 | a8083063 | Iustin Pop | make_option("-b", "--disk", dest="disk", metavar="sdX", |
503 | a8083063 | Iustin Pop | help=("The name of the instance disk" |
504 | a8083063 | Iustin Pop | " for which to add the mirror")), |
505 | a8083063 | Iustin Pop | make_option("-p", "--port", dest="port", metavar="PORT", |
506 | a8083063 | Iustin Pop | help=("The port of the drbd device" |
507 | a8083063 | Iustin Pop | " which to remove from the mirror"), |
508 | a8083063 | Iustin Pop | type="int"), |
509 | a8083063 | Iustin Pop | ], |
510 | a8083063 | Iustin Pop | "-b disk -p port <instance>", |
511 | a8083063 | Iustin Pop | "Removes a mirror from the instance"), |
512 | a8083063 | Iustin Pop | 'replace-disks': (ReplaceDisks, ARGS_ONE, |
513 | a8083063 | Iustin Pop | [DEBUG_OPT, |
514 | a8083063 | Iustin Pop | make_option("-n", "--new-secondary", dest="new_secondary", |
515 | a8083063 | Iustin Pop | metavar="NODE", |
516 | a8083063 | Iustin Pop | help=("New secondary node (if you want to" |
517 | a8083063 | Iustin Pop | " change the secondary)"))], |
518 | a8083063 | Iustin Pop | "[-n NODE] <instance>", |
519 | a8083063 | Iustin Pop | "Replaces all disks for the instance"), |
520 | a8083063 | Iustin Pop | |
521 | a8083063 | Iustin Pop | 'modify': (SetInstanceParms, ARGS_ONE, |
522 | a8083063 | Iustin Pop | [DEBUG_OPT, force_opt, |
523 | a8083063 | Iustin Pop | cli_option("-m", "--memory", dest="mem", |
524 | a8083063 | Iustin Pop | help="Memory size", |
525 | a8083063 | Iustin Pop | default=None, type="unit", metavar="<mem>"), |
526 | a8083063 | Iustin Pop | make_option("-p", "--cpu", dest="vcpus", |
527 | a8083063 | Iustin Pop | help="Number of virtual CPUs", |
528 | a8083063 | Iustin Pop | default=None, type="int", metavar="<PROC>"), |
529 | a8083063 | Iustin Pop | make_option("-i", "--ip", dest="ip", |
530 | a8083063 | Iustin Pop | help="IP address ('none' or numeric IP)", |
531 | a8083063 | Iustin Pop | default=None, type="string", metavar="<ADDRESS>"), |
532 | a8083063 | Iustin Pop | make_option("-b", "--bridge", dest="bridge", |
533 | a8083063 | Iustin Pop | help="Bridge to connect this instance to", |
534 | a8083063 | Iustin Pop | default=None, type="string", metavar="<bridge>") |
535 | a8083063 | Iustin Pop | ], |
536 | a8083063 | Iustin Pop | "<instance>", "Alters the parameters of an instance"), |
537 | a8083063 | Iustin Pop | 'shutdown': (ShutdownInstance, ARGS_ONE, [DEBUG_OPT], |
538 | a8083063 | Iustin Pop | "<instance>", "Stops an instance"), |
539 | a8083063 | Iustin Pop | 'startup': (StartupInstance, ARGS_ONE, |
540 | a8083063 | Iustin Pop | [DEBUG_OPT, force_opt, |
541 | a8083063 | Iustin Pop | make_option("-e", "--extra", dest="extra_args", |
542 | a8083063 | Iustin Pop | help="Extra arguments for the instance's kernel", |
543 | a8083063 | Iustin Pop | default=None, type="string", metavar="<PARAMS>"), |
544 | a8083063 | Iustin Pop | ], |
545 | a8083063 | Iustin Pop | "<instance>", "Starts an instance"), |
546 | a8083063 | Iustin Pop | 'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT], |
547 | a8083063 | Iustin Pop | "<instance>", |
548 | a8083063 | Iustin Pop | "Activate an instance's disks"), |
549 | a8083063 | Iustin Pop | 'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT], |
550 | a8083063 | Iustin Pop | "<instance>", |
551 | a8083063 | Iustin Pop | "Deactivate an instance's disks"), |
552 | a8083063 | Iustin Pop | } |
553 | a8083063 | Iustin Pop | |
554 | a8083063 | Iustin Pop | if __name__ == '__main__': |
555 | a8083063 | Iustin Pop | retcode = GenericMain(commands) |
556 | a8083063 | Iustin Pop | sys.exit(retcode) |