Manage apache2 process directly

Apache2 supports the signal USR1 to restart all its children and reload
configuration.
Apache2ctl cannot receive USR1 signal directly to this effect, therefore
manage the apache2 directly, configuring all the environment variables
from apache2ctl.

Closes-Bug: #2097259
Change-Id: I55741645b09d5de0f25970b16e4d5fdfa3c58a9d
Signed-off-by: Guillaume Boutry <guillaume.boutry@canonical.com>
This commit is contained in:
Guillaume Boutry 2025-02-13 15:31:33 +01:00
parent fba9eac56a
commit 2cc6bdfad6
No known key found for this signature in database
GPG Key ID: 0DD77DC1796E98CD
4 changed files with 115 additions and 8 deletions

View File

@ -24,6 +24,8 @@ This charm provide Glance services as part of an OpenStack deployment
import json import json
import logging import logging
import re import re
import signal
import typing
from typing import ( from typing import (
Callable, Callable,
List, List,
@ -74,7 +76,7 @@ STORAGE_NAME = "local-repository"
class GlanceAPIPebbleHandler(sunbeam_chandlers.ServicePebbleHandler): class GlanceAPIPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
"""Handler for glance api container.""" """Handler for glance api container."""
def get_layer(self) -> dict: def get_layer(self) -> ops.pebble.LayerDict:
"""Glance API service pebble layer. """Glance API service pebble layer.
:returns: pebble layer configuration for glance api service :returns: pebble layer configuration for glance api service
@ -86,6 +88,7 @@ class GlanceAPIPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
f"{self.service_name}": { f"{self.service_name}": {
"override": "replace", "override": "replace",
"summary": f"{self.service_name} standalone", "summary": f"{self.service_name} standalone",
"startup": "disabled",
"command": ( "command": (
"/usr/bin/glance-api " "/usr/bin/glance-api "
"--config-file /etc/glance/glance-api.conf" "--config-file /etc/glance/glance-api.conf"
@ -96,7 +99,16 @@ class GlanceAPIPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
"apache forwarder": { "apache forwarder": {
"override": "replace", "override": "replace",
"summary": "apache", "summary": "apache",
"command": "/usr/sbin/apache2ctl -DFOREGROUND", "command": "/usr/sbin/apache2 -DFOREGROUND -DNO_DETACH",
"startup": "disabled",
"environment": {
"APACHE_RUN_DIR": "/var/run/apache2",
"APACHE_PID_FILE": "/var/run/apache2/apache2.pid",
"APACHE_LOCK_DIR": "/var/lock/apache2",
"APACHE_RUN_USER": "www-data",
"APACHE_RUN_GROUP": "www-data",
"APACHE_LOG_DIR": "/var/log/apache2",
},
}, },
}, },
} }
@ -110,6 +122,16 @@ class GlanceAPIPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
self.execute(["a2enmod", "proxy_http"], exception_on_error=True) self.execute(["a2enmod", "proxy_http"], exception_on_error=True)
return super().init_service(context) return super().init_service(context)
@property
def _restart_methods(
self,
) -> typing.Mapping[str, Callable[[ops.Container, str], None]]:
return {
"apache forwarder": lambda container, service_name: container.send_signal(
signal.SIGUSR1, service_name
)
}
@sunbeam_tracing.trace_type @sunbeam_tracing.trace_type
class GlanceStorageRelationHandler(sunbeam_rhandlers.CephClientHandler): class GlanceStorageRelationHandler(sunbeam_rhandlers.CephClientHandler):

View File

@ -22,6 +22,8 @@ This charm deploys the openstack images sync service on Kubernetes.
import logging import logging
import os import os
import signal
import typing
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,
) )
@ -107,9 +109,14 @@ class OpenstackImagesSyncPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
self.charm.service_user, self.charm.service_user,
self.charm.service_group, self.charm.service_group,
), ),
sunbeam_chandlers.ContainerDir(
"/var/run/apache2",
"root",
"root",
),
] ]
def get_layer(self) -> dict: def get_layer(self) -> ops.pebble.LayerDict:
"""Openstack Images Sync service pebble layer. """Openstack Images Sync service pebble layer.
:returns: pebble layer configuration for openstack images sync service :returns: pebble layer configuration for openstack images sync service
@ -135,7 +142,16 @@ class OpenstackImagesSyncPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
"http-mirror": { "http-mirror": {
"override": "replace", "override": "replace",
"summary": "apache", "summary": "apache",
"command": "/usr/sbin/apache2ctl -DFOREGROUND", "command": "/usr/sbin/apache2 -DFOREGROUND -DNO_DETACH",
"startup": "disabled",
"environment": {
"APACHE_RUN_DIR": "/var/run/apache2",
"APACHE_PID_FILE": "/var/run/apache2/apache2.pid",
"APACHE_LOCK_DIR": "/var/lock/apache2",
"APACHE_RUN_USER": "www-data",
"APACHE_RUN_GROUP": "www-data",
"APACHE_LOG_DIR": "/var/log/apache2",
},
}, },
}, },
} }
@ -149,6 +165,16 @@ class OpenstackImagesSyncPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
self.execute(["a2dissite", "000-default"], exception_on_error=True) self.execute(["a2dissite", "000-default"], exception_on_error=True)
return super().init_service(context) return super().init_service(context)
@property
def _restart_methods(
self,
) -> typing.Mapping[str, typing.Callable[[ops.Container, str], None]]:
return {
"http-mirror": lambda container, service_name: container.send_signal(
signal.SIGUSR1, service_name
)
}
@sunbeam_tracing.trace_sunbeam_charm @sunbeam_tracing.trace_sunbeam_charm
class OpenstackImagesSyncK8SCharm(sunbeam_charm.OSBaseOperatorAPICharm): class OpenstackImagesSyncK8SCharm(sunbeam_charm.OSBaseOperatorAPICharm):

View File

@ -21,6 +21,7 @@ in the container.
import collections import collections
import logging import logging
import signal
import typing import typing
from collections.abc import ( from collections.abc import (
Callable, Callable,
@ -316,7 +317,26 @@ class PebbleHandler(ops.framework.Object):
self.status.set(ActiveStatus("")) self.status.set(ActiveStatus(""))
def start_all(self, restart: bool = True) -> None: @staticmethod
def _restart_service(container: ops.Container, service_name: str) -> None:
"""Restart service in container.
:param container: Container to restart service in.
:param service_name: Service to restart.
"""
container.restart(service_name)
@property
def _restart_methods(
self,
) -> typing.Mapping[str, Callable[[ops.Container, str], None]]:
"""Mapping of service names to restart methods."""
return {}
def start_all(
self,
restart: bool = True,
) -> None:
"""Start services in container. """Start services in container.
:param restart: Whether to stop services before starting them. :param restart: Whether to stop services before starting them.
@ -341,7 +361,9 @@ class PebbleHandler(ops.framework.Object):
logger.debug( logger.debug(
f"Restarting {service_name} in {self.container_name}" f"Restarting {service_name} in {self.container_name}"
) )
container.restart(service_name) self._restart_methods.get(service_name, self._restart_service)(
container, service_name
)
self._reset_files_changed() self._reset_files_changed()
def stop_all(self) -> None: def stop_all(self) -> None:
@ -425,6 +447,27 @@ class WSGIPebbleHandler(PebbleHandler):
) )
self.wsgi_service_name = wsgi_service_name self.wsgi_service_name = wsgi_service_name
@staticmethod
def _restart_wsgi_service(
container: ops.Container, service_name: str
) -> None:
"""Restart WSGI service in container.
WSGI services can be gracefully restarted by sending SIGUSR1 to the
service.
:param container: Container to restart service in.
:param service_name: Service to restart.
"""
container.send_signal(signal.SIGUSR1, service_name)
@property
def _restart_methods(
self,
) -> typing.Mapping[str, Callable[[ops.Container, str], None]]:
"""Mapping of service names to restart methods."""
return {self.wsgi_service_name: self._restart_wsgi_service}
def start_wsgi(self, restart: bool = True) -> None: def start_wsgi(self, restart: bool = True) -> None:
"""Check and start services in container. """Check and start services in container.
@ -459,8 +502,16 @@ class WSGIPebbleHandler(PebbleHandler):
f"{self.wsgi_service_name}": { f"{self.wsgi_service_name}": {
"override": "replace", "override": "replace",
"summary": f"{self.service_name} wsgi", "summary": f"{self.service_name} wsgi",
"command": "/usr/sbin/apache2ctl -DFOREGROUND", "command": "/usr/sbin/apache2 -DFOREGROUND -DNO_DETACH",
"startup": "disabled", "startup": "disabled",
"environment": {
"APACHE_RUN_DIR": "/var/run/apache2",
"APACHE_PID_FILE": "/var/run/apache2/apache2.pid",
"APACHE_LOCK_DIR": "/var/lock/apache2",
"APACHE_RUN_USER": "www-data",
"APACHE_RUN_GROUP": "www-data",
"APACHE_LOG_DIR": "/var/log/apache2",
},
}, },
}, },
} }

View File

@ -333,8 +333,16 @@ class MultiSvcPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
"apache forwarder": { "apache forwarder": {
"override": "replace", "override": "replace",
"summary": "apache", "summary": "apache",
"command": "/usr/sbin/apache2ctl -DFOREGROUND", "command": "/usr/sbin/apache2 -DFOREGROUND",
"startup": "disabled", "startup": "disabled",
"environment": {
"APACHE_RUN_DIR": "/var/run/apache2",
"APACHE_PID_FILE": "/var/run/apache2/apache2.pid",
"APACHE_LOCK_DIR": "/var/lock/apache2",
"APACHE_RUN_USER": "www-data",
"APACHE_RUN_GROUP": "www-data",
"APACHE_LOG_DIR": "/var/log/apache2",
},
}, },
}, },
} }