::
- DEFAULT_NGINX_IMAGE = 'quay.io/ceph/nginx:1.26.1'
+ mgr/cephadm/container_image_nginx = 'quay.io/ceph/nginx:sclorg-nginx-126'
Admins can specify the image to be used by changing the `container_image_nginx` cephadm module option. If there were already
running daemon(s) you must redeploy the daemon(s) in order to have them actually use the new image.
``var/lib/ceph/{FSID}/cephadm.{DIGEST}``, where ``{DIGEST}`` is an alphanumeric
string representing the currently-running version of Ceph.
-To see the default container images, run a command of the following form:
+To see the default container images, run below command:
.. prompt:: bash #
- grep -E "DEFAULT*IMAGE" /var/lib/ceph/{FSID}/cephadm.{DIGEST}
+ cephadm list-images
-::
-
- DEFAULT_PROMETHEUS_IMAGE = 'quay.io/prometheus/prometheus:v2.51.0'
- DEFAULT_LOKI_IMAGE = 'docker.io/grafana/loki:2.9.5'
- DEFAULT_PROMTAIL_IMAGE = 'docker.io/grafana/promtail:2.9.5'
- DEFAULT_NODE_EXPORTER_IMAGE = 'quay.io/prometheus/node-exporter:v1.7.0'
- DEFAULT_ALERT_MANAGER_IMAGE = 'quay.io/prometheus/alertmanager:v0.27.0'
- DEFAULT_GRAFANA_IMAGE = 'quay.io/ceph/grafana:10.4.0'
Default monitoring images are specified in
-``/src/cephadm/cephadmlib/constants.py`` and in
-``/src/pybind/mgr/cephadm/module.py``.
+``/src/python-common/ceph/cephadm/images.py``.
+
+
+.. autoclass:: ceph.cephadm.images.DefaultImages
+ :members:
+ :undoc-members:
+ :exclude-members: desc, image_ref, key
+
Using custom images
~~~~~~~~~~~~~~~~~~~
| [--log-dir LOG_DIR] [--logrotate-dir LOGROTATE_DIR]
| [--unit-dir UNIT_DIR] [--verbose] [--timeout TIMEOUT]
| [--retry RETRY] [--no-container-init]
-| {version,pull,inspect-image,ls,list-networks,adopt,rm-daemon,rm-cluster,run,shell,enter,ceph-volume,unit,logs,bootstrap,deploy,check-host,prepare-host,add-repo,rm-repo,install}
+| {version,pull,inspect-image,ls,list-networks,adopt,rm-daemon,rm-cluster,run,shell,enter,ceph-volume,unit,logs,bootstrap,deploy,check-host,prepare-host,add-repo,rm-repo,install,list-images}
| ...
| [--registry-password REGISTRY_PASSWORD]
| [--registry-json REGISTRY_JSON] [--fsid FSID]
+| **cephadm** **list-images**
+
Description
* [--name NAME, -n NAME] daemon name (type.id)
+list-images
+-----------
+
+List the default container images for all services in ini format. The output can be modified with custom images and passed to --config flag during bootstrap.
+
+
Availability
============
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
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
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,
)
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:
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:
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
'nginx_internal.key',
]
- default_image = DEFAULT_NGINX_IMAGE
+ default_image = DefaultImages.NGINX.image_ref
@classmethod
def for_daemon_type(cls, daemon_type: str) -> bool:
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
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,
components = {
'prometheus': {
- 'image': DEFAULT_PROMETHEUS_IMAGE,
+ 'image': DefaultImages.PROMETHEUS.image_ref,
'cpus': '2',
'memory': '4GB',
'args': [
],
},
'loki': {
- 'image': DEFAULT_LOKI_IMAGE,
+ 'image': DefaultImages.LOKI.image_ref,
'cpus': '1',
'memory': '1GB',
'args': [
'config-json-files': ['loki.yml'],
},
'promtail': {
- 'image': DEFAULT_PROMTAIL_IMAGE,
+ 'image': DefaultImages.PROMTAIL.image_ref,
'cpus': '1',
'memory': '1GB',
'args': [
],
},
'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': [],
],
},
'alertmanager': {
- 'image': DEFAULT_ALERTMANAGER_IMAGE,
+ 'image': DefaultImages.ALERTMANAGER.image_ref,
'cpus': '2',
'memory': '2GB',
'args': [
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
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:
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
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
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',
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
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 (
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:
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
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'
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
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
import subprocess
from prettytable import PrettyTable
-import ceph.cephadm.images as default_images
+from ceph.cephadm.images import DefaultImages
from ceph.deployment import inventory
from ceph.deployment.drive_group import DriveGroupSpec
from ceph.deployment.service_spec import \
desc='Container image name, without the tag',
runtime=True,
),
- Option(
- 'container_image_prometheus',
- default=default_images.DEFAULT_PROMETHEUS_IMAGE,
- desc='Prometheus container image',
- ),
- Option(
- 'container_image_nvmeof',
- default=default_images.DEFAULT_NVMEOF_IMAGE,
- desc='Nvme-of container image',
- ),
- Option(
- 'container_image_grafana',
- default=default_images.DEFAULT_GRAFANA_IMAGE,
- desc='Prometheus container image',
- ),
- Option(
- 'container_image_alertmanager',
- default=default_images.DEFAULT_ALERTMANAGER_IMAGE,
- desc='Prometheus container image',
- ),
- Option(
- 'container_image_node_exporter',
- default=default_images.DEFAULT_NODE_EXPORTER_IMAGE,
- desc='Prometheus container image',
- ),
- Option(
- 'container_image_loki',
- default=default_images.DEFAULT_LOKI_IMAGE,
- desc='Loki container image',
- ),
- Option(
- 'container_image_promtail',
- default=default_images.DEFAULT_PROMTAIL_IMAGE,
- desc='Promtail container image',
- ),
- Option(
- 'container_image_haproxy',
- default=default_images.DEFAULT_HAPROXY_IMAGE,
- desc='HAproxy container image',
- ),
- Option(
- 'container_image_keepalived',
- default=default_images.DEFAULT_KEEPALIVED_IMAGE,
- desc='Keepalived container image',
- ),
- Option(
- 'container_image_snmp_gateway',
- default=default_images.DEFAULT_SNMP_GATEWAY_IMAGE,
- desc='SNMP Gateway container image',
- ),
- Option(
- 'container_image_nginx',
- default=default_images.DEFAULT_NGINX_IMAGE,
- desc='Nginx container image',
- ),
- Option(
- 'container_image_oauth2_proxy',
- default=default_images.DEFAULT_OAUTH2_PROXY_IMAGE,
- desc='oauth2-proxy container image',
- ),
- Option(
- 'container_image_elasticsearch',
- default=default_images.DEFAULT_ELASTICSEARCH_IMAGE,
- desc='elasticsearch container image',
- ),
- Option(
- 'container_image_jaeger_agent',
- default=default_images.DEFAULT_JAEGER_AGENT_IMAGE,
- desc='Jaeger agent container image',
- ),
- Option(
- 'container_image_jaeger_collector',
- default=default_images.DEFAULT_JAEGER_COLLECTOR_IMAGE,
- desc='Jaeger collector container image',
- ),
- Option(
- 'container_image_jaeger_query',
- default=default_images.DEFAULT_JAEGER_QUERY_IMAGE,
- desc='Jaeger query container image',
- ),
- Option(
- 'container_image_samba',
- default=default_images.DEFAULT_SAMBA_IMAGE,
- desc='Samba/SMB container image',
- ),
- Option(
- 'container_image_samba_metrics',
- default=default_images.DEFAULT_SAMBA_METRICS_IMAGE,
- desc='Samba/SMB metrics exporter container image',
- ),
Option(
'warn_on_stray_hosts',
type='bool',
desc="Default address for RedFish API (oob management)."
),
]
+ for image in DefaultImages:
+ MODULE_OPTIONS.append(Option(image.key, default=image.image_ref, desc=image.desc))
def __init__(self, *args: Any, **kwargs: Any):
super(CephadmOrchestrator, self).__init__(*args, **kwargs)
# Default container images -----------------------------------------------------
-DEFAULT_PROMETHEUS_IMAGE = 'quay.io/prometheus/prometheus:v2.51.0'
-DEFAULT_NODE_EXPORTER_IMAGE = 'quay.io/prometheus/node-exporter:v1.7.0'
-DEFAULT_NVMEOF_IMAGE = 'quay.io/ceph/nvmeof:1.3.3'
-DEFAULT_LOKI_IMAGE = 'quay.io/ceph/loki:3.0.0'
-DEFAULT_PROMTAIL_IMAGE = 'quay.io/ceph/promtail:3.0.0'
-DEFAULT_ALERTMANAGER_IMAGE = 'quay.io/prometheus/alertmanager:v0.27.0'
-DEFAULT_GRAFANA_IMAGE = 'quay.io/ceph/grafana:10.4.8'
-DEFAULT_HAPROXY_IMAGE = 'quay.io/ceph/haproxy:2.3'
-DEFAULT_KEEPALIVED_IMAGE = 'quay.io/ceph/keepalived:2.2.4'
-DEFAULT_SNMP_GATEWAY_IMAGE = 'quay.io/ceph/snmp-notifier:v1.2.1'
-DEFAULT_ELASTICSEARCH_IMAGE = 'quay.io/omrizeneva/elasticsearch:6.8.23'
-DEFAULT_JAEGER_COLLECTOR_IMAGE = 'quay.io/jaegertracing/jaeger-collector:1.29'
-DEFAULT_JAEGER_AGENT_IMAGE = 'quay.io/jaegertracing/jaeger-agent:1.29'
-DEFAULT_NGINX_IMAGE = 'quay.io/ceph/nginx:sclorg-nginx-126'
-DEFAULT_OAUTH2_PROXY_IMAGE = 'quay.io/oauth2-proxy/oauth2-proxy:v7.6.0'
-DEFAULT_JAEGER_QUERY_IMAGE = 'quay.io/jaegertracing/jaeger-query:1.29'
-DEFAULT_SAMBA_IMAGE = 'quay.io/samba.org/samba-server:devbuilds-centos-amd64'
-DEFAULT_SAMBA_METRICS_IMAGE = 'quay.io/samba.org/samba-metrics:latest'
+
+from typing import NamedTuple
+from enum import Enum
+
+
+class ContainerImage(NamedTuple):
+ image_ref: str # reference to default container image
+ key: str # image key
+ desc: str # description of image
+
+ def __repr__(self) -> str:
+ return self.image_ref
+
+
+def _create_image(image_ref: str, key: str) -> ContainerImage:
+ _img_prefix = 'container_image_'
+ description = key.replace('_', ' ').capitalize()
+ return ContainerImage(
+ image_ref,
+ f'{_img_prefix}{key}',
+ f'{description} container image'
+ )
+
+
+class DefaultImages(Enum):
+ PROMETHEUS = _create_image('quay.io/prometheus/prometheus:v2.51.0', 'prometheus')
+ LOKI = _create_image('docker.io/grafana/loki:3.0.0', 'loki')
+ PROMTAIL = _create_image('docker.io/grafana/promtail:3.0.0', 'promtail')
+ NODE_EXPORTER = _create_image('quay.io/prometheus/node-exporter:v1.7.0', 'node_exporter')
+ ALERTMANAGER = _create_image('quay.io/prometheus/alertmanager:v0.27.0', 'alertmanager')
+ GRAFANA = _create_image('quay.io/ceph/grafana:10.4.8', 'grafana')
+ HAPROXY = _create_image('quay.io/ceph/haproxy:2.3', 'haproxy')
+ KEEPALIVED = _create_image('quay.io/ceph/keepalived:2.2.4', 'keepalived')
+ NVMEOF = _create_image('quay.io/ceph/nvmeof:1.2.17', 'nvmeof')
+ SNMP_GATEWAY = _create_image('docker.io/maxwo/snmp-notifier:v1.2.1', 'snmp_gateway')
+ ELASTICSEARCH = _create_image('quay.io/omrizeneva/elasticsearch:6.8.23', 'elasticsearch')
+ JAEGER_COLLECTOR = _create_image('quay.io/jaegertracing/jaeger-collector:1.29',
+ 'jaeger_collector')
+ JAEGER_AGENT = _create_image('quay.io/jaegertracing/jaeger-agent:1.29', 'jaeger_agent')
+ JAEGER_QUERY = _create_image('quay.io/jaegertracing/jaeger-query:1.29', 'jaeger_query')
+ SAMBA = _create_image('quay.io/samba.org/samba-server:devbuilds-centos-amd64', 'samba')
+ SAMBA_METRICS = _create_image('quay.io/samba.org/samba-metrics:latest', 'samba_metrics')
+ NGINX = _create_image('quay.io/ceph/nginx:sclorg-nginx-126', 'nginx')
+ OAUTH2_PROXY = _create_image('quay.io/oauth2-proxy/oauth2-proxy:v7.6.0', 'oauth2_proxy')
+
+ @property
+ def image_ref(self) -> str:
+ return self.value.image_ref
+
+ @property
+ def key(self) -> str:
+ return self.value.key
+
+ @property
+ def desc(self) -> str:
+ return self.value.desc