Statistics
| Branch: | Tag: | Revision:

root / lib / client / gnt_cluster.py @ c270ee07

History | View | Annotate | Download (51.7 kB)

1 7b3e7d41 Michael Hanselmann
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 c20a19ed Iustin Pop
# Copyright (C) 2006, 2007, 2010, 2011, 2012 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 b3989551 Iustin Pop
import os.path
30 95b2e626 Michael Hanselmann
import time
31 6d4a1656 Michael Hanselmann
import OpenSSL
32 66d1f035 René Nussbaumer
import itertools
33 a8083063 Iustin Pop
34 a8083063 Iustin Pop
from ganeti.cli import *
35 a8083063 Iustin Pop
from ganeti import opcodes
36 c2a62a33 Michael Hanselmann
from ganeti import constants
37 f4d4e184 Iustin Pop
from ganeti import errors
38 b63ed789 Iustin Pop
from ganeti import utils
39 a0c9f010 Michael Hanselmann
from ganeti import bootstrap
40 b3989551 Iustin Pop
from ganeti import ssh
41 d3cfe525 Guido Trotter
from ganeti import objects
42 1338f2b4 Balazs Lecz
from ganeti import uidpool
43 cea881e5 Michael Hanselmann
from ganeti import compat
44 66d1f035 René Nussbaumer
from ganeti import netutils
45 78e706bb Michael Hanselmann
from ganeti import pathutils
46 66d1f035 René Nussbaumer
47 66d1f035 René Nussbaumer
48 66d1f035 René Nussbaumer
ON_OPT = cli_option("--on", default=False,
49 66d1f035 René Nussbaumer
                    action="store_true", dest="on",
50 66d1f035 René Nussbaumer
                    help="Recover from an EPO")
51 66d1f035 René Nussbaumer
52 66d1f035 René Nussbaumer
GROUPS_OPT = cli_option("--groups", default=False,
53 5ae4945a Iustin Pop
                        action="store_true", dest="groups",
54 5ae4945a Iustin Pop
                        help="Arguments are node groups instead of nodes")
55 66d1f035 René Nussbaumer
56 6022a419 Iustin Pop
FORCE_FAILOVER = cli_option("--yes-do-it", dest="yes_do_it",
57 6022a419 Iustin Pop
                            help="Override interactive check for --no-voting",
58 6022a419 Iustin Pop
                            default=False, action="store_true")
59 6022a419 Iustin Pop
60 66d1f035 René Nussbaumer
_EPO_PING_INTERVAL = 30 # 30 seconds between pings
61 66d1f035 René Nussbaumer
_EPO_PING_TIMEOUT = 1 # 1 second
62 66d1f035 René Nussbaumer
_EPO_REACHABLE_TIMEOUT = 15 * 60 # 15 minutes
63 a8083063 Iustin Pop
64 a8083063 Iustin Pop
65 4331f6cd Michael Hanselmann
@UsesRPC
66 a8083063 Iustin Pop
def InitCluster(opts, args):
67 a8083063 Iustin Pop
  """Initialize the cluster.
68 a8083063 Iustin Pop

69 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
70 469ee405 Iustin Pop
  @type args: list
71 469ee405 Iustin Pop
  @param args: should contain only one element, the desired
72 469ee405 Iustin Pop
      cluster name
73 469ee405 Iustin Pop
  @rtype: int
74 469ee405 Iustin Pop
  @return: the desired exit code
75 a8083063 Iustin Pop

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

234 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
235 469ee405 Iustin Pop
  @type args: list
236 469ee405 Iustin Pop
  @param args: should be an empty list
237 469ee405 Iustin Pop
  @rtype: int
238 469ee405 Iustin Pop
  @return: the desired exit code
239 098c0958 Michael Hanselmann

240 a8083063 Iustin Pop
  """
241 a8083063 Iustin Pop
  if not opts.yes_do_it:
242 3a24c527 Iustin Pop
    ToStderr("Destroying a cluster is irreversible. If you really want"
243 3a24c527 Iustin Pop
             " destroy this cluster, supply the --yes-do-it option.")
244 a8083063 Iustin Pop
    return 1
245 a8083063 Iustin Pop
246 c6d43e9e Iustin Pop
  op = opcodes.OpClusterDestroy()
247 400ca2f7 Iustin Pop
  master = SubmitOpCode(op, opts=opts)
248 140aa4a8 Iustin Pop
  # if we reached this, the opcode didn't fail; we can proceed to
249 140aa4a8 Iustin Pop
  # shutdown all the daemons
250 140aa4a8 Iustin Pop
  bootstrap.FinalizeClusterDestroy(master)
251 a8083063 Iustin Pop
  return 0
252 a8083063 Iustin Pop
253 a8083063 Iustin Pop
254 07bd8a51 Iustin Pop
def RenameCluster(opts, args):
255 07bd8a51 Iustin Pop
  """Rename the cluster.
256 07bd8a51 Iustin Pop

257 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
258 469ee405 Iustin Pop
  @type args: list
259 469ee405 Iustin Pop
  @param args: should contain only one element, the new cluster name
260 469ee405 Iustin Pop
  @rtype: int
261 469ee405 Iustin Pop
  @return: the desired exit code
262 07bd8a51 Iustin Pop

263 07bd8a51 Iustin Pop
  """
264 6a016df9 Michael Hanselmann
  cl = GetClient()
265 6a016df9 Michael Hanselmann
266 6a016df9 Michael Hanselmann
  (cluster_name, ) = cl.QueryConfigValues(["cluster_name"])
267 6a016df9 Michael Hanselmann
268 6a016df9 Michael Hanselmann
  new_name = args[0]
269 07bd8a51 Iustin Pop
  if not opts.force:
270 6a016df9 Michael Hanselmann
    usertext = ("This will rename the cluster from '%s' to '%s'. If you are"
271 6a016df9 Michael Hanselmann
                " connected over the network to the cluster name, the"
272 6a016df9 Michael Hanselmann
                " operation is very dangerous as the IP address will be"
273 6a016df9 Michael Hanselmann
                " removed from the node and the change may not go through."
274 6a016df9 Michael Hanselmann
                " Continue?") % (cluster_name, new_name)
275 47988778 Iustin Pop
    if not AskUser(usertext):
276 07bd8a51 Iustin Pop
      return 1
277 07bd8a51 Iustin Pop
278 e126df25 Iustin Pop
  op = opcodes.OpClusterRename(name=new_name)
279 6a016df9 Michael Hanselmann
  result = SubmitOpCode(op, opts=opts, cl=cl)
280 6a016df9 Michael Hanselmann
281 48418fea Iustin Pop
  if result:
282 48418fea Iustin Pop
    ToStdout("Cluster renamed from '%s' to '%s'", cluster_name, result)
283 6a016df9 Michael Hanselmann
284 07bd8a51 Iustin Pop
  return 0
285 07bd8a51 Iustin Pop
286 07bd8a51 Iustin Pop
287 fb926117 Andrea Spadaccini
def ActivateMasterIp(opts, args):
288 fb926117 Andrea Spadaccini
  """Activates the master IP.
289 fb926117 Andrea Spadaccini

290 fb926117 Andrea Spadaccini
  """
291 fb926117 Andrea Spadaccini
  op = opcodes.OpClusterActivateMasterIp()
292 fb926117 Andrea Spadaccini
  SubmitOpCode(op)
293 fb926117 Andrea Spadaccini
  return 0
294 fb926117 Andrea Spadaccini
295 fb926117 Andrea Spadaccini
296 fb926117 Andrea Spadaccini
def DeactivateMasterIp(opts, args):
297 fb926117 Andrea Spadaccini
  """Deactivates the master IP.
298 fb926117 Andrea Spadaccini

299 fb926117 Andrea Spadaccini
  """
300 fb926117 Andrea Spadaccini
  if not opts.confirm:
301 fb926117 Andrea Spadaccini
    usertext = ("This will disable the master IP. All the open connections to"
302 fb926117 Andrea Spadaccini
                " the master IP will be closed. To reach the master you will"
303 fb926117 Andrea Spadaccini
                " need to use its node IP."
304 fb926117 Andrea Spadaccini
                " Continue?")
305 fb926117 Andrea Spadaccini
    if not AskUser(usertext):
306 fb926117 Andrea Spadaccini
      return 1
307 fb926117 Andrea Spadaccini
308 fb926117 Andrea Spadaccini
  op = opcodes.OpClusterDeactivateMasterIp()
309 fb926117 Andrea Spadaccini
  SubmitOpCode(op)
310 fb926117 Andrea Spadaccini
  return 0
311 fb926117 Andrea Spadaccini
312 fb926117 Andrea Spadaccini
313 afee0879 Iustin Pop
def RedistributeConfig(opts, args):
314 afee0879 Iustin Pop
  """Forces push of the cluster configuration.
315 afee0879 Iustin Pop

316 afee0879 Iustin Pop
  @param opts: the command line options selected by the user
317 afee0879 Iustin Pop
  @type args: list
318 afee0879 Iustin Pop
  @param args: empty list
319 afee0879 Iustin Pop
  @rtype: int
320 afee0879 Iustin Pop
  @return: the desired exit code
321 afee0879 Iustin Pop

322 afee0879 Iustin Pop
  """
323 d1240007 Iustin Pop
  op = opcodes.OpClusterRedistConf()
324 afee0879 Iustin Pop
  SubmitOrSend(op, opts)
325 afee0879 Iustin Pop
  return 0
326 afee0879 Iustin Pop
327 afee0879 Iustin Pop
328 a8083063 Iustin Pop
def ShowClusterVersion(opts, args):
329 a8083063 Iustin Pop
  """Write version of ganeti software to the standard output.
330 a8083063 Iustin Pop

331 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
332 469ee405 Iustin Pop
  @type args: list
333 469ee405 Iustin Pop
  @param args: should be an empty list
334 469ee405 Iustin Pop
  @rtype: int
335 469ee405 Iustin Pop
  @return: the desired exit code
336 a8083063 Iustin Pop

337 a8083063 Iustin Pop
  """
338 42ab9ac4 Iustin Pop
  cl = GetClient(query=True)
339 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
340 3a24c527 Iustin Pop
  ToStdout("Software version: %s", result["software_version"])
341 3a24c527 Iustin Pop
  ToStdout("Internode protocol: %s", result["protocol_version"])
342 3a24c527 Iustin Pop
  ToStdout("Configuration format: %s", result["config_version"])
343 3a24c527 Iustin Pop
  ToStdout("OS api version: %s", result["os_api_version"])
344 3a24c527 Iustin Pop
  ToStdout("Export interface: %s", result["export_version"])
345 a8083063 Iustin Pop
  return 0
346 a8083063 Iustin Pop
347 a8083063 Iustin Pop
348 a8083063 Iustin Pop
def ShowClusterMaster(opts, args):
349 a8083063 Iustin Pop
  """Write name of master node to the standard output.
350 a8083063 Iustin Pop

351 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
352 469ee405 Iustin Pop
  @type args: list
353 469ee405 Iustin Pop
  @param args: should be an empty list
354 469ee405 Iustin Pop
  @rtype: int
355 469ee405 Iustin Pop
  @return: the desired exit code
356 a8083063 Iustin Pop

357 a8083063 Iustin Pop
  """
358 8eb148ae Iustin Pop
  master = bootstrap.GetMaster()
359 8eb148ae Iustin Pop
  ToStdout(master)
360 a8083063 Iustin Pop
  return 0
361 a8083063 Iustin Pop
362 cac599f1 Michael Hanselmann
363 d729e03a Guido Trotter
def _PrintGroupedParams(paramsdict, level=1, roman=False):
364 1094acda Guido Trotter
  """Print Grouped parameters (be, nic, disk) by group.
365 1094acda Guido Trotter

366 1094acda Guido Trotter
  @type paramsdict: dict of dicts
367 1094acda Guido Trotter
  @param paramsdict: {group: {param: value, ...}, ...}
368 664a9d73 René Nussbaumer
  @type level: int
369 664a9d73 René Nussbaumer
  @param level: Level of indention
370 1094acda Guido Trotter

371 1094acda Guido Trotter
  """
372 664a9d73 René Nussbaumer
  indent = "  " * level
373 9d91c6ab Guido Trotter
  for item, val in sorted(paramsdict.items()):
374 664a9d73 René Nussbaumer
    if isinstance(val, dict):
375 664a9d73 René Nussbaumer
      ToStdout("%s- %s:", indent, item)
376 d729e03a Guido Trotter
      _PrintGroupedParams(val, level=level + 1, roman=roman)
377 d729e03a Guido Trotter
    elif roman and isinstance(val, int):
378 d729e03a Guido Trotter
      ToStdout("%s  %s: %s", indent, item, compat.TryToRoman(val))
379 664a9d73 René Nussbaumer
    else:
380 664a9d73 René Nussbaumer
      ToStdout("%s  %s: %s", indent, item, val)
381 a8083063 Iustin Pop
382 cac599f1 Michael Hanselmann
383 a8083063 Iustin Pop
def ShowClusterConfig(opts, args):
384 a8083063 Iustin Pop
  """Shows cluster information.
385 a8083063 Iustin Pop

386 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
387 469ee405 Iustin Pop
  @type args: list
388 469ee405 Iustin Pop
  @param args: should be an empty list
389 469ee405 Iustin Pop
  @rtype: int
390 469ee405 Iustin Pop
  @return: the desired exit code
391 469ee405 Iustin Pop

392 a8083063 Iustin Pop
  """
393 a2160e57 Iustin Pop
  cl = GetClient(query=True)
394 2e7b8369 Iustin Pop
  result = cl.QueryClusterInfo()
395 a8083063 Iustin Pop
396 3a24c527 Iustin Pop
  ToStdout("Cluster name: %s", result["name"])
397 259578eb Iustin Pop
  ToStdout("Cluster UUID: %s", result["uuid"])
398 a8083063 Iustin Pop
399 90f72445 Iustin Pop
  ToStdout("Creation time: %s", utils.FormatTime(result["ctime"]))
400 90f72445 Iustin Pop
  ToStdout("Modification time: %s", utils.FormatTime(result["mtime"]))
401 90f72445 Iustin Pop
402 3a24c527 Iustin Pop
  ToStdout("Master node: %s", result["master"])
403 a8083063 Iustin Pop
404 3a24c527 Iustin Pop
  ToStdout("Architecture (this node): %s (%s)",
405 3a24c527 Iustin Pop
           result["architecture"][0], result["architecture"][1])
406 a8083063 Iustin Pop
407 c118d1f4 Michael Hanselmann
  if result["tags"]:
408 1f864b60 Iustin Pop
    tags = utils.CommaJoin(utils.NiceSort(result["tags"]))
409 c118d1f4 Michael Hanselmann
  else:
410 c118d1f4 Michael Hanselmann
    tags = "(none)"
411 c118d1f4 Michael Hanselmann
412 c118d1f4 Michael Hanselmann
  ToStdout("Tags: %s", tags)
413 c118d1f4 Michael Hanselmann
414 02691904 Alexander Schreiber
  ToStdout("Default hypervisor: %s", result["default_hypervisor"])
415 1f864b60 Iustin Pop
  ToStdout("Enabled hypervisors: %s",
416 1f864b60 Iustin Pop
           utils.CommaJoin(result["enabled_hypervisors"]))
417 469f88e1 Iustin Pop
418 3a24c527 Iustin Pop
  ToStdout("Hypervisor parameters:")
419 1094acda Guido Trotter
  _PrintGroupedParams(result["hvparams"])
420 469f88e1 Iustin Pop
421 dbb24ec7 Iustin Pop
  ToStdout("OS-specific hypervisor parameters:")
422 664a9d73 René Nussbaumer
  _PrintGroupedParams(result["os_hvp"])
423 664a9d73 René Nussbaumer
424 dbb24ec7 Iustin Pop
  ToStdout("OS parameters:")
425 dbb24ec7 Iustin Pop
  _PrintGroupedParams(result["osparams"])
426 dbb24ec7 Iustin Pop
427 afc3c260 Iustin Pop
  ToStdout("Hidden OSes: %s", utils.CommaJoin(result["hidden_os"]))
428 afc3c260 Iustin Pop
  ToStdout("Blacklisted OSes: %s", utils.CommaJoin(result["blacklisted_os"]))
429 afc3c260 Iustin Pop
430 3a24c527 Iustin Pop
  ToStdout("Cluster parameters:")
431 d729e03a Guido Trotter
  ToStdout("  - candidate pool size: %s",
432 d729e03a Guido Trotter
            compat.TryToRoman(result["candidate_pool_size"],
433 d729e03a Guido Trotter
                              convert=opts.roman_integers))
434 a8001106 Guido Trotter
  ToStdout("  - master netdev: %s", result["master_netdev"])
435 5a8648eb Andrea Spadaccini
  ToStdout("  - master netmask: %s", result["master_netmask"])
436 bf689b7a Andrea Spadaccini
  ToStdout("  - use external master IP address setup script: %s",
437 bf689b7a Andrea Spadaccini
           result["use_external_mip_script"])
438 a8001106 Guido Trotter
  ToStdout("  - lvm volume group: %s", result["volume_group_name"])
439 5a3ab484 Iustin Pop
  if result["reserved_lvs"]:
440 5a3ab484 Iustin Pop
    reserved_lvs = utils.CommaJoin(result["reserved_lvs"])
441 5a3ab484 Iustin Pop
  else:
442 5a3ab484 Iustin Pop
    reserved_lvs = "(none)"
443 5a3ab484 Iustin Pop
  ToStdout("  - lvm reserved volumes: %s", reserved_lvs)
444 ed14ed48 Luca Bigliardi
  ToStdout("  - drbd usermode helper: %s", result["drbd_usermode_helper"])
445 a8001106 Guido Trotter
  ToStdout("  - file storage path: %s", result["file_storage_dir"])
446 4b97f902 Apollon Oikonomopoulos
  ToStdout("  - shared file storage path: %s",
447 4b97f902 Apollon Oikonomopoulos
           result["shared_file_storage_dir"])
448 3953242f Iustin Pop
  ToStdout("  - maintenance of node health: %s",
449 3953242f Iustin Pop
           result["maintain_node_health"])
450 23f1bf29 Michael Hanselmann
  ToStdout("  - uid pool: %s", uidpool.FormatUidPool(result["uid_pool"]))
451 bf4af505 Apollon Oikonomopoulos
  ToStdout("  - default instance allocator: %s", result["default_iallocator"])
452 e7323b5e Manuel Franceschini
  ToStdout("  - primary ip version: %d", result["primary_ip_version"])
453 b18ecea2 René Nussbaumer
  ToStdout("  - preallocation wipe disks: %s", result["prealloc_wipe_disks"])
454 78e706bb Michael Hanselmann
  ToStdout("  - OS search path: %s", utils.CommaJoin(pathutils.OS_SEARCH_PATH))
455 376631d1 Constantinos Venetsanopoulos
  ToStdout("  - ExtStorage Providers search path: %s",
456 376631d1 Constantinos Venetsanopoulos
           utils.CommaJoin(pathutils.ES_SEARCH_PATH))
457 7b9ceea7 Helga Velroyen
  ToStdout("  - enabled storage types: %s",
458 7b9ceea7 Helga Velroyen
           utils.CommaJoin(result["enabled_storage_types"]))
459 4b7735f9 Iustin Pop
460 88be69ee René Nussbaumer
  ToStdout("Default node parameters:")
461 88be69ee René Nussbaumer
  _PrintGroupedParams(result["ndparams"], roman=opts.roman_integers)
462 88be69ee René Nussbaumer
463 4b7735f9 Iustin Pop
  ToStdout("Default instance parameters:")
464 d729e03a Guido Trotter
  _PrintGroupedParams(result["beparams"], roman=opts.roman_integers)
465 1094acda Guido Trotter
466 1094acda Guido Trotter
  ToStdout("Default nic parameters:")
467 d729e03a Guido Trotter
  _PrintGroupedParams(result["nicparams"], roman=opts.roman_integers)
468 8a12ce45 Iustin Pop
469 f9bbf32b René Nussbaumer
  ToStdout("Default disk parameters:")
470 f9bbf32b René Nussbaumer
  _PrintGroupedParams(result["diskparams"], roman=opts.roman_integers)
471 f9bbf32b René Nussbaumer
472 be499e31 Agata Murawska
  ToStdout("Instance policy - limits for instances:")
473 12378fe3 Iustin Pop
  for key in constants.IPOLICY_ISPECS:
474 be499e31 Agata Murawska
    ToStdout("  - %s", key)
475 be499e31 Agata Murawska
    _PrintGroupedParams(result["ipolicy"][key], roman=opts.roman_integers)
476 2cc673a3 Iustin Pop
  ToStdout("  - enabled disk templates: %s",
477 d04c9d45 Iustin Pop
           utils.CommaJoin(result["ipolicy"][constants.IPOLICY_DTS]))
478 ff6c5e55 Iustin Pop
  for key in constants.IPOLICY_PARAMETERS:
479 ff6c5e55 Iustin Pop
    ToStdout("  - %s: %s", key, result["ipolicy"][key])
480 be499e31 Agata Murawska
481 a8083063 Iustin Pop
  return 0
482 a8083063 Iustin Pop
483 a8083063 Iustin Pop
484 a8083063 Iustin Pop
def ClusterCopyFile(opts, args):
485 a8083063 Iustin Pop
  """Copy a file from master to some nodes.
486 a8083063 Iustin Pop

487 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
488 469ee405 Iustin Pop
  @type args: list
489 469ee405 Iustin Pop
  @param args: should contain only one element, the path of
490 469ee405 Iustin Pop
      the file to be copied
491 469ee405 Iustin Pop
  @rtype: int
492 469ee405 Iustin Pop
  @return: the desired exit code
493 a8083063 Iustin Pop

494 a8083063 Iustin Pop
  """
495 b3989551 Iustin Pop
  filename = args[0]
496 b3989551 Iustin Pop
  if not os.path.exists(filename):
497 debac808 Iustin Pop
    raise errors.OpPrereqError("No such filename '%s'" % filename,
498 debac808 Iustin Pop
                               errors.ECODE_INVAL)
499 b3989551 Iustin Pop
500 56bece1f Iustin Pop
  cl = GetClient()
501 56bece1f Iustin Pop
502 56bece1f Iustin Pop
  cluster_name = cl.QueryConfigValues(["cluster_name"])[0]
503 56bece1f Iustin Pop
504 74adc100 Iustin Pop
  results = GetOnlineNodes(nodes=opts.nodes, cl=cl, filter_master=True,
505 b6e88032 Michael Hanselmann
                           secondary_ips=opts.use_replication_network,
506 b6e88032 Michael Hanselmann
                           nodegroup=opts.nodegroup)
507 e00ea635 Michael Hanselmann
508 224ff0f7 Michael Hanselmann
  srun = ssh.SshRunner(cluster_name)
509 b3989551 Iustin Pop
  for node in results:
510 b3989551 Iustin Pop
    if not srun.CopyFileToNode(node, filename):
511 3a24c527 Iustin Pop
      ToStderr("Copy of file %s to node %s failed", filename, node)
512 b3989551 Iustin Pop
513 a8083063 Iustin Pop
  return 0
514 a8083063 Iustin Pop
515 a8083063 Iustin Pop
516 a8083063 Iustin Pop
def RunClusterCommand(opts, args):
517 a8083063 Iustin Pop
  """Run a command on some nodes.
518 a8083063 Iustin Pop

519 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
520 469ee405 Iustin Pop
  @type args: list
521 469ee405 Iustin Pop
  @param args: should contain the command to be run and its arguments
522 469ee405 Iustin Pop
  @rtype: int
523 469ee405 Iustin Pop
  @return: the desired exit code
524 a8083063 Iustin Pop

525 a8083063 Iustin Pop
  """
526 56bece1f Iustin Pop
  cl = GetClient()
527 7688d0d3 Michael Hanselmann
528 a8083063 Iustin Pop
  command = " ".join(args)
529 4040a784 Iustin Pop
530 b6e88032 Michael Hanselmann
  nodes = GetOnlineNodes(nodes=opts.nodes, cl=cl, nodegroup=opts.nodegroup)
531 56bece1f Iustin Pop
532 56bece1f Iustin Pop
  cluster_name, master_node = cl.QueryConfigValues(["cluster_name",
533 56bece1f Iustin Pop
                                                    "master_node"])
534 b3989551 Iustin Pop
535 56bece1f Iustin Pop
  srun = ssh.SshRunner(cluster_name=cluster_name)
536 b3989551 Iustin Pop
537 7688d0d3 Michael Hanselmann
  # Make sure master node is at list end
538 b3989551 Iustin Pop
  if master_node in nodes:
539 b3989551 Iustin Pop
    nodes.remove(master_node)
540 b3989551 Iustin Pop
    nodes.append(master_node)
541 b3989551 Iustin Pop
542 b3989551 Iustin Pop
  for name in nodes:
543 052783ff Michael Hanselmann
    result = srun.Run(name, constants.SSH_LOGIN_USER, command)
544 d5b031dc Michael Hanselmann
545 d5b031dc Michael Hanselmann
    if opts.failure_only and result.exit_code == constants.EXIT_SUCCESS:
546 d5b031dc Michael Hanselmann
      # Do not output anything for successful commands
547 d5b031dc Michael Hanselmann
      continue
548 d5b031dc Michael Hanselmann
549 3a24c527 Iustin Pop
    ToStdout("------------------------------------------------")
550 a24aed2a Michael Hanselmann
    if opts.show_machine_names:
551 a24aed2a Michael Hanselmann
      for line in result.output.splitlines():
552 a24aed2a Michael Hanselmann
        ToStdout("%s: %s", name, line)
553 a24aed2a Michael Hanselmann
    else:
554 a24aed2a Michael Hanselmann
      ToStdout("node: %s", name)
555 a24aed2a Michael Hanselmann
      ToStdout("%s", result.output)
556 3a24c527 Iustin Pop
    ToStdout("return code = %s", result.exit_code)
557 b3989551 Iustin Pop
558 b3989551 Iustin Pop
  return 0
559 a8083063 Iustin Pop
560 a8083063 Iustin Pop
561 a8083063 Iustin Pop
def VerifyCluster(opts, args):
562 a8083063 Iustin Pop
  """Verify integrity of cluster, performing various test on nodes.
563 a8083063 Iustin Pop

564 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
565 469ee405 Iustin Pop
  @type args: list
566 469ee405 Iustin Pop
  @param args: should be an empty list
567 469ee405 Iustin Pop
  @rtype: int
568 469ee405 Iustin Pop
  @return: the desired exit code
569 a8083063 Iustin Pop

570 a8083063 Iustin Pop
  """
571 8d59409f Iustin Pop
  skip_checks = []
572 bf93ae69 Adeodato Simo
573 e54c4c5e Guido Trotter
  if opts.skip_nplusone_mem:
574 e54c4c5e Guido Trotter
    skip_checks.append(constants.VERIFY_NPLUSONE_MEM)
575 bf93ae69 Adeodato Simo
576 fcad7225 Michael Hanselmann
  cl = GetClient()
577 bf93ae69 Adeodato Simo
578 fcad7225 Michael Hanselmann
  op = opcodes.OpClusterVerify(verbose=opts.verbose,
579 fcad7225 Michael Hanselmann
                               error_codes=opts.error_codes,
580 fcad7225 Michael Hanselmann
                               debug_simulate_errors=opts.simulate_errors,
581 fcad7225 Michael Hanselmann
                               skip_checks=skip_checks,
582 93f2399e Andrea Spadaccini
                               ignore_errors=opts.ignore_errors,
583 fcad7225 Michael Hanselmann
                               group_name=opts.nodegroup)
584 fcad7225 Michael Hanselmann
  result = SubmitOpCode(op, cl=cl, opts=opts)
585 bf93ae69 Adeodato Simo
586 fcad7225 Michael Hanselmann
  # Keep track of submitted jobs
587 fcad7225 Michael Hanselmann
  jex = JobExecutor(cl=cl, opts=opts)
588 fcad7225 Michael Hanselmann
589 fcad7225 Michael Hanselmann
  for (status, job_id) in result[constants.JOB_IDS_KEY]:
590 fcad7225 Michael Hanselmann
    jex.AddJobId(None, status, job_id)
591 bf93ae69 Adeodato Simo
592 fcad7225 Michael Hanselmann
  results = jex.GetResults()
593 ebe6cf38 Michael Hanselmann
594 ebe6cf38 Michael Hanselmann
  (bad_jobs, bad_results) = \
595 ebe6cf38 Michael Hanselmann
    map(len,
596 ebe6cf38 Michael Hanselmann
        # Convert iterators to lists
597 ebe6cf38 Michael Hanselmann
        map(list,
598 ebe6cf38 Michael Hanselmann
            # Count errors
599 ebe6cf38 Michael Hanselmann
            map(compat.partial(itertools.ifilterfalse, bool),
600 ebe6cf38 Michael Hanselmann
                # Convert result to booleans in a tuple
601 ebe6cf38 Michael Hanselmann
                zip(*((job_success, len(op_results) == 1 and op_results[0])
602 ebe6cf38 Michael Hanselmann
                      for (job_success, op_results) in results)))))
603 ebe6cf38 Michael Hanselmann
604 ebe6cf38 Michael Hanselmann
  if bad_jobs == 0 and bad_results == 0:
605 fcad7225 Michael Hanselmann
    rcode = constants.EXIT_SUCCESS
606 e0508c86 Guido Trotter
  else:
607 fcad7225 Michael Hanselmann
    rcode = constants.EXIT_FAILURE
608 ebe6cf38 Michael Hanselmann
    if bad_jobs > 0:
609 ebe6cf38 Michael Hanselmann
      ToStdout("%s job(s) failed while verifying the cluster.", bad_jobs)
610 fcad7225 Michael Hanselmann
611 fcad7225 Michael Hanselmann
  return rcode
612 a8083063 Iustin Pop
613 a8083063 Iustin Pop
614 f4d4e184 Iustin Pop
def VerifyDisks(opts, args):
615 f4d4e184 Iustin Pop
  """Verify integrity of cluster disks.
616 f4d4e184 Iustin Pop

617 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
618 469ee405 Iustin Pop
  @type args: list
619 469ee405 Iustin Pop
  @param args: should be an empty list
620 469ee405 Iustin Pop
  @rtype: int
621 469ee405 Iustin Pop
  @return: the desired exit code
622 f4d4e184 Iustin Pop

623 f4d4e184 Iustin Pop
  """
624 f1b083ce Michael Hanselmann
  cl = GetClient()
625 f1b083ce Michael Hanselmann
626 bd8210a7 Iustin Pop
  op = opcodes.OpClusterVerifyDisks()
627 f4d4e184 Iustin Pop
628 ae1a845c Michael Hanselmann
  result = SubmitOpCode(op, cl=cl, opts=opts)
629 ae1a845c Michael Hanselmann
630 ae1a845c Michael Hanselmann
  # Keep track of submitted jobs
631 ae1a845c Michael Hanselmann
  jex = JobExecutor(cl=cl, opts=opts)
632 ae1a845c Michael Hanselmann
633 ae1a845c Michael Hanselmann
  for (status, job_id) in result[constants.JOB_IDS_KEY]:
634 ae1a845c Michael Hanselmann
    jex.AddJobId(None, status, job_id)
635 b63ed789 Iustin Pop
636 f4d4e184 Iustin Pop
  retcode = constants.EXIT_SUCCESS
637 b63ed789 Iustin Pop
638 ae1a845c Michael Hanselmann
  for (status, result) in jex.GetResults():
639 ae1a845c Michael Hanselmann
    if not status:
640 ae1a845c Michael Hanselmann
      ToStdout("Job failed: %s", result)
641 ae1a845c Michael Hanselmann
      continue
642 ae1a845c Michael Hanselmann
643 ae1a845c Michael Hanselmann
    ((bad_nodes, instances, missing), ) = result
644 ae1a845c Michael Hanselmann
645 29d376ec Iustin Pop
    for node, text in bad_nodes.items():
646 29d376ec Iustin Pop
      ToStdout("Error gathering data on node %s: %s",
647 26f15862 Iustin Pop
               node, utils.SafeEncode(text[-400:]))
648 ae1a845c Michael Hanselmann
      retcode = constants.EXIT_FAILURE
649 3a24c527 Iustin Pop
      ToStdout("You need to fix these nodes first before fixing instances")
650 b63ed789 Iustin Pop
651 f4d4e184 Iustin Pop
    for iname in instances:
652 b63ed789 Iustin Pop
      if iname in missing:
653 b63ed789 Iustin Pop
        continue
654 83f5d475 Iustin Pop
      op = opcodes.OpInstanceActivateDisks(instance_name=iname)
655 f4d4e184 Iustin Pop
      try:
656 3a24c527 Iustin Pop
        ToStdout("Activating disks for instance '%s'", iname)
657 f1b083ce Michael Hanselmann
        SubmitOpCode(op, opts=opts, cl=cl)
658 f4d4e184 Iustin Pop
      except errors.GenericError, err:
659 f4d4e184 Iustin Pop
        nret, msg = FormatError(err)
660 f4d4e184 Iustin Pop
        retcode |= nret
661 3a24c527 Iustin Pop
        ToStderr("Error activating disks for instance %s: %s", iname, msg)
662 b63ed789 Iustin Pop
663 ae1a845c Michael Hanselmann
    if missing:
664 ae1a845c Michael Hanselmann
      for iname, ival in missing.iteritems():
665 ae1a845c Michael Hanselmann
        all_missing = compat.all(x[0] in bad_nodes for x in ival)
666 ae1a845c Michael Hanselmann
        if all_missing:
667 ae1a845c Michael Hanselmann
          ToStdout("Instance %s cannot be verified as it lives on"
668 ae1a845c Michael Hanselmann
                   " broken nodes", iname)
669 ae1a845c Michael Hanselmann
        else:
670 ae1a845c Michael Hanselmann
          ToStdout("Instance %s has missing logical volumes:", iname)
671 ae1a845c Michael Hanselmann
          ival.sort()
672 ae1a845c Michael Hanselmann
          for node, vol in ival:
673 ae1a845c Michael Hanselmann
            if node in bad_nodes:
674 ae1a845c Michael Hanselmann
              ToStdout("\tbroken node %s /dev/%s", node, vol)
675 ae1a845c Michael Hanselmann
            else:
676 ae1a845c Michael Hanselmann
              ToStdout("\t%s /dev/%s", node, vol)
677 ae1a845c Michael Hanselmann
678 ae1a845c Michael Hanselmann
      ToStdout("You need to replace or recreate disks for all the above"
679 ae1a845c Michael Hanselmann
               " instances if this message persists after fixing broken nodes.")
680 ae1a845c Michael Hanselmann
      retcode = constants.EXIT_FAILURE
681 9b99be28 Michael Hanselmann
    elif not instances:
682 9b99be28 Michael Hanselmann
      ToStdout("No disks need to be activated.")
683 f4d4e184 Iustin Pop
684 f4d4e184 Iustin Pop
  return retcode
685 f4d4e184 Iustin Pop
686 f4d4e184 Iustin Pop
687 60975797 Iustin Pop
def RepairDiskSizes(opts, args):
688 60975797 Iustin Pop
  """Verify sizes of cluster disks.
689 60975797 Iustin Pop

690 60975797 Iustin Pop
  @param opts: the command line options selected by the user
691 60975797 Iustin Pop
  @type args: list
692 60975797 Iustin Pop
  @param args: optional list of instances to restrict check to
693 60975797 Iustin Pop
  @rtype: int
694 60975797 Iustin Pop
  @return: the desired exit code
695 60975797 Iustin Pop

696 60975797 Iustin Pop
  """
697 5d01aca3 Iustin Pop
  op = opcodes.OpClusterRepairDiskSizes(instances=args)
698 400ca2f7 Iustin Pop
  SubmitOpCode(op, opts=opts)
699 60975797 Iustin Pop
700 60975797 Iustin Pop
701 4331f6cd Michael Hanselmann
@UsesRPC
702 a8083063 Iustin Pop
def MasterFailover(opts, args):
703 a8083063 Iustin Pop
  """Failover the master node.
704 a8083063 Iustin Pop

705 a8083063 Iustin Pop
  This command, when run on a non-master node, will cause the current
706 a8083063 Iustin Pop
  master to cease being master, and the non-master to become new
707 a8083063 Iustin Pop
  master.
708 a8083063 Iustin Pop

709 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
710 469ee405 Iustin Pop
  @type args: list
711 469ee405 Iustin Pop
  @param args: should be an empty list
712 469ee405 Iustin Pop
  @rtype: int
713 469ee405 Iustin Pop
  @return: the desired exit code
714 469ee405 Iustin Pop

715 a8083063 Iustin Pop
  """
716 6022a419 Iustin Pop
  if opts.no_voting and not opts.yes_do_it:
717 8e2524c3 Guido Trotter
    usertext = ("This will perform the failover even if most other nodes"
718 8e2524c3 Guido Trotter
                " are down, or if this node is outdated. This is dangerous"
719 8e2524c3 Guido Trotter
                " as it can lead to a non-consistent cluster. Check the"
720 8e2524c3 Guido Trotter
                " gnt-cluster(8) man page before proceeding. Continue?")
721 8e2524c3 Guido Trotter
    if not AskUser(usertext):
722 8e2524c3 Guido Trotter
      return 1
723 8e2524c3 Guido Trotter
724 8e2524c3 Guido Trotter
  return bootstrap.MasterFailover(no_voting=opts.no_voting)
725 a8083063 Iustin Pop
726 a8083063 Iustin Pop
727 4404ffad Iustin Pop
def MasterPing(opts, args):
728 4404ffad Iustin Pop
  """Checks if the master is alive.
729 4404ffad Iustin Pop

730 4404ffad Iustin Pop
  @param opts: the command line options selected by the user
731 4404ffad Iustin Pop
  @type args: list
732 4404ffad Iustin Pop
  @param args: should be an empty list
733 4404ffad Iustin Pop
  @rtype: int
734 4404ffad Iustin Pop
  @return: the desired exit code
735 4404ffad Iustin Pop

736 4404ffad Iustin Pop
  """
737 4404ffad Iustin Pop
  try:
738 4404ffad Iustin Pop
    cl = GetClient()
739 4404ffad Iustin Pop
    cl.QueryClusterInfo()
740 4404ffad Iustin Pop
    return 0
741 b459a848 Andrea Spadaccini
  except Exception: # pylint: disable=W0703
742 4404ffad Iustin Pop
    return 1
743 4404ffad Iustin Pop
744 4404ffad Iustin Pop
745 73415719 Iustin Pop
def SearchTags(opts, args):
746 73415719 Iustin Pop
  """Searches the tags on all the cluster.
747 73415719 Iustin Pop

748 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
749 469ee405 Iustin Pop
  @type args: list
750 469ee405 Iustin Pop
  @param args: should contain only one element, the tag pattern
751 469ee405 Iustin Pop
  @rtype: int
752 469ee405 Iustin Pop
  @return: the desired exit code
753 469ee405 Iustin Pop

754 73415719 Iustin Pop
  """
755 715462e7 Iustin Pop
  op = opcodes.OpTagsSearch(pattern=args[0])
756 400ca2f7 Iustin Pop
  result = SubmitOpCode(op, opts=opts)
757 73415719 Iustin Pop
  if not result:
758 73415719 Iustin Pop
    return 1
759 73415719 Iustin Pop
  result = list(result)
760 73415719 Iustin Pop
  result.sort()
761 73415719 Iustin Pop
  for path, tag in result:
762 3a24c527 Iustin Pop
    ToStdout("%s %s", path, tag)
763 73415719 Iustin Pop
764 73415719 Iustin Pop
765 b6267745 Andrea Spadaccini
def _ReadAndVerifyCert(cert_filename, verify_private_key=False):
766 b6267745 Andrea Spadaccini
  """Reads and verifies an X509 certificate.
767 b6267745 Andrea Spadaccini

768 b6267745 Andrea Spadaccini
  @type cert_filename: string
769 b6267745 Andrea Spadaccini
  @param cert_filename: the path of the file containing the certificate to
770 b6267745 Andrea Spadaccini
                        verify encoded in PEM format
771 b6267745 Andrea Spadaccini
  @type verify_private_key: bool
772 b6267745 Andrea Spadaccini
  @param verify_private_key: whether to verify the private key in addition to
773 b6267745 Andrea Spadaccini
                             the public certificate
774 b6267745 Andrea Spadaccini
  @rtype: string
775 b6267745 Andrea Spadaccini
  @return: a string containing the PEM-encoded certificate.
776 b6267745 Andrea Spadaccini

777 b6267745 Andrea Spadaccini
  """
778 b6267745 Andrea Spadaccini
  try:
779 b6267745 Andrea Spadaccini
    pem = utils.ReadFile(cert_filename)
780 b6267745 Andrea Spadaccini
  except IOError, err:
781 b6267745 Andrea Spadaccini
    raise errors.X509CertError(cert_filename,
782 b6267745 Andrea Spadaccini
                               "Unable to read certificate: %s" % str(err))
783 b6267745 Andrea Spadaccini
784 b6267745 Andrea Spadaccini
  try:
785 b6267745 Andrea Spadaccini
    OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem)
786 b6267745 Andrea Spadaccini
  except Exception, err:
787 b6267745 Andrea Spadaccini
    raise errors.X509CertError(cert_filename,
788 b6267745 Andrea Spadaccini
                               "Unable to load certificate: %s" % str(err))
789 b6267745 Andrea Spadaccini
790 b6267745 Andrea Spadaccini
  if verify_private_key:
791 b6267745 Andrea Spadaccini
    try:
792 b6267745 Andrea Spadaccini
      OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, pem)
793 b6267745 Andrea Spadaccini
    except Exception, err:
794 b6267745 Andrea Spadaccini
      raise errors.X509CertError(cert_filename,
795 b6267745 Andrea Spadaccini
                                 "Unable to load private key: %s" % str(err))
796 b6267745 Andrea Spadaccini
797 b6267745 Andrea Spadaccini
  return pem
798 b6267745 Andrea Spadaccini
799 b6267745 Andrea Spadaccini
800 5ae4945a Iustin Pop
def _RenewCrypto(new_cluster_cert, new_rapi_cert, # pylint: disable=R0911
801 b6267745 Andrea Spadaccini
                 rapi_cert_filename, new_spice_cert, spice_cert_filename,
802 b6267745 Andrea Spadaccini
                 spice_cacert_filename, new_confd_hmac_key, new_cds,
803 b6267745 Andrea Spadaccini
                 cds_filename, force):
804 6d4a1656 Michael Hanselmann
  """Renews cluster certificates, keys and secrets.
805 6d4a1656 Michael Hanselmann

806 6d4a1656 Michael Hanselmann
  @type new_cluster_cert: bool
807 6d4a1656 Michael Hanselmann
  @param new_cluster_cert: Whether to generate a new cluster certificate
808 6d4a1656 Michael Hanselmann
  @type new_rapi_cert: bool
809 6d4a1656 Michael Hanselmann
  @param new_rapi_cert: Whether to generate a new RAPI certificate
810 6d4a1656 Michael Hanselmann
  @type rapi_cert_filename: string
811 6d4a1656 Michael Hanselmann
  @param rapi_cert_filename: Path to file containing new RAPI certificate
812 b6267745 Andrea Spadaccini
  @type new_spice_cert: bool
813 b6267745 Andrea Spadaccini
  @param new_spice_cert: Whether to generate a new SPICE certificate
814 b6267745 Andrea Spadaccini
  @type spice_cert_filename: string
815 b6267745 Andrea Spadaccini
  @param spice_cert_filename: Path to file containing new SPICE certificate
816 b6267745 Andrea Spadaccini
  @type spice_cacert_filename: string
817 b6267745 Andrea Spadaccini
  @param spice_cacert_filename: Path to file containing the certificate of the
818 b6267745 Andrea Spadaccini
                                CA that signed the SPICE certificate
819 6b7d5878 Michael Hanselmann
  @type new_confd_hmac_key: bool
820 6b7d5878 Michael Hanselmann
  @param new_confd_hmac_key: Whether to generate a new HMAC key
821 3db3eb2a Michael Hanselmann
  @type new_cds: bool
822 3db3eb2a Michael Hanselmann
  @param new_cds: Whether to generate a new cluster domain secret
823 3db3eb2a Michael Hanselmann
  @type cds_filename: string
824 3db3eb2a Michael Hanselmann
  @param cds_filename: Path to file containing new cluster domain secret
825 6d4a1656 Michael Hanselmann
  @type force: bool
826 6d4a1656 Michael Hanselmann
  @param force: Whether to ask user for confirmation
827 6d4a1656 Michael Hanselmann

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

925 6d4a1656 Michael Hanselmann
  """
926 6d4a1656 Michael Hanselmann
  return _RenewCrypto(opts.new_cluster_cert,
927 6d4a1656 Michael Hanselmann
                      opts.new_rapi_cert,
928 6d4a1656 Michael Hanselmann
                      opts.rapi_cert,
929 b6267745 Andrea Spadaccini
                      opts.new_spice_cert,
930 b6267745 Andrea Spadaccini
                      opts.spice_cert,
931 b6267745 Andrea Spadaccini
                      opts.spice_cacert,
932 6b7d5878 Michael Hanselmann
                      opts.new_confd_hmac_key,
933 3db3eb2a Michael Hanselmann
                      opts.new_cluster_domain_secret,
934 3db3eb2a Michael Hanselmann
                      opts.cluster_domain_secret,
935 6d4a1656 Michael Hanselmann
                      opts.force)
936 6d4a1656 Michael Hanselmann
937 6d4a1656 Michael Hanselmann
938 90b6aa3a Manuel Franceschini
def SetClusterParams(opts, args):
939 90b6aa3a Manuel Franceschini
  """Modify the cluster.
940 90b6aa3a Manuel Franceschini

941 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
942 469ee405 Iustin Pop
  @type args: list
943 469ee405 Iustin Pop
  @param args: should be an empty list
944 469ee405 Iustin Pop
  @rtype: int
945 469ee405 Iustin Pop
  @return: the desired exit code
946 90b6aa3a Manuel Franceschini

947 90b6aa3a Manuel Franceschini
  """
948 779c15bb Iustin Pop
  if not (not opts.lvm_storage or opts.vg_name or
949 ed14ed48 Luca Bigliardi
          not opts.drbd_storage or opts.drbd_helper or
950 779c15bb Iustin Pop
          opts.enabled_hypervisors or opts.hvparams or
951 bc5d0215 Andrea Spadaccini
          opts.beparams or opts.nicparams or
952 bc5d0215 Andrea Spadaccini
          opts.ndparams or opts.diskparams or
953 3953242f Iustin Pop
          opts.candidate_pool_size is not None or
954 1338f2b4 Balazs Lecz
          opts.uid_pool is not None or
955 fdad8c4d Balazs Lecz
          opts.maintain_node_health is not None or
956 fdad8c4d Balazs Lecz
          opts.add_uids is not None or
957 bf4af505 Apollon Oikonomopoulos
          opts.remove_uids is not None or
958 f38ea602 Iustin Pop
          opts.default_iallocator is not None or
959 b883637f René Nussbaumer
          opts.reserved_lvs is not None or
960 38f9d2cf Guido Trotter
          opts.master_netdev is not None or
961 5a8648eb Andrea Spadaccini
          opts.master_netmask is not None or
962 bf689b7a Andrea Spadaccini
          opts.use_external_mip_script is not None or
963 2da9f556 René Nussbaumer
          opts.prealloc_wipe_disks is not None or
964 2da9f556 René Nussbaumer
          opts.hv_state or
965 c270ee07 Helga Velroyen
          opts.enabled_storage_types or
966 e1a6850f Agata Murawska
          opts.disk_state or
967 1e7acc3b Iustin Pop
          opts.ispecs_mem_size or
968 1e7acc3b Iustin Pop
          opts.ispecs_cpu_count or
969 1e7acc3b Iustin Pop
          opts.ispecs_disk_count or
970 1e7acc3b Iustin Pop
          opts.ispecs_disk_size or
971 1e7acc3b Iustin Pop
          opts.ispecs_nic_count or
972 1e7acc3b Iustin Pop
          opts.ipolicy_disk_templates is not None or
973 31d827d1 René Nussbaumer
          opts.ipolicy_vcpu_ratio is not None or
974 31d827d1 René Nussbaumer
          opts.ipolicy_spindle_ratio is not None):
975 3a24c527 Iustin Pop
    ToStderr("Please give at least one of the parameters.")
976 90b6aa3a Manuel Franceschini
    return 1
977 90b6aa3a Manuel Franceschini
978 90b6aa3a Manuel Franceschini
  vg_name = opts.vg_name
979 90b6aa3a Manuel Franceschini
  if not opts.lvm_storage and opts.vg_name:
980 6d4a1656 Michael Hanselmann
    ToStderr("Options --no-lvm-storage and --vg-name conflict.")
981 90b6aa3a Manuel Franceschini
    return 1
982 6d4a1656 Michael Hanselmann
983 6d4a1656 Michael Hanselmann
  if not opts.lvm_storage:
984 6d4a1656 Michael Hanselmann
    vg_name = ""
985 90b6aa3a Manuel Franceschini
986 ed14ed48 Luca Bigliardi
  drbd_helper = opts.drbd_helper
987 ed14ed48 Luca Bigliardi
  if not opts.drbd_storage and opts.drbd_helper:
988 ed14ed48 Luca Bigliardi
    ToStderr("Options --no-drbd-storage and --drbd-usermode-helper conflict.")
989 ed14ed48 Luca Bigliardi
    return 1
990 ed14ed48 Luca Bigliardi
991 ed14ed48 Luca Bigliardi
  if not opts.drbd_storage:
992 ed14ed48 Luca Bigliardi
    drbd_helper = ""
993 ed14ed48 Luca Bigliardi
994 779c15bb Iustin Pop
  hvlist = opts.enabled_hypervisors
995 779c15bb Iustin Pop
  if hvlist is not None:
996 779c15bb Iustin Pop
    hvlist = hvlist.split(",")
997 779c15bb Iustin Pop
998 c270ee07 Helga Velroyen
  enabled_storage_types = opts.enabled_storage_types
999 c270ee07 Helga Velroyen
  if enabled_storage_types is not None:
1000 c270ee07 Helga Velroyen
    enabled_storage_types = enabled_storage_types.split(",")
1001 c270ee07 Helga Velroyen
1002 f8e7ddca Guido Trotter
  # a list of (name, dict) we can pass directly to dict() (or [])
1003 f8e7ddca Guido Trotter
  hvparams = dict(opts.hvparams)
1004 f4ad2ef0 Iustin Pop
  for hv_params in hvparams.values():
1005 a5728081 Guido Trotter
    utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
1006 779c15bb Iustin Pop
1007 bc5d0215 Andrea Spadaccini
  diskparams = dict(opts.diskparams)
1008 bc5d0215 Andrea Spadaccini
1009 c20a19ed Iustin Pop
  for dt_params in diskparams.values():
1010 bc5d0215 Andrea Spadaccini
    utils.ForceDictType(dt_params, constants.DISK_DT_TYPES)
1011 bc5d0215 Andrea Spadaccini
1012 779c15bb Iustin Pop
  beparams = opts.beparams
1013 b2e233a5 Guido Trotter
  utils.ForceDictType(beparams, constants.BES_PARAMETER_COMPAT)
1014 779c15bb Iustin Pop
1015 5af3da74 Guido Trotter
  nicparams = opts.nicparams
1016 5af3da74 Guido Trotter
  utils.ForceDictType(nicparams, constants.NICS_PARAMETER_TYPES)
1017 5af3da74 Guido Trotter
1018 6204ee71 René Nussbaumer
  ndparams = opts.ndparams
1019 6204ee71 René Nussbaumer
  if ndparams is not None:
1020 6204ee71 René Nussbaumer
    utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
1021 1338f2b4 Balazs Lecz
1022 703fa9ab Iustin Pop
  ipolicy = CreateIPolicyFromOpts(
1023 976b78ba Iustin Pop
    ispecs_mem_size=opts.ispecs_mem_size,
1024 976b78ba Iustin Pop
    ispecs_cpu_count=opts.ispecs_cpu_count,
1025 976b78ba Iustin Pop
    ispecs_disk_count=opts.ispecs_disk_count,
1026 976b78ba Iustin Pop
    ispecs_disk_size=opts.ispecs_disk_size,
1027 976b78ba Iustin Pop
    ispecs_nic_count=opts.ispecs_nic_count,
1028 976b78ba Iustin Pop
    ipolicy_disk_templates=opts.ipolicy_disk_templates,
1029 976b78ba Iustin Pop
    ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio,
1030 31d827d1 René Nussbaumer
    ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio,
1031 976b78ba Iustin Pop
    )
1032 e1a6850f Agata Murawska
1033 3953242f Iustin Pop
  mnh = opts.maintain_node_health
1034 3953242f Iustin Pop
1035 1338f2b4 Balazs Lecz
  uid_pool = opts.uid_pool
1036 1338f2b4 Balazs Lecz
  if uid_pool is not None:
1037 1338f2b4 Balazs Lecz
    uid_pool = uidpool.ParseUidPool(uid_pool)
1038 1338f2b4 Balazs Lecz
1039 fdad8c4d Balazs Lecz
  add_uids = opts.add_uids
1040 fdad8c4d Balazs Lecz
  if add_uids is not None:
1041 fdad8c4d Balazs Lecz
    add_uids = uidpool.ParseUidPool(add_uids)
1042 fdad8c4d Balazs Lecz
1043 fdad8c4d Balazs Lecz
  remove_uids = opts.remove_uids
1044 fdad8c4d Balazs Lecz
  if remove_uids is not None:
1045 fdad8c4d Balazs Lecz
    remove_uids = uidpool.ParseUidPool(remove_uids)
1046 fdad8c4d Balazs Lecz
1047 f38ea602 Iustin Pop
  if opts.reserved_lvs is not None:
1048 f38ea602 Iustin Pop
    if opts.reserved_lvs == "":
1049 f38ea602 Iustin Pop
      opts.reserved_lvs = []
1050 f38ea602 Iustin Pop
    else:
1051 f38ea602 Iustin Pop
      opts.reserved_lvs = utils.UnescapeAndSplit(opts.reserved_lvs, sep=",")
1052 f38ea602 Iustin Pop
1053 5a8648eb Andrea Spadaccini
  if opts.master_netmask is not None:
1054 5a8648eb Andrea Spadaccini
    try:
1055 5a8648eb Andrea Spadaccini
      opts.master_netmask = int(opts.master_netmask)
1056 5a8648eb Andrea Spadaccini
    except ValueError:
1057 5a8648eb Andrea Spadaccini
      ToStderr("The --master-netmask option expects an int parameter.")
1058 5a8648eb Andrea Spadaccini
      return 1
1059 5a8648eb Andrea Spadaccini
1060 bf689b7a Andrea Spadaccini
  ext_ip_script = opts.use_external_mip_script
1061 bf689b7a Andrea Spadaccini
1062 2da9f556 René Nussbaumer
  if opts.disk_state:
1063 2da9f556 René Nussbaumer
    disk_state = utils.FlatToDict(opts.disk_state)
1064 2da9f556 René Nussbaumer
  else:
1065 2da9f556 René Nussbaumer
    disk_state = {}
1066 2da9f556 René Nussbaumer
1067 2da9f556 René Nussbaumer
  hv_state = dict(opts.hv_state)
1068 2da9f556 René Nussbaumer
1069 c270ee07 Helga Velroyen
  op = opcodes.OpClusterSetParams(
1070 c270ee07 Helga Velroyen
    vg_name=vg_name,
1071 c270ee07 Helga Velroyen
    drbd_helper=drbd_helper,
1072 c270ee07 Helga Velroyen
    enabled_hypervisors=hvlist,
1073 c270ee07 Helga Velroyen
    hvparams=hvparams,
1074 c270ee07 Helga Velroyen
    os_hvp=None,
1075 c270ee07 Helga Velroyen
    beparams=beparams,
1076 c270ee07 Helga Velroyen
    nicparams=nicparams,
1077 c270ee07 Helga Velroyen
    ndparams=ndparams,
1078 c270ee07 Helga Velroyen
    diskparams=diskparams,
1079 c270ee07 Helga Velroyen
    ipolicy=ipolicy,
1080 c270ee07 Helga Velroyen
    candidate_pool_size=opts.candidate_pool_size,
1081 c270ee07 Helga Velroyen
    maintain_node_health=mnh,
1082 c270ee07 Helga Velroyen
    uid_pool=uid_pool,
1083 c270ee07 Helga Velroyen
    add_uids=add_uids,
1084 c270ee07 Helga Velroyen
    remove_uids=remove_uids,
1085 c270ee07 Helga Velroyen
    default_iallocator=opts.default_iallocator,
1086 c270ee07 Helga Velroyen
    prealloc_wipe_disks=opts.prealloc_wipe_disks,
1087 c270ee07 Helga Velroyen
    master_netdev=opts.master_netdev,
1088 c270ee07 Helga Velroyen
    master_netmask=opts.master_netmask,
1089 c270ee07 Helga Velroyen
    reserved_lvs=opts.reserved_lvs,
1090 c270ee07 Helga Velroyen
    use_external_mip_script=ext_ip_script,
1091 c270ee07 Helga Velroyen
    hv_state=hv_state,
1092 c270ee07 Helga Velroyen
    disk_state=disk_state,
1093 c270ee07 Helga Velroyen
    enabled_storage_types=enabled_storage_types,
1094 c270ee07 Helga Velroyen
    )
1095 745dae57 Michael Hanselmann
  SubmitOrSend(op, opts)
1096 90b6aa3a Manuel Franceschini
  return 0
1097 90b6aa3a Manuel Franceschini
1098 90b6aa3a Manuel Franceschini
1099 3ccafd0e Iustin Pop
def QueueOps(opts, args):
1100 3ccafd0e Iustin Pop
  """Queue operations.
1101 3ccafd0e Iustin Pop

1102 469ee405 Iustin Pop
  @param opts: the command line options selected by the user
1103 469ee405 Iustin Pop
  @type args: list
1104 469ee405 Iustin Pop
  @param args: should contain only one element, the subcommand
1105 469ee405 Iustin Pop
  @rtype: int
1106 469ee405 Iustin Pop
  @return: the desired exit code
1107 469ee405 Iustin Pop

1108 3ccafd0e Iustin Pop
  """
1109 3ccafd0e Iustin Pop
  command = args[0]
1110 3ccafd0e Iustin Pop
  client = GetClient()
1111 3ccafd0e Iustin Pop
  if command in ("drain", "undrain"):
1112 3ccafd0e Iustin Pop
    drain_flag = command == "drain"
1113 3ccafd0e Iustin Pop
    client.SetQueueDrainFlag(drain_flag)
1114 3ccafd0e Iustin Pop
  elif command == "info":
1115 3ccafd0e Iustin Pop
    result = client.QueryConfigValues(["drain_flag"])
1116 3ccafd0e Iustin Pop
    if result[0]:
1117 3a24c527 Iustin Pop
      val = "set"
1118 3ccafd0e Iustin Pop
    else:
1119 3a24c527 Iustin Pop
      val = "unset"
1120 3a24c527 Iustin Pop
    ToStdout("The drain flag is %s" % val)
1121 2e668b38 Guido Trotter
  else:
1122 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
1123 debac808 Iustin Pop
                               errors.ECODE_INVAL)
1124 2e668b38 Guido Trotter
1125 3ccafd0e Iustin Pop
  return 0
1126 3ccafd0e Iustin Pop
1127 95b2e626 Michael Hanselmann
1128 28b498cd Michael Hanselmann
def _ShowWatcherPause(until):
1129 28b498cd Michael Hanselmann
  if until is None or until < time.time():
1130 28b498cd Michael Hanselmann
    ToStdout("The watcher is not paused.")
1131 28b498cd Michael Hanselmann
  else:
1132 28b498cd Michael Hanselmann
    ToStdout("The watcher is paused until %s.", time.ctime(until))
1133 28b498cd Michael Hanselmann
1134 28b498cd Michael Hanselmann
1135 95b2e626 Michael Hanselmann
def WatcherOps(opts, args):
1136 95b2e626 Michael Hanselmann
  """Watcher operations.
1137 95b2e626 Michael Hanselmann

1138 95b2e626 Michael Hanselmann
  @param opts: the command line options selected by the user
1139 95b2e626 Michael Hanselmann
  @type args: list
1140 95b2e626 Michael Hanselmann
  @param args: should contain only one element, the subcommand
1141 95b2e626 Michael Hanselmann
  @rtype: int
1142 95b2e626 Michael Hanselmann
  @return: the desired exit code
1143 95b2e626 Michael Hanselmann

1144 95b2e626 Michael Hanselmann
  """
1145 95b2e626 Michael Hanselmann
  command = args[0]
1146 95b2e626 Michael Hanselmann
  client = GetClient()
1147 95b2e626 Michael Hanselmann
1148 95b2e626 Michael Hanselmann
  if command == "continue":
1149 95b2e626 Michael Hanselmann
    client.SetWatcherPause(None)
1150 28b498cd Michael Hanselmann
    ToStdout("The watcher is no longer paused.")
1151 95b2e626 Michael Hanselmann
1152 95b2e626 Michael Hanselmann
  elif command == "pause":
1153 95b2e626 Michael Hanselmann
    if len(args) < 2:
1154 debac808 Iustin Pop
      raise errors.OpPrereqError("Missing pause duration", errors.ECODE_INVAL)
1155 95b2e626 Michael Hanselmann
1156 28b498cd Michael Hanselmann
    result = client.SetWatcherPause(time.time() + ParseTimespec(args[1]))
1157 28b498cd Michael Hanselmann
    _ShowWatcherPause(result)
1158 95b2e626 Michael Hanselmann
1159 95b2e626 Michael Hanselmann
  elif command == "info":
1160 95b2e626 Michael Hanselmann
    result = client.QueryConfigValues(["watcher_pause"])
1161 cac599f1 Michael Hanselmann
    _ShowWatcherPause(result[0])
1162 95b2e626 Michael Hanselmann
1163 95b2e626 Michael Hanselmann
  else:
1164 debac808 Iustin Pop
    raise errors.OpPrereqError("Command '%s' is not valid." % command,
1165 debac808 Iustin Pop
                               errors.ECODE_INVAL)
1166 95b2e626 Michael Hanselmann
1167 95b2e626 Michael Hanselmann
  return 0
1168 95b2e626 Michael Hanselmann
1169 95b2e626 Michael Hanselmann
1170 66d1f035 René Nussbaumer
def _OobPower(opts, node_list, power):
1171 66d1f035 René Nussbaumer
  """Puts the node in the list to desired power state.
1172 66d1f035 René Nussbaumer

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

1178 66d1f035 René Nussbaumer
  """
1179 66d1f035 René Nussbaumer
  if power:
1180 66d1f035 René Nussbaumer
    command = constants.OOB_POWER_ON
1181 66d1f035 René Nussbaumer
  else:
1182 66d1f035 René Nussbaumer
    command = constants.OOB_POWER_OFF
1183 66d1f035 René Nussbaumer
1184 66d1f035 René Nussbaumer
  op = opcodes.OpOobCommand(node_names=node_list,
1185 66d1f035 René Nussbaumer
                            command=command,
1186 66d1f035 René Nussbaumer
                            ignore_status=True,
1187 cfed3b9f René Nussbaumer
                            timeout=opts.oob_timeout,
1188 cfed3b9f René Nussbaumer
                            power_delay=opts.power_delay)
1189 66d1f035 René Nussbaumer
  result = SubmitOpCode(op, opts=opts)
1190 66d1f035 René Nussbaumer
  errs = 0
1191 66d1f035 René Nussbaumer
  for node_result in result:
1192 66d1f035 René Nussbaumer
    (node_tuple, data_tuple) = node_result
1193 66d1f035 René Nussbaumer
    (_, node_name) = node_tuple
1194 66d1f035 René Nussbaumer
    (data_status, _) = data_tuple
1195 66d1f035 René Nussbaumer
    if data_status != constants.RS_NORMAL:
1196 66d1f035 René Nussbaumer
      assert data_status != constants.RS_UNAVAIL
1197 66d1f035 René Nussbaumer
      errs += 1
1198 66d1f035 René Nussbaumer
      ToStderr("There was a problem changing power for %s, please investigate",
1199 66d1f035 René Nussbaumer
               node_name)
1200 66d1f035 René Nussbaumer
1201 66d1f035 René Nussbaumer
  if errs > 0:
1202 66d1f035 René Nussbaumer
    return False
1203 66d1f035 René Nussbaumer
1204 66d1f035 René Nussbaumer
  return True
1205 66d1f035 René Nussbaumer
1206 66d1f035 René Nussbaumer
1207 3e0ed18c René Nussbaumer
def _InstanceStart(opts, inst_list, start, no_remember=False):
1208 66d1f035 René Nussbaumer
  """Puts the instances in the list to desired state.
1209 66d1f035 René Nussbaumer

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

1216 66d1f035 René Nussbaumer
  """
1217 66d1f035 René Nussbaumer
  if start:
1218 66d1f035 René Nussbaumer
    opcls = opcodes.OpInstanceStartup
1219 66d1f035 René Nussbaumer
    text_submit, text_success, text_failed = ("startup", "started", "starting")
1220 66d1f035 René Nussbaumer
  else:
1221 fcecea0b René Nussbaumer
    opcls = compat.partial(opcodes.OpInstanceShutdown,
1222 3e0ed18c René Nussbaumer
                           timeout=opts.shutdown_timeout,
1223 3e0ed18c René Nussbaumer
                           no_remember=no_remember)
1224 66d1f035 René Nussbaumer
    text_submit, text_success, text_failed = ("shutdown", "stopped", "stopping")
1225 66d1f035 René Nussbaumer
1226 66d1f035 René Nussbaumer
  jex = JobExecutor(opts=opts)
1227 66d1f035 René Nussbaumer
1228 66d1f035 René Nussbaumer
  for inst in inst_list:
1229 66d1f035 René Nussbaumer
    ToStdout("Submit %s of instance %s", text_submit, inst)
1230 66d1f035 René Nussbaumer
    op = opcls(instance_name=inst)
1231 66d1f035 René Nussbaumer
    jex.QueueJob(inst, op)
1232 66d1f035 René Nussbaumer
1233 66d1f035 René Nussbaumer
  results = jex.GetResults()
1234 66d1f035 René Nussbaumer
  bad_cnt = len([1 for (success, _) in results if not success])
1235 66d1f035 René Nussbaumer
1236 66d1f035 René Nussbaumer
  if bad_cnt == 0:
1237 66d1f035 René Nussbaumer
    ToStdout("All instances have been %s successfully", text_success)
1238 66d1f035 René Nussbaumer
  else:
1239 66d1f035 René Nussbaumer
    ToStderr("There were errors while %s instances:\n"
1240 66d1f035 René Nussbaumer
             "%d error(s) out of %d instance(s)", text_failed, bad_cnt,
1241 66d1f035 René Nussbaumer
             len(results))
1242 66d1f035 René Nussbaumer
    return False
1243 66d1f035 René Nussbaumer
1244 66d1f035 René Nussbaumer
  return True
1245 66d1f035 René Nussbaumer
1246 66d1f035 René Nussbaumer
1247 66d1f035 René Nussbaumer
class _RunWhenNodesReachableHelper:
1248 66d1f035 René Nussbaumer
  """Helper class to make shared internal state sharing easier.
1249 66d1f035 René Nussbaumer

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

1252 66d1f035 René Nussbaumer
  """
1253 8e74adce René Nussbaumer
  def __init__(self, node_list, action_cb, node2ip, port, feedback_fn,
1254 66d1f035 René Nussbaumer
               _ping_fn=netutils.TcpPing, _sleep_fn=time.sleep):
1255 66d1f035 René Nussbaumer
    """Init the object.
1256 66d1f035 René Nussbaumer

1257 66d1f035 René Nussbaumer
    @param node_list: The list of nodes to be reachable
1258 66d1f035 René Nussbaumer
    @param action_cb: Callback called when a new host is reachable
1259 66d1f035 René Nussbaumer
    @type node2ip: dict
1260 66d1f035 René Nussbaumer
    @param node2ip: Node to ip mapping
1261 66d1f035 René Nussbaumer
    @param port: The port to use for the TCP ping
1262 8e74adce René Nussbaumer
    @param feedback_fn: The function used for feedback
1263 66d1f035 René Nussbaumer
    @param _ping_fn: Function to check reachabilty (for unittest use only)
1264 66d1f035 René Nussbaumer
    @param _sleep_fn: Function to sleep (for unittest use only)
1265 66d1f035 René Nussbaumer

1266 66d1f035 René Nussbaumer
    """
1267 66d1f035 René Nussbaumer
    self.down = set(node_list)
1268 66d1f035 René Nussbaumer
    self.up = set()
1269 66d1f035 René Nussbaumer
    self.node2ip = node2ip
1270 66d1f035 René Nussbaumer
    self.success = True
1271 66d1f035 René Nussbaumer
    self.action_cb = action_cb
1272 66d1f035 René Nussbaumer
    self.port = port
1273 8e74adce René Nussbaumer
    self.feedback_fn = feedback_fn
1274 66d1f035 René Nussbaumer
    self._ping_fn = _ping_fn
1275 66d1f035 René Nussbaumer
    self._sleep_fn = _sleep_fn
1276 66d1f035 René Nussbaumer
1277 66d1f035 René Nussbaumer
  def __call__(self):
1278 66d1f035 René Nussbaumer
    """When called we run action_cb.
1279 66d1f035 René Nussbaumer

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

1282 66d1f035 René Nussbaumer
    """
1283 66d1f035 René Nussbaumer
    if not self.action_cb(self.up):
1284 66d1f035 René Nussbaumer
      self.success = False
1285 66d1f035 René Nussbaumer
1286 66d1f035 René Nussbaumer
    if self.down:
1287 66d1f035 René Nussbaumer
      raise utils.RetryAgain()
1288 66d1f035 René Nussbaumer
    else:
1289 66d1f035 René Nussbaumer
      return self.success
1290 66d1f035 René Nussbaumer
1291 66d1f035 René Nussbaumer
  def Wait(self, secs):
1292 66d1f035 René Nussbaumer
    """Checks if a host is up or waits remaining seconds.
1293 66d1f035 René Nussbaumer

1294 66d1f035 René Nussbaumer
    @param secs: The secs remaining
1295 66d1f035 René Nussbaumer

1296 66d1f035 René Nussbaumer
    """
1297 66d1f035 René Nussbaumer
    start = time.time()
1298 66d1f035 René Nussbaumer
    for node in self.down:
1299 66d1f035 René Nussbaumer
      if self._ping_fn(self.node2ip[node], self.port, timeout=_EPO_PING_TIMEOUT,
1300 66d1f035 René Nussbaumer
                       live_port_needed=True):
1301 8e74adce René Nussbaumer
        self.feedback_fn("Node %s became available" % node)
1302 66d1f035 René Nussbaumer
        self.up.add(node)
1303 66d1f035 René Nussbaumer
        self.down -= self.up
1304 66d1f035 René Nussbaumer
        # If we have a node available there is the possibility to run the
1305 66d1f035 René Nussbaumer
        # action callback successfully, therefore we don't wait and return
1306 66d1f035 René Nussbaumer
        return
1307 66d1f035 René Nussbaumer
1308 66d1f035 René Nussbaumer
    self._sleep_fn(max(0.0, start + secs - time.time()))
1309 66d1f035 René Nussbaumer
1310 66d1f035 René Nussbaumer
1311 66d1f035 René Nussbaumer
def _RunWhenNodesReachable(node_list, action_cb, interval):
1312 66d1f035 René Nussbaumer
  """Run action_cb when nodes become reachable.
1313 66d1f035 René Nussbaumer

1314 66d1f035 René Nussbaumer
  @param node_list: The list of nodes to be reachable
1315 66d1f035 René Nussbaumer
  @param action_cb: Callback called when a new host is reachable
1316 66d1f035 René Nussbaumer
  @param interval: The earliest time to retry
1317 66d1f035 René Nussbaumer

1318 66d1f035 René Nussbaumer
  """
1319 66d1f035 René Nussbaumer
  client = GetClient()
1320 66d1f035 René Nussbaumer
  cluster_info = client.QueryClusterInfo()
1321 66d1f035 René Nussbaumer
  if cluster_info["primary_ip_version"] == constants.IP4_VERSION:
1322 66d1f035 René Nussbaumer
    family = netutils.IPAddress.family
1323 66d1f035 René Nussbaumer
  else:
1324 66d1f035 René Nussbaumer
    family = netutils.IP6Address.family
1325 66d1f035 René Nussbaumer
1326 66d1f035 René Nussbaumer
  node2ip = dict((node, netutils.GetHostname(node, family=family).ip)
1327 66d1f035 René Nussbaumer
                 for node in node_list)
1328 66d1f035 René Nussbaumer
1329 66d1f035 René Nussbaumer
  port = netutils.GetDaemonPort(constants.NODED)
1330 8e74adce René Nussbaumer
  helper = _RunWhenNodesReachableHelper(node_list, action_cb, node2ip, port,
1331 8e74adce René Nussbaumer
                                        ToStdout)
1332 66d1f035 René Nussbaumer
1333 66d1f035 René Nussbaumer
  try:
1334 66d1f035 René Nussbaumer
    return utils.Retry(helper, interval, _EPO_REACHABLE_TIMEOUT,
1335 66d1f035 René Nussbaumer
                       wait_fn=helper.Wait)
1336 66d1f035 René Nussbaumer
  except utils.RetryTimeout:
1337 66d1f035 René Nussbaumer
    ToStderr("Time exceeded while waiting for nodes to become reachable"
1338 66d1f035 René Nussbaumer
             " again:\n  - %s", "  - ".join(helper.down))
1339 66d1f035 René Nussbaumer
    return False
1340 66d1f035 René Nussbaumer
1341 66d1f035 René Nussbaumer
1342 66d1f035 René Nussbaumer
def _MaybeInstanceStartup(opts, inst_map, nodes_online,
1343 66d1f035 René Nussbaumer
                          _instance_start_fn=_InstanceStart):
1344 66d1f035 René Nussbaumer
  """Start the instances conditional based on node_states.
1345 66d1f035 René Nussbaumer

1346 66d1f035 René Nussbaumer
  @param opts: The command line options selected by the user
1347 66d1f035 René Nussbaumer
  @param inst_map: A dict of inst -> nodes mapping
1348 66d1f035 René Nussbaumer
  @param nodes_online: A list of nodes online
1349 66d1f035 René Nussbaumer
  @param _instance_start_fn: Callback to start instances (unittest use only)
1350 66d1f035 René Nussbaumer
  @return: Success of the operation on all instances
1351 66d1f035 René Nussbaumer

1352 66d1f035 René Nussbaumer
  """
1353 66d1f035 René Nussbaumer
  start_inst_list = []
1354 66d1f035 René Nussbaumer
  for (inst, nodes) in inst_map.items():
1355 66d1f035 René Nussbaumer
    if not (nodes - nodes_online):
1356 66d1f035 René Nussbaumer
      # All nodes the instance lives on are back online
1357 66d1f035 René Nussbaumer
      start_inst_list.append(inst)
1358 66d1f035 René Nussbaumer
1359 66d1f035 René Nussbaumer
  for inst in start_inst_list:
1360 66d1f035 René Nussbaumer
    del inst_map[inst]
1361 66d1f035 René Nussbaumer
1362 66d1f035 René Nussbaumer
  if start_inst_list:
1363 66d1f035 René Nussbaumer
    return _instance_start_fn(opts, start_inst_list, True)
1364 66d1f035 René Nussbaumer
1365 66d1f035 René Nussbaumer
  return True
1366 66d1f035 René Nussbaumer
1367 66d1f035 René Nussbaumer
1368 66d1f035 René Nussbaumer
def _EpoOn(opts, full_node_list, node_list, inst_map):
1369 66d1f035 René Nussbaumer
  """Does the actual power on.
1370 66d1f035 René Nussbaumer

1371 66d1f035 René Nussbaumer
  @param opts: The command line options selected by the user
1372 66d1f035 René Nussbaumer
  @param full_node_list: All nodes to operate on (includes nodes not supporting
1373 66d1f035 René Nussbaumer
                         OOB)
1374 66d1f035 René Nussbaumer
  @param node_list: The list of nodes to operate on (all need to support OOB)
1375 66d1f035 René Nussbaumer
  @param inst_map: A dict of inst -> nodes mapping
1376 66d1f035 René Nussbaumer
  @return: The desired exit status
1377 66d1f035 René Nussbaumer

1378 66d1f035 René Nussbaumer
  """
1379 66d1f035 René Nussbaumer
  if node_list and not _OobPower(opts, node_list, False):
1380 66d1f035 René Nussbaumer
    ToStderr("Not all nodes seem to get back up, investigate and start"
1381 66d1f035 René Nussbaumer
             " manually if needed")
1382 66d1f035 René Nussbaumer
1383 66d1f035 René Nussbaumer
  # Wait for the nodes to be back up
1384 66d1f035 René Nussbaumer
  action_cb = compat.partial(_MaybeInstanceStartup, opts, dict(inst_map))
1385 66d1f035 René Nussbaumer
1386 66d1f035 René Nussbaumer
  ToStdout("Waiting until all nodes are available again")
1387 66d1f035 René Nussbaumer
  if not _RunWhenNodesReachable(full_node_list, action_cb, _EPO_PING_INTERVAL):
1388 66d1f035 René Nussbaumer
    ToStderr("Please investigate and start stopped instances manually")
1389 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1390 66d1f035 René Nussbaumer
1391 66d1f035 René Nussbaumer
  return constants.EXIT_SUCCESS
1392 66d1f035 René Nussbaumer
1393 66d1f035 René Nussbaumer
1394 66d1f035 René Nussbaumer
def _EpoOff(opts, node_list, inst_map):
1395 66d1f035 René Nussbaumer
  """Does the actual power off.
1396 66d1f035 René Nussbaumer

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

1402 66d1f035 René Nussbaumer
  """
1403 3e0ed18c René Nussbaumer
  if not _InstanceStart(opts, inst_map.keys(), False, no_remember=True):
1404 66d1f035 René Nussbaumer
    ToStderr("Please investigate and stop instances manually before continuing")
1405 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1406 66d1f035 René Nussbaumer
1407 66d1f035 René Nussbaumer
  if not node_list:
1408 66d1f035 René Nussbaumer
    return constants.EXIT_SUCCESS
1409 66d1f035 René Nussbaumer
1410 66d1f035 René Nussbaumer
  if _OobPower(opts, node_list, False):
1411 66d1f035 René Nussbaumer
    return constants.EXIT_SUCCESS
1412 66d1f035 René Nussbaumer
  else:
1413 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1414 66d1f035 René Nussbaumer
1415 66d1f035 René Nussbaumer
1416 1ca7b773 Michael Hanselmann
def Epo(opts, args, cl=None, _on_fn=_EpoOn, _off_fn=_EpoOff,
1417 1ca7b773 Michael Hanselmann
        _confirm_fn=ConfirmOperation,
1418 1ca7b773 Michael Hanselmann
        _stdout_fn=ToStdout, _stderr_fn=ToStderr):
1419 66d1f035 René Nussbaumer
  """EPO operations.
1420 66d1f035 René Nussbaumer

1421 66d1f035 René Nussbaumer
  @param opts: the command line options selected by the user
1422 66d1f035 René Nussbaumer
  @type args: list
1423 66d1f035 René Nussbaumer
  @param args: should contain only one element, the subcommand
1424 66d1f035 René Nussbaumer
  @rtype: int
1425 66d1f035 René Nussbaumer
  @return: the desired exit code
1426 66d1f035 René Nussbaumer

1427 66d1f035 René Nussbaumer
  """
1428 66d1f035 René Nussbaumer
  if opts.groups and opts.show_all:
1429 1ca7b773 Michael Hanselmann
    _stderr_fn("Only one of --groups or --all are allowed")
1430 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1431 66d1f035 René Nussbaumer
  elif args and opts.show_all:
1432 1ca7b773 Michael Hanselmann
    _stderr_fn("Arguments in combination with --all are not allowed")
1433 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1434 66d1f035 René Nussbaumer
1435 1ca7b773 Michael Hanselmann
  if cl is None:
1436 1ca7b773 Michael Hanselmann
    cl = GetClient()
1437 66d1f035 René Nussbaumer
1438 66d1f035 René Nussbaumer
  if opts.groups:
1439 1ca7b773 Michael Hanselmann
    node_query_list = \
1440 1ca7b773 Michael Hanselmann
      itertools.chain(*cl.QueryGroups(args, ["node_list"], False))
1441 66d1f035 René Nussbaumer
  else:
1442 66d1f035 René Nussbaumer
    node_query_list = args
1443 66d1f035 René Nussbaumer
1444 1ca7b773 Michael Hanselmann
  result = cl.QueryNodes(node_query_list, ["name", "master", "pinst_list",
1445 1ca7b773 Michael Hanselmann
                                           "sinst_list", "powered", "offline"],
1446 1ca7b773 Michael Hanselmann
                         False)
1447 45a36f36 Michael Hanselmann
1448 45a36f36 Michael Hanselmann
  all_nodes = map(compat.fst, result)
1449 66d1f035 René Nussbaumer
  node_list = []
1450 66d1f035 René Nussbaumer
  inst_map = {}
1451 3008f56c Iustin Pop
  for (node, master, pinsts, sinsts, powered, offline) in result:
1452 66d1f035 René Nussbaumer
    if not offline:
1453 66d1f035 René Nussbaumer
      for inst in (pinsts + sinsts):
1454 66d1f035 René Nussbaumer
        if inst in inst_map:
1455 66d1f035 René Nussbaumer
          if not master:
1456 66d1f035 René Nussbaumer
            inst_map[inst].add(node)
1457 66d1f035 René Nussbaumer
        elif master:
1458 66d1f035 René Nussbaumer
          inst_map[inst] = set()
1459 66d1f035 René Nussbaumer
        else:
1460 66d1f035 René Nussbaumer
          inst_map[inst] = set([node])
1461 66d1f035 René Nussbaumer
1462 66d1f035 René Nussbaumer
    if master and opts.on:
1463 66d1f035 René Nussbaumer
      # We ignore the master for turning on the machines, in fact we are
1464 66d1f035 René Nussbaumer
      # already operating on the master at this point :)
1465 66d1f035 René Nussbaumer
      continue
1466 66d1f035 René Nussbaumer
    elif master and not opts.show_all:
1467 1ca7b773 Michael Hanselmann
      _stderr_fn("%s is the master node, please do a master-failover to another"
1468 1ca7b773 Michael Hanselmann
                 " node not affected by the EPO or use --all if you intend to"
1469 1ca7b773 Michael Hanselmann
                 " shutdown the whole cluster", node)
1470 66d1f035 René Nussbaumer
      return constants.EXIT_FAILURE
1471 66d1f035 René Nussbaumer
    elif powered is None:
1472 1ca7b773 Michael Hanselmann
      _stdout_fn("Node %s does not support out-of-band handling, it can not be"
1473 1ca7b773 Michael Hanselmann
                 " handled in a fully automated manner", node)
1474 66d1f035 René Nussbaumer
    elif powered == opts.on:
1475 1ca7b773 Michael Hanselmann
      _stdout_fn("Node %s is already in desired power state, skipping", node)
1476 66d1f035 René Nussbaumer
    elif not offline or (offline and powered):
1477 66d1f035 René Nussbaumer
      node_list.append(node)
1478 66d1f035 René Nussbaumer
1479 1ca7b773 Michael Hanselmann
  if not (opts.force or _confirm_fn(all_nodes, "nodes", "epo")):
1480 66d1f035 René Nussbaumer
    return constants.EXIT_FAILURE
1481 66d1f035 René Nussbaumer
1482 66d1f035 René Nussbaumer
  if opts.on:
1483 1ca7b773 Michael Hanselmann
    return _on_fn(opts, all_nodes, node_list, inst_map)
1484 66d1f035 René Nussbaumer
  else:
1485 1ca7b773 Michael Hanselmann
    return _off_fn(opts, node_list, inst_map)
1486 1ca7b773 Michael Hanselmann
1487 66d1f035 René Nussbaumer
1488 a8083063 Iustin Pop
commands = {
1489 d0c8c01d Iustin Pop
  "init": (
1490 6ea815cf Iustin Pop
    InitCluster, [ArgHost(min=1, max=1)],
1491 064c21f8 Iustin Pop
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, GLOBAL_FILEDIR_OPT,
1492 5a8648eb Andrea Spadaccini
     HVLIST_OPT, MAC_PREFIX_OPT, MASTER_NETDEV_OPT, MASTER_NETMASK_OPT,
1493 5a8648eb Andrea Spadaccini
     NIC_PARAMS_OPT, NOLVM_STORAGE_OPT, NOMODIFY_ETCHOSTS_OPT,
1494 5a8648eb Andrea Spadaccini
     NOMODIFY_SSH_SETUP_OPT, SECONDARY_IP_OPT, VG_NAME_OPT,
1495 5a8648eb Andrea Spadaccini
     MAINTAIN_NODE_HEALTH_OPT, UIDPOOL_OPT, DRBD_HELPER_OPT, NODRBD_STORAGE_OPT,
1496 6204ee71 René Nussbaumer
     DEFAULT_IALLOCATOR_OPT, PRIMARY_IP_VERSION_OPT, PREALLOC_WIPE_DISKS_OPT,
1497 bc5d0215 Andrea Spadaccini
     NODE_PARAMS_OPT, GLOBAL_SHARED_FILEDIR_OPT, USE_EXTERNAL_MIP_SCRIPT,
1498 c4929a8b René Nussbaumer
     DISK_PARAMS_OPT, HV_STATE_OPT, DISK_STATE_OPT] + INSTANCE_POLICY_OPTS,
1499 6ea815cf Iustin Pop
    "[opts...] <cluster_name>", "Initialises a new cluster configuration"),
1500 d0c8c01d Iustin Pop
  "destroy": (
1501 064c21f8 Iustin Pop
    DestroyCluster, ARGS_NONE, [YES_DOIT_OPT],
1502 6ea815cf Iustin Pop
    "", "Destroy cluster"),
1503 d0c8c01d Iustin Pop
  "rename": (
1504 6ea815cf Iustin Pop
    RenameCluster, [ArgHost(min=1, max=1)],
1505 db5a8a2d Iustin Pop
    [FORCE_OPT, DRY_RUN_OPT],
1506 6ea815cf Iustin Pop
    "<new_name>",
1507 6ea815cf Iustin Pop
    "Renames the cluster"),
1508 d0c8c01d Iustin Pop
  "redist-conf": (
1509 aa06f8c6 Michael Hanselmann
    RedistributeConfig, ARGS_NONE, [SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
1510 6ea815cf Iustin Pop
    "", "Forces a push of the configuration file and ssconf files"
1511 6ea815cf Iustin Pop
    " to the nodes in the cluster"),
1512 d0c8c01d Iustin Pop
  "verify": (
1513 6ea815cf Iustin Pop
    VerifyCluster, ARGS_NONE,
1514 db5a8a2d Iustin Pop
    [VERBOSE_OPT, DEBUG_SIMERR_OPT, ERROR_CODES_OPT, NONPLUS1_OPT,
1515 93f2399e Andrea Spadaccini
     DRY_RUN_OPT, PRIORITY_OPT, NODEGROUP_OPT, IGNORE_ERRORS_OPT],
1516 6ea815cf Iustin Pop
    "", "Does a check on the cluster configuration"),
1517 d0c8c01d Iustin Pop
  "verify-disks": (
1518 aa06f8c6 Michael Hanselmann
    VerifyDisks, ARGS_NONE, [PRIORITY_OPT],
1519 6ea815cf Iustin Pop
    "", "Does a check on the cluster disk status"),
1520 d0c8c01d Iustin Pop
  "repair-disk-sizes": (
1521 aa06f8c6 Michael Hanselmann
    RepairDiskSizes, ARGS_MANY_INSTANCES, [DRY_RUN_OPT, PRIORITY_OPT],
1522 eb5ac108 Michael Hanselmann
    "[instance...]", "Updates mismatches in recorded disk sizes"),
1523 d0c8c01d Iustin Pop
  "master-failover": (
1524 6022a419 Iustin Pop
    MasterFailover, ARGS_NONE, [NOVOTING_OPT, FORCE_FAILOVER],
1525 6ea815cf Iustin Pop
    "", "Makes the current node the master"),
1526 d0c8c01d Iustin Pop
  "master-ping": (
1527 4404ffad Iustin Pop
    MasterPing, ARGS_NONE, [],
1528 4404ffad Iustin Pop
    "", "Checks if the master is alive"),
1529 d0c8c01d Iustin Pop
  "version": (
1530 064c21f8 Iustin Pop
    ShowClusterVersion, ARGS_NONE, [],
1531 6ea815cf Iustin Pop
    "", "Shows the cluster version"),
1532 d0c8c01d Iustin Pop
  "getmaster": (
1533 064c21f8 Iustin Pop
    ShowClusterMaster, ARGS_NONE, [],
1534 6ea815cf Iustin Pop
    "", "Shows the cluster master"),
1535 d0c8c01d Iustin Pop
  "copyfile": (
1536 6ea815cf Iustin Pop
    ClusterCopyFile, [ArgFile(min=1, max=1)],
1537 b6e88032 Michael Hanselmann
    [NODE_LIST_OPT, USE_REPL_NET_OPT, NODEGROUP_OPT],
1538 6ea815cf Iustin Pop
    "[-n node...] <filename>", "Copies a file to all (or only some) nodes"),
1539 d0c8c01d Iustin Pop
  "command": (
1540 6ea815cf Iustin Pop
    RunClusterCommand, [ArgCommand(min=1)],
1541 d5b031dc Michael Hanselmann
    [NODE_LIST_OPT, NODEGROUP_OPT, SHOW_MACHINE_OPT, FAILURE_ONLY_OPT],
1542 6ea815cf Iustin Pop
    "[-n node...] <command>", "Runs a command on all (or only some) nodes"),
1543 d0c8c01d Iustin Pop
  "info": (
1544 d729e03a Guido Trotter
    ShowClusterConfig, ARGS_NONE, [ROMAN_OPT],
1545 d729e03a Guido Trotter
    "[--roman]", "Show cluster configuration"),
1546 d0c8c01d Iustin Pop
  "list-tags": (
1547 064c21f8 Iustin Pop
    ListTags, ARGS_NONE, [], "", "List the tags of the cluster"),
1548 d0c8c01d Iustin Pop
  "add-tags": (
1549 6bc3ed14 Michael Hanselmann
    AddTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT, SUBMIT_OPT],
1550 6ea815cf Iustin Pop
    "tag...", "Add tags to the cluster"),
1551 d0c8c01d Iustin Pop
  "remove-tags": (
1552 6bc3ed14 Michael Hanselmann
    RemoveTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT, SUBMIT_OPT],
1553 6ea815cf Iustin Pop
    "tag...", "Remove tags from the cluster"),
1554 d0c8c01d Iustin Pop
  "search-tags": (
1555 aa06f8c6 Michael Hanselmann
    SearchTags, [ArgUnknown(min=1, max=1)], [PRIORITY_OPT], "",
1556 aa06f8c6 Michael Hanselmann
    "Searches the tags on all objects on"
1557 6ea815cf Iustin Pop
    " the cluster for a given pattern (regex)"),
1558 d0c8c01d Iustin Pop
  "queue": (
1559 6ea815cf Iustin Pop
    QueueOps,
1560 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["drain", "undrain", "info"])],
1561 064c21f8 Iustin Pop
    [], "drain|undrain|info", "Change queue properties"),
1562 d0c8c01d Iustin Pop
  "watcher": (
1563 6ea815cf Iustin Pop
    WatcherOps,
1564 6ea815cf Iustin Pop
    [ArgChoice(min=1, max=1, choices=["pause", "continue", "info"]),
1565 6ea815cf Iustin Pop
     ArgSuggest(min=0, max=1, choices=["30m", "1h", "4h"])],
1566 064c21f8 Iustin Pop
    [],
1567 6ea815cf Iustin Pop
    "{pause <timespec>|continue|info}", "Change watcher properties"),
1568 d0c8c01d Iustin Pop
  "modify": (
1569 6ea815cf Iustin Pop
    SetClusterParams, ARGS_NONE,
1570 38f9d2cf Guido Trotter
    [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, HVLIST_OPT, MASTER_NETDEV_OPT,
1571 5a8648eb Andrea Spadaccini
     MASTER_NETMASK_OPT, NIC_PARAMS_OPT, NOLVM_STORAGE_OPT, VG_NAME_OPT,
1572 5a8648eb Andrea Spadaccini
     MAINTAIN_NODE_HEALTH_OPT, UIDPOOL_OPT, ADD_UIDS_OPT, REMOVE_UIDS_OPT,
1573 5a8648eb Andrea Spadaccini
     DRBD_HELPER_OPT, NODRBD_STORAGE_OPT, DEFAULT_IALLOCATOR_OPT,
1574 5a8648eb Andrea Spadaccini
     RESERVED_LVS_OPT, DRY_RUN_OPT, PRIORITY_OPT, PREALLOC_WIPE_DISKS_OPT,
1575 2da9f556 René Nussbaumer
     NODE_PARAMS_OPT, USE_EXTERNAL_MIP_SCRIPT, DISK_PARAMS_OPT, HV_STATE_OPT,
1576 c270ee07 Helga Velroyen
     DISK_STATE_OPT, SUBMIT_OPT, ENABLED_STORAGE_TYPES_OPT] +
1577 32017174 Agata Murawska
    INSTANCE_POLICY_OPTS,
1578 6ea815cf Iustin Pop
    "[opts...]",
1579 6ea815cf Iustin Pop
    "Alters the parameters of the cluster"),
1580 6d4a1656 Michael Hanselmann
  "renew-crypto": (
1581 6d4a1656 Michael Hanselmann
    RenewCrypto, ARGS_NONE,
1582 6b7d5878 Michael Hanselmann
    [NEW_CLUSTER_CERT_OPT, NEW_RAPI_CERT_OPT, RAPI_CERT_OPT,
1583 3db3eb2a Michael Hanselmann
     NEW_CONFD_HMAC_KEY_OPT, FORCE_OPT,
1584 b6267745 Andrea Spadaccini
     NEW_CLUSTER_DOMAIN_SECRET_OPT, CLUSTER_DOMAIN_SECRET_OPT,
1585 b6267745 Andrea Spadaccini
     NEW_SPICE_CERT_OPT, SPICE_CERT_OPT, SPICE_CACERT_OPT],
1586 6d4a1656 Michael Hanselmann
    "[opts...]",
1587 6d4a1656 Michael Hanselmann
    "Renews cluster certificates, keys and secrets"),
1588 66d1f035 René Nussbaumer
  "epo": (
1589 66d1f035 René Nussbaumer
    Epo, [ArgUnknown()],
1590 fcecea0b René Nussbaumer
    [FORCE_OPT, ON_OPT, GROUPS_OPT, ALL_OPT, OOB_TIMEOUT_OPT,
1591 cfed3b9f René Nussbaumer
     SHUTDOWN_TIMEOUT_OPT, POWER_DELAY_OPT],
1592 66d1f035 René Nussbaumer
    "[opts...] [args]",
1593 66d1f035 René Nussbaumer
    "Performs an emergency power-off on given args"),
1594 fb926117 Andrea Spadaccini
  "activate-master-ip": (
1595 fb926117 Andrea Spadaccini
    ActivateMasterIp, ARGS_NONE, [], "", "Activates the master IP"),
1596 fb926117 Andrea Spadaccini
  "deactivate-master-ip": (
1597 fb926117 Andrea Spadaccini
    DeactivateMasterIp, ARGS_NONE, [CONFIRM_OPT], "",
1598 fb926117 Andrea Spadaccini
    "Deactivates the master IP"),
1599 a8083063 Iustin Pop
  }
1600 a8083063 Iustin Pop
1601 6d4a1656 Michael Hanselmann
1602 c28502b1 Iustin Pop
#: dictionary with aliases for commands
1603 c28502b1 Iustin Pop
aliases = {
1604 d0c8c01d Iustin Pop
  "masterfailover": "master-failover",
1605 96897af7 Alexander Schreiber
  "show": "info",
1606 c28502b1 Iustin Pop
}
1607 c28502b1 Iustin Pop
1608 c28502b1 Iustin Pop
1609 7b3e7d41 Michael Hanselmann
def Main():
1610 7b3e7d41 Michael Hanselmann
  return GenericMain(commands, override={"tag_type": constants.TAG_CLUSTER},
1611 7b3e7d41 Michael Hanselmann
                     aliases=aliases)