from ceph.deployment.inventory import Device
from ceph.deployment.drive_group import DriveGroupSpec
-from ceph.deployment.service_spec import ServiceSpec, NFSServiceSpec, RGWSpec
+from ceph.deployment.service_spec import ServiceSpec, NFSServiceSpec, RGWSpec, PlacementSpec, HostPlacementSpec
from ceph.utils import datetime_now
from ceph.deployment.drive_selection.matchers import SizeMatcher
from mgr_module import NFS_POOL_NAME
def blink_light(self, ident_fault, on, locs):
# type: (str, bool, List[orchestrator.DeviceLightLoc]) -> List[str]
return [self._execute_blight_job(ident_fault, on, loc) for loc in locs]
+
+def placement_spec_to_node_selector(spec: PlacementSpec, all_hosts: List) -> ccl.NodeSelectorTermsItem:
+ all_hostnames = [hs.hostname for hs in all_hosts]
+ res = ccl.NodeSelectorTermsItem(matchExpressions=ccl.MatchExpressionsList())
+ if spec.host_pattern and spec.host_pattern != "*":
+ raise RuntimeError("The Rook orchestrator only supports a host_pattern of * for placements")
+ if spec.label:
+ res.matchExpressions.append(
+ ccl.MatchExpressionsItem(
+ key="ceph-label/" + spec.label,
+ operator="Exists"
+ )
+ )
+ if spec.hosts:
+ host_list = [h.hostname for h in spec.hosts if h.hostname in all_hostnames]
+ res.matchExpressions.append(
+ ccl.MatchExpressionsItem(
+ key="kubernetes.io/hostname",
+ operator="In",
+ values=ccl.CrdObjectList(host_list)
+ )
+ )
+ if spec.host_pattern == "*":
+ res.matchExpressions.append(
+ ccl.MatchExpressionsItem(
+ key="kubernetes.io/hostname",
+ operator="Exists",
+ )
+ )
+ return res
+
+def node_selector_to_placement_spec(node_selector: ccl.NodeSelectorTermsItem) -> PlacementSpec:
+ res = PlacementSpec()
+ for expression in node_selector.matchExpressions:
+ if expression.key.startswith("ceph-label/"):
+ res.label = expression.key.split('/')[1]
+ elif expression.key == "kubernetes.io/hostname":
+ if expression.operator == "Exists":
+ res.host_pattern = "*"
+ elif expression.operator == "In":
+ res.hosts = [HostPlacementSpec(hostname=value, network='', name='')for value in expression.values]
+ return res
--- /dev/null
+# flake8: noqa
+
+from rook.rook_cluster import placement_spec_to_node_selector, node_selector_to_placement_spec
+from rook.rook_client.ceph.cephcluster import MatchExpressionsItem, MatchExpressionsList, NodeSelectorTermsItem
+import pytest
+from orchestrator import HostSpec
+from ceph.deployment.service_spec import PlacementSpec
+
+@pytest.mark.parametrize("hosts",
+ [ # noqa: E128
+ [
+ HostSpec(
+ hostname="node1",
+ labels=["label1"]
+ ),
+ HostSpec(
+ hostname="node2",
+ labels=[]
+ ),
+ HostSpec(
+ hostname="node3",
+ labels=["label1"]
+ )
+ ]
+ ])
+@pytest.mark.parametrize("expected_placement_spec, expected_node_selector",
+ [ # noqa: E128
+ (
+ PlacementSpec(
+ label="label1"
+ ),
+ NodeSelectorTermsItem(
+ matchExpressions=MatchExpressionsList(
+ [
+ MatchExpressionsItem(
+ key="ceph-label/label1",
+ operator="Exists"
+ )
+ ]
+ )
+ )
+ ),
+ (
+ PlacementSpec(
+ label="label1",
+ host_pattern="*"
+ ),
+ NodeSelectorTermsItem(
+ matchExpressions=MatchExpressionsList(
+ [
+ MatchExpressionsItem(
+ key="ceph-label/label1",
+ operator="Exists"
+ ),
+ MatchExpressionsItem(
+ key="kubernetes.io/hostname",
+ operator="Exists",
+ )
+ ]
+ )
+ )
+ ),
+ (
+ PlacementSpec(
+ host_pattern="*"
+ ),
+ NodeSelectorTermsItem(
+ matchExpressions=MatchExpressionsList(
+ [
+ MatchExpressionsItem(
+ key="kubernetes.io/hostname",
+ operator="Exists",
+ )
+ ]
+ )
+ )
+ ),
+ (
+ PlacementSpec(
+ hosts=["node1", "node2", "node3"]
+ ),
+ NodeSelectorTermsItem(
+ matchExpressions=MatchExpressionsList(
+ [
+ MatchExpressionsItem(
+ key="kubernetes.io/hostname",
+ operator="In",
+ values=["node1", "node2", "node3"]
+ )
+ ]
+ )
+ )
+ ),
+ ])
+def test_placement_spec_translate(hosts, expected_placement_spec, expected_node_selector):
+ node_selector = placement_spec_to_node_selector(expected_placement_spec, hosts)
+ assert [(getattr(expression, 'key', None), getattr(expression, 'operator', None), getattr(expression, 'values', None)) for expression in node_selector.matchExpressions] == [(getattr(expression, 'key', None), getattr(expression, 'operator', None), getattr(expression, 'values', None)) for expression in expected_node_selector.matchExpressions]
+ placement_spec = node_selector_to_placement_spec(expected_node_selector)
+ assert placement_spec == expected_placement_spec
+ assert (getattr(placement_spec, 'label', None), getattr(placement_spec, 'hosts', None), getattr(placement_spec, 'host_pattern', None)) == (getattr(expected_placement_spec, 'label', None), getattr(expected_placement_spec, 'hosts', None), getattr(expected_placement_spec, 'host_pattern', None))