From eacce78d5d5689364b7a2f516e29c1c65558fd60d6213af5818a408ddfa33f9c Mon Sep 17 00:00:00 2001 From: Robert Schweikert Date: Fri, 20 Jun 2014 23:13:07 +0000 Subject: [PATCH] - integrate openSUSE and SLE handler code + remove openSUSEHandler.diff + add suseIntegratedHandler.patch OBS-URL: https://build.opensuse.org/package/show/Cloud:Tools/cloud-init?expand=0&rev=13 --- cloud-init.changes | 7 + cloud-init.spec | 4 +- openSUSEHandler.diff | 91 -------- suseIntegratedHandler.patch | 400 ++++++++++++++++++++++++++++++++++++ 4 files changed, 409 insertions(+), 93 deletions(-) delete mode 100644 openSUSEHandler.diff create mode 100644 suseIntegratedHandler.patch diff --git a/cloud-init.changes b/cloud-init.changes index 11c21d7..a71af2e 100644 --- a/cloud-init.changes +++ b/cloud-init.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Fri Jun 20 17:59:37 UTC 2014 - rschweikert@suse.com + +- integrate openSUSE and SLE handler code + + remove openSUSEHandler.diff + + add suseIntegratedHandler.patch + ------------------------------------------------------------------- Mon Apr 14 18:58:18 UTC 2014 - rschweikert@suse.com diff --git a/cloud-init.spec b/cloud-init.spec index 3e25d48..9410697 100644 --- a/cloud-init.spec +++ b/cloud-init.spec @@ -26,7 +26,7 @@ Source0: %{name}-%{version}.tar.gz Source1: cloud.cfg.suse Patch0: suseSysVInit.diff Patch1: addopenSUSEBase.patch -Patch2: openSUSEHandler.diff +Patch2: suseIntegratedHandler.patch Patch3: setupSUSEsysVInit.diff Patch5: openSUSEhostsTemplate.diff BuildRequires: fdupes @@ -95,7 +95,7 @@ Unit tests for the cloud-init tools %setup -q %patch0 -p1 %patch1 -p1 -%patch2 -p1 +%patch2 %patch3 -p1 %patch5 diff --git a/openSUSEHandler.diff b/openSUSEHandler.diff deleted file mode 100644 index 9966cec..0000000 --- a/openSUSEHandler.diff +++ /dev/null @@ -1,91 +0,0 @@ -diff -urN cloud-init-0.7.4/cloudinit/distros/opensuse.py cloud-init-0.7.4.os/cloudinit/distros/opensuse.py ---- cloud-init-0.7.4/cloudinit/distros/opensuse.py 1969-12-31 19:00:00.000000000 -0500 -+++ cloud-init-0.7.4.os/cloudinit/distros/opensuse.py 2013-06-15 06:26:15.312348359 -0400 -@@ -0,0 +1,87 @@ -+# vi: ts=4 expandtab -+# -+# Copyright (C) 2013 SUSE LLC -+# -+# Author: Robert Schweikert -+# -+# Leaning very heavily on the RHEL implementation -+# -+# This program is free software: you can redistribute it and/or modify -+# it under the terms of the GNU General Public License version 3, as -+# published by the Free Software Foundation. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+import os -+ -+from cloudinit.distros import sles -+from cloudinit.distros import rhel_util -+ -+from cloudinit.distros.parsers.resolv_conf import ResolvConf -+from cloudinit.distros.parsers.sys_conf import SysConf -+ -+from cloudinit import helpers -+from cloudinit import log as logging -+from cloudinit import util -+ -+from cloudinit.settings import PER_INSTANCE -+ -+LOG = logging.getLogger(__name__) -+ -+class Distro(sles.Distro): -+ systemd_locale_conf_fn = '/etc/locale.conf' -+ -+ def __init__(self, name, cfg, paths): -+ sles.Distro.__init__(self, name, cfg, paths) -+ -+ def apply_locale(self, locale, out_fn=None): -+ if os.path.exists('/usr/bin/localectl'): -+ if not out_fn: -+ out_fn = systemd_locale_conf_fn -+ locale_cfg = { -+ 'LANG': locale, -+ } -+ else: -+ if not out_fn: -+ out_fn = self.locale_conf_fn -+ locale_cfg = { -+ 'RC_LANG': locale, -+ } -+ util.update_sysconfig_file(out_fn, locale_cfg) -+ -+ def _write_hostname(self, hostname, out_fn): -+ if os.path.exists('/usr/bin/hostnamectl'): -+ util.subp(['hostnamectl', 'set-hostname', str(hostname)]) -+ else: -+ host_cfg = { -+ 'HOSTNAME': hostname, -+ } -+ util.update_sysconfig_file(out_fn, host_cfg) -+ -+ def _select_hostname(self, hostname, fqdn): -+ if fqdn: -+ return fqdn -+ return hostname -+ -+ def _read_system_hostname(self): -+ host_fn = self.hostname_conf_fn -+ return (host_fn, self._read_hostname(host_fn)) -+ -+ def _read_hostname(self, filename, default=None): -+ (out, _err) = util.subp(['hostname']) -+ if len(out): -+ return out -+ else: -+ (_exists, contents) = rhel_util.read_sysconfig_file(filename) -+ if 'HOSTNAME' in contents: -+ return contents['HOSTNAME'] -+ else: -+ return default -+ -+ diff --git a/suseIntegratedHandler.patch b/suseIntegratedHandler.patch new file mode 100644 index 0000000..c6b4652 --- /dev/null +++ b/suseIntegratedHandler.patch @@ -0,0 +1,400 @@ +--- /dev/null ++++ cloudinit/distros/opensuse.py +@@ -0,0 +1,209 @@ ++# vi: ts=4 expandtab ++# ++# Copyright (C) 2014 SUSE LLC ++# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. ++# ++# Author: Robert Schweikert ++# Author: Juerg Haefliger ++# ++# Leaning very heavily on the RHEL and Debian implementation ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License version 3, as ++# published by the Free Software Foundation. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++from cloudinit import distros ++ ++from cloudinit.distros.parsers.hostname import HostnameConf ++ ++from cloudinit import helpers ++from cloudinit import log as logging ++from cloudinit import util ++ ++from cloudinit.distros import net_util ++from cloudinit.distros import rhel_util as rhutil ++from cloudinit.settings import PER_INSTANCE ++ ++LOG = logging.getLogger(__name__) ++ ++class Distro(distros.Distro): ++ clock_conf_fn = '/etc/sysconfig/clock' ++ locale_conf_fn = '/etc/sysconfig/language' ++ network_conf_fn = '/etc/sysconfig/network' ++ hostname_conf_fn = '/etc/HOSTNAME' ++ network_script_tpl = '/etc/sysconfig/network/ifcfg-%s' ++ resolve_conf_fn = '/etc/resolv.conf' ++ tz_local_fn = '/etc/localtime' ++ systemd_locale_conf_fn = '/etc/locale.conf' ++ ++ def __init__(self, name, cfg, paths): ++ distros.Distro.__init__(self, name, cfg, paths) ++ # This will be used to restrict certain ++ # calls from repeatly happening (when they ++ # should only happen say once per instance...) ++ self._runner = helpers.Runners(paths) ++ self.osfamily = 'suse' ++ self.systemdDist = util.which('systemctl') ++ ++ def apply_locale(self, locale, out_fn=None): ++ if self.systemdDist: ++ if not out_fn: ++ out_fn = self.systemd_locale_conf_fn ++ locale_cfg = {'LANG': locale} ++ else: ++ if not out_fn: ++ out_fn = self.locale_conf_fn ++ locale_cfg = {'RC_LANG': locale} ++ rhutil.update_sysconfig_file(out_fn, locale_cfg) ++ ++ def install_packages(self, pkglist): ++ self.package_command('install', args='-l', pkgs=pkglist) ++ ++ def package_command(self, command, args=None, pkgs=None): ++ if pkgs is None: ++ pkgs = [] ++ ++ cmd = ['zypper'] ++ # No user interaction possible, enable non-interactive mode ++ cmd.append('--non-interactive') ++ ++ # Comand is the operation, such as install ++ cmd.append(command) ++ ++ # args are the arguments to the command, not global options ++ if args and isinstance(args, str): ++ cmd.append(args) ++ elif args and isinstance(args, list): ++ cmd.extend(args) ++ ++ pkglist = util.expand_package_list('%s-%s', pkgs) ++ cmd.extend(pkglist) ++ ++ # Allow the output of this to flow outwards (ie not be captured) ++ util.subp(cmd, capture=False) ++ ++ def set_timezone(self, tz): ++ tz_file = self._find_tz_file(tz) ++ if self.systemdDist: ++ # Currently, timedatectl complains if invoked during startup ++ # so for compatibility, create the link manually. ++ util.del_file(self.tz_local_fn) ++ util.sym_link(tz_file, self.tz_local_fn) ++ else: ++ # Adjust the sysconfig clock zone setting ++ clock_cfg = { ++ 'TIMEZONE': str(tz), ++ } ++ rhel_util.update_sysconfig_file(self.clock_conf_fn, clock_cfg) ++ # This ensures that the correct tz will be used for the system ++ util.copy(tz_file, self.tz_local_fn) ++ ++ def update_package_sources(self): ++ self._runner.run("update-sources", self.package_command, ++ ['refresh'], freq=PER_INSTANCE) ++ ++ ++ def _bring_up_interfaces(self, device_names): ++ if device_names and 'all' in device_names: ++ raise RuntimeError(('Distro %s can not translate ' ++ 'the device name "all"') % (self.name)) ++ return distros.Distro._bring_up_interfaces(self, device_names) ++ ++ ++ def _read_hostname(self, filename, default=None): ++ (out, _err) = util.subp(['hostname']) ++ if len(out): ++ return out ++ else: ++ try: ++ conf = self._read_hostname_conf(filename) ++ hostname = conf.hostname ++ except IOError: ++ pass ++ if not hostname: ++ return default ++ return hostname ++ ++ def _read_hostname_conf(self, filename): ++ conf = HostnameConf(util.load_file(filename)) ++ conf.parse() ++ return conf ++ ++ def _read_system_hostname(self): ++ host_fn = self.hostname_conf_fn ++ return (host_fn, self._read_hostname(host_fn)) ++ ++ def _select_hostname(self, hostname, fqdn): ++ if fqdn: ++ return fqdn ++ return hostname ++ ++ def _write_hostname(self, hostname, out_fn): ++ if self.systemdDist: ++ util.subp(['hostnamectl', 'set-hostname', str(hostname)]) ++ else: ++ try: ++ # Try to update the previous one ++ # so lets see if we can read it first. ++ conf = self._read_hostname_conf(out_fn) ++ except IOError: ++ pass ++ if not conf: ++ conf = HostnameConf('') ++ conf.set_hostname(hostname) ++ util.write_file(out_fn, str(conf), 0644) ++ ++ def _write_network(self, settings): ++ # Convert debian settings to ifcfg format ++ entries = net_util.translate_network(settings) ++ LOG.debug("Translated ubuntu style network settings %s into %s", ++ settings, entries) ++ # Make the intermediate format as the suse format... ++ nameservers = [] ++ searchservers = [] ++ dev_names = entries.keys() ++ for (dev, info) in entries.iteritems(): ++ net_fn = self.network_script_tpl % (dev) ++ mode = info.get('auto') ++ if mode and mode.lower() == 'true': ++ mode = 'auto' ++ else: ++ mode = 'manual' ++ net_cfg = { ++ 'BOOTPROTO': info.get('bootproto'), ++ 'BROADCAST': info.get('broadcast'), ++ 'GATEWAY': info.get('gateway'), ++ 'IPADDR': info.get('address'), ++ 'LLADDR': info.get('hwaddress'), ++ 'NETMASK': info.get('netmask'), ++ 'STARTMODE': mode, ++ 'USERCONTROL': 'no' ++ } ++ if dev != 'lo': ++ net_cfg['ETHERDEVICE'] = dev ++ net_cfg['ETHTOOL_OPTIONS'] = '' ++ else: ++ net_cfg['FIREWALL'] = 'no' ++ rhel_util.update_sysconfig_file(net_fn, net_cfg, True) ++ if 'dns-nameservers' in info: ++ nameservers.extend(info['dns-nameservers']) ++ if 'dns-search' in info: ++ searchservers.extend(info['dns-search']) ++ if nameservers or searchservers: ++ rhel_util.update_resolve_conf_file(self.resolve_conf_fn, ++ nameservers, searchservers) ++ return dev_names ++ ++ ++ ++ ++ ++ +--- cloudinit/distros/sles.py.orig ++++ cloudinit/distros/sles.py +@@ -1,10 +1,8 @@ + # vi: ts=4 expandtab + # +-# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. ++# Copyright (C) 2014 SUSE LLC + # +-# Author: Juerg Haefliger +-# +-# Leaning very heavily on the RHEL and Debian implementation ++# Author: Robert Schweikert + # + # This program is free software: you can redistribute it and/or modify + # it under the terms of the GNU General Public License version 3, as +@@ -18,169 +16,11 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-from cloudinit import distros +- +-from cloudinit.distros.parsers.hostname import HostnameConf ++from cloudinit.distros import opensuse + +-from cloudinit import helpers + from cloudinit import log as logging +-from cloudinit import util +- +-from cloudinit.distros import net_util +-from cloudinit.distros import rhel_util +-from cloudinit.settings import PER_INSTANCE + + LOG = logging.getLogger(__name__) + +- +-class Distro(distros.Distro): +- clock_conf_fn = '/etc/sysconfig/clock' +- locale_conf_fn = '/etc/sysconfig/language' +- network_conf_fn = '/etc/sysconfig/network' +- hostname_conf_fn = '/etc/HOSTNAME' +- network_script_tpl = '/etc/sysconfig/network/ifcfg-%s' +- resolve_conf_fn = '/etc/resolv.conf' +- tz_local_fn = '/etc/localtime' +- +- def __init__(self, name, cfg, paths): +- distros.Distro.__init__(self, name, cfg, paths) +- # This will be used to restrict certain +- # calls from repeatly happening (when they +- # should only happen say once per instance...) +- self._runner = helpers.Runners(paths) +- self.osfamily = 'suse' +- +- def install_packages(self, pkglist): +- self.package_command('install', args='-l', pkgs=pkglist) +- +- def _write_network(self, settings): +- # Convert debian settings to ifcfg format +- entries = net_util.translate_network(settings) +- LOG.debug("Translated ubuntu style network settings %s into %s", +- settings, entries) +- # Make the intermediate format as the suse format... +- nameservers = [] +- searchservers = [] +- dev_names = entries.keys() +- for (dev, info) in entries.iteritems(): +- net_fn = self.network_script_tpl % (dev) +- mode = info.get('auto') +- if mode and mode.lower() == 'true': +- mode = 'auto' +- else: +- mode = 'manual' +- net_cfg = { +- 'BOOTPROTO': info.get('bootproto'), +- 'BROADCAST': info.get('broadcast'), +- 'GATEWAY': info.get('gateway'), +- 'IPADDR': info.get('address'), +- 'LLADDR': info.get('hwaddress'), +- 'NETMASK': info.get('netmask'), +- 'STARTMODE': mode, +- 'USERCONTROL': 'no' +- } +- if dev != 'lo': +- net_cfg['ETHERDEVICE'] = dev +- net_cfg['ETHTOOL_OPTIONS'] = '' +- else: +- net_cfg['FIREWALL'] = 'no' +- rhel_util.update_sysconfig_file(net_fn, net_cfg, True) +- if 'dns-nameservers' in info: +- nameservers.extend(info['dns-nameservers']) +- if 'dns-search' in info: +- searchservers.extend(info['dns-search']) +- if nameservers or searchservers: +- rhel_util.update_resolve_conf_file(self.resolve_conf_fn, +- nameservers, searchservers) +- return dev_names +- +- def apply_locale(self, locale, out_fn=None): +- if not out_fn: +- out_fn = self.locale_conf_fn +- locale_cfg = { +- 'RC_LANG': locale, +- } +- rhel_util.update_sysconfig_file(out_fn, locale_cfg) +- +- def _write_hostname(self, hostname, out_fn): +- conf = None +- try: +- # Try to update the previous one +- # so lets see if we can read it first. +- conf = self._read_hostname_conf(out_fn) +- except IOError: +- pass +- if not conf: +- conf = HostnameConf('') +- conf.set_hostname(hostname) +- util.write_file(out_fn, str(conf), 0644) +- +- def _select_hostname(self, hostname, fqdn): +- # Prefer the short hostname over the long +- # fully qualified domain name +- if not hostname: +- return fqdn +- return hostname +- +- def _read_system_hostname(self): +- host_fn = self.hostname_conf_fn +- return (host_fn, self._read_hostname(host_fn)) +- +- def _read_hostname_conf(self, filename): +- conf = HostnameConf(util.load_file(filename)) +- conf.parse() +- return conf +- +- def _read_hostname(self, filename, default=None): +- hostname = None +- try: +- conf = self._read_hostname_conf(filename) +- hostname = conf.hostname +- except IOError: +- pass +- if not hostname: +- return default +- return hostname +- +- def _bring_up_interfaces(self, device_names): +- if device_names and 'all' in device_names: +- raise RuntimeError(('Distro %s can not translate ' +- 'the device name "all"') % (self.name)) +- return distros.Distro._bring_up_interfaces(self, device_names) +- +- def set_timezone(self, tz): +- tz_file = self._find_tz_file(tz) +- # Adjust the sysconfig clock zone setting +- clock_cfg = { +- 'TIMEZONE': str(tz), +- } +- rhel_util.update_sysconfig_file(self.clock_conf_fn, clock_cfg) +- # This ensures that the correct tz will be used for the system +- util.copy(tz_file, self.tz_local_fn) +- +- def package_command(self, command, args=None, pkgs=None): +- if pkgs is None: +- pkgs = [] +- +- cmd = ['zypper'] +- # No user interaction possible, enable non-interactive mode +- cmd.append('--non-interactive') +- +- # Comand is the operation, such as install +- cmd.append(command) +- +- # args are the arguments to the command, not global options +- if args and isinstance(args, str): +- cmd.append(args) +- elif args and isinstance(args, list): +- cmd.extend(args) +- +- pkglist = util.expand_package_list('%s-%s', pkgs) +- cmd.extend(pkglist) +- +- # Allow the output of this to flow outwards (ie not be captured) +- util.subp(cmd, capture=False) +- +- def update_package_sources(self): +- self._runner.run("update-sources", self.package_command, +- ['refresh'], freq=PER_INSTANCE) ++class Distro(opensuse.Distro): ++ pass