setattr(op, name, val)
+def _CheckGlobalHvParams(params):
+ """Validates that given hypervisor params are not global ones.
+
+ This will ensure that instances don't get customised versions of
+ global params.
+
+ """
+ used_globals = constants.HVC_GLOBALS.intersection(params)
+ if used_globals:
+ msg = ("The following hypervisor parameters are global and cannot"
+ " be customized at instance level, please modify them at"
+ " cluster level: %s" % ", ".join(used_globals))
+ raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
+
+
def _CheckNodeOnline(lu, node):
"""Ensure that a given node is online.
if brlist:
result = lu.rpc.call_bridges_exist(target_node, brlist)
result.Raise("Error checking bridges on destination node '%s'" %
- target_node, prereq=True)
+ target_node, prereq=True, ecode=errors.ECODE_ENVIRON)
def _CheckInstanceBridgesExist(lu, instance, node=None):
result = rpc.call_blockdev_getmirrorstatus(node_name, instance.disks)
result.Raise("Failed to get disk status from node %s" % node_name,
- prereq=prereq)
+ prereq=prereq, ecode=errors.ECODE_ENVIRON)
for idx, bdev_status in enumerate(result.payload):
if bdev_status and bdev_status.ldisk_status == constants.LDS_FAULTY:
_ErrorIf(test, self.ENODESETUP, node, "node setup error: %s",
"; ".join(test))
+ # check pv names
+ if vg_name is not None:
+ pvlist = node_result.get(constants.NV_PVLIST, None)
+ test = pvlist is None
+ _ErrorIf(test, self.ENODELVM, node, "Can't get PV list from node")
+ if not test:
+ # check that ':' is not present in PV names, since it's a
+ # special character for lvcreate (denotes the range of PEs to
+ # use on the PV)
+ for size, pvname, owner_vg in pvlist:
+ test = ":" in pvname
+ _ErrorIf(test, self.ENODELVM, node, "Invalid character ':' in PV"
+ " '%s' of VG '%s'", pvname, owner_vg)
+
def _VerifyInstance(self, instance, instanceconfig, node_vol_is,
node_instance, n_offline):
"""Verify an instance.
if vg_name is not None:
node_verify_param[constants.NV_VGLIST] = None
node_verify_param[constants.NV_LVLIST] = vg_name
+ node_verify_param[constants.NV_PVLIST] = [vg_name]
node_verify_param[constants.NV_DRBDLIST] = None
all_nvinfo = self.rpc.call_node_verify(nodelist, node_verify_param,
self.cfg.GetClusterName())
"""Verify that the passed name is a valid one.
"""
- hostname = utils.HostInfo(self.op.name)
+ hostname = utils.GetHostInfo(self.op.name)
new_name = hostname.name
self.ip = new_ip = hostname.ip
self.new_nicparams = objects.FillDict(
cluster.nicparams[constants.PP_DEFAULT], self.op.nicparams)
objects.NIC.CheckParameterSyntax(self.new_nicparams)
+ nic_errors = []
+
+ # check all instances for consistency
+ for instance in self.cfg.GetAllInstancesInfo().values():
+ for nic_idx, nic in enumerate(instance.nics):
+ params_copy = copy.deepcopy(nic.nicparams)
+ params_filled = objects.FillDict(self.new_nicparams, params_copy)
+
+ # check parameter syntax
+ try:
+ objects.NIC.CheckParameterSyntax(params_filled)
+ except errors.ConfigurationError, err:
+ nic_errors.append("Instance %s, nic/%d: %s" %
+ (instance.name, nic_idx, err))
+
+ # if we're moving instances to routed, check that they have an ip
+ target_mode = params_filled[constants.NIC_MODE]
+ if target_mode == constants.NIC_MODE_ROUTED and not nic.ip:
+ nic_errors.append("Instance %s, nic/%d: routed nick with no ip" %
+ (instance.name, nic_idx))
+ if nic_errors:
+ raise errors.OpPrereqError("Cannot apply the change, errors:\n%s" %
+ "\n".join(nic_errors))
# hypervisor list/parameters
self.new_hvparams = objects.FillDict(cluster.hvparams, {})
_RedistributeAncillaryFiles(self)
-def _WaitForSync(lu, instance, oneshot=False, unlock=False):
+def _WaitForSync(lu, instance, oneshot=False):
"""Sleep and poll for an instance's disk to sync.
"""
for dev in instance.disks:
lu.cfg.SetDiskID(dev, node)
+ # TODO: Convert to utils.Retry
+
retries = 0
degr_retries = 10 # in seconds, as we sleep 1 second each time
while True:
node_name = self.op.node_name
cfg = self.cfg
- dns_data = utils.HostInfo(node_name)
+ dns_data = utils.GetHostInfo(node_name)
node = dns_data.name
primary_ip = self.op.primary_ip = dns_data.ip
result = self.rpc.call_node_has_ip_address(new_node.name,
new_node.secondary_ip)
result.Raise("Failure checking secondary ip on node %s" % new_node.name,
- prereq=True)
+ prereq=True, ecode=errors.ECODE_ENVIRON)
if not result.payload:
raise errors.OpExecError("Node claims it doesn't have the secondary ip"
" you gave (%s). Please fix and re-run this"
" candidate status: %s" % msg)
else:
_RedistributeAncillaryFiles(self, additional_nodes=[node])
- self.context.AddNode(new_node)
+ self.context.AddNode(new_node, self.proc.GetECId())
class LUSetNodeParams(LogicalUnit):
"""
nodeinfo = lu.rpc.call_node_info([node], lu.cfg.GetVGName(), hypervisor_name)
- nodeinfo[node].Raise("Can't get data from node %s" % node, prereq=True)
+ nodeinfo[node].Raise("Can't get data from node %s" % node,
+ prereq=True, ecode=errors.ECODE_ENVIRON)
free_mem = nodeinfo[node].payload.get('memory_free', None)
if not isinstance(free_mem, int):
raise errors.OpPrereqError("Can't compute free memory on node %s, result"
instance.name,
instance.hypervisor)
remote_info.Raise("Error checking node %s" % instance.primary_node,
- prereq=True)
+ prereq=True, ecode=errors.ECODE_ENVIRON)
if not remote_info.payload: # not running already
_CheckNodeFreeMemory(self, instance.primary_node,
"starting instance %s" % instance.name,
instance.name,
instance.hypervisor)
remote_info.Raise("Error checking node %s" % instance.primary_node,
- prereq=True)
+ prereq=True, ecode=errors.ECODE_ENVIRON)
if remote_info.payload:
raise errors.OpPrereqError("Instance '%s' is running on the node %s" %
(self.op.instance_name,
self.op.pnode, errors.ECODE_NOENT)
result = self.rpc.call_os_get(pnode.name, self.op.os_type)
result.Raise("OS '%s' not in supported OS list for primary node %s" %
- (self.op.os_type, pnode.name), prereq=True)
+ (self.op.os_type, pnode.name),
+ prereq=True, ecode=errors.ECODE_INVAL)
if not self.op.force_variant:
_CheckOSVariant(result.payload, self.op.os_type)
instance.name,
instance.hypervisor)
remote_info.Raise("Error checking node %s" % instance.primary_node,
- prereq=True)
+ prereq=True, ecode=errors.ECODE_ENVIRON)
if remote_info.payload:
raise errors.OpPrereqError("Instance '%s' is running on the node %s" %
(self.op.instance_name,
instance.name,
instance.hypervisor)
remote_info.Raise("Error checking node %s" % instance.primary_node,
- prereq=True)
+ prereq=True, ecode=errors.ECODE_ENVIRON)
if remote_info.payload:
raise errors.OpPrereqError("Instance '%s' is running on the node %s" %
(self.op.instance_name,
self.instance = instance
# new name verification
- name_info = utils.HostInfo(self.op.new_name)
+ name_info = utils.GetHostInfo(self.op.new_name)
self.op.new_name = new_name = name_info.name
instance_list = self.cfg.GetInstanceList()
"hvparams",
] + _SIMPLE_FIELDS +
["hv/%s" % name
- for name in constants.HVS_PARAMETERS] +
+ for name in constants.HVS_PARAMETERS
+ if name not in constants.HVC_GLOBALS] +
["be/%s" % name
for name in constants.BES_PARAMETERS])
_FIELDS_DYNAMIC = utils.FieldSet("oper_state", "oper_ram", "status")
cluster = self.cfg.GetClusterInfo()
for instance in instance_list:
iout = []
- i_hv = cluster.FillHV(instance)
+ i_hv = cluster.FillHV(instance, skip_globals=True)
i_be = cluster.FillBE(instance)
i_nicp = [objects.FillDict(cluster.nicparams[constants.PP_DEFAULT],
nic.nicparams) for nic in instance.nics]
elif field == "hvparams":
val = i_hv
elif (field.startswith(HVPREFIX) and
- field[len(HVPREFIX):] in constants.HVS_PARAMETERS):
+ field[len(HVPREFIX):] in constants.HVS_PARAMETERS and
+ field[len(HVPREFIX):] not in constants.HVC_GLOBALS):
val = i_hv.get(field[len(HVPREFIX):], None)
elif field == "beparams":
val = i_be
_CheckNodeNotDrained(self, target_node)
result = self.rpc.call_instance_migratable(instance.primary_node,
instance)
- result.Raise("Can't migrate, please use failover", prereq=True)
+ result.Raise("Can't migrate, please use failover",
+ prereq=True, ecode=errors.ECODE_STATE)
self.instance = instance
False)
abort_msg = abort_result.fail_msg
if abort_msg:
- logging.error("Aborting migration failed on target node %s: %s" %
- (target_node, abort_msg))
+ logging.error("Aborting migration failed on target node %s: %s",
+ target_node, abort_msg)
# Don't raise an exception here, as we stil have to try to revert the
# disk status, even if this step failed.
if msg:
logging.error("Instance pre-migration failed, trying to revert"
" disk status: %s", msg)
+ self.feedback_fn("Pre-migration failed, aborting")
self._AbortMigration()
self._RevertDiskStatus()
raise errors.OpExecError("Could not pre-migrate instance %s: %s" %
if msg:
logging.error("Instance migration failed, trying to revert"
" disk status: %s", msg)
+ self.feedback_fn("Migration failed, aborting")
self._AbortMigration()
self._RevertDiskStatus()
raise errors.OpExecError("Could not migrate instance %s: %s" %
msg = result.fail_msg
if msg:
logging.error("Instance migration succeeded, but finalization failed:"
- " %s" % msg)
+ " %s", msg)
raise errors.OpExecError("Could not finalize instance migration: %s" %
msg)
"""
results = []
for val in exts:
- new_id = lu.cfg.GenerateUniqueID()
+ new_id = lu.cfg.GenerateUniqueID(lu.proc.GetECId())
results.append("%s%s" % (new_id, val))
return results
"""
port = lu.cfg.AllocatePort()
vgname = lu.cfg.GetVGName()
- shared_secret = lu.cfg.GenerateDRBDSecret()
+ shared_secret = lu.cfg.GenerateDRBDSecret(lu.proc.GetECId())
dev_data = objects.Disk(dev_type=constants.LD_LV, size=size,
logical_id=(vgname, names[0]))
dev_meta = objects.Disk(dev_type=constants.LD_LV, size=128,
hv_type = hypervisor.GetHypervisor(self.op.hypervisor)
hv_type.CheckParameterSyntax(filled_hvp)
self.hv_full = filled_hvp
+ # check that we don't specify global parameters on an instance
+ _CheckGlobalHvParams(self.op.hvparams)
# fill and remember the beparams dict
utils.ForceDictType(self.op.beparams, constants.BES_PARAMETER_TYPES)
#### instance parameters check
# instance name verification
- hostname1 = utils.HostInfo(self.op.instance_name)
+ hostname1 = utils.GetHostInfo(self.op.instance_name)
self.op.instance_name = instance_name = hostname1.name
# this is just a preventive check, but someone might still add this
errors.ECODE_INVAL)
nic_ip = ip
- # TODO: check the ip for uniqueness !!
+ # TODO: check the ip address for uniqueness
if nic_mode == constants.NIC_MODE_ROUTED and not nic_ip:
raise errors.OpPrereqError("Routed nic mode requires an ip address",
errors.ECODE_INVAL)
raise errors.OpPrereqError("Invalid MAC address specified: %s" %
mac, errors.ECODE_INVAL)
else:
- # or validate/reserve the current one
- if self.cfg.IsMacInUse(mac):
+ try:
+ self.cfg.ReserveMAC(mac, self.proc.GetECId())
+ except errors.ReservationError:
raise errors.OpPrereqError("MAC address %s already in use"
" in cluster" % mac,
errors.ECODE_NOTUNIQUE)
# creation job will fail.
for nic in self.nics:
if nic.mac in (constants.VALUE_AUTO, constants.VALUE_GENERATE):
- nic.mac = self.cfg.GenerateMAC()
+ nic.mac = self.cfg.GenerateMAC(self.proc.GetECId())
#### allocator run
# os verification
result = self.rpc.call_os_get(pnode.name, self.op.os_type)
result.Raise("OS '%s' not in supported os list for primary node %s" %
- (self.op.os_type, pnode.name), prereq=True)
+ (self.op.os_type, pnode.name),
+ prereq=True, ecode=errors.ECODE_INVAL)
if not self.op.force_variant:
_CheckOSVariant(result.payload, self.op.os_type)
feedback_fn("adding instance %s to cluster config" % instance)
- self.cfg.AddInstance(iobj)
+ self.cfg.AddInstance(iobj, self.proc.GetECId())
+
# Declare that we don't want to remove the instance lock anymore, as we've
# added the instance to the config
del self.remove_locks[locking.LEVEL_INSTANCE]
# This can fail as the old devices are degraded and _WaitForSync
# does a combined result over all disks, so we don't check its return value
self.lu.LogStep(5, steps_total, "Sync devices")
- _WaitForSync(self.lu, self.instance, unlock=True)
+ _WaitForSync(self.lu, self.instance)
# Check all devices manually
self._CheckDevices(self.instance.primary_node, iv_names)
minors = self.cfg.AllocateDRBDMinor([self.new_node
for dev in self.instance.disks],
self.instance.name)
- logging.debug("Allocated minors %r" % (minors,))
+ logging.debug("Allocated minors %r", minors)
iv_names = {}
for idx, (dev, new_minor) in enumerate(zip(self.instance.disks, minors)):
# This can fail as the old devices are degraded and _WaitForSync
# does a combined result over all disks, so we don't check its return value
self.lu.LogStep(5, steps_total, "Sync devices")
- _WaitForSync(self.lu, self.instance, unlock=True)
+ _WaitForSync(self.lu, self.instance)
# Check all devices manually
self._CheckDevices(self.instance.primary_node, iv_names)
}
def _CheckFaultyDisks(self, instance, node_name):
- if _FindFaultyInstanceDisks(self.cfg, self.rpc, instance,
- node_name, True):
- raise errors.OpPrereqError("Instance '%s' has faulty disks on"
- " node '%s'" % (instance.name, node_name),
- errors.ECODE_STATE)
+ """Ensure faulty disks abort the opcode or at least warn."""
+ try:
+ if _FindFaultyInstanceDisks(self.cfg, self.rpc, instance,
+ node_name, True):
+ raise errors.OpPrereqError("Instance '%s' has faulty disks on"
+ " node '%s'" % (instance.name, node_name),
+ errors.ECODE_STATE)
+ except errors.OpPrereqError, err:
+ if self.op.ignore_consistency:
+ self.proc.LogWarning(str(err.args[0]))
+ else:
+ raise
def CheckPrereq(self):
"""Check prerequisites.
# Check whether any instance on this node has faulty disks
for inst in _GetNodeInstances(self.cfg, self.op.node_name):
+ if not inst.admin_up:
+ continue
check_nodes = set(inst.all_nodes)
check_nodes.discard(self.op.node_name)
for inst_node_name in check_nodes:
"hypervisor": instance.hypervisor,
"network_port": instance.network_port,
"hv_instance": instance.hvparams,
- "hv_actual": cluster.FillHV(instance),
+ "hv_actual": cluster.FillHV(instance, skip_globals=True),
"be_instance": instance.beparams,
"be_actual": cluster.FillBE(instance),
"serial_no": instance.serial_no,
self.op.hvparams or self.op.beparams):
raise errors.OpPrereqError("No changes submitted", errors.ECODE_INVAL)
+ if self.op.hvparams:
+ _CheckGlobalHvParams(self.op.hvparams)
+
# Disk validation
disk_addremove = 0
for disk_op, disk_dict in self.op.disks:
continue
if nic_op != constants.DDM_ADD:
# an existing nic
+ if not instance.nics:
+ raise errors.OpPrereqError("Invalid NIC index %s, instance has"
+ " no NICs" % nic_op,
+ errors.ECODE_INVAL)
if nic_op < 0 or nic_op >= len(instance.nics):
raise errors.OpPrereqError("Invalid NIC index %s, valid values"
" are 0 to %d" %
- (nic_op, len(instance.nics)),
+ (nic_op, len(instance.nics) - 1),
errors.ECODE_INVAL)
old_nic_params = instance.nics[nic_op].nicparams
old_nic_ip = instance.nics[nic_op].ip
errors.ECODE_INVAL)
elif nic_mac in (constants.VALUE_AUTO, constants.VALUE_GENERATE):
# otherwise generate the mac
- nic_dict['mac'] = self.cfg.GenerateMAC()
+ nic_dict['mac'] = self.cfg.GenerateMAC(self.proc.GetECId())
else:
# or validate/reserve the current one
- if self.cfg.IsMacInUse(nic_mac):
+ try:
+ self.cfg.ReserveMAC(nic_mac, self.proc.GetECId())
+ except errors.ReservationError:
raise errors.OpPrereqError("MAC address %s already in use"
" in cluster" % nic_mac,
errors.ECODE_NOTUNIQUE)
for key in 'mac', 'ip':
if key in nic_dict:
setattr(instance.nics[nic_op], key, nic_dict[key])
- if nic_op in self.nic_pnew:
- instance.nics[nic_op].nicparams = self.nic_pnew[nic_op]
+ if nic_op in self.nic_pinst:
+ instance.nics[nic_op].nicparams = self.nic_pinst[nic_op]
for key, val in nic_dict.iteritems():
result.append(("nic.%s/%d" % (key, nic_op), val))