mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Dogtag PKI typically takes around 10 seconds to start and respond to requests. Dogtag uses a simple systemd service, which means systemd is unable to detect when Dogtag is ready. Commands like ``systemctl start`` and ``systemctl restart`` don't block and wait until the CA is up. There have been various workarounds in Dogtag and IPA. Systemd has an ExecStartPost hook to run programs after the main service is started. The post hook blocks systemctl start and restart until all post hooks report ready, too. The new ipa-pki-wait-running script polls on port 8080 and waits until the CA subsystem returns ``running``. Related: https://pagure.io/freeipa/issue/7916 Signed-off-by: Christian Heimes <cheimes@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
132 lines
3.5 KiB
Plaintext
132 lines
3.5 KiB
Plaintext
@PYTHONSHEBANG@
|
|
"""Wait until pki-tomcatd is up
|
|
|
|
The script polls on Dogtag's HTTP port and wait until the admin interface
|
|
reports status 'running' for the CA sub system.
|
|
|
|
/etc/systemd/system/pki-tomcatd@pki-tomcat.service.d/ipa.conf
|
|
[Service]
|
|
ExecStartPost=/usr/libexec/ipa/ipa-pki-wait-running
|
|
"""
|
|
import os
|
|
import logging
|
|
import sys
|
|
import time
|
|
from xml.etree import ElementTree
|
|
|
|
from ipalib import api
|
|
from ipaplatform.paths import paths
|
|
|
|
from pki.client import PKIConnection
|
|
from pki.system import SystemStatusClient
|
|
from requests.exceptions import ConnectionError, Timeout, RequestException
|
|
|
|
logger = logging.getLogger('ipa-pki-wait-running')
|
|
|
|
# check the CA subsystem. All pki-tomcatd instances in IPA have a CA
|
|
SUBSYSTEM = 'ca'
|
|
# time out for TCP connection attempts
|
|
CONNECTION_TIMEOUT = 1.0
|
|
|
|
EXIT_SUCCESS = 0
|
|
EXIT_FAILURE = 1
|
|
|
|
|
|
if hasattr(time, 'monotonic'):
|
|
curtime = time.monotonic
|
|
else:
|
|
curtime = time.time
|
|
|
|
|
|
def check_installed(subsystem):
|
|
"""Check if the subsystem is configured
|
|
"""
|
|
catalina_base = os.environ.get(
|
|
'CATALINA_BASE', '/var/lib/pki/pki-tomcat'
|
|
)
|
|
# /var/lib/pki/pki-tomcat/conf -> /etc/pki/pki-tomcat
|
|
cs_cfg = os.path.join(catalina_base, 'conf', subsystem, 'CS.cfg')
|
|
if os.path.isfile(cs_cfg):
|
|
logger.debug("File %s exists.", cs_cfg)
|
|
return True
|
|
else:
|
|
logger.info("File %s does not exist.", cs_cfg)
|
|
return False
|
|
|
|
|
|
def get_conn(hostname, subsystem):
|
|
"""Create a connection object
|
|
"""
|
|
conn = PKIConnection(
|
|
hostname=hostname,
|
|
subsystem=subsystem
|
|
)
|
|
logger.info(
|
|
"Created connection %s://%s:%s/%s",
|
|
conn.protocol, conn.hostname, conn.port, conn.subsystem
|
|
)
|
|
return conn
|
|
|
|
|
|
def get_status(conn, timeout):
|
|
"""Get status from subsystem and return parsed (status, error)
|
|
"""
|
|
client = SystemStatusClient(conn)
|
|
response = client.get_status(timeout=timeout)
|
|
root = ElementTree.fromstring(response)
|
|
status = root.findtext("Status")
|
|
error = root.findtext("Error")
|
|
logging.debug("Got status '%s', error '%s'", status, error)
|
|
return status, error
|
|
|
|
|
|
def main():
|
|
if not check_installed(SUBSYSTEM):
|
|
logger.info(
|
|
"subsystem %s is not installed, exiting", SUBSYSTEM
|
|
)
|
|
sys.exit(EXIT_SUCCESS)
|
|
|
|
# bootstrap ipalib.api to parse config file
|
|
api.bootstrap(confdir=paths.ETC_IPA)
|
|
timeout = api.env.startup_timeout
|
|
|
|
conn = get_conn(api.env.host, subsystem=SUBSYSTEM)
|
|
end = curtime() + timeout
|
|
while curtime() < end:
|
|
try:
|
|
status, error = get_status(conn, CONNECTION_TIMEOUT)
|
|
except (ConnectionError, Timeout) as e:
|
|
logger.info("Connection failed: %s", e)
|
|
except RequestException as e:
|
|
logger.error("Request failed unexpectedly, %s ", e)
|
|
else:
|
|
if status == 'running':
|
|
logger.info("Success, subsystem %s is running!", SUBSYSTEM)
|
|
sys.exit(EXIT_SUCCESS)
|
|
elif error is not None:
|
|
logger.info(
|
|
"Subsystem %s failed with error '%s', giving up!",
|
|
SUBSYSTEM, error
|
|
)
|
|
sys.exit(EXIT_FAILURE)
|
|
else:
|
|
logger.info("Status is '%s', waiting...", status)
|
|
|
|
# wait and try again
|
|
time.sleep(1)
|
|
|
|
# giving up
|
|
logger.error(
|
|
"Reached end of wait timeout %s, giving up", timeout
|
|
)
|
|
sys.exit(EXIT_FAILURE)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
logging.basicConfig(
|
|
format='%(name)s: %(message)s',
|
|
level=logging.INFO
|
|
)
|
|
main()
|