Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_operation.py @ 18397489

History | View | Annotate | Download (16.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 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 13f6af81 Thomas Thrainer
    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 d0d7d7cf Thomas Thrainer
      result = self.rpc.call_instance_shutdown(self.instance.primary_node,
234 d0d7d7cf Thomas Thrainer
                                               self.instance,
235 d0d7d7cf Thomas Thrainer
                                               self.op.timeout, self.op.reason)
236 13f6af81 Thomas Thrainer
      msg = result.fail_msg
237 13f6af81 Thomas Thrainer
      if msg:
238 13f6af81 Thomas Thrainer
        self.LogWarning("Could not shutdown instance: %s", msg)
239 13f6af81 Thomas Thrainer
240 d0d7d7cf Thomas Thrainer
      ShutdownInstanceDisks(self, self.instance)
241 13f6af81 Thomas Thrainer
242 13f6af81 Thomas Thrainer
243 13f6af81 Thomas Thrainer
class LUInstanceReinstall(LogicalUnit):
244 13f6af81 Thomas Thrainer
  """Reinstall an instance.
245 13f6af81 Thomas Thrainer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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