Revision 0ad1ea40
b/lib/cmdlib.py | ||
---|---|---|
2099 | 2099 |
|
2100 | 2100 |
@classmethod |
2101 | 2101 |
def _VerifyFiles(cls, errorif, nodeinfo, master_node, all_nvinfo, |
2102 |
(files_all, files_all_opt, files_mc, files_vm)):
|
|
2102 |
(files_all, files_opt, files_mc, files_vm)): |
|
2103 | 2103 |
"""Verifies file checksums collected from all nodes. |
2104 | 2104 |
|
2105 | 2105 |
@param errorif: Callback for reporting errors |
... | ... | |
2108 | 2108 |
@param all_nvinfo: RPC results |
2109 | 2109 |
|
2110 | 2110 |
""" |
2111 |
assert (len(files_all | files_all_opt | files_mc | files_vm) == |
|
2112 |
sum(map(len, [files_all, files_all_opt, files_mc, files_vm]))), \ |
|
2113 |
"Found file listed in more than one file list" |
|
2114 |
|
|
2115 | 2111 |
# Define functions determining which nodes to consider for a file |
2116 | 2112 |
files2nodefn = [ |
2117 | 2113 |
(files_all, None), |
2118 |
(files_all_opt, None), |
|
2119 | 2114 |
(files_mc, lambda node: (node.master_candidate or |
2120 | 2115 |
node.name == master_node)), |
2121 | 2116 |
(files_vm, lambda node: node.vm_capable), |
... | ... | |
2132 | 2127 |
frozenset(map(operator.attrgetter("name"), filenodes))) |
2133 | 2128 |
for filename in files) |
2134 | 2129 |
|
2135 |
assert set(nodefiles) == (files_all | files_all_opt | files_mc | files_vm)
|
|
2130 |
assert set(nodefiles) == (files_all | files_mc | files_vm) |
|
2136 | 2131 |
|
2137 | 2132 |
fileinfo = dict((filename, {}) for filename in nodefiles) |
2138 | 2133 |
ignore_nodes = set() |
... | ... | |
2174 | 2169 |
# Nodes missing file |
2175 | 2170 |
missing_file = expected_nodes - with_file |
2176 | 2171 |
|
2177 |
if filename in files_all_opt:
|
|
2172 |
if filename in files_opt: |
|
2178 | 2173 |
# All or no nodes |
2179 | 2174 |
errorif(missing_file and missing_file != expected_nodes, |
2180 | 2175 |
cls.ECLUSTERFILECHECK, None, |
... | ... | |
3735 | 3730 |
constants.SSH_KNOWN_HOSTS_FILE, |
3736 | 3731 |
constants.CONFD_HMAC_KEY, |
3737 | 3732 |
constants.CLUSTER_DOMAIN_SECRET_FILE, |
3733 |
constants.RAPI_USERS_FILE, |
|
3738 | 3734 |
]) |
3739 | 3735 |
|
3740 | 3736 |
if not redist: |
... | ... | |
3747 | 3743 |
if cluster.modify_etc_hosts: |
3748 | 3744 |
files_all.add(constants.ETC_HOSTS) |
3749 | 3745 |
|
3750 |
# Files which must either exist on all nodes or on none |
|
3751 |
files_all_opt = set([ |
|
3746 |
# Files which are optional, these must: |
|
3747 |
# - be present in one other category as well |
|
3748 |
# - either exist or not exist on all nodes of that category (mc, vm all) |
|
3749 |
files_opt = set([ |
|
3752 | 3750 |
constants.RAPI_USERS_FILE, |
3753 | 3751 |
]) |
3754 | 3752 |
|
... | ... | |
3762 | 3760 |
for hv_name in cluster.enabled_hypervisors |
3763 | 3761 |
for filename in hypervisor.GetHypervisor(hv_name).GetAncillaryFiles()[0]) |
3764 | 3762 |
|
3765 |
# Filenames must be unique |
|
3766 |
assert (len(files_all | files_all_opt | files_mc | files_vm) == |
|
3767 |
sum(map(len, [files_all, files_all_opt, files_mc, files_vm]))), \ |
|
3763 |
files_opt |= set(filename |
|
3764 |
for hv_name in cluster.enabled_hypervisors |
|
3765 |
for filename in hypervisor.GetHypervisor(hv_name).GetAncillaryFiles()[1]) |
|
3766 |
|
|
3767 |
# Filenames in each category must be unique |
|
3768 |
all_files_set = files_all | files_mc | files_vm |
|
3769 |
assert (len(all_files_set) == |
|
3770 |
sum(map(len, [files_all, files_mc, files_vm]))), \ |
|
3768 | 3771 |
"Found file listed in more than one file list" |
3769 | 3772 |
|
3770 |
return (files_all, files_all_opt, files_mc, files_vm) |
|
3773 |
# Optional files must be present in one other category |
|
3774 |
assert all_files_set.issuperset(files_opt), \ |
|
3775 |
"Optional file not in a different required list" |
|
3776 |
|
|
3777 |
return (files_all, files_opt, files_mc, files_vm) |
|
3771 | 3778 |
|
3772 | 3779 |
|
3773 | 3780 |
def _RedistributeAncillaryFiles(lu, additional_nodes=None, additional_vm=True): |
... | ... | |
3801 | 3808 |
nodelist.remove(master_info.name) |
3802 | 3809 |
|
3803 | 3810 |
# Gather file lists |
3804 |
(files_all, files_all_opt, files_mc, files_vm) = \
|
|
3811 |
(files_all, _, files_mc, files_vm) = \
|
|
3805 | 3812 |
_ComputeAncillaryFiles(cluster, True) |
3806 | 3813 |
|
3807 | 3814 |
# Never re-distribute configuration file from here |
... | ... | |
3811 | 3818 |
|
3812 | 3819 |
filemap = [ |
3813 | 3820 |
(online_nodes, files_all), |
3814 |
(online_nodes, files_all_opt), |
|
3815 | 3821 |
(vm_nodes, files_vm), |
3816 | 3822 |
] |
3817 | 3823 |
|
b/test/ganeti.cmdlib_unittest.py | ||
---|---|---|
40 | 40 |
from ganeti import objects |
41 | 41 |
from ganeti import compat |
42 | 42 |
from ganeti import rpc |
43 |
from ganeti.hypervisor import hv_xen |
|
43 | 44 |
|
44 | 45 |
import testutils |
45 | 46 |
import mocks |
... | ... | |
289 | 290 |
errors = [] |
290 | 291 |
master_name = "master.example.com" |
291 | 292 |
nodeinfo = [ |
292 |
objects.Node(name=master_name, offline=False), |
|
293 |
objects.Node(name="node2.example.com", offline=False), |
|
294 |
objects.Node(name="node3.example.com", master_candidate=True), |
|
295 |
objects.Node(name="node4.example.com", offline=False), |
|
296 |
objects.Node(name="nodata.example.com"), |
|
293 |
objects.Node(name=master_name, offline=False, vm_capable=True), |
|
294 |
objects.Node(name="node2.example.com", offline=False, vm_capable=True), |
|
295 |
objects.Node(name="node3.example.com", master_candidate=True, |
|
296 |
vm_capable=False), |
|
297 |
objects.Node(name="node4.example.com", offline=False, vm_capable=True), |
|
298 |
objects.Node(name="nodata.example.com", offline=False, vm_capable=True), |
|
297 | 299 |
objects.Node(name="offline.example.com", offline=True), |
298 | 300 |
] |
299 | 301 |
cluster = objects.Cluster(modify_etc_hosts=True, |
... | ... | |
301 | 303 |
files_all = set([ |
302 | 304 |
constants.CLUSTER_DOMAIN_SECRET_FILE, |
303 | 305 |
constants.RAPI_CERT_FILE, |
306 |
constants.RAPI_USERS_FILE, |
|
304 | 307 |
]) |
305 |
files_all_opt = set([
|
|
308 |
files_opt = set([ |
|
306 | 309 |
constants.RAPI_USERS_FILE, |
310 |
hv_xen.XL_CONFIG_FILE, |
|
311 |
constants.VNC_PASSWORD_FILE, |
|
307 | 312 |
]) |
308 | 313 |
files_mc = set([ |
309 | 314 |
constants.CLUSTER_CONF_FILE, |
310 | 315 |
]) |
311 |
files_vm = set() |
|
316 |
files_vm = set([ |
|
317 |
hv_xen.XEND_CONFIG_FILE, |
|
318 |
hv_xen.XL_CONFIG_FILE, |
|
319 |
constants.VNC_PASSWORD_FILE, |
|
320 |
]) |
|
312 | 321 |
nvinfo = { |
313 | 322 |
master_name: rpc.RpcResult(data=(True, { |
314 | 323 |
constants.NV_FILELIST: { |
315 | 324 |
constants.CLUSTER_CONF_FILE: "82314f897f38b35f9dab2f7c6b1593e0", |
316 | 325 |
constants.RAPI_CERT_FILE: "babbce8f387bc082228e544a2146fee4", |
317 | 326 |
constants.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4", |
327 |
hv_xen.XEND_CONFIG_FILE: "b4a8a824ab3cac3d88839a9adeadf310", |
|
328 |
hv_xen.XL_CONFIG_FILE: "77935cee92afd26d162f9e525e3d49b9" |
|
318 | 329 |
}})), |
319 | 330 |
"node2.example.com": rpc.RpcResult(data=(True, { |
320 | 331 |
constants.NV_FILELIST: { |
321 | 332 |
constants.RAPI_CERT_FILE: "97f0356500e866387f4b84233848cc4a", |
333 |
hv_xen.XEND_CONFIG_FILE: "b4a8a824ab3cac3d88839a9adeadf310", |
|
322 | 334 |
} |
323 | 335 |
})), |
324 | 336 |
"node3.example.com": rpc.RpcResult(data=(True, { |
... | ... | |
333 | 345 |
constants.CLUSTER_CONF_FILE: "conf-a6d4b13e407867f7a7b4f0f232a8f527", |
334 | 346 |
constants.CLUSTER_DOMAIN_SECRET_FILE: "cds-47b5b3f19202936bb4", |
335 | 347 |
constants.RAPI_USERS_FILE: "rapiusers-ea3271e8d810ef3", |
348 |
hv_xen.XL_CONFIG_FILE: "77935cee92afd26d162f9e525e3d49b9" |
|
336 | 349 |
} |
337 | 350 |
})), |
338 | 351 |
"nodata.example.com": rpc.RpcResult(data=(True, {})), |
... | ... | |
342 | 355 |
|
343 | 356 |
self._VerifyFiles(compat.partial(self._FakeErrorIf, errors), nodeinfo, |
344 | 357 |
master_name, nvinfo, |
345 |
(files_all, files_all_opt, files_mc, files_vm))
|
|
358 |
(files_all, files_opt, files_mc, files_vm)) |
|
346 | 359 |
self.assertEqual(sorted(errors), sorted([ |
347 | 360 |
(None, ("File %s found with 2 different checksums (variant 1 on" |
348 | 361 |
" node2.example.com, node3.example.com, node4.example.com;" |
... | ... | |
351 | 364 |
constants.CLUSTER_DOMAIN_SECRET_FILE)), |
352 | 365 |
(None, ("File %s should not exist on node(s) node4.example.com" % |
353 | 366 |
constants.CLUSTER_CONF_FILE)), |
367 |
(None, ("File %s is missing from node(s) node4.example.com" % |
|
368 |
hv_xen.XEND_CONFIG_FILE)), |
|
354 | 369 |
(None, ("File %s is missing from node(s) node3.example.com" % |
355 | 370 |
constants.CLUSTER_CONF_FILE)), |
356 | 371 |
(None, ("File %s found with 2 different checksums (variant 1 on" |
... | ... | |
359 | 374 |
(None, ("File %s is optional, but it must exist on all or no nodes (not" |
360 | 375 |
" found on master.example.com, node2.example.com," |
361 | 376 |
" node3.example.com)" % constants.RAPI_USERS_FILE)), |
377 |
(None, ("File %s is optional, but it must exist on all or no nodes (not" |
|
378 |
" found on node2.example.com)" % hv_xen.XL_CONFIG_FILE)), |
|
362 | 379 |
("nodata.example.com", "Node did not return file checksum data"), |
363 | 380 |
])) |
364 | 381 |
|
Also available in: Unified diff