Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_operation.py @ 9808764a

History | View | Annotate | Download (17.3 kB)

1 13f6af81 Thomas Thrainer
#
2 13f6af81 Thomas Thrainer
#
3 13f6af81 Thomas Thrainer
4 13f6af81 Thomas Thrainer
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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 1c3231aa Thomas Thrainer
  CheckOSParams, ShareAll
41 5eacbcae Thomas Thrainer
from ganeti.cmdlib.instance_storage import StartInstanceDisks, \
42 5eacbcae Thomas Thrainer
  ShutdownInstanceDisks
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 13f6af81 Thomas Thrainer
  def ExpandNames(self):
260 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
261 13f6af81 Thomas Thrainer
262 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
263 13f6af81 Thomas Thrainer
    """Build hooks env.
264 13f6af81 Thomas Thrainer

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

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

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

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

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

336 13f6af81 Thomas Thrainer
    """
337 13f6af81 Thomas Thrainer
    if self.op.os_type is not None:
338 13f6af81 Thomas Thrainer
      feedback_fn("Changing OS to '%s'..." % self.op.os_type)
339 d0d7d7cf Thomas Thrainer
      self.instance.os = self.op.os_type
340 13f6af81 Thomas Thrainer
      # Write to configuration
341 d0d7d7cf Thomas Thrainer
      self.cfg.Update(self.instance, feedback_fn)
342 13f6af81 Thomas Thrainer
343 d0d7d7cf Thomas Thrainer
    StartInstanceDisks(self, self.instance, None)
344 13f6af81 Thomas Thrainer
    try:
345 13f6af81 Thomas Thrainer
      feedback_fn("Running the instance OS create scripts...")
346 13f6af81 Thomas Thrainer
      # FIXME: pass debug option from opcode to backend
347 d0d7d7cf Thomas Thrainer
      result = self.rpc.call_instance_os_add(self.instance.primary_node,
348 d0d7d7cf Thomas Thrainer
                                             (self.instance, self.os_inst),
349 d0d7d7cf Thomas Thrainer
                                             True, self.op.debug_level)
350 13f6af81 Thomas Thrainer
      result.Raise("Could not install OS for instance %s on node %s" %
351 d0d7d7cf Thomas Thrainer
                   (self.instance.name,
352 d0d7d7cf Thomas Thrainer
                    self.cfg.GetNodeName(self.instance.primary_node)))
353 13f6af81 Thomas Thrainer
    finally:
354 d0d7d7cf Thomas Thrainer
      ShutdownInstanceDisks(self, self.instance)
355 13f6af81 Thomas Thrainer
356 13f6af81 Thomas Thrainer
357 13f6af81 Thomas Thrainer
class LUInstanceReboot(LogicalUnit):
358 13f6af81 Thomas Thrainer
  """Reboot an instance.
359 13f6af81 Thomas Thrainer

360 13f6af81 Thomas Thrainer
  """
361 13f6af81 Thomas Thrainer
  HPATH = "instance-reboot"
362 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
363 13f6af81 Thomas Thrainer
  REQ_BGL = False
364 13f6af81 Thomas Thrainer
365 13f6af81 Thomas Thrainer
  def ExpandNames(self):
366 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
367 13f6af81 Thomas Thrainer
368 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
369 13f6af81 Thomas Thrainer
    """Build hooks env.
370 13f6af81 Thomas Thrainer

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

373 13f6af81 Thomas Thrainer
    """
374 13f6af81 Thomas Thrainer
    env = {
375 13f6af81 Thomas Thrainer
      "IGNORE_SECONDARIES": self.op.ignore_secondaries,
376 13f6af81 Thomas Thrainer
      "REBOOT_TYPE": self.op.reboot_type,
377 13f6af81 Thomas Thrainer
      "SHUTDOWN_TIMEOUT": self.op.shutdown_timeout,
378 13f6af81 Thomas Thrainer
      }
379 13f6af81 Thomas Thrainer
380 5eacbcae Thomas Thrainer
    env.update(BuildInstanceHookEnvByObject(self, self.instance))
381 13f6af81 Thomas Thrainer
382 13f6af81 Thomas Thrainer
    return env
383 13f6af81 Thomas Thrainer
384 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
385 13f6af81 Thomas Thrainer
    """Build hooks nodes.
386 13f6af81 Thomas Thrainer

387 13f6af81 Thomas Thrainer
    """
388 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
389 13f6af81 Thomas Thrainer
    return (nl, nl)
390 13f6af81 Thomas Thrainer
391 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
392 13f6af81 Thomas Thrainer
    """Check prerequisites.
393 13f6af81 Thomas Thrainer

394 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
395 13f6af81 Thomas Thrainer

396 13f6af81 Thomas Thrainer
    """
397 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
398 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
399 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
400 d0d7d7cf Thomas Thrainer
    CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
401 d0d7d7cf Thomas Thrainer
    CheckNodeOnline(self, self.instance.primary_node)
402 13f6af81 Thomas Thrainer
403 13f6af81 Thomas Thrainer
    # check bridges existence
404 d0d7d7cf Thomas Thrainer
    CheckInstanceBridgesExist(self, self.instance)
405 13f6af81 Thomas Thrainer
406 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
407 13f6af81 Thomas Thrainer
    """Reboot the instance.
408 13f6af81 Thomas Thrainer

409 13f6af81 Thomas Thrainer
    """
410 0bbec3af Helga Velroyen
    cluster = self.cfg.GetClusterInfo()
411 0bbec3af Helga Velroyen
    remote_info = self.rpc.call_instance_info(
412 d0d7d7cf Thomas Thrainer
        self.instance.primary_node, self.instance.name,
413 d0d7d7cf Thomas Thrainer
        self.instance.hypervisor, cluster.hvparams[self.instance.hypervisor])
414 1c3231aa Thomas Thrainer
    remote_info.Raise("Error checking node %s" %
415 d0d7d7cf Thomas Thrainer
                      self.cfg.GetNodeName(self.instance.primary_node))
416 13f6af81 Thomas Thrainer
    instance_running = bool(remote_info.payload)
417 13f6af81 Thomas Thrainer
418 d0d7d7cf Thomas Thrainer
    current_node_uuid = self.instance.primary_node
419 13f6af81 Thomas Thrainer
420 d0d7d7cf Thomas Thrainer
    if instance_running and \
421 d0d7d7cf Thomas Thrainer
        self.op.reboot_type in [constants.INSTANCE_REBOOT_SOFT,
422 d0d7d7cf Thomas Thrainer
                                constants.INSTANCE_REBOOT_HARD]:
423 d0d7d7cf Thomas Thrainer
      result = self.rpc.call_instance_reboot(current_node_uuid, self.instance,
424 d0d7d7cf Thomas Thrainer
                                             self.op.reboot_type,
425 d0d7d7cf Thomas Thrainer
                                             self.op.shutdown_timeout,
426 d0d7d7cf Thomas Thrainer
                                             self.op.reason)
427 13f6af81 Thomas Thrainer
      result.Raise("Could not reboot instance")
428 13f6af81 Thomas Thrainer
    else:
429 13f6af81 Thomas Thrainer
      if instance_running:
430 d0d7d7cf Thomas Thrainer
        result = self.rpc.call_instance_shutdown(current_node_uuid,
431 d0d7d7cf Thomas Thrainer
                                                 self.instance,
432 13f6af81 Thomas Thrainer
                                                 self.op.shutdown_timeout,
433 d0d7d7cf Thomas Thrainer
                                                 self.op.reason)
434 13f6af81 Thomas Thrainer
        result.Raise("Could not shutdown instance for full reboot")
435 d0d7d7cf Thomas Thrainer
        ShutdownInstanceDisks(self, self.instance)
436 13f6af81 Thomas Thrainer
      else:
437 13f6af81 Thomas Thrainer
        self.LogInfo("Instance %s was already stopped, starting now",
438 d0d7d7cf Thomas Thrainer
                     self.instance.name)
439 d0d7d7cf Thomas Thrainer
      StartInstanceDisks(self, self.instance, self.op.ignore_secondaries)
440 1c3231aa Thomas Thrainer
      result = self.rpc.call_instance_start(current_node_uuid,
441 d0d7d7cf Thomas Thrainer
                                            (self.instance, None, None), False,
442 d0d7d7cf Thomas Thrainer
                                            self.op.reason)
443 13f6af81 Thomas Thrainer
      msg = result.fail_msg
444 13f6af81 Thomas Thrainer
      if msg:
445 d0d7d7cf Thomas Thrainer
        ShutdownInstanceDisks(self, self.instance)
446 13f6af81 Thomas Thrainer
        raise errors.OpExecError("Could not start instance for"
447 13f6af81 Thomas Thrainer
                                 " full reboot: %s" % msg)
448 13f6af81 Thomas Thrainer
449 da4a52a3 Thomas Thrainer
    self.cfg.MarkInstanceUp(self.instance.uuid)
450 13f6af81 Thomas Thrainer
451 13f6af81 Thomas Thrainer
452 c42be2c0 Petr Pudlak
def GetInstanceConsole(cluster, instance, primary_node, node_group):
453 13f6af81 Thomas Thrainer
  """Returns console information for an instance.
454 13f6af81 Thomas Thrainer

455 13f6af81 Thomas Thrainer
  @type cluster: L{objects.Cluster}
456 13f6af81 Thomas Thrainer
  @type instance: L{objects.Instance}
457 1c3231aa Thomas Thrainer
  @type primary_node: L{objects.Node}
458 c42be2c0 Petr Pudlak
  @type node_group: L{objects.NodeGroup}
459 13f6af81 Thomas Thrainer
  @rtype: dict
460 13f6af81 Thomas Thrainer

461 13f6af81 Thomas Thrainer
  """
462 f92d9674 Helga Velroyen
  hyper = hypervisor.GetHypervisorClass(instance.hypervisor)
463 13f6af81 Thomas Thrainer
  # beparams and hvparams are passed separately, to avoid editing the
464 13f6af81 Thomas Thrainer
  # instance and then saving the defaults in the instance itself.
465 13f6af81 Thomas Thrainer
  hvparams = cluster.FillHV(instance)
466 13f6af81 Thomas Thrainer
  beparams = cluster.FillBE(instance)
467 c42be2c0 Petr Pudlak
  console = hyper.GetInstanceConsole(instance, primary_node, node_group,
468 c42be2c0 Petr Pudlak
                                     hvparams, beparams)
469 13f6af81 Thomas Thrainer
470 13f6af81 Thomas Thrainer
  assert console.instance == instance.name
471 13f6af81 Thomas Thrainer
  assert console.Validate()
472 13f6af81 Thomas Thrainer
473 13f6af81 Thomas Thrainer
  return console.ToDict()
474 13f6af81 Thomas Thrainer
475 13f6af81 Thomas Thrainer
476 13f6af81 Thomas Thrainer
class LUInstanceConsole(NoHooksLU):
477 13f6af81 Thomas Thrainer
  """Connect to an instance's console.
478 13f6af81 Thomas Thrainer

479 13f6af81 Thomas Thrainer
  This is somewhat special in that it returns the command line that
480 13f6af81 Thomas Thrainer
  you need to run on the master node in order to connect to the
481 13f6af81 Thomas Thrainer
  console.
482 13f6af81 Thomas Thrainer

483 13f6af81 Thomas Thrainer
  """
484 13f6af81 Thomas Thrainer
  REQ_BGL = False
485 13f6af81 Thomas Thrainer
486 13f6af81 Thomas Thrainer
  def ExpandNames(self):
487 5eacbcae Thomas Thrainer
    self.share_locks = ShareAll()
488 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
489 13f6af81 Thomas Thrainer
490 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
491 13f6af81 Thomas Thrainer
    """Check prerequisites.
492 13f6af81 Thomas Thrainer

493 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
494 13f6af81 Thomas Thrainer

495 13f6af81 Thomas Thrainer
    """
496 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
497 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
498 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
499 5eacbcae Thomas Thrainer
    CheckNodeOnline(self, self.instance.primary_node)
500 13f6af81 Thomas Thrainer
501 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
502 13f6af81 Thomas Thrainer
    """Connect to the console of an instance
503 13f6af81 Thomas Thrainer

504 13f6af81 Thomas Thrainer
    """
505 d0d7d7cf Thomas Thrainer
    node_uuid = self.instance.primary_node
506 13f6af81 Thomas Thrainer
507 8ac806e6 Helga Velroyen
    cluster_hvparams = self.cfg.GetClusterInfo().hvparams
508 d0d7d7cf Thomas Thrainer
    node_insts = self.rpc.call_instance_list(
509 d0d7d7cf Thomas Thrainer
                   [node_uuid], [self.instance.hypervisor],
510 d0d7d7cf Thomas Thrainer
                   cluster_hvparams)[node_uuid]
511 1c3231aa Thomas Thrainer
    node_insts.Raise("Can't get node information from %s" %
512 1c3231aa Thomas Thrainer
                     self.cfg.GetNodeName(node_uuid))
513 13f6af81 Thomas Thrainer
514 d0d7d7cf Thomas Thrainer
    if self.instance.name not in node_insts.payload:
515 d0d7d7cf Thomas Thrainer
      if self.instance.admin_state == constants.ADMINST_UP:
516 13f6af81 Thomas Thrainer
        state = constants.INSTST_ERRORDOWN
517 d0d7d7cf Thomas Thrainer
      elif self.instance.admin_state == constants.ADMINST_DOWN:
518 13f6af81 Thomas Thrainer
        state = constants.INSTST_ADMINDOWN
519 13f6af81 Thomas Thrainer
      else:
520 13f6af81 Thomas Thrainer
        state = constants.INSTST_ADMINOFFLINE
521 13f6af81 Thomas Thrainer
      raise errors.OpExecError("Instance %s is not running (state %s)" %
522 d0d7d7cf Thomas Thrainer
                               (self.instance.name, state))
523 13f6af81 Thomas Thrainer
524 d0d7d7cf Thomas Thrainer
    logging.debug("Connecting to console of %s on %s", self.instance.name,
525 1c3231aa Thomas Thrainer
                  self.cfg.GetNodeName(node_uuid))
526 13f6af81 Thomas Thrainer
527 c42be2c0 Petr Pudlak
    node = self.cfg.GetNodeInfo(self.instance.primary_node)
528 c42be2c0 Petr Pudlak
    group = self.cfg.GetNodeGroup(node.group)
529 c42be2c0 Petr Pudlak
    return GetInstanceConsole(self.cfg.GetClusterInfo(),
530 c42be2c0 Petr Pudlak
                              self.instance, node, group)