Revision d0d7d7cf lib/cmdlib/cluster.py
b/lib/cmdlib/cluster.py | ||
---|---|---|
1567 | 1567 |
reasonable values in the respose) |
1568 | 1568 |
|
1569 | 1569 |
""" |
1570 |
node_name = ninfo.name |
|
1571 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
1572 |
|
|
1573 | 1570 |
# main result, nresult should be a non-empty dict |
1574 | 1571 |
test = not nresult or not isinstance(nresult, dict) |
1575 |
_ErrorIf(test, constants.CV_ENODERPC, node_name,
|
|
1572 |
self._ErrorIf(test, constants.CV_ENODERPC, ninfo.name,
|
|
1576 | 1573 |
"unable to verify node: no data returned") |
1577 | 1574 |
if test: |
1578 | 1575 |
return False |
... | ... | |
1583 | 1580 |
test = not (remote_version and |
1584 | 1581 |
isinstance(remote_version, (list, tuple)) and |
1585 | 1582 |
len(remote_version) == 2) |
1586 |
_ErrorIf(test, constants.CV_ENODERPC, node_name,
|
|
1587 |
"connection to node returned invalid data") |
|
1583 |
self._ErrorIf(test, constants.CV_ENODERPC, ninfo.name,
|
|
1584 |
"connection to node returned invalid data")
|
|
1588 | 1585 |
if test: |
1589 | 1586 |
return False |
1590 | 1587 |
|
1591 | 1588 |
test = local_version != remote_version[0] |
1592 |
_ErrorIf(test, constants.CV_ENODEVERSION, node_name,
|
|
1593 |
"incompatible protocol versions: master %s," |
|
1594 |
" node %s", local_version, remote_version[0]) |
|
1589 |
self._ErrorIf(test, constants.CV_ENODEVERSION, ninfo.name,
|
|
1590 |
"incompatible protocol versions: master %s,"
|
|
1591 |
" node %s", local_version, remote_version[0])
|
|
1595 | 1592 |
if test: |
1596 | 1593 |
return False |
1597 | 1594 |
|
... | ... | |
1599 | 1596 |
|
1600 | 1597 |
# full package version |
1601 | 1598 |
self._ErrorIf(constants.RELEASE_VERSION != remote_version[1], |
1602 |
constants.CV_ENODEVERSION, node_name,
|
|
1599 |
constants.CV_ENODEVERSION, ninfo.name,
|
|
1603 | 1600 |
"software version mismatch: master %s, node %s", |
1604 | 1601 |
constants.RELEASE_VERSION, remote_version[1], |
1605 | 1602 |
code=self.ETYPE_WARNING) |
... | ... | |
1608 | 1605 |
if ninfo.vm_capable and isinstance(hyp_result, dict): |
1609 | 1606 |
for hv_name, hv_result in hyp_result.iteritems(): |
1610 | 1607 |
test = hv_result is not None |
1611 |
_ErrorIf(test, constants.CV_ENODEHV, node_name,
|
|
1612 |
"hypervisor %s verify failure: '%s'", hv_name, hv_result) |
|
1608 |
self._ErrorIf(test, constants.CV_ENODEHV, ninfo.name,
|
|
1609 |
"hypervisor %s verify failure: '%s'", hv_name, hv_result)
|
|
1613 | 1610 |
|
1614 | 1611 |
hvp_result = nresult.get(constants.NV_HVPARAMS, None) |
1615 | 1612 |
if ninfo.vm_capable and isinstance(hvp_result, list): |
1616 | 1613 |
for item, hv_name, hv_result in hvp_result: |
1617 |
_ErrorIf(True, constants.CV_ENODEHV, node_name,
|
|
1618 |
"hypervisor %s parameter verify failure (source %s): %s", |
|
1619 |
hv_name, item, hv_result) |
|
1614 |
self._ErrorIf(True, constants.CV_ENODEHV, ninfo.name,
|
|
1615 |
"hypervisor %s parameter verify failure (source %s): %s",
|
|
1616 |
hv_name, item, hv_result)
|
|
1620 | 1617 |
|
1621 | 1618 |
test = nresult.get(constants.NV_NODESETUP, |
1622 | 1619 |
["Missing NODESETUP results"]) |
1623 |
_ErrorIf(test, constants.CV_ENODESETUP, node_name, "node setup error: %s",
|
|
1624 |
"; ".join(test)) |
|
1620 |
self._ErrorIf(test, constants.CV_ENODESETUP, ninfo.name,
|
|
1621 |
"node setup error: %s", "; ".join(test))
|
|
1625 | 1622 |
|
1626 | 1623 |
return True |
1627 | 1624 |
|
... | ... | |
1636 | 1633 |
@param nvinfo_endtime: the end time of the RPC call |
1637 | 1634 |
|
1638 | 1635 |
""" |
1639 |
node_name = ninfo.name |
|
1640 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
1641 |
|
|
1642 | 1636 |
ntime = nresult.get(constants.NV_TIME, None) |
1643 | 1637 |
try: |
1644 | 1638 |
ntime_merged = utils.MergeTime(ntime) |
1645 | 1639 |
except (ValueError, TypeError): |
1646 |
_ErrorIf(True, constants.CV_ENODETIME, node_name,
|
|
1647 |
"Node returned invalid time") |
|
1640 |
self._ErrorIf(True, constants.CV_ENODETIME, ninfo.name,
|
|
1641 |
"Node returned invalid time")
|
|
1648 | 1642 |
return |
1649 | 1643 |
|
1650 | 1644 |
if ntime_merged < (nvinfo_starttime - constants.NODE_MAX_CLOCK_SKEW): |
... | ... | |
1654 | 1648 |
else: |
1655 | 1649 |
ntime_diff = None |
1656 | 1650 |
|
1657 |
_ErrorIf(ntime_diff is not None, constants.CV_ENODETIME, node_name,
|
|
1658 |
"Node time diverges by at least %s from master node time", |
|
1659 |
ntime_diff) |
|
1651 |
self._ErrorIf(ntime_diff is not None, constants.CV_ENODETIME, ninfo.name,
|
|
1652 |
"Node time diverges by at least %s from master node time",
|
|
1653 |
ntime_diff)
|
|
1660 | 1654 |
|
1661 | 1655 |
def _UpdateVerifyNodeLVM(self, ninfo, nresult, vg_name, nimg): |
1662 | 1656 |
"""Check the node LVM results and update info for cross-node checks. |
... | ... | |
1672 | 1666 |
if vg_name is None: |
1673 | 1667 |
return |
1674 | 1668 |
|
1675 |
node_name = ninfo.name |
|
1676 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
1677 |
|
|
1678 | 1669 |
# checks vg existence and size > 20G |
1679 | 1670 |
vglist = nresult.get(constants.NV_VGLIST, None) |
1680 | 1671 |
test = not vglist |
1681 |
_ErrorIf(test, constants.CV_ENODELVM, node_name,
|
|
1682 |
"unable to check volume groups") |
|
1672 |
self._ErrorIf(test, constants.CV_ENODELVM, ninfo.name,
|
|
1673 |
"unable to check volume groups")
|
|
1683 | 1674 |
if not test: |
1684 | 1675 |
vgstatus = utils.CheckVolumeGroupSize(vglist, vg_name, |
1685 | 1676 |
constants.MIN_VG_SIZE) |
1686 |
_ErrorIf(vgstatus, constants.CV_ENODELVM, node_name, vgstatus)
|
|
1677 |
self._ErrorIf(vgstatus, constants.CV_ENODELVM, ninfo.name, vgstatus)
|
|
1687 | 1678 |
|
1688 | 1679 |
# Check PVs |
1689 | 1680 |
(errmsgs, pvminmax) = CheckNodePVs(nresult, self._exclusive_storage) |
1690 | 1681 |
for em in errmsgs: |
1691 |
self._Error(constants.CV_ENODELVM, node_name, em)
|
|
1682 |
self._Error(constants.CV_ENODELVM, ninfo.name, em)
|
|
1692 | 1683 |
if pvminmax is not None: |
1693 | 1684 |
(nimg.pv_min, nimg.pv_max) = pvminmax |
1694 | 1685 |
|
... | ... | |
1754 | 1745 |
if not bridges: |
1755 | 1746 |
return |
1756 | 1747 |
|
1757 |
node_name = ninfo.name |
|
1758 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
1759 |
|
|
1760 | 1748 |
missing = nresult.get(constants.NV_BRIDGES, None) |
1761 | 1749 |
test = not isinstance(missing, list) |
1762 |
_ErrorIf(test, constants.CV_ENODENET, node_name,
|
|
1763 |
"did not return valid bridge information") |
|
1750 |
self._ErrorIf(test, constants.CV_ENODENET, ninfo.name,
|
|
1751 |
"did not return valid bridge information")
|
|
1764 | 1752 |
if not test: |
1765 |
_ErrorIf(bool(missing), constants.CV_ENODENET, node_name,
|
|
1766 |
"missing bridges: %s" % utils.CommaJoin(sorted(missing))) |
|
1753 |
self._ErrorIf(bool(missing), constants.CV_ENODENET, ninfo.name,
|
|
1754 |
"missing bridges: %s" % utils.CommaJoin(sorted(missing)))
|
|
1767 | 1755 |
|
1768 | 1756 |
def _VerifyNodeUserScripts(self, ninfo, nresult): |
1769 | 1757 |
"""Check the results of user scripts presence and executability on the node |
... | ... | |
1773 | 1761 |
@param nresult: the remote results for the node |
1774 | 1762 |
|
1775 | 1763 |
""" |
1776 |
node_name = ninfo.name |
|
1777 |
|
|
1778 | 1764 |
test = not constants.NV_USERSCRIPTS in nresult |
1779 |
self._ErrorIf(test, constants.CV_ENODEUSERSCRIPTS, node_name,
|
|
1765 |
self._ErrorIf(test, constants.CV_ENODEUSERSCRIPTS, ninfo.name,
|
|
1780 | 1766 |
"did not return user scripts information") |
1781 | 1767 |
|
1782 | 1768 |
broken_scripts = nresult.get(constants.NV_USERSCRIPTS, None) |
1783 | 1769 |
if not test: |
1784 |
self._ErrorIf(broken_scripts, constants.CV_ENODEUSERSCRIPTS, node_name,
|
|
1770 |
self._ErrorIf(broken_scripts, constants.CV_ENODEUSERSCRIPTS, ninfo.name,
|
|
1785 | 1771 |
"user scripts not present or not executable: %s" % |
1786 | 1772 |
utils.CommaJoin(sorted(broken_scripts))) |
1787 | 1773 |
|
... | ... | |
1793 | 1779 |
@param nresult: the remote results for the node |
1794 | 1780 |
|
1795 | 1781 |
""" |
1796 |
node_name = ninfo.name |
|
1797 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
1798 |
|
|
1799 | 1782 |
test = constants.NV_NODELIST not in nresult |
1800 |
_ErrorIf(test, constants.CV_ENODESSH, node_name,
|
|
1801 |
"node hasn't returned node ssh connectivity data") |
|
1783 |
self._ErrorIf(test, constants.CV_ENODESSH, ninfo.name,
|
|
1784 |
"node hasn't returned node ssh connectivity data")
|
|
1802 | 1785 |
if not test: |
1803 | 1786 |
if nresult[constants.NV_NODELIST]: |
1804 | 1787 |
for a_node, a_msg in nresult[constants.NV_NODELIST].items(): |
1805 |
_ErrorIf(True, constants.CV_ENODESSH, node_name,
|
|
1806 |
"ssh communication with node '%s': %s", a_node, a_msg) |
|
1788 |
self._ErrorIf(True, constants.CV_ENODESSH, ninfo.name,
|
|
1789 |
"ssh communication with node '%s': %s", a_node, a_msg)
|
|
1807 | 1790 |
|
1808 | 1791 |
test = constants.NV_NODENETTEST not in nresult |
1809 |
_ErrorIf(test, constants.CV_ENODENET, node_name,
|
|
1810 |
"node hasn't returned node tcp connectivity data") |
|
1792 |
self._ErrorIf(test, constants.CV_ENODENET, ninfo.name,
|
|
1793 |
"node hasn't returned node tcp connectivity data")
|
|
1811 | 1794 |
if not test: |
1812 | 1795 |
if nresult[constants.NV_NODENETTEST]: |
1813 | 1796 |
nlist = utils.NiceSort(nresult[constants.NV_NODENETTEST].keys()) |
1814 | 1797 |
for anode in nlist: |
1815 |
_ErrorIf(True, constants.CV_ENODENET, node_name,
|
|
1816 |
"tcp communication with node '%s': %s", |
|
1817 |
anode, nresult[constants.NV_NODENETTEST][anode]) |
|
1798 |
self._ErrorIf(True, constants.CV_ENODENET, ninfo.name,
|
|
1799 |
"tcp communication with node '%s': %s",
|
|
1800 |
anode, nresult[constants.NV_NODENETTEST][anode])
|
|
1818 | 1801 |
|
1819 | 1802 |
test = constants.NV_MASTERIP not in nresult |
1820 |
_ErrorIf(test, constants.CV_ENODENET, node_name,
|
|
1821 |
"node hasn't returned node master IP reachability data") |
|
1803 |
self._ErrorIf(test, constants.CV_ENODENET, ninfo.name,
|
|
1804 |
"node hasn't returned node master IP reachability data")
|
|
1822 | 1805 |
if not test: |
1823 | 1806 |
if not nresult[constants.NV_MASTERIP]: |
1824 | 1807 |
if ninfo.uuid == self.master_node: |
1825 | 1808 |
msg = "the master node cannot reach the master IP (not configured?)" |
1826 | 1809 |
else: |
1827 | 1810 |
msg = "cannot reach the master IP" |
1828 |
_ErrorIf(True, constants.CV_ENODENET, node_name, msg)
|
|
1811 |
self._ErrorIf(True, constants.CV_ENODENET, ninfo.name, msg)
|
|
1829 | 1812 |
|
1830 | 1813 |
def _VerifyInstance(self, instance, inst_config, node_image, |
1831 | 1814 |
diskstatus): |
... | ... | |
1836 | 1819 |
state. |
1837 | 1820 |
|
1838 | 1821 |
""" |
1839 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
1840 | 1822 |
pnode = inst_config.primary_node |
1841 | 1823 |
pnode_img = node_image[pnode] |
1842 | 1824 |
groupinfo = self.cfg.GetAllNodeGroupsInfo() |
... | ... | |
1848 | 1830 |
ipolicy = ganeti.masterd.instance.CalculateGroupIPolicy(cluster, |
1849 | 1831 |
self.group_info) |
1850 | 1832 |
err = ComputeIPolicyInstanceViolation(ipolicy, inst_config, self.cfg) |
1851 |
_ErrorIf(err, constants.CV_EINSTANCEPOLICY, instance, utils.CommaJoin(err),
|
|
1852 |
code=self.ETYPE_WARNING) |
|
1833 |
self._ErrorIf(err, constants.CV_EINSTANCEPOLICY, instance,
|
|
1834 |
utils.CommaJoin(err), code=self.ETYPE_WARNING)
|
|
1853 | 1835 |
|
1854 | 1836 |
for node in node_vol_should: |
1855 | 1837 |
n_img = node_image[node] |
... | ... | |
1858 | 1840 |
continue |
1859 | 1841 |
for volume in node_vol_should[node]: |
1860 | 1842 |
test = volume not in n_img.volumes |
1861 |
_ErrorIf(test, constants.CV_EINSTANCEMISSINGDISK, instance, |
|
1862 |
"volume %s missing on node %s", volume, |
|
1863 |
self.cfg.GetNodeName(node)) |
|
1843 |
self._ErrorIf(test, constants.CV_EINSTANCEMISSINGDISK, instance,
|
|
1844 |
"volume %s missing on node %s", volume,
|
|
1845 |
self.cfg.GetNodeName(node))
|
|
1864 | 1846 |
|
1865 | 1847 |
if inst_config.admin_state == constants.ADMINST_UP: |
1866 | 1848 |
test = instance not in pnode_img.instances and not pnode_img.offline |
1867 |
_ErrorIf(test, constants.CV_EINSTANCEDOWN, instance, |
|
1868 |
"instance not running on its primary node %s", |
|
1869 |
self.cfg.GetNodeName(pnode)) |
|
1870 |
_ErrorIf(pnode_img.offline, constants.CV_EINSTANCEBADNODE, instance, |
|
1871 |
"instance is marked as running and lives on offline node %s",
|
|
1872 |
self.cfg.GetNodeName(pnode)) |
|
1849 |
self._ErrorIf(test, constants.CV_EINSTANCEDOWN, instance,
|
|
1850 |
"instance not running on its primary node %s",
|
|
1851 |
self.cfg.GetNodeName(pnode))
|
|
1852 |
self._ErrorIf(pnode_img.offline, constants.CV_EINSTANCEBADNODE, instance,
|
|
1853 |
"instance is marked as running and lives on"
|
|
1854 |
" offline node %s", self.cfg.GetNodeName(pnode))
|
|
1873 | 1855 |
|
1874 | 1856 |
diskdata = [(nname, success, status, idx) |
1875 | 1857 |
for (nname, disks) in diskstatus.items() |
... | ... | |
1880 | 1862 |
# node here |
1881 | 1863 |
snode = node_image[nname] |
1882 | 1864 |
bad_snode = snode.ghost or snode.offline |
1883 |
_ErrorIf(inst_config.disks_active and |
|
1884 |
not success and not bad_snode, |
|
1885 |
constants.CV_EINSTANCEFAULTYDISK, instance, |
|
1886 |
"couldn't retrieve status for disk/%s on %s: %s", |
|
1887 |
idx, self.cfg.GetNodeName(nname), bdev_status) |
|
1888 |
_ErrorIf((inst_config.disks_active and |
|
1889 |
success and bdev_status.ldisk_status == constants.LDS_FAULTY), |
|
1890 |
constants.CV_EINSTANCEFAULTYDISK, instance, |
|
1891 |
"disk/%s on %s is faulty", idx, self.cfg.GetNodeName(nname)) |
|
1892 |
|
|
1893 |
_ErrorIf(pnode_img.rpc_fail and not pnode_img.offline, |
|
1894 |
constants.CV_ENODERPC, pnode, "instance %s, connection to" |
|
1895 |
" primary node failed", instance) |
|
1896 |
|
|
1897 |
_ErrorIf(len(inst_config.secondary_nodes) > 1, |
|
1898 |
constants.CV_EINSTANCELAYOUT, |
|
1899 |
instance, "instance has multiple secondary nodes: %s", |
|
1900 |
utils.CommaJoin(inst_config.secondary_nodes), |
|
1901 |
code=self.ETYPE_WARNING) |
|
1865 |
self._ErrorIf(inst_config.disks_active and |
|
1866 |
not success and not bad_snode, |
|
1867 |
constants.CV_EINSTANCEFAULTYDISK, instance, |
|
1868 |
"couldn't retrieve status for disk/%s on %s: %s", |
|
1869 |
idx, self.cfg.GetNodeName(nname), bdev_status) |
|
1870 |
self._ErrorIf((inst_config.disks_active and |
|
1871 |
success and |
|
1872 |
bdev_status.ldisk_status == constants.LDS_FAULTY), |
|
1873 |
constants.CV_EINSTANCEFAULTYDISK, instance, |
|
1874 |
"disk/%s on %s is faulty", idx, self.cfg.GetNodeName(nname)) |
|
1875 |
|
|
1876 |
self._ErrorIf(pnode_img.rpc_fail and not pnode_img.offline, |
|
1877 |
constants.CV_ENODERPC, pnode, "instance %s, connection to" |
|
1878 |
" primary node failed", instance) |
|
1879 |
|
|
1880 |
self._ErrorIf(len(inst_config.secondary_nodes) > 1, |
|
1881 |
constants.CV_EINSTANCELAYOUT, |
|
1882 |
instance, "instance has multiple secondary nodes: %s", |
|
1883 |
utils.CommaJoin(inst_config.secondary_nodes), |
|
1884 |
code=self.ETYPE_WARNING) |
|
1902 | 1885 |
|
1903 | 1886 |
es_flags = rpc.GetExclusiveStorageForNodes(self.cfg, |
1904 | 1887 |
inst_config.all_nodes) |
... | ... | |
1915 | 1898 |
inst_config.disk_template, |
1916 | 1899 |
utils.CommaJoin(self.cfg.GetNodeNames(es_nodes))) |
1917 | 1900 |
for (idx, disk) in enumerate(inst_config.disks): |
1918 |
_ErrorIf(disk.spindles is None, |
|
1919 |
constants.CV_EINSTANCEMISSINGCFGPARAMETER, instance, |
|
1920 |
"number of spindles not configured for disk %s while" |
|
1921 |
" exclusive storage is enabled, try running" |
|
1922 |
" gnt-cluster repair-disk-sizes", |
|
1923 |
idx) |
|
1901 |
self._ErrorIf(disk.spindles is None, |
|
1902 |
constants.CV_EINSTANCEMISSINGCFGPARAMETER, instance, |
|
1903 |
"number of spindles not configured for disk %s while" |
|
1904 |
" exclusive storage is enabled, try running" |
|
1905 |
" gnt-cluster repair-disk-sizes", idx) |
|
1924 | 1906 |
|
1925 | 1907 |
if inst_config.disk_template in constants.DTS_INT_MIRROR: |
1926 | 1908 |
instance_nodes = utils.NiceSort(inst_config.all_nodes) |
... | ... | |
1947 | 1929 |
inst_nodes_offline = [] |
1948 | 1930 |
for snode in inst_config.secondary_nodes: |
1949 | 1931 |
s_img = node_image[snode] |
1950 |
_ErrorIf(s_img.rpc_fail and not s_img.offline, constants.CV_ENODERPC, |
|
1951 |
snode, "instance %s, connection to secondary node failed", |
|
1952 |
instance) |
|
1932 |
self._ErrorIf(s_img.rpc_fail and not s_img.offline, constants.CV_ENODERPC,
|
|
1933 |
snode, "instance %s, connection to secondary node failed",
|
|
1934 |
instance)
|
|
1953 | 1935 |
|
1954 | 1936 |
if s_img.offline: |
1955 | 1937 |
inst_nodes_offline.append(snode) |
1956 | 1938 |
|
1957 | 1939 |
# warn that the instance lives on offline nodes |
1958 |
_ErrorIf(inst_nodes_offline, constants.CV_EINSTANCEBADNODE, instance, |
|
1959 |
"instance has offline secondary node(s) %s", |
|
1960 |
utils.CommaJoin(self.cfg.GetNodeNames(inst_nodes_offline))) |
|
1940 |
self._ErrorIf(inst_nodes_offline, constants.CV_EINSTANCEBADNODE, instance,
|
|
1941 |
"instance has offline secondary node(s) %s",
|
|
1942 |
utils.CommaJoin(self.cfg.GetNodeNames(inst_nodes_offline)))
|
|
1961 | 1943 |
# ... or ghost/non-vm_capable nodes |
1962 | 1944 |
for node in inst_config.all_nodes: |
1963 |
_ErrorIf(node_image[node].ghost, constants.CV_EINSTANCEBADNODE, |
|
1964 |
instance, "instance lives on ghost node %s", |
|
1965 |
self.cfg.GetNodeName(node)) |
|
1966 |
_ErrorIf(not node_image[node].vm_capable, constants.CV_EINSTANCEBADNODE, |
|
1967 |
instance, "instance lives on non-vm_capable node %s", |
|
1968 |
self.cfg.GetNodeName(node)) |
|
1945 |
self._ErrorIf(node_image[node].ghost, constants.CV_EINSTANCEBADNODE, |
|
1946 |
instance, "instance lives on ghost node %s", |
|
1947 |
self.cfg.GetNodeName(node)) |
|
1948 |
self._ErrorIf(not node_image[node].vm_capable, |
|
1949 |
constants.CV_EINSTANCEBADNODE, instance, |
|
1950 |
"instance lives on non-vm_capable node %s", |
|
1951 |
self.cfg.GetNodeName(node)) |
|
1969 | 1952 |
|
1970 | 1953 |
def _VerifyOrphanVolumes(self, node_vol_should, node_image, reserved): |
1971 | 1954 |
"""Verify if there are any unknown volumes in the cluster. |
... | ... | |
2155 | 2138 |
L{ganeti.config.ConfigWriter.ComputeDRBDMap} |
2156 | 2139 |
|
2157 | 2140 |
""" |
2158 |
node_name = ninfo.name |
|
2159 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
2160 |
|
|
2161 | 2141 |
if drbd_helper: |
2162 | 2142 |
helper_result = nresult.get(constants.NV_DRBDHELPER, None) |
2163 | 2143 |
test = (helper_result is None) |
2164 |
_ErrorIf(test, constants.CV_ENODEDRBDHELPER, node_name,
|
|
2165 |
"no drbd usermode helper returned") |
|
2144 |
self._ErrorIf(test, constants.CV_ENODEDRBDHELPER, ninfo.name,
|
|
2145 |
"no drbd usermode helper returned")
|
|
2166 | 2146 |
if helper_result: |
2167 | 2147 |
status, payload = helper_result |
2168 | 2148 |
test = not status |
2169 |
_ErrorIf(test, constants.CV_ENODEDRBDHELPER, node_name,
|
|
2170 |
"drbd usermode helper check unsuccessful: %s", payload) |
|
2149 |
self._ErrorIf(test, constants.CV_ENODEDRBDHELPER, ninfo.name,
|
|
2150 |
"drbd usermode helper check unsuccessful: %s", payload)
|
|
2171 | 2151 |
test = status and (payload != drbd_helper) |
2172 |
_ErrorIf(test, constants.CV_ENODEDRBDHELPER, node_name,
|
|
2173 |
"wrong drbd usermode helper: %s", payload) |
|
2152 |
self._ErrorIf(test, constants.CV_ENODEDRBDHELPER, ninfo.name,
|
|
2153 |
"wrong drbd usermode helper: %s", payload)
|
|
2174 | 2154 |
|
2175 | 2155 |
# compute the DRBD minors |
2176 | 2156 |
node_drbd = {} |
2177 | 2157 |
for minor, instance in drbd_map[ninfo.uuid].items(): |
2178 | 2158 |
test = instance not in instanceinfo |
2179 |
_ErrorIf(test, constants.CV_ECLUSTERCFG, None, |
|
2180 |
"ghost instance '%s' in temporary DRBD map", instance) |
|
2159 |
self._ErrorIf(test, constants.CV_ECLUSTERCFG, None,
|
|
2160 |
"ghost instance '%s' in temporary DRBD map", instance)
|
|
2181 | 2161 |
# ghost instance should not be running, but otherwise we |
2182 | 2162 |
# don't give double warnings (both ghost instance and |
2183 | 2163 |
# unallocated minor in use) |
... | ... | |
2190 | 2170 |
# and now check them |
2191 | 2171 |
used_minors = nresult.get(constants.NV_DRBDLIST, []) |
2192 | 2172 |
test = not isinstance(used_minors, (tuple, list)) |
2193 |
_ErrorIf(test, constants.CV_ENODEDRBD, node_name,
|
|
2194 |
"cannot parse drbd status file: %s", str(used_minors)) |
|
2173 |
self._ErrorIf(test, constants.CV_ENODEDRBD, ninfo.name,
|
|
2174 |
"cannot parse drbd status file: %s", str(used_minors))
|
|
2195 | 2175 |
if test: |
2196 | 2176 |
# we cannot check drbd status |
2197 | 2177 |
return |
2198 | 2178 |
|
2199 | 2179 |
for minor, (iname, must_exist) in node_drbd.items(): |
2200 | 2180 |
test = minor not in used_minors and must_exist |
2201 |
_ErrorIf(test, constants.CV_ENODEDRBD, node_name,
|
|
2202 |
"drbd minor %d of instance %s is not active", minor, iname) |
|
2181 |
self._ErrorIf(test, constants.CV_ENODEDRBD, ninfo.name,
|
|
2182 |
"drbd minor %d of instance %s is not active", minor, iname)
|
|
2203 | 2183 |
for minor in used_minors: |
2204 | 2184 |
test = minor not in node_drbd |
2205 |
_ErrorIf(test, constants.CV_ENODEDRBD, node_name,
|
|
2206 |
"unallocated drbd minor %d is in use", minor) |
|
2185 |
self._ErrorIf(test, constants.CV_ENODEDRBD, ninfo.name,
|
|
2186 |
"unallocated drbd minor %d is in use", minor)
|
|
2207 | 2187 |
|
2208 | 2188 |
def _UpdateNodeOS(self, ninfo, nresult, nimg): |
2209 | 2189 |
"""Builds the node OS structures. |
... | ... | |
2214 | 2194 |
@param nimg: the node image object |
2215 | 2195 |
|
2216 | 2196 |
""" |
2217 |
node_name = ninfo.name |
|
2218 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
2219 |
|
|
2220 | 2197 |
remote_os = nresult.get(constants.NV_OSLIST, None) |
2221 | 2198 |
test = (not isinstance(remote_os, list) or |
2222 | 2199 |
not compat.all(isinstance(v, list) and len(v) == 7 |
2223 | 2200 |
for v in remote_os)) |
2224 | 2201 |
|
2225 |
_ErrorIf(test, constants.CV_ENODEOS, node_name,
|
|
2226 |
"node hasn't returned valid OS data") |
|
2202 |
self._ErrorIf(test, constants.CV_ENODEOS, ninfo.name,
|
|
2203 |
"node hasn't returned valid OS data")
|
|
2227 | 2204 |
|
2228 | 2205 |
nimg.os_fail = test |
2229 | 2206 |
|
... | ... | |
2255 | 2232 |
@param base: the 'template' node we match against (e.g. from the master) |
2256 | 2233 |
|
2257 | 2234 |
""" |
2258 |
node_name = ninfo.name |
|
2259 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
2260 |
|
|
2261 | 2235 |
assert not nimg.os_fail, "Entered _VerifyNodeOS with failed OS rpc?" |
2262 | 2236 |
|
2263 | 2237 |
beautify_params = lambda l: ["%s: %s" % (k, v) for (k, v) in l] |
2264 | 2238 |
for os_name, os_data in nimg.oslist.items(): |
2265 | 2239 |
assert os_data, "Empty OS status for OS %s?!" % os_name |
2266 | 2240 |
f_path, f_status, f_diag, f_var, f_param, f_api = os_data[0] |
2267 |
_ErrorIf(not f_status, constants.CV_ENODEOS, node_name, |
|
2268 |
"Invalid OS %s (located at %s): %s", os_name, f_path, f_diag) |
|
2269 |
_ErrorIf(len(os_data) > 1, constants.CV_ENODEOS, node_name, |
|
2270 |
"OS '%s' has multiple entries (first one shadows the rest): %s", |
|
2271 |
os_name, utils.CommaJoin([v[0] for v in os_data])) |
|
2241 |
self._ErrorIf(not f_status, constants.CV_ENODEOS, ninfo.name, |
|
2242 |
"Invalid OS %s (located at %s): %s", |
|
2243 |
os_name, f_path, f_diag) |
|
2244 |
self._ErrorIf(len(os_data) > 1, constants.CV_ENODEOS, ninfo.name, |
|
2245 |
"OS '%s' has multiple entries" |
|
2246 |
" (first one shadows the rest): %s", |
|
2247 |
os_name, utils.CommaJoin([v[0] for v in os_data])) |
|
2272 | 2248 |
# comparisons with the 'base' image |
2273 | 2249 |
test = os_name not in base.oslist |
2274 |
_ErrorIf(test, constants.CV_ENODEOS, node_name,
|
|
2275 |
"Extra OS %s not present on reference node (%s)", |
|
2276 |
os_name, self.cfg.GetNodeName(base.uuid)) |
|
2250 |
self._ErrorIf(test, constants.CV_ENODEOS, ninfo.name,
|
|
2251 |
"Extra OS %s not present on reference node (%s)",
|
|
2252 |
os_name, self.cfg.GetNodeName(base.uuid))
|
|
2277 | 2253 |
if test: |
2278 | 2254 |
continue |
2279 | 2255 |
assert base.oslist[os_name], "Base node has empty OS status?" |
... | ... | |
2285 | 2261 |
("variants list", f_var, b_var), |
2286 | 2262 |
("parameters", beautify_params(f_param), |
2287 | 2263 |
beautify_params(b_param))]: |
2288 |
_ErrorIf(a != b, constants.CV_ENODEOS, node_name, |
|
2289 |
"OS %s for %s differs from reference node %s: [%s] vs. [%s]", |
|
2290 |
kind, os_name, self.cfg.GetNodeName(base.uuid), |
|
2291 |
utils.CommaJoin(sorted(a)), utils.CommaJoin(sorted(b))) |
|
2264 |
self._ErrorIf(a != b, constants.CV_ENODEOS, ninfo.name, |
|
2265 |
"OS %s for %s differs from reference node %s:" |
|
2266 |
" [%s] vs. [%s]", kind, os_name, |
|
2267 |
self.cfg.GetNodeName(base.uuid), |
|
2268 |
utils.CommaJoin(sorted(a)), utils.CommaJoin(sorted(b))) |
|
2292 | 2269 |
|
2293 | 2270 |
# check any missing OSes |
2294 | 2271 |
missing = set(base.oslist.keys()).difference(nimg.oslist.keys()) |
2295 |
_ErrorIf(missing, constants.CV_ENODEOS, node_name, |
|
2296 |
"OSes present on reference node %s but missing on this node: %s", |
|
2297 |
self.cfg.GetNodeName(base.uuid), utils.CommaJoin(missing)) |
|
2272 |
self._ErrorIf(missing, constants.CV_ENODEOS, ninfo.name, |
|
2273 |
"OSes present on reference node %s" |
|
2274 |
" but missing on this node: %s", |
|
2275 |
self.cfg.GetNodeName(base.uuid), utils.CommaJoin(missing)) |
|
2298 | 2276 |
|
2299 | 2277 |
def _VerifyFileStoragePaths(self, ninfo, nresult, is_master): |
2300 | 2278 |
"""Verifies paths in L{pathutils.FILE_STORAGE_PATHS_FILE}. |
... | ... | |
2306 | 2284 |
@param is_master: Whether node is the master node |
2307 | 2285 |
|
2308 | 2286 |
""" |
2309 |
node_name = ninfo.name |
|
2310 |
|
|
2311 | 2287 |
if (is_master and |
2312 | 2288 |
(constants.ENABLE_FILE_STORAGE or |
2313 | 2289 |
constants.ENABLE_SHARED_FILE_STORAGE)): |
... | ... | |
2315 | 2291 |
fspaths = nresult[constants.NV_FILE_STORAGE_PATHS] |
2316 | 2292 |
except KeyError: |
2317 | 2293 |
# This should never happen |
2318 |
self._ErrorIf(True, constants.CV_ENODEFILESTORAGEPATHS, node_name,
|
|
2294 |
self._ErrorIf(True, constants.CV_ENODEFILESTORAGEPATHS, ninfo.name,
|
|
2319 | 2295 |
"Node did not return forbidden file storage paths") |
2320 | 2296 |
else: |
2321 |
self._ErrorIf(fspaths, constants.CV_ENODEFILESTORAGEPATHS, node_name,
|
|
2297 |
self._ErrorIf(fspaths, constants.CV_ENODEFILESTORAGEPATHS, ninfo.name,
|
|
2322 | 2298 |
"Found forbidden file storage paths: %s", |
2323 | 2299 |
utils.CommaJoin(fspaths)) |
2324 | 2300 |
else: |
2325 | 2301 |
self._ErrorIf(constants.NV_FILE_STORAGE_PATHS in nresult, |
2326 |
constants.CV_ENODEFILESTORAGEPATHS, node_name,
|
|
2302 |
constants.CV_ENODEFILESTORAGEPATHS, ninfo.name,
|
|
2327 | 2303 |
"Node should not have returned forbidden file storage" |
2328 | 2304 |
" paths") |
2329 | 2305 |
|
... | ... | |
2335 | 2311 |
@param nresult: the remote results for the node |
2336 | 2312 |
|
2337 | 2313 |
""" |
2338 |
node_name = ninfo.name |
|
2339 | 2314 |
# We just have to verify the paths on master and/or master candidates |
2340 | 2315 |
# as the oob helper is invoked on the master |
2341 | 2316 |
if ((ninfo.master_candidate or ninfo.master_capable) and |
2342 | 2317 |
constants.NV_OOB_PATHS in nresult): |
2343 | 2318 |
for path_result in nresult[constants.NV_OOB_PATHS]: |
2344 | 2319 |
self._ErrorIf(path_result, constants.CV_ENODEOOBPATH, |
2345 |
node_name, path_result)
|
|
2320 |
ninfo.name, path_result)
|
|
2346 | 2321 |
|
2347 | 2322 |
def _UpdateNodeVolumes(self, ninfo, nresult, nimg, vg_name): |
2348 | 2323 |
"""Verifies and updates the node volume data. |
... | ... | |
2357 | 2332 |
@param vg_name: the configured VG name |
2358 | 2333 |
|
2359 | 2334 |
""" |
2360 |
node_name = ninfo.name |
|
2361 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
2362 |
|
|
2363 | 2335 |
nimg.lvm_fail = True |
2364 | 2336 |
lvdata = nresult.get(constants.NV_LVLIST, "Missing LV data") |
2365 | 2337 |
if vg_name is None: |
2366 | 2338 |
pass |
2367 | 2339 |
elif isinstance(lvdata, basestring): |
2368 |
_ErrorIf(True, constants.CV_ENODELVM, node_name,
|
|
2369 |
"LVM problem on node: %s", utils.SafeEncode(lvdata)) |
|
2340 |
self._ErrorIf(True, constants.CV_ENODELVM, ninfo.name,
|
|
2341 |
"LVM problem on node: %s", utils.SafeEncode(lvdata))
|
|
2370 | 2342 |
elif not isinstance(lvdata, dict): |
2371 |
_ErrorIf(True, constants.CV_ENODELVM, node_name,
|
|
2372 |
"rpc call to node failed (lvlist)") |
|
2343 |
self._ErrorIf(True, constants.CV_ENODELVM, ninfo.name,
|
|
2344 |
"rpc call to node failed (lvlist)")
|
|
2373 | 2345 |
else: |
2374 | 2346 |
nimg.volumes = lvdata |
2375 | 2347 |
nimg.lvm_fail = False |
... | ... | |
2407 | 2379 |
@param vg_name: the configured VG name |
2408 | 2380 |
|
2409 | 2381 |
""" |
2410 |
node_name = ninfo.name |
|
2411 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
2412 |
|
|
2413 | 2382 |
# try to read free memory (from the hypervisor) |
2414 | 2383 |
hv_info = nresult.get(constants.NV_HVINFO, None) |
2415 | 2384 |
test = not isinstance(hv_info, dict) or "memory_free" not in hv_info |
2416 |
_ErrorIf(test, constants.CV_ENODEHV, node_name,
|
|
2417 |
"rpc call to node failed (hvinfo)") |
|
2385 |
self._ErrorIf(test, constants.CV_ENODEHV, ninfo.name,
|
|
2386 |
"rpc call to node failed (hvinfo)")
|
|
2418 | 2387 |
if not test: |
2419 | 2388 |
try: |
2420 | 2389 |
nimg.mfree = int(hv_info["memory_free"]) |
2421 | 2390 |
except (ValueError, TypeError): |
2422 |
_ErrorIf(True, constants.CV_ENODERPC, node_name,
|
|
2423 |
"node returned invalid nodeinfo, check hypervisor") |
|
2391 |
self._ErrorIf(True, constants.CV_ENODERPC, ninfo.name,
|
|
2392 |
"node returned invalid nodeinfo, check hypervisor")
|
|
2424 | 2393 |
|
2425 | 2394 |
# FIXME: devise a free space model for file based instances as well |
2426 | 2395 |
if vg_name is not None: |
2427 | 2396 |
test = (constants.NV_VGLIST not in nresult or |
2428 | 2397 |
vg_name not in nresult[constants.NV_VGLIST]) |
2429 |
_ErrorIf(test, constants.CV_ENODELVM, node_name,
|
|
2430 |
"node didn't return data for the volume group '%s'" |
|
2431 |
" - it is either missing or broken", vg_name) |
|
2398 |
self._ErrorIf(test, constants.CV_ENODELVM, ninfo.name,
|
|
2399 |
"node didn't return data for the volume group '%s'"
|
|
2400 |
" - it is either missing or broken", vg_name)
|
|
2432 | 2401 |
if not test: |
2433 | 2402 |
try: |
2434 | 2403 |
nimg.dfree = int(nresult[constants.NV_VGLIST][vg_name]) |
2435 | 2404 |
except (ValueError, TypeError): |
2436 |
_ErrorIf(True, constants.CV_ENODERPC, node_name,
|
|
2437 |
"node returned invalid LVM info, check LVM status") |
|
2405 |
self._ErrorIf(True, constants.CV_ENODERPC, ninfo.name,
|
|
2406 |
"node returned invalid LVM info, check LVM status")
|
|
2438 | 2407 |
|
2439 | 2408 |
def _CollectDiskInfo(self, node_uuids, node_image, instanceinfo): |
2440 | 2409 |
"""Gets per-disk status information for all instances. |
... | ... | |
2606 | 2575 |
return True |
2607 | 2576 |
|
2608 | 2577 |
self.bad = False |
2609 |
_ErrorIf = self._ErrorIf # pylint: disable=C0103 |
|
2610 | 2578 |
verbose = self.op.verbose |
2611 | 2579 |
self._feedback_fn = feedback_fn |
2612 | 2580 |
|
... | ... | |
2828 | 2796 |
feedback_fn("* Verifying node %s (%s)" % (node_i.name, ntype)) |
2829 | 2797 |
|
2830 | 2798 |
msg = all_nvinfo[node_i.uuid].fail_msg |
2831 |
_ErrorIf(msg, constants.CV_ENODERPC, node_i.name, |
|
2832 |
"while contacting node: %s", msg) |
|
2799 |
self._ErrorIf(msg, constants.CV_ENODERPC, node_i.name,
|
|
2800 |
"while contacting node: %s", msg)
|
|
2833 | 2801 |
if msg: |
2834 | 2802 |
nimg.rpc_fail = True |
2835 | 2803 |
continue |
... | ... | |
2867 | 2835 |
|
2868 | 2836 |
for inst in non_primary_inst: |
2869 | 2837 |
test = inst in self.all_inst_info |
2870 |
_ErrorIf(test, constants.CV_EINSTANCEWRONGNODE, inst, |
|
2871 |
"instance should not run on node %s", node_i.name) |
|
2872 |
_ErrorIf(not test, constants.CV_ENODEORPHANINSTANCE, node_i.name, |
|
2873 |
"node is running unknown instance %s", inst) |
|
2838 |
self._ErrorIf(test, constants.CV_EINSTANCEWRONGNODE, inst,
|
|
2839 |
"instance should not run on node %s", node_i.name)
|
|
2840 |
self._ErrorIf(not test, constants.CV_ENODEORPHANINSTANCE, node_i.name,
|
|
2841 |
"node is running unknown instance %s", inst)
|
|
2874 | 2842 |
|
2875 | 2843 |
self._VerifyGroupDRBDVersion(all_nvinfo) |
2876 | 2844 |
self._VerifyGroupLVM(node_image, vg_name) |
Also available in: Unified diff