import json from ceph.deployment.service_spec import PlacementSpec, ServiceSpec, HostPlacementSpec from ceph.utils import datetime_to_str, datetime_now from cephadm import CephadmOrchestrator from cephadm.inventory import SPEC_STORE_PREFIX from cephadm.tests.fixtures import _run_cephadm, wait, with_host from cephadm.serve import CephadmServe from tests import mock @mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('[]')) @mock.patch( "cephadm.services.cephadmservice.RgwService.create_realm_zonegroup_zone", lambda _, __, ___: None) def test_migrate_scheduler(cephadm_module: CephadmOrchestrator): with with_host(cephadm_module, 'host1', refresh_hosts=False): with with_host(cephadm_module, 'host2', refresh_hosts=False): # emulate the old scheduler: c = cephadm_module.apply_rgw( ServiceSpec('rgw', 'r.z', placement=PlacementSpec(host_pattern='*', count=2))) assert wait(cephadm_module, c) == 'Scheduled rgw.r.z update...' # with pytest.raises(OrchestratorError, match="cephadm migration still ongoing. Please wait, until the migration is complete."): CephadmServe(cephadm_module)._apply_all_services() cephadm_module.migration_current = 0
from datetime import datetime import pytest from ceph.deployment.service_spec import PlacementSpec, ServiceSpec, HostPlacementSpec from cephadm import CephadmOrchestrator from cephadm.inventory import SPEC_STORE_PREFIX from cephadm.utils import DATEFMT from cephadm.tests.fixtures import _run_cephadm, cephadm_module, wait, with_host from orchestrator import OrchestratorError from cephadm.serve import CephadmServe from tests import mock @mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('[]')) @mock.patch( "cephadm.services.cephadmservice.RgwService.create_realm_zonegroup_zone", lambda _, __, ___: None) def test_migrate_scheduler(cephadm_module: CephadmOrchestrator): with with_host(cephadm_module, 'host1', refresh_hosts=False): with with_host(cephadm_module, 'host2', refresh_hosts=False): # emulate the old scheduler: c = cephadm_module.apply_rgw( ServiceSpec('rgw', 'r.z', placement=PlacementSpec(host_pattern='*', count=2))) assert wait(cephadm_module, c) == 'Scheduled rgw.r.z update...'
class TestMonitoring: @patch("cephadm.serve.CephadmServe._run_cephadm") def test_alertmanager_config(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): with with_service(cephadm_module, AlertManagerSpec()): y = dedent(""" # This file is generated by cephadm. # See https://prometheus.io/docs/alerting/configuration/ for documentation. global: resolve_timeout: 5m route: receiver: 'default' routes: - group_by: ['alertname'] group_wait: 10s group_interval: 10s repeat_interval: 1h receiver: 'ceph-dashboard' receivers: - name: 'default' webhook_configs: - name: 'ceph-dashboard' webhook_configs: - url: 'http://[::1]:8080/api/prometheus_receiver' """).lstrip() _run_cephadm.assert_called_with( 'test', 'alertmanager.test', 'deploy', [ '--name', 'alertmanager.test', '--meta-json', '{"service_name": "alertmanager", "ports": [9093, 9094], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null, "extra_container_args": null}', '--config-json', '-', '--tcp-ports', '9093 9094' ], stdin=json.dumps({"files": {"alertmanager.yml": y}, "peers": []}), image='')\ @patch("cephadm.serve.CephadmServe._run_cephadm") def test_prometheus_config(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): with with_service(cephadm_module, MonitoringSpec('node-exporter')) as _, \ with_service(cephadm_module, MonitoringSpec('prometheus')) as _: y = dedent(""" # This file is generated by cephadm. global: scrape_interval: 10s evaluation_interval: 10s rule_files: - /etc/prometheus/alerting/* scrape_configs: - job_name: 'ceph' honor_labels: true static_configs: - targets: - '[::1]:9283' - job_name: 'node' static_configs: - targets: ['[1::4]:9100'] labels: instance: 'test' """).lstrip() _run_cephadm.assert_called_with( 'test', 'prometheus.test', 'deploy', [ '--name', 'prometheus.test', '--meta-json', '{"service_name": "prometheus", "ports": [9095], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null, "extra_container_args": null}', '--config-json', '-', '--tcp-ports', '9095' ], stdin=json.dumps({"files": { "prometheus.yml": y }}), image='') @patch("cephadm.serve.CephadmServe._run_cephadm") def test_loki_config(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): with with_service(cephadm_module, MonitoringSpec('loki')) as _: y = dedent(""" # This file is generated by cephadm. auth_enabled: false server: http_listen_port: 3100 grpc_listen_port: 8080 common: path_prefix: /tmp/loki storage: filesystem: chunks_directory: /tmp/loki/chunks rules_directory: /tmp/loki/rules replication_factor: 1 ring: instance_addr: 127.0.0.1 kvstore: store: inmemory schema_config: configs: - from: 2020-10-24 store: boltdb-shipper object_store: filesystem schema: v11 index: prefix: index_ period: 24h""").lstrip() _run_cephadm.assert_called_with( 'test', 'loki.test', 'deploy', [ '--name', 'loki.test', '--meta-json', '{"service_name": "loki", "ports": [3100], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null, "extra_container_args": null}', '--config-json', '-', '--tcp-ports', '3100' ], stdin=json.dumps({"files": { "loki.yml": y }}), image='') @patch("cephadm.serve.CephadmServe._run_cephadm") def test_promtail_config(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): with with_service(cephadm_module, ServiceSpec('mgr')) as _, \ with_service(cephadm_module, MonitoringSpec('promtail')) as _: y = dedent(""" # This file is generated by cephadm. server: http_listen_port: 9080 grpc_listen_port: 0 positions: filename: /tmp/positions.yaml clients: - url: http://1::4:3100/loki/api/v1/push scrape_configs: - job_name: system static_configs: - targets: - 1::4 labels: job: Cluster Logs __path__: /var/log/ceph/**/*.log""").lstrip() _run_cephadm.assert_called_with( 'test', 'promtail.test', 'deploy', [ '--name', 'promtail.test', '--meta-json', '{"service_name": "promtail", "ports": [9080], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null, "extra_container_args": null}', '--config-json', '-', '--tcp-ports', '9080' ], stdin=json.dumps({"files": { "promtail.yml": y }}), image='') @patch("cephadm.serve.CephadmServe._run_cephadm") @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '1::4') @patch("cephadm.services.monitoring.verify_tls", lambda *_: None) def test_grafana_config(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(("{}", "", 0)) with with_host(cephadm_module, "test"): cephadm_module.set_store("grafana_crt", "c") cephadm_module.set_store("grafana_key", "k") with with_service(cephadm_module, MonitoringSpec("prometheus")) as _, with_service( cephadm_module, ServiceSpec("mgr")) as _, with_service( cephadm_module, GrafanaSpec("grafana")) as _: files = { 'grafana.ini': dedent(""" # This file is generated by cephadm. [users] default_theme = light [auth.anonymous] enabled = true org_name = 'Main Org.' org_role = 'Viewer' [server] domain = 'bootstrap.storage.lab' protocol = https cert_file = /etc/grafana/certs/cert_file cert_key = /etc/grafana/certs/cert_key http_port = 3000 http_addr = [security] disable_initial_admin_creation = true cookie_secure = true cookie_samesite = none allow_embedding = true""").lstrip(), # noqa: W291 'provisioning/datasources/ceph-dashboard.yml': dedent(""" # This file is generated by cephadm. deleteDatasources: - name: 'Dashboard1' orgId: 1 - name: 'Loki' orgId: 2 datasources: - name: 'Dashboard1' type: 'prometheus' access: 'proxy' orgId: 1 url: 'http://[1::4]:9095' basicAuth: false isDefault: true editable: false - name: 'Loki' type: 'loki' access: 'proxy' orgId: 2 url: 'http://[1::4]:3100' basicAuth: false isDefault: true editable: false""").lstrip(), 'certs/cert_file': dedent(""" # generated by cephadm c""").lstrip(), 'certs/cert_key': dedent(""" # generated by cephadm k""").lstrip(), } _run_cephadm.assert_called_with( 'test', 'grafana.test', 'deploy', [ '--name', 'grafana.test', '--meta-json', '{"service_name": "grafana", "ports": [3000], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null, "extra_container_args": null}', '--config-json', '-', '--tcp-ports', '3000' ], stdin=json.dumps({"files": files}), image='') @patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}')) def test_grafana_initial_admin_pw(self, cephadm_module: CephadmOrchestrator): with with_host(cephadm_module, 'test'): with with_service(cephadm_module, ServiceSpec('mgr')) as _, \ with_service(cephadm_module, GrafanaSpec(initial_admin_password='******')): out = cephadm_module.cephadm_services[ 'grafana'].generate_config( CephadmDaemonDeploySpec('test', 'daemon', 'grafana')) assert out == ({ 'files': { 'grafana.ini': '# This file is generated by cephadm.\n' '[users]\n' ' default_theme = light\n' '[auth.anonymous]\n' ' enabled = true\n' " org_name = 'Main Org.'\n" " org_role = 'Viewer'\n" '[server]\n' " domain = 'bootstrap.storage.lab'\n" ' protocol = https\n' ' cert_file = /etc/grafana/certs/cert_file\n' ' cert_key = /etc/grafana/certs/cert_key\n' ' http_port = 3000\n' ' http_addr = \n' '[security]\n' ' admin_user = admin\n' ' admin_password = secure\n' ' cookie_secure = true\n' ' cookie_samesite = none\n' ' allow_embedding = true', 'provisioning/datasources/ceph-dashboard.yml': "# This file is generated by cephadm.\n" 'deleteDatasources:\n\n' " - name: 'Loki'\n" ' orgId: 2\n\n' 'datasources:\n\n' " - name: 'Loki'\n" " type: 'loki'\n" " access: 'proxy'\n" ' orgId: 2\n' " url: 'http://[1::4]:3100'\n" ' basicAuth: false\n' ' isDefault: true\n' ' editable: false', 'certs/cert_file': ANY, 'certs/cert_key': ANY } }, []) @patch("cephadm.serve.CephadmServe._run_cephadm") def test_monitoring_ports(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): yaml_str = """service_type: alertmanager service_name: alertmanager placement: count: 1 spec: port: 4200 """ yaml_file = yaml.safe_load(yaml_str) spec = ServiceSpec.from_json(yaml_file) with patch( "cephadm.services.monitoring.AlertmanagerService.generate_config", return_value=({}, [])): with with_service(cephadm_module, spec): CephadmServe(cephadm_module)._check_daemons() _run_cephadm.assert_called_with( 'test', 'alertmanager.test', 'deploy', [ '--name', 'alertmanager.test', '--meta-json', '{"service_name": "alertmanager", "ports": [4200, 9094], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null, "extra_container_args": null}', '--config-json', '-', '--tcp-ports', '4200 9094', '--reconfig' ], stdin='{}', image='')
class TestMonitoring: @patch("cephadm.serve.CephadmServe._run_cephadm") def test_alertmanager_config(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): with with_service(cephadm_module, AlertManagerSpec()): y = dedent(""" # This file is generated by cephadm. # See https://prometheus.io/docs/alerting/configuration/ for documentation. global: resolve_timeout: 5m route: receiver: 'default' routes: - group_by: ['alertname'] group_wait: 10s group_interval: 10s repeat_interval: 1h receiver: 'ceph-dashboard' receivers: - name: 'default' webhook_configs: - name: 'ceph-dashboard' webhook_configs: - url: 'http://[::1]:8080/api/prometheus_receiver' """).lstrip() _run_cephadm.assert_called_with( 'test', 'alertmanager.test', 'deploy', [ '--name', 'alertmanager.test', '--meta-json', '{"service_name": "alertmanager", "ports": [9093, 9094], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null}', '--config-json', '-', '--tcp-ports', '9093 9094' ], stdin=json.dumps({"files": {"alertmanager.yml": y}, "peers": []}), image='')\ @patch("cephadm.serve.CephadmServe._run_cephadm") def test_prometheus_config(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): with with_service(cephadm_module, MonitoringSpec('node-exporter')) as _, \ with_service(cephadm_module, MonitoringSpec('prometheus')) as _: y = dedent(""" # This file is generated by cephadm. global: scrape_interval: 10s evaluation_interval: 10s rule_files: - /etc/prometheus/alerting/* scrape_configs: - job_name: 'ceph' honor_labels: true static_configs: - targets: - '[::1]:8081' - job_name: 'node' static_configs: - targets: ['[1::4]:9100'] labels: instance: 'test' """).lstrip() _run_cephadm.assert_called_with( 'test', 'prometheus.test', 'deploy', [ '--name', 'prometheus.test', '--meta-json', '{"service_name": "prometheus", "ports": [9095], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null}', '--config-json', '-', '--tcp-ports', '9095' ], stdin=json.dumps({"files": {"prometheus.yml": y}}), image='') @patch("cephadm.serve.CephadmServe._run_cephadm") @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '1::4') @patch("cephadm.services.monitoring.verify_tls", lambda *_: None) def test_grafana_config(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): cephadm_module.set_store('grafana_crt', 'c') cephadm_module.set_store('grafana_key', 'k') with with_service(cephadm_module, MonitoringSpec('prometheus')) as _, \ with_service(cephadm_module, GrafanaSpec('grafana')) as _: files = { 'grafana.ini': dedent(""" # This file is generated by cephadm. [users] default_theme = light [auth.anonymous] enabled = true org_name = 'Main Org.' org_role = 'Viewer' [server] domain = 'bootstrap.storage.lab' protocol = https cert_file = /etc/grafana/certs/cert_file cert_key = /etc/grafana/certs/cert_key http_port = 3000 http_addr = [security] disable_initial_admin_creation = true cookie_secure = true cookie_samesite = none allow_embedding = true""").lstrip(), # noqa: W291 'provisioning/datasources/ceph-dashboard.yml': dedent(""" # This file is generated by cephadm. deleteDatasources: - name: 'Dashboard1' orgId: 1 datasources: - name: 'Dashboard1' type: 'prometheus' access: 'proxy' orgId: 1 url: 'http://[1::4]:9095' basicAuth: false isDefault: true editable: false """).lstrip(), 'certs/cert_file': dedent(""" # generated by cephadm c""").lstrip(), 'certs/cert_key': dedent(""" # generated by cephadm k""").lstrip(), } _run_cephadm.assert_called_with( 'test', 'grafana.test', 'deploy', [ '--name', 'grafana.test', '--meta-json', '{"service_name": "grafana", "ports": [3000], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null}', '--config-json', '-', '--tcp-ports', '3000'], stdin=json.dumps({"files": files}), image='') @patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}')) def test_grafana_initial_admin_pw(self, cephadm_module: CephadmOrchestrator): with with_host(cephadm_module, 'test'): with with_service(cephadm_module, GrafanaSpec(initial_admin_password='******')): out = cephadm_module.cephadm_services['grafana'].generate_config( CephadmDaemonDeploySpec('test', 'daemon', 'grafana')) assert out == ( { 'files': { 'certs/cert_file': ANY, 'certs/cert_key': ANY, 'grafana.ini': '# This file is generated by cephadm.\n' '[users]\n' ' default_theme = light\n' '[auth.anonymous]\n' ' enabled = true\n' " org_name = 'Main Org.'\n" " org_role = 'Viewer'\n" '[server]\n' " domain = 'bootstrap.storage.lab'\n" ' protocol = https\n' ' cert_file = /etc/grafana/certs/cert_file\n' ' cert_key = /etc/grafana/certs/cert_key\n' ' http_port = 3000\n' ' http_addr = \n' '[security]\n' ' admin_user = admin\n' ' admin_password = secure\n' ' cookie_secure = true\n' ' cookie_samesite = none\n' ' allow_embedding = true', 'provisioning/datasources/ceph-dashboard.yml': '# This file is generated by cephadm.\n' 'deleteDatasources:\n' '\n' 'datasources:\n' } }, [], ) @patch("cephadm.serve.CephadmServe._run_cephadm") def test_monitoring_ports(self, _run_cephadm, cephadm_module: CephadmOrchestrator): _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) with with_host(cephadm_module, 'test'): yaml_str = """service_type: alertmanager service_name: alertmanager placement: count: 1 spec: port: 4200 """ yaml_file = yaml.safe_load(yaml_str) spec = ServiceSpec.from_json(yaml_file) with patch("cephadm.services.monitoring.AlertmanagerService.generate_config", return_value=({}, [])): with with_service(cephadm_module, spec): CephadmServe(cephadm_module)._check_daemons() _run_cephadm.assert_called_with( 'test', 'alertmanager.test', 'deploy', [ '--name', 'alertmanager.test', '--meta-json', '{"service_name": "alertmanager", "ports": [4200, 9094], "ip": null, "deployed_by": [], "rank": null, "rank_generation": null}', '--config-json', '-', '--tcp-ports', '4200 9094', '--reconfig' ], stdin='{}', image='')
from datetime import datetime from ceph.deployment.service_spec import PlacementSpec, ServiceSpec, HostPlacementSpec from cephadm import CephadmOrchestrator from cephadm.tests.fixtures import _run_cephadm, cephadm_module, wait, match_glob, with_host from orchestrator import ServiceDescription from tests import mock @mock.patch("cephadm.module.CephadmOrchestrator._run_cephadm", _run_cephadm('[]')) @mock.patch("cephadm.services.cephadmservice.RgwService.create_realm_zonegroup_zone", lambda _,__,___: None) def test_service_ls(cephadm_module: CephadmOrchestrator): with with_host(cephadm_module, 'host1'): with with_host(cephadm_module, 'host2'): # emulate the old scheduler: c = cephadm_module.apply_rgw( ServiceSpec('rgw', 'r.z', placement=PlacementSpec(host_pattern='*', count=2)) ) assert wait(cephadm_module, c) == 'Scheduled rgw.r.z update...' cephadm_module._apply_all_services() out = {o.hostname for o in wait(cephadm_module, cephadm_module.list_daemons())} assert out == {'host1', 'host2'} c = cephadm_module.apply_rgw( ServiceSpec('rgw', 'r.z', placement=PlacementSpec(host_pattern='host1', count=2)) ) assert wait(cephadm_module, c) == 'Scheduled rgw.r.z update...' cephadm_module.migration_current = 0 cephadm_module.migration.migrate()