Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-backup @ 0f87c43e

History | View | Annotate | Download (9.9 kB)

1 dd4b1106 Iustin Pop
#!/usr/bin/python
2 dd4b1106 Iustin Pop
#
3 dd4b1106 Iustin Pop
4 dd4b1106 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 dd4b1106 Iustin Pop
#
6 dd4b1106 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 dd4b1106 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 dd4b1106 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 dd4b1106 Iustin Pop
# (at your option) any later version.
10 dd4b1106 Iustin Pop
#
11 dd4b1106 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 dd4b1106 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 dd4b1106 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 dd4b1106 Iustin Pop
# General Public License for more details.
15 dd4b1106 Iustin Pop
#
16 dd4b1106 Iustin Pop
# You should have received a copy of the GNU General Public License
17 dd4b1106 Iustin Pop
# along with this program; if not, write to the Free Software
18 dd4b1106 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 dd4b1106 Iustin Pop
# 02110-1301, USA.
20 dd4b1106 Iustin Pop
21 dd4b1106 Iustin Pop
22 2f79bd34 Iustin Pop
# pylint: disable-msg=W0401,W0614
23 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
24 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
25 2f79bd34 Iustin Pop
26 dd4b1106 Iustin Pop
import sys
27 dd4b1106 Iustin Pop
28 dd4b1106 Iustin Pop
from ganeti.cli import *
29 dd4b1106 Iustin Pop
from ganeti import opcodes
30 dd4b1106 Iustin Pop
from ganeti import constants
31 50a707fa Iustin Pop
from ganeti import errors
32 50a707fa Iustin Pop
from ganeti import utils
33 dd4b1106 Iustin Pop
34 7c0d6283 Michael Hanselmann
35 e1d2aa39 Alexander Schreiber
_VALUE_TRUE = "true"
36 e1d2aa39 Alexander Schreiber
37 a8005e17 Michael Hanselmann
38 dd4b1106 Iustin Pop
def PrintExportList(opts, args):
39 dd4b1106 Iustin Pop
  """Prints a list of all the exported system images.
40 dd4b1106 Iustin Pop
41 48de3413 Iustin Pop
  @param opts: the command line options selected by the user
42 48de3413 Iustin Pop
  @type args: list
43 48de3413 Iustin Pop
  @param args: should be an empty list
44 48de3413 Iustin Pop
  @rtype: int
45 48de3413 Iustin Pop
  @return: the desired exit code
46 dd4b1106 Iustin Pop
47 dd4b1106 Iustin Pop
  """
48 77921a95 Iustin Pop
  exports = GetClient().QueryExports(opts.nodes, False)
49 d70b3058 Iustin Pop
  retcode = 0
50 dd4b1106 Iustin Pop
  for node in exports:
51 3a24c527 Iustin Pop
    ToStdout("Node: %s", node)
52 3a24c527 Iustin Pop
    ToStdout("Exports:")
53 461f0538 Guido Trotter
    if isinstance(exports[node], list):
54 461f0538 Guido Trotter
      for instance_name in exports[node]:
55 3a24c527 Iustin Pop
        ToStdout("\t%s", instance_name)
56 461f0538 Guido Trotter
    else:
57 3a24c527 Iustin Pop
      ToStdout("  Could not get exports list")
58 d70b3058 Iustin Pop
      retcode = 1
59 d70b3058 Iustin Pop
  return retcode
60 dd4b1106 Iustin Pop
61 dd4b1106 Iustin Pop
62 dd4b1106 Iustin Pop
def ExportInstance(opts, args):
63 dd4b1106 Iustin Pop
  """Export an instance to an image in the cluster.
64 dd4b1106 Iustin Pop
65 48de3413 Iustin Pop
  @param opts: the command line options selected by the user
66 48de3413 Iustin Pop
  @type args: list
67 48de3413 Iustin Pop
  @param args: should contain only one element, the name
68 48de3413 Iustin Pop
      of the instance to be exported
69 48de3413 Iustin Pop
  @rtype: int
70 48de3413 Iustin Pop
  @return: the desired exit code
71 dd4b1106 Iustin Pop
72 dd4b1106 Iustin Pop
  """
73 dd4b1106 Iustin Pop
  op = opcodes.OpExportInstance(instance_name=args[0],
74 dd4b1106 Iustin Pop
                                target_node=opts.node,
75 dd4b1106 Iustin Pop
                                shutdown=opts.shutdown)
76 dd4b1106 Iustin Pop
77 084f05a5 Iustin Pop
  fin_resu, dlist = SubmitOpCode(op)
78 084f05a5 Iustin Pop
  if not isinstance(dlist, list):
79 084f05a5 Iustin Pop
    ToStderr("Cannot parse execution results")
80 084f05a5 Iustin Pop
    return 1
81 084f05a5 Iustin Pop
  tot_dsk = len(dlist)
82 084f05a5 Iustin Pop
  # TODO: handle diskless instances
83 084f05a5 Iustin Pop
  if dlist.count(False) == 0:
84 084f05a5 Iustin Pop
    # all OK
85 084f05a5 Iustin Pop
    rcode = 0
86 084f05a5 Iustin Pop
  elif dlist.count(True) == 0:
87 084f05a5 Iustin Pop
    ToStderr("Error: No disks were backed up successfully."
88 084f05a5 Iustin Pop
             " The export doesn't have any valid data,"
89 084f05a5 Iustin Pop
             " it is recommended to retry the operation.")
90 084f05a5 Iustin Pop
    rcode = 1
91 084f05a5 Iustin Pop
  else:
92 084f05a5 Iustin Pop
    ToStderr("Partial export failure: %d disks backed up, %d disks failed.",
93 084f05a5 Iustin Pop
             dlist.count(True), dlist.count(False))
94 084f05a5 Iustin Pop
    rcode = 2
95 084f05a5 Iustin Pop
  if not fin_resu:
96 084f05a5 Iustin Pop
    rcode = 1
97 084f05a5 Iustin Pop
  return rcode
98 60d49723 Michael Hanselmann
99 dd4b1106 Iustin Pop
def ImportInstance(opts, args):
100 dd4b1106 Iustin Pop
  """Add an instance to the cluster.
101 dd4b1106 Iustin Pop
102 48de3413 Iustin Pop
  @param opts: the command line options selected by the user
103 48de3413 Iustin Pop
  @type args: list
104 48de3413 Iustin Pop
  @param args: should contain only one element, the new instance name
105 48de3413 Iustin Pop
  @rtype: int
106 48de3413 Iustin Pop
  @return: the desired exit code
107 dd4b1106 Iustin Pop
108 dd4b1106 Iustin Pop
  """
109 dd4b1106 Iustin Pop
  instance = args[0]
110 dd4b1106 Iustin Pop
111 60d49723 Michael Hanselmann
  (pnode, snode) = SplitNodeOption(opts.node)
112 60d49723 Michael Hanselmann
113 b03efa30 Guido Trotter
  hypervisor = None
114 b03efa30 Guido Trotter
  hvparams = {}
115 b03efa30 Guido Trotter
  if opts.hypervisor:
116 b03efa30 Guido Trotter
    hypervisor, hvparams = opts.hypervisor
117 b03efa30 Guido Trotter
118 50a707fa Iustin Pop
  if opts.nics:
119 50a707fa Iustin Pop
    try:
120 50a707fa Iustin Pop
      nic_max = max(int(nidx[0])+1 for nidx in opts.nics)
121 50a707fa Iustin Pop
    except ValueError, err:
122 50a707fa Iustin Pop
      raise errors.OpPrereqError("Invalid NIC index passed: %s" % str(err))
123 50a707fa Iustin Pop
    nics = [{}] * nic_max
124 dc922da0 Iustin Pop
    for nidx, ndict in opts.nics:
125 50a707fa Iustin Pop
      nidx = int(nidx)
126 8b46606c Guido Trotter
      if not isinstance(ndict, dict):
127 8b46606c Guido Trotter
        msg = "Invalid nic/%d value: expected dict, got %s" % (nidx, ndict)
128 8b46606c Guido Trotter
        raise errors.OpPrereqError(msg)
129 50a707fa Iustin Pop
      nics[nidx] = ndict
130 50a707fa Iustin Pop
  elif opts.no_nics:
131 50a707fa Iustin Pop
    # no nics
132 50a707fa Iustin Pop
    nics = []
133 50a707fa Iustin Pop
  else:
134 50a707fa Iustin Pop
    # default of one nic, all auto
135 50a707fa Iustin Pop
    nics = [{}]
136 50a707fa Iustin Pop
137 50a707fa Iustin Pop
  if opts.disk_template == constants.DT_DISKLESS:
138 c0e4a2c3 Iustin Pop
    if opts.disks or opts.sd_size is not None:
139 50a707fa Iustin Pop
      raise errors.OpPrereqError("Diskless instance but disk"
140 50a707fa Iustin Pop
                                 " information passed")
141 50a707fa Iustin Pop
    disks = []
142 50a707fa Iustin Pop
  else:
143 c0e4a2c3 Iustin Pop
    if not opts.disks and not opts.sd_size:
144 50a707fa Iustin Pop
      raise errors.OpPrereqError("No disk information specified")
145 c0e4a2c3 Iustin Pop
    if opts.disks and opts.sd_size is not None:
146 c0e4a2c3 Iustin Pop
      raise errors.OpPrereqError("Please use either the '--disk' or"
147 c0e4a2c3 Iustin Pop
                                 " '-s' option")
148 c0e4a2c3 Iustin Pop
    if opts.sd_size is not None:
149 c0e4a2c3 Iustin Pop
      opts.disks = [(0, {"size": opts.sd_size})]
150 50a707fa Iustin Pop
    try:
151 50a707fa Iustin Pop
      disk_max = max(int(didx[0])+1 for didx in opts.disks)
152 50a707fa Iustin Pop
    except ValueError, err:
153 50a707fa Iustin Pop
      raise errors.OpPrereqError("Invalid disk index passed: %s" % str(err))
154 50a707fa Iustin Pop
    disks = [{}] * disk_max
155 50a707fa Iustin Pop
    for didx, ddict in opts.disks:
156 50a707fa Iustin Pop
      didx = int(didx)
157 8b46606c Guido Trotter
      if not isinstance(ddict, dict):
158 8b46606c Guido Trotter
        msg = "Invalid disk/%d value: expected dict, got %s" % (didx, ddict)
159 8b46606c Guido Trotter
        raise errors.OpPrereqError(msg)
160 8b46606c Guido Trotter
      elif "size" not in ddict:
161 50a707fa Iustin Pop
        raise errors.OpPrereqError("Missing size for disk %d" % didx)
162 50a707fa Iustin Pop
      try:
163 50a707fa Iustin Pop
        ddict["size"] = utils.ParseUnit(ddict["size"])
164 50a707fa Iustin Pop
      except ValueError, err:
165 50a707fa Iustin Pop
        raise errors.OpPrereqError("Invalid disk size for disk %d: %s" %
166 50a707fa Iustin Pop
                                   (didx, err))
167 50a707fa Iustin Pop
      disks[didx] = ddict
168 50a707fa Iustin Pop
169 a5728081 Guido Trotter
  utils.ForceDictType(opts.beparams, constants.BES_PARAMETER_TYPES)
170 c0e4a2c3 Iustin Pop
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
171 b03efa30 Guido Trotter
172 338e51e8 Iustin Pop
  op = opcodes.OpCreateInstance(instance_name=instance,
173 dd4b1106 Iustin Pop
                                disk_template=opts.disk_template,
174 50a707fa Iustin Pop
                                disks=disks,
175 50a707fa Iustin Pop
                                nics=nics,
176 098c0958 Michael Hanselmann
                                mode=constants.INSTANCE_IMPORT,
177 60d49723 Michael Hanselmann
                                pnode=pnode, snode=snode,
178 338e51e8 Iustin Pop
                                ip_check=opts.ip_check,
179 50a707fa Iustin Pop
                                start=False,
180 dd4b1106 Iustin Pop
                                src_node=opts.src_node, src_path=opts.src_dir,
181 50a707fa Iustin Pop
                                wait_for_sync=opts.wait_for_sync,
182 93cb65c5 Manuel Franceschini
                                file_storage_dir=opts.file_storage_dir,
183 93cb65c5 Manuel Franceschini
                                file_driver=opts.file_driver,
184 e1d2aa39 Alexander Schreiber
                                iallocator=opts.iallocator,
185 b03efa30 Guido Trotter
                                hypervisor=hypervisor,
186 b03efa30 Guido Trotter
                                hvparams=hvparams,
187 b03efa30 Guido Trotter
                                beparams=opts.beparams)
188 e1d2aa39 Alexander Schreiber
189 dd4b1106 Iustin Pop
  SubmitOpCode(op)
190 dd4b1106 Iustin Pop
  return 0
191 dd4b1106 Iustin Pop
192 dd4b1106 Iustin Pop
193 9ac99fda Guido Trotter
def RemoveExport(opts, args):
194 9ac99fda Guido Trotter
  """Remove an export from the cluster.
195 9ac99fda Guido Trotter
196 48de3413 Iustin Pop
  @param opts: the command line options selected by the user
197 48de3413 Iustin Pop
  @type args: list
198 48de3413 Iustin Pop
  @param args: should contain only one element, the name of the
199 48de3413 Iustin Pop
      instance whose backup should be removed
200 48de3413 Iustin Pop
  @rtype: int
201 48de3413 Iustin Pop
  @return: the desired exit code
202 9ac99fda Guido Trotter
203 9ac99fda Guido Trotter
  """
204 9ac99fda Guido Trotter
  instance = args[0]
205 9ac99fda Guido Trotter
  op = opcodes.OpRemoveExport(instance_name=args[0])
206 9ac99fda Guido Trotter
207 9ac99fda Guido Trotter
  SubmitOpCode(op)
208 9ac99fda Guido Trotter
  return 0
209 9ac99fda Guido Trotter
210 9ac99fda Guido Trotter
211 dd4b1106 Iustin Pop
# this is defined separately due to readability only
212 dd4b1106 Iustin Pop
import_opts = [
213 dd4b1106 Iustin Pop
  DEBUG_OPT,
214 c38c44ad Michael Hanselmann
  cli_option("-n", "--node", dest="node",
215 c38c44ad Michael Hanselmann
             help="Target node and optional secondary node",
216 2d3ed64b Michael Hanselmann
             metavar="<pnode>[:<snode>]",
217 2d3ed64b Michael Hanselmann
             completion_suggest=OPT_COMPL_INST_ADD_NODES),
218 552c8dff Michael Hanselmann
  cli_option("-B", "--backend", dest="beparams",
219 552c8dff Michael Hanselmann
             type="keyval", default={},
220 552c8dff Michael Hanselmann
             help="Backend parameters"),
221 4f365444 Iustin Pop
  DISK_TEMPLATE_OPT,
222 552c8dff Michael Hanselmann
  cli_option("--disk", help="Disk information",
223 50a707fa Iustin Pop
             default=[], dest="disks",
224 50a707fa Iustin Pop
             action="append",
225 50a707fa Iustin Pop
             type="identkeyval"),
226 c0e4a2c3 Iustin Pop
  cli_option("-s", "--os-size", dest="sd_size", help="Disk size for a"
227 c0e4a2c3 Iustin Pop
             " single-disk configuration, when not using the --disk option,"
228 c0e4a2c3 Iustin Pop
             " in MiB unless a suffix is used",
229 c0e4a2c3 Iustin Pop
             default=None, type="unit", metavar="<size>"),
230 552c8dff Michael Hanselmann
  cli_option("--net", help="NIC information",
231 50a707fa Iustin Pop
             default=[], dest="nics",
232 50a707fa Iustin Pop
             action="append",
233 50a707fa Iustin Pop
             type="identkeyval"),
234 26023ecd Iustin Pop
  NONICS_OPT,
235 3f75b4f3 Iustin Pop
  NWSYNC_OPT,
236 c38c44ad Michael Hanselmann
  cli_option("--src-node", dest="src_node", help="Source node",
237 a52ba89d Michael Hanselmann
             metavar="<node>",
238 a52ba89d Michael Hanselmann
             completion_suggest=OPT_COMPL_ONE_NODE),
239 c38c44ad Michael Hanselmann
  cli_option("--src-dir", dest="src_dir", help="Source directory",
240 c38c44ad Michael Hanselmann
             metavar="<dir>"),
241 c38c44ad Michael Hanselmann
  cli_option("--no-ip-check", dest="ip_check", default=True,
242 c38c44ad Michael Hanselmann
             action="store_false", help="Don't check that the instance's IP"
243 c38c44ad Michael Hanselmann
             " is alive"),
244 c38c44ad Michael Hanselmann
  cli_option("-I", "--iallocator", metavar="<NAME>",
245 c38c44ad Michael Hanselmann
             help="Select nodes for the instance automatically using the"
246 a52ba89d Michael Hanselmann
             " <NAME> iallocator plugin", default=None, type="string",
247 a52ba89d Michael Hanselmann
             completion_suggest=OPT_COMPL_ONE_IALLOCATOR),
248 4a25828c Iustin Pop
  FILESTORE_DIR_OPT,
249 0f87c43e Iustin Pop
  FILESTORE_DRIVER_OPT,
250 552c8dff Michael Hanselmann
  cli_option("-H", "--hypervisor", dest="hypervisor",
251 c38c44ad Michael Hanselmann
             help="Hypervisor and hypervisor options, in the format"
252 c38c44ad Michael Hanselmann
             " hypervisor:option=value,option=value,...", default=None,
253 c38c44ad Michael Hanselmann
             type="identkeyval"),
254 dd4b1106 Iustin Pop
  ]
255 dd4b1106 Iustin Pop
256 dd4b1106 Iustin Pop
commands = {
257 4a265c08 Michael Hanselmann
  'list': (PrintExportList, ARGS_NONE,
258 dd4b1106 Iustin Pop
           [DEBUG_OPT,
259 c38c44ad Michael Hanselmann
            cli_option("--node", dest="nodes", default=[], action="append",
260 c38c44ad Michael Hanselmann
                       help="List only backups stored on this node"
261 a52ba89d Michael Hanselmann
                            " (can be used multiple times)",
262 a52ba89d Michael Hanselmann
                       completion_suggest=OPT_COMPL_ONE_NODE),
263 dd4b1106 Iustin Pop
            ],
264 9a033156 Iustin Pop
           "", "Lists instance exports available in the ganeti cluster"),
265 4a265c08 Michael Hanselmann
  'export': (ExportInstance, ARGS_ONE_INSTANCE,
266 60d49723 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT,
267 c38c44ad Michael Hanselmann
              cli_option("-n", "--node", dest="node", help="Target node",
268 a52ba89d Michael Hanselmann
                         metavar="<node>",
269 a52ba89d Michael Hanselmann
                         completion_suggest=OPT_COMPL_ONE_NODE),
270 c38c44ad Michael Hanselmann
              cli_option("","--noshutdown", dest="shutdown",
271 c38c44ad Michael Hanselmann
                         action="store_false", default=True,
272 c38c44ad Michael Hanselmann
                         help="Don't shutdown the instance (unsafe)"), ],
273 9a033156 Iustin Pop
             "-n <target_node> [opts...] <name>",
274 dd4b1106 Iustin Pop
             "Exports an instance to an image"),
275 4a265c08 Michael Hanselmann
  'import': (ImportInstance, ARGS_ONE_INSTANCE, import_opts,
276 bdb7d4e8 Michael Hanselmann
             ("[...] -t disk-type -n node[:secondary-node]"
277 bdb7d4e8 Michael Hanselmann
              " <name>"),
278 dd4b1106 Iustin Pop
             "Imports an instance from an exported image"),
279 a8005e17 Michael Hanselmann
  'remove': (RemoveExport, [ArgUnknown(min=1, max=1)],
280 9ac99fda Guido Trotter
             [DEBUG_OPT],
281 9a033156 Iustin Pop
             "<name>",
282 9ac99fda Guido Trotter
             "Remove exports of named instance from the filesystem."),
283 dd4b1106 Iustin Pop
  }
284 dd4b1106 Iustin Pop
285 a8005e17 Michael Hanselmann
286 dd4b1106 Iustin Pop
if __name__ == '__main__':
287 3ecf6786 Iustin Pop
  sys.exit(GenericMain(commands))