Statistics
| Branch: | Tag: | Revision:

root / scripts / gnt-backup @ 7d3a9fab

History | View | Annotate | Download (9.1 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 087ed2ed Iustin Pop
  BACKEND_OPT,
219 4f365444 Iustin Pop
  DISK_TEMPLATE_OPT,
220 552c8dff Michael Hanselmann
  cli_option("--disk", help="Disk information",
221 50a707fa Iustin Pop
             default=[], dest="disks",
222 50a707fa Iustin Pop
             action="append",
223 50a707fa Iustin Pop
             type="identkeyval"),
224 c0e4a2c3 Iustin Pop
  cli_option("-s", "--os-size", dest="sd_size", help="Disk size for a"
225 c0e4a2c3 Iustin Pop
             " single-disk configuration, when not using the --disk option,"
226 c0e4a2c3 Iustin Pop
             " in MiB unless a suffix is used",
227 c0e4a2c3 Iustin Pop
             default=None, type="unit", metavar="<size>"),
228 7d3a9fab Iustin Pop
  NET_OPT,
229 26023ecd Iustin Pop
  NONICS_OPT,
230 3f75b4f3 Iustin Pop
  NWSYNC_OPT,
231 c38c44ad Michael Hanselmann
  cli_option("--src-node", dest="src_node", help="Source node",
232 a52ba89d Michael Hanselmann
             metavar="<node>",
233 a52ba89d Michael Hanselmann
             completion_suggest=OPT_COMPL_ONE_NODE),
234 c38c44ad Michael Hanselmann
  cli_option("--src-dir", dest="src_dir", help="Source directory",
235 c38c44ad Michael Hanselmann
             metavar="<dir>"),
236 91e0748c Iustin Pop
  NOIPCHECK_OPT,
237 4eb62659 Iustin Pop
  IALLOCATOR_OPT,
238 4a25828c Iustin Pop
  FILESTORE_DIR_OPT,
239 0f87c43e Iustin Pop
  FILESTORE_DRIVER_OPT,
240 236fd9c4 Iustin Pop
  HYPERVISOR_OPT,
241 dd4b1106 Iustin Pop
  ]
242 dd4b1106 Iustin Pop
243 dd4b1106 Iustin Pop
commands = {
244 4a265c08 Michael Hanselmann
  'list': (PrintExportList, ARGS_NONE,
245 dd4b1106 Iustin Pop
           [DEBUG_OPT,
246 c38c44ad Michael Hanselmann
            cli_option("--node", dest="nodes", default=[], action="append",
247 c38c44ad Michael Hanselmann
                       help="List only backups stored on this node"
248 a52ba89d Michael Hanselmann
                            " (can be used multiple times)",
249 a52ba89d Michael Hanselmann
                       completion_suggest=OPT_COMPL_ONE_NODE),
250 dd4b1106 Iustin Pop
            ],
251 9a033156 Iustin Pop
           "", "Lists instance exports available in the ganeti cluster"),
252 4a265c08 Michael Hanselmann
  'export': (ExportInstance, ARGS_ONE_INSTANCE,
253 60d49723 Michael Hanselmann
             [DEBUG_OPT, FORCE_OPT,
254 c38c44ad Michael Hanselmann
              cli_option("-n", "--node", dest="node", help="Target node",
255 a52ba89d Michael Hanselmann
                         metavar="<node>",
256 a52ba89d Michael Hanselmann
                         completion_suggest=OPT_COMPL_ONE_NODE),
257 c38c44ad Michael Hanselmann
              cli_option("","--noshutdown", dest="shutdown",
258 c38c44ad Michael Hanselmann
                         action="store_false", default=True,
259 c38c44ad Michael Hanselmann
                         help="Don't shutdown the instance (unsafe)"), ],
260 9a033156 Iustin Pop
             "-n <target_node> [opts...] <name>",
261 dd4b1106 Iustin Pop
             "Exports an instance to an image"),
262 4a265c08 Michael Hanselmann
  'import': (ImportInstance, ARGS_ONE_INSTANCE, import_opts,
263 bdb7d4e8 Michael Hanselmann
             ("[...] -t disk-type -n node[:secondary-node]"
264 bdb7d4e8 Michael Hanselmann
              " <name>"),
265 dd4b1106 Iustin Pop
             "Imports an instance from an exported image"),
266 a8005e17 Michael Hanselmann
  'remove': (RemoveExport, [ArgUnknown(min=1, max=1)],
267 9ac99fda Guido Trotter
             [DEBUG_OPT],
268 9a033156 Iustin Pop
             "<name>",
269 9ac99fda Guido Trotter
             "Remove exports of named instance from the filesystem."),
270 dd4b1106 Iustin Pop
  }
271 dd4b1106 Iustin Pop
272 a8005e17 Michael Hanselmann
273 dd4b1106 Iustin Pop
if __name__ == '__main__':
274 3ecf6786 Iustin Pop
  sys.exit(GenericMain(commands))