Statistics
| Branch: | Tag: | Revision:

root / lib / cmdlib / instance_operation.py @ 6be5f3e0

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

144 13f6af81 Thomas Thrainer
    """
145 13f6af81 Thomas Thrainer
    instance = self.instance
146 13f6af81 Thomas Thrainer
    force = self.op.force
147 13f6af81 Thomas Thrainer
    reason = self.op.reason
148 13f6af81 Thomas Thrainer
149 13f6af81 Thomas Thrainer
    if not self.op.no_remember:
150 13f6af81 Thomas Thrainer
      self.cfg.MarkInstanceUp(instance.name)
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 13f6af81 Thomas Thrainer
      node_current = instance.primary_node
157 13f6af81 Thomas Thrainer
158 5eacbcae Thomas Thrainer
      StartInstanceDisks(self, instance, force)
159 13f6af81 Thomas Thrainer
160 13f6af81 Thomas Thrainer
      result = \
161 13f6af81 Thomas Thrainer
        self.rpc.call_instance_start(node_current,
162 13f6af81 Thomas Thrainer
                                     (instance, self.op.hvparams,
163 13f6af81 Thomas Thrainer
                                      self.op.beparams),
164 13f6af81 Thomas Thrainer
                                     self.op.startup_paused, reason)
165 13f6af81 Thomas Thrainer
      msg = result.fail_msg
166 13f6af81 Thomas Thrainer
      if msg:
167 5eacbcae Thomas Thrainer
        ShutdownInstanceDisks(self, instance)
168 13f6af81 Thomas Thrainer
        raise errors.OpExecError("Could not start instance: %s" % msg)
169 13f6af81 Thomas Thrainer
170 13f6af81 Thomas Thrainer
171 13f6af81 Thomas Thrainer
class LUInstanceShutdown(LogicalUnit):
172 13f6af81 Thomas Thrainer
  """Shutdown an instance.
173 13f6af81 Thomas Thrainer

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

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

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

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

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

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

225 13f6af81 Thomas Thrainer
    """
226 13f6af81 Thomas Thrainer
    instance = self.instance
227 13f6af81 Thomas Thrainer
    node_current = instance.primary_node
228 13f6af81 Thomas Thrainer
    timeout = self.op.timeout
229 13f6af81 Thomas Thrainer
    reason = self.op.reason
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 13f6af81 Thomas Thrainer
    if not self.op.no_remember and instance.admin_state in INSTANCE_ONLINE:
234 13f6af81 Thomas Thrainer
      self.cfg.MarkInstanceDown(instance.name)
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 13f6af81 Thomas Thrainer
      result = self.rpc.call_instance_shutdown(node_current, instance, timeout,
241 13f6af81 Thomas Thrainer
                                               reason)
242 13f6af81 Thomas Thrainer
      msg = result.fail_msg
243 13f6af81 Thomas Thrainer
      if msg:
244 13f6af81 Thomas Thrainer
        self.LogWarning("Could not shutdown instance: %s", msg)
245 13f6af81 Thomas Thrainer
246 5eacbcae Thomas Thrainer
      ShutdownInstanceDisks(self, instance)
247 13f6af81 Thomas Thrainer
248 13f6af81 Thomas Thrainer
249 13f6af81 Thomas Thrainer
class LUInstanceReinstall(LogicalUnit):
250 13f6af81 Thomas Thrainer
  """Reinstall an instance.
251 13f6af81 Thomas Thrainer

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

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

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

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

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

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

315 13f6af81 Thomas Thrainer
    """
316 13f6af81 Thomas Thrainer
    inst = self.instance
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 13f6af81 Thomas Thrainer
      inst.os = self.op.os_type
321 13f6af81 Thomas Thrainer
      # Write to configuration
322 13f6af81 Thomas Thrainer
      self.cfg.Update(inst, feedback_fn)
323 13f6af81 Thomas Thrainer
324 5eacbcae Thomas Thrainer
    StartInstanceDisks(self, inst, 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 13f6af81 Thomas Thrainer
      result = self.rpc.call_instance_os_add(inst.primary_node,
329 13f6af81 Thomas Thrainer
                                             (inst, self.os_inst), True,
330 13f6af81 Thomas Thrainer
                                             self.op.debug_level)
331 13f6af81 Thomas Thrainer
      result.Raise("Could not install OS for instance %s on node %s" %
332 13f6af81 Thomas Thrainer
                   (inst.name, inst.primary_node))
333 13f6af81 Thomas Thrainer
    finally:
334 5eacbcae Thomas Thrainer
      ShutdownInstanceDisks(self, inst)
335 13f6af81 Thomas Thrainer
336 13f6af81 Thomas Thrainer
337 13f6af81 Thomas Thrainer
class LUInstanceReboot(LogicalUnit):
338 13f6af81 Thomas Thrainer
  """Reboot an instance.
339 13f6af81 Thomas Thrainer

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

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

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

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

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

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

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

437 13f6af81 Thomas Thrainer
  @type cluster: L{objects.Cluster}
438 13f6af81 Thomas Thrainer
  @type instance: L{objects.Instance}
439 13f6af81 Thomas Thrainer
  @rtype: dict
440 13f6af81 Thomas Thrainer

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

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

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

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

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

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

509 06c2fb4a Dimitris Aragiorgis
  """
510 06c2fb4a Dimitris Aragiorgis
  HPATH = "instance-snapshot"
511 06c2fb4a Dimitris Aragiorgis
  HTYPE = constants.HTYPE_INSTANCE
512 06c2fb4a Dimitris Aragiorgis
  REQ_BGL = False
513 06c2fb4a Dimitris Aragiorgis
514 06c2fb4a Dimitris Aragiorgis
  def ExpandNames(self):
515 06c2fb4a Dimitris Aragiorgis
    self._ExpandAndLockInstance()
516 06c2fb4a Dimitris Aragiorgis
517 06c2fb4a Dimitris Aragiorgis
  def BuildHooksEnv(self):
518 06c2fb4a Dimitris Aragiorgis
    """Build hooks env.
519 06c2fb4a Dimitris Aragiorgis

520 06c2fb4a Dimitris Aragiorgis
    This runs on master, primary and secondary nodes of the instance.
521 06c2fb4a Dimitris Aragiorgis

522 06c2fb4a Dimitris Aragiorgis
    """
523 06c2fb4a Dimitris Aragiorgis
    return BuildInstanceHookEnvByObject(self, self.instance)
524 06c2fb4a Dimitris Aragiorgis
525 06c2fb4a Dimitris Aragiorgis
  def BuildHooksNodes(self):
526 06c2fb4a Dimitris Aragiorgis
    """Build hooks nodes.
527 06c2fb4a Dimitris Aragiorgis

528 06c2fb4a Dimitris Aragiorgis
    """
529 06c2fb4a Dimitris Aragiorgis
    nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
530 06c2fb4a Dimitris Aragiorgis
    return (nl, nl)
531 06c2fb4a Dimitris Aragiorgis
532 06c2fb4a Dimitris Aragiorgis
  def CheckPrereq(self):
533 06c2fb4a Dimitris Aragiorgis
    """Check prerequisites.
534 06c2fb4a Dimitris Aragiorgis

535 06c2fb4a Dimitris Aragiorgis
    This checks that the instance is in the cluster and is not running.
536 06c2fb4a Dimitris Aragiorgis

537 06c2fb4a Dimitris Aragiorgis
    """
538 06c2fb4a Dimitris Aragiorgis
    instance = self.cfg.GetInstanceInfo(self.op.instance_name)
539 06c2fb4a Dimitris Aragiorgis
    assert instance is not None, \
540 06c2fb4a Dimitris Aragiorgis
      "Cannot retrieve locked instance %s" % self.op.instance_name
541 06c2fb4a Dimitris Aragiorgis
    CheckNodeOnline(self, instance.primary_node, "Instance primary node"
542 06c2fb4a Dimitris Aragiorgis
                    " offline, cannot snapshot")
543 06c2fb4a Dimitris Aragiorgis
544 06c2fb4a Dimitris Aragiorgis
    self.snapshots = []
545 06c2fb4a Dimitris Aragiorgis
    for ident, params in self.op.disks:
546 06c2fb4a Dimitris Aragiorgis
      idx, disk = GetItemFromContainer(ident, 'disk', instance.disks)
547 06c2fb4a Dimitris Aragiorgis
      snapshot_name = params.get("snapshot_name", None)
548 06c2fb4a Dimitris Aragiorgis
      if not snapshot_name:
549 06c2fb4a Dimitris Aragiorgis
        raise errors.OpPrereqError("No snapshot_name passed for disk %s", ident)
550 06c2fb4a Dimitris Aragiorgis
      self.snapshots.append((idx, disk, snapshot_name))
551 06c2fb4a Dimitris Aragiorgis
552 06c2fb4a Dimitris Aragiorgis
    self.instance = instance
553 06c2fb4a Dimitris Aragiorgis
554 06c2fb4a Dimitris Aragiorgis
  def Exec(self, feedback_fn):
555 06c2fb4a Dimitris Aragiorgis
    """Take a snapshot of the instance the instance.
556 06c2fb4a Dimitris Aragiorgis

557 06c2fb4a Dimitris Aragiorgis
    """
558 06c2fb4a Dimitris Aragiorgis
    inst = self.instance
559 06c2fb4a Dimitris Aragiorgis
    node_uuid = inst.primary_node
560 06c2fb4a Dimitris Aragiorgis
    for idx, disk, snapshot_name in self.snapshots:
561 06c2fb4a Dimitris Aragiorgis
      self.cfg.SetDiskID(disk, node_uuid)
562 06c2fb4a Dimitris Aragiorgis
      feedback_fn("Taking a snapshot of instance...")
563 06c2fb4a Dimitris Aragiorgis
      result = self.rpc.call_blockdev_snapshot(node_uuid,
564 06c2fb4a Dimitris Aragiorgis
                                               (disk, inst),
565 06c2fb4a Dimitris Aragiorgis
                                               snapshot_name)
566 06c2fb4a Dimitris Aragiorgis
      result.Raise("Could not take a snapshot for instance %s disk/%d %s"
567 06c2fb4a Dimitris Aragiorgis
                   " on node %s" % (inst, idx, disk.uuid, inst.primary_node))