From e4e9b8064787df01a79846a40f49c8ae06a8eb0e Mon Sep 17 00:00:00 2001
From: Guido Trotter <ultrotter@google.com>
Date: Fri, 9 Oct 2009 11:35:34 +0100
Subject: [PATCH] backend.InstanceShutdown: small cleanup

1) unhardcode the timeout, abstracting it in a constant
2) Use time.time() rather than hiding the timeout in a range()
3) call hyper.StopInstance multiple times
   -- currently all hypervisors just ignore all calls but once
4) Use hyper.ListInstances() rather than GetInstanceList([hv_name])
   -- it's cheaper :)
5) Change the final message to "forcing" from "using destroy"

Signed-off-by: Guido Trotter <ultrotter@google.com>
Reviewed-by: Olivier Tharan <olive@google.com>
---
 lib/backend.py | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/lib/backend.py b/lib/backend.py
index edbbc4807..f35e40ff1 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -971,29 +971,36 @@ def InstanceShutdown(instance):
 
   """
   hv_name = instance.hypervisor
-  running_instances = GetInstanceList([hv_name])
+  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)
     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)
-- 
GitLab