On 12/02/2014 03:32 PM, 'Klaus Aehlig' via ganeti-devel wrote:
Extend LUInstanceCreate to also be able to commit an already
reserved instance.
Signed-off-by: Klaus Aehlig <[email protected]>
---
lib/cmdlib/instance_create.py | 106 +++++++++++++++++++++++++++++++++---------
1 file changed, 84 insertions(+), 22 deletions(-)
diff --git a/lib/cmdlib/instance_create.py b/lib/cmdlib/instance_create.py
index 8c93a99..f6a8693 100644
--- a/lib/cmdlib/instance_create.py
+++ b/lib/cmdlib/instance_create.py
@@ -61,7 +61,7 @@ from ganeti.cmdlib.common import \
from ganeti.cmdlib.instance_storage import CalculateFileStorageDir, \
CheckNodesFreeDiskPerVG, CheckRADOSFreeSpace,
CheckSpindlesExclusiveStorage, \
ComputeDiskSizePerVG, CreateDisks, \
- GenerateDiskTemplate, StartInstanceDisks, \
+ GenerateDiskTemplate, CommitDisks, StartInstanceDisks, \
WaitForSync, ComputeDisks, \
TemporaryDisk, ImageDisks, WipeDisks
from ganeti.cmdlib.instance_utils import \
@@ -178,6 +178,10 @@ class LUInstanceCreate(LogicalUnit):
"""Check arguments.
"""
+ if self.op.forthcoming and self.op.commit:
+ raise errors.OpPrereqError("Forthcoming generation and commiting are"
+ " mutually exclusive", errors.ECODE_INVAL)
+
# do not require name_check to ease forward/backward compatibility
# for tools
if self.op.no_install and self.op.start:
@@ -336,13 +340,31 @@ class LUInstanceCreate(LogicalUnit):
"""
self.needed_locks = {}
- # this is just a preventive check, but someone might still add this
- # instance in the meantime; we check again in CheckPrereq
- CheckInstanceExistence(self, self.op.instance_name)
+ if self.op.commit:
+ (uuid, name) = self.cfg.ExpandInstanceName(self.op.instance_name)
+ if name is None:
+ raise errors.OpPrereqError("Instance %s unknown" %
+ self.op.instance_name,
+ errors.ECODE_INVAL)
+ self.op.instance_name = name
+ if not self.cfg.GetInstanceInfo(uuid).forthcoming:
+ raise errors.OpPrereqError("Instance %s (with uuid %s) not forthcoming"
+ % (name, uuid), errors.ECODE_STATE)
Maybe "not forthcoming, but --commit was passed"?
+ logging.debug("Verified that instance %s with uuid %s if forthcoming",
s/if/is ?
+ name, uuid)
+ else:
+ # this is just a preventive check, but someone might still add this
+ # instance in the meantime; we check again in CheckPrereq
+ CheckInstanceExistence(self, self.op.instance_name)
self.add_locks[locking.LEVEL_INSTANCE] = self.op.instance_name
- if self.op.iallocator:
+ if self.op.commit:
Here we probably need `if not ...instance....forthcoming: FAIL`
+ (uuid, _) = self.cfg.ExpandInstanceName(self.op.instance_name)
+ self.needed_locks[locking.LEVEL_NODE] = self.cfg.GetInstanceNodes(uuid)
+ logging.debug("Forthcoming instance %s resides on %s", uuid,
+ self.needed_locks[locking.LEVEL_NODE])
+ elif self.op.iallocator:
# TODO: Find a solution to not lock all nodes in the cluster, e.g. by
# specifying a group on instance creation and then selecting nodes from
# that group
@@ -673,15 +695,44 @@ class LUInstanceCreate(LogicalUnit):
if name in os_defs_ and os_defs_[name] ==
self.op.osparams_private[name]:
del self.op.osparams_private[name]
+ def _GetNodesFromForthcomingInstance(self):
+ """Set nodes as in the forthcoming instance
+
+ """
+ (uuid, name) = self.cfg.ExpandInstanceName(self.op.instance_name)
+ inst = self.cfg.GetInstanceInfo(uuid)
+ self.op.pnode_uuid = inst.primary_node
+ self.op.pnode = self.cfg.GetNodeName(inst.primary_node)
+ sec_nodes = self.cfg.GetInstanceSecondaryNodes(uuid)
+ node_names = [self.op.pnode]
+ if sec_nodes:
+ self.op.snode_uuid = sec_nodes[0]
+ self.op.snode = self.cfg.GetNodeName(sec_nodes[0])
+ node_names.append(self.op.snode)
+ self.LogInfo("Nodes of instance %s: %s", name, node_names)
+
def CheckPrereq(self): # pylint: disable=R0914
"""Check prerequisites.
"""
- CheckInstanceExistence(self, self.op.instance_name)
+ owned_nodes = frozenset(self.owned_locks(locking.LEVEL_NODE))
+
+ if self.op.commit:
+ # Check that the instance is still on the cluster and
+ # still resides on the nodes we acquired.
+ (uuid, _) = self.cfg.ExpandInstanceName(self.op.instance_name)
+ required_nodes = self.cfg.GetInstanceNodes(uuid)
+ if not owned_nodes.issuperset(required_nodes):
+ raise errors.OpPrereqError("Forthcoming instance %s nodes changed"
+ " since locks were acquired; retry the"
+ " operation" % self.op.instance_name,
+ errors.ECODE_STATE)
+ else:
+ CheckInstanceExistence(self, self.op.instance_name)
+
# Check that the optimistically acquired groups are correct wrt the
# acquired nodes
owned_groups = frozenset(self.owned_locks(locking.LEVEL_NODEGROUP))
- owned_nodes = frozenset(self.owned_locks(locking.LEVEL_NODE))
cur_groups = list(self.cfg.GetNodeGroupsFromNodes(owned_nodes))
if not owned_groups.issuperset(cur_groups):
raise errors.OpPrereqError("New instance %s's node groups changed since"
@@ -807,7 +858,10 @@ class LUInstanceCreate(LogicalUnit):
#### allocator run
if self.op.iallocator is not None:
- self._RunAllocator()
+ if self.op.commit:
+ self._GetNodesFromForthcomingInstance()
+ else:
+ self._RunAllocator()
# Release all unneeded node locks
keep_locks = filter(None, [self.op.pnode_uuid, self.op.snode_uuid,
@@ -1391,23 +1445,31 @@ class LUInstanceCreate(LogicalUnit):
else:
network_port = None
- instance_uuid = self.cfg.GenerateUniqueID(self.proc.GetECId())
+ if self.op.commit:
+ (instance_uuid, _) = self.cfg.ExpandInstanceName(self.op.instance_name)
+ else:
+ instance_uuid = self.cfg.GenerateUniqueID(self.proc.GetECId())
# This is ugly but we got a chicken-egg problem here
# We can only take the group disk parameters, as the instance
# has no disks yet (we are generating them right here).
nodegroup = self.cfg.GetNodeGroup(self.pnode.group)
- disks = GenerateDiskTemplate(self,
- self.op.disk_template,
- instance_uuid, self.pnode.uuid,
- self.secondaries,
- self.disks,
- self.instance_file_storage_dir,
- self.op.file_driver,
- 0,
- feedback_fn,
- self.cfg.GetGroupDiskParams(nodegroup),
- forthcoming=self.op.forthcoming)
+
+ if self.op.commit:
+ disks = self.cfg.GetInstanceDisks(instance_uuid)
+ CommitDisks(disks)
+ else:
+ disks = GenerateDiskTemplate(self,
+ self.op.disk_template,
+ instance_uuid, self.pnode.uuid,
+ self.secondaries,
+ self.disks,
+ self.instance_file_storage_dir,
+ self.op.file_driver,
+ 0,
+ feedback_fn,
+ self.cfg.GetGroupDiskParams(nodegroup),
+ forthcoming=self.op.forthcoming)
if self.op.os_type is None:
os_type = ""
@@ -1460,11 +1522,11 @@ class LUInstanceCreate(LogicalUnit):
raise
feedback_fn("adding instance %s to cluster config" %
self.op.instance_name)
- self.cfg.AddInstance(iobj, self.proc.GetECId())
+ self.cfg.AddInstance(iobj, self.proc.GetECId(), replaces=self.op.commit)
feedback_fn("adding disks to cluster config")
for disk in disks:
- self.cfg.AddInstanceDisk(iobj.uuid, disk)
+ self.cfg.AddInstanceDisk(iobj.uuid, disk, replaces=self.op.commit)
if self.op.forthcoming:
feedback_fn("Instance is forthcoming; not creating the actual instance")
--
Niklas Hambüchen
Google Germany GmbH, Dienerstr. 12, 80331 Muenchen
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschaeftsfuehrer: Graham Law, Christine Elizabeth Flores