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, ExpandNodeName, \
40 GetUpdatedParams, 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 = instance = self.cfg.GetInstanceInfo(self.op.instance_name)
98 assert self.instance is not None, \
99 "Cannot retrieve locked instance %s" % self.op.instance_name
100
101
102 if self.op.hvparams:
103
104 cluster = self.cfg.GetClusterInfo()
105 utils.ForceDictType(self.op.hvparams, constants.HVS_PARAMETER_TYPES)
106 filled_hvp = cluster.FillHV(instance)
107 filled_hvp.update(self.op.hvparams)
108 hv_type = hypervisor.GetHypervisorClass(instance.hypervisor)
109 hv_type.CheckParameterSyntax(filled_hvp)
110 CheckHVParams(self, instance.all_nodes, instance.hypervisor, filled_hvp)
111
112 CheckInstanceState(self, instance, INSTANCE_ONLINE)
113
114 self.primary_offline = self.cfg.GetNodeInfo(instance.primary_node).offline
115
116 if self.primary_offline and self.op.ignore_offline_nodes:
117 self.LogWarning("Ignoring offline primary node")
118
119 if self.op.hvparams or self.op.beparams:
120 self.LogWarning("Overridden parameters are ignored")
121 else:
122 CheckNodeOnline(self, instance.primary_node)
123
124 bep = self.cfg.GetClusterInfo().FillBE(instance)
125 bep.update(self.op.beparams)
126
127
128 CheckInstanceBridgesExist(self, instance)
129
130 remote_info = self.rpc.call_instance_info(instance.primary_node,
131 instance.name,
132 instance.hypervisor)
133 remote_info.Raise("Error checking node %s" % instance.primary_node,
134 prereq=True, ecode=errors.ECODE_ENVIRON)
135 if not remote_info.payload:
136 CheckNodeFreeMemory(self, instance.primary_node,
137 "starting instance %s" % instance.name,
138 bep[constants.BE_MINMEM], instance.hypervisor)
139
140 - def Exec(self, feedback_fn):
168
169
171 """Shutdown an instance.
172
173 """
174 HPATH = "instance-stop"
175 HTYPE = constants.HTYPE_INSTANCE
176 REQ_BGL = False
177
180
182 """Build hooks env.
183
184 This runs on master, primary and secondary nodes of the instance.
185
186 """
187 env = BuildInstanceHookEnvByObject(self, self.instance)
188 env["TIMEOUT"] = self.op.timeout
189 return env
190
197
199 """Check prerequisites.
200
201 This checks that the instance is in the cluster.
202
203 """
204 self.instance = self.cfg.GetInstanceInfo(self.op.instance_name)
205 assert self.instance is not None, \
206 "Cannot retrieve locked instance %s" % self.op.instance_name
207
208 if not self.op.force:
209 CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
210 else:
211 self.LogWarning("Ignoring offline instance check")
212
213 self.primary_offline = \
214 self.cfg.GetNodeInfo(self.instance.primary_node).offline
215
216 if self.primary_offline and self.op.ignore_offline_nodes:
217 self.LogWarning("Ignoring offline primary node")
218 else:
219 CheckNodeOnline(self, self.instance.primary_node)
220
221 - def Exec(self, feedback_fn):
246
247
249 """Reinstall an instance.
250
251 """
252 HPATH = "instance-reinstall"
253 HTYPE = constants.HTYPE_INSTANCE
254 REQ_BGL = False
255
258
266
273
275 """Check prerequisites.
276
277 This checks that the instance is in the cluster and is not running.
278
279 """
280 instance = self.cfg.GetInstanceInfo(self.op.instance_name)
281 assert instance is not None, \
282 "Cannot retrieve locked instance %s" % self.op.instance_name
283 CheckNodeOnline(self, instance.primary_node, "Instance primary node"
284 " offline, cannot reinstall")
285
286 if instance.disk_template == constants.DT_DISKLESS:
287 raise errors.OpPrereqError("Instance '%s' has no disks" %
288 self.op.instance_name,
289 errors.ECODE_INVAL)
290 CheckInstanceState(self, instance, INSTANCE_DOWN, msg="cannot reinstall")
291
292 if self.op.os_type is not None:
293
294 pnode = ExpandNodeName(self.cfg, instance.primary_node)
295 CheckNodeHasOS(self, pnode, self.op.os_type, self.op.force_variant)
296 instance_os = self.op.os_type
297 else:
298 instance_os = instance.os
299
300 nodelist = list(instance.all_nodes)
301
302 if self.op.osparams:
303 i_osdict = GetUpdatedParams(instance.osparams, self.op.osparams)
304 CheckOSParams(self, True, nodelist, instance_os, i_osdict)
305 self.os_inst = i_osdict
306 else:
307 self.os_inst = None
308
309 self.instance = instance
310
311 - def Exec(self, feedback_fn):
312 """Reinstall the instance.
313
314 """
315 inst = self.instance
316
317 if self.op.os_type is not None:
318 feedback_fn("Changing OS to '%s'..." % self.op.os_type)
319 inst.os = self.op.os_type
320
321 self.cfg.Update(inst, feedback_fn)
322
323 StartInstanceDisks(self, inst, None)
324 try:
325 feedback_fn("Running the instance OS create scripts...")
326
327 result = self.rpc.call_instance_os_add(inst.primary_node,
328 (inst, self.os_inst), True,
329 self.op.debug_level)
330 result.Raise("Could not install OS for instance %s on node %s" %
331 (inst.name, inst.primary_node))
332 finally:
333 ShutdownInstanceDisks(self, inst)
334
335
337 """Reboot an instance.
338
339 """
340 HPATH = "instance-reboot"
341 HTYPE = constants.HTYPE_INSTANCE
342 REQ_BGL = False
343
346
348 """Build hooks env.
349
350 This runs on master, primary and secondary nodes of the instance.
351
352 """
353 env = {
354 "IGNORE_SECONDARIES": self.op.ignore_secondaries,
355 "REBOOT_TYPE": self.op.reboot_type,
356 "SHUTDOWN_TIMEOUT": self.op.shutdown_timeout,
357 }
358
359 env.update(BuildInstanceHookEnvByObject(self, self.instance))
360
361 return env
362
369
384
385 - def Exec(self, feedback_fn):
386 """Reboot the instance.
387
388 """
389 instance = self.instance
390 ignore_secondaries = self.op.ignore_secondaries
391 reboot_type = self.op.reboot_type
392 reason = self.op.reason
393
394 remote_info = self.rpc.call_instance_info(instance.primary_node,
395 instance.name,
396 instance.hypervisor)
397 remote_info.Raise("Error checking node %s" % instance.primary_node)
398 instance_running = bool(remote_info.payload)
399
400 node_current = instance.primary_node
401
402 if instance_running and reboot_type in [constants.INSTANCE_REBOOT_SOFT,
403 constants.INSTANCE_REBOOT_HARD]:
404 for disk in instance.disks:
405 self.cfg.SetDiskID(disk, node_current)
406 result = self.rpc.call_instance_reboot(node_current, instance,
407 reboot_type,
408 self.op.shutdown_timeout, reason)
409 result.Raise("Could not reboot instance")
410 else:
411 if instance_running:
412 result = self.rpc.call_instance_shutdown(node_current, instance,
413 self.op.shutdown_timeout,
414 reason)
415 result.Raise("Could not shutdown instance for full reboot")
416 ShutdownInstanceDisks(self, instance)
417 else:
418 self.LogInfo("Instance %s was already stopped, starting now",
419 instance.name)
420 StartInstanceDisks(self, instance, ignore_secondaries)
421 result = self.rpc.call_instance_start(node_current,
422 (instance, None, None), False,
423 reason)
424 msg = result.fail_msg
425 if msg:
426 ShutdownInstanceDisks(self, instance)
427 raise errors.OpExecError("Could not start instance for"
428 " full reboot: %s" % msg)
429
430 self.cfg.MarkInstanceUp(instance.name)
431
432
452
453
455 """Connect to an instance's console.
456
457 This is somewhat special in that it returns the command line that
458 you need to run on the master node in order to connect to the
459 console.
460
461 """
462 REQ_BGL = False
463
467
469 """Check prerequisites.
470
471 This checks that the instance is in the cluster.
472
473 """
474 self.instance = self.cfg.GetInstanceInfo(self.op.instance_name)
475 assert self.instance is not None, \
476 "Cannot retrieve locked instance %s" % self.op.instance_name
477 CheckNodeOnline(self, self.instance.primary_node)
478
479 - def Exec(self, feedback_fn):
503