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