Blame cloudinit/distros/opensuse.py

Packit Service a04d08
#    Copyright (C) 2017 SUSE LLC
Packit Service a04d08
#    Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
Packit Service a04d08
#
Packit Service a04d08
#    Author: Robert Schweikert <rjschwei@suse.com>
Packit Service a04d08
#    Author: Juerg Haefliger <juerg.haefliger@hp.com>
Packit Service a04d08
#
Packit Service a04d08
#    Leaning very heavily on the RHEL and Debian implementation
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
from cloudinit import distros
Packit Service a04d08
Packit Service a04d08
from cloudinit.distros.parsers.hostname import HostnameConf
Packit Service a04d08
Packit Service a04d08
from cloudinit import helpers
Packit Service a04d08
from cloudinit import log as logging
Packit Service a04d08
from cloudinit import subp
Packit Service a04d08
from cloudinit import util
Packit Service a04d08
Packit Service a04d08
from cloudinit.distros import rhel_util as rhutil
Packit Service a04d08
from cloudinit.settings import PER_INSTANCE
Packit Service a04d08
Packit Service a04d08
LOG = logging.getLogger(__name__)
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class Distro(distros.Distro):
Packit Service a04d08
    clock_conf_fn = '/etc/sysconfig/clock'
Packit Service a04d08
    hostname_conf_fn = '/etc/HOSTNAME'
Packit Service a04d08
    init_cmd = ['service']
Packit Service a04d08
    locale_conf_fn = '/etc/sysconfig/language'
Packit Service a04d08
    network_conf_fn = '/etc/sysconfig/network/config'
Packit Service a04d08
    network_script_tpl = '/etc/sysconfig/network/ifcfg-%s'
Packit Service a04d08
    resolve_conf_fn = '/etc/resolv.conf'
Packit Service a04d08
    route_conf_tpl = '/etc/sysconfig/network/ifroute-%s'
Packit Service a04d08
    systemd_hostname_conf_fn = '/etc/hostname'
Packit Service a04d08
    systemd_locale_conf_fn = '/etc/locale.conf'
Packit Service a04d08
    tz_local_fn = '/etc/localtime'
Packit Service a04d08
    renderer_configs = {
Packit Service a04d08
        'sysconfig': {
Packit Service a04d08
            'control': 'etc/sysconfig/network/config',
Packit Service a04d08
            'flavor': 'suse',
Packit Service a04d08
            'iface_templates': '%(base)s/network/ifcfg-%(name)s',
Packit Service a04d08
            'netrules_path': (
Packit Service a04d08
                'etc/udev/rules.d/85-persistent-net-cloud-init.rules'),
Packit Service a04d08
            'route_templates': {
Packit Service a04d08
                'ipv4': '%(base)s/network/ifroute-%(name)s',
Packit Service a04d08
                'ipv6': '%(base)s/network/ifroute-%(name)s',
Packit Service a04d08
            }
Packit Service a04d08
        }
Packit Service a04d08
    }
Packit Service a04d08
Packit Service a04d08
    def __init__(self, name, cfg, paths):
Packit Service a04d08
        distros.Distro.__init__(self, name, cfg, paths)
Packit Service a04d08
        self._runner = helpers.Runners(paths)
Packit Service a04d08
        self.osfamily = 'suse'
Packit Service a04d08
        cfg['ssh_svcname'] = 'sshd'
Packit Service a04d08
        if self.uses_systemd():
Packit Service a04d08
            self.init_cmd = ['systemctl']
Packit Service a04d08
            cfg['ssh_svcname'] = 'sshd.service'
Packit Service a04d08
Packit Service a04d08
    def apply_locale(self, locale, out_fn=None):
Packit Service a04d08
        if self.uses_systemd():
Packit Service a04d08
            if not out_fn:
Packit Service a04d08
                out_fn = self.systemd_locale_conf_fn
Packit Service a04d08
            locale_cfg = {'LANG': locale}
Packit Service a04d08
        else:
Packit Service a04d08
            if not out_fn:
Packit Service a04d08
                out_fn = self.locale_conf_fn
Packit Service a04d08
            locale_cfg = {'RC_LANG': locale}
Packit Service a04d08
        rhutil.update_sysconfig_file(out_fn, locale_cfg)
Packit Service a04d08
Packit Service a04d08
    def install_packages(self, pkglist):
Packit Service a04d08
        self.package_command(
Packit Service a04d08
            'install',
Packit Service a04d08
            args='--auto-agree-with-licenses',
Packit Service a04d08
            pkgs=pkglist
Packit Service a04d08
        )
Packit Service a04d08
Packit Service a04d08
    def package_command(self, command, args=None, pkgs=None):
Packit Service a04d08
        if pkgs is None:
Packit Service a04d08
            pkgs = []
Packit Service a04d08
Packit Service a04d08
        # No user interaction possible, enable non-interactive mode
Packit Service a04d08
        cmd = ['zypper', '--non-interactive']
Packit Service a04d08
Packit Service a04d08
        # Command is the operation, such as install
Packit Service a04d08
        if command == 'upgrade':
Packit Service a04d08
            command = 'update'
Packit Service a04d08
        cmd.append(command)
Packit Service a04d08
Packit Service a04d08
        # args are the arguments to the command, not global options
Packit Service a04d08
        if args and isinstance(args, str):
Packit Service a04d08
            cmd.append(args)
Packit Service a04d08
        elif args and isinstance(args, list):
Packit Service a04d08
            cmd.extend(args)
Packit Service a04d08
Packit Service a04d08
        pkglist = util.expand_package_list('%s-%s', pkgs)
Packit Service a04d08
        cmd.extend(pkglist)
Packit Service a04d08
Packit Service a04d08
        # Allow the output of this to flow outwards (ie not be captured)
Packit Service a04d08
        subp.subp(cmd, capture=False)
Packit Service a04d08
Packit Service a04d08
    def set_timezone(self, tz):
Packit Service a04d08
        tz_file = self._find_tz_file(tz)
Packit Service a04d08
        if self.uses_systemd():
Packit Service a04d08
            # Currently, timedatectl complains if invoked during startup
Packit Service a04d08
            # so for compatibility, create the link manually.
Packit Service a04d08
            util.del_file(self.tz_local_fn)
Packit Service a04d08
            util.sym_link(tz_file, self.tz_local_fn)
Packit Service a04d08
        else:
Packit Service a04d08
            # Adjust the sysconfig clock zone setting
Packit Service a04d08
            clock_cfg = {
Packit Service a04d08
                'TIMEZONE': str(tz),
Packit Service a04d08
            }
Packit Service a04d08
            rhutil.update_sysconfig_file(self.clock_conf_fn, clock_cfg)
Packit Service a04d08
            # This ensures that the correct tz will be used for the system
Packit Service a04d08
            util.copy(tz_file, self.tz_local_fn)
Packit Service a04d08
Packit Service a04d08
    def update_package_sources(self):
Packit Service a04d08
        self._runner.run("update-sources", self.package_command,
Packit Service a04d08
                         ['refresh'], freq=PER_INSTANCE)
Packit Service a04d08
Packit Service a04d08
    def _bring_up_interfaces(self, device_names):
Packit Service a04d08
        if device_names and 'all' in device_names:
Packit Service a04d08
            raise RuntimeError(('Distro %s can not translate '
Packit Service a04d08
                                'the device name "all"') % (self.name))
Packit Service a04d08
        return distros.Distro._bring_up_interfaces(self, device_names)
Packit Service a04d08
Packit Service a04d08
    def _read_hostname(self, filename, default=None):
Packit Service a04d08
        if self.uses_systemd() and filename.endswith('/previous-hostname'):
Packit Service a04d08
            return util.load_file(filename).strip()
Packit Service a04d08
        elif self.uses_systemd():
Packit Service a04d08
            (out, _err) = subp.subp(['hostname'])
Packit Service a04d08
            if len(out):
Packit Service a04d08
                return out
Packit Service a04d08
            else:
Packit Service a04d08
                return default
Packit Service a04d08
        else:
Packit Service a04d08
            try:
Packit Service a04d08
                conf = self._read_hostname_conf(filename)
Packit Service a04d08
                hostname = conf.hostname
Packit Service a04d08
            except IOError:
Packit Service a04d08
                pass
Packit Service a04d08
            if not hostname:
Packit Service a04d08
                return default
Packit Service a04d08
            return hostname
Packit Service a04d08
Packit Service a04d08
    def _get_localhost_ip(self):
Packit Service a04d08
        return "127.0.1.1"
Packit Service a04d08
Packit Service a04d08
    def _read_hostname_conf(self, filename):
Packit Service a04d08
        conf = HostnameConf(util.load_file(filename))
Packit Service a04d08
        conf.parse()
Packit Service a04d08
        return conf
Packit Service a04d08
Packit Service a04d08
    def _read_system_hostname(self):
Packit Service a04d08
        if self.uses_systemd():
Packit Service a04d08
            host_fn = self.systemd_hostname_conf_fn
Packit Service a04d08
        else:
Packit Service a04d08
            host_fn = self.hostname_conf_fn
Packit Service a04d08
        return (host_fn, self._read_hostname(host_fn))
Packit Service a04d08
Packit Service a04d08
    def _write_hostname(self, hostname, out_fn):
Packit Service a04d08
        if self.uses_systemd() and out_fn.endswith('/previous-hostname'):
Packit Service a04d08
            util.write_file(out_fn, hostname)
Packit Service a04d08
        elif self.uses_systemd():
Packit Service a04d08
            subp.subp(['hostnamectl', 'set-hostname', str(hostname)])
Packit Service a04d08
        else:
Packit Service a04d08
            conf = None
Packit Service a04d08
            try:
Packit Service a04d08
                # Try to update the previous one
Packit Service a04d08
                # so lets see if we can read it first.
Packit Service a04d08
                conf = self._read_hostname_conf(out_fn)
Packit Service a04d08
            except IOError:
Packit Service a04d08
                pass
Packit Service a04d08
            if not conf:
Packit Service a04d08
                conf = HostnameConf('')
Packit Service a04d08
            conf.set_hostname(hostname)
Packit Service a04d08
            util.write_file(out_fn, str(conf), 0o644)
Packit Service a04d08
Packit Service a04d08
    def _write_network_config(self, netconfig):
Packit Service a04d08
        return self._supported_write_network_config(netconfig)
Packit Service a04d08
Packit Service a04d08
    @property
Packit Service a04d08
    def preferred_ntp_clients(self):
Packit Service a04d08
        """The preferred ntp client is dependent on the version."""
Packit Service a04d08
Packit Service a04d08
        # Allow distro to determine the preferred ntp client list
Packit Service a04d08
        if not self._preferred_ntp_clients:
Packit Service a04d08
            distro_info = util.system_info()['dist']
Packit Service a04d08
            name = distro_info[0]
Packit Service a04d08
            major_ver = int(distro_info[1].split('.')[0])
Packit Service a04d08
Packit Service a04d08
            # This is horribly complicated because of a case of
Packit Service a04d08
            # "we do not care if versions should be increasing syndrome"
Packit Service a04d08
            if (
Packit Service a04d08
                (major_ver >= 15 and 'openSUSE' not in name) or
Packit Service a04d08
                (major_ver >= 15 and 'openSUSE' in name and major_ver != 42)
Packit Service a04d08
            ):
Packit Service a04d08
                self._preferred_ntp_clients = ['chrony',
Packit Service a04d08
                                               'systemd-timesyncd', 'ntp']
Packit Service a04d08
            else:
Packit Service a04d08
                self._preferred_ntp_clients = ['ntp',
Packit Service a04d08
                                               'systemd-timesyncd', 'chrony']
Packit Service a04d08
Packit Service a04d08
        return self._preferred_ntp_clients
Packit Service a04d08
Packit Service a04d08
# vi: ts=4 expandtab