From 5674f46f0cec041d5a502182066a097b214dd928 Mon Sep 17 00:00:00 2001 From: Kiefer Chang Date: Fri, 15 May 2020 17:20:55 +0800 Subject: [PATCH] mgr/cephadm: config iSCSI gateways in Dashboard - Add `daemon_check_post` fuction to allow services implement actions needed to be done after daemons are checked. - After iSCSI daemons are spawned, call dashboard CLI to set the API URL of the daemons. Fixes: https://tracker.ceph.com/issues/45163 Signed-off-by: Kiefer Chang --- src/pybind/mgr/cephadm/module.py | 22 ++++------ .../mgr/cephadm/services/cephadmservice.py | 8 +++- src/pybind/mgr/cephadm/services/iscsi.py | 40 +++++++++++++++++++ src/pybind/mgr/cephadm/services/monitoring.py | 14 +++++++ 4 files changed, 67 insertions(+), 17 deletions(-) diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index 966d75236a9..0881f4780df 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -1708,6 +1708,7 @@ you may want to run: daemons = self.cache.get_daemons() grafanas = [] # type: List[orchestrator.DaemonDescription] + iscsi_daemons = [] for dd in daemons: # orphan? spec = self.spec_store.specs.get(dd.service_name(), None) @@ -1725,6 +1726,8 @@ you may want to run: if dd.daemon_type == 'grafana': # put running instances at the front of the list grafanas.insert(0, dd) + elif dd.daemon_type == 'iscsi': + iscsi_daemons.append(dd) deps = self._calc_daemon_deps(dd.daemon_type, dd.daemon_id) last_deps, last_config = self.cache.get_daemon_last_config_deps( dd.hostname, dd.name()) @@ -1750,21 +1753,10 @@ you may want to run: self._create_daemon(dd.daemon_type, dd.daemon_id, dd.hostname, reconfig=True) - # make sure the dashboard [does not] references grafana - try: - current_url = self.get_module_option_ex('dashboard', - 'GRAFANA_API_URL') - if grafanas: - host = grafanas[0].hostname - url = f'https://{self.inventory.get_addr(host)}:3000' - if current_url != url: - self.log.info('Setting dashboard grafana config to %s' % url) - self.set_module_option_ex('dashboard', 'GRAFANA_API_URL', - url) - # FIXME: is it a signed cert?? - except Exception as e: - self.log.debug('got exception fetching dashboard grafana state: %s', - e) + if grafanas: + self.grafana_service.daemon_check_post(grafanas) + if iscsi_daemons: + self.iscsi_service.daemon_check_post(iscsi_daemons) def _add_daemon(self, daemon_type, spec, create_func: Callable[..., T], config_func=None) -> List[T]: diff --git a/src/pybind/mgr/cephadm/services/cephadmservice.py b/src/pybind/mgr/cephadm/services/cephadmservice.py index a810026810a..5e331d61980 100644 --- a/src/pybind/mgr/cephadm/services/cephadmservice.py +++ b/src/pybind/mgr/cephadm/services/cephadmservice.py @@ -1,8 +1,8 @@ import logging -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, List from ceph.deployment.service_spec import ServiceSpec, RGWSpec -from orchestrator import OrchestratorError +from orchestrator import OrchestratorError, DaemonDescription from cephadm import utils if TYPE_CHECKING: @@ -18,6 +18,10 @@ class CephadmService: def __init__(self, mgr: "CephadmOrchestrator"): self.mgr: "CephadmOrchestrator" = mgr + def daemon_check_post(self, daemon_descrs: List[DaemonDescription]): + """The post actions needed to be done after daemons are checked""" + raise NotImplementedError() + class MonService(CephadmService): def create(self, name, host, network): diff --git a/src/pybind/mgr/cephadm/services/iscsi.py b/src/pybind/mgr/cephadm/services/iscsi.py index 1739aacfa54..18bf1699f78 100644 --- a/src/pybind/mgr/cephadm/services/iscsi.py +++ b/src/pybind/mgr/cephadm/services/iscsi.py @@ -1,8 +1,11 @@ import json import logging +from typing import List, cast +from mgr_module import MonCommandFailed from ceph.deployment.service_spec import IscsiServiceSpec +from orchestrator import DaemonDescription from .cephadmservice import CephadmService from .. import utils @@ -68,3 +71,40 @@ class IscsiService(CephadmService): extra_config = {'iscsi-gateway.cfg': igw_conf} return self.mgr._create_daemon('iscsi', igw_id, host, keyring=keyring, extra_config=extra_config) + + def daemon_check_post(self, daemon_descrs: List[DaemonDescription]): + try: + _, out, _ = self.mgr.check_mon_command({ + 'prefix': 'dashboard iscsi-gateway-list' + }) + except MonCommandFailed as e: + logger.warning('Failed to get existing iSCSI gateways from the Dashboard: %s', e) + return + + gateways = json.loads(out)['gateways'] + for dd in daemon_descrs: + spec = cast(IscsiServiceSpec, + self.mgr.spec_store.specs.get(dd.service_name(), None)) + if not spec: + logger.warning('No ServiceSpec found for %s', dd) + continue + if not all([spec.api_user, spec.api_password]): + reason = 'api_user or api_password is not specified in ServiceSpec' + logger.warning( + 'Unable to add iSCSI gateway to the Dashboard for %s: %s', dd, reason) + continue + host = self.mgr.inventory.get_addr(dd.hostname) + service_url = 'http://{}:{}@{}:{}'.format( + spec.api_user, spec.api_password, host, spec.api_port or '5000') + gw = gateways.get(dd.hostname) + if not gw or gw['service_url'] != service_url: + try: + logger.info('Adding iSCSI gateway %s to Dashboard', service_url) + _, out, _ = self.mgr.check_mon_command({ + 'prefix': 'dashboard iscsi-gateway-add', + 'service_url': service_url, + 'name': dd.hostname + }) + except MonCommandFailed as e: + logger.warning( + 'Failed to add iSCSI gateway %s to the Dashboard: %s', service_url, e) diff --git a/src/pybind/mgr/cephadm/services/monitoring.py b/src/pybind/mgr/cephadm/services/monitoring.py index e3ca8a804f6..89c025e02b4 100644 --- a/src/pybind/mgr/cephadm/services/monitoring.py +++ b/src/pybind/mgr/cephadm/services/monitoring.py @@ -2,6 +2,7 @@ import logging import os from typing import List, Any, Tuple, Dict +from orchestrator import DaemonDescription from cephadm.services.cephadmservice import CephadmService from mgr_util import verify_tls, ServerConfigException, create_self_signed_cert @@ -104,6 +105,19 @@ datasources: } return config_file, sorted(deps) + def daemon_check_post(self, daemon_descrs: List[DaemonDescription]): + # make sure the dashboard [does not] references grafana + try: + current_url = self.mgr.get_module_option_ex('dashboard', 'GRAFANA_API_URL') + host = daemon_descrs[0].hostname + url = f'https://{self.mgr.inventory.get_addr(host)}:3000' + if current_url != url: + logger.info('Setting dashboard grafana config to %s' % url) + self.mgr.set_module_option_ex('dashboard', 'GRAFANA_API_URL', url) + # FIXME: is it a signed cert?? + except Exception as e: + logger.debug('got exception fetching dashboard grafana state: %s', e) + class AlertmanagerService(CephadmService): def create(self, daemon_id, host) -> str: -- 2.39.5