diff options
Diffstat (limited to 'src/cephadm')
-rwxr-xr-x | src/cephadm/cephadm.py | 42 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/container_types.py | 16 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/daemons/ingress.py | 9 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/daemons/mgmt_gateway.py | 6 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/daemons/monitoring.py | 49 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/daemons/nvmeof.py | 7 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/daemons/oauth2_proxy.py | 6 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/daemons/smb.py | 4 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/daemons/snmp.py | 4 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/daemons/tracing.py | 15 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/file_utils.py | 24 | ||||
-rw-r--r-- | src/cephadm/cephadmlib/net_utils.py | 14 | ||||
-rw-r--r-- | src/cephadm/tests/test_deploy.py | 2 |
13 files changed, 129 insertions, 69 deletions
diff --git a/src/cephadm/cephadm.py b/src/cephadm/cephadm.py index d2ddf564116..a8616980e4d 100755 --- a/src/cephadm/cephadm.py +++ b/src/cephadm/cephadm.py @@ -111,6 +111,7 @@ from cephadmlib.file_utils import ( unlink_file, write_new, write_tmp, + update_meta_file, ) from cephadmlib.net_utils import ( build_addrv_params, @@ -3453,6 +3454,7 @@ def list_daemons( detail: bool = True, legacy_dir: Optional[str] = None, daemon_name: Optional[str] = None, + type_of_daemon: Optional[str] = None, ) -> List[Dict[str, str]]: host_version: Optional[str] = None ls = [] @@ -3489,6 +3491,8 @@ def list_daemons( if os.path.exists(data_dir): for i in os.listdir(data_dir): if i in ['mon', 'osd', 'mds', 'mgr', 'rgw']: + if type_of_daemon and type_of_daemon != i: + continue daemon_type = i for j in os.listdir(os.path.join(data_dir, i)): if '-' not in j: @@ -3525,6 +3529,8 @@ def list_daemons( if daemon_name and name != daemon_name: continue (daemon_type, daemon_id) = j.split('.', 1) + if type_of_daemon and type_of_daemon != daemon_type: + continue unit_name = get_unit_name(fsid, daemon_type, daemon_id) @@ -4705,6 +4711,34 @@ def command_list_images(ctx: CephadmContext) -> None: # print default images cp_obj.write(sys.stdout) + +def update_service_for_daemon(ctx: CephadmContext, + available_daemons: list, + update_daemons: list) -> None: + """ Update the unit.meta file of daemon with required service name for valid daemons""" + + data = {'service_name': ctx.service_name} + # check if all the daemon names are valid + if not set(update_daemons).issubset(set(available_daemons)): + raise Error(f'Error EINVAL: one or more daemons of {update_daemons} does not exist on this host') + for name in update_daemons: + path = os.path.join(ctx.data_dir, ctx.fsid, name, 'unit.meta') + update_meta_file(path, data) + print(f'Successfully updated daemon {name} with service {ctx.service_name}') + + +@infer_fsid +def command_update_osd_service(ctx: CephadmContext) -> int: + """update service for provided daemon""" + update_daemons = [f'osd.{osd_id}' for osd_id in ctx.osd_ids.split(',')] + daemons = list_daemons(ctx, detail=False, type_of_daemon='osd') + if not daemons: + raise Error(f'Daemon {ctx.osd_ids} does not exists on this host') + available_daemons = [d['name'] for d in daemons] + update_service_for_daemon(ctx, available_daemons, update_daemons) + return 0 + + ################################## @@ -5571,6 +5605,14 @@ def _get_parser(): parser_list_images = subparsers.add_parser( 'list-images', help='list all the default images') parser_list_images.set_defaults(func=command_list_images) + + parser_update_service = subparsers.add_parser( + 'update-osd-service', help='update service for provided daemon') + parser_update_service.set_defaults(func=command_update_osd_service) + parser_update_service.add_argument('--fsid', help='cluster FSID') + parser_update_service.add_argument('--osd-ids', required=True, help='Comma-separated OSD IDs') + parser_update_service.add_argument('--service-name', required=True, help='OSD service name') + return parser diff --git a/src/cephadm/cephadmlib/container_types.py b/src/cephadm/cephadmlib/container_types.py index f1e829cbdf7..52a68888e78 100644 --- a/src/cephadm/cephadmlib/container_types.py +++ b/src/cephadm/cephadmlib/container_types.py @@ -9,7 +9,7 @@ from typing import Dict, List, Optional, Any, Union, Tuple, Iterable, cast from .call_wrappers import call, call_throws, CallVerbosity from .constants import DEFAULT_TIMEOUT -import ceph.cephadm.images as default_images +from ceph.cephadm.images import DefaultImages from .container_engines import Docker, Podman from .context import CephadmContext from .daemon_identity import DaemonIdentity, DaemonSubIdentity @@ -665,14 +665,8 @@ def enable_shared_namespaces( def get_mgr_images() -> dict: """Return dict of default mgr images""" - mgr_prefix = 'mgr/cephadm/container_image_' - mgr_images = {} - images = vars(default_images) - for key, value in images.items(): - if key.startswith('DEFAULT_') and key.endswith('_IMAGE'): - # flake8 and black disagree about spaces around ":" hence the noqa comment - suffix = key[ - len('DEFAULT_') : -len('_IMAGE') # noqa: E203 - ].lower() - mgr_images[mgr_prefix + suffix] = value + mgr_prefix = 'mgr/cephadm/' + mgr_images = { + f'{mgr_prefix}{image.key}': image.image_ref for image in DefaultImages + } return mgr_images diff --git a/src/cephadm/cephadmlib/daemons/ingress.py b/src/cephadm/cephadmlib/daemons/ingress.py index c88e39ac025..645654b59c8 100644 --- a/src/cephadm/cephadmlib/daemons/ingress.py +++ b/src/cephadm/cephadmlib/daemons/ingress.py @@ -2,10 +2,7 @@ import os from typing import Dict, List, Optional, Tuple, Union -from ceph.cephadm.images import ( - DEFAULT_HAPROXY_IMAGE, - DEFAULT_KEEPALIVED_IMAGE, -) +from ceph.cephadm.images import DefaultImages from ..constants import ( DATA_DIR_MODE, ) @@ -27,7 +24,7 @@ class HAproxy(ContainerDaemonForm): daemon_type = 'haproxy' required_files = ['haproxy.cfg'] - default_image = DEFAULT_HAPROXY_IMAGE + default_image = DefaultImages.HAPROXY.image_ref @classmethod def for_daemon_type(cls, daemon_type: str) -> bool: @@ -155,7 +152,7 @@ class Keepalived(ContainerDaemonForm): daemon_type = 'keepalived' required_files = ['keepalived.conf'] - default_image = DEFAULT_KEEPALIVED_IMAGE + default_image = DefaultImages.KEEPALIVED.image_ref @classmethod def for_daemon_type(cls, daemon_type: str) -> bool: diff --git a/src/cephadm/cephadmlib/daemons/mgmt_gateway.py b/src/cephadm/cephadmlib/daemons/mgmt_gateway.py index 85f72495909..2be18809aa3 100644 --- a/src/cephadm/cephadmlib/daemons/mgmt_gateway.py +++ b/src/cephadm/cephadmlib/daemons/mgmt_gateway.py @@ -11,7 +11,7 @@ from ..context_getters import fetch_configs from ..daemon_form import register as register_daemon_form from ..daemon_identity import DaemonIdentity from ..deployment_utils import to_deployment_container -from ceph.cephadm.images import DEFAULT_NGINX_IMAGE +from ceph.cephadm.images import DefaultImages from ..data_utils import dict_get, is_fsid from ..file_utils import populate_files, makedirs, recursive_chown from ..exceptions import Error @@ -32,7 +32,7 @@ class MgmtGateway(ContainerDaemonForm): 'nginx_internal.key', ] - default_image = DEFAULT_NGINX_IMAGE + default_image = DefaultImages.NGINX.image_ref @classmethod def for_daemon_type(cls, daemon_type: str) -> bool: @@ -44,7 +44,7 @@ class MgmtGateway(ContainerDaemonForm): fsid: str, daemon_id: str, config_json: Dict, - image: str = DEFAULT_NGINX_IMAGE, + image: str = DefaultImages.NGINX.image_ref, ): self.ctx = ctx self.fsid = fsid diff --git a/src/cephadm/cephadmlib/daemons/monitoring.py b/src/cephadm/cephadmlib/daemons/monitoring.py index 710093f0f46..4ba00daaefb 100644 --- a/src/cephadm/cephadmlib/daemons/monitoring.py +++ b/src/cephadm/cephadmlib/daemons/monitoring.py @@ -3,14 +3,7 @@ import os from typing import Dict, List, Tuple from ..call_wrappers import call, CallVerbosity -from ceph.cephadm.images import ( - DEFAULT_ALERTMANAGER_IMAGE, - DEFAULT_GRAFANA_IMAGE, - DEFAULT_LOKI_IMAGE, - DEFAULT_NODE_EXPORTER_IMAGE, - DEFAULT_PROMETHEUS_IMAGE, - DEFAULT_PROMTAIL_IMAGE, -) +from ceph.cephadm.images import DefaultImages from ..constants import ( UID_NOBODY, GID_NOGROUP, @@ -23,7 +16,13 @@ from ..daemon_form import register as register_daemon_form from ..daemon_identity import DaemonIdentity from ..deployment_utils import to_deployment_container from ..exceptions import Error -from ..net_utils import get_fqdn, get_hostname, get_ip_addresses, wrap_ipv6 +from ..net_utils import ( + get_fqdn, + get_hostname, + get_ip_addresses, + wrap_ipv6, + EndPoint, +) @register_daemon_form @@ -43,7 +42,7 @@ class Monitoring(ContainerDaemonForm): components = { 'prometheus': { - 'image': DEFAULT_PROMETHEUS_IMAGE, + 'image': DefaultImages.PROMETHEUS.image_ref, 'cpus': '2', 'memory': '4GB', 'args': [ @@ -55,7 +54,7 @@ class Monitoring(ContainerDaemonForm): ], }, 'loki': { - 'image': DEFAULT_LOKI_IMAGE, + 'image': DefaultImages.LOKI.image_ref, 'cpus': '1', 'memory': '1GB', 'args': [ @@ -64,7 +63,7 @@ class Monitoring(ContainerDaemonForm): 'config-json-files': ['loki.yml'], }, 'promtail': { - 'image': DEFAULT_PROMTAIL_IMAGE, + 'image': DefaultImages.PROMTAIL.image_ref, 'cpus': '1', 'memory': '1GB', 'args': [ @@ -75,13 +74,13 @@ class Monitoring(ContainerDaemonForm): ], }, 'node-exporter': { - 'image': DEFAULT_NODE_EXPORTER_IMAGE, + 'image': DefaultImages.NODE_EXPORTER.image_ref, 'cpus': '1', 'memory': '1GB', 'args': ['--no-collector.timex'], }, 'grafana': { - 'image': DEFAULT_GRAFANA_IMAGE, + 'image': DefaultImages.GRAFANA.image_ref, 'cpus': '2', 'memory': '4GB', 'args': [], @@ -93,14 +92,9 @@ class Monitoring(ContainerDaemonForm): ], }, 'alertmanager': { - 'image': DEFAULT_ALERTMANAGER_IMAGE, + 'image': DefaultImages.ALERTMANAGER.image_ref, 'cpus': '2', 'memory': '2GB', - 'args': [ - '--cluster.listen-address=:{}'.format( - port_map['alertmanager'][1] - ), - ], 'config-json-files': [ 'alertmanager.yml', ], @@ -255,11 +249,14 @@ class Monitoring(ContainerDaemonForm): ip = meta['ip'] if 'ports' in meta and meta['ports']: port = meta['ports'][0] - if daemon_type == 'prometheus': - config = fetch_configs(ctx) + config = fetch_configs(ctx) + if daemon_type in ['prometheus', 'alertmanager']: ip_to_bind_to = config.get('ip_to_bind_to', '') if ip_to_bind_to: ip = ip_to_bind_to + web_listen_addr = str(EndPoint(ip, port)) + r += [f'--web.listen-address={web_listen_addr}'] + if daemon_type == 'prometheus': retention_time = config.get('retention_time', '15d') retention_size = config.get( 'retention_size', '0' @@ -283,9 +280,11 @@ class Monitoring(ContainerDaemonForm): r += ['--web.route-prefix=/prometheus/'] else: r += [f'--web.external-url={scheme}://{host}:{port}'] - r += [f'--web.listen-address={ip}:{port}'] if daemon_type == 'alertmanager': - config = fetch_configs(ctx) + clus_listen_addr = str( + EndPoint(ip, self.port_map[daemon_type][1]) + ) + r += [f'--cluster.listen-address={clus_listen_addr}'] use_url_prefix = config.get('use_url_prefix', False) peers = config.get('peers', list()) # type: ignore for peer in peers: @@ -301,13 +300,11 @@ class Monitoring(ContainerDaemonForm): if daemon_type == 'promtail': r += ['--config.expand-env'] if daemon_type == 'prometheus': - config = fetch_configs(ctx) try: r += [f'--web.config.file={config["web_config"]}'] except KeyError: pass if daemon_type == 'node-exporter': - config = fetch_configs(ctx) try: r += [f'--web.config.file={config["web_config"]}'] except KeyError: diff --git a/src/cephadm/cephadmlib/daemons/nvmeof.py b/src/cephadm/cephadmlib/daemons/nvmeof.py index d916c7e6391..51b085df2a7 100644 --- a/src/cephadm/cephadmlib/daemons/nvmeof.py +++ b/src/cephadm/cephadmlib/daemons/nvmeof.py @@ -8,7 +8,7 @@ from ..container_types import CephContainer from ..context_getters import fetch_configs, get_config_and_keyring from ..daemon_form import register as register_daemon_form from ..daemon_identity import DaemonIdentity -from ceph.cephadm.images import DEFAULT_NVMEOF_IMAGE +from ceph.cephadm.images import DefaultImages from ..context import CephadmContext from ..data_utils import dict_get, is_fsid from ..deployment_utils import to_deployment_container @@ -26,7 +26,7 @@ class CephNvmeof(ContainerDaemonForm): daemon_type = 'nvmeof' required_files = ['ceph-nvmeof.conf'] - default_image = DEFAULT_NVMEOF_IMAGE + default_image = DefaultImages.NVMEOF.image_ref @classmethod def for_daemon_type(cls, daemon_type: str) -> bool: @@ -38,7 +38,7 @@ class CephNvmeof(ContainerDaemonForm): fsid: str, daemon_id: Union[int, str], config_json: Dict, - image: str = DEFAULT_NVMEOF_IMAGE, + image: str = DefaultImages.NVMEOF.image_ref, ) -> None: self.ctx = ctx self.fsid = fsid @@ -100,6 +100,7 @@ class CephNvmeof(ContainerDaemonForm): 'client_cert', 'client_key', 'root_ca_cert', + 'encryption_key', ]: if fn in files: mounts[ diff --git a/src/cephadm/cephadmlib/daemons/oauth2_proxy.py b/src/cephadm/cephadmlib/daemons/oauth2_proxy.py index 14202111c14..c4f4ec5562f 100644 --- a/src/cephadm/cephadmlib/daemons/oauth2_proxy.py +++ b/src/cephadm/cephadmlib/daemons/oauth2_proxy.py @@ -11,7 +11,7 @@ from ..context_getters import fetch_configs from ..daemon_form import register as register_daemon_form from ..daemon_identity import DaemonIdentity from ..deployment_utils import to_deployment_container -from ceph.cephadm.images import DEFAULT_OAUTH2_PROXY_IMAGE +from ceph.cephadm.images import DefaultImages from ..constants import UID_NOBODY, GID_NOGROUP from ..data_utils import dict_get, is_fsid from ..file_utils import populate_files, makedirs, recursive_chown @@ -25,7 +25,7 @@ logger = logging.getLogger() class OAuth2Proxy(ContainerDaemonForm): """Define the configs for the jaeger tracing containers""" - default_image = DEFAULT_OAUTH2_PROXY_IMAGE + default_image = DefaultImages.OAUTH2_PROXY.image_ref daemon_type = 'oauth2-proxy' required_files = [ 'oauth2-proxy.conf', @@ -43,7 +43,7 @@ class OAuth2Proxy(ContainerDaemonForm): fsid: str, daemon_id: str, config_json: Dict, - image: str = DEFAULT_OAUTH2_PROXY_IMAGE, + image: str = DefaultImages.OAUTH2_PROXY.image_ref, ): self.ctx = ctx self.fsid = fsid diff --git a/src/cephadm/cephadmlib/daemons/smb.py b/src/cephadm/cephadmlib/daemons/smb.py index 33d43cbe6ce..0efde198812 100644 --- a/src/cephadm/cephadmlib/daemons/smb.py +++ b/src/cephadm/cephadmlib/daemons/smb.py @@ -14,7 +14,7 @@ from .. import data_utils from .. import deployment_utils from .. import file_utils from ..call_wrappers import call, CallVerbosity -from ceph.cephadm.images import DEFAULT_SAMBA_IMAGE +from ceph.cephadm.images import DefaultImages from ..container_daemon_form import ContainerDaemonForm, daemon_to_container from ..container_engines import Podman from ..container_types import ( @@ -368,7 +368,7 @@ class SMB(ContainerDaemonForm): daemon_type = 'smb' daemon_base = '/usr/sbin/smbd' - default_image = DEFAULT_SAMBA_IMAGE + default_image = DefaultImages.SAMBA.image_ref @classmethod def for_daemon_type(cls, daemon_type: str) -> bool: diff --git a/src/cephadm/cephadmlib/daemons/snmp.py b/src/cephadm/cephadmlib/daemons/snmp.py index ab84a302f2c..0557a2ef972 100644 --- a/src/cephadm/cephadmlib/daemons/snmp.py +++ b/src/cephadm/cephadmlib/daemons/snmp.py @@ -5,7 +5,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union from urllib.error import HTTPError, URLError from urllib.request import urlopen -from ceph.cephadm.images import DEFAULT_SNMP_GATEWAY_IMAGE +from ceph.cephadm.images import DefaultImages from ..container_daemon_form import ContainerDaemonForm, daemon_to_container from ..container_types import CephContainer from ..context import CephadmContext @@ -24,7 +24,7 @@ class SNMPGateway(ContainerDaemonForm): daemon_type = 'snmp-gateway' SUPPORTED_VERSIONS = ['V2c', 'V3'] - default_image = DEFAULT_SNMP_GATEWAY_IMAGE + default_image = DefaultImages.SNMP_GATEWAY.image_ref DEFAULT_PORT = 9464 env_filename = 'snmp-gateway.conf' diff --git a/src/cephadm/cephadmlib/daemons/tracing.py b/src/cephadm/cephadmlib/daemons/tracing.py index 4cf74339455..44548a61d14 100644 --- a/src/cephadm/cephadmlib/daemons/tracing.py +++ b/src/cephadm/cephadmlib/daemons/tracing.py @@ -2,12 +2,7 @@ import logging from typing import Any, Dict, List, Tuple -from ceph.cephadm.images import ( - DEFAULT_ELASTICSEARCH_IMAGE, - DEFAULT_JAEGER_AGENT_IMAGE, - DEFAULT_JAEGER_COLLECTOR_IMAGE, - DEFAULT_JAEGER_QUERY_IMAGE, -) +from ceph.cephadm.images import DefaultImages from ..container_daemon_form import ContainerDaemonForm, daemon_to_container from ..container_types import CephContainer from ..context import CephadmContext @@ -27,17 +22,17 @@ class Tracing(ContainerDaemonForm): components: Dict[str, Dict[str, Any]] = { 'elasticsearch': { - 'image': DEFAULT_ELASTICSEARCH_IMAGE, + 'image': DefaultImages.ELASTICSEARCH.image_ref, 'envs': ['discovery.type=single-node'], }, 'jaeger-agent': { - 'image': DEFAULT_JAEGER_AGENT_IMAGE, + 'image': DefaultImages.JAEGER_AGENT.image_ref, }, 'jaeger-collector': { - 'image': DEFAULT_JAEGER_COLLECTOR_IMAGE, + 'image': DefaultImages.JAEGER_COLLECTOR.image_ref, }, 'jaeger-query': { - 'image': DEFAULT_JAEGER_QUERY_IMAGE, + 'image': DefaultImages.JAEGER_QUERY.image_ref, }, } # type: ignore diff --git a/src/cephadm/cephadmlib/file_utils.py b/src/cephadm/cephadmlib/file_utils.py index 27e70e31756..4dd88cc3671 100644 --- a/src/cephadm/cephadmlib/file_utils.py +++ b/src/cephadm/cephadmlib/file_utils.py @@ -5,6 +5,7 @@ import datetime import logging import os import tempfile +import json from contextlib import contextmanager from pathlib import Path @@ -157,3 +158,26 @@ def unlink_file( except Exception: if not ignore_errors: raise + + +def update_meta_file(file_path: str, update_key_val: dict) -> None: + """Update key in the file with provided value""" + try: + with open(file_path, 'r') as fh: + data = json.load(fh) + file_stat = os.stat(file_path) + except FileNotFoundError: + raise + except Exception: + logger.exception(f'Failed to update {file_path}') + raise + data.update( + {key: value for key, value in update_key_val.items() if key in data} + ) + + with write_new( + file_path, + owner=(file_stat.st_uid, file_stat.st_gid), + perms=(file_stat.st_mode & 0o777), + ) as fh: + fh.write(json.dumps(data, indent=4) + '\n') diff --git a/src/cephadm/cephadmlib/net_utils.py b/src/cephadm/cephadmlib/net_utils.py index 9a7f138b1c6..bfa61d933ef 100644 --- a/src/cephadm/cephadmlib/net_utils.py +++ b/src/cephadm/cephadmlib/net_utils.py @@ -24,12 +24,22 @@ class EndPoint: def __init__(self, ip: str, port: int) -> None: self.ip = ip self.port = port + self.is_ipv4 = True + try: + if ip and ipaddress.ip_network(ip).version == 6: + self.is_ipv4 = False + except Exception: + logger.exception('Failed to check ip address version') def __str__(self) -> str: - return f'{self.ip}:{self.port}' + if self.is_ipv4: + return f'{self.ip}:{self.port}' + return f'[{self.ip}]:{self.port}' def __repr__(self) -> str: - return f'{self.ip}:{self.port}' + if self.is_ipv4: + return f'{self.ip}:{self.port}' + return f'[{self.ip}]:{self.port}' def attempt_bind(ctx, s, address, port): diff --git a/src/cephadm/tests/test_deploy.py b/src/cephadm/tests/test_deploy.py index c5094db335f..1736639ed55 100644 --- a/src/cephadm/tests/test_deploy.py +++ b/src/cephadm/tests/test_deploy.py @@ -316,7 +316,7 @@ def test_deploy_a_monitoring_container(cephadm_fs, funkypatch): runfile_lines = f.read().splitlines() assert 'podman' in runfile_lines[-1] assert runfile_lines[-1].endswith( - 'quay.io/titans/prometheus:latest --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus --storage.tsdb.retention.time=15d --storage.tsdb.retention.size=0 --web.external-url=http://10.10.10.10:9095 --web.listen-address=1.2.3.4:9095' + 'quay.io/titans/prometheus:latest --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus --web.listen-address=1.2.3.4:9095 --storage.tsdb.retention.time=15d --storage.tsdb.retention.size=0 --web.external-url=http://10.10.10.10:9095' ) assert '--user 8765' in runfile_lines[-1] assert f'-v /var/lib/ceph/{fsid}/prometheus.fire/etc/prometheus:/etc/prometheus:Z' in runfile_lines[-1] |