Revision 1f350e0f
b/lib/backend.py | ||
---|---|---|
1355 | 1355 |
_Fail("Hypervisor error: %s", err, exc=True) |
1356 | 1356 |
|
1357 | 1357 |
|
1358 |
def InstanceShutdown(instance, timeout): |
|
1358 |
def InstanceShutdown(instance, timeout, reason, store_reason=True):
|
|
1359 | 1359 |
"""Shut an instance down. |
1360 | 1360 |
|
1361 | 1361 |
@note: this functions uses polling with a hardcoded timeout. |
... | ... | |
1364 | 1364 |
@param instance: the instance object |
1365 | 1365 |
@type timeout: integer |
1366 | 1366 |
@param timeout: maximum timeout for soft shutdown |
1367 |
@type reason: list of reasons |
|
1368 |
@param reason: the reason trail for this shutdown |
|
1369 |
@type store_reason: boolean |
|
1370 |
@param store_reason: whether to store the shutdown reason trail on file |
|
1367 | 1371 |
@rtype: None |
1368 | 1372 |
|
1369 | 1373 |
""" |
... | ... | |
1385 | 1389 |
|
1386 | 1390 |
try: |
1387 | 1391 |
hyper.StopInstance(instance, retry=self.tried_once) |
1392 |
if store_reason: |
|
1393 |
_StoreInstReasonTrail(instance.name, reason) |
|
1388 | 1394 |
except errors.HypervisorError, err: |
1389 | 1395 |
if iname not in hyper.ListInstances(): |
1390 | 1396 |
# if the instance is no longer existing, consider this a |
... | ... | |
1460 | 1466 |
_Fail("Failed to soft reboot instance %s: %s", instance.name, err) |
1461 | 1467 |
elif reboot_type == constants.INSTANCE_REBOOT_HARD: |
1462 | 1468 |
try: |
1463 |
InstanceShutdown(instance, shutdown_timeout) |
|
1469 |
InstanceShutdown(instance, shutdown_timeout, reason, store_reason=False)
|
|
1464 | 1470 |
result = StartInstance(instance, False) |
1465 | 1471 |
_StoreInstReasonTrail(instance.name, reason) |
1466 | 1472 |
return result |
b/lib/cmdlib.py | ||
---|---|---|
7449 | 7449 |
else: |
7450 | 7450 |
if instance_running: |
7451 | 7451 |
result = self.rpc.call_instance_shutdown(node_current, instance, |
7452 |
self.op.shutdown_timeout) |
|
7452 |
self.op.shutdown_timeout, |
|
7453 |
reason) |
|
7453 | 7454 |
result.Raise("Could not shutdown instance for full reboot") |
7454 | 7455 |
_ShutdownInstanceDisks(self, instance) |
7455 | 7456 |
else: |
... | ... | |
7525 | 7526 |
instance = self.instance |
7526 | 7527 |
node_current = instance.primary_node |
7527 | 7528 |
timeout = self.op.timeout |
7529 |
reason = self.op.reason |
|
7528 | 7530 |
|
7529 | 7531 |
# If the instance is offline we shouldn't mark it as down, as that |
7530 | 7532 |
# resets the offline flag. |
... | ... | |
7535 | 7537 |
assert self.op.ignore_offline_nodes |
7536 | 7538 |
self.LogInfo("Primary node offline, marked instance as stopped") |
7537 | 7539 |
else: |
7538 |
result = self.rpc.call_instance_shutdown(node_current, instance, timeout) |
|
7540 |
result = self.rpc.call_instance_shutdown(node_current, instance, timeout, |
|
7541 |
reason) |
|
7539 | 7542 |
msg = result.fail_msg |
7540 | 7543 |
if msg: |
7541 | 7544 |
self.LogWarning("Could not shutdown instance: %s", msg) |
... | ... | |
8116 | 8119 |
instance.name, instance.primary_node) |
8117 | 8120 |
|
8118 | 8121 |
result = self.rpc.call_instance_shutdown(instance.primary_node, instance, |
8119 |
self.op.shutdown_timeout) |
|
8122 |
self.op.shutdown_timeout, |
|
8123 |
self.op.reason) |
|
8120 | 8124 |
msg = result.fail_msg |
8121 | 8125 |
if msg: |
8122 | 8126 |
if self.op.ignore_failures: |
... | ... | |
8481 | 8485 |
self.owned_locks(locking.LEVEL_NODE_RES)) |
8482 | 8486 |
|
8483 | 8487 |
result = self.rpc.call_instance_shutdown(source_node, instance, |
8484 |
self.op.shutdown_timeout) |
|
8488 |
self.op.shutdown_timeout, |
|
8489 |
self.op.reason) |
|
8485 | 8490 |
msg = result.fail_msg |
8486 | 8491 |
if msg: |
8487 | 8492 |
if self.op.ignore_consistency: |
... | ... | |
9254 | 9259 |
instance.name, source_node) |
9255 | 9260 |
|
9256 | 9261 |
result = self.rpc.call_instance_shutdown(source_node, instance, |
9257 |
self.shutdown_timeout) |
|
9262 |
self.shutdown_timeout, |
|
9263 |
self.lu.op.reason) |
|
9258 | 9264 |
msg = result.fail_msg |
9259 | 9265 |
if msg: |
9260 | 9266 |
if self.ignore_consistency or primary_node.offline: |
... | ... | |
14927 | 14933 |
# shutdown the instance, but not the disks |
14928 | 14934 |
feedback_fn("Shutting down instance %s" % instance.name) |
14929 | 14935 |
result = self.rpc.call_instance_shutdown(src_node, instance, |
14930 |
self.op.shutdown_timeout) |
|
14936 |
self.op.shutdown_timeout, |
|
14937 |
self.op.reason) |
|
14931 | 14938 |
# TODO: Maybe ignore failures if ignore_remove_failures is set |
14932 | 14939 |
result.Raise("Could not shutdown instance %s on" |
14933 | 14940 |
" node %s" % (instance.name, src_node)) |
b/lib/rapi/client.py | ||
---|---|---|
1031 | 1031 |
(GANETI_RAPI_VERSION, instance)), query, None) |
1032 | 1032 |
|
1033 | 1033 |
def ShutdownInstance(self, instance, dry_run=False, no_remember=False, |
1034 |
**kwargs): |
|
1034 |
reason=None, **kwargs):
|
|
1035 | 1035 |
"""Shuts down an instance. |
1036 | 1036 |
|
1037 | 1037 |
@type instance: str |
... | ... | |
1040 | 1040 |
@param dry_run: whether to perform a dry run |
1041 | 1041 |
@type no_remember: bool |
1042 | 1042 |
@param no_remember: if true, will not record the state change |
1043 |
@type reason: string |
|
1044 |
@param reason: the reason for the shutdown |
|
1043 | 1045 |
@rtype: string |
1044 | 1046 |
@return: job id |
1045 | 1047 |
|
... | ... | |
1049 | 1051 |
|
1050 | 1052 |
_AppendDryRunIf(query, dry_run) |
1051 | 1053 |
_AppendIf(query, no_remember, ("no_remember", 1)) |
1054 |
_AppendIf(query, reason, ("reason", reason)) |
|
1052 | 1055 |
|
1053 | 1056 |
return self._SendRequest(HTTP_PUT, |
1054 | 1057 |
("/%s/instances/%s/shutdown" % |
b/lib/rpc_defs.py | ||
---|---|---|
235 | 235 |
("instance_shutdown", SINGLE, None, constants.RPC_TMO_NORMAL, [ |
236 | 236 |
("instance", ED_INST_DICT, "Instance object"), |
237 | 237 |
("timeout", None, None), |
238 |
("reason", None, "The reason for the shutdown"), |
|
238 | 239 |
], None, None, "Stops an instance"), |
239 | 240 |
("instance_balloon_memory", SINGLE, None, constants.RPC_TMO_NORMAL, [ |
240 | 241 |
("instance", ED_INST_DICT, "Instance object"), |
b/lib/server/noded.py | ||
---|---|---|
589 | 589 |
""" |
590 | 590 |
instance = objects.Instance.FromDict(params[0]) |
591 | 591 |
timeout = params[1] |
592 |
return backend.InstanceShutdown(instance, timeout) |
|
592 |
trail = params[2] |
|
593 |
_extendReasonTrail(trail, "shutdown") |
|
594 |
return backend.InstanceShutdown(instance, timeout, trail) |
|
593 | 595 |
|
594 | 596 |
@staticmethod |
595 | 597 |
def perspective_instance_start(params): |
b/test/py/ganeti.rapi.client_unittest.py | ||
---|---|---|
619 | 619 |
def testShutdownInstance(self): |
620 | 620 |
self.rapi.AddResponse("1487") |
621 | 621 |
self.assertEqual(1487, self.client.ShutdownInstance("foo-instance", |
622 |
dry_run=True, |
|
623 |
reason="NoMore")) |
|
624 |
self.assertHandler(rlib2.R_2_instances_name_shutdown) |
|
625 |
self.assertItems(["foo-instance"]) |
|
626 |
self.assertDryRun() |
|
627 |
self.assertQuery("reason", ["NoMore"]) |
|
628 |
|
|
629 |
def testShutdownInstanceDefaultReason(self): |
|
630 |
self.rapi.AddResponse("1487") |
|
631 |
self.assertEqual(1487, self.client.ShutdownInstance("foo-instance", |
|
622 | 632 |
dry_run=True)) |
623 | 633 |
self.assertHandler(rlib2.R_2_instances_name_shutdown) |
624 | 634 |
self.assertItems(["foo-instance"]) |
625 | 635 |
self.assertDryRun() |
636 |
self.assertQuery("reason", None) |
|
626 | 637 |
|
627 | 638 |
def testStartupInstance(self): |
628 | 639 |
self.rapi.AddResponse("27149") |
b/test/py/ganeti.rapi.rlib2_unittest.py | ||
---|---|---|
422 | 422 |
clfactory = _FakeClientFactory(_FakeClient) |
423 | 423 |
handler = _CreateHandler(rlib2.R_2_instances_name_shutdown, ["inst26791"], { |
424 | 424 |
"no_remember": ["0"], |
425 |
"reason": ["Not used anymore"], |
|
425 | 426 |
}, {}, clfactory) |
426 | 427 |
job_id = handler.PUT() |
427 | 428 |
|
... | ... | |
434 | 435 |
self.assertEqual(op.instance_name, "inst26791") |
435 | 436 |
self.assertFalse(op.no_remember) |
436 | 437 |
self.assertFalse(op.dry_run) |
438 |
self.assertEqual(op.reason[0][0], constants.OPCODE_REASON_SRC_USER) |
|
439 |
self.assertEqual(op.reason[0][1], "Not used anymore") |
|
440 |
self.assertEqual(op.reason[1][0], |
|
441 |
"%s:%s" % (constants.OPCODE_REASON_SRC_RLIB2, |
|
442 |
"instances_name_shutdown")) |
|
443 |
self.assertEqual(op.reason[1][1], "") |
|
437 | 444 |
|
438 | 445 |
self.assertRaises(IndexError, cl.GetNextSubmittedJob) |
439 | 446 |
|
Also available in: Unified diff