From: Adam King Date: Fri, 3 Mar 2023 20:31:03 +0000 (-0500) Subject: mgr/prometheus: remove dependency on cephadm module X-Git-Tag: v19.0.0~1603^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=8be588958bd2694b8a427bdfc10011ba62df8453;p=ceph-ci.git mgr/prometheus: remove dependency on cephadm module https://github.com/ceph/ceph/commit/f967ac061ebee362cdc82c458e955da75a9045e9 introduced an import of something in the cephadm module in the prometheus module. This seems to break the prometheus module in some non-cephadm setups. For example, the ceph-ansible ci hit failed: [mgr0 -> mon0] (item=prometheus) => changed=true ansible_loop_var: item cmd: - ceph - -n - client.admin - -k - /etc/ceph/ceph.client.admin.keyring - --cluster - ceph - mgr - module - enable - prometheus delta: '0:00:00.389965' end: '2023-03-03 15:30:07.631308' item: prometheus rc: 2 start: '2023-03-03 15:30:07.241343' stderr: 'Error ENOENT: module ''prometheus'' reports that it cannot run on the active manager daemon: No module named ''cephadm'' (pass --force to force enablement)' stderr_lines: stdout: '' stdout_lines: so we need to be a bit more careful with this import and make sure the prometheus module works fine without cephadm Signed-off-by: Adam King --- diff --git a/src/pybind/mgr/prometheus/module.py b/src/pybind/mgr/prometheus/module.py index b34b865e320..2689e69f1a9 100644 --- a/src/pybind/mgr/prometheus/module.py +++ b/src/pybind/mgr/prometheus/module.py @@ -14,7 +14,6 @@ from collections import namedtuple from mgr_module import CLIReadCommand, MgrModule, MgrStandbyModule, PG_STATES, Option, ServiceInfoT, HandleCommandResult, CLIWriteCommand from mgr_util import get_default_addr, profile_method, build_url from rbd import RBD -from cephadm.ssl_cert_utils import SSLCerts from typing import DefaultDict, Optional, Dict, Any, Set, cast, Tuple, Union, List, Callable @@ -637,7 +636,6 @@ class Module(MgrModule): _global_instance = self self.metrics_thread = MetricCollectionThread(_global_instance) self.health_history = HealthHistory(self) - self.ssl_certs = SSLCerts() def _setup_static_metrics(self) -> Dict[str, Metric]: metrics = {} @@ -1726,49 +1724,68 @@ class Module(MgrModule): self.get_file_sd_config() def configure(self, server_addr: str, server_port: int) -> None: - secure_monitoring_stack = self.get_module_option_ex( + # cephadm deployments have a TLS monitoring stack setup option. + # If the cephadm module is on and the setting is true (defaults to false) + # we should have prometheus be set up to interact with that + cephadm_secure_monitoring_stack = self.get_module_option_ex( 'cephadm', 'secure_monitoring_stack', False) - if secure_monitoring_stack: - self.generate_tls_certificates(self.get_mgr_ip()) - cherrypy.config.update({ - 'server.socket_host': server_addr, - 'server.socket_port': server_port, - 'engine.autoreload.on': False, - 'server.ssl_module': 'builtin', - 'server.ssl_certificate': self.cert_file, - 'server.ssl_private_key': self.key_file, - }) - # Publish the URI that others may use to access the service we're about to start serving - self.set_uri(build_url(scheme='https', host=self.get_server_addr(), - port=server_port, path='/')) - else: - cherrypy.config.update({ - 'server.socket_host': server_addr, - 'server.socket_port': server_port, - 'engine.autoreload.on': False, - 'server.ssl_module': None, - 'server.ssl_certificate': None, - 'server.ssl_private_key': None, - }) - # Publish the URI that others may use to access the service we're about to start serving - self.set_uri(build_url(scheme='http', host=self.get_server_addr(), - port=server_port, path='/')) - - def generate_tls_certificates(self, host: str) -> None: + if cephadm_secure_monitoring_stack: + try: + self.setup_cephadm_tls_config(server_addr, server_port) + return + except Exception as e: + self.log.exception(f'Failed to setup cephadm based secure monitoring stack: {e}\n', + 'Falling back to default configuration') + self.setup_default_config(server_addr, server_port) + + def setup_default_config(self, server_addr: str, server_port: int) -> None: + cherrypy.config.update({ + 'server.socket_host': server_addr, + 'server.socket_port': server_port, + 'engine.autoreload.on': False, + 'server.ssl_module': None, + 'server.ssl_certificate': None, + 'server.ssl_private_key': None, + }) + # Publish the URI that others may use to access the service we're about to start serving + self.set_uri(build_url(scheme='http', host=self.get_server_addr(), + port=server_port, path='/')) + + def setup_cephadm_tls_config(self, server_addr: str, server_port: int) -> None: + from cephadm.ssl_cert_utils import SSLCerts + # the ssl certs utils uses a NamedTemporaryFile for the cert files + # generated with generate_cert_files function. We need the SSLCerts + # object to not be cleaned up in order to have those temp files not + # be cleaned up, so making it an attribute of the module instead + # of just a standalone object + self.cephadm_monitoring_tls_ssl_certs = SSLCerts() + host = self.get_mgr_ip() try: old_cert = self.get_store('root/cert') old_key = self.get_store('root/key') if not old_cert or not old_key: raise Exception('No old credentials for mgr-prometheus endpoint') - self.ssl_certs.load_root_credentials(old_cert, old_key) + self.cephadm_monitoring_tls_ssl_certs.load_root_credentials(old_cert, old_key) except Exception: - self.ssl_certs.generate_root_cert(host) - self.set_store('root/cert', self.ssl_certs.get_root_cert()) - self.set_store('root/key', self.ssl_certs.get_root_key()) + self.cephadm_monitoring_tls_ssl_certs.generate_root_cert(host) + self.set_store('root/cert', self.cephadm_monitoring_tls_ssl_certs.get_root_cert()) + self.set_store('root/key', self.cephadm_monitoring_tls_ssl_certs.get_root_key()) - self.cert_file, self.key_file = self.ssl_certs.generate_cert_files( + cert_file_path, key_file_path = self.cephadm_monitoring_tls_ssl_certs.generate_cert_files( self.get_hostname(), host) + cherrypy.config.update({ + 'server.socket_host': server_addr, + 'server.socket_port': server_port, + 'engine.autoreload.on': False, + 'server.ssl_module': 'builtin', + 'server.ssl_certificate': cert_file_path, + 'server.ssl_private_key': key_file_path, + }) + # Publish the URI that others may use to access the service we're about to start serving + self.set_uri(build_url(scheme='https', host=self.get_server_addr(), + port=server_port, path='/')) + def serve(self) -> None: class Root(object):