Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_operation.py @ 3360026f

History | View | Annotate | Download (18.5 kB)

1 13f6af81 Thomas Thrainer
#
2 13f6af81 Thomas Thrainer
#
3 13f6af81 Thomas Thrainer
4 83f54caa Jose A. Lopes
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Google Inc.
5 13f6af81 Thomas Thrainer
#
6 13f6af81 Thomas Thrainer
# This program is free software; you can redistribute it and/or modify
7 13f6af81 Thomas Thrainer
# it under the terms of the GNU General Public License as published by
8 13f6af81 Thomas Thrainer
# the Free Software Foundation; either version 2 of the License, or
9 13f6af81 Thomas Thrainer
# (at your option) any later version.
10 13f6af81 Thomas Thrainer
#
11 13f6af81 Thomas Thrainer
# This program is distributed in the hope that it will be useful, but
12 13f6af81 Thomas Thrainer
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 13f6af81 Thomas Thrainer
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 13f6af81 Thomas Thrainer
# General Public License for more details.
15 13f6af81 Thomas Thrainer
#
16 13f6af81 Thomas Thrainer
# You should have received a copy of the GNU General Public License
17 13f6af81 Thomas Thrainer
# along with this program; if not, write to the Free Software
18 13f6af81 Thomas Thrainer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 13f6af81 Thomas Thrainer
# 02110-1301, USA.
20 13f6af81 Thomas Thrainer
21 13f6af81 Thomas Thrainer
22 13f6af81 Thomas Thrainer
"""Logical units dealing with instance operations (start/stop/...).
23 13f6af81 Thomas Thrainer

24 13f6af81 Thomas Thrainer
Those operations have in common that they affect the operating system in a
25 13f6af81 Thomas Thrainer
running instance directly.
26 13f6af81 Thomas Thrainer

27 13f6af81 Thomas Thrainer
"""
28 13f6af81 Thomas Thrainer
29 13f6af81 Thomas Thrainer
import logging
30 13f6af81 Thomas Thrainer
31 13f6af81 Thomas Thrainer
from ganeti import constants
32 13f6af81 Thomas Thrainer
from ganeti import errors
33 13f6af81 Thomas Thrainer
from ganeti import hypervisor
34 13f6af81 Thomas Thrainer
from ganeti import locking
35 13f6af81 Thomas Thrainer
from ganeti import objects
36 13f6af81 Thomas Thrainer
from ganeti import utils
37 13f6af81 Thomas Thrainer
from ganeti.cmdlib.base import LogicalUnit, NoHooksLU
38 13f6af81 Thomas Thrainer
from ganeti.cmdlib.common import INSTANCE_ONLINE, INSTANCE_DOWN, \
39 1c3231aa Thomas Thrainer
  CheckHVParams, CheckInstanceState, CheckNodeOnline, GetUpdatedParams, \
40 83f54caa Jose A. Lopes
  CheckOSParams, CheckOSImage, ShareAll
41 5eacbcae Thomas Thrainer
from ganeti.cmdlib.instance_storage import StartInstanceDisks, \
42 83f54caa Jose A. Lopes
  ShutdownInstanceDisks, ImageDisks
43 5eacbcae Thomas Thrainer
from ganeti.cmdlib.instance_utils import BuildInstanceHookEnvByObject, \
44 5eacbcae Thomas Thrainer
  CheckInstanceBridgesExist, CheckNodeFreeMemory, CheckNodeHasOS
45 9c71582f Jose A. Lopes
from ganeti.hypervisor import hv_base
46 13f6af81 Thomas Thrainer
47 13f6af81 Thomas Thrainer
48 13f6af81 Thomas Thrainer
class LUInstanceStartup(LogicalUnit):
49 13f6af81 Thomas Thrainer
  """Starts an instance.
50 13f6af81 Thomas Thrainer

51 13f6af81 Thomas Thrainer
  """
52 13f6af81 Thomas Thrainer
  HPATH = "instance-start"
53 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
54 13f6af81 Thomas Thrainer
  REQ_BGL = False
55 13f6af81 Thomas Thrainer
56 13f6af81 Thomas Thrainer
  def CheckArguments(self):
57 13f6af81 Thomas Thrainer
    # extra beparams
58 13f6af81 Thomas Thrainer
    if self.op.beparams:
59 13f6af81 Thomas Thrainer
      # fill the beparams dict
60 13f6af81 Thomas Thrainer
      objects.UpgradeBeParams(self.op.beparams)
61 13f6af81 Thomas Thrainer
      utils.ForceDictType(self.op.beparams, constants.BES_PARAMETER_TYPES)
62 13f6af81 Thomas Thrainer
63 13f6af81 Thomas Thrainer
  def ExpandNames(self):
64 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
65 13f6af81 Thomas Thrainer
    self.recalculate_locks[locking.LEVEL_NODE_RES] = constants.LOCKS_REPLACE
66 13f6af81 Thomas Thrainer
67 13f6af81 Thomas Thrainer
  def DeclareLocks(self, level):
68 13f6af81 Thomas Thrainer
    if level == locking.LEVEL_NODE_RES:
69 13f6af81 Thomas Thrainer
      self._LockInstancesNodes(primary_only=True, level=locking.LEVEL_NODE_RES)
70 13f6af81 Thomas Thrainer
71 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
72 13f6af81 Thomas Thrainer
    """Build hooks env.
73 13f6af81 Thomas Thrainer

74 13f6af81 Thomas Thrainer
    This runs on master, primary and secondary nodes of the instance.
75 13f6af81 Thomas Thrainer

76 13f6af81 Thomas Thrainer
    """
77 13f6af81 Thomas Thrainer
    env = {
78 13f6af81 Thomas Thrainer
      "FORCE": self.op.force,
79 13f6af81 Thomas Thrainer
      }
80 13f6af81 Thomas Thrainer
81 5eacbcae Thomas Thrainer
    env.update(BuildInstanceHookEnvByObject(self, self.instance))
82 13f6af81 Thomas Thrainer
83 13f6af81 Thomas Thrainer
    return env
84 13f6af81 Thomas Thrainer
85 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
86 13f6af81 Thomas Thrainer
    """Build hooks nodes.
87 13f6af81 Thomas Thrainer

88 13f6af81 Thomas Thrainer
    """
89 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
90 13f6af81 Thomas Thrainer
    return (nl, nl)
91 13f6af81 Thomas Thrainer
92 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
93 13f6af81 Thomas Thrainer
    """Check prerequisites.
94 13f6af81 Thomas Thrainer

95 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
96 13f6af81 Thomas Thrainer

97 13f6af81 Thomas Thrainer
    """
98 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
99 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
100 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
101 13f6af81 Thomas Thrainer
102 0bbec3af Helga Velroyen
    cluster = self.cfg.GetClusterInfo()
103 13f6af81 Thomas Thrainer
    # extra hvparams
104 13f6af81 Thomas Thrainer
    if self.op.hvparams:
105 13f6af81 Thomas Thrainer
      # check hypervisor parameter syntax (locally)
106 13f6af81 Thomas Thrainer
      utils.ForceDictType(self.op.hvparams, constants.HVS_PARAMETER_TYPES)
107 d0d7d7cf Thomas Thrainer
      filled_hvp = cluster.FillHV(self.instance)
108 13f6af81 Thomas Thrainer
      filled_hvp.update(self.op.hvparams)
109 d0d7d7cf Thomas Thrainer
      hv_type = hypervisor.GetHypervisorClass(self.instance.hypervisor)
110 13f6af81 Thomas Thrainer
      hv_type.CheckParameterSyntax(filled_hvp)
111 d0d7d7cf Thomas Thrainer
      CheckHVParams(self, self.instance.all_nodes, self.instance.hypervisor,
112 d0d7d7cf Thomas Thrainer
                    filled_hvp)
113 13f6af81 Thomas Thrainer
114 d0d7d7cf Thomas Thrainer
    CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
115 13f6af81 Thomas Thrainer
116 d0d7d7cf Thomas Thrainer
    self.primary_offline = \
117 d0d7d7cf Thomas Thrainer
      self.cfg.GetNodeInfo(self.instance.primary_node).offline
118 13f6af81 Thomas Thrainer
119 13f6af81 Thomas Thrainer
    if self.primary_offline and self.op.ignore_offline_nodes:
120 13f6af81 Thomas Thrainer
      self.LogWarning("Ignoring offline primary node")
121 13f6af81 Thomas Thrainer
122 13f6af81 Thomas Thrainer
      if self.op.hvparams or self.op.beparams:
123 13f6af81 Thomas Thrainer
        self.LogWarning("Overridden parameters are ignored")
124 13f6af81 Thomas Thrainer
    else:
125 d0d7d7cf Thomas Thrainer
      CheckNodeOnline(self, self.instance.primary_node)
126 13f6af81 Thomas Thrainer
127 d0d7d7cf Thomas Thrainer
      bep = self.cfg.GetClusterInfo().FillBE(self.instance)
128 13f6af81 Thomas Thrainer
      bep.update(self.op.beparams)
129 13f6af81 Thomas Thrainer
130 13f6af81 Thomas Thrainer
      # check bridges existence
131 d0d7d7cf Thomas Thrainer
      CheckInstanceBridgesExist(self, self.instance)
132 13f6af81 Thomas Thrainer
133 0bbec3af Helga Velroyen
      remote_info = self.rpc.call_instance_info(
134 d0d7d7cf Thomas Thrainer
          self.instance.primary_node, self.instance.name,
135 d0d7d7cf Thomas Thrainer
          self.instance.hypervisor, cluster.hvparams[self.instance.hypervisor])
136 1c3231aa Thomas Thrainer
      remote_info.Raise("Error checking node %s" %
137 d0d7d7cf Thomas Thrainer
                        self.cfg.GetNodeName(self.instance.primary_node),
138 13f6af81 Thomas Thrainer
                        prereq=True, ecode=errors.ECODE_ENVIRON)
139 9c71582f Jose A. Lopes
      if remote_info.payload:
140 9c71582f Jose A. Lopes
        if hv_base.HvInstanceState.IsShutdown(remote_info.payload["state"]):
141 9c71582f Jose A. Lopes
          raise errors.OpPrereqError("Instance '%s' was shutdown by the user,"
142 9c71582f Jose A. Lopes
                                     " please shutdown the instance before"
143 9c71582f Jose A. Lopes
                                     " starting it again" % self.instance.name,
144 9c71582f Jose A. Lopes
                                     errors.ECODE_INVAL)
145 9c71582f Jose A. Lopes
      else: # not running already
146 a295eb80 Helga Velroyen
        CheckNodeFreeMemory(
147 d0d7d7cf Thomas Thrainer
            self, self.instance.primary_node,
148 d0d7d7cf Thomas Thrainer
            "starting instance %s" % self.instance.name,
149 d0d7d7cf Thomas Thrainer
            bep[constants.BE_MINMEM], self.instance.hypervisor,
150 d0d7d7cf Thomas Thrainer
            self.cfg.GetClusterInfo().hvparams[self.instance.hypervisor])
151 13f6af81 Thomas Thrainer
152 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
153 13f6af81 Thomas Thrainer
    """Start the instance.
154 13f6af81 Thomas Thrainer

155 13f6af81 Thomas Thrainer
    """
156 13f6af81 Thomas Thrainer
    if not self.op.no_remember:
157 da4a52a3 Thomas Thrainer
      self.cfg.MarkInstanceUp(self.instance.uuid)
158 13f6af81 Thomas Thrainer
159 13f6af81 Thomas Thrainer
    if self.primary_offline:
160 13f6af81 Thomas Thrainer
      assert self.op.ignore_offline_nodes
161 13f6af81 Thomas Thrainer
      self.LogInfo("Primary node offline, marked instance as started")
162 13f6af81 Thomas Thrainer
    else:
163 d0d7d7cf Thomas Thrainer
      StartInstanceDisks(self, self.instance, self.op.force)
164 13f6af81 Thomas Thrainer
165 13f6af81 Thomas Thrainer
      result = \
166 d0d7d7cf Thomas Thrainer
        self.rpc.call_instance_start(self.instance.primary_node,
167 d0d7d7cf Thomas Thrainer
                                     (self.instance, self.op.hvparams,
168 13f6af81 Thomas Thrainer
                                      self.op.beparams),
169 d0d7d7cf Thomas Thrainer
                                     self.op.startup_paused, self.op.reason)
170 13f6af81 Thomas Thrainer
      msg = result.fail_msg
171 13f6af81 Thomas Thrainer
      if msg:
172 d0d7d7cf Thomas Thrainer
        ShutdownInstanceDisks(self, self.instance)
173 13f6af81 Thomas Thrainer
        raise errors.OpExecError("Could not start instance: %s" % msg)
174 13f6af81 Thomas Thrainer
175 13f6af81 Thomas Thrainer
176 13f6af81 Thomas Thrainer
class LUInstanceShutdown(LogicalUnit):
177 13f6af81 Thomas Thrainer
  """Shutdown an instance.
178 13f6af81 Thomas Thrainer

179 13f6af81 Thomas Thrainer
  """
180 13f6af81 Thomas Thrainer
  HPATH = "instance-stop"
181 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
182 13f6af81 Thomas Thrainer
  REQ_BGL = False
183 13f6af81 Thomas Thrainer
184 13f6af81 Thomas Thrainer
  def ExpandNames(self):
185 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
186 13f6af81 Thomas Thrainer
187 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
188 13f6af81 Thomas Thrainer
    """Build hooks env.
189 13f6af81 Thomas Thrainer

190 13f6af81 Thomas Thrainer
    This runs on master, primary and secondary nodes of the instance.
191 13f6af81 Thomas Thrainer

192 13f6af81 Thomas Thrainer
    """
193 5eacbcae Thomas Thrainer
    env = BuildInstanceHookEnvByObject(self, self.instance)
194 5cbf7832 Jose A. Lopes
    env["TIMEOUT"] = self.op.timeout
195 13f6af81 Thomas Thrainer
    return env
196 13f6af81 Thomas Thrainer
197 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
198 13f6af81 Thomas Thrainer
    """Build hooks nodes.
199 13f6af81 Thomas Thrainer

200 13f6af81 Thomas Thrainer
    """
201 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
202 13f6af81 Thomas Thrainer
    return (nl, nl)
203 13f6af81 Thomas Thrainer
204 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
205 13f6af81 Thomas Thrainer
    """Check prerequisites.
206 13f6af81 Thomas Thrainer

207 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
208 13f6af81 Thomas Thrainer

209 13f6af81 Thomas Thrainer
    """
210 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
211 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
212 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
213 13f6af81 Thomas Thrainer
214 13f6af81 Thomas Thrainer
    if not self.op.force:
215 5eacbcae Thomas Thrainer
      CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
216 13f6af81 Thomas Thrainer
    else:
217 13f6af81 Thomas Thrainer
      self.LogWarning("Ignoring offline instance check")
218 13f6af81 Thomas Thrainer
219 13f6af81 Thomas Thrainer
    self.primary_offline = \
220 13f6af81 Thomas Thrainer
      self.cfg.GetNodeInfo(self.instance.primary_node).offline
221 13f6af81 Thomas Thrainer
222 13f6af81 Thomas Thrainer
    if self.primary_offline and self.op.ignore_offline_nodes:
223 13f6af81 Thomas Thrainer
      self.LogWarning("Ignoring offline primary node")
224 13f6af81 Thomas Thrainer
    else:
225 5eacbcae Thomas Thrainer
      CheckNodeOnline(self, self.instance.primary_node)
226 13f6af81 Thomas Thrainer
227 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
228 13f6af81 Thomas Thrainer
    """Shutdown the instance.
229 13f6af81 Thomas Thrainer

230 13f6af81 Thomas Thrainer
    """
231 13f6af81 Thomas Thrainer
    # If the instance is offline we shouldn't mark it as down, as that
232 13f6af81 Thomas Thrainer
    # resets the offline flag.
233 d0d7d7cf Thomas Thrainer
    if not self.op.no_remember and self.instance.admin_state in INSTANCE_ONLINE:
234 da4a52a3 Thomas Thrainer
      self.cfg.MarkInstanceDown(self.instance.uuid)
235 13f6af81 Thomas Thrainer
236 13f6af81 Thomas Thrainer
    if self.primary_offline:
237 13f6af81 Thomas Thrainer
      assert self.op.ignore_offline_nodes
238 13f6af81 Thomas Thrainer
      self.LogInfo("Primary node offline, marked instance as stopped")
239 13f6af81 Thomas Thrainer
    else:
240 34af39e8 Jose A. Lopes
      result = self.rpc.call_instance_shutdown(
241 34af39e8 Jose A. Lopes
        self.instance.primary_node,
242 34af39e8 Jose A. Lopes
        self.instance,
243 5cbf7832 Jose A. Lopes
        self.op.timeout, self.op.reason)
244 13f6af81 Thomas Thrainer
      msg = result.fail_msg
245 13f6af81 Thomas Thrainer
      if msg:
246 13f6af81 Thomas Thrainer
        self.LogWarning("Could not shutdown instance: %s", msg)
247 13f6af81 Thomas Thrainer
248 d0d7d7cf Thomas Thrainer
      ShutdownInstanceDisks(self, self.instance)
249 13f6af81 Thomas Thrainer
250 13f6af81 Thomas Thrainer
251 13f6af81 Thomas Thrainer
class LUInstanceReinstall(LogicalUnit):
252 13f6af81 Thomas Thrainer
  """Reinstall an instance.
253 13f6af81 Thomas Thrainer

254 13f6af81 Thomas Thrainer
  """
255 13f6af81 Thomas Thrainer
  HPATH = "instance-reinstall"
256 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
257 13f6af81 Thomas Thrainer
  REQ_BGL = False
258 13f6af81 Thomas Thrainer
259 83f54caa Jose A. Lopes
  def CheckArguments(self):
260 83f54caa Jose A. Lopes
    CheckOSImage(self.op)
261 83f54caa Jose A. Lopes
262 13f6af81 Thomas Thrainer
  def ExpandNames(self):
263 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
264 13f6af81 Thomas Thrainer
265 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
266 13f6af81 Thomas Thrainer
    """Build hooks env.
267 13f6af81 Thomas Thrainer

268 13f6af81 Thomas Thrainer
    This runs on master, primary and secondary nodes of the instance.
269 13f6af81 Thomas Thrainer

270 13f6af81 Thomas Thrainer
    """
271 5eacbcae Thomas Thrainer
    return BuildInstanceHookEnvByObject(self, self.instance)
272 13f6af81 Thomas Thrainer
273 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
274 13f6af81 Thomas Thrainer
    """Build hooks nodes.
275 13f6af81 Thomas Thrainer

276 13f6af81 Thomas Thrainer
    """
277 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
278 13f6af81 Thomas Thrainer
    return (nl, nl)
279 13f6af81 Thomas Thrainer
280 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
281 13f6af81 Thomas Thrainer
    """Check prerequisites.
282 13f6af81 Thomas Thrainer

283 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster and is not running.
284 13f6af81 Thomas Thrainer

285 13f6af81 Thomas Thrainer
    """
286 da4a52a3 Thomas Thrainer
    instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
287 13f6af81 Thomas Thrainer
    assert instance is not None, \
288 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
289 5eacbcae Thomas Thrainer
    CheckNodeOnline(self, instance.primary_node, "Instance primary node"
290 5eacbcae Thomas Thrainer
                    " offline, cannot reinstall")
291 13f6af81 Thomas Thrainer
292 13f6af81 Thomas Thrainer
    if instance.disk_template == constants.DT_DISKLESS:
293 13f6af81 Thomas Thrainer
      raise errors.OpPrereqError("Instance '%s' has no disks" %
294 13f6af81 Thomas Thrainer
                                 self.op.instance_name,
295 13f6af81 Thomas Thrainer
                                 errors.ECODE_INVAL)
296 5eacbcae Thomas Thrainer
    CheckInstanceState(self, instance, INSTANCE_DOWN, msg="cannot reinstall")
297 13f6af81 Thomas Thrainer
298 da0aa302 Santi Raffa
    # Handle OS parameters
299 da0aa302 Santi Raffa
    self._MergeValidateOsParams(instance)
300 da0aa302 Santi Raffa
301 da0aa302 Santi Raffa
    self.instance = instance
302 da0aa302 Santi Raffa
303 da0aa302 Santi Raffa
  def _MergeValidateOsParams(self, instance):
304 da0aa302 Santi Raffa
    "Handle the OS parameter merging and validation for the target instance."
305 da0aa302 Santi Raffa
306 13f6af81 Thomas Thrainer
    if self.op.os_type is not None:
307 13f6af81 Thomas Thrainer
      # OS verification
308 1c3231aa Thomas Thrainer
      CheckNodeHasOS(self, instance.primary_node, self.op.os_type,
309 1c3231aa Thomas Thrainer
                     self.op.force_variant)
310 13f6af81 Thomas Thrainer
      instance_os = self.op.os_type
311 13f6af81 Thomas Thrainer
    else:
312 13f6af81 Thomas Thrainer
      instance_os = instance.os
313 13f6af81 Thomas Thrainer
314 1c3231aa Thomas Thrainer
    node_uuids = list(instance.all_nodes)
315 13f6af81 Thomas Thrainer
316 da0aa302 Santi Raffa
    self.op.osparams = self.op.osparams or {}
317 da0aa302 Santi Raffa
    self.op.osparams_private = self.op.osparams_private or {}
318 da0aa302 Santi Raffa
    self.op.osparams_secret = self.op.osparams_secret or {}
319 13f6af81 Thomas Thrainer
320 da0aa302 Santi Raffa
    # Handle the use of 'default' values.
321 da0aa302 Santi Raffa
    params_public = GetUpdatedParams(instance.osparams, self.op.osparams)
322 da0aa302 Santi Raffa
    params_private = GetUpdatedParams(instance.osparams_private,
323 da0aa302 Santi Raffa
                                        self.op.osparams_private)
324 da0aa302 Santi Raffa
    params_secret = self.op.osparams_secret
325 da0aa302 Santi Raffa
326 da0aa302 Santi Raffa
    cluster = self.cfg.GetClusterInfo()
327 83f54caa Jose A. Lopes
    self.osparams = cluster.SimpleFillOS(
328 da0aa302 Santi Raffa
      instance_os,
329 da0aa302 Santi Raffa
      params_public,
330 da0aa302 Santi Raffa
      os_params_private=params_private,
331 da0aa302 Santi Raffa
      os_params_secret=params_secret
332 da0aa302 Santi Raffa
    )
333 da0aa302 Santi Raffa
334 83f54caa Jose A. Lopes
    CheckOSParams(self, True, node_uuids, instance_os, self.osparams)
335 83f54caa Jose A. Lopes
336 83f54caa Jose A. Lopes
  def _ReinstallOSScripts(self, instance, osparams, debug_level):
337 83f54caa Jose A. Lopes
    """Reinstall OS scripts on an instance.
338 83f54caa Jose A. Lopes

339 83f54caa Jose A. Lopes
    @type instance: L{objects.Instance}
340 83f54caa Jose A. Lopes
    @param instance: instance of which the OS scripts should run
341 83f54caa Jose A. Lopes

342 83f54caa Jose A. Lopes
    @type osparams: L{dict}
343 83f54caa Jose A. Lopes
    @param osparams: OS parameters
344 83f54caa Jose A. Lopes

345 83f54caa Jose A. Lopes
    @type debug_level: non-negative int
346 83f54caa Jose A. Lopes
    @param debug_level: debug level
347 83f54caa Jose A. Lopes

348 83f54caa Jose A. Lopes
    @rtype: NoneType
349 83f54caa Jose A. Lopes
    @return: None
350 83f54caa Jose A. Lopes
    @raise errors.OpExecError: in case of failure
351 83f54caa Jose A. Lopes

352 83f54caa Jose A. Lopes
    """
353 83f54caa Jose A. Lopes
    self.LogInfo("Running instance OS create scripts...")
354 83f54caa Jose A. Lopes
    result = self.rpc.call_instance_os_add(instance.primary_node,
355 83f54caa Jose A. Lopes
                                           (instance, osparams),
356 83f54caa Jose A. Lopes
                                           True,
357 83f54caa Jose A. Lopes
                                           debug_level)
358 83f54caa Jose A. Lopes
    result.Raise("Could not install OS for instance '%s' on node '%s'" %
359 83f54caa Jose A. Lopes
                 (instance.name, self.cfg.GetNodeName(instance.primary_node)))
360 83f54caa Jose A. Lopes
361 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
362 13f6af81 Thomas Thrainer
    """Reinstall the instance.
363 13f6af81 Thomas Thrainer

364 13f6af81 Thomas Thrainer
    """
365 83f54caa Jose A. Lopes
    os_image = objects.GetOSImage(self.op.osparams)
366 83f54caa Jose A. Lopes
367 83f54caa Jose A. Lopes
    if os_image is not None:
368 83f54caa Jose A. Lopes
      feedback_fn("Using OS image '%s', not changing instance"
369 83f54caa Jose A. Lopes
                  " configuration" % os_image)
370 83f54caa Jose A. Lopes
    else:
371 83f54caa Jose A. Lopes
      os_image = objects.GetOSImage(self.instance.osparams)
372 83f54caa Jose A. Lopes
373 83f54caa Jose A. Lopes
    os_type = self.op.os_type
374 83f54caa Jose A. Lopes
375 83f54caa Jose A. Lopes
    if os_type is not None:
376 83f54caa Jose A. Lopes
      feedback_fn("Changing OS scripts to '%s'..." % os_type)
377 83f54caa Jose A. Lopes
      self.instance.os = os_type
378 d0d7d7cf Thomas Thrainer
      self.cfg.Update(self.instance, feedback_fn)
379 83f54caa Jose A. Lopes
    else:
380 83f54caa Jose A. Lopes
      os_type = self.instance.os
381 13f6af81 Thomas Thrainer
382 83f54caa Jose A. Lopes
    if not os_image and not os_type:
383 83f54caa Jose A. Lopes
      self.LogInfo("No OS scripts or OS image specified or found in the"
384 83f54caa Jose A. Lopes
                   " instance's configuration, nothing to install")
385 83f54caa Jose A. Lopes
    else:
386 83f54caa Jose A. Lopes
      StartInstanceDisks(self, self.instance, None)
387 83f54caa Jose A. Lopes
      try:
388 83f54caa Jose A. Lopes
        if os_image:
389 3360026f Jose A. Lopes
          ImageDisks(self, self.instance, os_image)
390 83f54caa Jose A. Lopes
391 83f54caa Jose A. Lopes
        if os_type:
392 83f54caa Jose A. Lopes
          self._ReinstallOSScripts(self.instance, self.osparams,
393 83f54caa Jose A. Lopes
                                   self.op.debug_level)
394 83f54caa Jose A. Lopes
      finally:
395 83f54caa Jose A. Lopes
        ShutdownInstanceDisks(self, self.instance)
396 13f6af81 Thomas Thrainer
397 13f6af81 Thomas Thrainer
398 13f6af81 Thomas Thrainer
class LUInstanceReboot(LogicalUnit):
399 13f6af81 Thomas Thrainer
  """Reboot an instance.
400 13f6af81 Thomas Thrainer

401 13f6af81 Thomas Thrainer
  """
402 13f6af81 Thomas Thrainer
  HPATH = "instance-reboot"
403 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
404 13f6af81 Thomas Thrainer
  REQ_BGL = False
405 13f6af81 Thomas Thrainer
406 13f6af81 Thomas Thrainer
  def ExpandNames(self):
407 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
408 13f6af81 Thomas Thrainer
409 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
410 13f6af81 Thomas Thrainer
    """Build hooks env.
411 13f6af81 Thomas Thrainer

412 13f6af81 Thomas Thrainer
    This runs on master, primary and secondary nodes of the instance.
413 13f6af81 Thomas Thrainer

414 13f6af81 Thomas Thrainer
    """
415 13f6af81 Thomas Thrainer
    env = {
416 13f6af81 Thomas Thrainer
      "IGNORE_SECONDARIES": self.op.ignore_secondaries,
417 13f6af81 Thomas Thrainer
      "REBOOT_TYPE": self.op.reboot_type,
418 13f6af81 Thomas Thrainer
      "SHUTDOWN_TIMEOUT": self.op.shutdown_timeout,
419 13f6af81 Thomas Thrainer
      }
420 13f6af81 Thomas Thrainer
421 5eacbcae Thomas Thrainer
    env.update(BuildInstanceHookEnvByObject(self, self.instance))
422 13f6af81 Thomas Thrainer
423 13f6af81 Thomas Thrainer
    return env
424 13f6af81 Thomas Thrainer
425 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
426 13f6af81 Thomas Thrainer
    """Build hooks nodes.
427 13f6af81 Thomas Thrainer

428 13f6af81 Thomas Thrainer
    """
429 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
430 13f6af81 Thomas Thrainer
    return (nl, nl)
431 13f6af81 Thomas Thrainer
432 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
433 13f6af81 Thomas Thrainer
    """Check prerequisites.
434 13f6af81 Thomas Thrainer

435 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
436 13f6af81 Thomas Thrainer

437 13f6af81 Thomas Thrainer
    """
438 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
439 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
440 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
441 d0d7d7cf Thomas Thrainer
    CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
442 d0d7d7cf Thomas Thrainer
    CheckNodeOnline(self, self.instance.primary_node)
443 13f6af81 Thomas Thrainer
444 13f6af81 Thomas Thrainer
    # check bridges existence
445 d0d7d7cf Thomas Thrainer
    CheckInstanceBridgesExist(self, self.instance)
446 13f6af81 Thomas Thrainer
447 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
448 13f6af81 Thomas Thrainer
    """Reboot the instance.
449 13f6af81 Thomas Thrainer

450 13f6af81 Thomas Thrainer
    """
451 0bbec3af Helga Velroyen
    cluster = self.cfg.GetClusterInfo()
452 0bbec3af Helga Velroyen
    remote_info = self.rpc.call_instance_info(
453 d0d7d7cf Thomas Thrainer
        self.instance.primary_node, self.instance.name,
454 d0d7d7cf Thomas Thrainer
        self.instance.hypervisor, cluster.hvparams[self.instance.hypervisor])
455 1c3231aa Thomas Thrainer
    remote_info.Raise("Error checking node %s" %
456 d0d7d7cf Thomas Thrainer
                      self.cfg.GetNodeName(self.instance.primary_node))
457 13f6af81 Thomas Thrainer
    instance_running = bool(remote_info.payload)
458 13f6af81 Thomas Thrainer
459 d0d7d7cf Thomas Thrainer
    current_node_uuid = self.instance.primary_node
460 13f6af81 Thomas Thrainer
461 d0d7d7cf Thomas Thrainer
    if instance_running and \
462 d0d7d7cf Thomas Thrainer
        self.op.reboot_type in [constants.INSTANCE_REBOOT_SOFT,
463 d0d7d7cf Thomas Thrainer
                                constants.INSTANCE_REBOOT_HARD]:
464 d0d7d7cf Thomas Thrainer
      result = self.rpc.call_instance_reboot(current_node_uuid, self.instance,
465 d0d7d7cf Thomas Thrainer
                                             self.op.reboot_type,
466 d0d7d7cf Thomas Thrainer
                                             self.op.shutdown_timeout,
467 d0d7d7cf Thomas Thrainer
                                             self.op.reason)
468 13f6af81 Thomas Thrainer
      result.Raise("Could not reboot instance")
469 13f6af81 Thomas Thrainer
    else:
470 13f6af81 Thomas Thrainer
      if instance_running:
471 d0d7d7cf Thomas Thrainer
        result = self.rpc.call_instance_shutdown(current_node_uuid,
472 d0d7d7cf Thomas Thrainer
                                                 self.instance,
473 13f6af81 Thomas Thrainer
                                                 self.op.shutdown_timeout,
474 d0d7d7cf Thomas Thrainer
                                                 self.op.reason)
475 13f6af81 Thomas Thrainer
        result.Raise("Could not shutdown instance for full reboot")
476 d0d7d7cf Thomas Thrainer
        ShutdownInstanceDisks(self, self.instance)
477 13f6af81 Thomas Thrainer
      else:
478 13f6af81 Thomas Thrainer
        self.LogInfo("Instance %s was already stopped, starting now",
479 d0d7d7cf Thomas Thrainer
                     self.instance.name)
480 d0d7d7cf Thomas Thrainer
      StartInstanceDisks(self, self.instance, self.op.ignore_secondaries)
481 1c3231aa Thomas Thrainer
      result = self.rpc.call_instance_start(current_node_uuid,
482 d0d7d7cf Thomas Thrainer
                                            (self.instance, None, None), False,
483 d0d7d7cf Thomas Thrainer
                                            self.op.reason)
484 13f6af81 Thomas Thrainer
      msg = result.fail_msg
485 13f6af81 Thomas Thrainer
      if msg:
486 d0d7d7cf Thomas Thrainer
        ShutdownInstanceDisks(self, self.instance)
487 13f6af81 Thomas Thrainer
        raise errors.OpExecError("Could not start instance for"
488 13f6af81 Thomas Thrainer
                                 " full reboot: %s" % msg)
489 13f6af81 Thomas Thrainer
490 da4a52a3 Thomas Thrainer
    self.cfg.MarkInstanceUp(self.instance.uuid)
491 13f6af81 Thomas Thrainer
492 13f6af81 Thomas Thrainer
493 c42be2c0 Petr Pudlak
def GetInstanceConsole(cluster, instance, primary_node, node_group):
494 13f6af81 Thomas Thrainer
  """Returns console information for an instance.
495 13f6af81 Thomas Thrainer

496 13f6af81 Thomas Thrainer
  @type cluster: L{objects.Cluster}
497 13f6af81 Thomas Thrainer
  @type instance: L{objects.Instance}
498 1c3231aa Thomas Thrainer
  @type primary_node: L{objects.Node}
499 c42be2c0 Petr Pudlak
  @type node_group: L{objects.NodeGroup}
500 13f6af81 Thomas Thrainer
  @rtype: dict
501 13f6af81 Thomas Thrainer

502 13f6af81 Thomas Thrainer
  """
503 f92d9674 Helga Velroyen
  hyper = hypervisor.GetHypervisorClass(instance.hypervisor)
504 13f6af81 Thomas Thrainer
  # beparams and hvparams are passed separately, to avoid editing the
505 13f6af81 Thomas Thrainer
  # instance and then saving the defaults in the instance itself.
506 13f6af81 Thomas Thrainer
  hvparams = cluster.FillHV(instance)
507 13f6af81 Thomas Thrainer
  beparams = cluster.FillBE(instance)
508 c42be2c0 Petr Pudlak
  console = hyper.GetInstanceConsole(instance, primary_node, node_group,
509 c42be2c0 Petr Pudlak
                                     hvparams, beparams)
510 13f6af81 Thomas Thrainer
511 13f6af81 Thomas Thrainer
  assert console.instance == instance.name
512 b3724640 Jose A. Lopes
  console.Validate()
513 13f6af81 Thomas Thrainer
514 13f6af81 Thomas Thrainer
  return console.ToDict()
515 13f6af81 Thomas Thrainer
516 13f6af81 Thomas Thrainer
517 13f6af81 Thomas Thrainer
class LUInstanceConsole(NoHooksLU):
518 13f6af81 Thomas Thrainer
  """Connect to an instance's console.
519 13f6af81 Thomas Thrainer

520 13f6af81 Thomas Thrainer
  This is somewhat special in that it returns the command line that
521 13f6af81 Thomas Thrainer
  you need to run on the master node in order to connect to the
522 13f6af81 Thomas Thrainer
  console.
523 13f6af81 Thomas Thrainer

524 13f6af81 Thomas Thrainer
  """
525 13f6af81 Thomas Thrainer
  REQ_BGL = False
526 13f6af81 Thomas Thrainer
527 13f6af81 Thomas Thrainer
  def ExpandNames(self):
528 5eacbcae Thomas Thrainer
    self.share_locks = ShareAll()
529 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
530 13f6af81 Thomas Thrainer
531 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
532 13f6af81 Thomas Thrainer
    """Check prerequisites.
533 13f6af81 Thomas Thrainer

534 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
535 13f6af81 Thomas Thrainer

536 13f6af81 Thomas Thrainer
    """
537 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
538 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
539 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
540 5eacbcae Thomas Thrainer
    CheckNodeOnline(self, self.instance.primary_node)
541 13f6af81 Thomas Thrainer
542 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
543 13f6af81 Thomas Thrainer
    """Connect to the console of an instance
544 13f6af81 Thomas Thrainer

545 13f6af81 Thomas Thrainer
    """
546 d0d7d7cf Thomas Thrainer
    node_uuid = self.instance.primary_node
547 13f6af81 Thomas Thrainer
548 8ac806e6 Helga Velroyen
    cluster_hvparams = self.cfg.GetClusterInfo().hvparams
549 d0d7d7cf Thomas Thrainer
    node_insts = self.rpc.call_instance_list(
550 d0d7d7cf Thomas Thrainer
                   [node_uuid], [self.instance.hypervisor],
551 d0d7d7cf Thomas Thrainer
                   cluster_hvparams)[node_uuid]
552 1c3231aa Thomas Thrainer
    node_insts.Raise("Can't get node information from %s" %
553 1c3231aa Thomas Thrainer
                     self.cfg.GetNodeName(node_uuid))
554 13f6af81 Thomas Thrainer
555 d0d7d7cf Thomas Thrainer
    if self.instance.name not in node_insts.payload:
556 d0d7d7cf Thomas Thrainer
      if self.instance.admin_state == constants.ADMINST_UP:
557 13f6af81 Thomas Thrainer
        state = constants.INSTST_ERRORDOWN
558 d0d7d7cf Thomas Thrainer
      elif self.instance.admin_state == constants.ADMINST_DOWN:
559 13f6af81 Thomas Thrainer
        state = constants.INSTST_ADMINDOWN
560 13f6af81 Thomas Thrainer
      else:
561 13f6af81 Thomas Thrainer
        state = constants.INSTST_ADMINOFFLINE
562 13f6af81 Thomas Thrainer
      raise errors.OpExecError("Instance %s is not running (state %s)" %
563 d0d7d7cf Thomas Thrainer
                               (self.instance.name, state))
564 13f6af81 Thomas Thrainer
565 d0d7d7cf Thomas Thrainer
    logging.debug("Connecting to console of %s on %s", self.instance.name,
566 1c3231aa Thomas Thrainer
                  self.cfg.GetNodeName(node_uuid))
567 13f6af81 Thomas Thrainer
568 c42be2c0 Petr Pudlak
    node = self.cfg.GetNodeInfo(self.instance.primary_node)
569 c42be2c0 Petr Pudlak
    group = self.cfg.GetNodeGroup(node.group)
570 c42be2c0 Petr Pudlak
    return GetInstanceConsole(self.cfg.GetClusterInfo(),
571 c42be2c0 Petr Pudlak
                              self.instance, node, group)