1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 """Logical units dealing with instance operations (start/stop/...).
32
33 Those operations have in common that they affect the operating system in a
34 running instance directly.
35
36 """
37
38 import logging
39
40 from ganeti import constants
41 from ganeti import errors
42 from ganeti import hypervisor
43 from ganeti import locking
44 from ganeti import objects
45 from ganeti import utils
46 from ganeti.cmdlib.base import LogicalUnit, NoHooksLU
47 from ganeti.cmdlib.common import INSTANCE_ONLINE, INSTANCE_DOWN, \
48 CheckHVParams, CheckInstanceState, CheckNodeOnline, GetUpdatedParams, \
49 CheckOSParams, ShareAll
50 from ganeti.cmdlib.instance_storage import StartInstanceDisks, \
51 ShutdownInstanceDisks
52 from ganeti.cmdlib.instance_utils import BuildInstanceHookEnvByObject, \
53 CheckInstanceBridgesExist, CheckNodeFreeMemory, CheckNodeHasOS
54 from ganeti.hypervisor import hv_base
55
56
64
65
67 """Starts an instance.
68
69 """
70 HPATH = "instance-start"
71 HTYPE = constants.HTYPE_INSTANCE
72 REQ_BGL = False
73
80
84
88
90 """Build hooks env.
91
92 This runs on master, primary and secondary nodes of the instance.
93
94 """
95 env = {
96 "FORCE": self.op.force,
97 }
98
99 env.update(BuildInstanceHookEnvByObject(self, self.instance))
100
101 return env
102
109
111 """Check prerequisites.
112
113 This checks that the instance is in the cluster.
114
115 """
116 self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
117 assert self.instance is not None, \
118 "Cannot retrieve locked instance %s" % self.op.instance_name
119
120 cluster = self.cfg.GetClusterInfo()
121
122 if self.op.hvparams:
123
124 utils.ForceDictType(self.op.hvparams, constants.HVS_PARAMETER_TYPES)
125 filled_hvp = cluster.FillHV(self.instance)
126 filled_hvp.update(self.op.hvparams)
127 hv_type = hypervisor.GetHypervisorClass(self.instance.hypervisor)
128 hv_type.CheckParameterSyntax(filled_hvp)
129 CheckHVParams(self, self.instance.all_nodes, self.instance.hypervisor,
130 filled_hvp)
131
132 CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
133
134 self.primary_offline = \
135 self.cfg.GetNodeInfo(self.instance.primary_node).offline
136
137 if self.primary_offline and self.op.ignore_offline_nodes:
138 self.LogWarning("Ignoring offline primary node")
139
140 if self.op.hvparams or self.op.beparams:
141 self.LogWarning("Overridden parameters are ignored")
142 else:
143 CheckNodeOnline(self, self.instance.primary_node)
144
145 bep = self.cfg.GetClusterInfo().FillBE(self.instance)
146 bep.update(self.op.beparams)
147
148
149 CheckInstanceBridgesExist(self, self.instance)
150
151 remote_info = self.rpc.call_instance_info(
152 self.instance.primary_node, self.instance.name,
153 self.instance.hypervisor, cluster.hvparams[self.instance.hypervisor])
154 remote_info.Raise("Error checking node %s" %
155 self.cfg.GetNodeName(self.instance.primary_node),
156 prereq=True, ecode=errors.ECODE_ENVIRON)
157
158 self.requires_cleanup = False
159
160 if remote_info.payload:
161 if _IsInstanceUserDown(self.cfg.GetClusterInfo(),
162 self.instance,
163 remote_info.payload):
164 self.requires_cleanup = True
165 else:
166 CheckNodeFreeMemory(
167 self, self.instance.primary_node,
168 "starting instance %s" % self.instance.name,
169 bep[constants.BE_MINMEM], self.instance.hypervisor,
170 self.cfg.GetClusterInfo().hvparams[self.instance.hypervisor])
171
172 - def Exec(self, feedback_fn):
173 """Start the instance.
174
175 """
176 if not self.op.no_remember:
177 self.cfg.MarkInstanceUp(self.instance.uuid)
178
179 if self.primary_offline:
180 assert self.op.ignore_offline_nodes
181 self.LogInfo("Primary node offline, marked instance as started")
182 else:
183 if self.requires_cleanup:
184 result = self.rpc.call_instance_shutdown(
185 self.instance.primary_node,
186 self.instance,
187 self.op.shutdown_timeout, self.op.reason)
188 result.Raise("Could not shutdown instance '%s'" % self.instance.name)
189
190 ShutdownInstanceDisks(self, self.instance)
191
192 StartInstanceDisks(self, self.instance, self.op.force)
193
194 result = \
195 self.rpc.call_instance_start(self.instance.primary_node,
196 (self.instance, self.op.hvparams,
197 self.op.beparams),
198 self.op.startup_paused, self.op.reason)
199 if result.fail_msg:
200 ShutdownInstanceDisks(self, self.instance)
201 result.Raise("Could not start instance '%s'" % self.instance.name)
202
203
205 """Shutdown an instance.
206
207 """
208 HPATH = "instance-stop"
209 HTYPE = constants.HTYPE_INSTANCE
210 REQ_BGL = False
211
214
216 """Check arguments.
217
218 """
219 if self.op.no_remember and self.op.admin_state_source is not None:
220 self.LogWarning("Parameter 'admin_state_source' has no effect if used"
221 " with parameter 'no_remember'")
222
223 if self.op.admin_state_source is None:
224 self.op.admin_state_source = constants.ADMIN_SOURCE
225
227 """Build hooks env.
228
229 This runs on master, primary and secondary nodes of the instance.
230
231 """
232 env = BuildInstanceHookEnvByObject(self, self.instance)
233 env["TIMEOUT"] = self.op.timeout
234 return env
235
242
244 """Check prerequisites.
245
246 This checks that the instance is in the cluster.
247
248 """
249 self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
250 assert self.instance is not None, \
251 "Cannot retrieve locked instance %s" % self.op.instance_name
252
253 if self.op.force:
254 self.LogWarning("Ignoring offline instance check")
255 else:
256 CheckInstanceState(self, self.instance, INSTANCE_ONLINE)
257
258 self.primary_offline = \
259 self.cfg.GetNodeInfo(self.instance.primary_node).offline
260
261 if self.primary_offline and self.op.ignore_offline_nodes:
262 self.LogWarning("Ignoring offline primary node")
263 else:
264 CheckNodeOnline(self, self.instance.primary_node)
265
266 if self.op.admin_state_source == constants.USER_SOURCE:
267 cluster = self.cfg.GetClusterInfo()
268
269 result = self.rpc.call_instance_info(
270 self.instance.primary_node,
271 self.instance.name,
272 self.instance.hypervisor,
273 cluster.hvparams[self.instance.hypervisor])
274 result.Raise("Error checking instance '%s'" % self.instance.name,
275 prereq=True)
276
277 if not _IsInstanceUserDown(cluster,
278 self.instance,
279 result.payload):
280 raise errors.OpPrereqError("Instance '%s' was not shutdown by the user"
281 % self.instance.name)
282
283 - def Exec(self, feedback_fn):
306
307
309 """Reinstall an instance.
310
311 """
312 HPATH = "instance-reinstall"
313 HTYPE = constants.HTYPE_INSTANCE
314 REQ_BGL = False
315
318
326
333
335 """Check prerequisites.
336
337 This checks that the instance is in the cluster and is not running.
338
339 """
340 instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
341 assert instance is not None, \
342 "Cannot retrieve locked instance %s" % self.op.instance_name
343 CheckNodeOnline(self, instance.primary_node, "Instance primary node"
344 " offline, cannot reinstall")
345
346 if instance.disk_template == constants.DT_DISKLESS:
347 raise errors.OpPrereqError("Instance '%s' has no disks" %
348 self.op.instance_name,
349 errors.ECODE_INVAL)
350 CheckInstanceState(self, instance, INSTANCE_DOWN, msg="cannot reinstall")
351
352 if self.op.os_type is not None:
353
354 CheckNodeHasOS(self, instance.primary_node, self.op.os_type,
355 self.op.force_variant)
356 instance_os = self.op.os_type
357 else:
358 instance_os = instance.os
359
360 node_uuids = list(instance.all_nodes)
361
362 if self.op.osparams:
363 i_osdict = GetUpdatedParams(instance.osparams, self.op.osparams)
364 CheckOSParams(self, True, node_uuids, instance_os, i_osdict)
365 self.os_inst = i_osdict
366 else:
367 self.os_inst = None
368
369 self.instance = instance
370
371 - def Exec(self, feedback_fn):
393
394
396 """Reboot an instance.
397
398 """
399 HPATH = "instance-reboot"
400 HTYPE = constants.HTYPE_INSTANCE
401 REQ_BGL = False
402
405
407 """Build hooks env.
408
409 This runs on master, primary and secondary nodes of the instance.
410
411 """
412 env = {
413 "IGNORE_SECONDARIES": self.op.ignore_secondaries,
414 "REBOOT_TYPE": self.op.reboot_type,
415 "SHUTDOWN_TIMEOUT": self.op.shutdown_timeout,
416 }
417
418 env.update(BuildInstanceHookEnvByObject(self, self.instance))
419
420 return env
421
428
443
444 - def Exec(self, feedback_fn):
445 """Reboot the instance.
446
447 """
448 cluster = self.cfg.GetClusterInfo()
449 remote_info = self.rpc.call_instance_info(
450 self.instance.primary_node, self.instance.name,
451 self.instance.hypervisor, cluster.hvparams[self.instance.hypervisor])
452 remote_info.Raise("Error checking node %s" %
453 self.cfg.GetNodeName(self.instance.primary_node))
454 instance_running = bool(remote_info.payload)
455
456 current_node_uuid = self.instance.primary_node
457
458 if instance_running and \
459 self.op.reboot_type in [constants.INSTANCE_REBOOT_SOFT,
460 constants.INSTANCE_REBOOT_HARD]:
461 result = self.rpc.call_instance_reboot(current_node_uuid, self.instance,
462 self.op.reboot_type,
463 self.op.shutdown_timeout,
464 self.op.reason)
465 result.Raise("Could not reboot instance")
466 else:
467 if instance_running:
468 result = self.rpc.call_instance_shutdown(current_node_uuid,
469 self.instance,
470 self.op.shutdown_timeout,
471 self.op.reason)
472 result.Raise("Could not shutdown instance for full reboot")
473 ShutdownInstanceDisks(self, self.instance)
474 else:
475 self.LogInfo("Instance %s was already stopped, starting now",
476 self.instance.name)
477 StartInstanceDisks(self, self.instance, self.op.ignore_secondaries)
478 result = self.rpc.call_instance_start(current_node_uuid,
479 (self.instance, None, None), False,
480 self.op.reason)
481 msg = result.fail_msg
482 if msg:
483 ShutdownInstanceDisks(self, self.instance)
484 raise errors.OpExecError("Could not start instance for"
485 " full reboot: %s" % msg)
486
487 self.cfg.MarkInstanceUp(self.instance.uuid)
488
489
512
513
515 """Connect to an instance's console.
516
517 This is somewhat special in that it returns the command line that
518 you need to run on the master node in order to connect to the
519 console.
520
521 """
522 REQ_BGL = False
523
527
529 """Check prerequisites.
530
531 This checks that the instance is in the cluster.
532
533 """
534 self.instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
535 assert self.instance is not None, \
536 "Cannot retrieve locked instance %s" % self.op.instance_name
537 CheckNodeOnline(self, self.instance.primary_node)
538
539 - def Exec(self, feedback_fn):
569