From b22fb2d0c84dd3a2400b01ce379b9a8057085240 Mon Sep 17 00:00:00 2001 From: Adam King Date: Thu, 6 Oct 2022 14:36:52 -0400 Subject: [PATCH] mgr/cephadm: specify ports for iscsi Fixes: https://tracker.ceph.com/issues/57786 Signed-off-by: Adam King (cherry picked from commit 9ee9c940a7d7481a090a2e986753ca7db4fa521e) --- src/cephadm/cephadm | 14 +++++- src/pybind/mgr/cephadm/tests/test_services.py | 48 +++++++++++++++++++ .../ceph/deployment/service_spec.py | 3 ++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/cephadm/cephadm b/src/cephadm/cephadm index 96ade7d0b88af..e41b982533548 100755 --- a/src/cephadm/cephadm +++ b/src/cephadm/cephadm @@ -3311,7 +3311,7 @@ def deploy_daemon(ctx, fsid, daemon_type, daemon_id, c, uid, gid, # Open ports explicitly required for the daemon if ports: fw = Firewalld(ctx) - fw.open_ports(ports) + fw.open_ports(ports + fw.external_ports.get(daemon_type, [])) fw.apply_rules() if reconfig and daemon_type not in Ceph.daemons: @@ -3544,6 +3544,18 @@ def deploy_daemon_units( class Firewalld(object): + + # for specifying ports we should always open when opening + # ports for a daemon of that type. Main use case is for ports + # that we should open when deploying the daemon type but that + # the daemon itself may not necessarily need to bind to the port. + # This needs to be handed differently as we don't want to fail + # deployment if the port cannot be bound to but we still want to + # open the port in the firewall. + external_ports: Dict[str, List[int]] = { + 'iscsi': [3260] # 3260 is the well known iSCSI port + } + def __init__(self, ctx): # type: (CephadmContext) -> None self.ctx = ctx diff --git a/src/pybind/mgr/cephadm/tests/test_services.py b/src/pybind/mgr/cephadm/tests/test_services.py index 1cf76b9db9e33..acecb5289eb0a 100644 --- a/src/pybind/mgr/cephadm/tests/test_services.py +++ b/src/pybind/mgr/cephadm/tests/test_services.py @@ -242,6 +242,54 @@ class TestISCSIService: assert dashboard_expected_call in self.mgr.check_mon_command.mock_calls + @patch("cephadm.serve.CephadmServe._run_cephadm") + @patch("cephadm.module.CephadmOrchestrator.get_unique_name") + @patch("cephadm.services.iscsi.IscsiService.get_trusted_ips") + def test_iscsi_config(self, _get_trusted_ips, _get_name, _run_cephadm, cephadm_module: CephadmOrchestrator): + + iscsi_daemon_id = 'testpool.test.qwert' + trusted_ips = '1.1.1.1,2.2.2.2' + api_port = 3456 + api_user = 'test-user' + api_password = 'test-password' + pool = 'testpool' + _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) + _get_name.return_value = iscsi_daemon_id + _get_trusted_ips.return_value = trusted_ips + + iscsi_gateway_conf = f"""# This file is generated by cephadm. +[config] +cluster_client_name = client.iscsi.{iscsi_daemon_id} +pool = {pool} +trusted_ip_list = {trusted_ips} +minimum_gateways = 1 +api_port = {api_port} +api_user = {api_user} +api_password = {api_password} +api_secure = False +log_to_stderr = True +log_to_stderr_prefix = debug +log_to_file = False""" + + with with_host(cephadm_module, 'test'): + with with_service(cephadm_module, IscsiServiceSpec(service_id=pool, + api_port=api_port, + api_user=api_user, + api_password=api_password, + pool=pool, + trusted_ip_list=trusted_ips)): + _run_cephadm.assert_called_with( + 'test', + f'iscsi.{iscsi_daemon_id}', + 'deploy', + [ + '--name', f'iscsi.{iscsi_daemon_id}', + '--meta-json', f'{"{"}"service_name": "iscsi.{pool}", "ports": [{api_port}], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null, "extra_container_args": null{"}"}', + '--config-json', '-', '--tcp-ports', '3456' + ], + stdin=json.dumps({"config": "", "keyring": "[client.iscsi.testpool.test.qwert]\nkey = None\n", "files": {"iscsi-gateway.cfg": iscsi_gateway_conf}}), + image='') + class TestMonitoring: def _get_config(self, url: str) -> str: diff --git a/src/python-common/ceph/deployment/service_spec.py b/src/python-common/ceph/deployment/service_spec.py index d1f39cc16ace3..4a4c6c07c2e41 100644 --- a/src/python-common/ceph/deployment/service_spec.py +++ b/src/python-common/ceph/deployment/service_spec.py @@ -965,6 +965,9 @@ class IscsiServiceSpec(ServiceSpec): if not self.api_secure and self.ssl_cert and self.ssl_key: self.api_secure = True + def get_port_start(self) -> List[int]: + return [self.api_port or 5000] + def validate(self) -> None: super(IscsiServiceSpec, self).validate() -- 2.39.5