From 1f14b07e63c5f33eeab989d3d6fc133ad581d313 Mon Sep 17 00:00:00 2001
From: Bernardo Dal Seno <bdalseno@google.com>
Date: Fri, 10 May 2013 16:27:20 +0200
Subject: [PATCH] Clean up when "gnt-instance modify" fails to create a disk

cmdlib.LUInstanceSetParams now uses helper functions to create and wipe
disks, so that when the creation of a disk fails, any leftover device is
cleaned up. As a bonus, exceptions raised by _CreateBlockDev() are caught
correctly.

Now cmdlib._CreateDisks() is used every time there are disks to create.

Signed-off-by: Bernardo Dal Seno <bdalseno@google.com>
Reviewed-by: Helga Velroyen <helgav@google.com>
---
 lib/cmdlib.py | 32 ++++++++++++--------------------
 1 file changed, 12 insertions(+), 20 deletions(-)

diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index de8f40e5e..0adf0f164 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -9736,7 +9736,7 @@ def _UndoCreateDisks(lu, disks_created):
                       " %s", disk, node, result.fail_msg)
 
 
-def _CreateDisks(lu, instance, to_skip=None, target_node=None):
+def _CreateDisks(lu, instance, to_skip=None, target_node=None, disks=None):
   """Create all disks for an instance.
 
   This abstracts away some work from AddInstance.
@@ -9749,6 +9749,9 @@ def _CreateDisks(lu, instance, to_skip=None, target_node=None):
   @param to_skip: list of indices to skip
   @type target_node: string
   @param target_node: if passed, overrides the target node for creation
+  @type disks: list of {objects.Disk}
+  @param disks: the disks to create; if not specified, all the disks of the
+      instance are created
   @return: information about the created disks, to be used to call
       L{_UndoCreateDisks}
   @raise errors.OpPrereqError: in case of error
@@ -9762,6 +9765,9 @@ def _CreateDisks(lu, instance, to_skip=None, target_node=None):
     pnode = target_node
     all_nodes = [pnode]
 
+  if disks is None:
+    disks = instance.disks
+
   if instance.disk_template in constants.DTS_FILEBASED:
     file_storage_dir = os.path.dirname(instance.disks[0].logical_id[1])
     result = lu.rpc.call_file_storage_dir_create(pnode, file_storage_dir)
@@ -9770,13 +9776,10 @@ def _CreateDisks(lu, instance, to_skip=None, target_node=None):
                  " node %s" % (file_storage_dir, pnode))
 
   disks_created = []
-  # Note: this needs to be kept in sync with adding of disks in
-  # LUInstanceSetParams
-  for idx, device in enumerate(instance.disks):
+  for idx, device in enumerate(disks):
     if to_skip and idx in to_skip:
       continue
     logging.info("Creating disk %s for instance '%s'", idx, instance.name)
-    #HARDCODE
     for node in all_nodes:
       f_create = node == pnode
       try:
@@ -14162,24 +14165,13 @@ class LUInstanceSetParams(LogicalUnit):
                             [params], file_path, file_driver, idx,
                             self.Log, self.diskparams)[0]
 
-    info = _GetInstanceInfoText(instance)
-
-    logging.info("Creating volume %s for instance %s",
-                 disk.iv_name, instance.name)
-    # Note: this needs to be kept in sync with _CreateDisks
-    #HARDCODE
-    for node in instance.all_nodes:
-      f_create = (node == instance.primary_node)
-      try:
-        _CreateBlockDev(self, node, instance, disk, f_create, info, f_create)
-      except errors.OpExecError, err:
-        self.LogWarning("Failed to create volume %s (%s) on node '%s': %s",
-                        disk.iv_name, disk, node, err)
+    new_disks = _CreateDisks(self, instance, disks=[disk])
 
     if self.cluster.prealloc_wipe_disks:
       # Wipe new disk
-      _WipeDisks(self, instance,
-                 disks=[(idx, disk, 0)])
+      _WipeOrCleanupDisks(self, instance,
+                          disks=[(idx, disk, 0)],
+                          cleanup=new_disks)
 
     return (disk, [
       ("disk/%d" % idx, "add:size=%s,mode=%s" % (disk.size, disk.mode)),
-- 
GitLab