Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_operation.py @ 2a02d6fe

History | View | Annotate | Download (16.7 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 13f6af81 Thomas Thrainer
    if self.op.os_type is not None:
296 13f6af81 Thomas Thrainer
      # OS verification
297 1c3231aa Thomas Thrainer
      CheckNodeHasOS(self, instance.primary_node, self.op.os_type,
298 1c3231aa Thomas Thrainer
                     self.op.force_variant)
299 13f6af81 Thomas Thrainer
      instance_os = self.op.os_type
300 13f6af81 Thomas Thrainer
    else:
301 13f6af81 Thomas Thrainer
      instance_os = instance.os
302 13f6af81 Thomas Thrainer
303 1c3231aa Thomas Thrainer
    node_uuids = list(instance.all_nodes)
304 13f6af81 Thomas Thrainer
305 13f6af81 Thomas Thrainer
    if self.op.osparams:
306 5eacbcae Thomas Thrainer
      i_osdict = GetUpdatedParams(instance.osparams, self.op.osparams)
307 1c3231aa Thomas Thrainer
      CheckOSParams(self, True, node_uuids, instance_os, i_osdict)
308 13f6af81 Thomas Thrainer
      self.os_inst = i_osdict # the new dict (without defaults)
309 13f6af81 Thomas Thrainer
    else:
310 13f6af81 Thomas Thrainer
      self.os_inst = None
311 13f6af81 Thomas Thrainer
312 13f6af81 Thomas Thrainer
    self.instance = instance
313 13f6af81 Thomas Thrainer
314 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
315 13f6af81 Thomas Thrainer
    """Reinstall the instance.
316 13f6af81 Thomas Thrainer

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

341 13f6af81 Thomas Thrainer
  """
342 13f6af81 Thomas Thrainer
  HPATH = "instance-reboot"
343 13f6af81 Thomas Thrainer
  HTYPE = constants.HTYPE_INSTANCE
344 13f6af81 Thomas Thrainer
  REQ_BGL = False
345 13f6af81 Thomas Thrainer
346 13f6af81 Thomas Thrainer
  def ExpandNames(self):
347 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
348 13f6af81 Thomas Thrainer
349 13f6af81 Thomas Thrainer
  def BuildHooksEnv(self):
350 13f6af81 Thomas Thrainer
    """Build hooks env.
351 13f6af81 Thomas Thrainer

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

354 13f6af81 Thomas Thrainer
    """
355 13f6af81 Thomas Thrainer
    env = {
356 13f6af81 Thomas Thrainer
      "IGNORE_SECONDARIES": self.op.ignore_secondaries,
357 13f6af81 Thomas Thrainer
      "REBOOT_TYPE": self.op.reboot_type,
358 13f6af81 Thomas Thrainer
      "SHUTDOWN_TIMEOUT": self.op.shutdown_timeout,
359 13f6af81 Thomas Thrainer
      }
360 13f6af81 Thomas Thrainer
361 5eacbcae Thomas Thrainer
    env.update(BuildInstanceHookEnvByObject(self, self.instance))
362 13f6af81 Thomas Thrainer
363 13f6af81 Thomas Thrainer
    return env
364 13f6af81 Thomas Thrainer
365 13f6af81 Thomas Thrainer
  def BuildHooksNodes(self):
366 13f6af81 Thomas Thrainer
    """Build hooks nodes.
367 13f6af81 Thomas Thrainer

368 13f6af81 Thomas Thrainer
    """
369 13f6af81 Thomas Thrainer
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
370 13f6af81 Thomas Thrainer
    return (nl, nl)
371 13f6af81 Thomas Thrainer
372 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
373 13f6af81 Thomas Thrainer
    """Check prerequisites.
374 13f6af81 Thomas Thrainer

375 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
376 13f6af81 Thomas Thrainer

377 13f6af81 Thomas Thrainer
    """
378 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
379 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
380 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
381 d0d7d7cf Thomas Thrainer
    CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
382 d0d7d7cf Thomas Thrainer
    CheckNodeOnline(self, self.instance.primary_node)
383 13f6af81 Thomas Thrainer
384 13f6af81 Thomas Thrainer
    # check bridges existence
385 d0d7d7cf Thomas Thrainer
    CheckInstanceBridgesExist(self, self.instance)
386 13f6af81 Thomas Thrainer
387 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
388 13f6af81 Thomas Thrainer
    """Reboot the instance.
389 13f6af81 Thomas Thrainer

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

436 13f6af81 Thomas Thrainer
  @type cluster: L{objects.Cluster}
437 13f6af81 Thomas Thrainer
  @type instance: L{objects.Instance}
438 1c3231aa Thomas Thrainer
  @type primary_node: L{objects.Node}
439 c42be2c0 Petr Pudlak
  @type node_group: L{objects.NodeGroup}
440 13f6af81 Thomas Thrainer
  @rtype: dict
441 13f6af81 Thomas Thrainer

442 13f6af81 Thomas Thrainer
  """
443 f92d9674 Helga Velroyen
  hyper = hypervisor.GetHypervisorClass(instance.hypervisor)
444 13f6af81 Thomas Thrainer
  # beparams and hvparams are passed separately, to avoid editing the
445 13f6af81 Thomas Thrainer
  # instance and then saving the defaults in the instance itself.
446 13f6af81 Thomas Thrainer
  hvparams = cluster.FillHV(instance)
447 13f6af81 Thomas Thrainer
  beparams = cluster.FillBE(instance)
448 c42be2c0 Petr Pudlak
  console = hyper.GetInstanceConsole(instance, primary_node, node_group,
449 c42be2c0 Petr Pudlak
                                     hvparams, beparams)
450 13f6af81 Thomas Thrainer
451 13f6af81 Thomas Thrainer
  assert console.instance == instance.name
452 13f6af81 Thomas Thrainer
  assert console.Validate()
453 13f6af81 Thomas Thrainer
454 13f6af81 Thomas Thrainer
  return console.ToDict()
455 13f6af81 Thomas Thrainer
456 13f6af81 Thomas Thrainer
457 13f6af81 Thomas Thrainer
class LUInstanceConsole(NoHooksLU):
458 13f6af81 Thomas Thrainer
  """Connect to an instance's console.
459 13f6af81 Thomas Thrainer

460 13f6af81 Thomas Thrainer
  This is somewhat special in that it returns the command line that
461 13f6af81 Thomas Thrainer
  you need to run on the master node in order to connect to the
462 13f6af81 Thomas Thrainer
  console.
463 13f6af81 Thomas Thrainer

464 13f6af81 Thomas Thrainer
  """
465 13f6af81 Thomas Thrainer
  REQ_BGL = False
466 13f6af81 Thomas Thrainer
467 13f6af81 Thomas Thrainer
  def ExpandNames(self):
468 5eacbcae Thomas Thrainer
    self.share_locks = ShareAll()
469 13f6af81 Thomas Thrainer
    self._ExpandAndLockInstance()
470 13f6af81 Thomas Thrainer
471 13f6af81 Thomas Thrainer
  def CheckPrereq(self):
472 13f6af81 Thomas Thrainer
    """Check prerequisites.
473 13f6af81 Thomas Thrainer

474 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
475 13f6af81 Thomas Thrainer

476 13f6af81 Thomas Thrainer
    """
477 da4a52a3 Thomas Thrainer
    self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
478 13f6af81 Thomas Thrainer
    assert self.instance is not None, \
479 13f6af81 Thomas Thrainer
      "Cannot retrieve locked instance %s" % self.op.instance_name
480 5eacbcae Thomas Thrainer
    CheckNodeOnline(self, self.instance.primary_node)
481 13f6af81 Thomas Thrainer
482 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
483 13f6af81 Thomas Thrainer
    """Connect to the console of an instance
484 13f6af81 Thomas Thrainer

485 13f6af81 Thomas Thrainer
    """
486 d0d7d7cf Thomas Thrainer
    node_uuid = self.instance.primary_node
487 13f6af81 Thomas Thrainer
488 8ac806e6 Helga Velroyen
    cluster_hvparams = self.cfg.GetClusterInfo().hvparams
489 d0d7d7cf Thomas Thrainer
    node_insts = self.rpc.call_instance_list(
490 d0d7d7cf Thomas Thrainer
                   [node_uuid], [self.instance.hypervisor],
491 d0d7d7cf Thomas Thrainer
                   cluster_hvparams)[node_uuid]
492 1c3231aa Thomas Thrainer
    node_insts.Raise("Can't get node information from %s" %
493 1c3231aa Thomas Thrainer
                     self.cfg.GetNodeName(node_uuid))
494 13f6af81 Thomas Thrainer
495 d0d7d7cf Thomas Thrainer
    if self.instance.name not in node_insts.payload:
496 d0d7d7cf Thomas Thrainer
      if self.instance.admin_state == constants.ADMINST_UP:
497 13f6af81 Thomas Thrainer
        state = constants.INSTST_ERRORDOWN
498 d0d7d7cf Thomas Thrainer
      elif self.instance.admin_state == constants.ADMINST_DOWN:
499 13f6af81 Thomas Thrainer
        state = constants.INSTST_ADMINDOWN
500 13f6af81 Thomas Thrainer
      else:
501 13f6af81 Thomas Thrainer
        state = constants.INSTST_ADMINOFFLINE
502 13f6af81 Thomas Thrainer
      raise errors.OpExecError("Instance %s is not running (state %s)" %
503 d0d7d7cf Thomas Thrainer
                               (self.instance.name, state))
504 13f6af81 Thomas Thrainer
505 d0d7d7cf Thomas Thrainer
    logging.debug("Connecting to console of %s on %s", self.instance.name,
506 1c3231aa Thomas Thrainer
                  self.cfg.GetNodeName(node_uuid))
507 13f6af81 Thomas Thrainer
508 c42be2c0 Petr Pudlak
    node = self.cfg.GetNodeInfo(self.instance.primary_node)
509 c42be2c0 Petr Pudlak
    group = self.cfg.GetNodeGroup(node.group)
510 c42be2c0 Petr Pudlak
    return GetInstanceConsole(self.cfg.GetClusterInfo(),
511 c42be2c0 Petr Pudlak
                              self.instance, node, group)