diff --git a/daemons/ganeti-noded b/daemons/ganeti-noded index c7528177645062a23c1f5f598d3784282059b61f..7582597b3a2407964dd1df1f7ab7b7785fb245a6 100755 --- a/daemons/ganeti-noded +++ b/daemons/ganeti-noded @@ -449,7 +449,8 @@ class NodeHttpServer(http.server.HttpServer): """ instance = objects.Instance.FromDict(params[0]) - return backend.InstanceShutdown(instance) + timeout = params[1] + return backend.InstanceShutdown(instance, timeout) @staticmethod def perspective_instance_start(params): diff --git a/lib/backend.py b/lib/backend.py index f35e40ff11a161939a2c84b1a491ee4075c8c463..ec87aae307a4097d5c5a120525df253f547be01a 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -960,13 +960,15 @@ def StartInstance(instance): _Fail("Hypervisor error: %s", err, exc=True) -def InstanceShutdown(instance): +def InstanceShutdown(instance, timeout): """Shut an instance down. @note: this functions uses polling with a hardcoded timeout. @type instance: L{objects.Instance} @param instance: the instance object + @type timeout: integer + @param timeout: maximum timeout for soft shutdown @rtype: None """ @@ -974,7 +976,6 @@ def InstanceShutdown(instance): hyper = hypervisor.GetHypervisor(hv_name) running_instances = hyper.ListInstances() iname = instance.name - timeout = constants.DEFAULT_SHUTDOWN_TIMEOUT if iname not in running_instances: logging.info("Instance %s not running, doing nothing", iname) diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 0023cac617b6124561b504e79b7684e04811a2c5..a5e25316b0667e9efba2c7831c6b672a83b364f7 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -3679,6 +3679,13 @@ class LUShutdownInstance(LogicalUnit): _OP_REQP = ["instance_name"] REQ_BGL = False + def CheckArguments(self): + """Check the arguments. + + """ + self.timeout = getattr(self.op, "timeout", + constants.DEFAULT_SHUTDOWN_TIMEOUT) + def ExpandNames(self): self._ExpandAndLockInstance() @@ -3689,6 +3696,7 @@ class LUShutdownInstance(LogicalUnit): """ env = _BuildInstanceHookEnvByObject(self, self.instance) + env["TIMEOUT"] = self.timeout nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes) return env, nl, nl @@ -3709,8 +3717,9 @@ class LUShutdownInstance(LogicalUnit): """ instance = self.instance node_current = instance.primary_node + timeout = self.timeout self.cfg.MarkInstanceDown(instance.name) - result = self.rpc.call_instance_shutdown(node_current, instance) + result = self.rpc.call_instance_shutdown(node_current, instance, timeout) msg = result.fail_msg if msg: self.proc.LogWarning("Could not shutdown instance: %s" % msg) diff --git a/lib/opcodes.py b/lib/opcodes.py index 929c62fee0ebbeb72f8272e476931dffd881c035..5ff1eb1ff34d94a9212613ed178de8496bf61a87 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -489,7 +489,7 @@ class OpShutdownInstance(OpCode): """Shutdown an instance.""" OP_ID = "OP_INSTANCE_SHUTDOWN" OP_DSC_FIELD = "instance_name" - __slots__ = OpCode.__slots__ + ["instance_name"] + __slots__ = OpCode.__slots__ + ["instance_name", "timeout"] class OpRebootInstance(OpCode): diff --git a/lib/rpc.py b/lib/rpc.py index ea132a9b383116c5edad63f2360c1499f3af2406..227e355cf1a24b00e8602990c90db2a946b5e4f7 100644 --- a/lib/rpc.py +++ b/lib/rpc.py @@ -467,14 +467,14 @@ class RpcRunner(object): idict = self._InstDict(instance, hvp=hvp, bep=bep) return self._SingleNodeCall(node, "instance_start", [idict]) - def call_instance_shutdown(self, node, instance): + def call_instance_shutdown(self, node, instance, timeout): """Stops an instance. This is a single-node call. """ return self._SingleNodeCall(node, "instance_shutdown", - [self._InstDict(instance)]) + [self._InstDict(instance), timeout]) def call_migration_info(self, node, instance): """Gather the information necessary to prepare an instance migration. diff --git a/scripts/gnt-instance b/scripts/gnt-instance index 194e6977166dc536920ee8dceb8a1623f4cc5cb2..8d5351384925fa05a07d77688ff52c0e41522a06 100755 --- a/scripts/gnt-instance +++ b/scripts/gnt-instance @@ -727,7 +727,8 @@ def _ShutdownInstance(name, opts): @return: the opcode needed for the operation """ - return opcodes.OpShutdownInstance(instance_name=name) + return opcodes.OpShutdownInstance(instance_name=name, + timeout=opts.timeout) def ReplaceDisks(opts, args): @@ -1346,7 +1347,7 @@ commands = { 'shutdown': ( GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()], [m_node_opt, m_pri_node_opt, m_sec_node_opt, m_clust_opt, - m_inst_opt, m_force_multi, SUBMIT_OPT], + m_inst_opt, m_force_multi, TIMEOUT_OPT, SUBMIT_OPT], "<instance>", "Stops an instance"), 'startup': ( GenericManyOps("startup", _StartupInstance), [ArgInstance()],