Merge branch 'stable-2.8'
[ganeti-local] / lib / cmdlib / instance_storage.py
index 4ad08d0..1aed5b2 100644 (file)
@@ -343,10 +343,13 @@ def ComputeDisks(op, default_vg):
       constants.IDISK_NAME: name,
       }
 
-    if constants.IDISK_METAVG in disk:
-      new_disk[constants.IDISK_METAVG] = disk[constants.IDISK_METAVG]
-    if constants.IDISK_ADOPT in disk:
-      new_disk[constants.IDISK_ADOPT] = disk[constants.IDISK_ADOPT]
+    for key in [
+      constants.IDISK_METAVG,
+      constants.IDISK_ADOPT,
+      constants.IDISK_SPINDLES,
+      ]:
+      if key in disk:
+        new_disk[key] = disk[key]
 
     # For extstorage, demand the `provider' option and add any
     # additional parameters (ext-params) to the dict
@@ -507,7 +510,8 @@ def GenerateDiskTemplate(
                               logical_id=logical_id_fn(idx, disk_index, disk),
                               iv_name="disk/%d" % disk_index,
                               mode=disk[constants.IDISK_MODE],
-                              params=params)
+                              params=params,
+                              spindles=disk.get(constants.IDISK_SPINDLES))
       disk_dev.name = disk.get(constants.IDISK_NAME, None)
       disk_dev.uuid = lu.cfg.GenerateUniqueID(lu.proc.GetECId())
       disks.append(disk_dev)
@@ -515,6 +519,23 @@ def GenerateDiskTemplate(
   return disks
 
 
+def CheckSpindlesExclusiveStorage(diskdict, es_flag):
+  """Check the presence of the spindle options with exclusive_storage.
+
+  @type diskdict: dict
+  @param diskdict: disk parameters
+  @type es_flag: bool
+  @param es_flag: the effective value of the exlusive_storage flag
+  @raise errors.OpPrereqError when spindles are given and they should not
+
+  """
+  if (not es_flag and constants.IDISK_SPINDLES in diskdict and
+      diskdict[constants.IDISK_SPINDLES] is not None):
+    raise errors.OpPrereqError("Spindles in instance disks cannot be specified"
+                               " when exclusive storage is not active",
+                               errors.ECODE_INVAL)
+
+
 class LUInstanceRecreateDisks(LogicalUnit):
   """Recreate an instance's missing disks.
 
@@ -526,6 +547,7 @@ class LUInstanceRecreateDisks(LogicalUnit):
   _MODIFYABLE = compat.UniqueFrozenset([
     constants.IDISK_SIZE,
     constants.IDISK_MODE,
+    constants.IDISK_SPINDLES,
     ])
 
   # New or changed disk parameters may have different semantics
@@ -757,6 +779,16 @@ class LUInstanceRecreateDisks(LogicalUnit):
 
     assert not self.glm.is_owned(locking.LEVEL_NODE_ALLOC)
 
+    if self.op.nodes:
+      nodes = self.op.nodes
+    else:
+      nodes = instance.all_nodes
+    excl_stor = compat.any(
+      rpc.GetExclusiveStorageForNodeNames(self.cfg, nodes).values()
+      )
+    for new_params in self.disks.values():
+      CheckSpindlesExclusiveStorage(new_params, excl_stor)
+
   def Exec(self, feedback_fn):
     """Recreate the disks.
 
@@ -802,7 +834,8 @@ class LUInstanceRecreateDisks(LogicalUnit):
         disk.logical_id = new_id
       if changes:
         disk.Update(size=changes.get(constants.IDISK_SIZE, None),
-                    mode=changes.get(constants.IDISK_MODE, None))
+                    mode=changes.get(constants.IDISK_MODE, None),
+                    spindles=changes.get(constants.IDISK_SPINDLES, None))
 
     # change primary node, if needed
     if self.op.nodes:
@@ -847,7 +880,10 @@ def _CheckNodesFreeDiskOnVG(lu, nodenames, vg, requested):
 
   """
   es_flags = rpc.GetExclusiveStorageForNodeNames(lu.cfg, nodenames)
-  nodeinfo = lu.rpc.call_node_info(nodenames, [vg], None, es_flags)
+  # FIXME: This maps everything to storage type 'lvm-vg' to maintain
+  # the current functionality. Refactor to make it more flexible.
+  nodeinfo = lu.rpc.call_node_info(nodenames, [(constants.ST_LVM_VG, vg)], None,
+                                   es_flags)
   for node in nodenames:
     info = nodeinfo[node]
     info.Raise("Cannot get current information from node %s" % node,
@@ -1513,7 +1549,7 @@ class LUInstanceReplaceDisks(LogicalUnit):
       self.op.remote_node = ExpandNodeName(self.cfg, self.op.remote_node)
 
       # Warning: do not remove the locking of the new secondary here
-      # unless DRBD8.AddChildren is changed to work in parallel;
+      # unless DRBD8Dev.AddChildren is changed to work in parallel;
       # currently it doesn't since parallel invocations of
       # FindUnusedMinor will conflict
       self.needed_locks[locking.LEVEL_NODE] = [self.op.remote_node]