LoadNodeEvacResult, CheckIAllocatorOrNode, CheckParamsNotGlobal, \
IsExclusiveStorageEnabledNode, CheckHVParams, CheckOSParams, \
AnnotateDiskParams, GetUpdatedParams, ExpandInstanceUuidAndName, \
- ComputeIPolicySpecViolation, CheckInstanceState, ExpandNodeUuidAndName
+ ComputeIPolicySpecViolation, CheckInstanceState, ExpandNodeUuidAndName, \
+ CheckDiskTemplateEnabled
from ganeti.cmdlib.instance_storage import CreateDisks, \
CheckNodesFreeDiskPerVG, WipeDisks, WipeOrCleanupDisks, WaitForSync, \
IsExclusiveStorageEnabledNodeUuid, CreateSingleBlockDev, ComputeDisks, \
HTYPE = constants.HTYPE_INSTANCE
REQ_BGL = False
- def CheckArguments(self):
- """Check arguments.
+ def _CheckDiskTemplateValid(self):
+ """Checks validity of disk template.
"""
- # do not require name_check to ease forward/backward compatibility
- # for tools
- if self.op.no_install and self.op.start:
- self.LogInfo("No-installation mode selected, disabling startup")
- self.op.start = False
- # validate/normalize the instance name
- self.op.instance_name = \
- netutils.Hostname.GetNormalizedName(self.op.instance_name)
-
- if self.op.ip_check and not self.op.name_check:
- # TODO: make the ip check more flexible and not depend on the name check
- raise errors.OpPrereqError("Cannot do IP address check without a name"
- " check", errors.ECODE_INVAL)
+ cluster = self.cfg.GetClusterInfo()
+ if self.op.disk_template is None:
+ # FIXME: It would be better to take the default disk template from the
+ # ipolicy, but for the ipolicy we need the primary node, which we get from
+ # the iallocator, which wants the disk template as input. To solve this
+ # chicken-and-egg problem, it should be possible to specify just a node
+ # group from the iallocator and take the ipolicy from that.
+ self.op.disk_template = cluster.enabled_disk_templates[0]
+ CheckDiskTemplateEnabled(cluster, self.op.disk_template)
- # check nics' parameter names
- for nic in self.op.nics:
- utils.ForceDictType(nic, constants.INIC_PARAMS_TYPES)
- # check that NIC's parameters names are unique and valid
- utils.ValidateDeviceNames("NIC", self.op.nics)
+ def _CheckDiskArguments(self):
+ """Checks validity of disk-related arguments.
+ """
# check that disk's names are unique and valid
utils.ValidateDeviceNames("disk", self.op.disks)
- cluster = self.cfg.GetClusterInfo()
- if not self.op.disk_template in cluster.enabled_disk_templates:
- raise errors.OpPrereqError("Cannot create an instance with disk template"
- " '%s', because it is not enabled in the"
- " cluster. Enabled disk templates are: %s." %
- (self.op.disk_template,
- ",".join(cluster.enabled_disk_templates)))
+ self._CheckDiskTemplateValid()
# check disks. parameter names and consistent adopt/no-adopt strategy
has_adopt = has_no_adopt = False
self.adopt_disks = has_adopt
+ def CheckArguments(self):
+ """Check arguments.
+
+ """
+ # do not require name_check to ease forward/backward compatibility
+ # for tools
+ if self.op.no_install and self.op.start:
+ self.LogInfo("No-installation mode selected, disabling startup")
+ self.op.start = False
+ # validate/normalize the instance name
+ self.op.instance_name = \
+ netutils.Hostname.GetNormalizedName(self.op.instance_name)
+
+ if self.op.ip_check and not self.op.name_check:
+ # TODO: make the ip check more flexible and not depend on the name check
+ raise errors.OpPrereqError("Cannot do IP address check without a name"
+ " check", errors.ECODE_INVAL)
+
+ # check nics' parameter names
+ for nic in self.op.nics:
+ utils.ForceDictType(nic, constants.INIC_PARAMS_TYPES)
+ # check that NIC's parameters names are unique and valid
+ utils.ValidateDeviceNames("NIC", self.op.nics)
+
+ self._CheckDiskArguments()
+
# instance name verification
if self.op.name_check:
self.hostname = _CheckHostnameSane(self, self.op.instance_name)
raise errors.OpPrereqError("Invalid file driver name '%s'" %
self.op.file_driver, errors.ECODE_INVAL)
- if self.op.disk_template == constants.DT_FILE:
- opcodes.RequireFileStorage()
- elif self.op.disk_template == constants.DT_SHARED_FILE:
- opcodes.RequireSharedFileStorage()
-
### Node/iallocator related checks
CheckIAllocatorOrNode(self, "iallocator", "pnode")
if self.needed_locks[locking.LEVEL_NODE] is not locking.ALL_SET:
self.needed_locks[locking.LEVEL_NODE].append(self.op.src_node_uuid)
if not os.path.isabs(src_path):
- self.op.src_path = src_path = \
+ self.op.src_path = \
utils.PathJoin(pathutils.EXPORT_DIR, src_path)
self.needed_locks[locking.LEVEL_NODE_RES] = \
locked_nodes = self.owned_locks(locking.LEVEL_NODE)
exp_list = self.rpc.call_export_list(locked_nodes)
found = False
- for node in exp_list:
- if exp_list[node].fail_msg:
+ for node_uuid in exp_list:
+ if exp_list[node_uuid].fail_msg:
continue
- if self.op.src_path in exp_list[node].payload:
+ if self.op.src_path in exp_list[node_uuid].payload:
found = True
- self.op.src_node = node
- self.op.src_node_uuid = self.cfg.GetNodeInfoByName(node).uuid
+ self.op.src_node = self.cfg.GetNodeInfo(node_uuid).name
+ self.op.src_node_uuid = node_uuid
self.op.src_path = utils.PathJoin(pathutils.EXPORT_DIR,
self.op.src_path)
break
"""
self.op.os_type = einfo.get(constants.INISECT_EXP, "os")
- if self.op.disk_template is None:
- if einfo.has_option(constants.INISECT_INS, "disk_template"):
- self.op.disk_template = einfo.get(constants.INISECT_INS,
- "disk_template")
- if self.op.disk_template not in constants.DISK_TEMPLATES:
- raise errors.OpPrereqError("Disk template specified in configuration"
- " file is not one of the allowed values:"
- " %s" %
- " ".join(constants.DISK_TEMPLATES),
- errors.ECODE_INVAL)
- else:
- raise errors.OpPrereqError("No disk template specified and the export"
- " is missing the disk_template information",
- errors.ECODE_INVAL)
-
if not self.op.disks:
disks = []
# TODO: import the disk iv_name too
if einfo.has_option(constants.INISECT_INS, "nic%d_mac" % idx):
ndict = {}
for name in list(constants.NICS_PARAMETERS) + ["ip", "mac"]:
- v = einfo.get(constants.INISECT_INS, "nic%d_%s" % (idx, name))
- ndict[name] = v
+ nic_param_name = "nic%d_%s" % (idx, name)
+ if einfo.has_option(constants.INISECT_INS, nic_param_name):
+ v = einfo.get(constants.INISECT_INS, nic_param_name)
+ ndict[name] = v
nics.append(ndict)
else:
break
self.op.instance_name)
instance = self.cfg.GetInstanceInfo(self.op.instance_uuid)
assert instance is not None
+
+ # It should actually not happen that an instance is running with a disabled
+ # disk template, but in case it does, the renaming of file-based instances
+ # will fail horribly. Thus, we test it before.
+ if (instance.disk_template in constants.DTS_FILEBASED and
+ self.op.new_name != instance.name):
+ CheckDiskTemplateEnabled(self.cfg.GetClusterInfo(),
+ instance.disk_template)
+
CheckNodeOnline(self, instance.primary_node)
CheckInstanceState(self, instance, INSTANCE_NOT_RUNNING,
msg="cannot rename")
(self.op.target_node_uuid, self.op.target_node) = \
ExpandNodeUuidAndName(self.cfg, self.op.target_node_uuid,
self.op.target_node)
- self.needed_locks[locking.LEVEL_NODE] = [self.op.target_node]
+ self.needed_locks[locking.LEVEL_NODE] = [self.op.target_node_uuid]
self.needed_locks[locking.LEVEL_NODE_RES] = []
self.recalculate_locks[locking.LEVEL_NODE] = constants.LOCKS_APPEND
" pnode/snode while others do not",
errors.ECODE_INVAL)
- if self.op.iallocator is None:
+ if not has_nodes and self.op.iallocator is None:
default_iallocator = self.cfg.GetDefaultIAllocator()
- if default_iallocator and has_nodes:
+ if default_iallocator:
self.op.iallocator = default_iallocator
else:
raise errors.OpPrereqError("No iallocator or nodes on the instances"
for inst in self.op.instances:
(inst.pnode_uuid, inst.pnode) = \
ExpandNodeUuidAndName(self.cfg, inst.pnode_uuid, inst.pnode)
- nodeslist.append(inst.pnode)
+ nodeslist.append(inst.pnode_uuid)
if inst.snode is not None:
(inst.snode_uuid, inst.snode) = \
ExpandNodeUuidAndName(self.cfg, inst.snode_uuid, inst.snode)
- nodeslist.append(inst.snode)
+ nodeslist.append(inst.snode_uuid)
self.needed_locks[locking.LEVEL_NODE] = nodeslist
# Lock resources of instance's primary and secondary nodes (copy to
"""Check prerequisite.
"""
- cluster = self.cfg.GetClusterInfo()
- default_vg = self.cfg.GetVGName()
- ec_id = self.proc.GetECId()
+ if self.op.iallocator:
+ cluster = self.cfg.GetClusterInfo()
+ default_vg = self.cfg.GetVGName()
+ ec_id = self.proc.GetECId()
- if self.op.opportunistic_locking:
- # Only consider nodes for which a lock is held
- node_whitelist = self.cfg.GetNodeNames(
- list(self.owned_locks(locking.LEVEL_NODE)))
- else:
- node_whitelist = None
+ if self.op.opportunistic_locking:
+ # Only consider nodes for which a lock is held
+ node_whitelist = self.cfg.GetNodeNames(
+ list(self.owned_locks(locking.LEVEL_NODE)))
+ else:
+ node_whitelist = None
- insts = [_CreateInstanceAllocRequest(op, ComputeDisks(op, default_vg),
- _ComputeNics(op, cluster, None,
- self.cfg, ec_id),
- _ComputeFullBeParams(op, cluster),
- node_whitelist)
- for op in self.op.instances]
+ insts = [_CreateInstanceAllocRequest(op, ComputeDisks(op, default_vg),
+ _ComputeNics(op, cluster, None,
+ self.cfg, ec_id),
+ _ComputeFullBeParams(op, cluster),
+ node_whitelist)
+ for op in self.op.instances]
- req = iallocator.IAReqMultiInstanceAlloc(instances=insts)
- ial = iallocator.IAllocator(self.cfg, self.rpc, req)
+ req = iallocator.IAReqMultiInstanceAlloc(instances=insts)
+ ial = iallocator.IAllocator(self.cfg, self.rpc, req)
- ial.Run(self.op.iallocator)
+ ial.Run(self.op.iallocator)
- if not ial.success:
- raise errors.OpPrereqError("Can't compute nodes using"
- " iallocator '%s': %s" %
- (self.op.iallocator, ial.info),
- errors.ECODE_NORES)
+ if not ial.success:
+ raise errors.OpPrereqError("Can't compute nodes using"
+ " iallocator '%s': %s" %
+ (self.op.iallocator, ial.info),
+ errors.ECODE_NORES)
- self.ia_result = ial.result
+ self.ia_result = ial.result
if self.op.dry_run:
self.dry_run_result = objects.FillDict(self._ConstructPartialResult(), {
"""Contructs the partial result.
"""
- (allocatable, failed) = self.ia_result
+ if self.op.iallocator:
+ (allocatable, failed_insts) = self.ia_result
+ allocatable_insts = map(compat.fst, allocatable)
+ else:
+ allocatable_insts = [op.instance_name for op in self.op.instances]
+ failed_insts = []
+
return {
- opcodes.OpInstanceMultiAlloc.ALLOCATABLE_KEY:
- map(compat.fst, allocatable),
- opcodes.OpInstanceMultiAlloc.FAILED_KEY: failed,
+ opcodes.OpInstanceMultiAlloc.ALLOCATABLE_KEY: allocatable_insts,
+ opcodes.OpInstanceMultiAlloc.FAILED_KEY: failed_insts,
}
def Exec(self, feedback_fn):
"""Executes the opcode.
"""
- op2inst = dict((op.instance_name, op) for op in self.op.instances)
- (allocatable, failed) = self.ia_result
-
jobs = []
- for (name, node_names) in allocatable:
- op = op2inst.pop(name)
+ if self.op.iallocator:
+ op2inst = dict((op.instance_name, op) for op in self.op.instances)
+ (allocatable, failed) = self.ia_result
- (op.pnode_uuid, op.pnode) = \
- ExpandNodeUuidAndName(self.cfg, None, node_names[0])
- if len(node_names) > 1:
- (op.snode_uuid, op.snode) = \
- ExpandNodeUuidAndName(self.cfg, None, node_names[1])
+ for (name, node_names) in allocatable:
+ op = op2inst.pop(name)
- jobs.append([op])
+ (op.pnode_uuid, op.pnode) = \
+ ExpandNodeUuidAndName(self.cfg, None, node_names[0])
+ if len(node_names) > 1:
+ (op.snode_uuid, op.snode) = \
+ ExpandNodeUuidAndName(self.cfg, None, node_names[1])
- missing = set(op2inst.keys()) - set(failed)
- assert not missing, \
- "Iallocator did return incomplete result: %s" % utils.CommaJoin(missing)
+ jobs.append([op])
+
+ missing = set(op2inst.keys()) - set(failed)
+ assert not missing, \
+ "Iallocator did return incomplete result: %s" % \
+ utils.CommaJoin(missing)
+ else:
+ jobs.extend([op] for op in self.op.instances)
return ResultWithJobs(jobs, **self._ConstructPartialResult())
def CheckArguments(self):
if not (self.op.nics or self.op.disks or self.op.disk_template or
self.op.hvparams or self.op.beparams or self.op.os_name or
- self.op.offline is not None or self.op.runtime_mem or
- self.op.pnode):
+ self.op.osparams or self.op.offline is not None or
+ self.op.runtime_mem or self.op.pnode):
raise errors.OpPrereqError("No changes submitted", errors.ECODE_INVAL)
if self.op.hvparams:
self.instance.disk_template,
errors.ECODE_INVAL)
+ if not self.cluster.IsDiskTemplateEnabled(self.instance.disk_template):
+ raise errors.OpPrereqError("Disk template '%s' is not enabled for this"
+ " cluster." % self.instance.disk_template)
+
if (self.instance.disk_template,
self.op.disk_template) not in self._DISK_CONVERSIONS:
raise errors.OpPrereqError("Unsupported disk template conversion from"