"prealloc_wipe_disks": cluster.prealloc_wipe_disks,
"hidden_os": cluster.hidden_os,
"blacklisted_os": cluster.blacklisted_os,
+ "enabled_disk_templates": cluster.enabled_disk_templates,
}
return result
def ExpandNames(self):
if self.op.instances:
- self.wanted_names = GetWantedInstances(self, self.op.instances)
+ (_, self.wanted_names) = GetWantedInstances(self, self.op.instances)
# Not getting the node allocation lock as only a specific set of
# instances (and their nodes) is going to be acquired
self.needed_locks = {
self.wanted_names = self.owned_locks(locking.LEVEL_INSTANCE)
self.wanted_instances = \
- map(compat.snd, self.cfg.GetMultiInstanceInfo(self.wanted_names))
+ map(compat.snd, self.cfg.GetMultiInstanceInfoByName(self.wanted_names))
def _EnsureChildSizes(self, disk):
"""Ensure children of the disk have the needed disk size.
(netmask), errors.ECODE_INVAL)
+def CheckFileBasedStoragePathVsEnabledDiskTemplates(
+ logging_warn_fn, file_storage_dir, enabled_disk_templates,
+ file_disk_template):
+ """Checks whether the given file-based storage directory is acceptable.
+
+ Note: This function is public, because it is also used in bootstrap.py.
+
+ @type logging_warn_fn: function
+ @param logging_warn_fn: function which accepts a string and logs it
+ @type file_storage_dir: string
+ @param file_storage_dir: the directory to be used for file-based instances
+ @type enabled_disk_templates: list of string
+ @param enabled_disk_templates: the list of enabled disk templates
+ @type file_disk_template: string
+ @param file_disk_template: the file-based disk template for which the
+ path should be checked
+
+ """
+ assert (file_disk_template in
+ utils.storage.GetDiskTemplatesOfStorageType(constants.ST_FILE))
+ file_storage_enabled = file_disk_template in enabled_disk_templates
+ if file_storage_dir is not None:
+ if file_storage_dir == "":
+ if file_storage_enabled:
+ raise errors.OpPrereqError(
+ "Unsetting the '%s' storage directory while having '%s' storage"
+ " enabled is not permitted." %
+ (file_disk_template, file_disk_template))
+ else:
+ if not file_storage_enabled:
+ logging_warn_fn(
+ "Specified a %s storage directory, although %s storage is not"
+ " enabled." % (file_disk_template, file_disk_template))
+ else:
+ raise errors.ProgrammerError("Received %s storage dir with value"
+ " 'None'." % file_disk_template)
+
+
+def CheckFileStoragePathVsEnabledDiskTemplates(
+ logging_warn_fn, file_storage_dir, enabled_disk_templates):
+ """Checks whether the given file storage directory is acceptable.
+
+ @see: C{CheckFileBasedStoragePathVsEnabledDiskTemplates}
+
+ """
+ CheckFileBasedStoragePathVsEnabledDiskTemplates(
+ logging_warn_fn, file_storage_dir, enabled_disk_templates,
+ constants.DT_FILE)
+
+
+def CheckSharedFileStoragePathVsEnabledDiskTemplates(
+ logging_warn_fn, file_storage_dir, enabled_disk_templates):
+ """Checks whether the given shared file storage directory is acceptable.
+
+ @see: C{CheckFileBasedStoragePathVsEnabledDiskTemplates}
+
+ """
+ CheckFileBasedStoragePathVsEnabledDiskTemplates(
+ logging_warn_fn, file_storage_dir, enabled_disk_templates,
+ constants.DT_SHARED_FILE)
+
+
class LUClusterSetParams(LogicalUnit):
"""Change the parameters of the cluster.
self._CheckVgName(vm_capable_node_uuids, enabled_disk_templates,
new_enabled_disk_templates)
+ if self.op.file_storage_dir is not None:
+ CheckFileStoragePathVsEnabledDiskTemplates(
+ self.LogWarning, self.op.file_storage_dir, enabled_disk_templates)
+
+ if self.op.shared_file_storage_dir is not None:
+ CheckSharedFileStoragePathVsEnabledDiskTemplates(
+ self.LogWarning, self.op.shared_file_storage_dir,
+ enabled_disk_templates)
+
if self.op.drbd_helper:
# checks given drbd helper on all nodes
helpers = self.rpc.call_drbd_helper(node_uuids)
for nuuid in inst.all_nodes)])
new_ipolicy = objects.FillIPolicy(self.new_ipolicy, group.ipolicy)
ipol = masterd.instance.CalculateGroupIPolicy(cluster, group)
- new = ComputeNewInstanceViolations(ipol,
- new_ipolicy, instances, self.cfg)
+ new = ComputeNewInstanceViolations(ipol, new_ipolicy, instances,
+ self.cfg)
if new:
violations.update(new)
raise errors.OpPrereqError("Please specify a volume group when"
" enabling lvm-based disk-templates.")
+ def _SetFileStorageDir(self, feedback_fn):
+ """Set the file storage directory.
+
+ """
+ if self.op.file_storage_dir is not None:
+ if self.cluster.file_storage_dir == self.op.file_storage_dir:
+ feedback_fn("Global file storage dir already set to value '%s'"
+ % self.cluster.file_storage_dir)
+ else:
+ self.cluster.file_storage_dir = self.op.file_storage_dir
+
def Exec(self, feedback_fn):
"""Change the parameters of the cluster.
list(set(self.op.enabled_disk_templates))
self._SetVgName(feedback_fn)
+ self._SetFileStorageDir(feedback_fn)
if self.op.drbd_helper is not None:
if not constants.DT_DRBD8 in self.cluster.enabled_disk_templates:
" maintenance is not useful (still enabling it)")
self.cluster.maintain_node_health = self.op.maintain_node_health
+ if self.op.modify_etc_hosts is not None:
+ self.cluster.modify_etc_hosts = self.op.modify_etc_hosts
+
if self.op.prealloc_wipe_disks is not None:
self.cluster.prealloc_wipe_disks = self.op.prealloc_wipe_disks
self.cluster.master_netdev)
result = self.rpc.call_node_deactivate_master_ip(master_params.uuid,
master_params, ems)
- result.Raise("Could not disable the master ip")
+ if not self.op.force:
+ result.Raise("Could not disable the master ip")
+ else:
+ if result.fail_msg:
+ msg = ("Could not disable the master ip (continuing anyway): %s" %
+ result.fail_msg)
+ feedback_fn(msg)
feedback_fn("Changing master_netdev from %s to %s" %
(master_params.netdev, self.op.master_netdev))
self.cluster.master_netdev = self.op.master_netdev
(errcode, msg) = _VerifyCertificate(cert_filename)
self._ErrorIf(errcode, constants.CV_ECLUSTERCERT, None, msg, code=errcode)
+ self._ErrorIf(not utils.CanRead(constants.CONFD_USER,
+ pathutils.NODED_CERT_FILE),
+ constants.CV_ECLUSTERCERT,
+ None,
+ pathutils.NODED_CERT_FILE + " must be accessible by the " +
+ constants.CONFD_USER + " user")
+
feedback_fn("* Verifying hypervisor parameters")
self._VerifyHVP(_GetAllHypervisorParameters(self.cfg.GetClusterInfo(),
for inst in self.all_inst_info.values():
if inst.primary_node in [node.uuid for node in dangling_nodes]:
- dangling_instances.setdefault(inst.primary_node, []).append(inst.name)
+ dangling_instances.setdefault(inst.primary_node, []).append(inst)
elif inst.primary_node not in self.all_node_info:
- no_node_instances.append(inst.name)
+ no_node_instances.append(inst)
pretty_dangling = [
"%s (%s)" %
(node.name,
- utils.CommaJoin(dangling_instances.get(node.uuid,
- ["no instances"])))
+ utils.CommaJoin(
+ self.cfg.GetInstanceNames(
+ dangling_instances.get(node.uuid, []))))
for node in dangling_nodes]
self._ErrorIf(bool(dangling_nodes), constants.CV_ECLUSTERDANGLINGNODES,
self._ErrorIf(bool(no_node_instances), constants.CV_ECLUSTERDANGLINGINST,
None,
"the following instances have a non-existing primary-node:"
- " %s", utils.CommaJoin(no_node_instances))
+ " %s", utils.CommaJoin(
+ self.cfg.GetInstanceNames(no_node_instances)))
return not self.bad
self.group_uuid = self.cfg.LookupNodeGroup(self.op.group_name)
# Get instances in node group; this is unsafe and needs verification later
- inst_names = \
+ inst_uuids = \
self.cfg.GetNodeGroupInstances(self.group_uuid, primary_only=True)
self.needed_locks = {
- locking.LEVEL_INSTANCE: inst_names,
+ locking.LEVEL_INSTANCE: self.cfg.GetInstanceNames(inst_uuids),
locking.LEVEL_NODEGROUP: [self.group_uuid],
locking.LEVEL_NODE: [],
# Get members of node group; this is unsafe and needs verification later
nodes = set(self.cfg.GetNodeGroup(self.group_uuid).members)
- all_inst_info = self.cfg.GetAllInstancesInfo()
-
# In Exec(), we warn about mirrored instances that have primary and
# secondary living in separate node groups. To fully verify that
# volumes for these instances are healthy, we will need to do an
# extra call to their secondaries. We ensure here those nodes will
# be locked.
- for inst in self.owned_locks(locking.LEVEL_INSTANCE):
+ for inst_name in self.owned_locks(locking.LEVEL_INSTANCE):
# Important: access only the instances whose lock is owned
- if all_inst_info[inst].disk_template in constants.DTS_INT_MIRROR:
- nodes.update(all_inst_info[inst].secondary_nodes)
+ instance = self.cfg.GetInstanceInfoByName(inst_name)
+ if instance.disk_template in constants.DTS_INT_MIRROR:
+ nodes.update(instance.secondary_nodes)
self.needed_locks[locking.LEVEL_NODE] = nodes
self.group_info = self.cfg.GetNodeGroup(self.group_uuid)
group_node_uuids = set(self.group_info.members)
- group_instances = \
+ group_inst_uuids = \
self.cfg.GetNodeGroupInstances(self.group_uuid, primary_only=True)
unlocked_node_uuids = \
group_node_uuids.difference(self.owned_locks(locking.LEVEL_NODE))
- unlocked_instances = \
- group_instances.difference(self.owned_locks(locking.LEVEL_INSTANCE))
+ unlocked_inst_uuids = \
+ group_inst_uuids.difference(
+ [self.cfg.GetInstanceInfoByName(name).uuid
+ for name in self.owned_locks(locking.LEVEL_INSTANCE)])
if unlocked_node_uuids:
raise errors.OpPrereqError(
utils.CommaJoin(self.cfg.GetNodeNames(unlocked_node_uuids)),
errors.ECODE_STATE)
- if unlocked_instances:
- raise errors.OpPrereqError("Missing lock for instances: %s" %
- utils.CommaJoin(unlocked_instances),
- errors.ECODE_STATE)
+ if unlocked_inst_uuids:
+ raise errors.OpPrereqError(
+ "Missing lock for instances: %s" %
+ utils.CommaJoin(self.cfg.GetInstanceNames(unlocked_inst_uuids)),
+ errors.ECODE_STATE)
self.all_node_info = self.cfg.GetAllNodesInfo()
self.all_inst_info = self.cfg.GetAllInstancesInfo()
self.my_node_info = dict((node_uuid, self.all_node_info[node_uuid])
for node_uuid in group_node_uuids)
- self.my_inst_names = utils.NiceSort(group_instances)
- self.my_inst_info = dict((name, self.all_inst_info[name])
- for name in self.my_inst_names)
+ self.my_inst_uuids = group_inst_uuids
+ self.my_inst_info = dict((inst_uuid, self.all_inst_info[inst_uuid])
+ for inst_uuid in group_inst_uuids)
# We detect here the nodes that will need the extra RPC calls for verifying
# split LV volumes; they should be locked.
reasonable values in the respose)
"""
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
# main result, nresult should be a non-empty dict
test = not nresult or not isinstance(nresult, dict)
- _ErrorIf(test, constants.CV_ENODERPC, node_name,
+ self._ErrorIf(test, constants.CV_ENODERPC, ninfo.name,
"unable to verify node: no data returned")
if test:
return False
test = not (remote_version and
isinstance(remote_version, (list, tuple)) and
len(remote_version) == 2)
- _ErrorIf(test, constants.CV_ENODERPC, node_name,
- "connection to node returned invalid data")
+ self._ErrorIf(test, constants.CV_ENODERPC, ninfo.name,
+ "connection to node returned invalid data")
if test:
return False
test = local_version != remote_version[0]
- _ErrorIf(test, constants.CV_ENODEVERSION, node_name,
- "incompatible protocol versions: master %s,"
- " node %s", local_version, remote_version[0])
+ self._ErrorIf(test, constants.CV_ENODEVERSION, ninfo.name,
+ "incompatible protocol versions: master %s,"
+ " node %s", local_version, remote_version[0])
if test:
return False
# full package version
self._ErrorIf(constants.RELEASE_VERSION != remote_version[1],
- constants.CV_ENODEVERSION, node_name,
+ constants.CV_ENODEVERSION, ninfo.name,
"software version mismatch: master %s, node %s",
constants.RELEASE_VERSION, remote_version[1],
code=self.ETYPE_WARNING)
if ninfo.vm_capable and isinstance(hyp_result, dict):
for hv_name, hv_result in hyp_result.iteritems():
test = hv_result is not None
- _ErrorIf(test, constants.CV_ENODEHV, node_name,
- "hypervisor %s verify failure: '%s'", hv_name, hv_result)
+ self._ErrorIf(test, constants.CV_ENODEHV, ninfo.name,
+ "hypervisor %s verify failure: '%s'", hv_name, hv_result)
hvp_result = nresult.get(constants.NV_HVPARAMS, None)
if ninfo.vm_capable and isinstance(hvp_result, list):
for item, hv_name, hv_result in hvp_result:
- _ErrorIf(True, constants.CV_ENODEHV, node_name,
- "hypervisor %s parameter verify failure (source %s): %s",
- hv_name, item, hv_result)
+ self._ErrorIf(True, constants.CV_ENODEHV, ninfo.name,
+ "hypervisor %s parameter verify failure (source %s): %s",
+ hv_name, item, hv_result)
test = nresult.get(constants.NV_NODESETUP,
["Missing NODESETUP results"])
- _ErrorIf(test, constants.CV_ENODESETUP, node_name, "node setup error: %s",
- "; ".join(test))
+ self._ErrorIf(test, constants.CV_ENODESETUP, ninfo.name,
+ "node setup error: %s", "; ".join(test))
return True
@param nvinfo_endtime: the end time of the RPC call
"""
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
ntime = nresult.get(constants.NV_TIME, None)
try:
ntime_merged = utils.MergeTime(ntime)
except (ValueError, TypeError):
- _ErrorIf(True, constants.CV_ENODETIME, node_name,
- "Node returned invalid time")
+ self._ErrorIf(True, constants.CV_ENODETIME, ninfo.name,
+ "Node returned invalid time")
return
if ntime_merged < (nvinfo_starttime - constants.NODE_MAX_CLOCK_SKEW):
else:
ntime_diff = None
- _ErrorIf(ntime_diff is not None, constants.CV_ENODETIME, node_name,
- "Node time diverges by at least %s from master node time",
- ntime_diff)
+ self._ErrorIf(ntime_diff is not None, constants.CV_ENODETIME, ninfo.name,
+ "Node time diverges by at least %s from master node time",
+ ntime_diff)
def _UpdateVerifyNodeLVM(self, ninfo, nresult, vg_name, nimg):
"""Check the node LVM results and update info for cross-node checks.
if vg_name is None:
return
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
# checks vg existence and size > 20G
vglist = nresult.get(constants.NV_VGLIST, None)
test = not vglist
- _ErrorIf(test, constants.CV_ENODELVM, node_name,
- "unable to check volume groups")
+ self._ErrorIf(test, constants.CV_ENODELVM, ninfo.name,
+ "unable to check volume groups")
if not test:
vgstatus = utils.CheckVolumeGroupSize(vglist, vg_name,
constants.MIN_VG_SIZE)
- _ErrorIf(vgstatus, constants.CV_ENODELVM, node_name, vgstatus)
+ self._ErrorIf(vgstatus, constants.CV_ENODELVM, ninfo.name, vgstatus)
# Check PVs
(errmsgs, pvminmax) = CheckNodePVs(nresult, self._exclusive_storage)
for em in errmsgs:
- self._Error(constants.CV_ENODELVM, node_name, em)
+ self._Error(constants.CV_ENODELVM, ninfo.name, em)
if pvminmax is not None:
(nimg.pv_min, nimg.pv_max) = pvminmax
if vg_name is None:
return
- # Only exlcusive storage needs this kind of checks
+ # Only exclusive storage needs this kind of checks
if not self._exclusive_storage:
return
vals = filter((lambda ni: ni.pv_min is not None), node_image.values())
if not vals:
return
- (pvmin, minnode) = min((ni.pv_min, ni.name) for ni in vals)
- (pvmax, maxnode) = max((ni.pv_max, ni.name) for ni in vals)
+ (pvmin, minnode_uuid) = min((ni.pv_min, ni.uuid) for ni in vals)
+ (pvmax, maxnode_uuid) = max((ni.pv_max, ni.uuid) for ni in vals)
bad = utils.LvmExclusiveTestBadPvSizes(pvmin, pvmax)
self._ErrorIf(bad, constants.CV_EGROUPDIFFERENTPVSIZE, self.group_info.name,
"PV sizes differ too much in the group; smallest (%s MB) is"
" on %s, biggest (%s MB) is on %s",
- pvmin, minnode, pvmax, maxnode)
+ pvmin, self.cfg.GetNodeName(minnode_uuid),
+ pvmax, self.cfg.GetNodeName(maxnode_uuid))
def _VerifyNodeBridges(self, ninfo, nresult, bridges):
"""Check the node bridges.
if not bridges:
return
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
missing = nresult.get(constants.NV_BRIDGES, None)
test = not isinstance(missing, list)
- _ErrorIf(test, constants.CV_ENODENET, node_name,
- "did not return valid bridge information")
+ self._ErrorIf(test, constants.CV_ENODENET, ninfo.name,
+ "did not return valid bridge information")
if not test:
- _ErrorIf(bool(missing), constants.CV_ENODENET, node_name,
- "missing bridges: %s" % utils.CommaJoin(sorted(missing)))
+ self._ErrorIf(bool(missing), constants.CV_ENODENET, ninfo.name,
+ "missing bridges: %s" % utils.CommaJoin(sorted(missing)))
def _VerifyNodeUserScripts(self, ninfo, nresult):
"""Check the results of user scripts presence and executability on the node
@param nresult: the remote results for the node
"""
- node_name = ninfo.name
-
test = not constants.NV_USERSCRIPTS in nresult
- self._ErrorIf(test, constants.CV_ENODEUSERSCRIPTS, node_name,
+ self._ErrorIf(test, constants.CV_ENODEUSERSCRIPTS, ninfo.name,
"did not return user scripts information")
broken_scripts = nresult.get(constants.NV_USERSCRIPTS, None)
if not test:
- self._ErrorIf(broken_scripts, constants.CV_ENODEUSERSCRIPTS, node_name,
+ self._ErrorIf(broken_scripts, constants.CV_ENODEUSERSCRIPTS, ninfo.name,
"user scripts not present or not executable: %s" %
utils.CommaJoin(sorted(broken_scripts)))
@param nresult: the remote results for the node
"""
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
test = constants.NV_NODELIST not in nresult
- _ErrorIf(test, constants.CV_ENODESSH, node_name,
- "node hasn't returned node ssh connectivity data")
+ self._ErrorIf(test, constants.CV_ENODESSH, ninfo.name,
+ "node hasn't returned node ssh connectivity data")
if not test:
if nresult[constants.NV_NODELIST]:
for a_node, a_msg in nresult[constants.NV_NODELIST].items():
- _ErrorIf(True, constants.CV_ENODESSH, node_name,
- "ssh communication with node '%s': %s", a_node, a_msg)
+ self._ErrorIf(True, constants.CV_ENODESSH, ninfo.name,
+ "ssh communication with node '%s': %s", a_node, a_msg)
test = constants.NV_NODENETTEST not in nresult
- _ErrorIf(test, constants.CV_ENODENET, node_name,
- "node hasn't returned node tcp connectivity data")
+ self._ErrorIf(test, constants.CV_ENODENET, ninfo.name,
+ "node hasn't returned node tcp connectivity data")
if not test:
if nresult[constants.NV_NODENETTEST]:
nlist = utils.NiceSort(nresult[constants.NV_NODENETTEST].keys())
for anode in nlist:
- _ErrorIf(True, constants.CV_ENODENET, node_name,
- "tcp communication with node '%s': %s",
- anode, nresult[constants.NV_NODENETTEST][anode])
+ self._ErrorIf(True, constants.CV_ENODENET, ninfo.name,
+ "tcp communication with node '%s': %s",
+ anode, nresult[constants.NV_NODENETTEST][anode])
test = constants.NV_MASTERIP not in nresult
- _ErrorIf(test, constants.CV_ENODENET, node_name,
- "node hasn't returned node master IP reachability data")
+ self._ErrorIf(test, constants.CV_ENODENET, ninfo.name,
+ "node hasn't returned node master IP reachability data")
if not test:
if not nresult[constants.NV_MASTERIP]:
if ninfo.uuid == self.master_node:
msg = "the master node cannot reach the master IP (not configured?)"
else:
msg = "cannot reach the master IP"
- _ErrorIf(True, constants.CV_ENODENET, node_name, msg)
+ self._ErrorIf(True, constants.CV_ENODENET, ninfo.name, msg)
- def _VerifyInstance(self, instance, inst_config, node_image,
- diskstatus):
+ def _VerifyInstance(self, instance, node_image, diskstatus):
"""Verify an instance.
This function checks to see if the required block devices are
state.
"""
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
- pnode = inst_config.primary_node
- pnode_img = node_image[pnode]
+ pnode_uuid = instance.primary_node
+ pnode_img = node_image[pnode_uuid]
groupinfo = self.cfg.GetAllNodeGroupsInfo()
node_vol_should = {}
- inst_config.MapLVsByNode(node_vol_should)
+ instance.MapLVsByNode(node_vol_should)
cluster = self.cfg.GetClusterInfo()
ipolicy = ganeti.masterd.instance.CalculateGroupIPolicy(cluster,
self.group_info)
- err = ComputeIPolicyInstanceViolation(ipolicy, inst_config, self.cfg)
- _ErrorIf(err, constants.CV_EINSTANCEPOLICY, instance, utils.CommaJoin(err),
- code=self.ETYPE_WARNING)
+ err = ComputeIPolicyInstanceViolation(ipolicy, instance, self.cfg)
+ self._ErrorIf(err, constants.CV_EINSTANCEPOLICY, instance.name,
+ utils.CommaJoin(err), code=self.ETYPE_WARNING)
- for node in node_vol_should:
- n_img = node_image[node]
+ for node_uuid in node_vol_should:
+ n_img = node_image[node_uuid]
if n_img.offline or n_img.rpc_fail or n_img.lvm_fail:
# ignore missing volumes on offline or broken nodes
continue
- for volume in node_vol_should[node]:
+ for volume in node_vol_should[node_uuid]:
test = volume not in n_img.volumes
- _ErrorIf(test, constants.CV_EINSTANCEMISSINGDISK, instance,
- "volume %s missing on node %s", volume,
- self.cfg.GetNodeName(node))
-
- if inst_config.admin_state == constants.ADMINST_UP:
- test = instance not in pnode_img.instances and not pnode_img.offline
- _ErrorIf(test, constants.CV_EINSTANCEDOWN, instance,
- "instance not running on its primary node %s",
- self.cfg.GetNodeName(pnode))
- _ErrorIf(pnode_img.offline, constants.CV_EINSTANCEBADNODE, instance,
- "instance is marked as running and lives on offline node %s",
- self.cfg.GetNodeName(pnode))
+ self._ErrorIf(test, constants.CV_EINSTANCEMISSINGDISK, instance.name,
+ "volume %s missing on node %s", volume,
+ self.cfg.GetNodeName(node_uuid))
+
+ if instance.admin_state == constants.ADMINST_UP:
+ test = instance.uuid not in pnode_img.instances and not pnode_img.offline
+ self._ErrorIf(test, constants.CV_EINSTANCEDOWN, instance.name,
+ "instance not running on its primary node %s",
+ self.cfg.GetNodeName(pnode_uuid))
+ self._ErrorIf(pnode_img.offline, constants.CV_EINSTANCEBADNODE,
+ instance.name, "instance is marked as running and lives on"
+ " offline node %s", self.cfg.GetNodeName(pnode_uuid))
diskdata = [(nname, success, status, idx)
for (nname, disks) in diskstatus.items()
# node here
snode = node_image[nname]
bad_snode = snode.ghost or snode.offline
- _ErrorIf(inst_config.disks_active and
- not success and not bad_snode,
- constants.CV_EINSTANCEFAULTYDISK, instance,
- "couldn't retrieve status for disk/%s on %s: %s",
- idx, self.cfg.GetNodeName(nname), bdev_status)
- _ErrorIf((inst_config.disks_active and
- success and bdev_status.ldisk_status == constants.LDS_FAULTY),
- constants.CV_EINSTANCEFAULTYDISK, instance,
- "disk/%s on %s is faulty", idx, self.cfg.GetNodeName(nname))
-
- _ErrorIf(pnode_img.rpc_fail and not pnode_img.offline,
- constants.CV_ENODERPC, pnode, "instance %s, connection to"
- " primary node failed", instance)
-
- _ErrorIf(len(inst_config.secondary_nodes) > 1,
- constants.CV_EINSTANCELAYOUT,
- instance, "instance has multiple secondary nodes: %s",
- utils.CommaJoin(inst_config.secondary_nodes),
- code=self.ETYPE_WARNING)
+ self._ErrorIf(instance.disks_active and
+ not success and not bad_snode,
+ constants.CV_EINSTANCEFAULTYDISK, instance.name,
+ "couldn't retrieve status for disk/%s on %s: %s",
+ idx, self.cfg.GetNodeName(nname), bdev_status)
+
+ if instance.disks_active and success and \
+ (bdev_status.is_degraded or
+ bdev_status.ldisk_status != constants.LDS_OKAY):
+ msg = "disk/%s on %s" % (idx, self.cfg.GetNodeName(nname))
+ if bdev_status.is_degraded:
+ msg += " is degraded"
+ if bdev_status.ldisk_status != constants.LDS_OKAY:
+ msg += "; state is '%s'" % \
+ constants.LDS_NAMES[bdev_status.ldisk_status]
+
+ self._Error(constants.CV_EINSTANCEFAULTYDISK, instance.name, msg)
+
+ self._ErrorIf(pnode_img.rpc_fail and not pnode_img.offline,
+ constants.CV_ENODERPC, self.cfg.GetNodeName(pnode_uuid),
+ "instance %s, connection to primary node failed",
+ instance.name)
+
+ self._ErrorIf(len(instance.secondary_nodes) > 1,
+ constants.CV_EINSTANCELAYOUT, instance.name,
+ "instance has multiple secondary nodes: %s",
+ utils.CommaJoin(instance.secondary_nodes),
+ code=self.ETYPE_WARNING)
- es_flags = rpc.GetExclusiveStorageForNodes(self.cfg,
- inst_config.all_nodes)
+ es_flags = rpc.GetExclusiveStorageForNodes(self.cfg, instance.all_nodes)
if any(es_flags.values()):
- if inst_config.disk_template not in constants.DTS_EXCL_STORAGE:
+ if instance.disk_template not in constants.DTS_EXCL_STORAGE:
# Disk template not compatible with exclusive_storage: no instance
# node should have the flag set
es_nodes = [n
for (n, es) in es_flags.items()
if es]
- self._Error(constants.CV_EINSTANCEUNSUITABLENODE, instance,
+ self._Error(constants.CV_EINSTANCEUNSUITABLENODE, instance.name,
"instance has template %s, which is not supported on nodes"
" that have exclusive storage set: %s",
- inst_config.disk_template,
+ instance.disk_template,
utils.CommaJoin(self.cfg.GetNodeNames(es_nodes)))
- for (idx, disk) in enumerate(inst_config.disks):
- _ErrorIf(disk.spindles is None,
- constants.CV_EINSTANCEMISSINGCFGPARAMETER, instance,
- "number of spindles not configured for disk %s while"
- " exclusive storage is enabled, try running"
- " gnt-cluster repair-disk-sizes",
- idx)
-
- if inst_config.disk_template in constants.DTS_INT_MIRROR:
- instance_nodes = utils.NiceSort(inst_config.all_nodes)
+ for (idx, disk) in enumerate(instance.disks):
+ self._ErrorIf(disk.spindles is None,
+ constants.CV_EINSTANCEMISSINGCFGPARAMETER, instance.name,
+ "number of spindles not configured for disk %s while"
+ " exclusive storage is enabled, try running"
+ " gnt-cluster repair-disk-sizes", idx)
+
+ if instance.disk_template in constants.DTS_INT_MIRROR:
+ instance_nodes = utils.NiceSort(instance.all_nodes)
instance_groups = {}
- for node in instance_nodes:
- instance_groups.setdefault(self.all_node_info[node].group,
- []).append(node)
+ for node_uuid in instance_nodes:
+ instance_groups.setdefault(self.all_node_info[node_uuid].group,
+ []).append(node_uuid)
pretty_list = [
"%s (group %s)" % (utils.CommaJoin(self.cfg.GetNodeNames(nodes)),
groupinfo[group].name)
# Sort so that we always list the primary node first.
for group, nodes in sorted(instance_groups.items(),
- key=lambda (_, nodes): pnode in nodes,
+ key=lambda (_, nodes): pnode_uuid in nodes,
reverse=True)]
self._ErrorIf(len(instance_groups) > 1,
constants.CV_EINSTANCESPLITGROUPS,
- instance, "instance has primary and secondary nodes in"
+ instance.name, "instance has primary and secondary nodes in"
" different groups: %s", utils.CommaJoin(pretty_list),
code=self.ETYPE_WARNING)
inst_nodes_offline = []
- for snode in inst_config.secondary_nodes:
+ for snode in instance.secondary_nodes:
s_img = node_image[snode]
- _ErrorIf(s_img.rpc_fail and not s_img.offline, constants.CV_ENODERPC,
- snode, "instance %s, connection to secondary node failed",
- instance)
+ self._ErrorIf(s_img.rpc_fail and not s_img.offline, constants.CV_ENODERPC,
+ self.cfg.GetNodeName(snode),
+ "instance %s, connection to secondary node failed",
+ instance.name)
if s_img.offline:
inst_nodes_offline.append(snode)
# warn that the instance lives on offline nodes
- _ErrorIf(inst_nodes_offline, constants.CV_EINSTANCEBADNODE, instance,
- "instance has offline secondary node(s) %s",
- utils.CommaJoin(self.cfg.GetNodeNames(inst_nodes_offline)))
+ self._ErrorIf(inst_nodes_offline, constants.CV_EINSTANCEBADNODE,
+ instance.name, "instance has offline secondary node(s) %s",
+ utils.CommaJoin(self.cfg.GetNodeNames(inst_nodes_offline)))
# ... or ghost/non-vm_capable nodes
- for node in inst_config.all_nodes:
- _ErrorIf(node_image[node].ghost, constants.CV_EINSTANCEBADNODE,
- instance, "instance lives on ghost node %s",
- self.cfg.GetNodeName(node))
- _ErrorIf(not node_image[node].vm_capable, constants.CV_EINSTANCEBADNODE,
- instance, "instance lives on non-vm_capable node %s",
- self.cfg.GetNodeName(node))
+ for node_uuid in instance.all_nodes:
+ self._ErrorIf(node_image[node_uuid].ghost, constants.CV_EINSTANCEBADNODE,
+ instance.name, "instance lives on ghost node %s",
+ self.cfg.GetNodeName(node_uuid))
+ self._ErrorIf(not node_image[node_uuid].vm_capable,
+ constants.CV_EINSTANCEBADNODE, instance.name,
+ "instance lives on non-vm_capable node %s",
+ self.cfg.GetNodeName(node_uuid))
def _VerifyOrphanVolumes(self, node_vol_should, node_image, reserved):
"""Verify if there are any unknown volumes in the cluster.
self.cfg.GetNodeName(node_uuid),
"volume %s is unknown", volume)
- def _VerifyNPlusOneMemory(self, node_image, instance_cfg):
+ def _VerifyNPlusOneMemory(self, node_image, all_insts):
"""Verify N+1 Memory Resilience.
Check that if one single node dies we can still start all the
# nodes, and that's enough warning
continue
#TODO(dynmem): also consider ballooning out other instances
- for prinode, instances in n_img.sbp.items():
+ for prinode, inst_uuids in n_img.sbp.items():
needed_mem = 0
- for instance in instances:
- bep = cluster_info.FillBE(instance_cfg[instance])
+ for inst_uuid in inst_uuids:
+ bep = cluster_info.FillBE(all_insts[inst_uuid])
if bep[constants.BE_AUTO_BALANCE]:
needed_mem += bep[constants.BE_MINMEM]
test = n_img.mfree < needed_mem
L{ganeti.config.ConfigWriter.ComputeDRBDMap}
"""
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
if drbd_helper:
helper_result = nresult.get(constants.NV_DRBDHELPER, None)
test = (helper_result is None)
- _ErrorIf(test, constants.CV_ENODEDRBDHELPER, node_name,
- "no drbd usermode helper returned")
+ self._ErrorIf(test, constants.CV_ENODEDRBDHELPER, ninfo.name,
+ "no drbd usermode helper returned")
if helper_result:
status, payload = helper_result
test = not status
- _ErrorIf(test, constants.CV_ENODEDRBDHELPER, node_name,
- "drbd usermode helper check unsuccessful: %s", payload)
+ self._ErrorIf(test, constants.CV_ENODEDRBDHELPER, ninfo.name,
+ "drbd usermode helper check unsuccessful: %s", payload)
test = status and (payload != drbd_helper)
- _ErrorIf(test, constants.CV_ENODEDRBDHELPER, node_name,
- "wrong drbd usermode helper: %s", payload)
+ self._ErrorIf(test, constants.CV_ENODEDRBDHELPER, ninfo.name,
+ "wrong drbd usermode helper: %s", payload)
# compute the DRBD minors
node_drbd = {}
- for minor, instance in drbd_map[ninfo.uuid].items():
- test = instance not in instanceinfo
- _ErrorIf(test, constants.CV_ECLUSTERCFG, None,
- "ghost instance '%s' in temporary DRBD map", instance)
+ for minor, inst_uuid in drbd_map[ninfo.uuid].items():
+ test = inst_uuid not in instanceinfo
+ self._ErrorIf(test, constants.CV_ECLUSTERCFG, None,
+ "ghost instance '%s' in temporary DRBD map", inst_uuid)
# ghost instance should not be running, but otherwise we
# don't give double warnings (both ghost instance and
# unallocated minor in use)
if test:
- node_drbd[minor] = (instance, False)
+ node_drbd[minor] = (inst_uuid, False)
else:
- instance = instanceinfo[instance]
- node_drbd[minor] = (instance.name, instance.disks_active)
+ instance = instanceinfo[inst_uuid]
+ node_drbd[minor] = (inst_uuid, instance.disks_active)
# and now check them
used_minors = nresult.get(constants.NV_DRBDLIST, [])
test = not isinstance(used_minors, (tuple, list))
- _ErrorIf(test, constants.CV_ENODEDRBD, node_name,
- "cannot parse drbd status file: %s", str(used_minors))
+ self._ErrorIf(test, constants.CV_ENODEDRBD, ninfo.name,
+ "cannot parse drbd status file: %s", str(used_minors))
if test:
# we cannot check drbd status
return
- for minor, (iname, must_exist) in node_drbd.items():
+ for minor, (inst_uuid, must_exist) in node_drbd.items():
test = minor not in used_minors and must_exist
- _ErrorIf(test, constants.CV_ENODEDRBD, node_name,
- "drbd minor %d of instance %s is not active", minor, iname)
+ self._ErrorIf(test, constants.CV_ENODEDRBD, ninfo.name,
+ "drbd minor %d of instance %s is not active", minor,
+ self.cfg.GetInstanceName(inst_uuid))
for minor in used_minors:
test = minor not in node_drbd
- _ErrorIf(test, constants.CV_ENODEDRBD, node_name,
- "unallocated drbd minor %d is in use", minor)
+ self._ErrorIf(test, constants.CV_ENODEDRBD, ninfo.name,
+ "unallocated drbd minor %d is in use", minor)
def _UpdateNodeOS(self, ninfo, nresult, nimg):
"""Builds the node OS structures.
@param nimg: the node image object
"""
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
remote_os = nresult.get(constants.NV_OSLIST, None)
test = (not isinstance(remote_os, list) or
not compat.all(isinstance(v, list) and len(v) == 7
for v in remote_os))
- _ErrorIf(test, constants.CV_ENODEOS, node_name,
- "node hasn't returned valid OS data")
+ self._ErrorIf(test, constants.CV_ENODEOS, ninfo.name,
+ "node hasn't returned valid OS data")
nimg.os_fail = test
@param base: the 'template' node we match against (e.g. from the master)
"""
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
assert not nimg.os_fail, "Entered _VerifyNodeOS with failed OS rpc?"
beautify_params = lambda l: ["%s: %s" % (k, v) for (k, v) in l]
for os_name, os_data in nimg.oslist.items():
assert os_data, "Empty OS status for OS %s?!" % os_name
f_path, f_status, f_diag, f_var, f_param, f_api = os_data[0]
- _ErrorIf(not f_status, constants.CV_ENODEOS, node_name,
- "Invalid OS %s (located at %s): %s", os_name, f_path, f_diag)
- _ErrorIf(len(os_data) > 1, constants.CV_ENODEOS, node_name,
- "OS '%s' has multiple entries (first one shadows the rest): %s",
- os_name, utils.CommaJoin([v[0] for v in os_data]))
+ self._ErrorIf(not f_status, constants.CV_ENODEOS, ninfo.name,
+ "Invalid OS %s (located at %s): %s",
+ os_name, f_path, f_diag)
+ self._ErrorIf(len(os_data) > 1, constants.CV_ENODEOS, ninfo.name,
+ "OS '%s' has multiple entries"
+ " (first one shadows the rest): %s",
+ os_name, utils.CommaJoin([v[0] for v in os_data]))
# comparisons with the 'base' image
test = os_name not in base.oslist
- _ErrorIf(test, constants.CV_ENODEOS, node_name,
- "Extra OS %s not present on reference node (%s)",
- os_name, self.cfg.GetNodeName(base.uuid))
+ self._ErrorIf(test, constants.CV_ENODEOS, ninfo.name,
+ "Extra OS %s not present on reference node (%s)",
+ os_name, self.cfg.GetNodeName(base.uuid))
if test:
continue
assert base.oslist[os_name], "Base node has empty OS status?"
("variants list", f_var, b_var),
("parameters", beautify_params(f_param),
beautify_params(b_param))]:
- _ErrorIf(a != b, constants.CV_ENODEOS, node_name,
- "OS %s for %s differs from reference node %s: [%s] vs. [%s]",
- kind, os_name, self.cfg.GetNodeName(base.uuid),
- utils.CommaJoin(sorted(a)), utils.CommaJoin(sorted(b)))
+ self._ErrorIf(a != b, constants.CV_ENODEOS, ninfo.name,
+ "OS %s for %s differs from reference node %s:"
+ " [%s] vs. [%s]", kind, os_name,
+ self.cfg.GetNodeName(base.uuid),
+ utils.CommaJoin(sorted(a)), utils.CommaJoin(sorted(b)))
# check any missing OSes
missing = set(base.oslist.keys()).difference(nimg.oslist.keys())
- _ErrorIf(missing, constants.CV_ENODEOS, node_name,
- "OSes present on reference node %s but missing on this node: %s",
- self.cfg.GetNodeName(base.uuid), utils.CommaJoin(missing))
+ self._ErrorIf(missing, constants.CV_ENODEOS, ninfo.name,
+ "OSes present on reference node %s"
+ " but missing on this node: %s",
+ self.cfg.GetNodeName(base.uuid), utils.CommaJoin(missing))
- def _VerifyFileStoragePaths(self, ninfo, nresult, is_master):
+ def _VerifyAcceptedFileStoragePaths(self, ninfo, nresult, is_master):
"""Verifies paths in L{pathutils.FILE_STORAGE_PATHS_FILE}.
@type ninfo: L{objects.Node}
@param is_master: Whether node is the master node
"""
- node_name = ninfo.name
-
+ cluster = self.cfg.GetClusterInfo()
if (is_master and
- (constants.ENABLE_FILE_STORAGE or
- constants.ENABLE_SHARED_FILE_STORAGE)):
+ (cluster.IsFileStorageEnabled() or
+ cluster.IsSharedFileStorageEnabled())):
try:
- fspaths = nresult[constants.NV_FILE_STORAGE_PATHS]
+ fspaths = nresult[constants.NV_ACCEPTED_STORAGE_PATHS]
except KeyError:
# This should never happen
- self._ErrorIf(True, constants.CV_ENODEFILESTORAGEPATHS, node_name,
+ self._ErrorIf(True, constants.CV_ENODEFILESTORAGEPATHS, ninfo.name,
"Node did not return forbidden file storage paths")
else:
- self._ErrorIf(fspaths, constants.CV_ENODEFILESTORAGEPATHS, node_name,
+ self._ErrorIf(fspaths, constants.CV_ENODEFILESTORAGEPATHS, ninfo.name,
"Found forbidden file storage paths: %s",
utils.CommaJoin(fspaths))
else:
- self._ErrorIf(constants.NV_FILE_STORAGE_PATHS in nresult,
- constants.CV_ENODEFILESTORAGEPATHS, node_name,
+ self._ErrorIf(constants.NV_ACCEPTED_STORAGE_PATHS in nresult,
+ constants.CV_ENODEFILESTORAGEPATHS, ninfo.name,
"Node should not have returned forbidden file storage"
" paths")
+ def _VerifyStoragePaths(self, ninfo, nresult, file_disk_template,
+ verify_key, error_key):
+ """Verifies (file) storage paths.
+
+ @type ninfo: L{objects.Node}
+ @param ninfo: the node to check
+ @param nresult: the remote results for the node
+ @type file_disk_template: string
+ @param file_disk_template: file-based disk template, whose directory
+ is supposed to be verified
+ @type verify_key: string
+ @param verify_key: key for the verification map of this file
+ verification step
+ @param error_key: error key to be added to the verification results
+ in case something goes wrong in this verification step
+
+ """
+ assert (file_disk_template in
+ utils.storage.GetDiskTemplatesOfStorageType(constants.ST_FILE))
+ cluster = self.cfg.GetClusterInfo()
+ if cluster.IsDiskTemplateEnabled(file_disk_template):
+ self._ErrorIf(
+ verify_key in nresult,
+ error_key, ninfo.name,
+ "The configured %s storage path is unusable: %s" %
+ (file_disk_template, nresult.get(verify_key)))
+
+ def _VerifyFileStoragePaths(self, ninfo, nresult):
+ """Verifies (file) storage paths.
+
+ @see: C{_VerifyStoragePaths}
+
+ """
+ self._VerifyStoragePaths(
+ ninfo, nresult, constants.DT_FILE,
+ constants.NV_FILE_STORAGE_PATH,
+ constants.CV_ENODEFILESTORAGEPATHUNUSABLE)
+
+ def _VerifySharedFileStoragePaths(self, ninfo, nresult):
+ """Verifies (file) storage paths.
+
+ @see: C{_VerifyStoragePaths}
+
+ """
+ self._VerifyStoragePaths(
+ ninfo, nresult, constants.DT_SHARED_FILE,
+ constants.NV_SHARED_FILE_STORAGE_PATH,
+ constants.CV_ENODESHAREDFILESTORAGEPATHUNUSABLE)
+
def _VerifyOob(self, ninfo, nresult):
"""Verifies out of band functionality of a node.
@param nresult: the remote results for the node
"""
- node_name = ninfo.name
# We just have to verify the paths on master and/or master candidates
# as the oob helper is invoked on the master
if ((ninfo.master_candidate or ninfo.master_capable) and
constants.NV_OOB_PATHS in nresult):
for path_result in nresult[constants.NV_OOB_PATHS]:
self._ErrorIf(path_result, constants.CV_ENODEOOBPATH,
- node_name, path_result)
+ ninfo.name, path_result)
def _UpdateNodeVolumes(self, ninfo, nresult, nimg, vg_name):
"""Verifies and updates the node volume data.
@param vg_name: the configured VG name
"""
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
nimg.lvm_fail = True
lvdata = nresult.get(constants.NV_LVLIST, "Missing LV data")
if vg_name is None:
pass
elif isinstance(lvdata, basestring):
- _ErrorIf(True, constants.CV_ENODELVM, node_name,
- "LVM problem on node: %s", utils.SafeEncode(lvdata))
+ self._ErrorIf(True, constants.CV_ENODELVM, ninfo.name,
+ "LVM problem on node: %s", utils.SafeEncode(lvdata))
elif not isinstance(lvdata, dict):
- _ErrorIf(True, constants.CV_ENODELVM, node_name,
- "rpc call to node failed (lvlist)")
+ self._ErrorIf(True, constants.CV_ENODELVM, ninfo.name,
+ "rpc call to node failed (lvlist)")
else:
nimg.volumes = lvdata
nimg.lvm_fail = False
if test:
nimg.hyp_fail = True
else:
- nimg.instances = idata
+ nimg.instances = [inst.uuid for (_, inst) in
+ self.cfg.GetMultiInstanceInfoByName(idata)]
def _UpdateNodeInfo(self, ninfo, nresult, nimg, vg_name):
"""Verifies and computes a node information map
@param vg_name: the configured VG name
"""
- node_name = ninfo.name
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
-
# try to read free memory (from the hypervisor)
hv_info = nresult.get(constants.NV_HVINFO, None)
test = not isinstance(hv_info, dict) or "memory_free" not in hv_info
- _ErrorIf(test, constants.CV_ENODEHV, node_name,
- "rpc call to node failed (hvinfo)")
+ self._ErrorIf(test, constants.CV_ENODEHV, ninfo.name,
+ "rpc call to node failed (hvinfo)")
if not test:
try:
nimg.mfree = int(hv_info["memory_free"])
except (ValueError, TypeError):
- _ErrorIf(True, constants.CV_ENODERPC, node_name,
- "node returned invalid nodeinfo, check hypervisor")
+ self._ErrorIf(True, constants.CV_ENODERPC, ninfo.name,
+ "node returned invalid nodeinfo, check hypervisor")
# FIXME: devise a free space model for file based instances as well
if vg_name is not None:
test = (constants.NV_VGLIST not in nresult or
vg_name not in nresult[constants.NV_VGLIST])
- _ErrorIf(test, constants.CV_ENODELVM, node_name,
- "node didn't return data for the volume group '%s'"
- " - it is either missing or broken", vg_name)
+ self._ErrorIf(test, constants.CV_ENODELVM, ninfo.name,
+ "node didn't return data for the volume group '%s'"
+ " - it is either missing or broken", vg_name)
if not test:
try:
nimg.dfree = int(nresult[constants.NV_VGLIST][vg_name])
except (ValueError, TypeError):
- _ErrorIf(True, constants.CV_ENODERPC, node_name,
- "node returned invalid LVM info, check LVM status")
+ self._ErrorIf(True, constants.CV_ENODERPC, ninfo.name,
+ "node returned invalid LVM info, check LVM status")
def _CollectDiskInfo(self, node_uuids, node_image, instanceinfo):
"""Gets per-disk status information for all instances.
@type node_uuids: list of strings
@param node_uuids: Node UUIDs
- @type node_image: dict of (name, L{objects.Node})
+ @type node_image: dict of (UUID, L{objects.Node})
@param node_image: Node objects
- @type instanceinfo: dict of (name, L{objects.Instance})
+ @type instanceinfo: dict of (UUID, L{objects.Instance})
@param instanceinfo: Instance objects
@rtype: {instance: {node: [(succes, payload)]}}
@return: a dictionary of per-instance dictionaries with nodes as
diskless = constants.DT_DISKLESS
for nuuid in node_uuids:
- node_instances = list(itertools.chain(node_image[nuuid].pinst,
- node_image[nuuid].sinst))
- diskless_instances.update(inst for inst in node_instances
- if instanceinfo[inst].disk_template == diskless)
- disks = [(inst, disk)
- for inst in node_instances
- for disk in instanceinfo[inst].disks]
+ node_inst_uuids = list(itertools.chain(node_image[nuuid].pinst,
+ node_image[nuuid].sinst))
+ diskless_instances.update(uuid for uuid in node_inst_uuids
+ if instanceinfo[uuid].disk_template == diskless)
+ disks = [(inst_uuid, disk)
+ for inst_uuid in node_inst_uuids
+ for disk in instanceinfo[inst_uuid].disks]
if not disks:
# No need to collect data
# _AnnotateDiskParams makes already copies of the disks
devonly = []
- for (inst, dev) in disks:
- (anno_disk,) = AnnotateDiskParams(instanceinfo[inst], [dev], self.cfg)
+ for (inst_uuid, dev) in disks:
+ (anno_disk,) = AnnotateDiskParams(instanceinfo[inst_uuid], [dev],
+ self.cfg)
self.cfg.SetDiskID(anno_disk, nuuid)
devonly.append(anno_disk)
node.name, idx, i)
data.append((False, "Invalid result from the remote node"))
- for ((inst, _), status) in zip(disks, data):
- instdisk.setdefault(inst, {}).setdefault(node.uuid, []).append(status)
+ for ((inst_uuid, _), status) in zip(disks, data):
+ instdisk.setdefault(inst_uuid, {}).setdefault(node.uuid, []) \
+ .append(status)
# Add empty entries for diskless instances.
- for inst in diskless_instances:
- assert inst not in instdisk
- instdisk[inst] = {}
+ for inst_uuid in diskless_instances:
+ assert inst_uuid not in instdisk
+ instdisk[inst_uuid] = {}
assert compat.all(len(statuses) == len(instanceinfo[inst].disks) and
len(nuuids) <= len(instanceinfo[inst].all_nodes) and
return True
self.bad = False
- _ErrorIf = self._ErrorIf # pylint: disable=C0103
verbose = self.op.verbose
self._feedback_fn = feedback_fn
node_verify_param[constants.NV_DRBDLIST] = None
node_verify_param[constants.NV_DRBDHELPER] = drbd_helper
- if constants.ENABLE_FILE_STORAGE or constants.ENABLE_SHARED_FILE_STORAGE:
+ if cluster.IsFileStorageEnabled() or \
+ cluster.IsSharedFileStorageEnabled():
# Load file storage paths only from master node
- node_verify_param[constants.NV_FILE_STORAGE_PATHS] = \
+ node_verify_param[constants.NV_ACCEPTED_STORAGE_PATHS] = \
self.cfg.GetMasterNodeName()
+ if cluster.IsFileStorageEnabled():
+ node_verify_param[constants.NV_FILE_STORAGE_PATH] = \
+ cluster.file_storage_dir
# bridge checks
# FIXME: this needs to be changed per node-group, not cluster-wide
default_nicpp = cluster.nicparams[constants.PP_DEFAULT]
if default_nicpp[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
bridges.add(default_nicpp[constants.NIC_LINK])
- for instance in self.my_inst_info.values():
- for nic in instance.nics:
+ for inst_uuid in self.my_inst_info.values():
+ for nic in inst_uuid.nics:
full_nic = cluster.SimpleFillNIC(nic.nicparams)
if full_nic[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
bridges.add(full_nic[constants.NIC_LINK])
if oob_paths:
node_verify_param[constants.NV_OOB_PATHS] = oob_paths
- for instance in self.my_inst_names:
- inst_config = self.my_inst_info[instance]
- if inst_config.admin_state == constants.ADMINST_OFFLINE:
+ for inst_uuid in self.my_inst_uuids:
+ instance = self.my_inst_info[inst_uuid]
+ if instance.admin_state == constants.ADMINST_OFFLINE:
i_offline += 1
- for nuuid in inst_config.all_nodes:
+ for nuuid in instance.all_nodes:
if nuuid not in node_image:
gnode = self.NodeImage(uuid=nuuid)
gnode.ghost = (nuuid not in self.all_node_info)
node_image[nuuid] = gnode
- inst_config.MapLVsByNode(node_vol_should)
+ instance.MapLVsByNode(node_vol_should)
- pnode = inst_config.primary_node
- node_image[pnode].pinst.append(instance)
+ pnode = instance.primary_node
+ node_image[pnode].pinst.append(instance.uuid)
- for snode in inst_config.secondary_nodes:
+ for snode in instance.secondary_nodes:
nimg = node_image[snode]
- nimg.sinst.append(instance)
+ nimg.sinst.append(instance.uuid)
if pnode not in nimg.sbp:
nimg.sbp[pnode] = []
- nimg.sbp[pnode].append(instance)
+ nimg.sbp[pnode].append(instance.uuid)
es_flags = rpc.GetExclusiveStorageForNodes(self.cfg,
self.my_node_info.keys())
feedback_fn("* Verifying node %s (%s)" % (node_i.name, ntype))
msg = all_nvinfo[node_i.uuid].fail_msg
- _ErrorIf(msg, constants.CV_ENODERPC, node_i.name,
- "while contacting node: %s", msg)
+ self._ErrorIf(msg, constants.CV_ENODERPC, node_i.name,
+ "while contacting node: %s", msg)
if msg:
nimg.rpc_fail = True
continue
self._VerifyNodeNetwork(node_i, nresult)
self._VerifyNodeUserScripts(node_i, nresult)
self._VerifyOob(node_i, nresult)
- self._VerifyFileStoragePaths(node_i, nresult,
- node_i.uuid == master_node_uuid)
+ self._VerifyAcceptedFileStoragePaths(node_i, nresult,
+ node_i.uuid == master_node_uuid)
+ self._VerifyFileStoragePaths(node_i, nresult)
+ self._VerifySharedFileStoragePaths(node_i, nresult)
if nimg.vm_capable:
self._UpdateVerifyNodeLVM(node_i, nresult, vg_name, nimg)
self._VerifyNodeOS(node_i, nimg, refos_img)
self._VerifyNodeBridges(node_i, nresult, bridges)
- # Check whether all running instancies are primary for the node. (This
+ # Check whether all running instances are primary for the node. (This
# can no longer be done from _VerifyInstance below, since some of the
# wrong instances could be from other node groups.)
- non_primary_inst = set(nimg.instances).difference(nimg.pinst)
+ non_primary_inst_uuids = set(nimg.instances).difference(nimg.pinst)
- for inst in non_primary_inst:
- test = inst in self.all_inst_info
- _ErrorIf(test, constants.CV_EINSTANCEWRONGNODE, inst,
- "instance should not run on node %s", node_i.name)
- _ErrorIf(not test, constants.CV_ENODEORPHANINSTANCE, node_i.name,
- "node is running unknown instance %s", inst)
+ for inst_uuid in non_primary_inst_uuids:
+ test = inst_uuid in self.all_inst_info
+ self._ErrorIf(test, constants.CV_EINSTANCEWRONGNODE,
+ self.cfg.GetInstanceName(inst_uuid),
+ "instance should not run on node %s", node_i.name)
+ self._ErrorIf(not test, constants.CV_ENODEORPHANINSTANCE, node_i.name,
+ "node is running unknown instance %s", inst_uuid)
self._VerifyGroupDRBDVersion(all_nvinfo)
self._VerifyGroupLVM(node_image, vg_name)
node_image[node_uuid], vg_name)
feedback_fn("* Verifying instance status")
- for instance in self.my_inst_names:
+ for inst_uuid in self.my_inst_uuids:
+ instance = self.my_inst_info[inst_uuid]
if verbose:
- feedback_fn("* Verifying instance %s" % instance)
- inst_config = self.my_inst_info[instance]
- self._VerifyInstance(instance, inst_config, node_image,
- instdisk[instance])
+ feedback_fn("* Verifying instance %s" % instance.name)
+ self._VerifyInstance(instance, node_image, instdisk[inst_uuid])
# If the instance is non-redundant we cannot survive losing its primary
# node, so we are not N+1 compliant.
- if inst_config.disk_template not in constants.DTS_MIRRORED:
+ if instance.disk_template not in constants.DTS_MIRRORED:
i_non_redundant.append(instance)
- if not cluster.FillBE(inst_config)[constants.BE_AUTO_BALANCE]:
+ if not cluster.FillBE(instance)[constants.BE_AUTO_BALANCE]:
i_non_a_balanced.append(instance)
feedback_fn("* Verifying orphan volumes")
# We will get spurious "unknown volume" warnings if any node of this group
# is secondary for an instance whose primary is in another group. To avoid
# them, we find these instances and add their volumes to node_vol_should.
- for inst in self.all_inst_info.values():
- for secondary in inst.secondary_nodes:
+ for instance in self.all_inst_info.values():
+ for secondary in instance.secondary_nodes:
if (secondary in self.my_node_info
- and inst.name not in self.my_inst_info):
- inst.MapLVsByNode(node_vol_should)
+ and instance.name not in self.my_inst_info):
+ instance.MapLVsByNode(node_vol_should)
break
self._VerifyOrphanVolumes(node_vol_should, node_image, reserved)