X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/f11280b52cca0b1c923b09d55913921d1a6ae358..4d98c5658a6d01a7be3bb08c6c7328bb6d9678ae:/lib/backend.py?ds=sidebyside diff --git a/lib/backend.py b/lib/backend.py index 09831fb..4e40cb7 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -960,40 +960,48 @@ 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 """ hv_name = instance.hypervisor - running_instances = GetInstanceList([hv_name]) + hyper = hypervisor.GetHypervisor(hv_name) + running_instances = hyper.ListInstances() iname = instance.name if iname not in running_instances: logging.info("Instance %s not running, doing nothing", iname) return - hyper = hypervisor.GetHypervisor(hv_name) - try: - hyper.StopInstance(instance) - except errors.HypervisorError, err: - _Fail("Failed to stop instance %s: %s", iname, err) - - # test every 10secs for 2min + start = time.time() + end = start + timeout + sleep_time = 1 - time.sleep(1) - for _ in range(11): - if instance.name not in GetInstanceList([hv_name]): + tried_once = False + while not tried_once and time.time() < end: + try: + hyper.StopInstance(instance, retry=tried_once) + except errors.HypervisorError, err: + _Fail("Failed to stop instance %s: %s", iname, err) + tried_once = True + time.sleep(sleep_time) + if instance.name not in hyper.ListInstances(): break - time.sleep(10) + if sleep_time < 5: + # 1.2 behaves particularly good for our case: + # it gives us 10 increasing steps and caps just slightly above 5 seconds + sleep_time *= 1.2 else: # the shutdown did not succeed - logging.error("Shutdown of '%s' unsuccessful, using destroy", iname) + logging.error("Shutdown of '%s' unsuccessful, forcing", iname) try: hyper.StopInstance(instance, force=True) @@ -1007,7 +1015,7 @@ def InstanceShutdown(instance): _RemoveBlockDevLinks(iname, instance.disks) -def InstanceReboot(instance, reboot_type): +def InstanceReboot(instance, reboot_type, shutdown_timeout): """Reboot an instance. @type instance: L{objects.Instance} @@ -1023,6 +1031,8 @@ def InstanceReboot(instance, reboot_type): not accepted here, since that mode is handled differently, in cmdlib, and translates into full stop and start of the instance (instead of a call_instance_reboot RPC) + @type timeout: integer + @param timeout: maximum timeout for soft shutdown @rtype: None """ @@ -1039,7 +1049,7 @@ def InstanceReboot(instance, reboot_type): _Fail("Failed to soft reboot instance %s: %s", instance.name, err) elif reboot_type == constants.INSTANCE_REBOOT_HARD: try: - InstanceShutdown(instance) + InstanceShutdown(instance, shutdown_timeout) return StartInstance(instance) except errors.HypervisorError, err: _Fail("Failed to hard reboot instance %s: %s", instance.name, err) @@ -1633,12 +1643,13 @@ def DiagnoseOS(top_dirs=None): search (if not given defaults to L{constants.OS_SEARCH_PATH}) @rtype: list of L{objects.OS} - @return: a list of tuples (name, path, status, diagnose) + @return: a list of tuples (name, path, status, diagnose, variants) for all (potential) OSes under all search paths, where: - name is the (potential) OS name - path is the full path to the OS - status True/False is the validity of the OS - diagnose is the error message for an invalid OS, otherwise empty + - variants is a list of supported OS variants, if any """ if top_dirs is None: @@ -1657,9 +1668,11 @@ def DiagnoseOS(top_dirs=None): status, os_inst = _TryOSFromDisk(name, base_dir=dir_name) if status: diagnose = "" + variants = os_inst.supported_variants else: diagnose = os_inst - result.append((name, os_path, status, diagnose)) + variants = [] + result.append((name, os_path, status, diagnose, variants)) return result @@ -1757,7 +1770,8 @@ def OSFromDisk(name, base_dir=None): @raise RPCFail: if we don't find a valid OS """ - status, payload = _TryOSFromDisk(name, base_dir) + name_only = name.split("+", 1)[0] + status, payload = _TryOSFromDisk(name_only, base_dir) if not status: _Fail(payload)