1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """Logical units dealing with instance operations (start/stop/...).
23
24 Those operations have in common that they affect the operating system in a
25 running instance directly.
26
27 """
28
29 import logging
30
31 from ganeti import constants
32 from ganeti import errors
33 from ganeti import hypervisor
34 from ganeti import locking
35 from ganeti import objects
36 from ganeti import utils
37 from ganeti.cmdlib.base import LogicalUnit, NoHooksLU
38 from ganeti.cmdlib.common import INSTANCE_ONLINE, INSTANCE_DOWN, \
39 CheckHVParams, CheckInstanceState, CheckNodeOnline, GetUpdatedParams, \
40 CheckOSParams, ShareAll
41 from ganeti.cmdlib.instance_storage import StartInstanceDisks, \
42 ShutdownInstanceDisks
43 from ganeti.cmdlib.instance_utils import BuildInstanceHookEnvByObject, \
44 CheckInstanceBridgesExist, CheckNodeFreeMemory, CheckNodeHasOS
45
46
48 """Starts an instance.
49
50 """
51 HPATH = "instance-start"
52 HTYPE = constants.HTYPE_INSTANCE
53 REQ_BGL = False
54
61
65
69
71 """Build hooks env.
72
73 This runs on master, primary and secondary nodes of the instance.
74
75 """
76 env = {
77 "FORCE": self.op.force,
78 }
79
80 env.update(BuildInstanceHookEnvByObject(self, self.instance))
81
82 return env
83
90
92 """Check prerequisites.
93
94 This checks that the instance is in the cluster.
95
96 """
97 self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
98 assert self.instance is not None, \
99 "Cannot retrieve locked instance %s" % self.op.instance_name
100
101 cluster = self.cfg.GetClusterInfo()
102
103 if self.op.hvparams:
104
105 utils.ForceDictType(self.op.hvparams, constants.HVS_PARAMETER_TYPES)
106 filled_hvp = cluster.FillHV(self.instance)
107 filled_hvp.update(self.op.hvparams)
108 hv_type = hypervisor.GetHypervisorClass(self.instance.hypervisor)
109 hv_type.CheckParameterSyntax(filled_hvp)
110 CheckHVParams(self, self.instance.all_nodes, self.instance.hypervisor,
111 filled_hvp)
112
113 CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
114
115 self.primary_offline = \
116 self.cfg.GetNodeInfo(self.instance.primary_node).offline
117
118 if self.primary_offline and self.op.ignore_offline_nodes:
119 self.LogWarning("Ignoring offline primary node")
120
121 if self.op.hvparams or self.op.beparams:
122 self.LogWarning("Overridden parameters are ignored")
123 else:
124 CheckNodeOnline(self, self.instance.primary_node)
125
126 bep = self.cfg.GetClusterInfo().FillBE(self.instance)
127 bep.update(self.op.beparams)
128
129
130 CheckInstanceBridgesExist(self, self.instance)
131
132 remote_info = self.rpc.call_instance_info(
133 self.instance.primary_node, self.instance.name,
134 self.instance.hypervisor, cluster.hvparams[self.instance.hypervisor])
135 remote_info.Raise("Error checking node %s" %
136 self.cfg.GetNodeName(self.instance.primary_node),
137 prereq=True, ecode=errors.ECODE_ENVIRON)
138 if not remote_info.payload:
139 CheckNodeFreeMemory(
140 self, self.instance.primary_node,
141 "starting instance %s" % self.instance.name,
142 bep[constants.BE_MINMEM], self.instance.hypervisor,
143 self.cfg.GetClusterInfo().hvparams[self.instance.hypervisor])
144
145 - def Exec(self, feedback_fn):
167
168
170 """Shutdown an instance.
171
172 """
173 HPATH = "instance-stop"
174 HTYPE = constants.HTYPE_INSTANCE
175 REQ_BGL = False
176
179
181 """Build hooks env.
182
183 This runs on master, primary and secondary nodes of the instance.
184
185 """
186 env = BuildInstanceHookEnvByObject(self, self.instance)
187 env["TIMEOUT"] = self.op.timeout
188 return env
189
196
198 """Check prerequisites.
199
200 This checks that the instance is in the cluster.
201
202 """
203 self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
204 assert self.instance is not None, \
205 "Cannot retrieve locked instance %s" % self.op.instance_name
206
207 if not self.op.force:
208 CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
209 else:
210 self.LogWarning("Ignoring offline instance check")
211
212 self.primary_offline = \
213 self.cfg.GetNodeInfo(self.instance.primary_node).offline
214
215 if self.primary_offline and self.op.ignore_offline_nodes:
216 self.LogWarning("Ignoring offline primary node")
217 else:
218 CheckNodeOnline(self, self.instance.primary_node)
219
220 - def Exec(self, feedback_fn):
241
242
244 """Reinstall an instance.
245
246 """
247 HPATH = "instance-reinstall"
248 HTYPE = constants.HTYPE_INSTANCE
249 REQ_BGL = False
250
253
261
268
270 """Check prerequisites.
271
272 This checks that the instance is in the cluster and is not running.
273
274 """
275 instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
276 assert instance is not None, \
277 "Cannot retrieve locked instance %s" % self.op.instance_name
278 CheckNodeOnline(self, instance.primary_node, "Instance primary node"
279 " offline, cannot reinstall")
280
281 if instance.disk_template == constants.DT_DISKLESS:
282 raise errors.OpPrereqError("Instance '%s' has no disks" %
283 self.op.instance_name,
284 errors.ECODE_INVAL)
285 CheckInstanceState(self, instance, INSTANCE_DOWN, msg="cannot reinstall")
286
287 if self.op.os_type is not None:
288
289 CheckNodeHasOS(self, instance.primary_node, self.op.os_type,
290 self.op.force_variant)
291 instance_os = self.op.os_type
292 else:
293 instance_os = instance.os
294
295 node_uuids = list(instance.all_nodes)
296
297 if self.op.osparams:
298 i_osdict = GetUpdatedParams(instance.osparams, self.op.osparams)
299 CheckOSParams(self, True, node_uuids, instance_os, i_osdict)
300 self.os_inst = i_osdict
301 else:
302 self.os_inst = None
303
304 self.instance = instance
305
306 - def Exec(self, feedback_fn):
328
329
331 """Reboot an instance.
332
333 """
334 HPATH = "instance-reboot"
335 HTYPE = constants.HTYPE_INSTANCE
336 REQ_BGL = False
337
340
342 """Build hooks env.
343
344 This runs on master, primary and secondary nodes of the instance.
345
346 """
347 env = {
348 "IGNORE_SECONDARIES": self.op.ignore_secondaries,
349 "REBOOT_TYPE": self.op.reboot_type,
350 "SHUTDOWN_TIMEOUT": self.op.shutdown_timeout,
351 }
352
353 env.update(BuildInstanceHookEnvByObject(self, self.instance))
354
355 return env
356
363
378
379 - def Exec(self, feedback_fn):
380 """Reboot the instance.
381
382 """
383 cluster = self.cfg.GetClusterInfo()
384 remote_info = self.rpc.call_instance_info(
385 self.instance.primary_node, self.instance.name,
386 self.instance.hypervisor, cluster.hvparams[self.instance.hypervisor])
387 remote_info.Raise("Error checking node %s" %
388 self.cfg.GetNodeName(self.instance.primary_node))
389 instance_running = bool(remote_info.payload)
390
391 current_node_uuid = self.instance.primary_node
392
393 if instance_running and \
394 self.op.reboot_type in [constants.INSTANCE_REBOOT_SOFT,
395 constants.INSTANCE_REBOOT_HARD]:
396 for disk in self.instance.disks:
397 self.cfg.SetDiskID(disk, current_node_uuid)
398 result = self.rpc.call_instance_reboot(current_node_uuid, self.instance,
399 self.op.reboot_type,
400 self.op.shutdown_timeout,
401 self.op.reason)
402 result.Raise("Could not reboot instance")
403 else:
404 if instance_running:
405 result = self.rpc.call_instance_shutdown(current_node_uuid,
406 self.instance,
407 self.op.shutdown_timeout,
408 self.op.reason)
409 result.Raise("Could not shutdown instance for full reboot")
410 ShutdownInstanceDisks(self, self.instance)
411 else:
412 self.LogInfo("Instance %s was already stopped, starting now",
413 self.instance.name)
414 StartInstanceDisks(self, self.instance, self.op.ignore_secondaries)
415 result = self.rpc.call_instance_start(current_node_uuid,
416 (self.instance, None, None), False,
417 self.op.reason)
418 msg = result.fail_msg
419 if msg:
420 ShutdownInstanceDisks(self, self.instance)
421 raise errors.OpExecError("Could not start instance for"
422 " full reboot: %s" % msg)
423
424 self.cfg.MarkInstanceUp(self.instance.uuid)
425
426
447
448
450 """Connect to an instance's console.
451
452 This is somewhat special in that it returns the command line that
453 you need to run on the master node in order to connect to the
454 console.
455
456 """
457 REQ_BGL = False
458
462
464 """Check prerequisites.
465
466 This checks that the instance is in the cluster.
467
468 """
469 self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
470 assert self.instance is not None, \
471 "Cannot retrieve locked instance %s" % self.op.instance_name
472 CheckNodeOnline(self, self.instance.primary_node)
473
474 - def Exec(self, feedback_fn):
502