Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_cluster.py @ 3039e2dc

History | View | Annotate | Download (53.3 kB)

1 7b3e7d41 Michael Hanselmann
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 eeaa5f6c Bernardo Dal Seno
# Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 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 7260cfbe Iustin Pop
"""Cluster related commands"""
22 a8083063 Iustin Pop
23 b459a848 Andrea Spadaccini
# pylint: disable=W0401,W0613,W0614,C0103
24 2f79bd34 Iustin Pop
# W0401: Wildcard import ganeti.cli
25 2d54e29c Iustin Pop
# W0613: Unused argument, since all functions follow the same API
26 2f79bd34 Iustin Pop
# W0614: Unused import %s from wildcard import (since we need cli)
27 7260cfbe Iustin Pop
# C0103: Invalid name gnt-cluster
28 2f79bd34 Iustin Pop
29 ea9d3b40 Bernardo Dal Seno
from cStringIO import StringIO
30 b3989551 Iustin Pop
import os.path
31 95b2e626 Michael Hanselmann
import time
32 6d4a1656 Michael Hanselmann
import OpenSSL
33 66d1f035 René Nussbaumer
import itertools
34 a8083063 Iustin Pop
35 a8083063 Iustin Pop
from ganeti.cli import *
36 a8083063 Iustin Pop
from ganeti import opcodes
37 c2a62a33 Michael Hanselmann
from ganeti import constants
38 f4d4e184 Iustin Pop
from ganeti import errors
39 b63ed789 Iustin Pop
from ganeti import utils
40 a0c9f010 Michael Hanselmann
from ganeti import bootstrap
41 b3989551 Iustin Pop
from ganeti import ssh
42 d3cfe525 Guido Trotter
from ganeti import objects
43 1338f2b4 Balazs Lecz
from ganeti import uidpool
44 cea881e5 Michael Hanselmann
from ganeti import compat
45 66d1f035 René Nussbaumer
from ganeti import netutils
46 78e706bb Michael Hanselmann
from ganeti import pathutils
47 66d1f035 René Nussbaumer
48 66d1f035 René Nussbaumer
49 66d1f035 René Nussbaumer
ON_OPT = cli_option("--on", default=False,
50 66d1f035 René Nussbaumer
                    action="store_true", dest="on",
51 66d1f035 René Nussbaumer
                    help="Recover from an EPO")
52 66d1f035 René Nussbaumer
53 66d1f035 René Nussbaumer
GROUPS_OPT = cli_option("--groups", default=False,
54 5ae4945a Iustin Pop
                        action="store_true", dest="groups",
55 5ae4945a Iustin Pop
                        help="Arguments are node groups instead of nodes")
56 66d1f035 René Nussbaumer
57 6022a419 Iustin Pop
FORCE_FAILOVER = cli_option("--yes-do-it", dest="yes_do_it",
58 6022a419 Iustin Pop
                            help="Override interactive check for --no-voting",
59 6022a419 Iustin Pop
                            default=False, action="store_true")
60 6022a419 Iustin Pop
61 66d1f035 René Nussbaumer
_EPO_PING_INTERVAL = 30 # 30 seconds between pings
62 66d1f035 René Nussbaumer
_EPO_PING_TIMEOUT = 1 # 1 second
63 66d1f035 René Nussbaumer
_EPO_REACHABLE_TIMEOUT = 15 * 60 # 15 minutes
64 a8083063 Iustin Pop
65 a8083063 Iustin Pop
66 912737ba Helga Velroyen
def _CheckNoLvmStorageOptDeprecated(opts):
67 912737ba Helga Velroyen
  """Checks if the legacy option '--no-lvm-storage' is used.
68 912737ba Helga Velroyen

69 912737ba Helga Velroyen
  """
70 912737ba Helga Velroyen
  if not opts.lvm_storage:
71 912737ba Helga Velroyen
    ToStderr("The option --no-lvm-storage is no longer supported. If you want"
72 912737ba Helga Velroyen
             " to disable lvm-based storage cluster-wide, use the option"
73 912737ba Helga Velroyen
             " --enabled-disk-templates to disable all of these lvm-base disk "
74 912737ba Helga Velroyen
             "  templates: %s" %
75 912737ba Helga Velroyen
             utils.CommaJoin(utils.GetLvmDiskTemplates()))
76 912737ba Helga Velroyen
    return 1
77 912737ba Helga Velroyen
78 912737ba Helga Velroyen
79 4331f6cd Michael Hanselmann
@UsesRPC
80 a8083063 Iustin Pop
def InitCluster(opts, args):
81 a8083063 Iustin Pop
  """Initialize the cluster.
82 a8083063 Iustin Pop

83 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
84 469ee405 Iustin Pop
  @type args: list
85 469ee405 Iustin Pop
  @param args: should contain only one element, the desired
86 469ee405 Iustin Pop
      cluster name
87 469ee405 Iustin Pop
  @rtype: int
88 469ee405 Iustin Pop
  @return: the desired exit code
89 a8083063 Iustin Pop

90 a8083063 Iustin Pop
  """
91 912737ba Helga Velroyen
  if _CheckNoLvmStorageOptDeprecated(opts):
92 90b6aa3a Manuel Franceschini
    return 1
93 912737ba Helga Velroyen
  enabled_disk_templates = opts.enabled_disk_templates
94 912737ba Helga Velroyen
  if enabled_disk_templates:
95 912737ba Helga Velroyen
    enabled_disk_templates = enabled_disk_templates.split(",")
96 912737ba Helga Velroyen
  else:
97 decf86f9 Helga Velroyen
    enabled_disk_templates = constants.DEFAULT_ENABLED_DISK_TEMPLATES
98 90b6aa3a Manuel Franceschini
99 912737ba Helga Velroyen
  vg_name = None
100 912737ba Helga Velroyen
  if opts.vg_name is not None:
101 912737ba Helga Velroyen
    vg_name = opts.vg_name
102 912737ba Helga Velroyen
    if vg_name:
103 912737ba Helga Velroyen
      if not utils.IsLvmEnabled(enabled_disk_templates):
104 912737ba Helga Velroyen
        ToStdout("You specified a volume group with --vg-name, but you did not"
105 912737ba Helga Velroyen
                 " enable any disk template that uses lvm.")
106 912737ba Helga Velroyen
    else:
107 912737ba Helga Velroyen
      if utils.IsLvmEnabled(enabled_disk_templates):
108 912737ba Helga Velroyen
        ToStderr("LVM disk templates are enabled, but vg name not set.")
109 912737ba Helga Velroyen
        return 1
110 912737ba Helga Velroyen
  else:
111 912737ba Helga Velroyen
    if utils.IsLvmEnabled(enabled_disk_templates):
112 912737ba Helga Velroyen
      vg_name = constants.DEFAULT_VG
113 90b6aa3a Manuel Franceschini
114 ed14ed48 Luca Bigliardi
  if not opts.drbd_storage and opts.drbd_helper:
115 ed14ed48 Luca Bigliardi
    ToStderr("Options --no-drbd-storage and --drbd-usermode-helper conflict.")
116 ed14ed48 Luca Bigliardi
    return 1
117 ed14ed48 Luca Bigliardi
118 ed14ed48 Luca Bigliardi
  drbd_helper = opts.drbd_helper
119 ed14ed48 Luca Bigliardi
  if opts.drbd_storage and not opts.drbd_helper:
120 ed14ed48 Luca Bigliardi
    drbd_helper = constants.DEFAULT_DRBD_HELPER
121 ed14ed48 Luca Bigliardi
122 25be0c75 Guido Trotter
  master_netdev = opts.master_netdev
123 25be0c75 Guido Trotter
  if master_netdev is None:
124 25be0c75 Guido Trotter
    master_netdev = constants.DEFAULT_BRIDGE
125 25be0c75 Guido Trotter
126 ea3a925f Alexander Schreiber
  hvlist = opts.enabled_hypervisors
127 383a3591 Iustin Pop
  if hvlist is None:
128 383a3591 Iustin Pop
    hvlist = constants.DEFAULT_ENABLED_HYPERVISOR
129 066f465d Guido Trotter
  hvlist = hvlist.split(",")
130 ea3a925f Alexander Schreiber
131 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
132 ea3a925f Alexander Schreiber
  beparams = opts.beparams
133 b6a30b0d Guido Trotter
  nicparams = opts.nicparams
134 ea3a925f Alexander Schreiber
135 bc5d0215 Andrea Spadaccini
  diskparams = dict(opts.diskparams)
136 bc5d0215 Andrea Spadaccini
137 bc5d0215 Andrea Spadaccini
  # check the disk template types here, as we cannot rely on the type check done
138 bc5d0215 Andrea Spadaccini
  # by the opcode parameter types
139 bc5d0215 Andrea Spadaccini
  diskparams_keys = set(diskparams.keys())
140 bc5d0215 Andrea Spadaccini
  if not (diskparams_keys <= constants.DISK_TEMPLATES):
141 bc5d0215 Andrea Spadaccini
    unknown = utils.NiceSort(diskparams_keys - constants.DISK_TEMPLATES)
142 bc5d0215 Andrea Spadaccini
    ToStderr("Disk templates unknown: %s" % utils.CommaJoin(unknown))
143 bc5d0215 Andrea Spadaccini
    return 1
144 bc5d0215 Andrea Spadaccini
145 ea3a925f Alexander Schreiber
  # prepare beparams dict
146 d3cfe525 Guido Trotter
  beparams = objects.FillDict(constants.BEC_DEFAULTS, beparams)
147 b2e233a5 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_COMPAT)
148 ea3a925f Alexander Schreiber
149 b6a30b0d Guido Trotter
  # prepare nicparams dict
150 b6a30b0d Guido Trotter
  nicparams = objects.FillDict(constants.NICC_DEFAULTS, nicparams)
151 b6a30b0d Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
152 b6a30b0d Guido Trotter
153 6204ee71 René Nussbaumer
  # prepare ndparams dict
154 6204ee71 René Nussbaumer
  if opts.ndparams is None:
155 6204ee71 René Nussbaumer
    ndparams = dict(constants.NDC_DEFAULTS)
156 6204ee71 René Nussbaumer
  else:
157 6204ee71 René Nussbaumer
    ndparams = objects.FillDict(constants.NDC_DEFAULTS, opts.ndparams)
158 6204ee71 René Nussbaumer
    utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
159 6204ee71 René Nussbaumer
160 ea3a925f Alexander Schreiber
  # prepare hvparams dict
161 ea3a925f Alexander Schreiber
  for hv in constants.HYPER_TYPES:
162 ea3a925f Alexander Schreiber
    if hv not in hvparams:
163 ea3a925f Alexander Schreiber
      hvparams[hv] = {}
164 d3cfe525 Guido Trotter
    hvparams[hv] = objects.FillDict(constants.HVC_DEFAULTS[hv], hvparams[hv])
165 a5728081 Guido Trotter
    utils.ForceDictType(hvparams[hv], constants.HVS_PARAMETER_TYPES)
166 ea3a925f Alexander Schreiber
167 bc5d0215 Andrea Spadaccini
  # prepare diskparams dict
168 bc5d0215 Andrea Spadaccini
  for templ in constants.DISK_TEMPLATES:
169 bc5d0215 Andrea Spadaccini
    if templ not in diskparams:
170 bc5d0215 Andrea Spadaccini
      diskparams[templ] = {}
171 bc5d0215 Andrea Spadaccini
    diskparams[templ] = objects.FillDict(constants.DISK_DT_DEFAULTS[templ],
172 bc5d0215 Andrea Spadaccini
                                         diskparams[templ])
173 bc5d0215 Andrea Spadaccini
    utils.ForceDictType(diskparams[templ], constants.DISK_DT_TYPES)
174 bc5d0215 Andrea Spadaccini
175 18bb6d28 Agata Murawska
  # prepare ipolicy dict
176 eeaa5f6c Bernardo Dal Seno
  ipolicy = CreateIPolicyFromOpts(
177 976b78ba Iustin Pop
    ispecs_mem_size=opts.ispecs_mem_size,
178 976b78ba Iustin Pop
    ispecs_cpu_count=opts.ispecs_cpu_count,
179 976b78ba Iustin Pop
    ispecs_disk_count=opts.ispecs_disk_count,
180 976b78ba Iustin Pop
    ispecs_disk_size=opts.ispecs_disk_size,
181 976b78ba Iustin Pop
    ispecs_nic_count=opts.ispecs_nic_count,
182 d2d3935a Bernardo Dal Seno
    minmax_ispecs=opts.ipolicy_bounds_specs,
183 d2d3935a Bernardo Dal Seno
    std_ispecs=opts.ipolicy_std_specs,
184 976b78ba Iustin Pop
    ipolicy_disk_templates=opts.ipolicy_disk_templates,
185 976b78ba Iustin Pop
    ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio,
186 31d827d1 René Nussbaumer
    ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio,
187 976b78ba Iustin Pop
    fill_all=True)
188 18bb6d28 Agata Murawska
189 e32df528 Iustin Pop
  if opts.candidate_pool_size is None:
190 e32df528 Iustin Pop
    opts.candidate_pool_size = constants.MASTER_POOL_SIZE_DEFAULT
191 e32df528 Iustin Pop
192 e3646f22 Iustin Pop
  if opts.mac_prefix is None:
193 e3646f22 Iustin Pop
    opts.mac_prefix = constants.DEFAULT_MAC_PREFIX
194 e3646f22 Iustin Pop
195 39b0f0c2 Balazs Lecz
  uid_pool = opts.uid_pool
196 39b0f0c2 Balazs Lecz
  if uid_pool is not None:
197 39b0f0c2 Balazs Lecz
    uid_pool = uidpool.ParseUidPool(uid_pool)
198 39b0f0c2 Balazs Lecz
199 b883637f René Nussbaumer
  if opts.prealloc_wipe_disks is None:
200 b883637f René Nussbaumer
    opts.prealloc_wipe_disks = False
201 b883637f René Nussbaumer
202 bf689b7a Andrea Spadaccini
  external_ip_setup_script = opts.use_external_mip_script
203 bf689b7a Andrea Spadaccini
  if external_ip_setup_script is None:
204 bf689b7a Andrea Spadaccini
    external_ip_setup_script = False
205 bf689b7a Andrea Spadaccini
206 e7323b5e Manuel Franceschini
  try:
207 e7323b5e Manuel Franceschini
    primary_ip_version = int(opts.primary_ip_version)
208 e7323b5e Manuel Franceschini
  except (ValueError, TypeError), err:
209 e7323b5e Manuel Franceschini
    ToStderr("Invalid primary ip version value: %s" % str(err))
210 e7323b5e Manuel Franceschini
    return 1
211 e7323b5e Manuel Franceschini
212 5a8648eb Andrea Spadaccini
  master_netmask = opts.master_netmask
213 5a8648eb Andrea Spadaccini
  try:
214 5a8648eb Andrea Spadaccini
    if master_netmask is not None:
215 5a8648eb Andrea Spadaccini
      master_netmask = int(master_netmask)
216 5a8648eb Andrea Spadaccini
  except (ValueError, TypeError), err:
217 5a8648eb Andrea Spadaccini
    ToStderr("Invalid master netmask value: %s" % str(err))
218 5a8648eb Andrea Spadaccini
    return 1
219 5a8648eb Andrea Spadaccini
220 c4929a8b René Nussbaumer
  if opts.disk_state:
221 c4929a8b René Nussbaumer
    disk_state = utils.FlatToDict(opts.disk_state)
222 c4929a8b René Nussbaumer
  else:
223 c4929a8b René Nussbaumer
    disk_state = {}
224 c4929a8b René Nussbaumer
225 c4929a8b René Nussbaumer
  hv_state = dict(opts.hv_state)
226 c4929a8b René Nussbaumer
227 a0c9f010 Michael Hanselmann
  bootstrap.InitCluster(cluster_name=args[0],
228 a0c9f010 Michael Hanselmann
                        secondary_ip=opts.secondary_ip,
229 a0c9f010 Michael Hanselmann
                        vg_name=vg_name,
230 a0c9f010 Michael Hanselmann
                        mac_prefix=opts.mac_prefix,
231 5a8648eb Andrea Spadaccini
                        master_netmask=master_netmask,
232 25be0c75 Guido Trotter
                        master_netdev=master_netdev,
233 ea3a925f Alexander Schreiber
                        file_storage_dir=opts.file_storage_dir,
234 7925d409 Apollon Oikonomopoulos
                        shared_file_storage_dir=opts.shared_file_storage_dir,
235 ea3a925f Alexander Schreiber
                        enabled_hypervisors=hvlist,
236 ea3a925f Alexander Schreiber
                        hvparams=hvparams,
237 ce735215 Guido Trotter
                        beparams=beparams,
238 b6a30b0d Guido Trotter
                        nicparams=nicparams,
239 6204ee71 René Nussbaumer
                        ndparams=ndparams,
240 bc5d0215 Andrea Spadaccini
                        diskparams=diskparams,
241 18bb6d28 Agata Murawska
                        ipolicy=ipolicy,
242 ce735215 Guido Trotter
                        candidate_pool_size=opts.candidate_pool_size,
243 b86a6bcd Guido Trotter
                        modify_etc_hosts=opts.modify_etc_hosts,
244 b989b9d9 Ken Wehr
                        modify_ssh_setup=opts.modify_ssh_setup,
245 3953242f Iustin Pop
                        maintain_node_health=opts.maintain_node_health,
246 ed14ed48 Luca Bigliardi
                        drbd_helper=drbd_helper,
247 39b0f0c2 Balazs Lecz
                        uid_pool=uid_pool,
248 bf4af505 Apollon Oikonomopoulos
                        default_iallocator=opts.default_iallocator,
249 e7323b5e Manuel Franceschini
                        primary_ip_version=primary_ip_version,
250 b18ecea2 René Nussbaumer
                        prealloc_wipe_disks=opts.prealloc_wipe_disks,
251 bf689b7a Andrea Spadaccini
                        use_external_mip_script=external_ip_setup_script,
252 c4929a8b René Nussbaumer
                        hv_state=hv_state,
253 c4929a8b René Nussbaumer
                        disk_state=disk_state,
254 3bde79ee Helga Velroyen
                        enabled_disk_templates=enabled_disk_templates,
255 ce735215 Guido Trotter
                        )
256 bc84ffa7 Iustin Pop
  op = opcodes.OpClusterPostInit()
257 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
258 a8083063 Iustin Pop
  return 0
259 a8083063 Iustin Pop
260 a8083063 Iustin Pop
261 4331f6cd Michael Hanselmann
@UsesRPC
262 a8083063 Iustin Pop
def DestroyCluster(opts, args):
263 a8083063 Iustin Pop
  """Destroy the cluster.
264 a8083063 Iustin Pop

265 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
266 469ee405 Iustin Pop
  @type args: list
267 469ee405 Iustin Pop
  @param args: should be an empty list
268 469ee405 Iustin Pop
  @rtype: int
269 469ee405 Iustin Pop
  @return: the desired exit code
270 098c0958 Michael Hanselmann

271 a8083063 Iustin Pop
  """
272 a8083063 Iustin Pop
  if not opts.yes_do_it:
273 3a24c527 Iustin Pop
    ToStderr("Destroying a cluster is irreversible. If you really want"
274 3a24c527 Iustin Pop
             " destroy this cluster, supply the --yes-do-it option.")
275 a8083063 Iustin Pop
    return 1
276 a8083063 Iustin Pop
277 c6d43e9e Iustin Pop
  op = opcodes.OpClusterDestroy()
278 1c3231aa Thomas Thrainer
  master_uuid = SubmitOpCode(op, opts=opts)
279 140aa4a8 Iustin Pop
  # if we reached this, the opcode didn't fail; we can proceed to
280 140aa4a8 Iustin Pop
  # shutdown all the daemons
281 1c3231aa Thomas Thrainer
  bootstrap.FinalizeClusterDestroy(master_uuid)
282 a8083063 Iustin Pop
  return 0
283 a8083063 Iustin Pop
284 a8083063 Iustin Pop
285 07bd8a51 Iustin Pop
def RenameCluster(opts, args):
286 07bd8a51 Iustin Pop
  """Rename the cluster.
287 07bd8a51 Iustin Pop

288 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
289 469ee405 Iustin Pop
  @type args: list
290 469ee405 Iustin Pop
  @param args: should contain only one element, the new cluster name
291 469ee405 Iustin Pop
  @rtype: int
292 469ee405 Iustin Pop
  @return: the desired exit code
293 07bd8a51 Iustin Pop

294 07bd8a51 Iustin Pop
  """
295 6a016df9 Michael Hanselmann
  cl = GetClient()
296 6a016df9 Michael Hanselmann
297 6a016df9 Michael Hanselmann
  (cluster_name, ) = cl.QueryConfigValues(["cluster_name"])
298 6a016df9 Michael Hanselmann
299 6a016df9 Michael Hanselmann
  new_name = args[0]
300 07bd8a51 Iustin Pop
  if not opts.force:
301 6a016df9 Michael Hanselmann
    usertext = ("This will rename the cluster from '%s' to '%s'. If you are"
302 6a016df9 Michael Hanselmann
                " connected over the network to the cluster name, the"
303 6a016df9 Michael Hanselmann
                " operation is very dangerous as the IP address will be"
304 6a016df9 Michael Hanselmann
                " removed from the node and the change may not go through."
305 6a016df9 Michael Hanselmann
                " Continue?") % (cluster_name, new_name)
306 47988778 Iustin Pop
    if not AskUser(usertext):
307 07bd8a51 Iustin Pop
      return 1
308 07bd8a51 Iustin Pop
309 e126df25 Iustin Pop
  op = opcodes.OpClusterRename(name=new_name)
310 6a016df9 Michael Hanselmann
  result = SubmitOpCode(op, opts=opts, cl=cl)
311 6a016df9 Michael Hanselmann
312 48418fea Iustin Pop
  if result:
313 48418fea Iustin Pop
    ToStdout("Cluster renamed from '%s' to '%s'", cluster_name, result)
314 6a016df9 Michael Hanselmann
315 07bd8a51 Iustin Pop
  return 0
316 07bd8a51 Iustin Pop
317 07bd8a51 Iustin Pop
318 fb926117 Andrea Spadaccini
def ActivateMasterIp(opts, args):
319 fb926117 Andrea Spadaccini
  """Activates the master IP.
320 fb926117 Andrea Spadaccini

321 fb926117 Andrea Spadaccini
  """
322 fb926117 Andrea Spadaccini
  op = opcodes.OpClusterActivateMasterIp()
323 fb926117 Andrea Spadaccini
  SubmitOpCode(op)
324 fb926117 Andrea Spadaccini
  return 0
325 fb926117 Andrea Spadaccini
326 fb926117 Andrea Spadaccini
327 fb926117 Andrea Spadaccini
def DeactivateMasterIp(opts, args):
328 fb926117 Andrea Spadaccini
  """Deactivates the master IP.
329 fb926117 Andrea Spadaccini

330 fb926117 Andrea Spadaccini
  """
331 fb926117 Andrea Spadaccini
  if not opts.confirm:
332 fb926117 Andrea Spadaccini
    usertext = ("This will disable the master IP. All the open connections to"
333 fb926117 Andrea Spadaccini
                " the master IP will be closed. To reach the master you will"
334 fb926117 Andrea Spadaccini
                " need to use its node IP."
335 fb926117 Andrea Spadaccini
                " Continue?")
336 fb926117 Andrea Spadaccini
    if not AskUser(usertext):
337 fb926117 Andrea Spadaccini
      return 1
338 fb926117 Andrea Spadaccini
339 fb926117 Andrea Spadaccini
  op = opcodes.OpClusterDeactivateMasterIp()
340 fb926117 Andrea Spadaccini
  SubmitOpCode(op)
341 fb926117 Andrea Spadaccini
  return 0
342 fb926117 Andrea Spadaccini
343 fb926117 Andrea Spadaccini
344 afee0879 Iustin Pop
def RedistributeConfig(opts, args):
345 afee0879 Iustin Pop
  """Forces push of the cluster configuration.
346 afee0879 Iustin Pop

347 afee0879 Iustin Pop
  @param opts: the command line options selected by the user
348 afee0879 Iustin Pop
  @type args: list
349 afee0879 Iustin Pop
  @param args: empty list
350 afee0879 Iustin Pop
  @rtype: int
351 afee0879 Iustin Pop
  @return: the desired exit code
352 afee0879 Iustin Pop

353 afee0879 Iustin Pop
  """
354 d1240007 Iustin Pop
  op = opcodes.OpClusterRedistConf()
355 afee0879 Iustin Pop
  SubmitOrSend(op, opts)
356 afee0879 Iustin Pop
  return 0
357 afee0879 Iustin Pop
358 afee0879 Iustin Pop
359 a8083063 Iustin Pop
def ShowClusterVersion(opts, args):
360 a8083063 Iustin Pop
  """Write version of ganeti software to the standard output.
361 a8083063 Iustin Pop

362 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
363 469ee405 Iustin Pop
  @type args: list
364 469ee405 Iustin Pop
  @param args: should be an empty list
365 469ee405 Iustin Pop
  @rtype: int
366 469ee405 Iustin Pop
  @return: the desired exit code
367 a8083063 Iustin Pop

368 a8083063 Iustin Pop
  """
369 42ab9ac4 Iustin Pop
  cl = GetClient(query=True)
370 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
371 3a24c527 Iustin Pop
  ToStdout("Software version: %s", result["software_version"])
372 3a24c527 Iustin Pop
  ToStdout("Internode protocol: %s", result["protocol_version"])
373 3a24c527 Iustin Pop
  ToStdout("Configuration format: %s", result["config_version"])
374 3a24c527 Iustin Pop
  ToStdout("OS api version: %s", result["os_api_version"])
375 3a24c527 Iustin Pop
  ToStdout("Export interface: %s", result["export_version"])
376 a8083063 Iustin Pop
  return 0
377 a8083063 Iustin Pop
378 a8083063 Iustin Pop
379 a8083063 Iustin Pop
def ShowClusterMaster(opts, args):
380 a8083063 Iustin Pop
  """Write name of master node to the standard output.
381 a8083063 Iustin Pop

382 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
383 469ee405 Iustin Pop
  @type args: list
384 469ee405 Iustin Pop
  @param args: should be an empty list
385 469ee405 Iustin Pop
  @rtype: int
386 469ee405 Iustin Pop
  @return: the desired exit code
387 a8083063 Iustin Pop

388 a8083063 Iustin Pop
  """
389 8eb148ae Iustin Pop
  master = bootstrap.GetMaster()
390 8eb148ae Iustin Pop
  ToStdout(master)
391 a8083063 Iustin Pop
  return 0
392 a8083063 Iustin Pop
393 cac599f1 Michael Hanselmann
394 0e79564a Bernardo Dal Seno
def _FormatGroupedParams(paramsdict, roman=False):
395 0e79564a Bernardo Dal Seno
  """Format Grouped parameters (be, nic, disk) by group.
396 1094acda Guido Trotter

397 1094acda Guido Trotter
  @type paramsdict: dict of dicts
398 1094acda Guido Trotter
  @param paramsdict: {group: {param: value, ...}, ...}
399 0e79564a Bernardo Dal Seno
  @rtype: dict of dicts
400 0e79564a Bernardo Dal Seno
  @return: copy of the input dictionaries with strings as values
401 1094acda Guido Trotter

402 1094acda Guido Trotter
  """
403 0e79564a Bernardo Dal Seno
  ret = {}
404 0e79564a Bernardo Dal Seno
  for (item, val) in paramsdict.items():
405 664a9d73 René Nussbaumer
    if isinstance(val, dict):
406 0e79564a Bernardo Dal Seno
      ret[item] = _FormatGroupedParams(val, roman=roman)
407 d729e03a Guido Trotter
    elif roman and isinstance(val, int):
408 0e79564a Bernardo Dal Seno
      ret[item] = compat.TryToRoman(val)
409 664a9d73 René Nussbaumer
    else:
410 0e79564a Bernardo Dal Seno
      ret[item] = str(val)
411 0e79564a Bernardo Dal Seno
  return ret
412 a8083063 Iustin Pop
413 cac599f1 Michael Hanselmann
414 a8083063 Iustin Pop
def ShowClusterConfig(opts, args):
415 a8083063 Iustin Pop
  """Shows cluster information.
416 a8083063 Iustin Pop

417 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
418 469ee405 Iustin Pop
  @type args: list
419 469ee405 Iustin Pop
  @param args: should be an empty list
420 469ee405 Iustin Pop
  @rtype: int
421 469ee405 Iustin Pop
  @return: the desired exit code
422 469ee405 Iustin Pop

423 a8083063 Iustin Pop
  """
424 a2160e57 Iustin Pop
  cl = GetClient(query=True)
425 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
426 a8083063 Iustin Pop
427 c118d1f4 Michael Hanselmann
  if result["tags"]:
428 1f864b60 Iustin Pop
    tags = utils.CommaJoin(utils.NiceSort(result["tags"]))
429 c118d1f4 Michael Hanselmann
  else:
430 c118d1f4 Michael Hanselmann
    tags = "(none)"
431 5a3ab484 Iustin Pop
  if result["reserved_lvs"]:
432 5a3ab484 Iustin Pop
    reserved_lvs = utils.CommaJoin(result["reserved_lvs"])
433 5a3ab484 Iustin Pop
  else:
434 5a3ab484 Iustin Pop
    reserved_lvs = "(none)"
435 be499e31 Agata Murawska
436 df5e2a28 Klaus Aehlig
  enabled_hv = result["enabled_hypervisors"]
437 df5e2a28 Klaus Aehlig
  hvparams = dict((k, v) for k, v in result["hvparams"].iteritems()
438 df5e2a28 Klaus Aehlig
                  if k in enabled_hv)
439 df5e2a28 Klaus Aehlig
440 0e79564a Bernardo Dal Seno
  info = [
441 0e79564a Bernardo Dal Seno
    ("Cluster name", result["name"]),
442 0e79564a Bernardo Dal Seno
    ("Cluster UUID", result["uuid"]),
443 0e79564a Bernardo Dal Seno
444 0e79564a Bernardo Dal Seno
    ("Creation time", utils.FormatTime(result["ctime"])),
445 0e79564a Bernardo Dal Seno
    ("Modification time", utils.FormatTime(result["mtime"])),
446 0e79564a Bernardo Dal Seno
447 0e79564a Bernardo Dal Seno
    ("Master node", result["master"]),
448 0e79564a Bernardo Dal Seno
449 0e79564a Bernardo Dal Seno
    ("Architecture (this node)",
450 0e79564a Bernardo Dal Seno
     "%s (%s)" % (result["architecture"][0], result["architecture"][1])),
451 0e79564a Bernardo Dal Seno
452 0e79564a Bernardo Dal Seno
    ("Tags", tags),
453 0e79564a Bernardo Dal Seno
454 0e79564a Bernardo Dal Seno
    ("Default hypervisor", result["default_hypervisor"]),
455 df5e2a28 Klaus Aehlig
    ("Enabled hypervisors", utils.CommaJoin(enabled_hv)),
456 0e79564a Bernardo Dal Seno
457 df5e2a28 Klaus Aehlig
    ("Hypervisor parameters", _FormatGroupedParams(hvparams)),
458 0e79564a Bernardo Dal Seno
459 0e79564a Bernardo Dal Seno
    ("OS-specific hypervisor parameters",
460 0e79564a Bernardo Dal Seno
     _FormatGroupedParams(result["os_hvp"])),
461 0e79564a Bernardo Dal Seno
462 0e79564a Bernardo Dal Seno
    ("OS parameters", _FormatGroupedParams(result["osparams"])),
463 0e79564a Bernardo Dal Seno
464 0e79564a Bernardo Dal Seno
    ("Hidden OSes", utils.CommaJoin(result["hidden_os"])),
465 0e79564a Bernardo Dal Seno
    ("Blacklisted OSes", utils.CommaJoin(result["blacklisted_os"])),
466 0e79564a Bernardo Dal Seno
467 0e79564a Bernardo Dal Seno
    ("Cluster parameters", [
468 0e79564a Bernardo Dal Seno
      ("candidate pool size",
469 0e79564a Bernardo Dal Seno
       compat.TryToRoman(result["candidate_pool_size"],
470 0e79564a Bernardo Dal Seno
                         convert=opts.roman_integers)),
471 0e79564a Bernardo Dal Seno
      ("master netdev", result["master_netdev"]),
472 0e79564a Bernardo Dal Seno
      ("master netmask", result["master_netmask"]),
473 0e79564a Bernardo Dal Seno
      ("use external master IP address setup script",
474 0e79564a Bernardo Dal Seno
       result["use_external_mip_script"]),
475 0e79564a Bernardo Dal Seno
      ("lvm volume group", result["volume_group_name"]),
476 0e79564a Bernardo Dal Seno
      ("lvm reserved volumes", reserved_lvs),
477 0e79564a Bernardo Dal Seno
      ("drbd usermode helper", result["drbd_usermode_helper"]),
478 0e79564a Bernardo Dal Seno
      ("file storage path", result["file_storage_dir"]),
479 0e79564a Bernardo Dal Seno
      ("shared file storage path", result["shared_file_storage_dir"]),
480 0e79564a Bernardo Dal Seno
      ("maintenance of node health", result["maintain_node_health"]),
481 0e79564a Bernardo Dal Seno
      ("uid pool", uidpool.FormatUidPool(result["uid_pool"])),
482 0e79564a Bernardo Dal Seno
      ("default instance allocator", result["default_iallocator"]),
483 0e79564a Bernardo Dal Seno
      ("primary ip version", result["primary_ip_version"]),
484 0e79564a Bernardo Dal Seno
      ("preallocation wipe disks", result["prealloc_wipe_disks"]),
485 0e79564a Bernardo Dal Seno
      ("OS search path", utils.CommaJoin(pathutils.OS_SEARCH_PATH)),
486 0e79564a Bernardo Dal Seno
      ("ExtStorage Providers search path",
487 0e79564a Bernardo Dal Seno
       utils.CommaJoin(pathutils.ES_SEARCH_PATH)),
488 966e1580 Helga Velroyen
      ("enabled disk templates",
489 966e1580 Helga Velroyen
       utils.CommaJoin(result["enabled_disk_templates"])),
490 0e79564a Bernardo Dal Seno
      ]),
491 0e79564a Bernardo Dal Seno
492 0e79564a Bernardo Dal Seno
    ("Default node parameters",
493 0e79564a Bernardo Dal Seno
     _FormatGroupedParams(result["ndparams"], roman=opts.roman_integers)),
494 0e79564a Bernardo Dal Seno
495 0e79564a Bernardo Dal Seno
    ("Default instance parameters",
496 0e79564a Bernardo Dal Seno
     _FormatGroupedParams(result["beparams"], roman=opts.roman_integers)),
497 0e79564a Bernardo Dal Seno
498 0e79564a Bernardo Dal Seno
    ("Default nic parameters",
499 0e79564a Bernardo Dal Seno
     _FormatGroupedParams(result["nicparams"], roman=opts.roman_integers)),
500 0e79564a Bernardo Dal Seno
501 0e79564a Bernardo Dal Seno
    ("Default disk parameters",
502 0e79564a Bernardo Dal Seno
     _FormatGroupedParams(result["diskparams"], roman=opts.roman_integers)),
503 0e79564a Bernardo Dal Seno
504 0e79564a Bernardo Dal Seno
    ("Instance policy - limits for instances",
505 d00884a2 Bernardo Dal Seno
     FormatPolicyInfo(result["ipolicy"], None, True)),
506 0e79564a Bernardo Dal Seno
    ]
507 0e79564a Bernardo Dal Seno
508 0e79564a Bernardo Dal Seno
  PrintGenericInfo(info)
509 a8083063 Iustin Pop
  return 0
510 a8083063 Iustin Pop
511 a8083063 Iustin Pop
512 a8083063 Iustin Pop
def ClusterCopyFile(opts, args):
513 a8083063 Iustin Pop
  """Copy a file from master to some nodes.
514 a8083063 Iustin Pop

515 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
516 469ee405 Iustin Pop
  @type args: list
517 469ee405 Iustin Pop
  @param args: should contain only one element, the path of
518 469ee405 Iustin Pop
      the file to be copied
519 469ee405 Iustin Pop
  @rtype: int
520 469ee405 Iustin Pop
  @return: the desired exit code
521 a8083063 Iustin Pop

522 a8083063 Iustin Pop
  """
523 b3989551 Iustin Pop
  filename = args[0]
524 b3989551 Iustin Pop
  if not os.path.exists(filename):
525 debac808 Iustin Pop
    raise errors.OpPrereqError("No such filename '%s'" % filename,
526 debac808 Iustin Pop
                               errors.ECODE_INVAL)
527 b3989551 Iustin Pop
528 56bece1f Iustin Pop
  cl = GetClient()
529 56bece1f Iustin Pop
530 56bece1f Iustin Pop
  cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
531 56bece1f Iustin Pop
532 74adc100 Iustin Pop
  results = GetOnlineNodes(nodes=opts.nodes, cl=cl, filter_master=True,
533 b6e88032 Michael Hanselmann
                           secondary_ips=opts.use_replication_network,
534 b6e88032 Michael Hanselmann
                           nodegroup=opts.nodegroup)
535 e00ea635 Michael Hanselmann
536 224ff0f7 Michael Hanselmann
  srun = ssh.SshRunner(cluster_name)
537 b3989551 Iustin Pop
  for node in results:
538 b3989551 Iustin Pop
    if not srun.CopyFileToNode(node, filename):
539 3a24c527 Iustin Pop
      ToStderr("Copy of file %s to node %s failed", filename, node)
540 b3989551 Iustin Pop
541 a8083063 Iustin Pop
  return 0
542 a8083063 Iustin Pop
543 a8083063 Iustin Pop
544 a8083063 Iustin Pop
def RunClusterCommand(opts, args):
545 a8083063 Iustin Pop
  """Run a command on some nodes.
546 a8083063 Iustin Pop

547 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
548 469ee405 Iustin Pop
  @type args: list
549 469ee405 Iustin Pop
  @param args: should contain the command to be run and its arguments
550 469ee405 Iustin Pop
  @rtype: int
551 469ee405 Iustin Pop
  @return: the desired exit code
552 a8083063 Iustin Pop

553 a8083063 Iustin Pop
  """
554 56bece1f Iustin Pop
  cl = GetClient()
555 7688d0d3 Michael Hanselmann
556 a8083063 Iustin Pop
  command = " ".join(args)
557 4040a784 Iustin Pop
558 b6e88032 Michael Hanselmann
  nodes = GetOnlineNodes(nodes=opts.nodes, cl=cl, nodegroup=opts.nodegroup)
559 56bece1f Iustin Pop
560 56bece1f Iustin Pop
  cluster_name, master_node = cl.QueryConfigValues(["cluster_name",
561 56bece1f Iustin Pop
                                                    "master_node"])
562 b3989551 Iustin Pop
563 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
564 b3989551 Iustin Pop
565 7688d0d3 Michael Hanselmann
  # Make sure master node is at list end
566 b3989551 Iustin Pop
  if master_node in nodes:
567 b3989551 Iustin Pop
    nodes.remove(master_node)
568 b3989551 Iustin Pop
    nodes.append(master_node)
569 b3989551 Iustin Pop
570 b3989551 Iustin Pop
  for name in nodes:
571 052783ff Michael Hanselmann
    result = srun.Run(name, constants.SSH_LOGIN_USER, command)
572 d5b031dc Michael Hanselmann
573 d5b031dc Michael Hanselmann
    if opts.failure_only and result.exit_code == constants.EXIT_SUCCESS:
574 d5b031dc Michael Hanselmann
      # Do not output anything for successful commands
575 d5b031dc Michael Hanselmann
      continue
576 d5b031dc Michael Hanselmann
577 3a24c527 Iustin Pop
    ToStdout("------------------------------------------------")
578 a24aed2a Michael Hanselmann
    if opts.show_machine_names:
579 a24aed2a Michael Hanselmann
      for line in result.output.splitlines():
580 a24aed2a Michael Hanselmann
        ToStdout("%s: %s", name, line)
581 a24aed2a Michael Hanselmann
    else:
582 a24aed2a Michael Hanselmann
      ToStdout("node: %s", name)
583 a24aed2a Michael Hanselmann
      ToStdout("%s", result.output)
584 3a24c527 Iustin Pop
    ToStdout("return code = %s", result.exit_code)
585 b3989551 Iustin Pop
586 b3989551 Iustin Pop
  return 0
587 a8083063 Iustin Pop
588 a8083063 Iustin Pop
589 a8083063 Iustin Pop
def VerifyCluster(opts, args):
590 a8083063 Iustin Pop
  """Verify integrity of cluster, performing various test on nodes.
591 a8083063 Iustin Pop

592 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
593 469ee405 Iustin Pop
  @type args: list
594 469ee405 Iustin Pop
  @param args: should be an empty list
595 469ee405 Iustin Pop
  @rtype: int
596 469ee405 Iustin Pop
  @return: the desired exit code
597 a8083063 Iustin Pop

598 a8083063 Iustin Pop
  """
599 8d59409f Iustin Pop
  skip_checks = []
600 bf93ae69 Adeodato Simo
601 e54c4c5e Guido Trotter
  if opts.skip_nplusone_mem:
602 e54c4c5e Guido Trotter
    skip_checks.append(constants.VERIFY_NPLUSONE_MEM)
603 bf93ae69 Adeodato Simo
604 fcad7225 Michael Hanselmann
  cl = GetClient()
605 bf93ae69 Adeodato Simo
606 fcad7225 Michael Hanselmann
  op = opcodes.OpClusterVerify(verbose=opts.verbose,
607 fcad7225 Michael Hanselmann
                               error_codes=opts.error_codes,
608 fcad7225 Michael Hanselmann
                               debug_simulate_errors=opts.simulate_errors,
609 fcad7225 Michael Hanselmann
                               skip_checks=skip_checks,
610 93f2399e Andrea Spadaccini
                               ignore_errors=opts.ignore_errors,
611 fcad7225 Michael Hanselmann
                               group_name=opts.nodegroup)
612 fcad7225 Michael Hanselmann
  result = SubmitOpCode(op, cl=cl, opts=opts)
613 bf93ae69 Adeodato Simo
614 fcad7225 Michael Hanselmann
  # Keep track of submitted jobs
615 fcad7225 Michael Hanselmann
  jex = JobExecutor(cl=cl, opts=opts)
616 fcad7225 Michael Hanselmann
617 fcad7225 Michael Hanselmann
  for (status, job_id) in result[constants.JOB_IDS_KEY]:
618 fcad7225 Michael Hanselmann
    jex.AddJobId(None, status, job_id)
619 bf93ae69 Adeodato Simo
620 fcad7225 Michael Hanselmann
  results = jex.GetResults()
621 ebe6cf38 Michael Hanselmann
622 ebe6cf38 Michael Hanselmann
  (bad_jobs, bad_results) = \
623 ebe6cf38 Michael Hanselmann
    map(len,
624 ebe6cf38 Michael Hanselmann
        # Convert iterators to lists
625 ebe6cf38 Michael Hanselmann
        map(list,
626 ebe6cf38 Michael Hanselmann
            # Count errors
627 ebe6cf38 Michael Hanselmann
            map(compat.partial(itertools.ifilterfalse, bool),
628 ebe6cf38 Michael Hanselmann
                # Convert result to booleans in a tuple
629 ebe6cf38 Michael Hanselmann
                zip(*((job_success, len(op_results) == 1 and op_results[0])
630 ebe6cf38 Michael Hanselmann
                      for (job_success, op_results) in results)))))
631 ebe6cf38 Michael Hanselmann
632 ebe6cf38 Michael Hanselmann
  if bad_jobs == 0 and bad_results == 0:
633 fcad7225 Michael Hanselmann
    rcode = constants.EXIT_SUCCESS
634 e0508c86 Guido Trotter
  else:
635 fcad7225 Michael Hanselmann
    rcode = constants.EXIT_FAILURE
636 ebe6cf38 Michael Hanselmann
    if bad_jobs > 0:
637 ebe6cf38 Michael Hanselmann
      ToStdout("%s job(s) failed while verifying the cluster.", bad_jobs)
638 fcad7225 Michael Hanselmann
639 fcad7225 Michael Hanselmann
  return rcode
640 a8083063 Iustin Pop
641 a8083063 Iustin Pop
642 f4d4e184 Iustin Pop
def VerifyDisks(opts, args):
643 f4d4e184 Iustin Pop
  """Verify integrity of cluster disks.
644 f4d4e184 Iustin Pop

645 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
646 469ee405 Iustin Pop
  @type args: list
647 469ee405 Iustin Pop
  @param args: should be an empty list
648 469ee405 Iustin Pop
  @rtype: int
649 469ee405 Iustin Pop
  @return: the desired exit code
650 f4d4e184 Iustin Pop

651 f4d4e184 Iustin Pop
  """
652 f1b083ce Michael Hanselmann
  cl = GetClient()
653 f1b083ce Michael Hanselmann
654 bd8210a7 Iustin Pop
  op = opcodes.OpClusterVerifyDisks()
655 f4d4e184 Iustin Pop
656 ae1a845c Michael Hanselmann
  result = SubmitOpCode(op, cl=cl, opts=opts)
657 ae1a845c Michael Hanselmann
658 ae1a845c Michael Hanselmann
  # Keep track of submitted jobs
659 ae1a845c Michael Hanselmann
  jex = JobExecutor(cl=cl, opts=opts)
660 ae1a845c Michael Hanselmann
661 ae1a845c Michael Hanselmann
  for (status, job_id) in result[constants.JOB_IDS_KEY]:
662 ae1a845c Michael Hanselmann
    jex.AddJobId(None, status, job_id)
663 b63ed789 Iustin Pop
664 f4d4e184 Iustin Pop
  retcode = constants.EXIT_SUCCESS
665 b63ed789 Iustin Pop
666 ae1a845c Michael Hanselmann
  for (status, result) in jex.GetResults():
667 ae1a845c Michael Hanselmann
    if not status:
668 ae1a845c Michael Hanselmann
      ToStdout("Job failed: %s", result)
669 ae1a845c Michael Hanselmann
      continue
670 ae1a845c Michael Hanselmann
671 ae1a845c Michael Hanselmann
    ((bad_nodes, instances, missing), ) = result
672 ae1a845c Michael Hanselmann
673 29d376ec Iustin Pop
    for node, text in bad_nodes.items():
674 29d376ec Iustin Pop
      ToStdout("Error gathering data on node %s: %s",
675 26f15862 Iustin Pop
               node, utils.SafeEncode(text[-400:]))
676 ae1a845c Michael Hanselmann
      retcode = constants.EXIT_FAILURE
677 3a24c527 Iustin Pop
      ToStdout("You need to fix these nodes first before fixing instances")
678 b63ed789 Iustin Pop
679 f4d4e184 Iustin Pop
    for iname in instances:
680 b63ed789 Iustin Pop
      if iname in missing:
681 b63ed789 Iustin Pop
        continue
682 83f5d475 Iustin Pop
      op = opcodes.OpInstanceActivateDisks(instance_name=iname)
683 f4d4e184 Iustin Pop
      try:
684 3a24c527 Iustin Pop
        ToStdout("Activating disks for instance '%s'", iname)
685 f1b083ce Michael Hanselmann
        SubmitOpCode(op, opts=opts, cl=cl)
686 f4d4e184 Iustin Pop
      except errors.GenericError, err:
687 f4d4e184 Iustin Pop
        nret, msg = FormatError(err)
688 f4d4e184 Iustin Pop
        retcode |= nret
689 3a24c527 Iustin Pop
        ToStderr("Error activating disks for instance %s: %s", iname, msg)
690 b63ed789 Iustin Pop
691 ae1a845c Michael Hanselmann
    if missing:
692 ae1a845c Michael Hanselmann
      for iname, ival in missing.iteritems():
693 ae1a845c Michael Hanselmann
        all_missing = compat.all(x[0] in bad_nodes for x in ival)
694 ae1a845c Michael Hanselmann
        if all_missing:
695 ae1a845c Michael Hanselmann
          ToStdout("Instance %s cannot be verified as it lives on"
696 ae1a845c Michael Hanselmann
                   " broken nodes", iname)
697 ae1a845c Michael Hanselmann
        else:
698 ae1a845c Michael Hanselmann
          ToStdout("Instance %s has missing logical volumes:", iname)
699 ae1a845c Michael Hanselmann
          ival.sort()
700 ae1a845c Michael Hanselmann
          for node, vol in ival:
701 ae1a845c Michael Hanselmann
            if node in bad_nodes:
702 ae1a845c Michael Hanselmann
              ToStdout("\tbroken node %s /dev/%s", node, vol)
703 ae1a845c Michael Hanselmann
            else:
704 ae1a845c Michael Hanselmann
              ToStdout("\t%s /dev/%s", node, vol)
705 ae1a845c Michael Hanselmann
706 ae1a845c Michael Hanselmann
      ToStdout("You need to replace or recreate disks for all the above"
707 ae1a845c Michael Hanselmann
               " instances if this message persists after fixing broken nodes.")
708 ae1a845c Michael Hanselmann
      retcode = constants.EXIT_FAILURE
709 9b99be28 Michael Hanselmann
    elif not instances:
710 9b99be28 Michael Hanselmann
      ToStdout("No disks need to be activated.")
711 f4d4e184 Iustin Pop
712 f4d4e184 Iustin Pop
  return retcode
713 f4d4e184 Iustin Pop
714 f4d4e184 Iustin Pop
715 60975797 Iustin Pop
def RepairDiskSizes(opts, args):
716 60975797 Iustin Pop
  """Verify sizes of cluster disks.
717 60975797 Iustin Pop

718 60975797 Iustin Pop
  @param opts: the command line options selected by the user
719 60975797 Iustin Pop
  @type args: list
720 60975797 Iustin Pop
  @param args: optional list of instances to restrict check to
721 60975797 Iustin Pop
  @rtype: int
722 60975797 Iustin Pop
  @return: the desired exit code
723 60975797 Iustin Pop

724 60975797 Iustin Pop
  """
725 5d01aca3 Iustin Pop
  op = opcodes.OpClusterRepairDiskSizes(instances=args)
726 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
727 60975797 Iustin Pop
728 60975797 Iustin Pop
729 4331f6cd Michael Hanselmann
@UsesRPC
730 a8083063 Iustin Pop
def MasterFailover(opts, args):
731 a8083063 Iustin Pop
  """Failover the master node.
732 a8083063 Iustin Pop

733 a8083063 Iustin Pop
  This command, when run on a non-master node, will cause the current
734 a8083063 Iustin Pop
  master to cease being master, and the non-master to become new
735 a8083063 Iustin Pop
  master.
736 a8083063 Iustin Pop

737 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
738 469ee405 Iustin Pop
  @type args: list
739 469ee405 Iustin Pop
  @param args: should be an empty list
740 469ee405 Iustin Pop
  @rtype: int
741 469ee405 Iustin Pop
  @return: the desired exit code
742 469ee405 Iustin Pop

743 a8083063 Iustin Pop
  """
744 6022a419 Iustin Pop
  if opts.no_voting and not opts.yes_do_it:
745 8e2524c3 Guido Trotter
    usertext = ("This will perform the failover even if most other nodes"
746 8e2524c3 Guido Trotter
                " are down, or if this node is outdated. This is dangerous"
747 8e2524c3 Guido Trotter
                " as it can lead to a non-consistent cluster. Check the"
748 8e2524c3 Guido Trotter
                " gnt-cluster(8) man page before proceeding. Continue?")
749 8e2524c3 Guido Trotter
    if not AskUser(usertext):
750 8e2524c3 Guido Trotter
      return 1
751 8e2524c3 Guido Trotter
752 8e2524c3 Guido Trotter
  return bootstrap.MasterFailover(no_voting=opts.no_voting)
753 a8083063 Iustin Pop
754 a8083063 Iustin Pop
755 4404ffad Iustin Pop
def MasterPing(opts, args):
756 4404ffad Iustin Pop
  """Checks if the master is alive.
757 4404ffad Iustin Pop

758 4404ffad Iustin Pop
  @param opts: the command line options selected by the user
759 4404ffad Iustin Pop
  @type args: list
760 4404ffad Iustin Pop
  @param args: should be an empty list
761 4404ffad Iustin Pop
  @rtype: int
762 4404ffad Iustin Pop
  @return: the desired exit code
763 4404ffad Iustin Pop

764 4404ffad Iustin Pop
  """
765 4404ffad Iustin Pop
  try:
766 4404ffad Iustin Pop
    cl = GetClient()
767 4404ffad Iustin Pop
    cl.QueryClusterInfo()
768 4404ffad Iustin Pop
    return 0
769 b459a848 Andrea Spadaccini
  except Exception: # pylint: disable=W0703
770 4404ffad Iustin Pop
    return 1
771 4404ffad Iustin Pop
772 4404ffad Iustin Pop
773 73415719 Iustin Pop
def SearchTags(opts, args):
774 73415719 Iustin Pop
  """Searches the tags on all the cluster.
775 73415719 Iustin Pop

776 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
777 469ee405 Iustin Pop
  @type args: list
778 469ee405 Iustin Pop
  @param args: should contain only one element, the tag pattern
779 469ee405 Iustin Pop
  @rtype: int
780 469ee405 Iustin Pop
  @return: the desired exit code
781 469ee405 Iustin Pop

782 73415719 Iustin Pop
  """
783 715462e7 Iustin Pop
  op = opcodes.OpTagsSearch(pattern=args[0])
784 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
785 73415719 Iustin Pop
  if not result:
786 73415719 Iustin Pop
    return 1
787 73415719 Iustin Pop
  result = list(result)
788 73415719 Iustin Pop
  result.sort()
789 73415719 Iustin Pop
  for path, tag in result:
790 3a24c527 Iustin Pop
    ToStdout("%s %s", path, tag)
791 73415719 Iustin Pop
792 73415719 Iustin Pop
793 b6267745 Andrea Spadaccini
def _ReadAndVerifyCert(cert_filename, verify_private_key=False):
794 b6267745 Andrea Spadaccini
  """Reads and verifies an X509 certificate.
795 b6267745 Andrea Spadaccini

796 b6267745 Andrea Spadaccini
  @type cert_filename: string
797 b6267745 Andrea Spadaccini
  @param cert_filename: the path of the file containing the certificate to
798 b6267745 Andrea Spadaccini
                        verify encoded in PEM format
799 b6267745 Andrea Spadaccini
  @type verify_private_key: bool
800 b6267745 Andrea Spadaccini
  @param verify_private_key: whether to verify the private key in addition to
801 b6267745 Andrea Spadaccini
                             the public certificate
802 b6267745 Andrea Spadaccini
  @rtype: string
803 b6267745 Andrea Spadaccini
  @return: a string containing the PEM-encoded certificate.
804 b6267745 Andrea Spadaccini

805 b6267745 Andrea Spadaccini
  """
806 b6267745 Andrea Spadaccini
  try:
807 b6267745 Andrea Spadaccini
    pem = utils.ReadFile(cert_filename)
808 b6267745 Andrea Spadaccini
  except IOError, err:
809 b6267745 Andrea Spadaccini
    raise errors.X509CertError(cert_filename,
810 b6267745 Andrea Spadaccini
                               "Unable to read certificate: %s" % str(err))
811 b6267745 Andrea Spadaccini
812 b6267745 Andrea Spadaccini
  try:
813 b6267745 Andrea Spadaccini
    OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem)
814 b6267745 Andrea Spadaccini
  except Exception, err:
815 b6267745 Andrea Spadaccini
    raise errors.X509CertError(cert_filename,
816 b6267745 Andrea Spadaccini
                               "Unable to load certificate: %s" % str(err))
817 b6267745 Andrea Spadaccini
818 b6267745 Andrea Spadaccini
  if verify_private_key:
819 b6267745 Andrea Spadaccini
    try:
820 b6267745 Andrea Spadaccini
      OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, pem)
821 b6267745 Andrea Spadaccini
    except Exception, err:
822 b6267745 Andrea Spadaccini
      raise errors.X509CertError(cert_filename,
823 b6267745 Andrea Spadaccini
                                 "Unable to load private key: %s" % str(err))
824 b6267745 Andrea Spadaccini
825 b6267745 Andrea Spadaccini
  return pem
826 b6267745 Andrea Spadaccini
827 b6267745 Andrea Spadaccini
828 5ae4945a Iustin Pop
def _RenewCrypto(new_cluster_cert, new_rapi_cert, # pylint: disable=R0911
829 b6267745 Andrea Spadaccini
                 rapi_cert_filename, new_spice_cert, spice_cert_filename,
830 b6267745 Andrea Spadaccini
                 spice_cacert_filename, new_confd_hmac_key, new_cds,
831 b6267745 Andrea Spadaccini
                 cds_filename, force):
832 6d4a1656 Michael Hanselmann
  """Renews cluster certificates, keys and secrets.
833 6d4a1656 Michael Hanselmann

834 6d4a1656 Michael Hanselmann
  @type new_cluster_cert: bool
835 6d4a1656 Michael Hanselmann
  @param new_cluster_cert: Whether to generate a new cluster certificate
836 6d4a1656 Michael Hanselmann
  @type new_rapi_cert: bool
837 6d4a1656 Michael Hanselmann
  @param new_rapi_cert: Whether to generate a new RAPI certificate
838 6d4a1656 Michael Hanselmann
  @type rapi_cert_filename: string
839 6d4a1656 Michael Hanselmann
  @param rapi_cert_filename: Path to file containing new RAPI certificate
840 b6267745 Andrea Spadaccini
  @type new_spice_cert: bool
841 b6267745 Andrea Spadaccini
  @param new_spice_cert: Whether to generate a new SPICE certificate
842 b6267745 Andrea Spadaccini
  @type spice_cert_filename: string
843 b6267745 Andrea Spadaccini
  @param spice_cert_filename: Path to file containing new SPICE certificate
844 b6267745 Andrea Spadaccini
  @type spice_cacert_filename: string
845 b6267745 Andrea Spadaccini
  @param spice_cacert_filename: Path to file containing the certificate of the
846 b6267745 Andrea Spadaccini
                                CA that signed the SPICE certificate
847 6b7d5878 Michael Hanselmann
  @type new_confd_hmac_key: bool
848 6b7d5878 Michael Hanselmann
  @param new_confd_hmac_key: Whether to generate a new HMAC key
849 3db3eb2a Michael Hanselmann
  @type new_cds: bool
850 3db3eb2a Michael Hanselmann
  @param new_cds: Whether to generate a new cluster domain secret
851 3db3eb2a Michael Hanselmann
  @type cds_filename: string
852 3db3eb2a Michael Hanselmann
  @param cds_filename: Path to file containing new cluster domain secret
853 6d4a1656 Michael Hanselmann
  @type force: bool
854 6d4a1656 Michael Hanselmann
  @param force: Whether to ask user for confirmation
855 6d4a1656 Michael Hanselmann

856 6d4a1656 Michael Hanselmann
  """
857 6d4a1656 Michael Hanselmann
  if new_rapi_cert and rapi_cert_filename:
858 6e060e15 Andrea Spadaccini
    ToStderr("Only one of the --new-rapi-certificate and --rapi-certificate"
859 6d4a1656 Michael Hanselmann
             " options can be specified at the same time.")
860 6d4a1656 Michael Hanselmann
    return 1
861 6d4a1656 Michael Hanselmann
862 3db3eb2a Michael Hanselmann
  if new_cds and cds_filename:
863 3db3eb2a Michael Hanselmann
    ToStderr("Only one of the --new-cluster-domain-secret and"
864 3db3eb2a Michael Hanselmann
             " --cluster-domain-secret options can be specified at"
865 3db3eb2a Michael Hanselmann
             " the same time.")
866 3db3eb2a Michael Hanselmann
    return 1
867 3db3eb2a Michael Hanselmann
868 b6267745 Andrea Spadaccini
  if new_spice_cert and (spice_cert_filename or spice_cacert_filename):
869 b6267745 Andrea Spadaccini
    ToStderr("When using --new-spice-certificate, the --spice-certificate"
870 b6267745 Andrea Spadaccini
             " and --spice-ca-certificate must not be used.")
871 b6267745 Andrea Spadaccini
    return 1
872 6d4a1656 Michael Hanselmann
873 b6267745 Andrea Spadaccini
  if bool(spice_cacert_filename) ^ bool(spice_cert_filename):
874 b6267745 Andrea Spadaccini
    ToStderr("Both --spice-certificate and --spice-ca-certificate must be"
875 b6267745 Andrea Spadaccini
             " specified.")
876 b6267745 Andrea Spadaccini
    return 1
877 6d4a1656 Michael Hanselmann
878 b6267745 Andrea Spadaccini
  rapi_cert_pem, spice_cert_pem, spice_cacert_pem = (None, None, None)
879 b6267745 Andrea Spadaccini
  try:
880 b6267745 Andrea Spadaccini
    if rapi_cert_filename:
881 b6267745 Andrea Spadaccini
      rapi_cert_pem = _ReadAndVerifyCert(rapi_cert_filename, True)
882 b6267745 Andrea Spadaccini
    if spice_cert_filename:
883 b6267745 Andrea Spadaccini
      spice_cert_pem = _ReadAndVerifyCert(spice_cert_filename, True)
884 b6267745 Andrea Spadaccini
      spice_cacert_pem = _ReadAndVerifyCert(spice_cacert_filename)
885 b6267745 Andrea Spadaccini
  except errors.X509CertError, err:
886 b6267745 Andrea Spadaccini
    ToStderr("Unable to load X509 certificate from %s: %s", err[0], err[1])
887 b6267745 Andrea Spadaccini
    return 1
888 6d4a1656 Michael Hanselmann
889 3db3eb2a Michael Hanselmann
  if cds_filename:
890 3db3eb2a Michael Hanselmann
    try:
891 3db3eb2a Michael Hanselmann
      cds = utils.ReadFile(cds_filename)
892 b459a848 Andrea Spadaccini
    except Exception, err: # pylint: disable=W0703
893 3db3eb2a Michael Hanselmann
      ToStderr("Can't load new cluster domain secret from %s: %s" %
894 3db3eb2a Michael Hanselmann
               (cds_filename, str(err)))
895 3db3eb2a Michael Hanselmann
      return 1
896 3db3eb2a Michael Hanselmann
  else:
897 3db3eb2a Michael Hanselmann
    cds = None
898 3db3eb2a Michael Hanselmann
899 6d4a1656 Michael Hanselmann
  if not force:
900 6d4a1656 Michael Hanselmann
    usertext = ("This requires all daemons on all nodes to be restarted and"
901 6d4a1656 Michael Hanselmann
                " may take some time. Continue?")
902 6d4a1656 Michael Hanselmann
    if not AskUser(usertext):
903 6d4a1656 Michael Hanselmann
      return 1
904 6d4a1656 Michael Hanselmann
905 6d4a1656 Michael Hanselmann
  def _RenewCryptoInner(ctx):
906 6d4a1656 Michael Hanselmann
    ctx.feedback_fn("Updating certificates and keys")
907 b6267745 Andrea Spadaccini
    bootstrap.GenerateClusterCrypto(new_cluster_cert,
908 b6267745 Andrea Spadaccini
                                    new_rapi_cert,
909 b6267745 Andrea Spadaccini
                                    new_spice_cert,
910 6b7d5878 Michael Hanselmann
                                    new_confd_hmac_key,
911 3db3eb2a Michael Hanselmann
                                    new_cds,
912 3db3eb2a Michael Hanselmann
                                    rapi_cert_pem=rapi_cert_pem,
913 b6267745 Andrea Spadaccini
                                    spice_cert_pem=spice_cert_pem,
914 b6267745 Andrea Spadaccini
                                    spice_cacert_pem=spice_cacert_pem,
915 3db3eb2a Michael Hanselmann
                                    cds=cds)
916 6d4a1656 Michael Hanselmann
917 6d4a1656 Michael Hanselmann
    files_to_copy = []
918 6d4a1656 Michael Hanselmann
919 6d4a1656 Michael Hanselmann
    if new_cluster_cert:
920 78e706bb Michael Hanselmann
      files_to_copy.append(pathutils.NODED_CERT_FILE)
921 6d4a1656 Michael Hanselmann
922 6d4a1656 Michael Hanselmann
    if new_rapi_cert or rapi_cert_pem:
923 78e706bb Michael Hanselmann
      files_to_copy.append(pathutils.RAPI_CERT_FILE)
924 6d4a1656 Michael Hanselmann
925 b6267745 Andrea Spadaccini
    if new_spice_cert or spice_cert_pem:
926 78e706bb Michael Hanselmann
      files_to_copy.append(pathutils.SPICE_CERT_FILE)
927 78e706bb Michael Hanselmann
      files_to_copy.append(pathutils.SPICE_CACERT_FILE)
928 b6267745 Andrea Spadaccini
929 6b7d5878 Michael Hanselmann
    if new_confd_hmac_key:
930 78e706bb Michael Hanselmann
      files_to_copy.append(pathutils.CONFD_HMAC_KEY)
931 6d4a1656 Michael Hanselmann
932 3db3eb2a Michael Hanselmann
    if new_cds or cds:
933 78e706bb Michael Hanselmann
      files_to_copy.append(pathutils.CLUSTER_DOMAIN_SECRET_FILE)
934 3db3eb2a Michael Hanselmann
935 6d4a1656 Michael Hanselmann
    if files_to_copy:
936 6d4a1656 Michael Hanselmann
      for node_name in ctx.nonmaster_nodes:
937 6d4a1656 Michael Hanselmann
        ctx.feedback_fn("Copying %s to %s" %
938 6d4a1656 Michael Hanselmann
                        (", ".join(files_to_copy), node_name))
939 6d4a1656 Michael Hanselmann
        for file_name in files_to_copy:
940 6d4a1656 Michael Hanselmann
          ctx.ssh.CopyFileToNode(node_name, file_name)
941 6d4a1656 Michael Hanselmann
942 6d4a1656 Michael Hanselmann
  RunWhileClusterStopped(ToStdout, _RenewCryptoInner)
943 6d4a1656 Michael Hanselmann
944 6d4a1656 Michael Hanselmann
  ToStdout("All requested certificates and keys have been replaced."
945 6d4a1656 Michael Hanselmann
           " Running \"gnt-cluster verify\" now is recommended.")
946 6d4a1656 Michael Hanselmann
947 6d4a1656 Michael Hanselmann
  return 0
948 6d4a1656 Michael Hanselmann
949 6d4a1656 Michael Hanselmann
950 6d4a1656 Michael Hanselmann
def RenewCrypto(opts, args):
951 6d4a1656 Michael Hanselmann
  """Renews cluster certificates, keys and secrets.
952 6d4a1656 Michael Hanselmann

953 6d4a1656 Michael Hanselmann
  """
954 6d4a1656 Michael Hanselmann
  return _RenewCrypto(opts.new_cluster_cert,
955 6d4a1656 Michael Hanselmann
                      opts.new_rapi_cert,
956 6d4a1656 Michael Hanselmann
                      opts.rapi_cert,
957 b6267745 Andrea Spadaccini
                      opts.new_spice_cert,
958 b6267745 Andrea Spadaccini
                      opts.spice_cert,
959 b6267745 Andrea Spadaccini
                      opts.spice_cacert,
960 6b7d5878 Michael Hanselmann
                      opts.new_confd_hmac_key,
961 3db3eb2a Michael Hanselmann
                      opts.new_cluster_domain_secret,
962 3db3eb2a Michael Hanselmann
                      opts.cluster_domain_secret,
963 6d4a1656 Michael Hanselmann
                      opts.force)
964 6d4a1656 Michael Hanselmann
965 6d4a1656 Michael Hanselmann
966 90b6aa3a Manuel Franceschini
def SetClusterParams(opts, args):
967 90b6aa3a Manuel Franceschini
  """Modify the cluster.
968 90b6aa3a Manuel Franceschini

969 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
970 469ee405 Iustin Pop
  @type args: list
971 469ee405 Iustin Pop
  @param args: should be an empty list
972 469ee405 Iustin Pop
  @rtype: int
973 469ee405 Iustin Pop
  @return: the desired exit code
974 90b6aa3a Manuel Franceschini

975 90b6aa3a Manuel Franceschini
  """
976 912737ba Helga Velroyen
  if not (opts.vg_name is not None or opts.drbd_helper or
977 779c15bb Iustin Pop
          opts.enabled_hypervisors or opts.hvparams or
978 bc5d0215 Andrea Spadaccini
          opts.beparams or opts.nicparams or
979 bc5d0215 Andrea Spadaccini
          opts.ndparams or opts.diskparams or
980 3953242f Iustin Pop
          opts.candidate_pool_size is not None or
981 1338f2b4 Balazs Lecz
          opts.uid_pool is not None or
982 fdad8c4d Balazs Lecz
          opts.maintain_node_health is not None or
983 fdad8c4d Balazs Lecz
          opts.add_uids is not None or
984 bf4af505 Apollon Oikonomopoulos
          opts.remove_uids is not None or
985 f38ea602 Iustin Pop
          opts.default_iallocator is not None or
986 b883637f René Nussbaumer
          opts.reserved_lvs is not None or
987 38f9d2cf Guido Trotter
          opts.master_netdev is not None or
988 5a8648eb Andrea Spadaccini
          opts.master_netmask is not None or
989 bf689b7a Andrea Spadaccini
          opts.use_external_mip_script is not None or
990 2da9f556 René Nussbaumer
          opts.prealloc_wipe_disks is not None or
991 2da9f556 René Nussbaumer
          opts.hv_state or
992 66af5ec5 Helga Velroyen
          opts.enabled_disk_templates or
993 e1a6850f Agata Murawska
          opts.disk_state or
994 d2d3935a Bernardo Dal Seno
          opts.ipolicy_bounds_specs is not None or
995 d2d3935a Bernardo Dal Seno
          opts.ipolicy_std_specs is not None or
996 1e7acc3b Iustin Pop
          opts.ipolicy_disk_templates is not None or
997 31d827d1 René Nussbaumer
          opts.ipolicy_vcpu_ratio is not None or
998 75f2ff7d Michele Tartara
          opts.ipolicy_spindle_ratio is not None or
999 3039e2dc Helga Velroyen
          opts.modify_etc_hosts is not None or
1000 3039e2dc Helga Velroyen
          opts.file_storage_dir is not None):
1001 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
1002 90b6aa3a Manuel Franceschini
    return 1
1003 90b6aa3a Manuel Franceschini
1004 912737ba Helga Velroyen
  if _CheckNoLvmStorageOptDeprecated(opts):
1005 90b6aa3a Manuel Franceschini
    return 1
1006 6d4a1656 Michael Hanselmann
1007 912737ba Helga Velroyen
  enabled_disk_templates = None
1008 912737ba Helga Velroyen
  if opts.enabled_disk_templates:
1009 912737ba Helga Velroyen
    enabled_disk_templates = opts.enabled_disk_templates.split(",")
1010 912737ba Helga Velroyen
1011 912737ba Helga Velroyen
  # consistency between vg name and enabled disk templates
1012 912737ba Helga Velroyen
  vg_name = None
1013 912737ba Helga Velroyen
  if opts.vg_name is not None:
1014 912737ba Helga Velroyen
    vg_name = opts.vg_name
1015 912737ba Helga Velroyen
  if enabled_disk_templates:
1016 912737ba Helga Velroyen
    if vg_name and not utils.IsLvmEnabled(enabled_disk_templates):
1017 912737ba Helga Velroyen
      ToStdout("You specified a volume group with --vg-name, but you did not"
1018 912737ba Helga Velroyen
               " enable any of the following lvm-based disk templates: %s" %
1019 912737ba Helga Velroyen
               utils.CommaJoin(utils.GetLvmDiskTemplates()))
1020 90b6aa3a Manuel Franceschini
1021 ed14ed48 Luca Bigliardi
  drbd_helper = opts.drbd_helper
1022 ed14ed48 Luca Bigliardi
  if not opts.drbd_storage and opts.drbd_helper:
1023 ed14ed48 Luca Bigliardi
    ToStderr("Options --no-drbd-storage and --drbd-usermode-helper conflict.")
1024 ed14ed48 Luca Bigliardi
    return 1
1025 ed14ed48 Luca Bigliardi
1026 ed14ed48 Luca Bigliardi
  if not opts.drbd_storage:
1027 ed14ed48 Luca Bigliardi
    drbd_helper = ""
1028 ed14ed48 Luca Bigliardi
1029 779c15bb Iustin Pop
  hvlist = opts.enabled_hypervisors
1030 779c15bb Iustin Pop
  if hvlist is not None:
1031 779c15bb Iustin Pop
    hvlist = hvlist.split(",")
1032 779c15bb Iustin Pop
1033 f8e7ddca Guido Trotter
  # a list of (name, dict) we can pass directly to dict() (or [])
1034 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
1035 f4ad2ef0 Iustin Pop
  for hv_params in hvparams.values():
1036 a5728081 Guido Trotter
    utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
1037 779c15bb Iustin Pop
1038 bc5d0215 Andrea Spadaccini
  diskparams = dict(opts.diskparams)
1039 bc5d0215 Andrea Spadaccini
1040 c20a19ed Iustin Pop
  for dt_params in diskparams.values():
1041 bc5d0215 Andrea Spadaccini
    utils.ForceDictType(dt_params, constants.DISK_DT_TYPES)
1042 bc5d0215 Andrea Spadaccini
1043 779c15bb Iustin Pop
  beparams = opts.beparams
1044 b2e233a5 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_COMPAT)
1045 779c15bb Iustin Pop
1046 5af3da74 Guido Trotter
  nicparams = opts.nicparams
1047 5af3da74 Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
1048 5af3da74 Guido Trotter
1049 6204ee71 René Nussbaumer
  ndparams = opts.ndparams
1050 6204ee71 René Nussbaumer
  if ndparams is not None:
1051 6204ee71 René Nussbaumer
    utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
1052 1338f2b4 Balazs Lecz
1053 703fa9ab Iustin Pop
  ipolicy = CreateIPolicyFromOpts(
1054 d2d3935a Bernardo Dal Seno
    minmax_ispecs=opts.ipolicy_bounds_specs,
1055 d2d3935a Bernardo Dal Seno
    std_ispecs=opts.ipolicy_std_specs,
1056 976b78ba Iustin Pop
    ipolicy_disk_templates=opts.ipolicy_disk_templates,
1057 976b78ba Iustin Pop
    ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio,
1058 31d827d1 René Nussbaumer
    ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio,
1059 976b78ba Iustin Pop
    )
1060 e1a6850f Agata Murawska
1061 3953242f Iustin Pop
  mnh = opts.maintain_node_health
1062 3953242f Iustin Pop
1063 1338f2b4 Balazs Lecz
  uid_pool = opts.uid_pool
1064 1338f2b4 Balazs Lecz
  if uid_pool is not None:
1065 1338f2b4 Balazs Lecz
    uid_pool = uidpool.ParseUidPool(uid_pool)
1066 1338f2b4 Balazs Lecz
1067 fdad8c4d Balazs Lecz
  add_uids = opts.add_uids
1068 fdad8c4d Balazs Lecz
  if add_uids is not None:
1069 fdad8c4d Balazs Lecz
    add_uids = uidpool.ParseUidPool(add_uids)
1070 fdad8c4d Balazs Lecz
1071 fdad8c4d Balazs Lecz
  remove_uids = opts.remove_uids
1072 fdad8c4d Balazs Lecz
  if remove_uids is not None:
1073 fdad8c4d Balazs Lecz
    remove_uids = uidpool.ParseUidPool(remove_uids)
1074 fdad8c4d Balazs Lecz
1075 f38ea602 Iustin Pop
  if opts.reserved_lvs is not None:
1076 f38ea602 Iustin Pop
    if opts.reserved_lvs == "":
1077 f38ea602 Iustin Pop
      opts.reserved_lvs = []
1078 f38ea602 Iustin Pop
    else:
1079 f38ea602 Iustin Pop
      opts.reserved_lvs = utils.UnescapeAndSplit(opts.reserved_lvs, sep=",")
1080 f38ea602 Iustin Pop
1081 5a8648eb Andrea Spadaccini
  if opts.master_netmask is not None:
1082 5a8648eb Andrea Spadaccini
    try:
1083 5a8648eb Andrea Spadaccini
      opts.master_netmask = int(opts.master_netmask)
1084 5a8648eb Andrea Spadaccini
    except ValueError:
1085 5a8648eb Andrea Spadaccini
      ToStderr("The --master-netmask option expects an int parameter.")
1086 5a8648eb Andrea Spadaccini
      return 1
1087 5a8648eb Andrea Spadaccini
1088 bf689b7a Andrea Spadaccini
  ext_ip_script = opts.use_external_mip_script
1089 bf689b7a Andrea Spadaccini
1090 2da9f556 René Nussbaumer
  if opts.disk_state:
1091 2da9f556 René Nussbaumer
    disk_state = utils.FlatToDict(opts.disk_state)
1092 2da9f556 René Nussbaumer
  else:
1093 2da9f556 René Nussbaumer
    disk_state = {}
1094 2da9f556 René Nussbaumer
1095 2da9f556 René Nussbaumer
  hv_state = dict(opts.hv_state)
1096 2da9f556 René Nussbaumer
1097 c270ee07 Helga Velroyen
  op = opcodes.OpClusterSetParams(
1098 c270ee07 Helga Velroyen
    vg_name=vg_name,
1099 c270ee07 Helga Velroyen
    drbd_helper=drbd_helper,
1100 c270ee07 Helga Velroyen
    enabled_hypervisors=hvlist,
1101 c270ee07 Helga Velroyen
    hvparams=hvparams,
1102 c270ee07 Helga Velroyen
    os_hvp=None,
1103 c270ee07 Helga Velroyen
    beparams=beparams,
1104 c270ee07 Helga Velroyen
    nicparams=nicparams,
1105 c270ee07 Helga Velroyen
    ndparams=ndparams,
1106 c270ee07 Helga Velroyen
    diskparams=diskparams,
1107 c270ee07 Helga Velroyen
    ipolicy=ipolicy,
1108 c270ee07 Helga Velroyen
    candidate_pool_size=opts.candidate_pool_size,
1109 c270ee07 Helga Velroyen
    maintain_node_health=mnh,
1110 75f2ff7d Michele Tartara
    modify_etc_hosts=opts.modify_etc_hosts,
1111 c270ee07 Helga Velroyen
    uid_pool=uid_pool,
1112 c270ee07 Helga Velroyen
    add_uids=add_uids,
1113 c270ee07 Helga Velroyen
    remove_uids=remove_uids,
1114 c270ee07 Helga Velroyen
    default_iallocator=opts.default_iallocator,
1115 c270ee07 Helga Velroyen
    prealloc_wipe_disks=opts.prealloc_wipe_disks,
1116 c270ee07 Helga Velroyen
    master_netdev=opts.master_netdev,
1117 c270ee07 Helga Velroyen
    master_netmask=opts.master_netmask,
1118 c270ee07 Helga Velroyen
    reserved_lvs=opts.reserved_lvs,
1119 c270ee07 Helga Velroyen
    use_external_mip_script=ext_ip_script,
1120 c270ee07 Helga Velroyen
    hv_state=hv_state,
1121 c270ee07 Helga Velroyen
    disk_state=disk_state,
1122 66af5ec5 Helga Velroyen
    enabled_disk_templates=enabled_disk_templates,
1123 2f836021 Klaus Aehlig
    force=opts.force,
1124 3039e2dc Helga Velroyen
    file_storage_dir=opts.file_storage_dir,
1125 c270ee07 Helga Velroyen
    )
1126 745dae57 Michael Hanselmann
  SubmitOrSend(op, opts)
1127 90b6aa3a Manuel Franceschini
  return 0
1128 90b6aa3a Manuel Franceschini
1129 90b6aa3a Manuel Franceschini
1130 3ccafd0e Iustin Pop
def QueueOps(opts, args):
1131 3ccafd0e Iustin Pop
  """Queue operations.
1132 3ccafd0e Iustin Pop

1133 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
1134 469ee405 Iustin Pop
  @type args: list
1135 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
1136 469ee405 Iustin Pop
  @rtype: int
1137 469ee405 Iustin Pop
  @return: the desired exit code
1138 469ee405 Iustin Pop

1139 3ccafd0e Iustin Pop
  """
1140 3ccafd0e Iustin Pop
  command = args[0]
1141 3ccafd0e Iustin Pop
  client = GetClient()
1142 3ccafd0e Iustin Pop
  if command in ("drain", "undrain"):
1143 3ccafd0e Iustin Pop
    drain_flag = command == "drain"
1144 3ccafd0e Iustin Pop
    client.SetQueueDrainFlag(drain_flag)
1145 3ccafd0e Iustin Pop
  elif command == "info":
1146 3ccafd0e Iustin Pop
    result = client.QueryConfigValues(["drain_flag"])
1147 3ccafd0e Iustin Pop
    if result[0]:
1148 3a24c527 Iustin Pop
      val = "set"
1149 3ccafd0e Iustin Pop
    else:
1150 3a24c527 Iustin Pop
      val = "unset"
1151 3a24c527 Iustin Pop
    ToStdout("The drain flag is %s" % val)
1152 2e668b38 Guido Trotter
  else:
1153 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
1154 debac808 Iustin Pop
                               errors.ECODE_INVAL)
1155 2e668b38 Guido Trotter
1156 3ccafd0e Iustin Pop
  return 0
1157 3ccafd0e Iustin Pop
1158 95b2e626 Michael Hanselmann
1159 28b498cd Michael Hanselmann
def _ShowWatcherPause(until):
1160 28b498cd Michael Hanselmann
  if until is None or until < time.time():
1161 28b498cd Michael Hanselmann
    ToStdout("The watcher is not paused.")
1162 28b498cd Michael Hanselmann
  else:
1163 28b498cd Michael Hanselmann
    ToStdout("The watcher is paused until %s.", time.ctime(until))
1164 28b498cd Michael Hanselmann
1165 28b498cd Michael Hanselmann
1166 95b2e626 Michael Hanselmann
def WatcherOps(opts, args):
1167 95b2e626 Michael Hanselmann
  """Watcher operations.
1168 95b2e626 Michael Hanselmann

1169 95b2e626 Michael Hanselmann
  @param opts: the command line options selected by the user
1170 95b2e626 Michael Hanselmann
  @type args: list
1171 95b2e626 Michael Hanselmann
  @param args: should contain only one element, the subcommand
1172 95b2e626 Michael Hanselmann
  @rtype: int
1173 95b2e626 Michael Hanselmann
  @return: the desired exit code
1174 95b2e626 Michael Hanselmann

1175 95b2e626 Michael Hanselmann
  """
1176 95b2e626 Michael Hanselmann
  command = args[0]
1177 95b2e626 Michael Hanselmann
  client = GetClient()
1178 95b2e626 Michael Hanselmann
1179 95b2e626 Michael Hanselmann
  if command == "continue":
1180 95b2e626 Michael Hanselmann
    client.SetWatcherPause(None)
1181 28b498cd Michael Hanselmann
    ToStdout("The watcher is no longer paused.")
1182 95b2e626 Michael Hanselmann
1183 95b2e626 Michael Hanselmann
  elif command == "pause":
1184 95b2e626 Michael Hanselmann
    if len(args) < 2:
1185 debac808 Iustin Pop
      raise errors.OpPrereqError("Missing pause duration", errors.ECODE_INVAL)
1186 95b2e626 Michael Hanselmann
1187 28b498cd Michael Hanselmann
    result = client.SetWatcherPause(time.time() + ParseTimespec(args[1]))
1188 28b498cd Michael Hanselmann
    _ShowWatcherPause(result)
1189 95b2e626 Michael Hanselmann
1190 95b2e626 Michael Hanselmann
  elif command == "info":
1191 95b2e626 Michael Hanselmann
    result = client.QueryConfigValues(["watcher_pause"])
1192 cac599f1 Michael Hanselmann
    _ShowWatcherPause(result[0])
1193 95b2e626 Michael Hanselmann
1194 95b2e626 Michael Hanselmann
  else:
1195 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
1196 debac808 Iustin Pop
                               errors.ECODE_INVAL)
1197 95b2e626 Michael Hanselmann
1198 95b2e626 Michael Hanselmann
  return 0
1199 95b2e626 Michael Hanselmann
1200 95b2e626 Michael Hanselmann
1201 66d1f035 René Nussbaumer
def _OobPower(opts, node_list, power):
1202 66d1f035 René Nussbaumer
  """Puts the node in the list to desired power state.
1203 66d1f035 René Nussbaumer

1204 66d1f035 René Nussbaumer
  @param opts: The command line options selected by the user
1205 66d1f035 René Nussbaumer
  @param node_list: The list of nodes to operate on
1206 66d1f035 René Nussbaumer
  @param power: True if they should be powered on, False otherwise
1207 66d1f035 René Nussbaumer
  @return: The success of the operation (none failed)
1208 66d1f035 René Nussbaumer

1209 66d1f035 René Nussbaumer
  """
1210 66d1f035 René Nussbaumer
  if power:
1211 66d1f035 René Nussbaumer
    command = constants.OOB_POWER_ON
1212 66d1f035 René Nussbaumer
  else:
1213 66d1f035 René Nussbaumer
    command = constants.OOB_POWER_OFF
1214 66d1f035 René Nussbaumer
1215 66d1f035 René Nussbaumer
  op = opcodes.OpOobCommand(node_names=node_list,
1216 66d1f035 René Nussbaumer
                            command=command,
1217 66d1f035 René Nussbaumer
                            ignore_status=True,
1218 cfed3b9f René Nussbaumer
                            timeout=opts.oob_timeout,
1219 cfed3b9f René Nussbaumer
                            power_delay=opts.power_delay)
1220 66d1f035 René Nussbaumer
  result = SubmitOpCode(op, opts=opts)
1221 66d1f035 René Nussbaumer
  errs = 0
1222 66d1f035 René Nussbaumer
  for node_result in result:
1223 66d1f035 René Nussbaumer
    (node_tuple, data_tuple) = node_result
1224 66d1f035 René Nussbaumer
    (_, node_name) = node_tuple
1225 66d1f035 René Nussbaumer
    (data_status, _) = data_tuple
1226 66d1f035 René Nussbaumer
    if data_status != constants.RS_NORMAL:
1227 66d1f035 René Nussbaumer
      assert data_status != constants.RS_UNAVAIL
1228 66d1f035 René Nussbaumer
      errs += 1
1229 66d1f035 René Nussbaumer
      ToStderr("There was a problem changing power for %s, please investigate",
1230 66d1f035 René Nussbaumer
               node_name)
1231 66d1f035 René Nussbaumer
1232 66d1f035 René Nussbaumer
  if errs > 0:
1233 66d1f035 René Nussbaumer
    return False
1234 66d1f035 René Nussbaumer
1235 66d1f035 René Nussbaumer
  return True
1236 66d1f035 René Nussbaumer
1237 66d1f035 René Nussbaumer
1238 3e0ed18c René Nussbaumer
def _InstanceStart(opts, inst_list, start, no_remember=False):
1239 66d1f035 René Nussbaumer
  """Puts the instances in the list to desired state.
1240 66d1f035 René Nussbaumer

1241 66d1f035 René Nussbaumer
  @param opts: The command line options selected by the user
1242 66d1f035 René Nussbaumer
  @param inst_list: The list of instances to operate on
1243 66d1f035 René Nussbaumer
  @param start: True if they should be started, False for shutdown
1244 3e0ed18c René Nussbaumer
  @param no_remember: If the instance state should be remembered
1245 66d1f035 René Nussbaumer
  @return: The success of the operation (none failed)
1246 66d1f035 René Nussbaumer

1247 66d1f035 René Nussbaumer
  """
1248 66d1f035 René Nussbaumer
  if start:
1249 66d1f035 René Nussbaumer
    opcls = opcodes.OpInstanceStartup
1250 66d1f035 René Nussbaumer
    text_submit, text_success, text_failed = ("startup", "started", "starting")
1251 66d1f035 René Nussbaumer
  else:
1252 fcecea0b René Nussbaumer
    opcls = compat.partial(opcodes.OpInstanceShutdown,
1253 3e0ed18c René Nussbaumer
                           timeout=opts.shutdown_timeout,
1254 3e0ed18c René Nussbaumer
                           no_remember=no_remember)
1255 66d1f035 René Nussbaumer
    text_submit, text_success, text_failed = ("shutdown", "stopped", "stopping")
1256 66d1f035 René Nussbaumer
1257 66d1f035 René Nussbaumer
  jex = JobExecutor(opts=opts)
1258 66d1f035 René Nussbaumer
1259 66d1f035 René Nussbaumer
  for inst in inst_list:
1260 66d1f035 René Nussbaumer
    ToStdout("Submit %s of instance %s", text_submit, inst)
1261 66d1f035 René Nussbaumer
    op = opcls(instance_name=inst)
1262 66d1f035 René Nussbaumer
    jex.QueueJob(inst, op)
1263 66d1f035 René Nussbaumer
1264 66d1f035 René Nussbaumer
  results = jex.GetResults()
1265 66d1f035 René Nussbaumer
  bad_cnt = len([1 for (success, _) in results if not success])
1266 66d1f035 René Nussbaumer
1267 66d1f035 René Nussbaumer
  if bad_cnt == 0:
1268 66d1f035 René Nussbaumer
    ToStdout("All instances have been %s successfully", text_success)
1269 66d1f035 René Nussbaumer
  else:
1270 66d1f035 René Nussbaumer
    ToStderr("There were errors while %s instances:\n"
1271 66d1f035 René Nussbaumer
             "%d error(s) out of %d instance(s)", text_failed, bad_cnt,
1272 66d1f035 René Nussbaumer
             len(results))
1273 66d1f035 René Nussbaumer
    return False
1274 66d1f035 René Nussbaumer
1275 66d1f035 René Nussbaumer
  return True
1276 66d1f035 René Nussbaumer
1277 66d1f035 René Nussbaumer
1278 66d1f035 René Nussbaumer
class _RunWhenNodesReachableHelper:
1279 66d1f035 René Nussbaumer
  """Helper class to make shared internal state sharing easier.
1280 66d1f035 René Nussbaumer

1281 66d1f035 René Nussbaumer
  @ivar success: Indicates if all action_cb calls were successful
1282 66d1f035 René Nussbaumer

1283 66d1f035 René Nussbaumer
  """
1284 8e74adce René Nussbaumer
  def __init__(self, node_list, action_cb, node2ip, port, feedback_fn,
1285 66d1f035 René Nussbaumer
               _ping_fn=netutils.TcpPing, _sleep_fn=time.sleep):
1286 66d1f035 René Nussbaumer
    """Init the object.
1287 66d1f035 René Nussbaumer

1288 66d1f035 René Nussbaumer
    @param node_list: The list of nodes to be reachable
1289 66d1f035 René Nussbaumer
    @param action_cb: Callback called when a new host is reachable
1290 66d1f035 René Nussbaumer
    @type node2ip: dict
1291 66d1f035 René Nussbaumer
    @param node2ip: Node to ip mapping
1292 66d1f035 René Nussbaumer
    @param port: The port to use for the TCP ping
1293 8e74adce René Nussbaumer
    @param feedback_fn: The function used for feedback
1294 66d1f035 René Nussbaumer
    @param _ping_fn: Function to check reachabilty (for unittest use only)
1295 66d1f035 René Nussbaumer
    @param _sleep_fn: Function to sleep (for unittest use only)
1296 66d1f035 René Nussbaumer

1297 66d1f035 René Nussbaumer
    """
1298 66d1f035 René Nussbaumer
    self.down = set(node_list)
1299 66d1f035 René Nussbaumer
    self.up = set()
1300 66d1f035 René Nussbaumer
    self.node2ip = node2ip
1301 66d1f035 René Nussbaumer
    self.success = True
1302 66d1f035 René Nussbaumer
    self.action_cb = action_cb
1303 66d1f035 René Nussbaumer
    self.port = port
1304 8e74adce René Nussbaumer
    self.feedback_fn = feedback_fn
1305 66d1f035 René Nussbaumer
    self._ping_fn = _ping_fn
1306 66d1f035 René Nussbaumer
    self._sleep_fn = _sleep_fn
1307 66d1f035 René Nussbaumer
1308 66d1f035 René Nussbaumer
  def __call__(self):
1309 66d1f035 René Nussbaumer
    """When called we run action_cb.
1310 66d1f035 René Nussbaumer

1311 66d1f035 René Nussbaumer
    @raises utils.RetryAgain: When there are still down nodes
1312 66d1f035 René Nussbaumer

1313 66d1f035 René Nussbaumer
    """
1314 66d1f035 René Nussbaumer
    if not self.action_cb(self.up):
1315 66d1f035 René Nussbaumer
      self.success = False
1316 66d1f035 René Nussbaumer
1317 66d1f035 René Nussbaumer
    if self.down:
1318 66d1f035 René Nussbaumer
      raise utils.RetryAgain()
1319 66d1f035 René Nussbaumer
    else:
1320 66d1f035 René Nussbaumer
      return self.success
1321 66d1f035 René Nussbaumer
1322 66d1f035 René Nussbaumer
  def Wait(self, secs):
1323 66d1f035 René Nussbaumer
    """Checks if a host is up or waits remaining seconds.
1324 66d1f035 René Nussbaumer

1325 66d1f035 René Nussbaumer
    @param secs: The secs remaining
1326 66d1f035 René Nussbaumer

1327 66d1f035 René Nussbaumer
    """
1328 66d1f035 René Nussbaumer
    start = time.time()
1329 66d1f035 René Nussbaumer
    for node in self.down:
1330 66d1f035 René Nussbaumer
      if self._ping_fn(self.node2ip[node], self.port, timeout=_EPO_PING_TIMEOUT,
1331 66d1f035 René Nussbaumer
                       live_port_needed=True):
1332 8e74adce René Nussbaumer
        self.feedback_fn("Node %s became available" % node)
1333 66d1f035 René Nussbaumer
        self.up.add(node)
1334 66d1f035 René Nussbaumer
        self.down -= self.up
1335 66d1f035 René Nussbaumer
        # If we have a node available there is the possibility to run the
1336 66d1f035 René Nussbaumer
        # action callback successfully, therefore we don't wait and return
1337 66d1f035 René Nussbaumer
        return
1338 66d1f035 René Nussbaumer
1339 66d1f035 René Nussbaumer
    self._sleep_fn(max(0.0, start + secs - time.time()))
1340 66d1f035 René Nussbaumer
1341 66d1f035 René Nussbaumer
1342 66d1f035 René Nussbaumer
def _RunWhenNodesReachable(node_list, action_cb, interval):
1343 66d1f035 René Nussbaumer
  """Run action_cb when nodes become reachable.
1344 66d1f035 René Nussbaumer

1345 66d1f035 René Nussbaumer
  @param node_list: The list of nodes to be reachable
1346 66d1f035 René Nussbaumer
  @param action_cb: Callback called when a new host is reachable
1347 66d1f035 René Nussbaumer
  @param interval: The earliest time to retry
1348 66d1f035 René Nussbaumer

1349 66d1f035 René Nussbaumer
  """
1350 66d1f035 René Nussbaumer
  client = GetClient()
1351 66d1f035 René Nussbaumer
  cluster_info = client.QueryClusterInfo()
1352 66d1f035 René Nussbaumer
  if cluster_info["primary_ip_version"] == constants.IP4_VERSION:
1353 66d1f035 René Nussbaumer
    family = netutils.IPAddress.family
1354 66d1f035 René Nussbaumer
  else:
1355 66d1f035 René Nussbaumer
    family = netutils.IP6Address.family
1356 66d1f035 René Nussbaumer
1357 66d1f035 René Nussbaumer
  node2ip = dict((node, netutils.GetHostname(node, family=family).ip)
1358 66d1f035 René Nussbaumer
                 for node in node_list)
1359 66d1f035 René Nussbaumer
1360 66d1f035 René Nussbaumer
  port = netutils.GetDaemonPort(constants.NODED)
1361 8e74adce René Nussbaumer
  helper = _RunWhenNodesReachableHelper(node_list, action_cb, node2ip, port,
1362 8e74adce René Nussbaumer
                                        ToStdout)
1363 66d1f035 René Nussbaumer
1364 66d1f035 René Nussbaumer
  try:
1365 66d1f035 René Nussbaumer
    return utils.Retry(helper, interval, _EPO_REACHABLE_TIMEOUT,
1366 66d1f035 René Nussbaumer
                       wait_fn=helper.Wait)
1367 66d1f035 René Nussbaumer
  except utils.RetryTimeout:
1368 66d1f035 René Nussbaumer
    ToStderr("Time exceeded while waiting for nodes to become reachable"
1369 66d1f035 René Nussbaumer
             " again:\n  - %s", "  - ".join(helper.down))
1370 66d1f035 René Nussbaumer
    return False
1371 66d1f035 René Nussbaumer
1372 66d1f035 René Nussbaumer
1373 66d1f035 René Nussbaumer
def _MaybeInstanceStartup(opts, inst_map, nodes_online,
1374 66d1f035 René Nussbaumer
                          _instance_start_fn=_InstanceStart):
1375 66d1f035 René Nussbaumer
  """Start the instances conditional based on node_states.
1376 66d1f035 René Nussbaumer

1377 66d1f035 René Nussbaumer
  @param opts: The command line options selected by the user
1378 66d1f035 René Nussbaumer
  @param inst_map: A dict of inst -> nodes mapping
1379 66d1f035 René Nussbaumer
  @param nodes_online: A list of nodes online
1380 66d1f035 René Nussbaumer
  @param _instance_start_fn: Callback to start instances (unittest use only)
1381 66d1f035 René Nussbaumer
  @return: Success of the operation on all instances
1382 66d1f035 René Nussbaumer

1383 66d1f035 René Nussbaumer
  """
1384 66d1f035 René Nussbaumer
  start_inst_list = []
1385 66d1f035 René Nussbaumer
  for (inst, nodes) in inst_map.items():
1386 66d1f035 René Nussbaumer
    if not (nodes - nodes_online):
1387 66d1f035 René Nussbaumer
      # All nodes the instance lives on are back online
1388 66d1f035 René Nussbaumer
      start_inst_list.append(inst)
1389 66d1f035 René Nussbaumer
1390 66d1f035 René Nussbaumer
  for inst in start_inst_list:
1391 66d1f035 René Nussbaumer
    del inst_map[inst]
1392 66d1f035 René Nussbaumer
1393 66d1f035 René Nussbaumer
  if start_inst_list:
1394 66d1f035 René Nussbaumer
    return _instance_start_fn(opts, start_inst_list, True)
1395 66d1f035 René Nussbaumer
1396 66d1f035 René Nussbaumer
  return True
1397 66d1f035 René Nussbaumer
1398 66d1f035 René Nussbaumer
1399 66d1f035 René Nussbaumer
def _EpoOn(opts, full_node_list, node_list, inst_map):
1400 66d1f035 René Nussbaumer
  """Does the actual power on.
1401 66d1f035 René Nussbaumer

1402 66d1f035 René Nussbaumer
  @param opts: The command line options selected by the user
1403 66d1f035 René Nussbaumer
  @param full_node_list: All nodes to operate on (includes nodes not supporting
1404 66d1f035 René Nussbaumer
                         OOB)
1405 66d1f035 René Nussbaumer
  @param node_list: The list of nodes to operate on (all need to support OOB)
1406 66d1f035 René Nussbaumer
  @param inst_map: A dict of inst -> nodes mapping
1407 66d1f035 René Nussbaumer
  @return: The desired exit status
1408 66d1f035 René Nussbaumer

1409 66d1f035 René Nussbaumer
  """
1410 66d1f035 René Nussbaumer
  if node_list and not _OobPower(opts, node_list, False):
1411 66d1f035 René Nussbaumer
    ToStderr("Not all nodes seem to get back up, investigate and start"
1412 66d1f035 René Nussbaumer
             " manually if needed")
1413 66d1f035 René Nussbaumer
1414 66d1f035 René Nussbaumer
  # Wait for the nodes to be back up
1415 66d1f035 René Nussbaumer
  action_cb = compat.partial(_MaybeInstanceStartup, opts, dict(inst_map))
1416 66d1f035 René Nussbaumer
1417 66d1f035 René Nussbaumer
  ToStdout("Waiting until all nodes are available again")
1418 66d1f035 René Nussbaumer
  if not _RunWhenNodesReachable(full_node_list, action_cb, _EPO_PING_INTERVAL):
1419 66d1f035 René Nussbaumer
    ToStderr("Please investigate and start stopped instances manually")
1420 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1421 66d1f035 René Nussbaumer
1422 66d1f035 René Nussbaumer
  return constants.EXIT_SUCCESS
1423 66d1f035 René Nussbaumer
1424 66d1f035 René Nussbaumer
1425 66d1f035 René Nussbaumer
def _EpoOff(opts, node_list, inst_map):
1426 66d1f035 René Nussbaumer
  """Does the actual power off.
1427 66d1f035 René Nussbaumer

1428 66d1f035 René Nussbaumer
  @param opts: The command line options selected by the user
1429 66d1f035 René Nussbaumer
  @param node_list: The list of nodes to operate on (all need to support OOB)
1430 66d1f035 René Nussbaumer
  @param inst_map: A dict of inst -> nodes mapping
1431 66d1f035 René Nussbaumer
  @return: The desired exit status
1432 66d1f035 René Nussbaumer

1433 66d1f035 René Nussbaumer
  """
1434 3e0ed18c René Nussbaumer
  if not _InstanceStart(opts, inst_map.keys(), False, no_remember=True):
1435 66d1f035 René Nussbaumer
    ToStderr("Please investigate and stop instances manually before continuing")
1436 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1437 66d1f035 René Nussbaumer
1438 66d1f035 René Nussbaumer
  if not node_list:
1439 66d1f035 René Nussbaumer
    return constants.EXIT_SUCCESS
1440 66d1f035 René Nussbaumer
1441 66d1f035 René Nussbaumer
  if _OobPower(opts, node_list, False):
1442 66d1f035 René Nussbaumer
    return constants.EXIT_SUCCESS
1443 66d1f035 René Nussbaumer
  else:
1444 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1445 66d1f035 René Nussbaumer
1446 66d1f035 René Nussbaumer
1447 1ca7b773 Michael Hanselmann
def Epo(opts, args, cl=None, _on_fn=_EpoOn, _off_fn=_EpoOff,
1448 1ca7b773 Michael Hanselmann
        _confirm_fn=ConfirmOperation,
1449 1ca7b773 Michael Hanselmann
        _stdout_fn=ToStdout, _stderr_fn=ToStderr):
1450 66d1f035 René Nussbaumer
  """EPO operations.
1451 66d1f035 René Nussbaumer

1452 66d1f035 René Nussbaumer
  @param opts: the command line options selected by the user
1453 66d1f035 René Nussbaumer
  @type args: list
1454 66d1f035 René Nussbaumer
  @param args: should contain only one element, the subcommand
1455 66d1f035 René Nussbaumer
  @rtype: int
1456 66d1f035 René Nussbaumer
  @return: the desired exit code
1457 66d1f035 René Nussbaumer

1458 66d1f035 René Nussbaumer
  """
1459 66d1f035 René Nussbaumer
  if opts.groups and opts.show_all:
1460 1ca7b773 Michael Hanselmann
    _stderr_fn("Only one of --groups or --all are allowed")
1461 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1462 66d1f035 René Nussbaumer
  elif args and opts.show_all:
1463 1ca7b773 Michael Hanselmann
    _stderr_fn("Arguments in combination with --all are not allowed")
1464 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1465 66d1f035 René Nussbaumer
1466 1ca7b773 Michael Hanselmann
  if cl is None:
1467 1ca7b773 Michael Hanselmann
    cl = GetClient()
1468 66d1f035 René Nussbaumer
1469 66d1f035 René Nussbaumer
  if opts.groups:
1470 1ca7b773 Michael Hanselmann
    node_query_list = \
1471 1ca7b773 Michael Hanselmann
      itertools.chain(*cl.QueryGroups(args, ["node_list"], False))
1472 66d1f035 René Nussbaumer
  else:
1473 66d1f035 René Nussbaumer
    node_query_list = args
1474 66d1f035 René Nussbaumer
1475 1ca7b773 Michael Hanselmann
  result = cl.QueryNodes(node_query_list, ["name", "master", "pinst_list",
1476 1ca7b773 Michael Hanselmann
                                           "sinst_list", "powered", "offline"],
1477 1ca7b773 Michael Hanselmann
                         False)
1478 45a36f36 Michael Hanselmann
1479 45a36f36 Michael Hanselmann
  all_nodes = map(compat.fst, result)
1480 66d1f035 René Nussbaumer
  node_list = []
1481 66d1f035 René Nussbaumer
  inst_map = {}
1482 3008f56c Iustin Pop
  for (node, master, pinsts, sinsts, powered, offline) in result:
1483 66d1f035 René Nussbaumer
    if not offline:
1484 66d1f035 René Nussbaumer
      for inst in (pinsts + sinsts):
1485 66d1f035 René Nussbaumer
        if inst in inst_map:
1486 66d1f035 René Nussbaumer
          if not master:
1487 66d1f035 René Nussbaumer
            inst_map[inst].add(node)
1488 66d1f035 René Nussbaumer
        elif master:
1489 66d1f035 René Nussbaumer
          inst_map[inst] = set()
1490 66d1f035 René Nussbaumer
        else:
1491 66d1f035 René Nussbaumer
          inst_map[inst] = set([node])
1492 66d1f035 René Nussbaumer
1493 66d1f035 René Nussbaumer
    if master and opts.on:
1494 66d1f035 René Nussbaumer
      # We ignore the master for turning on the machines, in fact we are
1495 66d1f035 René Nussbaumer
      # already operating on the master at this point :)
1496 66d1f035 René Nussbaumer
      continue
1497 66d1f035 René Nussbaumer
    elif master and not opts.show_all:
1498 1ca7b773 Michael Hanselmann
      _stderr_fn("%s is the master node, please do a master-failover to another"
1499 1ca7b773 Michael Hanselmann
                 " node not affected by the EPO or use --all if you intend to"
1500 1ca7b773 Michael Hanselmann
                 " shutdown the whole cluster", node)
1501 66d1f035 René Nussbaumer
      return constants.EXIT_FAILURE
1502 66d1f035 René Nussbaumer
    elif powered is None:
1503 1ca7b773 Michael Hanselmann
      _stdout_fn("Node %s does not support out-of-band handling, it can not be"
1504 1ca7b773 Michael Hanselmann
                 " handled in a fully automated manner", node)
1505 66d1f035 René Nussbaumer
    elif powered == opts.on:
1506 1ca7b773 Michael Hanselmann
      _stdout_fn("Node %s is already in desired power state, skipping", node)
1507 66d1f035 René Nussbaumer
    elif not offline or (offline and powered):
1508 66d1f035 René Nussbaumer
      node_list.append(node)
1509 66d1f035 René Nussbaumer
1510 1ca7b773 Michael Hanselmann
  if not (opts.force or _confirm_fn(all_nodes, "nodes", "epo")):
1511 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1512 66d1f035 René Nussbaumer
1513 66d1f035 René Nussbaumer
  if opts.on:
1514 1ca7b773 Michael Hanselmann
    return _on_fn(opts, all_nodes, node_list, inst_map)
1515 66d1f035 René Nussbaumer
  else:
1516 1ca7b773 Michael Hanselmann
    return _off_fn(opts, node_list, inst_map)
1517 1ca7b773 Michael Hanselmann
1518 66d1f035 René Nussbaumer
1519 ea9d3b40 Bernardo Dal Seno
def _GetCreateCommand(info):
1520 ea9d3b40 Bernardo Dal Seno
  buf = StringIO()
1521 ea9d3b40 Bernardo Dal Seno
  buf.write("gnt-cluster init")
1522 ea9d3b40 Bernardo Dal Seno
  PrintIPolicyCommand(buf, info["ipolicy"], False)
1523 ea9d3b40 Bernardo Dal Seno
  buf.write(" ")
1524 ea9d3b40 Bernardo Dal Seno
  buf.write(info["name"])
1525 ea9d3b40 Bernardo Dal Seno
  return buf.getvalue()
1526 ea9d3b40 Bernardo Dal Seno
1527 ea9d3b40 Bernardo Dal Seno
1528 ea9d3b40 Bernardo Dal Seno
def ShowCreateCommand(opts, args):
1529 ea9d3b40 Bernardo Dal Seno
  """Shows the command that can be used to re-create the cluster.
1530 ea9d3b40 Bernardo Dal Seno

1531 ea9d3b40 Bernardo Dal Seno
  Currently it works only for ipolicy specs.
1532 ea9d3b40 Bernardo Dal Seno

1533 ea9d3b40 Bernardo Dal Seno
  """
1534 ea9d3b40 Bernardo Dal Seno
  cl = GetClient(query=True)
1535 ea9d3b40 Bernardo Dal Seno
  result = cl.QueryClusterInfo()
1536 ea9d3b40 Bernardo Dal Seno
  ToStdout(_GetCreateCommand(result))
1537 ea9d3b40 Bernardo Dal Seno
1538 ea9d3b40 Bernardo Dal Seno
1539 a8083063 Iustin Pop
commands = {
1540 d0c8c01d Iustin Pop
  "init": (
1541 6ea815cf Iustin Pop
    InitCluster, [ArgHost(min=1, max=1)],
1542 064c21f8 Iustin Pop
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, GLOBAL_FILEDIR_OPT,
1543 5a8648eb Andrea Spadaccini
     HVLIST_OPT, MAC_PREFIX_OPT, MASTER_NETDEV_OPT, MASTER_NETMASK_OPT,
1544 5a8648eb Andrea Spadaccini
     NIC_PARAMS_OPT, NOLVM_STORAGE_OPT, NOMODIFY_ETCHOSTS_OPT,
1545 5a8648eb Andrea Spadaccini
     NOMODIFY_SSH_SETUP_OPT, SECONDARY_IP_OPT, VG_NAME_OPT,
1546 5a8648eb Andrea Spadaccini
     MAINTAIN_NODE_HEALTH_OPT, UIDPOOL_OPT, DRBD_HELPER_OPT, NODRBD_STORAGE_OPT,
1547 6204ee71 René Nussbaumer
     DEFAULT_IALLOCATOR_OPT, PRIMARY_IP_VERSION_OPT, PREALLOC_WIPE_DISKS_OPT,
1548 bc5d0215 Andrea Spadaccini
     NODE_PARAMS_OPT, GLOBAL_SHARED_FILEDIR_OPT, USE_EXTERNAL_MIP_SCRIPT,
1549 d2d3935a Bernardo Dal Seno
     DISK_PARAMS_OPT, HV_STATE_OPT, DISK_STATE_OPT, ENABLED_DISK_TEMPLATES_OPT,
1550 919db916 Bernardo Dal Seno
     IPOLICY_STD_SPECS_OPT] + INSTANCE_POLICY_OPTS + SPLIT_ISPECS_OPTS,
1551 6ea815cf Iustin Pop
    "[opts...] <cluster_name>", "Initialises a new cluster configuration"),
1552 d0c8c01d Iustin Pop
  "destroy": (
1553 064c21f8 Iustin Pop
    DestroyCluster, ARGS_NONE, [YES_DOIT_OPT],
1554 6ea815cf Iustin Pop
    "", "Destroy cluster"),
1555 d0c8c01d Iustin Pop
  "rename": (
1556 6ea815cf Iustin Pop
    RenameCluster, [ArgHost(min=1, max=1)],
1557 db5a8a2d Iustin Pop
    [FORCE_OPT, DRY_RUN_OPT],
1558 6ea815cf Iustin Pop
    "<new_name>",
1559 6ea815cf Iustin Pop
    "Renames the cluster"),
1560 d0c8c01d Iustin Pop
  "redist-conf": (
1561 d6cd74dd Klaus Aehlig
    RedistributeConfig, ARGS_NONE, SUBMIT_OPTS + [DRY_RUN_OPT, PRIORITY_OPT],
1562 6ea815cf Iustin Pop
    "", "Forces a push of the configuration file and ssconf files"
1563 6ea815cf Iustin Pop
    " to the nodes in the cluster"),
1564 d0c8c01d Iustin Pop
  "verify": (
1565 6ea815cf Iustin Pop
    VerifyCluster, ARGS_NONE,
1566 db5a8a2d Iustin Pop
    [VERBOSE_OPT, DEBUG_SIMERR_OPT, ERROR_CODES_OPT, NONPLUS1_OPT,
1567 93f2399e Andrea Spadaccini
     DRY_RUN_OPT, PRIORITY_OPT, NODEGROUP_OPT, IGNORE_ERRORS_OPT],
1568 6ea815cf Iustin Pop
    "", "Does a check on the cluster configuration"),
1569 d0c8c01d Iustin Pop
  "verify-disks": (
1570 aa06f8c6 Michael Hanselmann
    VerifyDisks, ARGS_NONE, [PRIORITY_OPT],
1571 6ea815cf Iustin Pop
    "", "Does a check on the cluster disk status"),
1572 d0c8c01d Iustin Pop
  "repair-disk-sizes": (
1573 aa06f8c6 Michael Hanselmann
    RepairDiskSizes, ARGS_MANY_INSTANCES, [DRY_RUN_OPT, PRIORITY_OPT],
1574 eb5ac108 Michael Hanselmann
    "[instance...]", "Updates mismatches in recorded disk sizes"),
1575 d0c8c01d Iustin Pop
  "master-failover": (
1576 6022a419 Iustin Pop
    MasterFailover, ARGS_NONE, [NOVOTING_OPT, FORCE_FAILOVER],
1577 6ea815cf Iustin Pop
    "", "Makes the current node the master"),
1578 d0c8c01d Iustin Pop
  "master-ping": (
1579 4404ffad Iustin Pop
    MasterPing, ARGS_NONE, [],
1580 4404ffad Iustin Pop
    "", "Checks if the master is alive"),
1581 d0c8c01d Iustin Pop
  "version": (
1582 064c21f8 Iustin Pop
    ShowClusterVersion, ARGS_NONE, [],
1583 6ea815cf Iustin Pop
    "", "Shows the cluster version"),
1584 d0c8c01d Iustin Pop
  "getmaster": (
1585 064c21f8 Iustin Pop
    ShowClusterMaster, ARGS_NONE, [],
1586 6ea815cf Iustin Pop
    "", "Shows the cluster master"),
1587 d0c8c01d Iustin Pop
  "copyfile": (
1588 6ea815cf Iustin Pop
    ClusterCopyFile, [ArgFile(min=1, max=1)],
1589 b6e88032 Michael Hanselmann
    [NODE_LIST_OPT, USE_REPL_NET_OPT, NODEGROUP_OPT],
1590 6ea815cf Iustin Pop
    "[-n node...] <filename>", "Copies a file to all (or only some) nodes"),
1591 d0c8c01d Iustin Pop
  "command": (
1592 6ea815cf Iustin Pop
    RunClusterCommand, [ArgCommand(min=1)],
1593 d5b031dc Michael Hanselmann
    [NODE_LIST_OPT, NODEGROUP_OPT, SHOW_MACHINE_OPT, FAILURE_ONLY_OPT],
1594 6ea815cf Iustin Pop
    "[-n node...] <command>", "Runs a command on all (or only some) nodes"),
1595 d0c8c01d Iustin Pop
  "info": (
1596 d729e03a Guido Trotter
    ShowClusterConfig, ARGS_NONE, [ROMAN_OPT],
1597 d729e03a Guido Trotter
    "[--roman]", "Show cluster configuration"),
1598 d0c8c01d Iustin Pop
  "list-tags": (
1599 064c21f8 Iustin Pop
    ListTags, ARGS_NONE, [], "", "List the tags of the cluster"),
1600 d0c8c01d Iustin Pop
  "add-tags": (
1601 d6cd74dd Klaus Aehlig
    AddTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
1602 6ea815cf Iustin Pop
    "tag...", "Add tags to the cluster"),
1603 d0c8c01d Iustin Pop
  "remove-tags": (
1604 d6cd74dd Klaus Aehlig
    RemoveTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
1605 6ea815cf Iustin Pop
    "tag...", "Remove tags from the cluster"),
1606 d0c8c01d Iustin Pop
  "search-tags": (
1607 aa06f8c6 Michael Hanselmann
    SearchTags, [ArgUnknown(min=1, max=1)], [PRIORITY_OPT], "",
1608 aa06f8c6 Michael Hanselmann
    "Searches the tags on all objects on"
1609 6ea815cf Iustin Pop
    " the cluster for a given pattern (regex)"),
1610 d0c8c01d Iustin Pop
  "queue": (
1611 6ea815cf Iustin Pop
    QueueOps,
1612 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["drain", "undrain", "info"])],
1613 064c21f8 Iustin Pop
    [], "drain|undrain|info", "Change queue properties"),
1614 d0c8c01d Iustin Pop
  "watcher": (
1615 6ea815cf Iustin Pop
    WatcherOps,
1616 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["pause", "continue", "info"]),
1617 6ea815cf Iustin Pop
     ArgSuggest(min=0, max=1, choices=["30m", "1h", "4h"])],
1618 064c21f8 Iustin Pop
    [],
1619 6ea815cf Iustin Pop
    "{pause <timespec>|continue|info}", "Change watcher properties"),
1620 d0c8c01d Iustin Pop
  "modify": (
1621 6ea815cf Iustin Pop
    SetClusterParams, ARGS_NONE,
1622 2f836021 Klaus Aehlig
    [FORCE_OPT,
1623 2f836021 Klaus Aehlig
     BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, HVLIST_OPT, MASTER_NETDEV_OPT,
1624 5a8648eb Andrea Spadaccini
     MASTER_NETMASK_OPT, NIC_PARAMS_OPT, NOLVM_STORAGE_OPT, VG_NAME_OPT,
1625 5a8648eb Andrea Spadaccini
     MAINTAIN_NODE_HEALTH_OPT, UIDPOOL_OPT, ADD_UIDS_OPT, REMOVE_UIDS_OPT,
1626 5a8648eb Andrea Spadaccini
     DRBD_HELPER_OPT, NODRBD_STORAGE_OPT, DEFAULT_IALLOCATOR_OPT,
1627 5a8648eb Andrea Spadaccini
     RESERVED_LVS_OPT, DRY_RUN_OPT, PRIORITY_OPT, PREALLOC_WIPE_DISKS_OPT,
1628 2da9f556 René Nussbaumer
     NODE_PARAMS_OPT, USE_EXTERNAL_MIP_SCRIPT, DISK_PARAMS_OPT, HV_STATE_OPT,
1629 d6cd74dd Klaus Aehlig
     DISK_STATE_OPT] + SUBMIT_OPTS +
1630 c832f7e9 Klaus Aehlig
     [ENABLED_DISK_TEMPLATES_OPT, IPOLICY_STD_SPECS_OPT, MODIFY_ETCHOSTS_OPT] +
1631 3039e2dc Helga Velroyen
     INSTANCE_POLICY_OPTS + [GLOBAL_FILEDIR_OPT],
1632 6ea815cf Iustin Pop
    "[opts...]",
1633 6ea815cf Iustin Pop
    "Alters the parameters of the cluster"),
1634 6d4a1656 Michael Hanselmann
  "renew-crypto": (
1635 6d4a1656 Michael Hanselmann
    RenewCrypto, ARGS_NONE,
1636 6b7d5878 Michael Hanselmann
    [NEW_CLUSTER_CERT_OPT, NEW_RAPI_CERT_OPT, RAPI_CERT_OPT,
1637 3db3eb2a Michael Hanselmann
     NEW_CONFD_HMAC_KEY_OPT, FORCE_OPT,
1638 b6267745 Andrea Spadaccini
     NEW_CLUSTER_DOMAIN_SECRET_OPT, CLUSTER_DOMAIN_SECRET_OPT,
1639 b6267745 Andrea Spadaccini
     NEW_SPICE_CERT_OPT, SPICE_CERT_OPT, SPICE_CACERT_OPT],
1640 6d4a1656 Michael Hanselmann
    "[opts...]",
1641 6d4a1656 Michael Hanselmann
    "Renews cluster certificates, keys and secrets"),
1642 66d1f035 René Nussbaumer
  "epo": (
1643 66d1f035 René Nussbaumer
    Epo, [ArgUnknown()],
1644 fcecea0b René Nussbaumer
    [FORCE_OPT, ON_OPT, GROUPS_OPT, ALL_OPT, OOB_TIMEOUT_OPT,
1645 cfed3b9f René Nussbaumer
     SHUTDOWN_TIMEOUT_OPT, POWER_DELAY_OPT],
1646 66d1f035 René Nussbaumer
    "[opts...] [args]",
1647 66d1f035 René Nussbaumer
    "Performs an emergency power-off on given args"),
1648 fb926117 Andrea Spadaccini
  "activate-master-ip": (
1649 fb926117 Andrea Spadaccini
    ActivateMasterIp, ARGS_NONE, [], "", "Activates the master IP"),
1650 fb926117 Andrea Spadaccini
  "deactivate-master-ip": (
1651 fb926117 Andrea Spadaccini
    DeactivateMasterIp, ARGS_NONE, [CONFIRM_OPT], "",
1652 fb926117 Andrea Spadaccini
    "Deactivates the master IP"),
1653 ea9d3b40 Bernardo Dal Seno
  "show-ispecs-cmd": (
1654 ea9d3b40 Bernardo Dal Seno
    ShowCreateCommand, ARGS_NONE, [], "",
1655 ea9d3b40 Bernardo Dal Seno
    "Show the command line to re-create the cluster"),
1656 a8083063 Iustin Pop
  }
1657 a8083063 Iustin Pop
1658 6d4a1656 Michael Hanselmann
1659 c28502b1 Iustin Pop
#: dictionary with aliases for commands
1660 c28502b1 Iustin Pop
aliases = {
1661 d0c8c01d Iustin Pop
  "masterfailover": "master-failover",
1662 96897af7 Alexander Schreiber
  "show": "info",
1663 c28502b1 Iustin Pop
}
1664 c28502b1 Iustin Pop
1665 c28502b1 Iustin Pop
1666 7b3e7d41 Michael Hanselmann
def Main():
1667 7b3e7d41 Michael Hanselmann
  return GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER},
1668 7b3e7d41 Michael Hanselmann
                     aliases=aliases)