Merge branch 'stable-2.1' into devel-2.1
authorIustin Pop <iustin@google.com>
Mon, 8 Feb 2010 13:16:58 +0000 (14:16 +0100)
committerIustin Pop <iustin@google.com>
Mon, 8 Feb 2010 14:04:40 +0000 (15:04 +0100)
* stable-2.1:
  TLReplaceDisks: Delay iallocator when evacuating node
  Implement debug level across OS-related RPC calls
  Second try to fix LUVerifyCluster
  LUVerifyCluster: Fix bug with offline nodes
  utils: Fix retry delay calculator
  Bump RPC protocol version to 30

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>

daemons/ganeti-noded
lib/backend.py
lib/cmdlib.py
lib/constants.py
lib/rpc.py
lib/utils.py

index 7b030a6..30087f1 100755 (executable)
@@ -345,8 +345,9 @@ class NodeHttpServer(http.server.HttpServer):
     instance = objects.Instance.FromDict(params[2])
     cluster_name = params[3]
     dev_idx = params[4]
+    debug = params[5]
     return backend.ExportSnapshot(disk, dest_node, instance,
-                                  cluster_name, dev_idx)
+                                  cluster_name, dev_idx, debug)
 
   @staticmethod
   def perspective_finalize_export(params):
@@ -451,26 +452,27 @@ class NodeHttpServer(http.server.HttpServer):
     inst_s = params[0]
     inst = objects.Instance.FromDict(inst_s)
     reinstall = params[1]
-    return backend.InstanceOsAdd(inst, reinstall)
+    debug = params[2]
+    return backend.InstanceOsAdd(inst, reinstall, debug)
 
   @staticmethod
   def perspective_instance_run_rename(params):
     """Runs the OS rename script for an instance.
 
     """
-    inst_s, old_name = params
+    inst_s, old_name, debug = params
     inst = objects.Instance.FromDict(inst_s)
-    return backend.RunRenameInstance(inst, old_name)
+    return backend.RunRenameInstance(inst, old_name, debug)
 
   @staticmethod
   def perspective_instance_os_import(params):
     """Run the import function of an OS onto a given instance.
 
     """
-    inst_s, src_node, src_images, cluster_name = params
+    inst_s, src_node, src_images, cluster_name, debug = params
     inst = objects.Instance.FromDict(inst_s)
     return backend.ImportOSIntoInstance(inst, src_node, src_images,
-                                        cluster_name)
+                                        cluster_name, debug)
 
   @staticmethod
   def perspective_instance_shutdown(params):
index 711d7bc..3b2538e 100644 (file)
@@ -789,19 +789,21 @@ def GetAllInstancesInfo(hypervisor_list):
   return output
 
 
-def InstanceOsAdd(instance, reinstall):
+def InstanceOsAdd(instance, reinstall, debug):
   """Add an OS to an instance.
 
   @type instance: L{objects.Instance}
   @param instance: Instance whose OS is to be installed
   @type reinstall: boolean
   @param reinstall: whether this is an instance reinstall
+  @type debug: integer
+  @param debug: debug level, passed to the OS scripts
   @rtype: None
 
   """
   inst_os = OSFromDisk(instance.os)
 
-  create_env = OSEnvironment(instance, inst_os)
+  create_env = OSEnvironment(instance, inst_os, debug)
   if reinstall:
     create_env['INSTANCE_REINSTALL'] = "1"
 
@@ -820,20 +822,22 @@ def InstanceOsAdd(instance, reinstall):
           " log file:\n%s", result.fail_reason, "\n".join(lines), log=False)
 
 
-def RunRenameInstance(instance, old_name):
+def RunRenameInstance(instance, old_name, debug):
   """Run the OS rename script for an instance.
 
   @type instance: L{objects.Instance}
   @param instance: Instance whose OS is to be installed
   @type old_name: string
   @param old_name: previous instance name
+  @type debug: integer
+  @param debug: debug level, passed to the OS scripts
   @rtype: boolean
   @return: the success of the operation
 
   """
   inst_os = OSFromDisk(instance.os)
 
-  rename_env = OSEnvironment(instance, inst_os)
+  rename_env = OSEnvironment(instance, inst_os, debug)
   rename_env['OLD_INSTANCE_NAME'] = old_name
 
   logfile = "%s/rename-%s-%s-%s-%d.log" % (constants.LOG_OS_DIR, instance.os,
@@ -1944,7 +1948,7 @@ def BlockdevSnapshot(disk):
           disk.unique_id, disk.dev_type)
 
 
-def ExportSnapshot(disk, dest_node, instance, cluster_name, idx):
+def ExportSnapshot(disk, dest_node, instance, cluster_name, idx, debug):
   """Export a block device snapshot to a remote node.
 
   @type disk: L{objects.Disk}
@@ -1958,11 +1962,13 @@ def ExportSnapshot(disk, dest_node, instance, cluster_name, idx):
   @type idx: int
   @param idx: the index of the disk in the instance's disk list,
       used to export to the OS scripts environment
+  @type debug: integer
+  @param debug: debug level, passed to the OS scripts
   @rtype: None
 
   """
   inst_os = OSFromDisk(instance.os)
-  export_env = OSEnvironment(instance, inst_os)
+  export_env = OSEnvironment(instance, inst_os, debug)
 
   export_script = inst_os.export_script
 
@@ -2092,7 +2098,7 @@ def ExportInfo(dest):
   return config.Dumps()
 
 
-def ImportOSIntoInstance(instance, src_node, src_images, cluster_name):
+def ImportOSIntoInstance(instance, src_node, src_images, cluster_name, debug):
   """Import an os image into an instance.
 
   @type instance: L{objects.Instance}
@@ -2101,12 +2107,14 @@ def ImportOSIntoInstance(instance, src_node, src_images, cluster_name):
   @param src_node: source node for the disk images
   @type src_images: list of string
   @param src_images: absolute paths of the disk images
+  @type debug: integer
+  @param debug: debug level, passed to the OS scripts
   @rtype: list of boolean
   @return: each boolean represent the success of importing the n-th disk
 
   """
   inst_os = OSFromDisk(instance.os)
-  import_env = OSEnvironment(instance, inst_os)
+  import_env = OSEnvironment(instance, inst_os, debug)
   import_script = inst_os.import_script
 
   logfile = "%s/import-%s-%s-%s.log" % (constants.LOG_OS_DIR, instance.os,
index 7dffa46..cb922eb 100644 (file)
@@ -1603,7 +1603,8 @@ class LUVerifyCluster(LogicalUnit):
         test = msg and not res.offline
         self._ErrorIf(test, self.ENODEHOOKS, node_name,
                       "Communication failure in hooks execution: %s", msg)
-        if test:
+        if res.offline or msg:
+          # No need to investigate payload if node is offline or gave an error.
           # override manually lu_result here as _ErrorIf only
           # overrides self.bad
           lu_result = 1
@@ -3992,7 +3993,8 @@ class LUReinstallInstance(LogicalUnit):
     _StartInstanceDisks(self, inst, None)
     try:
       feedback_fn("Running the instance OS create scripts...")
-      result = self.rpc.call_instance_os_add(inst.primary_node, inst, True)
+      # FIXME: pass debug option from opcode to backend
+      result = self.rpc.call_instance_os_add(inst.primary_node, inst, True, 0)
       result.Raise("Could not install OS for instance %s on node %s" %
                    (inst.name, inst.primary_node))
     finally:
@@ -4176,7 +4178,7 @@ class LURenameInstance(LogicalUnit):
     _StartInstanceDisks(self, inst, None)
     try:
       result = self.rpc.call_instance_run_rename(inst.primary_node, inst,
-                                                 old_name)
+                                                 old_name, 0)
       msg = result.fail_msg
       if msg:
         msg = ("Could not run OS rename script for instance %s on node %s"
@@ -6229,7 +6231,8 @@ class LUCreateInstance(LogicalUnit):
     if iobj.disk_template != constants.DT_DISKLESS:
       if self.op.mode == constants.INSTANCE_CREATE:
         feedback_fn("* running the instance OS create scripts...")
-        result = self.rpc.call_instance_os_add(pnode_name, iobj, False)
+        # FIXME: pass debug option from opcode to backend
+        result = self.rpc.call_instance_os_add(pnode_name, iobj, False, 0)
         result.Raise("Could not add os for instance %s"
                      " on node %s" % (instance, pnode_name))
 
@@ -6238,9 +6241,10 @@ class LUCreateInstance(LogicalUnit):
         src_node = self.op.src_node
         src_images = self.src_images
         cluster_name = self.cfg.GetClusterName()
+        # FIXME: pass debug option from opcode to backend
         import_result = self.rpc.call_instance_os_import(pnode_name, iobj,
                                                          src_node, src_images,
-                                                         cluster_name)
+                                                         cluster_name, 0)
         msg = import_result.fail_msg
         if msg:
           self.LogWarning("Error while importing the disk images for instance"
@@ -6359,7 +6363,7 @@ class LUReplaceDisks(LogicalUnit):
 
     self.replacer = TLReplaceDisks(self, self.op.instance_name, self.op.mode,
                                    self.op.iallocator, self.op.remote_node,
-                                   self.op.disks)
+                                   self.op.disks, False)
 
     self.tasklets = [self.replacer]
 
@@ -6451,7 +6455,8 @@ class LUEvacuateNode(LogicalUnit):
       names.append(inst.name)
 
       replacer = TLReplaceDisks(self, inst.name, constants.REPLACE_DISK_CHG,
-                                self.op.iallocator, self.op.remote_node, [])
+                                self.op.iallocator, self.op.remote_node, [],
+                                True)
       tasklets.append(replacer)
 
     self.tasklets = tasklets
@@ -6493,7 +6498,7 @@ class TLReplaceDisks(Tasklet):
 
   """
   def __init__(self, lu, instance_name, mode, iallocator_name, remote_node,
-               disks):
+               disks, delay_iallocator):
     """Initializes this class.
 
     """
@@ -6505,6 +6510,7 @@ class TLReplaceDisks(Tasklet):
     self.iallocator_name = iallocator_name
     self.remote_node = remote_node
     self.disks = disks
+    self.delay_iallocator = delay_iallocator
 
     # Runtime data
     self.instance = None
@@ -6591,6 +6597,19 @@ class TLReplaceDisks(Tasklet):
                                  len(instance.secondary_nodes),
                                  errors.ECODE_FAULT)
 
+    if not self.delay_iallocator:
+      self._CheckPrereq2()
+
+  def _CheckPrereq2(self):
+    """Check prerequisites, second part.
+
+    This function should always be part of CheckPrereq. It was separated and is
+    now called from Exec because during node evacuation iallocator was only
+    called with an unmodified cluster model, not taking planned changes into
+    account.
+
+    """
+    instance = self.instance
     secondary_node = instance.secondary_nodes[0]
 
     if self.iallocator_name is None:
@@ -6694,6 +6713,9 @@ class TLReplaceDisks(Tasklet):
     This dispatches the disk replacement to the appropriate handler.
 
     """
+    if self.delay_iallocator:
+      self._CheckPrereq2()
+
     if not self.disks:
       feedback_fn("No disks need replacement")
       return
@@ -8148,8 +8170,10 @@ class LUExportInstance(LogicalUnit):
         feedback_fn("Exporting snapshot %s from %s to %s" %
                     (idx, src_node, dst_node.name))
         if dev:
+          # FIXME: pass debug from opcode to backend
           result = self.rpc.call_snapshot_export(src_node, dev, dst_node.name,
-                                                 instance, cluster_name, idx)
+                                                 instance, cluster_name,
+                                                 idx, 0)
           msg = result.fail_msg
           if msg:
             self.LogWarning("Could not export disk/%s from node %s to"
index f91ea78..3f71443 100644 (file)
@@ -26,7 +26,7 @@ import re
 from ganeti import _autoconf
 
 # various versions
-PROTOCOL_VERSION = 20
+PROTOCOL_VERSION = 30
 RELEASE_VERSION = _autoconf.PACKAGE_VERSION
 OS_API_V10 = 10
 OS_API_V15 = 15
index 69e692c..d9114f1 100644 (file)
@@ -576,23 +576,23 @@ class RpcRunner(object):
                                 [self._InstDict(inst), reboot_type,
                                  shutdown_timeout])
 
-  def call_instance_os_add(self, node, inst, reinstall):
+  def call_instance_os_add(self, node, inst, reinstall, debug):
     """Installs an OS on the given instance.
 
     This is a single-node call.
 
     """
     return self._SingleNodeCall(node, "instance_os_add",
-                                [self._InstDict(inst), reinstall])
+                                [self._InstDict(inst), reinstall, debug])
 
-  def call_instance_run_rename(self, node, inst, old_name):
+  def call_instance_run_rename(self, node, inst, old_name, debug):
     """Run the OS rename script for an instance.
 
     This is a single-node call.
 
     """
     return self._SingleNodeCall(node, "instance_run_rename",
-                                [self._InstDict(inst), old_name])
+                                [self._InstDict(inst), old_name, debug])
 
   def call_instance_info(self, node, instance, hname):
     """Returns information about a single instance.
@@ -988,7 +988,7 @@ class RpcRunner(object):
     return self._SingleNodeCall(node, "blockdev_snapshot", [cf_bdev.ToDict()])
 
   def call_snapshot_export(self, node, snap_bdev, dest_node, instance,
-                           cluster_name, idx):
+                           cluster_name, idx, debug):
     """Request the export of a given snapshot.
 
     This is a single-node call.
@@ -996,7 +996,8 @@ class RpcRunner(object):
     """
     return self._SingleNodeCall(node, "snapshot_export",
                                 [snap_bdev.ToDict(), dest_node,
-                                 self._InstDict(instance), cluster_name, idx])
+                                 self._InstDict(instance), cluster_name,
+                                 idx, debug])
 
   def call_finalize_export(self, node, instance, snap_disks):
     """Request the completion of an export operation.
@@ -1025,7 +1026,7 @@ class RpcRunner(object):
     return self._SingleNodeCall(node, "export_info", [path])
 
   def call_instance_os_import(self, node, inst, src_node, src_images,
-                              cluster_name):
+                              cluster_name, debug):
     """Request the import of a backup into an instance.
 
     This is a single-node call.
@@ -1033,7 +1034,7 @@ class RpcRunner(object):
     """
     return self._SingleNodeCall(node, "instance_os_import",
                                 [self._InstDict(inst), src_node, src_images,
-                                 cluster_name])
+                                 cluster_name, debug])
 
   def call_export_list(self, node_list):
     """Gets the stored exports list.
index 438a120..45f0ecd 100644 (file)
@@ -2172,7 +2172,7 @@ class _RetryDelayCalculator(object):
 
     # Update for next run
     if self._limit is None or self._next < self._limit:
-      self._next = max(self._limit, self._next * self._factor)
+      self._next = min(self._limit, self._next * self._factor)
 
     return current