from cephadm.schedule import HostAssignment
from cephadm.utils import forall_hosts, cephadmNoImage, is_repo_digest, \
CephadmNoImage, CEPH_UPGRADE_ORDER, ContainerInspectInfo
+from mgr_module import MonCommandFailed
+
+from . import utils
if TYPE_CHECKING:
from cephadm.module import CephadmOrchestrator
return r
+ def _apply_service_config(self, spec: ServiceSpec) -> None:
+ if spec.config:
+ section = utils.name_to_config_section(spec.service_name())
+ for k, v in spec.config.items():
+ try:
+ current = self.mgr.get_foreign_ceph_option(section, k)
+ except KeyError:
+ self.log.warning(
+ f'Ignoring invalid {spec.service_name()} config option {k}'
+ )
+ self.mgr.events.for_service(
+ spec, OrchestratorEvent.ERROR, f'Invalid config option {k}'
+ )
+ continue
+ if current != v:
+ self.log.debug(f'setting [{section}] {k} = {v}')
+ try:
+ self.mgr.check_mon_command({
+ 'prefix': 'config set',
+ 'name': k,
+ 'value': str(v),
+ 'who': section,
+ })
+ except MonCommandFailed as e:
+ self.log.warning(
+ f'Failed to set {spec.service_name()} option {k}: {e}'
+ )
+
def _apply_service(self, spec: ServiceSpec) -> bool:
"""
Schedule a service. Deploy new daemons or remove old ones, depending
return False
self.log.debug('Applying service %s spec' % service_name)
+ self._apply_service_config(spec)
+
if service_type == 'osd':
self.mgr.osd_service.create_from_spec(cast(DriveGroupSpec, spec))
# TODO: return True would result in a busy loop
service_id: Optional[str] = None,
placement: Optional[PlacementSpec] = None,
count: Optional[int] = None,
+ config: Optional[Dict[str, str]] = None,
unmanaged: bool = False,
preview_only: bool = False,
):
self.unmanaged = unmanaged
self.preview_only = preview_only
+ self.config: Optional[Dict[str, str]] = None
+ if config:
+ self.config = {k.replace(' ', '_'): v for k, v in config.items()}
+
@classmethod
@handle_type_error
def from_json(cls: Type[ServiceSpecT], json_spec: Dict) -> ServiceSpecT:
service_type: nfs
service_id: foo
+ config:
+ some_option: the_value
spec:
pool: mypool
namespace: myns
namespace: Optional[str] = None,
placement: Optional[PlacementSpec] = None,
unmanaged: bool = False,
- preview_only: bool = False
+ preview_only: bool = False,
+ config: Optional[Dict[str, str]] = None,
):
assert service_type == 'nfs'
super(NFSServiceSpec, self).__init__(
'nfs', service_id=service_id,
- placement=placement, unmanaged=unmanaged, preview_only=preview_only)
+ placement=placement, unmanaged=unmanaged, preview_only=preview_only,
+ config=config)
#: RADOS pool where NFS client recovery data is stored.
self.pool = pool
unmanaged: bool = False,
ssl: bool = False,
preview_only: bool = False,
+ config: Optional[Dict[str, str]] = None,
):
assert service_type == 'rgw', service_type
if service_id:
super(RGWSpec, self).__init__(
'rgw', service_id=service_id,
placement=placement, unmanaged=unmanaged,
- preview_only=preview_only)
+ preview_only=preview_only, config=config)
self.rgw_realm = rgw_realm
self.rgw_zone = rgw_zone
ssl_key: Optional[str] = None,
placement: Optional[PlacementSpec] = None,
unmanaged: bool = False,
- preview_only: bool = False
+ preview_only: bool = False,
+ config: Optional[Dict[str, str]] = None,
):
assert service_type == 'iscsi'
super(IscsiServiceSpec, self).__init__('iscsi', service_id=service_id,
placement=placement, unmanaged=unmanaged,
- preview_only=preview_only)
+ preview_only=preview_only,
+ config=config)
#: RADOS pool where ceph-iscsi config data is stored.
self.pool = pool
unmanaged: bool = False,
preview_only: bool = False,
user_data: Optional[Dict[str, Any]] = None,
+ config: Optional[Dict[str, str]] = None,
):
assert service_type == 'alertmanager'
super(AlertManagerSpec, self).__init__(
'alertmanager', service_id=service_id,
placement=placement, unmanaged=unmanaged,
- preview_only=preview_only)
+ preview_only=preview_only, config=config)
# Custom configuration.
#
def __init__(self,
service_type: str = 'ha-rgw',
service_id: Optional[str] = None,
+ config: Optional[Dict[str, str]] = None,
placement: Optional[PlacementSpec] = None,
virtual_ip_interface: Optional[str] = None,
virtual_ip_address: Optional[str] = None,
definitive_host_list: Optional[List[HostPlacementSpec]] = None
):
assert service_type == 'ha-rgw'
- super(HA_RGWSpec, self).__init__('ha-rgw', service_id=service_id, placement=placement)
+ super(HA_RGWSpec, self).__init__('ha-rgw', service_id=service_id,
+ placement=placement, config=config)
self.virtual_ip_interface = virtual_ip_interface
self.virtual_ip_address = virtual_ip_address
def __init__(self,
service_type: str = 'container',
service_id: Optional[str] = None,
+ config: Optional[Dict[str, str]] = None,
placement: Optional[PlacementSpec] = None,
unmanaged: bool = False,
preview_only: bool = False,
super(CustomContainerSpec, self).__init__(
service_type, service_id,
placement=placement, unmanaged=unmanaged,
- preview_only=preview_only)
+ preview_only=preview_only, config=config)
self.image = image
self.entrypoint = entrypoint