Blame cloudinit/config/cc_yum_add_repo.py

Packit Service a04d08
# Copyright (C) 2012 Yahoo! Inc.
Packit Service a04d08
#
Packit Service a04d08
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
Packit Service a04d08
#
Packit Service a04d08
# This file is part of cloud-init. See LICENSE file for license information.
Packit Service a04d08
Packit Service a04d08
"""
Packit Service a04d08
Yum Add Repo
Packit Service a04d08
------------
Packit Service a04d08
**Summary:** add yum repository configuration to the system
Packit Service a04d08
Packit Service a04d08
Add yum repository configuration to ``/etc/yum.repos.d``. Configuration files
Packit Service a04d08
are named based on the dictionary key under the ``yum_repos`` they are
Packit Service a04d08
specified with. If a config file already exists with the same name as a config
Packit Service a04d08
entry, the config entry will be skipped.
Packit Service a04d08
Packit Service a04d08
**Internal name:** ``cc_yum_add_repo``
Packit Service a04d08
Packit Service a04d08
**Module frequency:** per always
Packit Service a04d08
Packit Service 751c4a
**Supported distros:** centos, fedora, rhel
Packit Service a04d08
Packit Service a04d08
**Config keys**::
Packit Service a04d08
Packit Service a04d08
    yum_repos:
Packit Service a04d08
        <repo-name>:
Packit Service a04d08
            baseurl: <repo url>
Packit Service a04d08
            name: <repo name>
Packit Service a04d08
            enabled: <true/false>
Packit Service a04d08
            # any repository configuration options (see man yum.conf)
Packit Service a04d08
"""
Packit Service a04d08
Packit Service 751c4a
import io
Packit Service a04d08
import os
Packit Service 751c4a
from configparser import ConfigParser
Packit Service a04d08
Packit Service a04d08
from cloudinit import util
Packit Service a04d08
Packit Service 751c4a
distros = ['centos', 'fedora', 'rhel']
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def _canonicalize_id(repo_id):
Packit Service a04d08
    repo_id = repo_id.lower().replace("-", "_")
Packit Service a04d08
    repo_id = repo_id.replace(" ", "_")
Packit Service a04d08
    return repo_id
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def _format_repo_value(val):
Packit Service a04d08
    if isinstance(val, (bool)):
Packit Service a04d08
        # Seems like yum prefers 1/0
Packit Service a04d08
        return str(int(val))
Packit Service a04d08
    if isinstance(val, (list, tuple)):
Packit Service a04d08
        # Can handle 'lists' in certain cases
Packit Service a04d08
        # See: https://linux.die.net/man/5/yum.conf
Packit Service a04d08
        return "\n".join([_format_repo_value(v) for v in val])
Packit Service 751c4a
    if not isinstance(val, str):
Packit Service a04d08
        return str(val)
Packit Service a04d08
    return val
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
# TODO(harlowja): move to distro?
Packit Service a04d08
# See man yum.conf
Packit Service a04d08
def _format_repository_config(repo_id, repo_config):
Packit Service a04d08
    to_be = ConfigParser()
Packit Service a04d08
    to_be.add_section(repo_id)
Packit Service a04d08
    # Do basic translation of the items -> values
Packit Service a04d08
    for (k, v) in repo_config.items():
Packit Service a04d08
        # For now assume that people using this know
Packit Service a04d08
        # the format of yum and don't verify keys/values further
Packit Service a04d08
        to_be.set(repo_id, k, _format_repo_value(v))
Packit Service 751c4a
    to_be_stream = io.StringIO()
Packit Service a04d08
    to_be.write(to_be_stream)
Packit Service a04d08
    to_be_stream.seek(0)
Packit Service a04d08
    lines = to_be_stream.readlines()
Packit Service a04d08
    lines.insert(0, "# Created by cloud-init on %s\n" % (util.time_rfc2822()))
Packit Service a04d08
    return "".join(lines)
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def handle(name, cfg, _cloud, log, _args):
Packit Service a04d08
    repos = cfg.get('yum_repos')
Packit Service a04d08
    if not repos:
Packit Service a04d08
        log.debug(("Skipping module named %s,"
Packit Service a04d08
                   " no 'yum_repos' configuration found"), name)
Packit Service a04d08
        return
Packit Service a04d08
    repo_base_path = util.get_cfg_option_str(cfg, 'yum_repo_dir',
Packit Service a04d08
                                             '/etc/yum.repos.d/')
Packit Service a04d08
    repo_locations = {}
Packit Service a04d08
    repo_configs = {}
Packit Service a04d08
    for (repo_id, repo_config) in repos.items():
Packit Service a04d08
        canon_repo_id = _canonicalize_id(repo_id)
Packit Service a04d08
        repo_fn_pth = os.path.join(repo_base_path, "%s.repo" % (canon_repo_id))
Packit Service a04d08
        if os.path.exists(repo_fn_pth):
Packit Service a04d08
            log.info("Skipping repo %s, file %s already exists!",
Packit Service a04d08
                     repo_id, repo_fn_pth)
Packit Service a04d08
            continue
Packit Service a04d08
        elif canon_repo_id in repo_locations:
Packit Service a04d08
            log.info("Skipping repo %s, file %s already pending!",
Packit Service a04d08
                     repo_id, repo_fn_pth)
Packit Service a04d08
            continue
Packit Service a04d08
        if not repo_config:
Packit Service a04d08
            repo_config = {}
Packit Service a04d08
        # Do some basic sanity checks/cleaning
Packit Service a04d08
        n_repo_config = {}
Packit Service a04d08
        for (k, v) in repo_config.items():
Packit Service a04d08
            k = k.lower().strip().replace("-", "_")
Packit Service a04d08
            if k:
Packit Service a04d08
                n_repo_config[k] = v
Packit Service a04d08
        repo_config = n_repo_config
Packit Service a04d08
        missing_required = 0
Packit Service a04d08
        for req_field in ['baseurl']:
Packit Service a04d08
            if req_field not in repo_config:
Packit Service a04d08
                log.warning(("Repository %s does not contain a %s"
Packit Service a04d08
                             " configuration 'required' entry"),
Packit Service a04d08
                            repo_id, req_field)
Packit Service a04d08
                missing_required += 1
Packit Service a04d08
        if not missing_required:
Packit Service a04d08
            repo_configs[canon_repo_id] = repo_config
Packit Service a04d08
            repo_locations[canon_repo_id] = repo_fn_pth
Packit Service a04d08
        else:
Packit Service a04d08
            log.warning("Repository %s is missing %s required fields, "
Packit Service a04d08
                        "skipping!", repo_id, missing_required)
Packit Service a04d08
    for (c_repo_id, path) in repo_locations.items():
Packit Service a04d08
        repo_blob = _format_repository_config(c_repo_id,
Packit Service a04d08
                                              repo_configs.get(c_repo_id))
Packit Service a04d08
        util.write_file(path, repo_blob)
Packit Service a04d08
Packit Service a04d08
# vi: ts=4 expandtab