def Exec(self, feedback_fn): # pylint: disable=R0915
    # This method has too many local variables. pylint: disable=R0914
    feedback_fn("* Verifying group '%s'" % self.group_info.name)

    if not self.my_node_uuids:
      # empty node group
      feedback_fn("* Empty node group, skipping verification")
      return True

    self.bad = False
    verbose = self.op.verbose
    self._feedback_fn = feedback_fn

    vg_name = self.cfg.GetVGName()
    drbd_helper = self.cfg.GetDRBDHelper()
    cluster = self.cfg.GetClusterInfo()
    hypervisors = cluster.enabled_hypervisors
    node_data_list = self.my_node_info.values()

    i_non_redundant = [] # Non redundant instances
    i_non_a_balanced = [] # Non auto-balanced instances
    i_offline = 0 # Count of offline instances
    n_offline = 0 # Count of offline nodes
    n_drained = 0 # Count of nodes being drained
    node_vol_should = {}

    # FIXME: verify OS list

    # File verification
    filemap = ComputeAncillaryFiles(cluster, False)

    # do local checksums
    master_node_uuid = self.master_node = self.cfg.GetMasterNode()
    master_ip = self.cfg.GetMasterIP()

    online_master_candidates = sorted(
        node.name for node in node_data_list
        if (node.master_candidate and not node.offline))

    feedback_fn("* Gathering data (%d nodes)" % len(self.my_node_uuids))

    user_scripts = []
    if self.cfg.GetUseExternalMipScript():
      user_scripts.append(pathutils.EXTERNAL_MASTER_SETUP_SCRIPT)

    online_nodes = [(node.name, node.primary_ip, node.secondary_ip)
                    for node in node_data_list if not node.offline]
    node_nettest_params = (online_nodes, online_master_candidates)

    node_verify_param = {
      constants.NV_FILELIST:
        map(vcluster.MakeVirtualPath,
            utils.UniqueSequence(filename
                                 for files in filemap
                                 for filename in files)),
      constants.NV_NODELIST:
        self._SelectSshCheckNodes(node_data_list, self.group_uuid,
                                  self.all_node_info.values()),
      constants.NV_HYPERVISOR: hypervisors,
      constants.NV_HVPARAMS:
        _GetAllHypervisorParameters(cluster, self.all_inst_info.values()),
      constants.NV_NODENETTEST: node_nettest_params,
      constants.NV_INSTANCELIST: hypervisors,
      constants.NV_VERSION: None,
      constants.NV_HVINFO: self.cfg.GetHypervisorType(),
      constants.NV_NODESETUP: None,
      constants.NV_TIME: None,
      constants.NV_MASTERIP: (self.cfg.GetMasterNodeName(), master_ip,
                              online_master_candidates),
      constants.NV_OSLIST: None,
      constants.NV_NONVMNODES: self.cfg.GetNonVmCapableNodeNameList(),
      constants.NV_USERSCRIPTS: user_scripts,
      constants.NV_CLIENT_CERT: None,
      }

    if self.cfg.GetClusterInfo().modify_ssh_setup:
      node_verify_param[constants.NV_SSH_SETUP] = \
        (self._PrepareSshSetupCheck(), self.cfg.GetClusterInfo().ssh_key_type)
      if self.op.verify_clutter:
        node_verify_param[constants.NV_SSH_CLUTTER] = True

    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]

    if cluster.IsDiskTemplateEnabled(constants.DT_DRBD8):
      if drbd_helper:
        node_verify_param[constants.NV_DRBDVERSION] = None
        node_verify_param[constants.NV_DRBDLIST] = None
        node_verify_param[constants.NV_DRBDHELPER] = drbd_helper

    if cluster.IsFileStorageEnabled() or \
        cluster.IsSharedFileStorageEnabled():
      # Load file storage paths only from master node
      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
      if cluster.IsSharedFileStorageEnabled():
        node_verify_param[constants.NV_SHARED_FILE_STORAGE_PATH] = \
          cluster.shared_file_storage_dir

    # bridge checks
    # FIXME: this needs to be changed per node-group, not cluster-wide
    bridges = set()
    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 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 bridges:
      node_verify_param[constants.NV_BRIDGES] = list(bridges)

    # Build our expected cluster state
    node_image = dict((node.uuid, self.NodeImage(offline=node.offline,
                                                 uuid=node.uuid,
                                                 vm_capable=node.vm_capable))
                      for node in node_data_list)

    # Gather OOB paths
    oob_paths = []
    for node in self.all_node_info.values():
      path = SupportsOob(self.cfg, node)
      if path and path not in oob_paths:
        oob_paths.append(path)

    if oob_paths:
      node_verify_param[constants.NV_OOB_PATHS] = oob_paths

    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

      inst_nodes = self.cfg.GetInstanceNodes(instance.uuid)
      for nuuid in inst_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

      self.cfg.GetInstanceLVsByNode(instance.uuid, lvmap=node_vol_should)

      pnode = instance.primary_node
      node_image[pnode].pinst.append(instance.uuid)

      for snode in self.cfg.GetInstanceSecondaryNodes(instance.uuid):
        nimg = node_image[snode]
        nimg.sinst.append(instance.uuid)
        if pnode not in nimg.sbp:
          nimg.sbp[pnode] = []
        nimg.sbp[pnode].append(instance.uuid)

    es_flags = rpc.GetExclusiveStorageForNodes(self.cfg,
                                               self.my_node_info.keys())
    # The value of exclusive_storage should be the same across the group, so if
    # it's True for at least a node, we act as if it were set for all the nodes
    self._exclusive_storage = compat.any(es_flags.values())
    if self._exclusive_storage:
      node_verify_param[constants.NV_EXCLUSIVEPVS] = True

    # At this point, we have the in-memory data structures complete,
    # except for the runtime information, which we'll gather next

    # NOTE: Here we lock the configuration for the duration of RPC calls,
    # which means that the cluster configuration changes are blocked during
    # this period.
    # This is something that should be done only exceptionally and only for
    # justified cases!
    # In this case, we need the lock as we can only verify the integrity of
    # configuration files on MCs only if we know nobody else is modifying it.
    # FIXME: The check for integrity of config.data should be moved to
    # WConfD, which is the only one who can otherwise ensure nobody
    # will modify the configuration during the check.
    with self.cfg.GetConfigManager(shared=True, forcelock=True):
      feedback_fn("* Gathering information about nodes (%s nodes)" %
                  len(self.my_node_uuids))
      # Force the configuration to be fully distributed before doing any tests
      self.cfg.FlushConfigGroup(self.group_uuid)
      # Due to the way our RPC system works, exact response times cannot be
      # guaranteed (e.g. a broken node could run into a timeout). By keeping
      # the time before and after executing the request, we can at least have
      # a time window.
      nvinfo_starttime = time.time()
      # Get lock on the configuration so that nobody modifies it concurrently.
      # Otherwise it can be modified by other jobs, failing the consistency
      # test.
      # NOTE: This is an exceptional situation, we should otherwise avoid
      # locking the configuration for something but very fast, pure operations.
      cluster_name = self.cfg.GetClusterName()
      hvparams = self.cfg.GetClusterInfo().hvparams

      all_nvinfo = self.rpc.call_node_verify(self.my_node_uuids,
                                             node_verify_param,
                                             cluster_name,
                                             hvparams)
      nvinfo_endtime = time.time()

      if self.extra_lv_nodes and vg_name is not None:
        feedback_fn("* Gathering information about extra nodes (%s nodes)" %
                    len(self.extra_lv_nodes))
        extra_lv_nvinfo = \
            self.rpc.call_node_verify(self.extra_lv_nodes,
                                      {constants.NV_LVLIST: vg_name},
                                      self.cfg.GetClusterName(),
                                      self.cfg.GetClusterInfo().hvparams)
      else:
        extra_lv_nvinfo = {}

      # If not all nodes are being checked, we need to make sure the master
      # node and a non-checked vm_capable node are in the list.
      absent_node_uuids = set(self.all_node_info).difference(self.my_node_info)
      if absent_node_uuids:
        vf_nvinfo = all_nvinfo.copy()
        vf_node_info = list(self.my_node_info.values())
        additional_node_uuids = []
        if master_node_uuid not in self.my_node_info:
          additional_node_uuids.append(master_node_uuid)
          vf_node_info.append(self.all_node_info[master_node_uuid])
        # Add the first vm_capable node we find which is not included,
        # excluding the master node (which we already have)
        for node_uuid in absent_node_uuids:
          nodeinfo = self.all_node_info[node_uuid]
          if (nodeinfo.vm_capable and not nodeinfo.offline and
              node_uuid != master_node_uuid):
            additional_node_uuids.append(node_uuid)
            vf_node_info.append(self.all_node_info[node_uuid])
            break
        key = constants.NV_FILELIST

        feedback_fn("* Gathering information about the master node")
        vf_nvinfo.update(self.rpc.call_node_verify(
           additional_node_uuids, {key: node_verify_param[key]},
           self.cfg.GetClusterName(), self.cfg.GetClusterInfo().hvparams))
      else:
        vf_nvinfo = all_nvinfo
        vf_node_info = self.my_node_info.values()

    all_drbd_map = self.cfg.ComputeDRBDMap()

    feedback_fn("* Gathering disk information (%s nodes)" %
                len(self.my_node_uuids))
    instdisk = self._CollectDiskInfo(self.my_node_info.keys(), node_image,
                                     self.my_inst_info)

    feedback_fn("* Verifying configuration file consistency")

    self._VerifyClientCertificates(self.my_node_info.values(), all_nvinfo)
    if self.cfg.GetClusterInfo().modify_ssh_setup:
      self._VerifySshSetup(self.my_node_info.values(), all_nvinfo)
    self._VerifyFiles(vf_node_info, master_node_uuid, vf_nvinfo, filemap)

    feedback_fn("* Verifying node status")

    refos_img = None

    for node_i in node_data_list:
      nimg = node_image[node_i.uuid]

      if node_i.offline:
        if verbose:
          feedback_fn("* Skipping offline node %s" % (node_i.name,))
        n_offline += 1
        continue

      if node_i.uuid == master_node_uuid:
        ntype = "master"
      elif node_i.master_candidate:
        ntype = "master candidate"
      elif node_i.drained:
        ntype = "drained"
        n_drained += 1
      else:
        ntype = "regular"
      if verbose:
        feedback_fn("* Verifying node %s (%s)" % (node_i.name, ntype))

      msg = all_nvinfo[node_i.uuid].fail_msg
      self._ErrorIf(msg, constants.CV_ENODERPC, node_i.name,
                    "while contacting node: %s", msg)
      if msg:
        nimg.rpc_fail = True
        continue

      nresult = all_nvinfo[node_i.uuid].payload

      nimg.call_ok = self._VerifyNode(node_i, nresult)
      self._VerifyNodeTime(node_i, nresult, nvinfo_starttime, nvinfo_endtime)
      self._VerifyNodeNetwork(node_i, nresult)
      self._VerifyNodeUserScripts(node_i, nresult)
      self._VerifyOob(node_i, nresult)
      self._VerifyAcceptedFileStoragePaths(node_i, nresult,
                                           node_i.uuid == master_node_uuid)
      self._VerifyFileStoragePaths(node_i, nresult)
      self._VerifySharedFileStoragePaths(node_i, nresult)
      self._VerifyGlusterStoragePaths(node_i, nresult)

      if nimg.vm_capable:
        self._UpdateVerifyNodeLVM(node_i, nresult, vg_name, nimg)
        if constants.DT_DRBD8 in cluster.enabled_disk_templates:
          self._VerifyNodeDrbd(node_i, nresult, self.all_inst_info,
                               self.all_disks_info, drbd_helper, all_drbd_map)

        if (constants.DT_PLAIN in cluster.enabled_disk_templates) or \
            (constants.DT_DRBD8 in cluster.enabled_disk_templates):
          self._UpdateNodeVolumes(node_i, nresult, nimg, vg_name)
        self._UpdateNodeInstances(node_i, nresult, nimg)
        self._UpdateNodeInfo(node_i, nresult, nimg, vg_name)
        self._UpdateNodeOS(node_i, nresult, nimg)

        if not nimg.os_fail:
          if refos_img is None:
            refos_img = nimg
          self._VerifyNodeOS(node_i, nimg, refos_img)
        self._VerifyNodeBridges(node_i, nresult, bridges)

        # 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_uuids = set(nimg.instances).difference(nimg.pinst)

        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._VerifyExclusionTags(node_i.name, nimg.pinst, cluster.tags)

    self._VerifyGroupDRBDVersion(all_nvinfo)
    self._VerifyGroupLVM(node_image, vg_name)

    for node_uuid, result in extra_lv_nvinfo.items():
      self._UpdateNodeVolumes(self.all_node_info[node_uuid], result.payload,
                              node_image[node_uuid], vg_name)

    feedback_fn("* Verifying instance status")
    for inst_uuid in self.my_inst_uuids:
      instance = self.my_inst_info[inst_uuid]
      if verbose:
        feedback_fn("* Verifying instance %s" % instance.name)
      self._VerifyInstance(instance, node_image, instdisk[inst_uuid])

      # If the instance is not fully redundant we cannot survive losing its
      # primary node, so we are not N+1 compliant.
      inst_disks = self.cfg.GetInstanceDisks(instance.uuid)
      if not utils.AllDiskOfType(inst_disks, constants.DTS_MIRRORED):
        i_non_redundant.append(instance)

      if not cluster.FillBE(instance)[constants.BE_AUTO_BALANCE]:
        i_non_a_balanced.append(instance)

    feedback_fn("* Verifying orphan volumes")
    reserved = utils.FieldSet(*cluster.reserved_lvs)

    # 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 instance in self.all_inst_info.values():
      for secondary in self.cfg.GetInstanceSecondaryNodes(instance.uuid):
        if (secondary in self.my_node_info
            and instance.uuid not in self.my_inst_info):
          self.cfg.GetInstanceLVsByNode(instance.uuid, lvmap=node_vol_should)
          break

    self._VerifyOrphanVolumes(vg_name, node_vol_should, node_image, reserved)

    if constants.VERIFY_NPLUSONE_MEM not in self.op.skip_checks:
      feedback_fn("* Verifying N+1 Memory redundancy")
      self._VerifyNPlusOneMemory(node_image, self.my_inst_info)

    self._VerifyOtherNotes(feedback_fn, i_non_redundant, i_non_a_balanced,
                           i_offline, n_offline, n_drained)

    return not self.bad
Add a child ``<Override>`` element with attributes set to parameter
dataset/ETHPy150Open ganeti/ganeti/lib/cmdlib/cluster/verify.py/LUClusterVerifyGroup.Exec--crossover with--dataset/ETHPy150Open scanny/python-pptx/pptx/opc/oxml.py/CT_Types.add_override