This structure is supposed to be enough information to
start the services.
"""
- KNOWN_SERVICE_TYPES = 'alertmanager crash grafana iscsi mds mgr mon nfs ' \
+ KNOWN_SERVICE_TYPES = 'alertmanager crash grafana iscsi loki promtail mds mgr mon nfs ' \
'node-exporter osd prometheus rbd-mirror rgw agent ' \
'container ingress cephfs-mirror snmp-gateway'.split()
REQUIRES_SERVICE_ID = 'iscsi mds nfs rgw container ingress '.split()
'rgw': RGWSpec,
'nfs': NFSServiceSpec,
'osd': DriveGroupSpec,
+ 'mds': MDSSpec,
'iscsi': IscsiServiceSpec,
'alertmanager': AlertManagerSpec,
'ingress': IngressSpec,
'grafana': GrafanaSpec,
'node-exporter': MonitoringSpec,
'prometheus': MonitoringSpec,
+ 'loki': MonitoringSpec,
+ 'promtail': MonitoringSpec,
'snmp-gateway': SNMPGatewaySpec,
}.get(service_type, cls)
if ret == ServiceSpec and not service_type:
f'Service of type \'{self.service_type}\' should not contain a service id')
if self.service_id:
- if not re.match('^[a-zA-Z0-9_.-]+$', self.service_id):
+ if not re.match('^[a-zA-Z0-9_.-]+$', str(self.service_id)):
raise SpecValidationError('Service id contains invalid characters, '
'only [a-zA-Z0-9_.-] allowed')
config: Optional[Dict[str, str]] = None,
networks: Optional[List[str]] = None,
port: Optional[int] = None,
+ extra_container_args: Optional[List[str]] = None,
):
assert service_type == 'nfs'
super(NFSServiceSpec, self).__init__(
'nfs', service_id=service_id,
placement=placement, unmanaged=unmanaged, preview_only=preview_only,
- config=config, networks=networks)
+ config=config, networks=networks, extra_container_args=extra_container_args)
self.port = port
config: Optional[Dict[str, str]] = None,
networks: Optional[List[str]] = None,
subcluster: Optional[str] = None, # legacy, only for from_json on upgrade
+ extra_container_args: Optional[List[str]] = None,
):
assert service_type == 'rgw', service_type
super(RGWSpec, self).__init__(
'rgw', service_id=service_id,
placement=placement, unmanaged=unmanaged,
- preview_only=preview_only, config=config, networks=networks)
+ preview_only=preview_only, config=config, networks=networks,
+ extra_container_args=extra_container_args)
#: The RGW realm associated with this service. Needs to be manually created
self.rgw_realm: Optional[str] = rgw_realm
preview_only: bool = False,
config: Optional[Dict[str, str]] = None,
networks: Optional[List[str]] = None,
+ extra_container_args: Optional[List[str]] = None,
):
assert service_type == 'iscsi'
super(IscsiServiceSpec, self).__init__('iscsi', service_id=service_id,
placement=placement, unmanaged=unmanaged,
preview_only=preview_only,
- config=config, networks=networks)
+ config=config, networks=networks,
+ extra_container_args=extra_container_args)
#: RADOS pool where ceph-iscsi config data is stored.
self.pool = pool
virtual_ip: Optional[str] = None,
virtual_interface_networks: Optional[List[str]] = [],
unmanaged: bool = False,
- ssl: bool = False
+ ssl: bool = False,
+ extra_container_args: Optional[List[str]] = None,
):
assert service_type == 'ingress'
super(IngressSpec, self).__init__(
'ingress', service_id=service_id,
placement=placement, config=config,
- networks=networks
+ networks=networks,
+ extra_container_args=extra_container_args
)
self.backend_service = backend_service
self.frontend_port = frontend_port
unmanaged: bool = False,
preview_only: bool = False,
port: Optional[int] = None,
+ extra_container_args: Optional[List[str]] = None,
):
- assert service_type in ['grafana', 'node-exporter', 'prometheus', 'alertmanager']
+ assert service_type in ['grafana', 'node-exporter', 'prometheus', 'alertmanager',
+ 'loki', 'promtail']
super(MonitoringSpec, self).__init__(
service_type, service_id,
placement=placement, unmanaged=unmanaged,
preview_only=preview_only, config=config,
- networks=networks)
+ networks=networks, extra_container_args=extra_container_args)
self.service_type = service_type
self.port = port
return {'prometheus': 9095,
'node-exporter': 9100,
'alertmanager': 9093,
- 'grafana': 3000}[self.service_type]
+ 'grafana': 3000,
+ 'loki': 3100,
+ 'promtail': 9080}[self.service_type]
yaml.add_representer(MonitoringSpec, ServiceSpec.yaml_representer)
config: Optional[Dict[str, str]] = None,
networks: Optional[List[str]] = None,
port: Optional[int] = None,
+ secure: bool = False,
+ extra_container_args: Optional[List[str]] = None,
):
assert service_type == 'alertmanager'
super(AlertManagerSpec, self).__init__(
'alertmanager', service_id=service_id,
placement=placement, unmanaged=unmanaged,
- preview_only=preview_only, config=config, networks=networks, port=port)
+ preview_only=preview_only, config=config, networks=networks, port=port,
+ extra_container_args=extra_container_args)
# Custom configuration.
#
# added to the default receivers'
# <webhook_configs> configuration.
self.user_data = user_data or {}
+ self.secure = secure
def get_port_start(self) -> List[int]:
return [self.get_port(), 9094]
config: Optional[Dict[str, str]] = None,
networks: Optional[List[str]] = None,
port: Optional[int] = None,
- initial_admin_password: Optional[str] = None
+ initial_admin_password: Optional[str] = None,
+ extra_container_args: Optional[List[str]] = None,
):
assert service_type == 'grafana'
super(GrafanaSpec, self).__init__(
'grafana', service_id=service_id,
placement=placement, unmanaged=unmanaged,
- preview_only=preview_only, config=config, networks=networks, port=port)
+ preview_only=preview_only, config=config, networks=networks, port=port,
+ extra_container_args=extra_container_args)
self.initial_admin_password = initial_admin_password
unmanaged: bool = False,
preview_only: bool = False,
port: Optional[int] = None,
+ extra_container_args: Optional[List[str]] = None,
):
assert service_type == 'snmp-gateway'
service_type,
placement=placement,
unmanaged=unmanaged,
- preview_only=preview_only)
+ preview_only=preview_only,
+ extra_container_args=extra_container_args)
self.service_type = service_type
self.snmp_version = snmp_version
yaml.add_representer(SNMPGatewaySpec, ServiceSpec.yaml_representer)
+
+
+class MDSSpec(ServiceSpec):
+ def __init__(self,
+ service_type: str = 'mds',
+ service_id: Optional[str] = None,
+ placement: Optional[PlacementSpec] = None,
+ config: Optional[Dict[str, str]] = None,
+ unmanaged: bool = False,
+ preview_only: bool = False,
+ extra_container_args: Optional[List[str]] = None,
+ ):
+ assert service_type == 'mds'
+ super(MDSSpec, self).__init__('mds', service_id=service_id,
+ placement=placement,
+ config=config,
+ unmanaged=unmanaged,
+ preview_only=preview_only,
+ extra_container_args=extra_container_args)
+
+ def validate(self) -> None:
+ super(MDSSpec, self).validate()
+
+ if str(self.service_id)[0].isdigit():
+ raise SpecValidationError('MDS service id cannot start with a numeric digit')
+
+
+yaml.add_representer(MDSSpec, ServiceSpec.yaml_representer)