Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_operation.py @ b54ecf12

History | View | Annotate | Download (15.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 5eacbcae Thomas Thrainer
  CheckHVParams, CheckInstanceState, CheckNodeOnline, ExpandNodeName, \
40 5eacbcae Thomas Thrainer
  GetUpdatedParams, 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 13f6af81 Thomas Thrainer
    self.instance = instance = self.cfg.GetInstanceInfo(self.op.instance_name)
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 13f6af81 Thomas Thrainer
    # extra hvparams
102 13f6af81 Thomas Thrainer
    if self.op.hvparams:
103 13f6af81 Thomas Thrainer
      # check hypervisor parameter syntax (locally)
104 13f6af81 Thomas Thrainer
      cluster = self.cfg.GetClusterInfo()
105 13f6af81 Thomas Thrainer
      utils.ForceDictType(self.op.hvparams, constants.HVS_PARAMETER_TYPES)
106 13f6af81 Thomas Thrainer
      filled_hvp = cluster.FillHV(instance)
107 13f6af81 Thomas Thrainer
      filled_hvp.update(self.op.hvparams)
108 13f6af81 Thomas Thrainer
      hv_type = hypervisor.GetHypervisorClass(instance.hypervisor)
109 13f6af81 Thomas Thrainer
      hv_type.CheckParameterSyntax(filled_hvp)
110 5eacbcae Thomas Thrainer
      CheckHVParams(self, instance.all_nodes, instance.hypervisor, filled_hvp)
111 13f6af81 Thomas Thrainer
112 5eacbcae Thomas Thrainer
    CheckInstanceState(self, instance, INSTANCE_ONLINE)
113 13f6af81 Thomas Thrainer
114 13f6af81 Thomas Thrainer
    self.primary_offline = self.cfg.GetNodeInfo(instance.primary_node).offline
115 13f6af81 Thomas Thrainer
116 13f6af81 Thomas Thrainer
    if self.primary_offline and self.op.ignore_offline_nodes:
117 13f6af81 Thomas Thrainer
      self.LogWarning("Ignoring offline primary node")
118 13f6af81 Thomas Thrainer
119 13f6af81 Thomas Thrainer
      if self.op.hvparams or self.op.beparams:
120 13f6af81 Thomas Thrainer
        self.LogWarning("Overridden parameters are ignored")
121 13f6af81 Thomas Thrainer
    else:
122 5eacbcae Thomas Thrainer
      CheckNodeOnline(self, instance.primary_node)
123 13f6af81 Thomas Thrainer
124 13f6af81 Thomas Thrainer
      bep = self.cfg.GetClusterInfo().FillBE(instance)
125 13f6af81 Thomas Thrainer
      bep.update(self.op.beparams)
126 13f6af81 Thomas Thrainer
127 13f6af81 Thomas Thrainer
      # check bridges existence
128 5eacbcae Thomas Thrainer
      CheckInstanceBridgesExist(self, instance)
129 13f6af81 Thomas Thrainer
130 13f6af81 Thomas Thrainer
      remote_info = self.rpc.call_instance_info(instance.primary_node,
131 13f6af81 Thomas Thrainer
                                                instance.name,
132 13f6af81 Thomas Thrainer
                                                instance.hypervisor)
133 13f6af81 Thomas Thrainer
      remote_info.Raise("Error checking node %s" % instance.primary_node,
134 13f6af81 Thomas Thrainer
                        prereq=True, ecode=errors.ECODE_ENVIRON)
135 13f6af81 Thomas Thrainer
      if not remote_info.payload: # not running already
136 5eacbcae Thomas Thrainer
        CheckNodeFreeMemory(self, instance.primary_node,
137 5eacbcae Thomas Thrainer
                            "starting instance %s" % instance.name,
138 5eacbcae Thomas Thrainer
                            bep[constants.BE_MINMEM], instance.hypervisor)
139 13f6af81 Thomas Thrainer
140 13f6af81 Thomas Thrainer
  def Exec(self, feedback_fn):
141 13f6af81 Thomas Thrainer
    """Start the instance.
142 13f6af81 Thomas Thrainer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

373 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
374 13f6af81 Thomas Thrainer

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

388 13f6af81 Thomas Thrainer
    """
389 13f6af81 Thomas Thrainer
    instance = self.instance
390 13f6af81 Thomas Thrainer
    ignore_secondaries = self.op.ignore_secondaries
391 13f6af81 Thomas Thrainer
    reboot_type = self.op.reboot_type
392 13f6af81 Thomas Thrainer
    reason = self.op.reason
393 13f6af81 Thomas Thrainer
394 13f6af81 Thomas Thrainer
    remote_info = self.rpc.call_instance_info(instance.primary_node,
395 13f6af81 Thomas Thrainer
                                              instance.name,
396 13f6af81 Thomas Thrainer
                                              instance.hypervisor)
397 13f6af81 Thomas Thrainer
    remote_info.Raise("Error checking node %s" % instance.primary_node)
398 13f6af81 Thomas Thrainer
    instance_running = bool(remote_info.payload)
399 13f6af81 Thomas Thrainer
400 13f6af81 Thomas Thrainer
    node_current = instance.primary_node
401 13f6af81 Thomas Thrainer
402 13f6af81 Thomas Thrainer
    if instance_running and reboot_type in [constants.INSTANCE_REBOOT_SOFT,
403 13f6af81 Thomas Thrainer
                                            constants.INSTANCE_REBOOT_HARD]:
404 13f6af81 Thomas Thrainer
      for disk in instance.disks:
405 13f6af81 Thomas Thrainer
        self.cfg.SetDiskID(disk, node_current)
406 13f6af81 Thomas Thrainer
      result = self.rpc.call_instance_reboot(node_current, instance,
407 13f6af81 Thomas Thrainer
                                             reboot_type,
408 13f6af81 Thomas Thrainer
                                             self.op.shutdown_timeout, reason)
409 13f6af81 Thomas Thrainer
      result.Raise("Could not reboot instance")
410 13f6af81 Thomas Thrainer
    else:
411 13f6af81 Thomas Thrainer
      if instance_running:
412 13f6af81 Thomas Thrainer
        result = self.rpc.call_instance_shutdown(node_current, instance,
413 13f6af81 Thomas Thrainer
                                                 self.op.shutdown_timeout,
414 13f6af81 Thomas Thrainer
                                                 reason)
415 13f6af81 Thomas Thrainer
        result.Raise("Could not shutdown instance for full reboot")
416 5eacbcae Thomas Thrainer
        ShutdownInstanceDisks(self, instance)
417 13f6af81 Thomas Thrainer
      else:
418 13f6af81 Thomas Thrainer
        self.LogInfo("Instance %s was already stopped, starting now",
419 13f6af81 Thomas Thrainer
                     instance.name)
420 5eacbcae Thomas Thrainer
      StartInstanceDisks(self, instance, ignore_secondaries)
421 13f6af81 Thomas Thrainer
      result = self.rpc.call_instance_start(node_current,
422 13f6af81 Thomas Thrainer
                                            (instance, None, None), False,
423 13f6af81 Thomas Thrainer
                                            reason)
424 13f6af81 Thomas Thrainer
      msg = result.fail_msg
425 13f6af81 Thomas Thrainer
      if msg:
426 5eacbcae Thomas Thrainer
        ShutdownInstanceDisks(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 13f6af81 Thomas Thrainer
    self.cfg.MarkInstanceUp(instance.name)
431 13f6af81 Thomas Thrainer
432 13f6af81 Thomas Thrainer
433 5eacbcae Thomas Thrainer
def GetInstanceConsole(cluster, instance):
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 13f6af81 Thomas Thrainer
  @rtype: dict
439 13f6af81 Thomas Thrainer

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

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

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

471 13f6af81 Thomas Thrainer
    This checks that the instance is in the cluster.
472 13f6af81 Thomas Thrainer

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

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