]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/cephadm/schedule: respect count-per-host
authorSage Weil <sage@newdream.net>
Sat, 6 Mar 2021 15:10:42 +0000 (10:10 -0500)
committerSage Weil <sage@newdream.net>
Tue, 16 Mar 2021 12:56:18 +0000 (07:56 -0500)
In the no-count cases, our job is simple: we have a set of hosts specified
via some other means (label, filter, explicit list) and simply need to
do N instances for each of those hosts.

Signed-off-by: Sage Weil <sage@newdream.net>
(cherry picked from commit d8d808cf30eb5406e8cf6545d6c9900bc1e2be58)

src/pybind/mgr/cephadm/schedule.py
src/pybind/mgr/cephadm/tests/test_scheduling.py

index b6cb3f4841bc25673ca7dafb47f23c0cc6ce0109..794297e7c1af757a65408958afcf3807509c94bb 100644 (file)
@@ -116,21 +116,28 @@ class HostAssignment(object):
 
         count = self.spec.placement.count
 
-        # get candidates based on [hosts, label, host_pattern]
-        candidates = self.get_candidates()
+        # get candidate hosts based on [hosts, label, host_pattern]
+        candidates = self.get_candidates()  # type: List[HostPlacementSpec]
 
         # If we don't have <count> the list of candidates is definitive.
         if count is None:
             logger.debug('Provided hosts: %s' % candidates)
+
+            if self.spec.placement.count_per_host:
+                per_host = self.spec.placement.count_per_host
+            else:
+                per_host = 1
+
             # do not deploy ha-rgw on hosts that don't support virtual ips
             if self.spec.service_type == 'ha-rgw' and self.filter_new_host:
                 old = candidates
                 candidates = [h for h in candidates if self.filter_new_host(h.hostname)]
                 for h in list(set(old) - set(candidates)):
                     logger.info(
-                        f"Filtered out host {h.hostname} for ha-rgw. Could not verify host allowed virtual ips")
-                logger.info('filtered %s down to %s' % (old, candidates))
-            return candidates
+                        f"Filtered out host {h.hostname} for ha-rgw: could not verify host allowed virtual ips")
+                logger.debug('Filtered %s down to %s' % (old, candidates))
+
+            return candidates * per_host
 
         # prefer hosts that already have services.
         # this avoids re-assigning to _new_ hosts
@@ -141,7 +148,7 @@ class HostAssignment(object):
         # The amount of hosts that need to be selected in order to fulfill count.
         need = count - len(hosts_with_daemons)
 
-        # hostspecs that are do not have daemons on them but are still candidates.
+        # hostspecs that do not have daemons on them but are still candidates.
         others = difference_hostspecs(candidates, hosts_with_daemons)
 
         # we don't need any additional hosts
@@ -215,12 +222,12 @@ class HostAssignment(object):
     def get_candidates(self) -> List[HostPlacementSpec]:
         if self.spec.placement.hosts:
             return self.spec.placement.hosts
-        elif self.spec.placement.label:
+        if self.spec.placement.label:
             return [
                 HostPlacementSpec(x.hostname, '', '')
                 for x in self.hosts_by_label(self.spec.placement.label)
             ]
-        elif self.spec.placement.host_pattern:
+        if self.spec.placement.host_pattern:
             return [
                 HostPlacementSpec(x, '', '')
                 for x in self.spec.placement.filter_matching_hostspecs(self.hosts)
index 5066c7dab1acca068445d3a8a422c1e01549a55d..78f38b07b82c64e0d485a21ce41456c928c8e948 100644 (file)
@@ -349,6 +349,17 @@ class NodeAssignmentTest(NamedTuple):
             ],
             ['host1', 'host2', 'host3']
         ),
+        # all_hosts + count_per_host
+        NodeAssignmentTest(
+            'mgr',
+            PlacementSpec(host_pattern='*', count_per_host=2),
+            'host1 host2 host3'.split(),
+            [
+                DaemonDescription('mgr', 'a', 'host1'),
+                DaemonDescription('mgr', 'b', 'host2'),
+            ],
+            ['host1', 'host2', 'host3', 'host1', 'host2', 'host3']
+        ),
         # count that is bigger than the amount of hosts. Truncate to len(hosts)
         # RGWs should not be co-located to each other.
         NodeAssignmentTest(
@@ -418,6 +429,15 @@ class NodeAssignmentTest(NamedTuple):
             [],
             ['host1', 'host2', 'host3']
         ),
+        # label only + count_per_hst
+        NodeAssignmentTest(
+            'mgr',
+            PlacementSpec(label='foo', count_per_host=3),
+            'host1 host2 host3'.split(),
+            [],
+            ['host1', 'host2', 'host3', 'host1', 'host2', 'host3',
+             'host1', 'host2', 'host3']
+        ),
         # host_pattern
         NodeAssignmentTest(
             'mgr',
@@ -426,6 +446,14 @@ class NodeAssignmentTest(NamedTuple):
             [],
             ['mgrhost1', 'mgrhost2']
         ),
+        # host_pattern + count_per_host
+        NodeAssignmentTest(
+            'mgr',
+            PlacementSpec(host_pattern='mgr*', count_per_host=3),
+            'mgrhost1 mgrhost2 datahost'.split(),
+            [],
+            ['mgrhost1', 'mgrhost2', 'mgrhost1', 'mgrhost2', 'mgrhost1', 'mgrhost2']
+        ),
     ])
 def test_node_assignment(service_type, placement, hosts, daemons, expected):
     service_id = None