Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_operation.py @ 896cc964

History | View | Annotate | Download (16.1 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 13f6af81 Thomas Thrainer
46 13f6af81 Thomas Thrainer
47 13f6af81 Thomas Thrainer
class LUInstanceStartup(LogicalUnit):
48 13f6af81 Thomas Thrainer
  """Starts an instance.
49 13f6af81 Thomas Thrainer

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

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

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

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

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

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

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

172 13f6af81 Thomas Thrainer
  """
173 13f6af81 Thomas Thrainer
  HPATH = "instance-stop"
174 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
175 13f6af81 Thomas Thrainer
  REQ_BGL = False
176 13f6af81 Thomas Thrainer
177 13f6af81 Thomas Thrainer
  def ExpandNames(self):
178 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
179 13f6af81 Thomas Thrainer
180 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
181 13f6af81 Thomas Thrainer
    """Build hooks env.
182 13f6af81 Thomas Thrainer

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

185 13f6af81 Thomas Thrainer
    """
186 5eacbcae Thomas Thrainer
    env = BuildInstanceHookEnvByObject(self, self.instance)
187 5cbf7832 Jose A. Lopes
    env["TIMEOUT"] = self.op.timeout
188 13f6af81 Thomas Thrainer
    return env
189 13f6af81 Thomas Thrainer
190 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
191 13f6af81 Thomas Thrainer
    """Build hooks nodes.
192 13f6af81 Thomas Thrainer

193 13f6af81 Thomas Thrainer
    """
194 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
195 13f6af81 Thomas Thrainer
    return (nl, nl)
196 13f6af81 Thomas Thrainer
197 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
198 13f6af81 Thomas Thrainer
    """Check prerequisites.
199 13f6af81 Thomas Thrainer

200 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
201 13f6af81 Thomas Thrainer

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

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

247 13f6af81 Thomas Thrainer
  """
248 13f6af81 Thomas Thrainer
  HPATH = "instance-reinstall"
249 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
250 13f6af81 Thomas Thrainer
  REQ_BGL = False
251 13f6af81 Thomas Thrainer
252 13f6af81 Thomas Thrainer
  def ExpandNames(self):
253 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
254 13f6af81 Thomas Thrainer
255 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
256 13f6af81 Thomas Thrainer
    """Build hooks env.
257 13f6af81 Thomas Thrainer

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

260 13f6af81 Thomas Thrainer
    """
261 5eacbcae Thomas Thrainer
    return BuildInstanceHookEnvByObject(self, self.instance)
262 13f6af81 Thomas Thrainer
263 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
264 13f6af81 Thomas Thrainer
    """Build hooks nodes.
265 13f6af81 Thomas Thrainer

266 13f6af81 Thomas Thrainer
    """
267 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
268 13f6af81 Thomas Thrainer
    return (nl, nl)
269 13f6af81 Thomas Thrainer
270 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
271 13f6af81 Thomas Thrainer
    """Check prerequisites.
272 13f6af81 Thomas Thrainer

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

275 13f6af81 Thomas Thrainer
    """
276 da4a52a3 Thomas Thrainer
    instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
277 13f6af81 Thomas Thrainer
    assert instance is not None, \
278 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
279 5eacbcae Thomas Thrainer
    CheckNodeOnline(self, instance.primary_node, "Instance primary node"
280 5eacbcae Thomas Thrainer
                    " offline, cannot reinstall")
281 13f6af81 Thomas Thrainer
282 13f6af81 Thomas Thrainer
    if instance.disk_template == constants.DT_DISKLESS:
283 13f6af81 Thomas Thrainer
      raise errors.OpPrereqError("Instance '%s' has no disks" %
284 13f6af81 Thomas Thrainer
                                 self.op.instance_name,
285 13f6af81 Thomas Thrainer
                                 errors.ECODE_INVAL)
286 5eacbcae Thomas Thrainer
    CheckInstanceState(self, instance, INSTANCE_DOWN, msg="cannot reinstall")
287 13f6af81 Thomas Thrainer
288 13f6af81 Thomas Thrainer
    if self.op.os_type is not None:
289 13f6af81 Thomas Thrainer
      # OS verification
290 1c3231aa Thomas Thrainer
      CheckNodeHasOS(self, instance.primary_node, self.op.os_type,
291 1c3231aa Thomas Thrainer
                     self.op.force_variant)
292 13f6af81 Thomas Thrainer
      instance_os = self.op.os_type
293 13f6af81 Thomas Thrainer
    else:
294 13f6af81 Thomas Thrainer
      instance_os = instance.os
295 13f6af81 Thomas Thrainer
296 1c3231aa Thomas Thrainer
    node_uuids = list(instance.all_nodes)
297 13f6af81 Thomas Thrainer
298 13f6af81 Thomas Thrainer
    if self.op.osparams:
299 5eacbcae Thomas Thrainer
      i_osdict = GetUpdatedParams(instance.osparams, self.op.osparams)
300 1c3231aa Thomas Thrainer
      CheckOSParams(self, True, node_uuids, instance_os, i_osdict)
301 13f6af81 Thomas Thrainer
      self.os_inst = i_osdict # the new dict (without defaults)
302 13f6af81 Thomas Thrainer
    else:
303 13f6af81 Thomas Thrainer
      self.os_inst = None
304 13f6af81 Thomas Thrainer
305 13f6af81 Thomas Thrainer
    self.instance = instance
306 13f6af81 Thomas Thrainer
307 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
308 13f6af81 Thomas Thrainer
    """Reinstall the instance.
309 13f6af81 Thomas Thrainer

310 13f6af81 Thomas Thrainer
    """
311 13f6af81 Thomas Thrainer
    if self.op.os_type is not None:
312 13f6af81 Thomas Thrainer
      feedback_fn("Changing OS to '%s'..." % self.op.os_type)
313 d0d7d7cf Thomas Thrainer
      self.instance.os = self.op.os_type
314 13f6af81 Thomas Thrainer
      # Write to configuration
315 d0d7d7cf Thomas Thrainer
      self.cfg.Update(self.instance, feedback_fn)
316 13f6af81 Thomas Thrainer
317 d0d7d7cf Thomas Thrainer
    StartInstanceDisks(self, self.instance, None)
318 13f6af81 Thomas Thrainer
    try:
319 13f6af81 Thomas Thrainer
      feedback_fn("Running the instance OS create scripts...")
320 13f6af81 Thomas Thrainer
      # FIXME: pass debug option from opcode to backend
321 d0d7d7cf Thomas Thrainer
      result = self.rpc.call_instance_os_add(self.instance.primary_node,
322 d0d7d7cf Thomas Thrainer
                                             (self.instance, self.os_inst),
323 d0d7d7cf Thomas Thrainer
                                             True, self.op.debug_level)
324 13f6af81 Thomas Thrainer
      result.Raise("Could not install OS for instance %s on node %s" %
325 d0d7d7cf Thomas Thrainer
                   (self.instance.name,
326 d0d7d7cf Thomas Thrainer
                    self.cfg.GetNodeName(self.instance.primary_node)))
327 13f6af81 Thomas Thrainer
    finally:
328 d0d7d7cf Thomas Thrainer
      ShutdownInstanceDisks(self, self.instance)
329 13f6af81 Thomas Thrainer
330 13f6af81 Thomas Thrainer
331 13f6af81 Thomas Thrainer
class LUInstanceReboot(LogicalUnit):
332 13f6af81 Thomas Thrainer
  """Reboot an instance.
333 13f6af81 Thomas Thrainer

334 13f6af81 Thomas Thrainer
  """
335 13f6af81 Thomas Thrainer
  HPATH = "instance-reboot"
336 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
337 13f6af81 Thomas Thrainer
  REQ_BGL = False
338 13f6af81 Thomas Thrainer
339 13f6af81 Thomas Thrainer
  def ExpandNames(self):
340 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
341 13f6af81 Thomas Thrainer
342 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
343 13f6af81 Thomas Thrainer
    """Build hooks env.
344 13f6af81 Thomas Thrainer

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

347 13f6af81 Thomas Thrainer
    """
348 13f6af81 Thomas Thrainer
    env = {
349 13f6af81 Thomas Thrainer
      "IGNORE_SECONDARIES": self.op.ignore_secondaries,
350 13f6af81 Thomas Thrainer
      "REBOOT_TYPE": self.op.reboot_type,
351 13f6af81 Thomas Thrainer
      "SHUTDOWN_TIMEOUT": self.op.shutdown_timeout,
352 13f6af81 Thomas Thrainer
      }
353 13f6af81 Thomas Thrainer
354 5eacbcae Thomas Thrainer
    env.update(BuildInstanceHookEnvByObject(self, self.instance))
355 13f6af81 Thomas Thrainer
356 13f6af81 Thomas Thrainer
    return env
357 13f6af81 Thomas Thrainer
358 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
359 13f6af81 Thomas Thrainer
    """Build hooks nodes.
360 13f6af81 Thomas Thrainer

361 13f6af81 Thomas Thrainer
    """
362 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
363 13f6af81 Thomas Thrainer
    return (nl, nl)
364 13f6af81 Thomas Thrainer
365 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
366 13f6af81 Thomas Thrainer
    """Check prerequisites.
367 13f6af81 Thomas Thrainer

368 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
369 13f6af81 Thomas Thrainer

370 13f6af81 Thomas Thrainer
    """
371 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
372 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
373 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
374 d0d7d7cf Thomas Thrainer
    CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
375 d0d7d7cf Thomas Thrainer
    CheckNodeOnline(self, self.instance.primary_node)
376 13f6af81 Thomas Thrainer
377 13f6af81 Thomas Thrainer
    # check bridges existence
378 d0d7d7cf Thomas Thrainer
    CheckInstanceBridgesExist(self, self.instance)
379 13f6af81 Thomas Thrainer
380 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
381 13f6af81 Thomas Thrainer
    """Reboot the instance.
382 13f6af81 Thomas Thrainer

383 13f6af81 Thomas Thrainer
    """
384 0bbec3af Helga Velroyen
    cluster = self.cfg.GetClusterInfo()
385 0bbec3af Helga Velroyen
    remote_info = self.rpc.call_instance_info(
386 d0d7d7cf Thomas Thrainer
        self.instance.primary_node, self.instance.name,
387 d0d7d7cf Thomas Thrainer
        self.instance.hypervisor, cluster.hvparams[self.instance.hypervisor])
388 1c3231aa Thomas Thrainer
    remote_info.Raise("Error checking node %s" %
389 d0d7d7cf Thomas Thrainer
                      self.cfg.GetNodeName(self.instance.primary_node))
390 13f6af81 Thomas Thrainer
    instance_running = bool(remote_info.payload)
391 13f6af81 Thomas Thrainer
392 d0d7d7cf Thomas Thrainer
    current_node_uuid = self.instance.primary_node
393 13f6af81 Thomas Thrainer
394 d0d7d7cf Thomas Thrainer
    if instance_running and \
395 d0d7d7cf Thomas Thrainer
        self.op.reboot_type in [constants.INSTANCE_REBOOT_SOFT,
396 d0d7d7cf Thomas Thrainer
                                constants.INSTANCE_REBOOT_HARD]:
397 d0d7d7cf Thomas Thrainer
      result = self.rpc.call_instance_reboot(current_node_uuid, self.instance,
398 d0d7d7cf Thomas Thrainer
                                             self.op.reboot_type,
399 d0d7d7cf Thomas Thrainer
                                             self.op.shutdown_timeout,
400 d0d7d7cf Thomas Thrainer
                                             self.op.reason)
401 13f6af81 Thomas Thrainer
      result.Raise("Could not reboot instance")
402 13f6af81 Thomas Thrainer
    else:
403 13f6af81 Thomas Thrainer
      if instance_running:
404 d0d7d7cf Thomas Thrainer
        result = self.rpc.call_instance_shutdown(current_node_uuid,
405 d0d7d7cf Thomas Thrainer
                                                 self.instance,
406 13f6af81 Thomas Thrainer
                                                 self.op.shutdown_timeout,
407 d0d7d7cf Thomas Thrainer
                                                 self.op.reason)
408 13f6af81 Thomas Thrainer
        result.Raise("Could not shutdown instance for full reboot")
409 d0d7d7cf Thomas Thrainer
        ShutdownInstanceDisks(self, self.instance)
410 13f6af81 Thomas Thrainer
      else:
411 13f6af81 Thomas Thrainer
        self.LogInfo("Instance %s was already stopped, starting now",
412 d0d7d7cf Thomas Thrainer
                     self.instance.name)
413 d0d7d7cf Thomas Thrainer
      StartInstanceDisks(self, self.instance, self.op.ignore_secondaries)
414 1c3231aa Thomas Thrainer
      result = self.rpc.call_instance_start(current_node_uuid,
415 d0d7d7cf Thomas Thrainer
                                            (self.instance, None, None), False,
416 d0d7d7cf Thomas Thrainer
                                            self.op.reason)
417 13f6af81 Thomas Thrainer
      msg = result.fail_msg
418 13f6af81 Thomas Thrainer
      if msg:
419 d0d7d7cf Thomas Thrainer
        ShutdownInstanceDisks(self, self.instance)
420 13f6af81 Thomas Thrainer
        raise errors.OpExecError("Could not start instance for"
421 13f6af81 Thomas Thrainer
                                 " full reboot: %s" % msg)
422 13f6af81 Thomas Thrainer
423 da4a52a3 Thomas Thrainer
    self.cfg.MarkInstanceUp(self.instance.uuid)
424 13f6af81 Thomas Thrainer
425 13f6af81 Thomas Thrainer
426 1c3231aa Thomas Thrainer
def GetInstanceConsole(cluster, instance, primary_node):
427 13f6af81 Thomas Thrainer
  """Returns console information for an instance.
428 13f6af81 Thomas Thrainer

429 13f6af81 Thomas Thrainer
  @type cluster: L{objects.Cluster}
430 13f6af81 Thomas Thrainer
  @type instance: L{objects.Instance}
431 1c3231aa Thomas Thrainer
  @type primary_node: L{objects.Node}
432 13f6af81 Thomas Thrainer
  @rtype: dict
433 13f6af81 Thomas Thrainer

434 13f6af81 Thomas Thrainer
  """
435 8ef418bb Helga Velroyen
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
436 13f6af81 Thomas Thrainer
  # beparams and hvparams are passed separately, to avoid editing the
437 13f6af81 Thomas Thrainer
  # instance and then saving the defaults in the instance itself.
438 13f6af81 Thomas Thrainer
  hvparams = cluster.FillHV(instance)
439 13f6af81 Thomas Thrainer
  beparams = cluster.FillBE(instance)
440 1c3231aa Thomas Thrainer
  console = hyper.GetInstanceConsole(instance, primary_node, hvparams, beparams)
441 13f6af81 Thomas Thrainer
442 13f6af81 Thomas Thrainer
  assert console.instance == instance.name
443 13f6af81 Thomas Thrainer
  assert console.Validate()
444 13f6af81 Thomas Thrainer
445 13f6af81 Thomas Thrainer
  return console.ToDict()
446 13f6af81 Thomas Thrainer
447 13f6af81 Thomas Thrainer
448 13f6af81 Thomas Thrainer
class LUInstanceConsole(NoHooksLU):
449 13f6af81 Thomas Thrainer
  """Connect to an instance's console.
450 13f6af81 Thomas Thrainer

451 13f6af81 Thomas Thrainer
  This is somewhat special in that it returns the command line that
452 13f6af81 Thomas Thrainer
  you need to run on the master node in order to connect to the
453 13f6af81 Thomas Thrainer
  console.
454 13f6af81 Thomas Thrainer

455 13f6af81 Thomas Thrainer
  """
456 13f6af81 Thomas Thrainer
  REQ_BGL = False
457 13f6af81 Thomas Thrainer
458 13f6af81 Thomas Thrainer
  def ExpandNames(self):
459 5eacbcae Thomas Thrainer
    self.share_locks = ShareAll()
460 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
461 13f6af81 Thomas Thrainer
462 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
463 13f6af81 Thomas Thrainer
    """Check prerequisites.
464 13f6af81 Thomas Thrainer

465 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
466 13f6af81 Thomas Thrainer

467 13f6af81 Thomas Thrainer
    """
468 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
469 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
470 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
471 5eacbcae Thomas Thrainer
    CheckNodeOnline(self, self.instance.primary_node)
472 13f6af81 Thomas Thrainer
473 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
474 13f6af81 Thomas Thrainer
    """Connect to the console of an instance
475 13f6af81 Thomas Thrainer

476 13f6af81 Thomas Thrainer
    """
477 d0d7d7cf Thomas Thrainer
    node_uuid = self.instance.primary_node
478 13f6af81 Thomas Thrainer
479 8ac806e6 Helga Velroyen
    cluster_hvparams = self.cfg.GetClusterInfo().hvparams
480 d0d7d7cf Thomas Thrainer
    node_insts = self.rpc.call_instance_list(
481 d0d7d7cf Thomas Thrainer
                   [node_uuid], [self.instance.hypervisor],
482 d0d7d7cf Thomas Thrainer
                   cluster_hvparams)[node_uuid]
483 1c3231aa Thomas Thrainer
    node_insts.Raise("Can't get node information from %s" %
484 1c3231aa Thomas Thrainer
                     self.cfg.GetNodeName(node_uuid))
485 13f6af81 Thomas Thrainer
486 d0d7d7cf Thomas Thrainer
    if self.instance.name not in node_insts.payload:
487 d0d7d7cf Thomas Thrainer
      if self.instance.admin_state == constants.ADMINST_UP:
488 13f6af81 Thomas Thrainer
        state = constants.INSTST_ERRORDOWN
489 d0d7d7cf Thomas Thrainer
      elif self.instance.admin_state == constants.ADMINST_DOWN:
490 13f6af81 Thomas Thrainer
        state = constants.INSTST_ADMINDOWN
491 13f6af81 Thomas Thrainer
      else:
492 13f6af81 Thomas Thrainer
        state = constants.INSTST_ADMINOFFLINE
493 13f6af81 Thomas Thrainer
      raise errors.OpExecError("Instance %s is not running (state %s)" %
494 d0d7d7cf Thomas Thrainer
                               (self.instance.name, state))
495 13f6af81 Thomas Thrainer
496 d0d7d7cf Thomas Thrainer
    logging.debug("Connecting to console of %s on %s", self.instance.name,
497 1c3231aa Thomas Thrainer
                  self.cfg.GetNodeName(node_uuid))
498 13f6af81 Thomas Thrainer
499 d0d7d7cf Thomas Thrainer
    return GetInstanceConsole(self.cfg.GetClusterInfo(), self.instance,
500 d0d7d7cf Thomas Thrainer
                              self.cfg.GetNodeInfo(self.instance.primary_node))