Blame cloudinit/config/cc_ubuntu_advantage.py

Packit Service a04d08
# This file is part of cloud-init. See LICENSE file for license information.
Packit Service a04d08
Packit Service a04d08
"""ubuntu_advantage: Configure Ubuntu Advantage support services"""
Packit Service a04d08
Packit Service a04d08
from textwrap import dedent
Packit Service a04d08
Packit Service a04d08
from cloudinit.config.schema import (
Packit Service a04d08
    get_schema_doc, validate_cloudconfig_schema)
Packit Service a04d08
from cloudinit import log as logging
Packit Service a04d08
from cloudinit.settings import PER_INSTANCE
Packit Service 751c4a
from cloudinit import subp
Packit Service a04d08
from cloudinit import util
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
UA_URL = 'https://ubuntu.com/advantage'
Packit Service a04d08
Packit Service a04d08
distros = ['ubuntu']
Packit Service a04d08
Packit Service a04d08
schema = {
Packit Service a04d08
    'id': 'cc_ubuntu_advantage',
Packit Service a04d08
    'name': 'Ubuntu Advantage',
Packit Service a04d08
    'title': 'Configure Ubuntu Advantage support services',
Packit Service a04d08
    'description': dedent("""\
Packit Service a04d08
        Attach machine to an existing Ubuntu Advantage support contract and
Packit Service a04d08
        enable or disable support services such as Livepatch, ESM,
Packit Service a04d08
        FIPS and FIPS Updates. When attaching a machine to Ubuntu Advantage,
Packit Service a04d08
        one can also specify services to enable.  When the 'enable'
Packit Service a04d08
        list is present, any named service will be enabled and all absent
Packit Service a04d08
        services will remain disabled.
Packit Service a04d08
Packit Service a04d08
        Note that when enabling FIPS or FIPS updates you will need to schedule
Packit Service a04d08
        a reboot to ensure the machine is running the FIPS-compliant kernel.
Packit Service a04d08
        See :ref:`Power State Change` for information on how to configure
Packit Service a04d08
        cloud-init to perform this reboot.
Packit Service a04d08
        """),
Packit Service a04d08
    'distros': distros,
Packit Service a04d08
    'examples': [dedent("""\
Packit Service a04d08
        # Attach the machine to an Ubuntu Advantage support contract with a
Packit Service a04d08
        # UA contract token obtained from %s.
Packit Service a04d08
        ubuntu_advantage:
Packit Service a04d08
          token: <ua_contract_token>
Packit Service a04d08
    """ % UA_URL), dedent("""\
Packit Service a04d08
        # Attach the machine to an Ubuntu Advantage support contract enabling
Packit Service a04d08
        # only fips and esm services. Services will only be enabled if
Packit Service a04d08
        # the environment supports said service. Otherwise warnings will
Packit Service a04d08
        # be logged for incompatible services specified.
Packit Service a04d08
        ubuntu-advantage:
Packit Service a04d08
          token: <ua_contract_token>
Packit Service a04d08
          enable:
Packit Service a04d08
          - fips
Packit Service a04d08
          - esm
Packit Service a04d08
    """), dedent("""\
Packit Service a04d08
        # Attach the machine to an Ubuntu Advantage support contract and enable
Packit Service a04d08
        # the FIPS service.  Perform a reboot once cloud-init has
Packit Service a04d08
        # completed.
Packit Service a04d08
        power_state:
Packit Service a04d08
          mode: reboot
Packit Service a04d08
        ubuntu-advantage:
Packit Service a04d08
          token: <ua_contract_token>
Packit Service a04d08
          enable:
Packit Service a04d08
          - fips
Packit Service a04d08
        """)],
Packit Service a04d08
    'frequency': PER_INSTANCE,
Packit Service a04d08
    'type': 'object',
Packit Service a04d08
    'properties': {
Packit Service a04d08
        'ubuntu_advantage': {
Packit Service a04d08
            'type': 'object',
Packit Service a04d08
            'properties': {
Packit Service a04d08
                'enable': {
Packit Service a04d08
                    'type': 'array',
Packit Service a04d08
                    'items': {'type': 'string'},
Packit Service a04d08
                },
Packit Service a04d08
                'token': {
Packit Service a04d08
                    'type': 'string',
Packit Service a04d08
                    'description': (
Packit Service a04d08
                        'A contract token obtained from %s.' % UA_URL)
Packit Service a04d08
                }
Packit Service a04d08
            },
Packit Service a04d08
            'required': ['token'],
Packit Service a04d08
            'additionalProperties': False
Packit Service a04d08
        }
Packit Service a04d08
    }
Packit Service a04d08
}
Packit Service a04d08
Packit Service a04d08
__doc__ = get_schema_doc(schema)  # Supplement python help()
Packit Service a04d08
Packit Service a04d08
LOG = logging.getLogger(__name__)
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def configure_ua(token=None, enable=None):
Packit Service a04d08
    """Call ua commandline client to attach or enable services."""
Packit Service a04d08
    error = None
Packit Service a04d08
    if not token:
Packit Service a04d08
        error = ('ubuntu_advantage: token must be provided')
Packit Service a04d08
        LOG.error(error)
Packit Service a04d08
        raise RuntimeError(error)
Packit Service a04d08
Packit Service a04d08
    if enable is None:
Packit Service a04d08
        enable = []
Packit Service 751c4a
    elif isinstance(enable, str):
Packit Service a04d08
        LOG.warning('ubuntu_advantage: enable should be a list, not'
Packit Service a04d08
                    ' a string; treating as a single enable')
Packit Service a04d08
        enable = [enable]
Packit Service a04d08
    elif not isinstance(enable, list):
Packit Service a04d08
        LOG.warning('ubuntu_advantage: enable should be a list, not'
Packit Service a04d08
                    ' a %s; skipping enabling services',
Packit Service a04d08
                    type(enable).__name__)
Packit Service a04d08
        enable = []
Packit Service a04d08
Packit Service a04d08
    attach_cmd = ['ua', 'attach', token]
Packit Service a04d08
    LOG.debug('Attaching to Ubuntu Advantage. %s', ' '.join(attach_cmd))
Packit Service a04d08
    try:
Packit Service 751c4a
        subp.subp(attach_cmd)
Packit Service 751c4a
    except subp.ProcessExecutionError as e:
Packit Service a04d08
        msg = 'Failure attaching Ubuntu Advantage:\n{error}'.format(
Packit Service a04d08
            error=str(e))
Packit Service a04d08
        util.logexc(LOG, msg)
Packit Service 751c4a
        raise RuntimeError(msg) from e
Packit Service a04d08
    enable_errors = []
Packit Service a04d08
    for service in enable:
Packit Service a04d08
        try:
Packit Service a04d08
            cmd = ['ua', 'enable', service]
Packit Service 751c4a
            subp.subp(cmd, capture=True)
Packit Service 751c4a
        except subp.ProcessExecutionError as e:
Packit Service a04d08
            enable_errors.append((service, e))
Packit Service a04d08
    if enable_errors:
Packit Service a04d08
        for service, error in enable_errors:
Packit Service a04d08
            msg = 'Failure enabling "{service}":\n{error}'.format(
Packit Service a04d08
                service=service, error=str(error))
Packit Service a04d08
            util.logexc(LOG, msg)
Packit Service a04d08
        raise RuntimeError(
Packit Service a04d08
            'Failure enabling Ubuntu Advantage service(s): {}'.format(
Packit Service a04d08
                ', '.join('"{}"'.format(service)
Packit Service a04d08
                          for service, _ in enable_errors)))
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def maybe_install_ua_tools(cloud):
Packit Service a04d08
    """Install ubuntu-advantage-tools if not present."""
Packit Service 751c4a
    if subp.which('ua'):
Packit Service a04d08
        return
Packit Service a04d08
    try:
Packit Service a04d08
        cloud.distro.update_package_sources()
Packit Service a04d08
    except Exception:
Packit Service a04d08
        util.logexc(LOG, "Package update failed")
Packit Service a04d08
        raise
Packit Service a04d08
    try:
Packit Service a04d08
        cloud.distro.install_packages(['ubuntu-advantage-tools'])
Packit Service a04d08
    except Exception:
Packit Service a04d08
        util.logexc(LOG, "Failed to install ubuntu-advantage-tools")
Packit Service a04d08
        raise
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def handle(name, cfg, cloud, log, args):
Packit Service a04d08
    ua_section = None
Packit Service a04d08
    if 'ubuntu-advantage' in cfg:
Packit Service a04d08
        LOG.warning('Deprecated configuration key "ubuntu-advantage" provided.'
Packit Service a04d08
                    ' Expected underscore delimited "ubuntu_advantage"; will'
Packit Service a04d08
                    ' attempt to continue.')
Packit Service a04d08
        ua_section = cfg['ubuntu-advantage']
Packit Service a04d08
    if 'ubuntu_advantage' in cfg:
Packit Service a04d08
        ua_section = cfg['ubuntu_advantage']
Packit Service a04d08
    if ua_section is None:
Packit Service a04d08
        LOG.debug("Skipping module named %s,"
Packit Service a04d08
                  " no 'ubuntu_advantage' configuration found", name)
Packit Service a04d08
        return
Packit Service a04d08
    validate_cloudconfig_schema(cfg, schema)
Packit Service a04d08
    if 'commands' in ua_section:
Packit Service a04d08
        msg = (
Packit Service a04d08
            'Deprecated configuration "ubuntu-advantage: commands" provided.'
Packit Service a04d08
            ' Expected "token"')
Packit Service a04d08
        LOG.error(msg)
Packit Service a04d08
        raise RuntimeError(msg)
Packit Service a04d08
Packit Service a04d08
    maybe_install_ua_tools(cloud)
Packit Service a04d08
    configure_ua(token=ua_section.get('token'),
Packit Service a04d08
                 enable=ua_section.get('enable'))
Packit Service a04d08
Packit Service a04d08
# vi: ts=4 expandtab