diff --git a/rpmbuild/copr-rpmbuild.yml b/rpmbuild/copr-rpmbuild.yml index fcfffc104..4c48609ba 100644 --- a/rpmbuild/copr-rpmbuild.yml +++ b/rpmbuild/copr-rpmbuild.yml @@ -12,3 +12,8 @@ # cute # multiline # snippet +# +# Chroots that require active Red Hat subscription +# rhsm: +# - rhel-* +# - epel-* diff --git a/rpmbuild/copr_rpmbuild/config.py b/rpmbuild/copr_rpmbuild/config.py index ebdcee715..0442b31af 100644 --- a/rpmbuild/copr_rpmbuild/config.py +++ b/rpmbuild/copr_rpmbuild/config.py @@ -12,8 +12,10 @@ class Config: """ Configuration class for copr-rpmbuild """ + def __init__(self): self.tags_to_mock_snippet = [] + self.rhsm = [] def load_config(self): """ @@ -27,3 +29,4 @@ def load_config(self): pass self.tags_to_mock_snippet = config_data.get("tags_to_mock_snippet", []) + self.rhsm = config_data.get("rhsm", []) diff --git a/rpmbuild/copr_rpmbuild/rhsm.py b/rpmbuild/copr_rpmbuild/rhsm.py new file mode 100644 index 000000000..7f9db4f52 --- /dev/null +++ b/rpmbuild/copr_rpmbuild/rhsm.py @@ -0,0 +1,57 @@ +""" +Red Hat Subscription Management + +Activating Red Hat subscription may take a lot of time and historically, the +subscription service used to be unreliable, so we should wait for the +subscription only when necessary. +""" + +import os +import time +import logging +from fnmatch import fnmatch + + +log = logging.getLogger("__main__") + + +def subscription_required(task, config): + """ + Is subscription required for this task? + """ + for pattern in config.rhsm: + if fnmatch(task["chroot"], pattern): + return True + return False + + +def active_subscription(): + """ + Is subscription active on this system? + """ + # This is not a 100% reliable check that the subscription is active. The + # ideal check would be running `subscription-manager status` and checking + # its exit code but that requires root privileges. This check will break + # in the following corner cases: + # - The system is registered and then halted for a long time and then + # booted again after the entitlement is no longer valid + # - The system is unregistered from the server (but not from the client + # itself), making all the client files stale + return os.path.exists("/etc/pki/consumer/cert.pem") + + +def wait_for_subscription(timeout=86400): + """ + Wait until this system has an active subscription + """ + start = time.time() + attempt = 1 + while True: + log.info("Checking Red Hat subscription (attempt #%s)", attempt) + if active_subscription(): + log.info("Red Hat subscription active") + return + if time.time() > start + timeout: + raise RuntimeError("Waiting for Red Hat subscription timeouted!") + time.sleep(30) + attempt += 1 diff --git a/rpmbuild/main.py b/rpmbuild/main.py index ab4edb2d3..964ec5d4a 100755 --- a/rpmbuild/main.py +++ b/rpmbuild/main.py @@ -11,6 +11,7 @@ import shutil import pprint import shlex +from six.moves.urllib.parse import urlparse, urljoin, urlencode from copr_common.request import SafeRequest, RequestError from copr_rpmbuild import providers @@ -25,7 +26,8 @@ locate_srpm, package_version, ) -from six.moves.urllib.parse import urlparse, urljoin, urlencode +from copr_rpmbuild.config import Config +from copr_rpmbuild.rhsm import subscription_required, wait_for_subscription log = logging.getLogger(__name__) log.setLevel(logging.INFO) @@ -256,6 +258,11 @@ def build_rpm(args, config): task = get_task(args, config, build_config_url_path, task_id) log_task(task) + copr_rpmbuild_config = Config() + copr_rpmbuild_config.load_config() + if subscription_required(task, copr_rpmbuild_config): + wait_for_subscription() + try: source_json = { "clone_url": task["git_repo"],