1433 |
1433 |
self.op and self._feedback_fn to be available.)
|
1434 |
1434 |
|
1435 |
1435 |
"""
|
1436 |
|
TCLUSTER = "cluster"
|
1437 |
|
TNODE = "node"
|
1438 |
|
TINSTANCE = "instance"
|
1439 |
|
|
1440 |
|
ECLUSTERCFG = (TCLUSTER, "ECLUSTERCFG")
|
1441 |
|
ECLUSTERCERT = (TCLUSTER, "ECLUSTERCERT")
|
1442 |
|
ECLUSTERFILECHECK = (TCLUSTER, "ECLUSTERFILECHECK")
|
1443 |
|
ECLUSTERDANGLINGNODES = (TNODE, "ECLUSTERDANGLINGNODES")
|
1444 |
|
ECLUSTERDANGLINGINST = (TNODE, "ECLUSTERDANGLINGINST")
|
1445 |
|
EINSTANCEBADNODE = (TINSTANCE, "EINSTANCEBADNODE")
|
1446 |
|
EINSTANCEDOWN = (TINSTANCE, "EINSTANCEDOWN")
|
1447 |
|
EINSTANCELAYOUT = (TINSTANCE, "EINSTANCELAYOUT")
|
1448 |
|
EINSTANCEMISSINGDISK = (TINSTANCE, "EINSTANCEMISSINGDISK")
|
1449 |
|
EINSTANCEFAULTYDISK = (TINSTANCE, "EINSTANCEFAULTYDISK")
|
1450 |
|
EINSTANCEWRONGNODE = (TINSTANCE, "EINSTANCEWRONGNODE")
|
1451 |
|
EINSTANCESPLITGROUPS = (TINSTANCE, "EINSTANCESPLITGROUPS")
|
1452 |
|
ENODEDRBD = (TNODE, "ENODEDRBD")
|
1453 |
|
ENODEDRBDHELPER = (TNODE, "ENODEDRBDHELPER")
|
1454 |
|
ENODEFILECHECK = (TNODE, "ENODEFILECHECK")
|
1455 |
|
ENODEHOOKS = (TNODE, "ENODEHOOKS")
|
1456 |
|
ENODEHV = (TNODE, "ENODEHV")
|
1457 |
|
ENODELVM = (TNODE, "ENODELVM")
|
1458 |
|
ENODEN1 = (TNODE, "ENODEN1")
|
1459 |
|
ENODENET = (TNODE, "ENODENET")
|
1460 |
|
ENODEOS = (TNODE, "ENODEOS")
|
1461 |
|
ENODEORPHANINSTANCE = (TNODE, "ENODEORPHANINSTANCE")
|
1462 |
|
ENODEORPHANLV = (TNODE, "ENODEORPHANLV")
|
1463 |
|
ENODERPC = (TNODE, "ENODERPC")
|
1464 |
|
ENODESSH = (TNODE, "ENODESSH")
|
1465 |
|
ENODEVERSION = (TNODE, "ENODEVERSION")
|
1466 |
|
ENODESETUP = (TNODE, "ENODESETUP")
|
1467 |
|
ENODETIME = (TNODE, "ENODETIME")
|
1468 |
|
ENODEOOBPATH = (TNODE, "ENODEOOBPATH")
|
1469 |
1436 |
|
1470 |
1437 |
ETYPE_FIELD = "code"
|
1471 |
1438 |
ETYPE_ERROR = "ERROR"
|
... | ... | |
1569 |
1536 |
utils.ForceDictType(hv_params, constants.HVS_PARAMETER_TYPES)
|
1570 |
1537 |
hv_class.CheckParameterSyntax(hv_params)
|
1571 |
1538 |
except errors.GenericError, err:
|
1572 |
|
self._ErrorIf(True, self.ECLUSTERCFG, None, msg % str(err))
|
|
1539 |
self._ErrorIf(True, constants.CV_ECLUSTERCFG, None, msg % str(err))
|
1573 |
1540 |
|
1574 |
1541 |
def ExpandNames(self):
|
1575 |
1542 |
# Information can be safely retrieved as the BGL is acquired in exclusive
|
... | ... | |
1590 |
1557 |
feedback_fn("* Verifying cluster config")
|
1591 |
1558 |
|
1592 |
1559 |
for msg in self.cfg.VerifyConfig():
|
1593 |
|
self._ErrorIf(True, self.ECLUSTERCFG, None, msg)
|
|
1560 |
self._ErrorIf(True, constants.CV_ECLUSTERCFG, None, msg)
|
1594 |
1561 |
|
1595 |
1562 |
feedback_fn("* Verifying cluster certificate files")
|
1596 |
1563 |
|
1597 |
1564 |
for cert_filename in constants.ALL_CERT_FILES:
|
1598 |
1565 |
(errcode, msg) = _VerifyCertificate(cert_filename)
|
1599 |
|
self._ErrorIf(errcode, self.ECLUSTERCERT, None, msg, code=errcode)
|
|
1566 |
self._ErrorIf(errcode, constants.CV_ECLUSTERCERT, None, msg, code=errcode)
|
1600 |
1567 |
|
1601 |
1568 |
feedback_fn("* Verifying hypervisor parameters")
|
1602 |
1569 |
|
... | ... | |
1628 |
1595 |
["no instances"])))
|
1629 |
1596 |
for node in dangling_nodes]
|
1630 |
1597 |
|
1631 |
|
self._ErrorIf(bool(dangling_nodes), self.ECLUSTERDANGLINGNODES, None,
|
|
1598 |
self._ErrorIf(bool(dangling_nodes), constants.CV_ECLUSTERDANGLINGNODES,
|
|
1599 |
None,
|
1632 |
1600 |
"the following nodes (and their instances) belong to a non"
|
1633 |
1601 |
" existing group: %s", utils.CommaJoin(pretty_dangling))
|
1634 |
1602 |
|
1635 |
|
self._ErrorIf(bool(no_node_instances), self.ECLUSTERDANGLINGINST, None,
|
|
1603 |
self._ErrorIf(bool(no_node_instances), constants.CV_ECLUSTERDANGLINGINST,
|
|
1604 |
None,
|
1636 |
1605 |
"the following instances have a non-existing primary-node:"
|
1637 |
1606 |
" %s", utils.CommaJoin(no_node_instances))
|
1638 |
1607 |
|
... | ... | |
1805 |
1774 |
|
1806 |
1775 |
# main result, nresult should be a non-empty dict
|
1807 |
1776 |
test = not nresult or not isinstance(nresult, dict)
|
1808 |
|
_ErrorIf(test, self.ENODERPC, node,
|
|
1777 |
_ErrorIf(test, constants.CV_ENODERPC, node,
|
1809 |
1778 |
"unable to verify node: no data returned")
|
1810 |
1779 |
if test:
|
1811 |
1780 |
return False
|
... | ... | |
1816 |
1785 |
test = not (remote_version and
|
1817 |
1786 |
isinstance(remote_version, (list, tuple)) and
|
1818 |
1787 |
len(remote_version) == 2)
|
1819 |
|
_ErrorIf(test, self.ENODERPC, node,
|
|
1788 |
_ErrorIf(test, constants.CV_ENODERPC, node,
|
1820 |
1789 |
"connection to node returned invalid data")
|
1821 |
1790 |
if test:
|
1822 |
1791 |
return False
|
1823 |
1792 |
|
1824 |
1793 |
test = local_version != remote_version[0]
|
1825 |
|
_ErrorIf(test, self.ENODEVERSION, node,
|
|
1794 |
_ErrorIf(test, constants.CV_ENODEVERSION, node,
|
1826 |
1795 |
"incompatible protocol versions: master %s,"
|
1827 |
1796 |
" node %s", local_version, remote_version[0])
|
1828 |
1797 |
if test:
|
... | ... | |
1832 |
1801 |
|
1833 |
1802 |
# full package version
|
1834 |
1803 |
self._ErrorIf(constants.RELEASE_VERSION != remote_version[1],
|
1835 |
|
self.ENODEVERSION, node,
|
|
1804 |
constants.CV_ENODEVERSION, node,
|
1836 |
1805 |
"software version mismatch: master %s, node %s",
|
1837 |
1806 |
constants.RELEASE_VERSION, remote_version[1],
|
1838 |
1807 |
code=self.ETYPE_WARNING)
|
... | ... | |
1841 |
1810 |
if ninfo.vm_capable and isinstance(hyp_result, dict):
|
1842 |
1811 |
for hv_name, hv_result in hyp_result.iteritems():
|
1843 |
1812 |
test = hv_result is not None
|
1844 |
|
_ErrorIf(test, self.ENODEHV, node,
|
|
1813 |
_ErrorIf(test, constants.CV_ENODEHV, node,
|
1845 |
1814 |
"hypervisor %s verify failure: '%s'", hv_name, hv_result)
|
1846 |
1815 |
|
1847 |
1816 |
hvp_result = nresult.get(constants.NV_HVPARAMS, None)
|
1848 |
1817 |
if ninfo.vm_capable and isinstance(hvp_result, list):
|
1849 |
1818 |
for item, hv_name, hv_result in hvp_result:
|
1850 |
|
_ErrorIf(True, self.ENODEHV, node,
|
|
1819 |
_ErrorIf(True, constants.CV_ENODEHV, node,
|
1851 |
1820 |
"hypervisor %s parameter verify failure (source %s): %s",
|
1852 |
1821 |
hv_name, item, hv_result)
|
1853 |
1822 |
|
1854 |
1823 |
test = nresult.get(constants.NV_NODESETUP,
|
1855 |
1824 |
["Missing NODESETUP results"])
|
1856 |
|
_ErrorIf(test, self.ENODESETUP, node, "node setup error: %s",
|
|
1825 |
_ErrorIf(test, constants.CV_ENODESETUP, node, "node setup error: %s",
|
1857 |
1826 |
"; ".join(test))
|
1858 |
1827 |
|
1859 |
1828 |
return True
|
... | ... | |
1876 |
1845 |
try:
|
1877 |
1846 |
ntime_merged = utils.MergeTime(ntime)
|
1878 |
1847 |
except (ValueError, TypeError):
|
1879 |
|
_ErrorIf(True, self.ENODETIME, node, "Node returned invalid time")
|
|
1848 |
_ErrorIf(True, constants.CV_ENODETIME, node, "Node returned invalid time")
|
1880 |
1849 |
return
|
1881 |
1850 |
|
1882 |
1851 |
if ntime_merged < (nvinfo_starttime - constants.NODE_MAX_CLOCK_SKEW):
|
... | ... | |
1886 |
1855 |
else:
|
1887 |
1856 |
ntime_diff = None
|
1888 |
1857 |
|
1889 |
|
_ErrorIf(ntime_diff is not None, self.ENODETIME, node,
|
|
1858 |
_ErrorIf(ntime_diff is not None, constants.CV_ENODETIME, node,
|
1890 |
1859 |
"Node time diverges by at least %s from master node time",
|
1891 |
1860 |
ntime_diff)
|
1892 |
1861 |
|
... | ... | |
1908 |
1877 |
# checks vg existence and size > 20G
|
1909 |
1878 |
vglist = nresult.get(constants.NV_VGLIST, None)
|
1910 |
1879 |
test = not vglist
|
1911 |
|
_ErrorIf(test, self.ENODELVM, node, "unable to check volume groups")
|
|
1880 |
_ErrorIf(test, constants.CV_ENODELVM, node, "unable to check volume groups")
|
1912 |
1881 |
if not test:
|
1913 |
1882 |
vgstatus = utils.CheckVolumeGroupSize(vglist, vg_name,
|
1914 |
1883 |
constants.MIN_VG_SIZE)
|
1915 |
|
_ErrorIf(vgstatus, self.ENODELVM, node, vgstatus)
|
|
1884 |
_ErrorIf(vgstatus, constants.CV_ENODELVM, node, vgstatus)
|
1916 |
1885 |
|
1917 |
1886 |
# check pv names
|
1918 |
1887 |
pvlist = nresult.get(constants.NV_PVLIST, None)
|
1919 |
1888 |
test = pvlist is None
|
1920 |
|
_ErrorIf(test, self.ENODELVM, node, "Can't get PV list from node")
|
|
1889 |
_ErrorIf(test, constants.CV_ENODELVM, node, "Can't get PV list from node")
|
1921 |
1890 |
if not test:
|
1922 |
1891 |
# check that ':' is not present in PV names, since it's a
|
1923 |
1892 |
# special character for lvcreate (denotes the range of PEs to
|
1924 |
1893 |
# use on the PV)
|
1925 |
1894 |
for _, pvname, owner_vg in pvlist:
|
1926 |
1895 |
test = ":" in pvname
|
1927 |
|
_ErrorIf(test, self.ENODELVM, node, "Invalid character ':' in PV"
|
1928 |
|
" '%s' of VG '%s'", pvname, owner_vg)
|
|
1896 |
_ErrorIf(test, constants.CV_ENODELVM, node,
|
|
1897 |
"Invalid character ':' in PV '%s' of VG '%s'",
|
|
1898 |
pvname, owner_vg)
|
1929 |
1899 |
|
1930 |
1900 |
def _VerifyNodeBridges(self, ninfo, nresult, bridges):
|
1931 |
1901 |
"""Check the node bridges.
|
... | ... | |
1944 |
1914 |
|
1945 |
1915 |
missing = nresult.get(constants.NV_BRIDGES, None)
|
1946 |
1916 |
test = not isinstance(missing, list)
|
1947 |
|
_ErrorIf(test, self.ENODENET, node,
|
|
1917 |
_ErrorIf(test, constants.CV_ENODENET, node,
|
1948 |
1918 |
"did not return valid bridge information")
|
1949 |
1919 |
if not test:
|
1950 |
|
_ErrorIf(bool(missing), self.ENODENET, node, "missing bridges: %s" %
|
1951 |
|
utils.CommaJoin(sorted(missing)))
|
|
1920 |
_ErrorIf(bool(missing), constants.CV_ENODENET, node,
|
|
1921 |
"missing bridges: %s" % utils.CommaJoin(sorted(missing)))
|
1952 |
1922 |
|
1953 |
1923 |
def _VerifyNodeNetwork(self, ninfo, nresult):
|
1954 |
1924 |
"""Check the node network connectivity results.
|
... | ... | |
1962 |
1932 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103
|
1963 |
1933 |
|
1964 |
1934 |
test = constants.NV_NODELIST not in nresult
|
1965 |
|
_ErrorIf(test, self.ENODESSH, node,
|
|
1935 |
_ErrorIf(test, constants.CV_ENODESSH, node,
|
1966 |
1936 |
"node hasn't returned node ssh connectivity data")
|
1967 |
1937 |
if not test:
|
1968 |
1938 |
if nresult[constants.NV_NODELIST]:
|
1969 |
1939 |
for a_node, a_msg in nresult[constants.NV_NODELIST].items():
|
1970 |
|
_ErrorIf(True, self.ENODESSH, node,
|
|
1940 |
_ErrorIf(True, constants.CV_ENODESSH, node,
|
1971 |
1941 |
"ssh communication with node '%s': %s", a_node, a_msg)
|
1972 |
1942 |
|
1973 |
1943 |
test = constants.NV_NODENETTEST not in nresult
|
1974 |
|
_ErrorIf(test, self.ENODENET, node,
|
|
1944 |
_ErrorIf(test, constants.CV_ENODENET, node,
|
1975 |
1945 |
"node hasn't returned node tcp connectivity data")
|
1976 |
1946 |
if not test:
|
1977 |
1947 |
if nresult[constants.NV_NODENETTEST]:
|
1978 |
1948 |
nlist = utils.NiceSort(nresult[constants.NV_NODENETTEST].keys())
|
1979 |
1949 |
for anode in nlist:
|
1980 |
|
_ErrorIf(True, self.ENODENET, node,
|
|
1950 |
_ErrorIf(True, constants.CV_ENODENET, node,
|
1981 |
1951 |
"tcp communication with node '%s': %s",
|
1982 |
1952 |
anode, nresult[constants.NV_NODENETTEST][anode])
|
1983 |
1953 |
|
1984 |
1954 |
test = constants.NV_MASTERIP not in nresult
|
1985 |
|
_ErrorIf(test, self.ENODENET, node,
|
|
1955 |
_ErrorIf(test, constants.CV_ENODENET, node,
|
1986 |
1956 |
"node hasn't returned node master IP reachability data")
|
1987 |
1957 |
if not test:
|
1988 |
1958 |
if not nresult[constants.NV_MASTERIP]:
|
... | ... | |
1990 |
1960 |
msg = "the master node cannot reach the master IP (not configured?)"
|
1991 |
1961 |
else:
|
1992 |
1962 |
msg = "cannot reach the master IP"
|
1993 |
|
_ErrorIf(True, self.ENODENET, node, msg)
|
|
1963 |
_ErrorIf(True, constants.CV_ENODENET, node, msg)
|
1994 |
1964 |
|
1995 |
1965 |
def _VerifyInstance(self, instance, instanceconfig, node_image,
|
1996 |
1966 |
diskstatus):
|
... | ... | |
2013 |
1983 |
continue
|
2014 |
1984 |
for volume in node_vol_should[node]:
|
2015 |
1985 |
test = volume not in n_img.volumes
|
2016 |
|
_ErrorIf(test, self.EINSTANCEMISSINGDISK, instance,
|
|
1986 |
_ErrorIf(test, constants.CV_EINSTANCEMISSINGDISK, instance,
|
2017 |
1987 |
"volume %s missing on node %s", volume, node)
|
2018 |
1988 |
|
2019 |
1989 |
if instanceconfig.admin_up:
|
2020 |
1990 |
pri_img = node_image[node_current]
|
2021 |
1991 |
test = instance not in pri_img.instances and not pri_img.offline
|
2022 |
|
_ErrorIf(test, self.EINSTANCEDOWN, instance,
|
|
1992 |
_ErrorIf(test, constants.CV_EINSTANCEDOWN, instance,
|
2023 |
1993 |
"instance not running on its primary node %s",
|
2024 |
1994 |
node_current)
|
2025 |
1995 |
|
... | ... | |
2033 |
2003 |
snode = node_image[nname]
|
2034 |
2004 |
bad_snode = snode.ghost or snode.offline
|
2035 |
2005 |
_ErrorIf(instanceconfig.admin_up and not success and not bad_snode,
|
2036 |
|
self.EINSTANCEFAULTYDISK, instance,
|
|
2006 |
constants.CV_EINSTANCEFAULTYDISK, instance,
|
2037 |
2007 |
"couldn't retrieve status for disk/%s on %s: %s",
|
2038 |
2008 |
idx, nname, bdev_status)
|
2039 |
2009 |
_ErrorIf((instanceconfig.admin_up and success and
|
2040 |
2010 |
bdev_status.ldisk_status == constants.LDS_FAULTY),
|
2041 |
|
self.EINSTANCEFAULTYDISK, instance,
|
|
2011 |
constants.CV_EINSTANCEFAULTYDISK, instance,
|
2042 |
2012 |
"disk/%s on %s is faulty", idx, nname)
|
2043 |
2013 |
|
2044 |
2014 |
def _VerifyOrphanVolumes(self, node_vol_should, node_image, reserved):
|
... | ... | |
2059 |
2029 |
test = ((node not in node_vol_should or
|
2060 |
2030 |
volume not in node_vol_should[node]) and
|
2061 |
2031 |
not reserved.Matches(volume))
|
2062 |
|
self._ErrorIf(test, self.ENODEORPHANLV, node,
|
|
2032 |
self._ErrorIf(test, constants.CV_ENODEORPHANLV, node,
|
2063 |
2033 |
"volume %s is unknown", volume)
|
2064 |
2034 |
|
2065 |
2035 |
def _VerifyNPlusOneMemory(self, node_image, instance_cfg):
|
... | ... | |
2092 |
2062 |
if bep[constants.BE_AUTO_BALANCE]:
|
2093 |
2063 |
needed_mem += bep[constants.BE_MEMORY]
|
2094 |
2064 |
test = n_img.mfree < needed_mem
|
2095 |
|
self._ErrorIf(test, self.ENODEN1, node,
|
|
2065 |
self._ErrorIf(test, constants.CV_ENODEN1, node,
|
2096 |
2066 |
"not enough memory to accomodate instance failovers"
|
2097 |
2067 |
" should node %s fail (%dMiB needed, %dMiB available)",
|
2098 |
2068 |
prinode, needed_mem, n_img.mfree)
|
... | ... | |
2150 |
2120 |
node_files = nresult.payload.get(constants.NV_FILELIST, None)
|
2151 |
2121 |
|
2152 |
2122 |
test = not (node_files and isinstance(node_files, dict))
|
2153 |
|
errorif(test, cls.ENODEFILECHECK, node.name,
|
|
2123 |
errorif(test, constants.CV_ENODEFILECHECK, node.name,
|
2154 |
2124 |
"Node did not return file checksum data")
|
2155 |
2125 |
if test:
|
2156 |
2126 |
ignore_nodes.add(node.name)
|
... | ... | |
2177 |
2147 |
if filename in files_all_opt:
|
2178 |
2148 |
# All or no nodes
|
2179 |
2149 |
errorif(missing_file and missing_file != expected_nodes,
|
2180 |
|
cls.ECLUSTERFILECHECK, None,
|
|
2150 |
constants.CV_ECLUSTERFILECHECK, None,
|
2181 |
2151 |
"File %s is optional, but it must exist on all or no"
|
2182 |
2152 |
" nodes (not found on %s)",
|
2183 |
2153 |
filename, utils.CommaJoin(utils.NiceSort(missing_file)))
|
2184 |
2154 |
else:
|
2185 |
|
# Non-optional files
|
2186 |
|
errorif(missing_file, cls.ECLUSTERFILECHECK, None,
|
|
2155 |
errorif(missing_file, constants.CV_ECLUSTERFILECHECK, None,
|
2187 |
2156 |
"File %s is missing from node(s) %s", filename,
|
2188 |
2157 |
utils.CommaJoin(utils.NiceSort(missing_file)))
|
2189 |
2158 |
|
2190 |
2159 |
# Warn if a node has a file it shouldn't
|
2191 |
2160 |
unexpected = with_file - expected_nodes
|
2192 |
2161 |
errorif(unexpected,
|
2193 |
|
cls.ECLUSTERFILECHECK, None,
|
|
2162 |
constants.CV_ECLUSTERFILECHECK, None,
|
2194 |
2163 |
"File %s should not exist on node(s) %s",
|
2195 |
2164 |
filename, utils.CommaJoin(utils.NiceSort(unexpected)))
|
2196 |
2165 |
|
... | ... | |
2204 |
2173 |
else:
|
2205 |
2174 |
variants = []
|
2206 |
2175 |
|
2207 |
|
errorif(test, cls.ECLUSTERFILECHECK, None,
|
|
2176 |
errorif(test, constants.CV_ECLUSTERFILECHECK, None,
|
2208 |
2177 |
"File %s found with %s different checksums (%s)",
|
2209 |
2178 |
filename, len(checksums), "; ".join(variants))
|
2210 |
2179 |
|
... | ... | |
2227 |
2196 |
if drbd_helper:
|
2228 |
2197 |
helper_result = nresult.get(constants.NV_DRBDHELPER, None)
|
2229 |
2198 |
test = (helper_result == None)
|
2230 |
|
_ErrorIf(test, self.ENODEDRBDHELPER, node,
|
|
2199 |
_ErrorIf(test, constants.CV_ENODEDRBDHELPER, node,
|
2231 |
2200 |
"no drbd usermode helper returned")
|
2232 |
2201 |
if helper_result:
|
2233 |
2202 |
status, payload = helper_result
|
2234 |
2203 |
test = not status
|
2235 |
|
_ErrorIf(test, self.ENODEDRBDHELPER, node,
|
|
2204 |
_ErrorIf(test, constants.CV_ENODEDRBDHELPER, node,
|
2236 |
2205 |
"drbd usermode helper check unsuccessful: %s", payload)
|
2237 |
2206 |
test = status and (payload != drbd_helper)
|
2238 |
|
_ErrorIf(test, self.ENODEDRBDHELPER, node,
|
|
2207 |
_ErrorIf(test, constants.CV_ENODEDRBDHELPER, node,
|
2239 |
2208 |
"wrong drbd usermode helper: %s", payload)
|
2240 |
2209 |
|
2241 |
2210 |
# compute the DRBD minors
|
2242 |
2211 |
node_drbd = {}
|
2243 |
2212 |
for minor, instance in drbd_map[node].items():
|
2244 |
2213 |
test = instance not in instanceinfo
|
2245 |
|
_ErrorIf(test, self.ECLUSTERCFG, None,
|
|
2214 |
_ErrorIf(test, constants.CV_ECLUSTERCFG, None,
|
2246 |
2215 |
"ghost instance '%s' in temporary DRBD map", instance)
|
2247 |
2216 |
# ghost instance should not be running, but otherwise we
|
2248 |
2217 |
# don't give double warnings (both ghost instance and
|
... | ... | |
2256 |
2225 |
# and now check them
|
2257 |
2226 |
used_minors = nresult.get(constants.NV_DRBDLIST, [])
|
2258 |
2227 |
test = not isinstance(used_minors, (tuple, list))
|
2259 |
|
_ErrorIf(test, self.ENODEDRBD, node,
|
|
2228 |
_ErrorIf(test, constants.CV_ENODEDRBD, node,
|
2260 |
2229 |
"cannot parse drbd status file: %s", str(used_minors))
|
2261 |
2230 |
if test:
|
2262 |
2231 |
# we cannot check drbd status
|
... | ... | |
2264 |
2233 |
|
2265 |
2234 |
for minor, (iname, must_exist) in node_drbd.items():
|
2266 |
2235 |
test = minor not in used_minors and must_exist
|
2267 |
|
_ErrorIf(test, self.ENODEDRBD, node,
|
|
2236 |
_ErrorIf(test, constants.CV_ENODEDRBD, node,
|
2268 |
2237 |
"drbd minor %d of instance %s is not active", minor, iname)
|
2269 |
2238 |
for minor in used_minors:
|
2270 |
2239 |
test = minor not in node_drbd
|
2271 |
|
_ErrorIf(test, self.ENODEDRBD, node,
|
|
2240 |
_ErrorIf(test, constants.CV_ENODEDRBD, node,
|
2272 |
2241 |
"unallocated drbd minor %d is in use", minor)
|
2273 |
2242 |
|
2274 |
2243 |
def _UpdateNodeOS(self, ninfo, nresult, nimg):
|
... | ... | |
2288 |
2257 |
not compat.all(isinstance(v, list) and len(v) == 7
|
2289 |
2258 |
for v in remote_os))
|
2290 |
2259 |
|
2291 |
|
_ErrorIf(test, self.ENODEOS, node,
|
|
2260 |
_ErrorIf(test, constants.CV_ENODEOS, node,
|
2292 |
2261 |
"node hasn't returned valid OS data")
|
2293 |
2262 |
|
2294 |
2263 |
nimg.os_fail = test
|
... | ... | |
2330 |
2299 |
for os_name, os_data in nimg.oslist.items():
|
2331 |
2300 |
assert os_data, "Empty OS status for OS %s?!" % os_name
|
2332 |
2301 |
f_path, f_status, f_diag, f_var, f_param, f_api = os_data[0]
|
2333 |
|
_ErrorIf(not f_status, self.ENODEOS, node,
|
|
2302 |
_ErrorIf(not f_status, constants.CV_ENODEOS, node,
|
2334 |
2303 |
"Invalid OS %s (located at %s): %s", os_name, f_path, f_diag)
|
2335 |
|
_ErrorIf(len(os_data) > 1, self.ENODEOS, node,
|
|
2304 |
_ErrorIf(len(os_data) > 1, constants.CV_ENODEOS, node,
|
2336 |
2305 |
"OS '%s' has multiple entries (first one shadows the rest): %s",
|
2337 |
2306 |
os_name, utils.CommaJoin([v[0] for v in os_data]))
|
2338 |
2307 |
# comparisons with the 'base' image
|
2339 |
2308 |
test = os_name not in base.oslist
|
2340 |
|
_ErrorIf(test, self.ENODEOS, node,
|
|
2309 |
_ErrorIf(test, constants.CV_ENODEOS, node,
|
2341 |
2310 |
"Extra OS %s not present on reference node (%s)",
|
2342 |
2311 |
os_name, base.name)
|
2343 |
2312 |
if test:
|
... | ... | |
2351 |
2320 |
("variants list", f_var, b_var),
|
2352 |
2321 |
("parameters", beautify_params(f_param),
|
2353 |
2322 |
beautify_params(b_param))]:
|
2354 |
|
_ErrorIf(a != b, self.ENODEOS, node,
|
|
2323 |
_ErrorIf(a != b, constants.CV_ENODEOS, node,
|
2355 |
2324 |
"OS %s for %s differs from reference node %s: [%s] vs. [%s]",
|
2356 |
2325 |
kind, os_name, base.name,
|
2357 |
2326 |
utils.CommaJoin(sorted(a)), utils.CommaJoin(sorted(b)))
|
2358 |
2327 |
|
2359 |
2328 |
# check any missing OSes
|
2360 |
2329 |
missing = set(base.oslist.keys()).difference(nimg.oslist.keys())
|
2361 |
|
_ErrorIf(missing, self.ENODEOS, node,
|
|
2330 |
_ErrorIf(missing, constants.CV_ENODEOS, node,
|
2362 |
2331 |
"OSes present on reference node %s but missing on this node: %s",
|
2363 |
2332 |
base.name, utils.CommaJoin(missing))
|
2364 |
2333 |
|
... | ... | |
2376 |
2345 |
if ((ninfo.master_candidate or ninfo.master_capable) and
|
2377 |
2346 |
constants.NV_OOB_PATHS in nresult):
|
2378 |
2347 |
for path_result in nresult[constants.NV_OOB_PATHS]:
|
2379 |
|
self._ErrorIf(path_result, self.ENODEOOBPATH, node, path_result)
|
|
2348 |
self._ErrorIf(path_result, constants.CV_ENODEOOBPATH, node, path_result)
|
2380 |
2349 |
|
2381 |
2350 |
def _UpdateNodeVolumes(self, ninfo, nresult, nimg, vg_name):
|
2382 |
2351 |
"""Verifies and updates the node volume data.
|
... | ... | |
2399 |
2368 |
if vg_name is None:
|
2400 |
2369 |
pass
|
2401 |
2370 |
elif isinstance(lvdata, basestring):
|
2402 |
|
_ErrorIf(True, self.ENODELVM, node, "LVM problem on node: %s",
|
|
2371 |
_ErrorIf(True, constants.CV_ENODELVM, node, "LVM problem on node: %s",
|
2403 |
2372 |
utils.SafeEncode(lvdata))
|
2404 |
2373 |
elif not isinstance(lvdata, dict):
|
2405 |
|
_ErrorIf(True, self.ENODELVM, node, "rpc call to node failed (lvlist)")
|
|
2374 |
_ErrorIf(True, constants.CV_ENODELVM, node,
|
|
2375 |
"rpc call to node failed (lvlist)")
|
2406 |
2376 |
else:
|
2407 |
2377 |
nimg.volumes = lvdata
|
2408 |
2378 |
nimg.lvm_fail = False
|
... | ... | |
2422 |
2392 |
"""
|
2423 |
2393 |
idata = nresult.get(constants.NV_INSTANCELIST, None)
|
2424 |
2394 |
test = not isinstance(idata, list)
|
2425 |
|
self._ErrorIf(test, self.ENODEHV, ninfo.name, "rpc call to node failed"
|
2426 |
|
" (instancelist): %s", utils.SafeEncode(str(idata)))
|
|
2395 |
self._ErrorIf(test, constants.CV_ENODEHV, ninfo.name,
|
|
2396 |
"rpc call to node failed (instancelist): %s",
|
|
2397 |
utils.SafeEncode(str(idata)))
|
2427 |
2398 |
if test:
|
2428 |
2399 |
nimg.hyp_fail = True
|
2429 |
2400 |
else:
|
... | ... | |
2445 |
2416 |
# try to read free memory (from the hypervisor)
|
2446 |
2417 |
hv_info = nresult.get(constants.NV_HVINFO, None)
|
2447 |
2418 |
test = not isinstance(hv_info, dict) or "memory_free" not in hv_info
|
2448 |
|
_ErrorIf(test, self.ENODEHV, node, "rpc call to node failed (hvinfo)")
|
|
2419 |
_ErrorIf(test, constants.CV_ENODEHV, node,
|
|
2420 |
"rpc call to node failed (hvinfo)")
|
2449 |
2421 |
if not test:
|
2450 |
2422 |
try:
|
2451 |
2423 |
nimg.mfree = int(hv_info["memory_free"])
|
2452 |
2424 |
except (ValueError, TypeError):
|
2453 |
|
_ErrorIf(True, self.ENODERPC, node,
|
|
2425 |
_ErrorIf(True, constants.CV_ENODERPC, node,
|
2454 |
2426 |
"node returned invalid nodeinfo, check hypervisor")
|
2455 |
2427 |
|
2456 |
2428 |
# FIXME: devise a free space model for file based instances as well
|
2457 |
2429 |
if vg_name is not None:
|
2458 |
2430 |
test = (constants.NV_VGLIST not in nresult or
|
2459 |
2431 |
vg_name not in nresult[constants.NV_VGLIST])
|
2460 |
|
_ErrorIf(test, self.ENODELVM, node,
|
|
2432 |
_ErrorIf(test, constants.CV_ENODELVM, node,
|
2461 |
2433 |
"node didn't return data for the volume group '%s'"
|
2462 |
2434 |
" - it is either missing or broken", vg_name)
|
2463 |
2435 |
if not test:
|
2464 |
2436 |
try:
|
2465 |
2437 |
nimg.dfree = int(nresult[constants.NV_VGLIST][vg_name])
|
2466 |
2438 |
except (ValueError, TypeError):
|
2467 |
|
_ErrorIf(True, self.ENODERPC, node,
|
|
2439 |
_ErrorIf(True, constants.CV_ENODERPC, node,
|
2468 |
2440 |
"node returned invalid LVM info, check LVM status")
|
2469 |
2441 |
|
2470 |
2442 |
def _CollectDiskInfo(self, nodelist, node_image, instanceinfo):
|
... | ... | |
2531 |
2503 |
data = len(disks) * [(False, "node offline")]
|
2532 |
2504 |
else:
|
2533 |
2505 |
msg = nres.fail_msg
|
2534 |
|
_ErrorIf(msg, self.ENODERPC, nname,
|
|
2506 |
_ErrorIf(msg, constants.CV_ENODERPC, nname,
|
2535 |
2507 |
"while getting disk information: %s", msg)
|
2536 |
2508 |
if msg:
|
2537 |
2509 |
# No data from this node
|
... | ... | |
2830 |
2802 |
feedback_fn("* Verifying node %s (%s)" % (node, ntype))
|
2831 |
2803 |
|
2832 |
2804 |
msg = all_nvinfo[node].fail_msg
|
2833 |
|
_ErrorIf(msg, self.ENODERPC, node, "while contacting node: %s", msg)
|
|
2805 |
_ErrorIf(msg, constants.CV_ENODERPC, node, "while contacting node: %s",
|
|
2806 |
msg)
|
2834 |
2807 |
if msg:
|
2835 |
2808 |
nimg.rpc_fail = True
|
2836 |
2809 |
continue
|
... | ... | |
2865 |
2838 |
|
2866 |
2839 |
for inst in non_primary_inst:
|
2867 |
2840 |
test = inst in self.all_inst_info
|
2868 |
|
_ErrorIf(test, self.EINSTANCEWRONGNODE, inst,
|
|
2841 |
_ErrorIf(test, constants.CV_EINSTANCEWRONGNODE, inst,
|
2869 |
2842 |
"instance should not run on node %s", node_i.name)
|
2870 |
|
_ErrorIf(not test, self.ENODEORPHANINSTANCE, node_i.name,
|
|
2843 |
_ErrorIf(not test, constants.CV_ENODEORPHANINSTANCE, node_i.name,
|
2871 |
2844 |
"node is running unknown instance %s", inst)
|
2872 |
2845 |
|
2873 |
2846 |
for node, result in extra_lv_nvinfo.items():
|
... | ... | |
2886 |
2859 |
pnode = inst_config.primary_node
|
2887 |
2860 |
pnode_img = node_image[pnode]
|
2888 |
2861 |
_ErrorIf(pnode_img.rpc_fail and not pnode_img.offline,
|
2889 |
|
self.ENODERPC, pnode, "instance %s, connection to"
|
|
2862 |
constants.CV_ENODERPC, pnode, "instance %s, connection to"
|
2890 |
2863 |
" primary node failed", instance)
|
2891 |
2864 |
|
2892 |
2865 |
_ErrorIf(inst_config.admin_up and pnode_img.offline,
|
2893 |
|
self.EINSTANCEBADNODE, instance,
|
|
2866 |
constants.CV_EINSTANCEBADNODE, instance,
|
2894 |
2867 |
"instance is marked as running and lives on offline node %s",
|
2895 |
2868 |
inst_config.primary_node)
|
2896 |
2869 |
|
... | ... | |
2902 |
2875 |
if not inst_config.secondary_nodes:
|
2903 |
2876 |
i_non_redundant.append(instance)
|
2904 |
2877 |
|
2905 |
|
_ErrorIf(len(inst_config.secondary_nodes) > 1, self.EINSTANCELAYOUT,
|
|
2878 |
_ErrorIf(len(inst_config.secondary_nodes) > 1,
|
|
2879 |
constants.CV_EINSTANCELAYOUT,
|
2906 |
2880 |
instance, "instance has multiple secondary nodes: %s",
|
2907 |
2881 |
utils.CommaJoin(inst_config.secondary_nodes),
|
2908 |
2882 |
code=self.ETYPE_WARNING)
|
... | ... | |
2923 |
2897 |
key=lambda (_, nodes): pnode in nodes,
|
2924 |
2898 |
reverse=True)]
|
2925 |
2899 |
|
2926 |
|
self._ErrorIf(len(instance_groups) > 1, self.EINSTANCESPLITGROUPS,
|
|
2900 |
self._ErrorIf(len(instance_groups) > 1,
|
|
2901 |
constants.CV_EINSTANCESPLITGROUPS,
|
2927 |
2902 |
instance, "instance has primary and secondary nodes in"
|
2928 |
2903 |
" different groups: %s", utils.CommaJoin(pretty_list),
|
2929 |
2904 |
code=self.ETYPE_WARNING)
|
... | ... | |
2933 |
2908 |
|
2934 |
2909 |
for snode in inst_config.secondary_nodes:
|
2935 |
2910 |
s_img = node_image[snode]
|
2936 |
|
_ErrorIf(s_img.rpc_fail and not s_img.offline, self.ENODERPC, snode,
|
2937 |
|
"instance %s, connection to secondary node failed", instance)
|
|
2911 |
_ErrorIf(s_img.rpc_fail and not s_img.offline, constants.CV_ENODERPC,
|
|
2912 |
snode, "instance %s, connection to secondary node failed",
|
|
2913 |
instance)
|
2938 |
2914 |
|
2939 |
2915 |
if s_img.offline:
|
2940 |
2916 |
inst_nodes_offline.append(snode)
|
2941 |
2917 |
|
2942 |
2918 |
# warn that the instance lives on offline nodes
|
2943 |
|
_ErrorIf(inst_nodes_offline, self.EINSTANCEBADNODE, instance,
|
|
2919 |
_ErrorIf(inst_nodes_offline, constants.CV_EINSTANCEBADNODE, instance,
|
2944 |
2920 |
"instance has offline secondary node(s) %s",
|
2945 |
2921 |
utils.CommaJoin(inst_nodes_offline))
|
2946 |
2922 |
# ... or ghost/non-vm_capable nodes
|
2947 |
2923 |
for node in inst_config.all_nodes:
|
2948 |
|
_ErrorIf(node_image[node].ghost, self.EINSTANCEBADNODE, instance,
|
2949 |
|
"instance lives on ghost node %s", node)
|
2950 |
|
_ErrorIf(not node_image[node].vm_capable, self.EINSTANCEBADNODE,
|
|
2924 |
_ErrorIf(node_image[node].ghost, constants.CV_EINSTANCEBADNODE,
|
|
2925 |
instance, "instance lives on ghost node %s", node)
|
|
2926 |
_ErrorIf(not node_image[node].vm_capable, constants.CV_EINSTANCEBADNODE,
|
2951 |
2927 |
instance, "instance lives on non-vm_capable node %s", node)
|
2952 |
2928 |
|
2953 |
2929 |
feedback_fn("* Verifying orphan volumes")
|
... | ... | |
3015 |
2991 |
res = hooks_results[node_name]
|
3016 |
2992 |
msg = res.fail_msg
|
3017 |
2993 |
test = msg and not res.offline
|
3018 |
|
self._ErrorIf(test, self.ENODEHOOKS, node_name,
|
|
2994 |
self._ErrorIf(test, constants.CV_ENODEHOOKS, node_name,
|
3019 |
2995 |
"Communication failure in hooks execution: %s", msg)
|
3020 |
2996 |
if res.offline or msg:
|
3021 |
2997 |
# No need to investigate payload if node is offline or gave
|
... | ... | |
3023 |
2999 |
continue
|
3024 |
3000 |
for script, hkr, output in res.payload:
|
3025 |
3001 |
test = hkr == constants.HKR_FAIL
|
3026 |
|
self._ErrorIf(test, self.ENODEHOOKS, node_name,
|
|
3002 |
self._ErrorIf(test, constants.CV_ENODEHOOKS, node_name,
|
3027 |
3003 |
"Script %s failed, output:", script)
|
3028 |
3004 |
if test:
|
3029 |
3005 |
output = self._HOOKS_INDENT_RE.sub(" ", output)
|