freeipa/install/tools/ipa-pki-wait-running.in
Chris Kelley 9310366a6f Parse getStatus as JSON not XML
On dogtagpki/pki master XML is being replaced by JSON, getStatus will
return JSON in PKI 11.0+

The PR for dogtagpki/pki that makes this change necessary is:
https://github.com/dogtagpki/pki/pull/3674

Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Francois Cami <fcami@redhat.com>
2021-08-05 17:35:51 -04:00

143 lines
3.9 KiB
Python

#!/usr/bin/python3
"""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
import json
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,
cert_paths=paths.IPA_CA_CRT
)
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)
status = None
error = None
try:
json_response = json.loads(response)
status = json_response['Response']['Status']
except KeyError as e:
error = repr(e)
except json.JSONDecodeError:
logger.debug("Response is not valid JSON, try XML")
root = ElementTree.fromstring(response)
status = root.findtext("Status")
error = root.findtext("Error")
logger.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, log=None)
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()