freeipa/install/tools/ipa-pki-wait-running.in
Christian Heimes 3f9e23f125 Add ExecStartPost hook to wait for Dogtag PKI
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>
2019-04-24 09:09:28 +02:00

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()