Fix verify config if a node has no instances
[ganeti-local] / lib / cmdlib / cluster.py
index 51cc1cd..4c4673f 100644 (file)
@@ -324,6 +324,7 @@ class LUClusterQuery(NoHooksLU):
       "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
@@ -443,7 +444,7 @@ class LUClusterRepairDiskSizes(NoHooksLU):
 
   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 = {
@@ -481,7 +482,7 @@ class LUClusterRepairDiskSizes(NoHooksLU):
       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.
@@ -608,6 +609,68 @@ def _ValidateNetmask(cfg, netmask):
                                (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.
 
@@ -751,6 +814,15 @@ class LUClusterSetParams(LogicalUnit):
     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)
@@ -812,8 +884,8 @@ class LUClusterSetParams(LogicalUnit):
                                              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)
 
@@ -997,6 +1069,17 @@ class LUClusterSetParams(LogicalUnit):
         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.
 
@@ -1006,6 +1089,7 @@ class LUClusterSetParams(LogicalUnit):
         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:
@@ -1054,6 +1138,9 @@ class LUClusterSetParams(LogicalUnit):
                     " 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
 
@@ -1105,7 +1192,13 @@ class LUClusterSetParams(LogicalUnit):
                   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
@@ -1348,6 +1441,13 @@ class LUClusterVerifyConfig(NoHooksLU, _VerifyErrors):
       (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(),
@@ -1367,15 +1467,16 @@ class LUClusterVerifyConfig(NoHooksLU, _VerifyErrors):
 
     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,
@@ -1386,7 +1487,8 @@ class LUClusterVerifyConfig(NoHooksLU, _VerifyErrors):
     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
 
@@ -1462,11 +1564,11 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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: [],
 
@@ -1483,17 +1585,16 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
       # 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
 
@@ -1502,14 +1603,16 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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(
@@ -1517,10 +1620,11 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
         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()
@@ -1529,9 +1633,9 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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.
@@ -1567,12 +1671,9 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
          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
@@ -1583,15 +1684,15 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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
 
@@ -1599,7 +1700,7 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
 
     # 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)
@@ -1608,20 +1709,20 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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
 
@@ -1636,15 +1737,12 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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):
@@ -1654,9 +1752,9 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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.
@@ -1672,23 +1770,20 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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
 
@@ -1724,7 +1819,7 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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
 
@@ -1734,13 +1829,14 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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.
@@ -1754,16 +1850,13 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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
@@ -1773,15 +1866,13 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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)))
 
@@ -1793,42 +1884,38 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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
@@ -1836,40 +1923,39 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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()
@@ -1880,92 +1966,101 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
       # 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.
@@ -1990,7 +2085,7 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
                       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
@@ -2015,10 +2110,10 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
         # 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
@@ -2155,55 +2250,53 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
         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.
@@ -2214,16 +2307,13 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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
 
@@ -2255,25 +2345,24 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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?"
@@ -2285,18 +2374,20 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
                          ("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}
@@ -2306,27 +2397,75 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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.
 
@@ -2335,14 +2474,13 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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.
@@ -2357,19 +2495,16 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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
@@ -2395,7 +2530,8 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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
@@ -2407,43 +2543,40 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     @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
@@ -2457,13 +2590,13 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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
@@ -2473,8 +2606,9 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
 
       # _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)
 
@@ -2514,13 +2648,14 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
                               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
@@ -2606,7 +2741,6 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
       return True
 
     self.bad = False
-    _ErrorIf = self._ErrorIf # pylint: disable=C0103
     verbose = self.op.verbose
     self._feedback_fn = feedback_fn
 
@@ -2674,10 +2808,14 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
       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
@@ -2685,8 +2823,8 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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])
@@ -2710,28 +2848,28 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     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())
@@ -2828,8 +2966,8 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
         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
@@ -2841,8 +2979,10 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
       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)
@@ -2860,17 +3000,18 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
           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)
@@ -2880,19 +3021,18 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
                               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")
@@ -2901,11 +3041,11 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors):
     # 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)