Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-instance @ 47988778

History | View | Annotate | Download (24.4 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 312ac745 Iustin Pop
import itertools
25 a8083063 Iustin Pop
from optparse import make_option
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 312ac745 Iustin Pop
from ganeti import errors
34 312ac745 Iustin Pop
35 312ac745 Iustin Pop
36 312ac745 Iustin Pop
_SHUTDOWN_CLUSTER = "cluster"
37 312ac745 Iustin Pop
_SHUTDOWN_NODES_BOTH = "nodes"
38 312ac745 Iustin Pop
_SHUTDOWN_NODES_PRI = "nodes-pri"
39 312ac745 Iustin Pop
_SHUTDOWN_NODES_SEC = "nodes-sec"
40 312ac745 Iustin Pop
_SHUTDOWN_INSTANCES = "instances"
41 312ac745 Iustin Pop
42 312ac745 Iustin Pop
def _ExpandMultiNames(mode, names):
43 312ac745 Iustin Pop
  """Expand the given names using the passed mode.
44 312ac745 Iustin Pop
45 312ac745 Iustin Pop
  Args:
46 312ac745 Iustin Pop
    - mode, which can be one of _SHUTDOWN_CLUSTER, _SHUTDOWN_NODES_BOTH,
47 312ac745 Iustin Pop
      _SHUTDOWN_NODES_PRI, _SHUTDOWN_NODES_SEC or _SHUTDOWN_INSTANCES
48 312ac745 Iustin Pop
    - names, which is a list of names; for cluster, it must be empty,
49 312ac745 Iustin Pop
      and for node and instance it must be a list of valid item
50 312ac745 Iustin Pop
      names (short names are valid as usual, e.g. node1 instead of
51 312ac745 Iustin Pop
      node1.example.com)
52 312ac745 Iustin Pop
53 312ac745 Iustin Pop
  For _SHUTDOWN_CLUSTER, all instances will be returned. For
54 312ac745 Iustin Pop
  _SHUTDOWN_NODES_PRI/SEC, all instances having those nodes as
55 312ac745 Iustin Pop
  primary/secondary will be shutdown. For _SHUTDOWN_NODES_BOTH, all
56 312ac745 Iustin Pop
  instances having those nodes as either primary or secondary will be
57 312ac745 Iustin Pop
  returned. For _SHUTDOWN_INSTANCES, the given instances will be
58 312ac745 Iustin Pop
  returned.
59 312ac745 Iustin Pop
60 312ac745 Iustin Pop
  """
61 312ac745 Iustin Pop
  if mode == _SHUTDOWN_CLUSTER:
62 312ac745 Iustin Pop
    if names:
63 312ac745 Iustin Pop
      raise errors.OpPrereqError("Cluster filter mode takes no arguments")
64 312ac745 Iustin Pop
    op = opcodes.OpQueryInstances(output_fields=["name"], names=[])
65 312ac745 Iustin Pop
    idata = SubmitOpCode(op)
66 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
67 312ac745 Iustin Pop
68 312ac745 Iustin Pop
  elif mode in (_SHUTDOWN_NODES_BOTH,
69 312ac745 Iustin Pop
                _SHUTDOWN_NODES_PRI,
70 312ac745 Iustin Pop
                _SHUTDOWN_NODES_SEC):
71 312ac745 Iustin Pop
    if not names:
72 312ac745 Iustin Pop
      raise errors.OpPrereqError("No node names passed")
73 312ac745 Iustin Pop
    op = opcodes.OpQueryNodes(output_fields=["name", "pinst_list",
74 312ac745 Iustin Pop
                                             "sinst_list"], names=names)
75 312ac745 Iustin Pop
    ndata = SubmitOpCode(op)
76 312ac745 Iustin Pop
    ipri = [row[1] for row in ndata]
77 312ac745 Iustin Pop
    pri_names = list(itertools.chain(*ipri))
78 312ac745 Iustin Pop
    isec = [row[2] for row in ndata]
79 312ac745 Iustin Pop
    sec_names = list(itertools.chain(*isec))
80 312ac745 Iustin Pop
    if mode == _SHUTDOWN_NODES_BOTH:
81 312ac745 Iustin Pop
      inames = pri_names + sec_names
82 312ac745 Iustin Pop
    elif mode == _SHUTDOWN_NODES_PRI:
83 312ac745 Iustin Pop
      inames = pri_names
84 312ac745 Iustin Pop
    elif mode == _SHUTDOWN_NODES_SEC:
85 312ac745 Iustin Pop
      inames = sec_names
86 312ac745 Iustin Pop
    else:
87 312ac745 Iustin Pop
      raise errors.ProgrammerError("Unhandled shutdown type")
88 312ac745 Iustin Pop
89 312ac745 Iustin Pop
  elif mode == _SHUTDOWN_INSTANCES:
90 312ac745 Iustin Pop
    if not names:
91 312ac745 Iustin Pop
      raise errors.OpPrereqError("No instance names passed")
92 312ac745 Iustin Pop
    op = opcodes.OpQueryInstances(output_fields=["name"], names=names)
93 312ac745 Iustin Pop
    idata = SubmitOpCode(op)
94 312ac745 Iustin Pop
    inames = [row[0] for row in idata]
95 312ac745 Iustin Pop
96 312ac745 Iustin Pop
  else:
97 312ac745 Iustin Pop
    raise errors.OpPrereqError("Unknown mode '%s'" % mode)
98 312ac745 Iustin Pop
99 312ac745 Iustin Pop
  return inames
100 a8083063 Iustin Pop
101 a8083063 Iustin Pop
102 a8083063 Iustin Pop
def ListInstances(opts, args):
103 a8083063 Iustin Pop
  """List nodes and their properties.
104 a8083063 Iustin Pop
105 a8083063 Iustin Pop
  """
106 a8083063 Iustin Pop
  if opts.output is None:
107 a8083063 Iustin Pop
    selected_fields = ["name", "os", "pnode", "admin_state",
108 a8083063 Iustin Pop
                       "oper_state", "oper_ram"]
109 a8083063 Iustin Pop
  else:
110 a8083063 Iustin Pop
    selected_fields = opts.output.split(",")
111 a8083063 Iustin Pop
112 069dcc86 Iustin Pop
  op = opcodes.OpQueryInstances(output_fields=selected_fields, names=[])
113 a8083063 Iustin Pop
  output = SubmitOpCode(op)
114 a8083063 Iustin Pop
115 a8083063 Iustin Pop
  if not opts.no_headers:
116 137161c9 Michael Hanselmann
    headers = {"name": "Instance", "os": "OS", "pnode": "Primary_node",
117 137161c9 Michael Hanselmann
               "snodes": "Secondary_Nodes", "admin_state": "Autostart",
118 137161c9 Michael Hanselmann
               "oper_state": "Status", "admin_ram": "Configured_memory",
119 137161c9 Michael Hanselmann
               "oper_ram": "Memory", "disk_template": "Disk_template",
120 137161c9 Michael Hanselmann
               "ip": "IP Address", "mac": "MAC Address",
121 644eeef9 Iustin Pop
               "bridge": "Bridge",
122 644eeef9 Iustin Pop
               "sda_size": "Disk/0", "sdb_size": "Disk/1"}
123 137161c9 Michael Hanselmann
  else:
124 137161c9 Michael Hanselmann
    headers = None
125 137161c9 Michael Hanselmann
126 137161c9 Michael Hanselmann
  if opts.human_readable:
127 644eeef9 Iustin Pop
    unitfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size"]
128 137161c9 Michael Hanselmann
  else:
129 137161c9 Michael Hanselmann
    unitfields = None
130 137161c9 Michael Hanselmann
131 644eeef9 Iustin Pop
  numfields = ["admin_ram", "oper_ram", "sda_size", "sdb_size"]
132 137161c9 Michael Hanselmann
133 8a23d2d3 Iustin Pop
  # change raw values to nicer strings
134 8a23d2d3 Iustin Pop
  for row in output:
135 8a23d2d3 Iustin Pop
    for idx, field in enumerate(selected_fields):
136 8a23d2d3 Iustin Pop
      val = row[idx]
137 8a23d2d3 Iustin Pop
      if field == "snodes":
138 8a23d2d3 Iustin Pop
        val = ",".join(val) or "-"
139 8a23d2d3 Iustin Pop
      elif field == "admin_state":
140 8a23d2d3 Iustin Pop
        if val:
141 8a23d2d3 Iustin Pop
          val = "yes"
142 8a23d2d3 Iustin Pop
        else:
143 8a23d2d3 Iustin Pop
          val = "no"
144 8a23d2d3 Iustin Pop
      elif field == "oper_state":
145 8a23d2d3 Iustin Pop
        if val is None:
146 8a23d2d3 Iustin Pop
          val = "(node down)"
147 8a23d2d3 Iustin Pop
        elif val: # True
148 8a23d2d3 Iustin Pop
          val = "running"
149 8a23d2d3 Iustin Pop
        else:
150 8a23d2d3 Iustin Pop
          val = "stopped"
151 8a23d2d3 Iustin Pop
      elif field == "oper_ram":
152 8a23d2d3 Iustin Pop
        if val is None:
153 8a23d2d3 Iustin Pop
          val = "(node down)"
154 8a23d2d3 Iustin Pop
      elif field == "sda_size" or field == "sdb_size":
155 8a23d2d3 Iustin Pop
        if val is None:
156 8a23d2d3 Iustin Pop
          val = "N/A"
157 8a23d2d3 Iustin Pop
      row[idx] = str(val)
158 8a23d2d3 Iustin Pop
159 16be8703 Iustin Pop
  data = GenerateTable(separator=opts.separator, headers=headers,
160 16be8703 Iustin Pop
                       fields=selected_fields, unitfields=unitfields,
161 16be8703 Iustin Pop
                       numfields=numfields, data=output)
162 16be8703 Iustin Pop
163 16be8703 Iustin Pop
  for line in data:
164 16be8703 Iustin Pop
    logger.ToStdout(line)
165 a8083063 Iustin Pop
166 a8083063 Iustin Pop
  return 0
167 a8083063 Iustin Pop
168 a8083063 Iustin Pop
169 a8083063 Iustin Pop
def AddInstance(opts, args):
170 a8083063 Iustin Pop
  """Add an instance to the cluster.
171 a8083063 Iustin Pop
172 a8083063 Iustin Pop
  Args:
173 a8083063 Iustin Pop
    opts - class with options as members
174 a8083063 Iustin Pop
    args - list with a single element, the instance name
175 a8083063 Iustin Pop
  Opts used:
176 a8083063 Iustin Pop
    mem - amount of memory to allocate to instance (MiB)
177 a8083063 Iustin Pop
    size - amount of disk space to allocate to instance (MiB)
178 a8083063 Iustin Pop
    os - which OS to run on instance
179 a8083063 Iustin Pop
    node - node to run new instance on
180 a8083063 Iustin Pop
181 a8083063 Iustin Pop
  """
182 a8083063 Iustin Pop
  instance = args[0]
183 a8083063 Iustin Pop
184 a8083063 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance, mem_size=opts.mem,
185 a8083063 Iustin Pop
                                disk_size=opts.size, swap_size=opts.swap,
186 a8083063 Iustin Pop
                                disk_template=opts.disk_template,
187 a8083063 Iustin Pop
                                mode=constants.INSTANCE_CREATE,
188 a8083063 Iustin Pop
                                os_type=opts.os, pnode=opts.node,
189 a8083063 Iustin Pop
                                snode=opts.snode, vcpus=opts.vcpus,
190 bdd55f71 Iustin Pop
                                ip=opts.ip, bridge=opts.bridge,
191 bdd55f71 Iustin Pop
                                start=opts.start, ip_check=opts.ip_check,
192 a8083063 Iustin Pop
                                wait_for_sync=opts.wait_for_sync)
193 a8083063 Iustin Pop
  SubmitOpCode(op)
194 a8083063 Iustin Pop
  return 0
195 a8083063 Iustin Pop
196 a8083063 Iustin Pop
197 fe7b0351 Michael Hanselmann
def ReinstallInstance(opts, args):
198 fe7b0351 Michael Hanselmann
  """Reinstall an instance.
199 fe7b0351 Michael Hanselmann
200 fe7b0351 Michael Hanselmann
  Args:
201 fe7b0351 Michael Hanselmann
    opts - class with options as members
202 fe7b0351 Michael Hanselmann
    args - list containing a single element, the instance name
203 fe7b0351 Michael Hanselmann
204 fe7b0351 Michael Hanselmann
  """
205 fe7b0351 Michael Hanselmann
  instance_name = args[0]
206 fe7b0351 Michael Hanselmann
207 fe7b0351 Michael Hanselmann
  if not opts.force:
208 fe7b0351 Michael Hanselmann
    usertext = ("This will reinstall the instance %s and remove "
209 fe7b0351 Michael Hanselmann
                "all data. Continue?") % instance_name
210 47988778 Iustin Pop
    if not AskUser(usertext):
211 fe7b0351 Michael Hanselmann
      return 1
212 fe7b0351 Michael Hanselmann
213 d0834de3 Michael Hanselmann
  op = opcodes.OpReinstallInstance(instance_name=instance_name,
214 d0834de3 Michael Hanselmann
                                   os_type=opts.os)
215 fe7b0351 Michael Hanselmann
  SubmitOpCode(op)
216 fe7b0351 Michael Hanselmann
217 fe7b0351 Michael Hanselmann
  return 0
218 fe7b0351 Michael Hanselmann
219 fe7b0351 Michael Hanselmann
220 a8083063 Iustin Pop
def RemoveInstance(opts, args):
221 a8083063 Iustin Pop
  """Remove an instance.
222 a8083063 Iustin Pop
223 a8083063 Iustin Pop
  Args:
224 a8083063 Iustin Pop
    opts - class with options as members
225 a8083063 Iustin Pop
    args - list containing a single element, the instance name
226 a8083063 Iustin Pop
227 a8083063 Iustin Pop
  """
228 a8083063 Iustin Pop
  instance_name = args[0]
229 a8083063 Iustin Pop
  force = opts.force
230 a8083063 Iustin Pop
231 a8083063 Iustin Pop
  if not force:
232 a8083063 Iustin Pop
    usertext = ("This will remove the volumes of the instance %s"
233 a8083063 Iustin Pop
                " (including mirrors), thus removing all the data"
234 a8083063 Iustin Pop
                " of the instance. Continue?") % instance_name
235 47988778 Iustin Pop
    if not AskUser(usertext):
236 a8083063 Iustin Pop
      return 1
237 a8083063 Iustin Pop
238 a8083063 Iustin Pop
  op = opcodes.OpRemoveInstance(instance_name=instance_name)
239 a8083063 Iustin Pop
  SubmitOpCode(op)
240 a8083063 Iustin Pop
  return 0
241 a8083063 Iustin Pop
242 a8083063 Iustin Pop
243 decd5f45 Iustin Pop
def RenameInstance(opts, args):
244 4ab0b9e3 Guido Trotter
  """Rename an instance.
245 decd5f45 Iustin Pop
246 decd5f45 Iustin Pop
  Args:
247 decd5f45 Iustin Pop
    opts - class with options as members
248 decd5f45 Iustin Pop
    args - list containing two elements, the instance name and the new name
249 decd5f45 Iustin Pop
250 decd5f45 Iustin Pop
  """
251 decd5f45 Iustin Pop
  op = opcodes.OpRenameInstance(instance_name=args[0],
252 decd5f45 Iustin Pop
                                new_name=args[1],
253 decd5f45 Iustin Pop
                                ignore_ip=opts.ignore_ip)
254 decd5f45 Iustin Pop
  SubmitOpCode(op)
255 decd5f45 Iustin Pop
256 decd5f45 Iustin Pop
  return 0
257 decd5f45 Iustin Pop
258 decd5f45 Iustin Pop
259 a8083063 Iustin Pop
def ActivateDisks(opts, args):
260 a8083063 Iustin Pop
  """Activate an instance's disks.
261 a8083063 Iustin Pop
262 a8083063 Iustin Pop
  This serves two purposes:
263 a8083063 Iustin Pop
    - it allows one (as long as the instance is not running) to mount
264 a8083063 Iustin Pop
    the disks and modify them from the node
265 a8083063 Iustin Pop
    - it repairs inactive secondary drbds
266 a8083063 Iustin Pop
267 a8083063 Iustin Pop
  """
268 a8083063 Iustin Pop
  instance_name = args[0]
269 a8083063 Iustin Pop
  op = opcodes.OpActivateInstanceDisks(instance_name=instance_name)
270 a8083063 Iustin Pop
  disks_info = SubmitOpCode(op)
271 a8083063 Iustin Pop
  for host, iname, nname in disks_info:
272 a8083063 Iustin Pop
    print "%s:%s:%s" % (host, iname, nname)
273 a8083063 Iustin Pop
  return 0
274 a8083063 Iustin Pop
275 a8083063 Iustin Pop
276 a8083063 Iustin Pop
def DeactivateDisks(opts, args):
277 a8083063 Iustin Pop
  """Command-line interface for _ShutdownInstanceBlockDevices.
278 a8083063 Iustin Pop
279 a8083063 Iustin Pop
  This function takes the instance name, looks for its primary node
280 a8083063 Iustin Pop
  and the tries to shutdown its block devices on that node.
281 a8083063 Iustin Pop
282 a8083063 Iustin Pop
  """
283 a8083063 Iustin Pop
  instance_name = args[0]
284 a8083063 Iustin Pop
  op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
285 a8083063 Iustin Pop
  SubmitOpCode(op)
286 a8083063 Iustin Pop
  return 0
287 a8083063 Iustin Pop
288 a8083063 Iustin Pop
289 a8083063 Iustin Pop
def StartupInstance(opts, args):
290 decd5f45 Iustin Pop
  """Startup an instance.
291 a8083063 Iustin Pop
292 a8083063 Iustin Pop
  Args:
293 a8083063 Iustin Pop
    opts - class with options as members
294 a8083063 Iustin Pop
    args - list containing a single element, the instance name
295 a8083063 Iustin Pop
296 a8083063 Iustin Pop
  """
297 312ac745 Iustin Pop
  if opts.multi_mode is None:
298 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
299 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
300 312ac745 Iustin Pop
  multi_on = len(inames) > 1
301 312ac745 Iustin Pop
  for name in inames:
302 312ac745 Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=name,
303 312ac745 Iustin Pop
                                   force=opts.force,
304 312ac745 Iustin Pop
                                   extra_args=opts.extra_args)
305 312ac745 Iustin Pop
    if multi_on:
306 312ac745 Iustin Pop
      logger.ToStdout("Starting up %s" % name)
307 312ac745 Iustin Pop
    SubmitOpCode(op)
308 a8083063 Iustin Pop
  return 0
309 a8083063 Iustin Pop
310 a8083063 Iustin Pop
311 a8083063 Iustin Pop
def ShutdownInstance(opts, args):
312 a8083063 Iustin Pop
  """Shutdown an instance.
313 a8083063 Iustin Pop
314 a8083063 Iustin Pop
  Args:
315 a8083063 Iustin Pop
    opts - class with options as members
316 a8083063 Iustin Pop
    args - list containing a single element, the instance name
317 a8083063 Iustin Pop
318 a8083063 Iustin Pop
  """
319 312ac745 Iustin Pop
  if opts.multi_mode is None:
320 312ac745 Iustin Pop
    opts.multi_mode = _SHUTDOWN_INSTANCES
321 312ac745 Iustin Pop
  inames = _ExpandMultiNames(opts.multi_mode, args)
322 312ac745 Iustin Pop
  multi_on = len(inames) > 1
323 312ac745 Iustin Pop
  for name in inames:
324 312ac745 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=name)
325 312ac745 Iustin Pop
    if multi_on:
326 312ac745 Iustin Pop
      logger.ToStdout("Shutting down %s" % name)
327 312ac745 Iustin Pop
    SubmitOpCode(op)
328 a8083063 Iustin Pop
  return 0
329 a8083063 Iustin Pop
330 a8083063 Iustin Pop
331 a8083063 Iustin Pop
def AddMDDRBDComponent(opts, args):
332 a8083063 Iustin Pop
  """Add a new component to a remote_raid1 disk.
333 a8083063 Iustin Pop
334 a8083063 Iustin Pop
  Args:
335 a8083063 Iustin Pop
    opts - class with options as members
336 a8083063 Iustin Pop
    args - list with a single element, the instance name
337 a8083063 Iustin Pop
338 a8083063 Iustin Pop
  """
339 a8083063 Iustin Pop
  op = opcodes.OpAddMDDRBDComponent(instance_name=args[0],
340 a8083063 Iustin Pop
                                    disk_name=opts.disk,
341 a8083063 Iustin Pop
                                    remote_node=opts.node)
342 a8083063 Iustin Pop
  SubmitOpCode(op)
343 a8083063 Iustin Pop
  return 0
344 a8083063 Iustin Pop
345 a8083063 Iustin Pop
346 a8083063 Iustin Pop
def RemoveMDDRBDComponent(opts, args):
347 bdb8c997 Guido Trotter
  """Remove a component from a remote_raid1 disk.
348 a8083063 Iustin Pop
349 a8083063 Iustin Pop
  Args:
350 a8083063 Iustin Pop
    opts - class with options as members
351 a8083063 Iustin Pop
    args - list with a single element, the instance name
352 a8083063 Iustin Pop
353 a8083063 Iustin Pop
  """
354 a8083063 Iustin Pop
  op = opcodes.OpRemoveMDDRBDComponent(instance_name=args[0],
355 a8083063 Iustin Pop
                                       disk_name=opts.disk,
356 a8083063 Iustin Pop
                                       disk_id=opts.port)
357 a8083063 Iustin Pop
  SubmitOpCode(op)
358 a8083063 Iustin Pop
  return 0
359 a8083063 Iustin Pop
360 a8083063 Iustin Pop
361 a8083063 Iustin Pop
def ReplaceDisks(opts, args):
362 a8083063 Iustin Pop
  """Replace the disks of an instance
363 a8083063 Iustin Pop
364 a8083063 Iustin Pop
  Args:
365 a8083063 Iustin Pop
    opts - class with options as members
366 a8083063 Iustin Pop
    args - list with a single element, the instance name
367 a8083063 Iustin Pop
368 a8083063 Iustin Pop
  """
369 a8083063 Iustin Pop
  instance_name = args[0]
370 a8083063 Iustin Pop
  new_secondary = opts.new_secondary
371 a8083063 Iustin Pop
  op = opcodes.OpReplaceDisks(instance_name=args[0],
372 a8083063 Iustin Pop
                              remote_node=opts.new_secondary)
373 a8083063 Iustin Pop
  SubmitOpCode(op)
374 a8083063 Iustin Pop
  return 0
375 a8083063 Iustin Pop
376 a8083063 Iustin Pop
377 a8083063 Iustin Pop
def FailoverInstance(opts, args):
378 a8083063 Iustin Pop
  """Failover an instance.
379 a8083063 Iustin Pop
380 a8083063 Iustin Pop
  The failover is done by shutting it down on its present node and
381 a8083063 Iustin Pop
  starting it on the secondary.
382 a8083063 Iustin Pop
383 a8083063 Iustin Pop
  Args:
384 a8083063 Iustin Pop
    opts - class with options as members
385 a8083063 Iustin Pop
    args - list with a single element, the instance name
386 a8083063 Iustin Pop
  Opts used:
387 a8083063 Iustin Pop
    force - whether to failover without asking questions.
388 a8083063 Iustin Pop
389 a8083063 Iustin Pop
  """
390 a8083063 Iustin Pop
  instance_name = args[0]
391 a8083063 Iustin Pop
  force = opts.force
392 a8083063 Iustin Pop
393 a8083063 Iustin Pop
  if not force:
394 a8083063 Iustin Pop
    usertext = ("Failover will happen to image %s."
395 a8083063 Iustin Pop
                " This requires a shutdown of the instance. Continue?" %
396 a8083063 Iustin Pop
                (instance_name,))
397 47988778 Iustin Pop
    if not AskUser(usertext):
398 a8083063 Iustin Pop
      return 1
399 a8083063 Iustin Pop
400 a8083063 Iustin Pop
  op = opcodes.OpFailoverInstance(instance_name=instance_name,
401 a8083063 Iustin Pop
                                  ignore_consistency=opts.ignore_consistency)
402 a8083063 Iustin Pop
  SubmitOpCode(op)
403 a8083063 Iustin Pop
  return 0
404 a8083063 Iustin Pop
405 a8083063 Iustin Pop
406 a8083063 Iustin Pop
def ConnectToInstanceConsole(opts, args):
407 a8083063 Iustin Pop
  """Connect to the console of an instance.
408 a8083063 Iustin Pop
409 a8083063 Iustin Pop
  Args:
410 a8083063 Iustin Pop
    opts - class with options as members
411 a8083063 Iustin Pop
    args - list with a single element, the instance name
412 a8083063 Iustin Pop
413 a8083063 Iustin Pop
  """
414 a8083063 Iustin Pop
  instance_name = args[0]
415 a8083063 Iustin Pop
416 a8083063 Iustin Pop
  op = opcodes.OpConnectConsole(instance_name=instance_name)
417 82122173 Iustin Pop
  cmd, argv = SubmitOpCode(op)
418 a8083063 Iustin Pop
  # drop lock and exec so other commands can run while we have console
419 a8083063 Iustin Pop
  utils.Unlock("cmd")
420 a8083063 Iustin Pop
  try:
421 82122173 Iustin Pop
    os.execvp(cmd, argv)
422 a8083063 Iustin Pop
  finally:
423 82122173 Iustin Pop
    sys.stderr.write("Can't run console command %s with arguments:\n'%s'" %
424 82122173 Iustin Pop
                     (cmd, " ".join(argv)))
425 a8083063 Iustin Pop
    os._exit(1)
426 a8083063 Iustin Pop
427 a8083063 Iustin Pop
428 a8083063 Iustin Pop
def _FormatBlockDevInfo(buf, dev, indent_level):
429 a8083063 Iustin Pop
  """Show block device information.
430 a8083063 Iustin Pop
431 a8083063 Iustin Pop
  This is only used by ShowInstanceConfig(), but it's too big to be
432 a8083063 Iustin Pop
  left for an inline definition.
433 a8083063 Iustin Pop
434 a8083063 Iustin Pop
  """
435 a8083063 Iustin Pop
  def helper(buf, dtype, status):
436 a8083063 Iustin Pop
    """Format one line for phsyical device status."""
437 a8083063 Iustin Pop
    if not status:
438 a8083063 Iustin Pop
      buf.write("not active\n")
439 a8083063 Iustin Pop
    else:
440 a8083063 Iustin Pop
      (path, major, minor, syncp, estt, degr) = status
441 a8083063 Iustin Pop
      buf.write("%s (%d:%d)" % (path, major, minor))
442 a8083063 Iustin Pop
      if dtype in ("md_raid1", "drbd"):
443 a8083063 Iustin Pop
        if syncp is not None:
444 a8083063 Iustin Pop
          sync_text = "*RECOVERING* %5.2f%%," % syncp
445 a8083063 Iustin Pop
          if estt:
446 a8083063 Iustin Pop
            sync_text += " ETA %ds" % estt
447 a8083063 Iustin Pop
          else:
448 a8083063 Iustin Pop
            sync_text += " ETA unknown"
449 a8083063 Iustin Pop
        else:
450 a8083063 Iustin Pop
          sync_text = "in sync"
451 a8083063 Iustin Pop
        if degr:
452 a8083063 Iustin Pop
          degr_text = "*DEGRADED*"
453 a8083063 Iustin Pop
        else:
454 a8083063 Iustin Pop
          degr_text = "ok"
455 a8083063 Iustin Pop
        buf.write(" %s, status %s" % (sync_text, degr_text))
456 a8083063 Iustin Pop
      buf.write("\n")
457 a8083063 Iustin Pop
458 a8083063 Iustin Pop
  if dev["iv_name"] is not None:
459 a8083063 Iustin Pop
    data = "  - %s, " % dev["iv_name"]
460 a8083063 Iustin Pop
  else:
461 a8083063 Iustin Pop
    data = "  - "
462 a8083063 Iustin Pop
  data += "type: %s" % dev["dev_type"]
463 a8083063 Iustin Pop
  if dev["logical_id"] is not None:
464 a8083063 Iustin Pop
    data += ", logical_id: %s" % (dev["logical_id"],)
465 a8083063 Iustin Pop
  elif dev["physical_id"] is not None:
466 a8083063 Iustin Pop
    data += ", physical_id: %s" % (dev["physical_id"],)
467 a8083063 Iustin Pop
  buf.write("%*s%s\n" % (2*indent_level, "", data))
468 a8083063 Iustin Pop
  buf.write("%*s    primary:   " % (2*indent_level, ""))
469 a8083063 Iustin Pop
  helper(buf, dev["dev_type"], dev["pstatus"])
470 a8083063 Iustin Pop
471 a8083063 Iustin Pop
  if dev["sstatus"]:
472 a8083063 Iustin Pop
    buf.write("%*s    secondary: " % (2*indent_level, ""))
473 a8083063 Iustin Pop
    helper(buf, dev["dev_type"], dev["sstatus"])
474 a8083063 Iustin Pop
475 a8083063 Iustin Pop
  if dev["children"]:
476 a8083063 Iustin Pop
    for child in dev["children"]:
477 a8083063 Iustin Pop
      _FormatBlockDevInfo(buf, child, indent_level+1)
478 a8083063 Iustin Pop
479 a8083063 Iustin Pop
480 a8083063 Iustin Pop
def ShowInstanceConfig(opts, args):
481 a8083063 Iustin Pop
  """Compute instance run-time status.
482 a8083063 Iustin Pop
483 a8083063 Iustin Pop
  """
484 a8083063 Iustin Pop
  retcode = 0
485 a8083063 Iustin Pop
  op = opcodes.OpQueryInstanceData(instances=args)
486 a8083063 Iustin Pop
  result = SubmitOpCode(op)
487 a8083063 Iustin Pop
488 a8083063 Iustin Pop
  if not result:
489 a8083063 Iustin Pop
    logger.ToStdout("No instances.")
490 a8083063 Iustin Pop
    return 1
491 a8083063 Iustin Pop
492 a8083063 Iustin Pop
  buf = StringIO()
493 a8083063 Iustin Pop
  retcode = 0
494 a8083063 Iustin Pop
  for instance_name in result:
495 a8083063 Iustin Pop
    instance = result[instance_name]
496 a8083063 Iustin Pop
    buf.write("Instance name: %s\n" % instance["name"])
497 a8083063 Iustin Pop
    buf.write("State: configured to be %s, actual state is %s\n" %
498 a8083063 Iustin Pop
              (instance["config_state"], instance["run_state"]))
499 a8083063 Iustin Pop
    buf.write("  Nodes:\n")
500 a8083063 Iustin Pop
    buf.write("    - primary: %s\n" % instance["pnode"])
501 a8083063 Iustin Pop
    buf.write("    - secondaries: %s\n" % ", ".join(instance["snodes"]))
502 a8083063 Iustin Pop
    buf.write("  Operating system: %s\n" % instance["os"])
503 a8083063 Iustin Pop
    buf.write("  Hardware:\n")
504 a8083063 Iustin Pop
    buf.write("    - memory: %dMiB\n" % instance["memory"])
505 a8083063 Iustin Pop
    buf.write("    - NICs: %s\n" %
506 a8083063 Iustin Pop
        ", ".join(["{MAC: %s, IP: %s, bridge: %s}" %
507 a8083063 Iustin Pop
                   (mac, ip, bridge)
508 a8083063 Iustin Pop
                     for mac, ip, bridge in instance["nics"]]))
509 a8083063 Iustin Pop
    buf.write("  Block devices:\n")
510 a8083063 Iustin Pop
511 a8083063 Iustin Pop
    for device in instance["disks"]:
512 a8083063 Iustin Pop
      _FormatBlockDevInfo(buf, device, 1)
513 a8083063 Iustin Pop
514 a8083063 Iustin Pop
  logger.ToStdout(buf.getvalue().rstrip('\n'))
515 a8083063 Iustin Pop
  return retcode
516 a8083063 Iustin Pop
517 a8083063 Iustin Pop
518 a8083063 Iustin Pop
def SetInstanceParms(opts, args):
519 a8083063 Iustin Pop
  """Modifies an instance.
520 a8083063 Iustin Pop
521 a8083063 Iustin Pop
  All parameters take effect only at the next restart of the instance.
522 a8083063 Iustin Pop
523 a8083063 Iustin Pop
  Args:
524 a8083063 Iustin Pop
    opts - class with options as members
525 a8083063 Iustin Pop
    args - list with a single element, the instance name
526 a8083063 Iustin Pop
  Opts used:
527 a8083063 Iustin Pop
    memory - the new memory size
528 a8083063 Iustin Pop
    vcpus - the new number of cpus
529 a8083063 Iustin Pop
530 a8083063 Iustin Pop
  """
531 a8083063 Iustin Pop
  if not opts.mem and not opts.vcpus and not opts.ip and not opts.bridge:
532 a8083063 Iustin Pop
    logger.ToStdout("Please give at least one of the parameters.")
533 a8083063 Iustin Pop
    return 1
534 a8083063 Iustin Pop
535 a8083063 Iustin Pop
  op = opcodes.OpSetInstanceParms(instance_name=args[0], mem=opts.mem,
536 a8083063 Iustin Pop
                                  vcpus=opts.vcpus, ip=opts.ip,
537 a8083063 Iustin Pop
                                  bridge=opts.bridge)
538 a8083063 Iustin Pop
  result = SubmitOpCode(op)
539 a8083063 Iustin Pop
540 a8083063 Iustin Pop
  if result:
541 a8083063 Iustin Pop
    logger.ToStdout("Modified instance %s" % args[0])
542 a8083063 Iustin Pop
    for param, data in result:
543 a8083063 Iustin Pop
      logger.ToStdout(" - %-5s -> %s" % (param, data))
544 a8083063 Iustin Pop
    logger.ToStdout("Please don't forget that these parameters take effect"
545 a8083063 Iustin Pop
                    " only at the next start of the instance.")
546 a8083063 Iustin Pop
  return 0
547 a8083063 Iustin Pop
548 a8083063 Iustin Pop
549 a8083063 Iustin Pop
# options used in more than one cmd
550 a8083063 Iustin Pop
node_opt = make_option("-n", "--node", dest="node", help="Target node",
551 a8083063 Iustin Pop
                       metavar="<node>")
552 a8083063 Iustin Pop
553 d0834de3 Michael Hanselmann
os_opt = cli_option("-o", "--os-type", dest="os", help="What OS to run",
554 739ecd56 Michael Hanselmann
                    metavar="<os>")
555 d0834de3 Michael Hanselmann
556 312ac745 Iustin Pop
# multi-instance selection options
557 312ac745 Iustin Pop
m_pri_node_opt = make_option("--primary", dest="multi_mode",
558 312ac745 Iustin Pop
                             help="Filter by nodes (primary only)",
559 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_PRI, action="store_const")
560 312ac745 Iustin Pop
561 312ac745 Iustin Pop
m_sec_node_opt = make_option("--secondary", dest="multi_mode",
562 312ac745 Iustin Pop
                             help="Filter by nodes (secondary only)",
563 312ac745 Iustin Pop
                             const=_SHUTDOWN_NODES_SEC, action="store_const")
564 312ac745 Iustin Pop
565 312ac745 Iustin Pop
m_node_opt = make_option("--node", dest="multi_mode",
566 312ac745 Iustin Pop
                         help="Filter by nodes (primary and secondary)",
567 312ac745 Iustin Pop
                         const=_SHUTDOWN_NODES_BOTH, action="store_const")
568 312ac745 Iustin Pop
569 312ac745 Iustin Pop
m_clust_opt = make_option("--all", dest="multi_mode",
570 312ac745 Iustin Pop
                          help="Select all instances in the cluster",
571 312ac745 Iustin Pop
                          const=_SHUTDOWN_CLUSTER, action="store_const")
572 312ac745 Iustin Pop
573 312ac745 Iustin Pop
m_inst_opt = make_option("--instance", dest="multi_mode",
574 312ac745 Iustin Pop
                         help="Filter by instance name [default]",
575 312ac745 Iustin Pop
                         const=_SHUTDOWN_INSTANCES, action="store_const")
576 312ac745 Iustin Pop
577 312ac745 Iustin Pop
578 a8083063 Iustin Pop
# this is defined separately due to readability only
579 a8083063 Iustin Pop
add_opts = [
580 a8083063 Iustin Pop
  DEBUG_OPT,
581 a8083063 Iustin Pop
  node_opt,
582 b9ac33e9 Iustin Pop
  cli_option("-s", "--os-size", dest="size", help="Disk size, in MiB unless"
583 b9ac33e9 Iustin Pop
             " a suffix is used",
584 a8083063 Iustin Pop
             default=20 * 1024, type="unit", metavar="<size>"),
585 b9ac33e9 Iustin Pop
  cli_option("--swap-size", dest="swap", help="Swap size, in MiB unless a"
586 b9ac33e9 Iustin Pop
             " suffix is used",
587 a8083063 Iustin Pop
             default=4 * 1024, type="unit", metavar="<size>"),
588 d0834de3 Michael Hanselmann
  os_opt,
589 b9ac33e9 Iustin Pop
  cli_option("-m", "--memory", dest="mem", help="Memory size (in MiB)",
590 a8083063 Iustin Pop
              default=128, type="unit", metavar="<mem>"),
591 a8083063 Iustin Pop
  make_option("-p", "--cpu", dest="vcpus", help="Number of virtual CPUs",
592 a8083063 Iustin Pop
              default=1, type="int", metavar="<PROC>"),
593 a8083063 Iustin Pop
  make_option("-t", "--disk-template", dest="disk_template",
594 a8083063 Iustin Pop
              help="Custom disk setup (diskless, plain, local_raid1 or"
595 a8083063 Iustin Pop
              " remote_raid1)", default=None, metavar="TEMPL"),
596 a8083063 Iustin Pop
  make_option("-i", "--ip", dest="ip",
597 a8083063 Iustin Pop
              help="IP address ('none' [default], 'auto', or specify address)",
598 a8083063 Iustin Pop
              default='none', type="string", metavar="<ADDRESS>"),
599 a8083063 Iustin Pop
  make_option("--no-wait-for-sync", dest="wait_for_sync", default=True,
600 a8083063 Iustin Pop
              action="store_false", help="Don't wait for sync (DANGEROUS!)"),
601 a8083063 Iustin Pop
  make_option("--secondary-node", dest="snode",
602 a8083063 Iustin Pop
              help="Secondary node for remote_raid1 disk layout",
603 a8083063 Iustin Pop
              metavar="<node>"),
604 a8083063 Iustin Pop
  make_option("-b", "--bridge", dest="bridge",
605 a8083063 Iustin Pop
              help="Bridge to connect this instance to",
606 bdd55f71 Iustin Pop
              default=None, metavar="<bridge>"),
607 bdd55f71 Iustin Pop
  make_option("--no-start", dest="start", default=True,
608 bdd55f71 Iustin Pop
              action="store_false", help="Don't start the instance after"
609 bdd55f71 Iustin Pop
              " creation"),
610 bdd55f71 Iustin Pop
  make_option("--no-ip-check", dest="ip_check", default=True,
611 bdd55f71 Iustin Pop
              action="store_false", help="Don't check that the instance's IP"
612 bdd55f71 Iustin Pop
              " is alive (only valid with --no-start)"),
613 a8083063 Iustin Pop
  ]
614 a8083063 Iustin Pop
615 a8083063 Iustin Pop
commands = {
616 a8083063 Iustin Pop
  'add': (AddInstance, ARGS_ONE, add_opts,
617 a8083063 Iustin Pop
          "[opts...] <name>",
618 a8083063 Iustin Pop
          "Creates and adds a new instance to the cluster"),
619 a8083063 Iustin Pop
  'add-mirror': (AddMDDRBDComponent, ARGS_ONE,
620 a8083063 Iustin Pop
                [DEBUG_OPT, node_opt,
621 a8083063 Iustin Pop
                 make_option("-b", "--disk", dest="disk", metavar="sdX",
622 a8083063 Iustin Pop
                             help=("The name of the instance disk for which to"
623 a8083063 Iustin Pop
                                   " add the mirror"))],
624 a8083063 Iustin Pop
                "-n node -b disk <instance>",
625 a8083063 Iustin Pop
                "Creates a new mirror for the instance"),
626 a8083063 Iustin Pop
  'console': (ConnectToInstanceConsole, ARGS_ONE, [DEBUG_OPT],
627 a8083063 Iustin Pop
              "<instance>",
628 a8083063 Iustin Pop
              "Opens a console on the specified instance"),
629 a8083063 Iustin Pop
  'failover': (FailoverInstance, ARGS_ONE,
630 fe7b0351 Michael Hanselmann
               [DEBUG_OPT, FORCE_OPT,
631 a8083063 Iustin Pop
                make_option("--ignore-consistency", dest="ignore_consistency",
632 a8083063 Iustin Pop
                            action="store_true", default=False,
633 a8083063 Iustin Pop
                            help="Ignore the consistency of the disks on"
634 a8083063 Iustin Pop
                            " the secondary"),
635 a8083063 Iustin Pop
                ],
636 a8083063 Iustin Pop
               "[-f] <instance>",
637 a8083063 Iustin Pop
               "Stops the instance and starts it on the backup node, using"
638 a8083063 Iustin Pop
               " the remote mirror (only for instances of type remote_raid1)"),
639 a8083063 Iustin Pop
  'info': (ShowInstanceConfig, ARGS_ANY, [DEBUG_OPT], "[<instance>...]",
640 a8083063 Iustin Pop
           "Show information on the specified instance"),
641 a8083063 Iustin Pop
  'list': (ListInstances, ARGS_NONE,
642 dcb93971 Michael Hanselmann
           [DEBUG_OPT, NOHDR_OPT, SEP_OPT, USEUNITS_OPT, FIELDS_OPT],
643 a8083063 Iustin Pop
           "", "Lists the instances and their status"),
644 d0834de3 Michael Hanselmann
  'reinstall': (ReinstallInstance, ARGS_ONE, [DEBUG_OPT, FORCE_OPT, os_opt],
645 fe7b0351 Michael Hanselmann
                "[-f] <instance>", "Reinstall the instance"),
646 fe7b0351 Michael Hanselmann
  'remove': (RemoveInstance, ARGS_ONE, [DEBUG_OPT, FORCE_OPT],
647 a8083063 Iustin Pop
             "[-f] <instance>", "Shuts down the instance and removes it"),
648 a8083063 Iustin Pop
  'remove-mirror': (RemoveMDDRBDComponent, ARGS_ONE,
649 a8083063 Iustin Pop
                   [DEBUG_OPT, node_opt,
650 a8083063 Iustin Pop
                    make_option("-b", "--disk", dest="disk", metavar="sdX",
651 a8083063 Iustin Pop
                                help=("The name of the instance disk"
652 a8083063 Iustin Pop
                                      " for which to add the mirror")),
653 a8083063 Iustin Pop
                    make_option("-p", "--port", dest="port", metavar="PORT",
654 a8083063 Iustin Pop
                                help=("The port of the drbd device"
655 a8083063 Iustin Pop
                                      " which to remove from the mirror"),
656 a8083063 Iustin Pop
                                type="int"),
657 a8083063 Iustin Pop
                    ],
658 a8083063 Iustin Pop
                   "-b disk -p port <instance>",
659 a8083063 Iustin Pop
                   "Removes a mirror from the instance"),
660 decd5f45 Iustin Pop
  'rename': (RenameInstance, ARGS_FIXED(2),
661 decd5f45 Iustin Pop
             [DEBUG_OPT,
662 decd5f45 Iustin Pop
              make_option("--no-ip-check", dest="ignore_ip",
663 decd5f45 Iustin Pop
                          help="Do not check that the IP of the new name"
664 decd5f45 Iustin Pop
                          " is alive",
665 decd5f45 Iustin Pop
                          default=False, action="store_true"),
666 decd5f45 Iustin Pop
              ],
667 decd5f45 Iustin Pop
             "<instance> <new_name>", "Rename the instance"),
668 a8083063 Iustin Pop
  'replace-disks': (ReplaceDisks, ARGS_ONE,
669 a8083063 Iustin Pop
                    [DEBUG_OPT,
670 a8083063 Iustin Pop
                     make_option("-n", "--new-secondary", dest="new_secondary",
671 a8083063 Iustin Pop
                                 metavar="NODE",
672 a8083063 Iustin Pop
                                 help=("New secondary node (if you want to"
673 a8083063 Iustin Pop
                                       " change the secondary)"))],
674 a8083063 Iustin Pop
                    "[-n NODE] <instance>",
675 a8083063 Iustin Pop
                    "Replaces all disks for the instance"),
676 a8083063 Iustin Pop
  'modify': (SetInstanceParms, ARGS_ONE,
677 fe7b0351 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT,
678 a8083063 Iustin Pop
              cli_option("-m", "--memory", dest="mem",
679 a8083063 Iustin Pop
                         help="Memory size",
680 a8083063 Iustin Pop
                         default=None, type="unit", metavar="<mem>"),
681 a8083063 Iustin Pop
              make_option("-p", "--cpu", dest="vcpus",
682 a8083063 Iustin Pop
                          help="Number of virtual CPUs",
683 a8083063 Iustin Pop
                          default=None, type="int", metavar="<PROC>"),
684 a8083063 Iustin Pop
              make_option("-i", "--ip", dest="ip",
685 a8083063 Iustin Pop
                          help="IP address ('none' or numeric IP)",
686 a8083063 Iustin Pop
                          default=None, type="string", metavar="<ADDRESS>"),
687 a8083063 Iustin Pop
              make_option("-b", "--bridge", dest="bridge",
688 a8083063 Iustin Pop
                          help="Bridge to connect this instance to",
689 decd5f45 Iustin Pop
                          default=None, type="string", metavar="<bridge>"),
690 a8083063 Iustin Pop
              ],
691 a8083063 Iustin Pop
             "<instance>", "Alters the parameters of an instance"),
692 312ac745 Iustin Pop
  'shutdown': (ShutdownInstance, ARGS_ANY,
693 312ac745 Iustin Pop
               [DEBUG_OPT, m_node_opt, m_pri_node_opt, m_sec_node_opt,
694 312ac745 Iustin Pop
                m_clust_opt, m_inst_opt],
695 a8083063 Iustin Pop
               "<instance>", "Stops an instance"),
696 312ac745 Iustin Pop
  'startup': (StartupInstance, ARGS_ANY,
697 fe7b0351 Michael Hanselmann
              [DEBUG_OPT, FORCE_OPT,
698 a8083063 Iustin Pop
               make_option("-e", "--extra", dest="extra_args",
699 a8083063 Iustin Pop
                           help="Extra arguments for the instance's kernel",
700 a8083063 Iustin Pop
                           default=None, type="string", metavar="<PARAMS>"),
701 312ac745 Iustin Pop
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
702 312ac745 Iustin Pop
               m_clust_opt, m_inst_opt,
703 a8083063 Iustin Pop
               ],
704 a8083063 Iustin Pop
            "<instance>", "Starts an instance"),
705 a8083063 Iustin Pop
  'activate-disks': (ActivateDisks, ARGS_ONE, [DEBUG_OPT],
706 a8083063 Iustin Pop
                     "<instance>",
707 a8083063 Iustin Pop
                     "Activate an instance's disks"),
708 a8083063 Iustin Pop
  'deactivate-disks': (DeactivateDisks, ARGS_ONE, [DEBUG_OPT],
709 a8083063 Iustin Pop
                       "<instance>",
710 a8083063 Iustin Pop
                       "Deactivate an instance's disks"),
711 a8083063 Iustin Pop
  }
712 a8083063 Iustin Pop
713 a8083063 Iustin Pop
if __name__ == '__main__':
714 3ecf6786 Iustin Pop
  sys.exit(GenericMain(commands))