Accepting request 179244 from Base:System

- add the distro specific handler for openSUSE
  + patch openSUSEHandler.diff
- fix syntax in SLE handler
  + dict access uses [] not {}, duh (forwarded request 179074 from rjschwei)

OBS-URL: https://build.opensuse.org/request/show/179244
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/cloud-init?expand=0&rev=3
This commit is contained in:
Stephan Kulow 2013-06-18 08:29:23 +00:00 committed by Git OBS Bridge
parent 04e3dd1a0d
commit 5ee9623a83
12 changed files with 616 additions and 186 deletions

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:643b54792d0a4e6578678c6ac4cceab600a030539dc0d73575442713fc3e834c
size 102993

3
cloud-init-0.7.2.tar.bz2 Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cc5ab984596100f76e95c7a02dabb2ac7ce27cd2e46a590f793fca2afe121ab0
size 377139

View File

@ -1,3 +1,30 @@
-------------------------------------------------------------------
Sat Jun 15 10:40:42 UTC 2013 - rschweikert@suse.com
- add the distro specific handler for openSUSE
+ patch openSUSEHandler.diff
- fix syntax in SLE handler
+ dict access uses [] not {}, duh
-------------------------------------------------------------------
Fri Jun 14 00:57:18 UTC 2013 - rschweikert@suse.com
- add the distro specific handler for SLE
+ patch slesHandler.diff
-------------------------------------------------------------------
Wed Jun 5 15:12:52 UTC 2013 - rschweikert@suse.com
- update to version 0.7.2, see Changelog in source for fixes
- use the upstream sysvinit and systemd files
- remove all previously created patches
+ drop-MAAS-datasource.diff
+ drop-python27-only-code.diff
+ drop-ubuntu-default-username.diff
+ relative-authorized-keys-file.diff
- create a doc and test package to reduce size of main package
- add patch (fixupSysVinit.patch) to fix the upstream sysvinit LSB headers
-------------------------------------------------------------------
Mon May 6 14:50:17 UTC 2013 - jdsn@suse.de

View File

@ -1,74 +0,0 @@
#!/bin/sh
# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
# Author: J. Daniel Schmidt <jdsn@suse.de>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; version 2.1 of the License
#
# /etc/init.d/cloud-init
# and its symbolic link
# /usr/sbin/rccloud-init
#
#
### BEGIN INIT INFO
# Provides: cloud-init
# Required-Start: $network $syslog $remote_fs $named
# Should-Start: $time
# Required-Stop: $null
# Should-Stop: $null
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Short-Description: Starts the cloud-init process
# Description: Starts the cloud-init process that fetches
# the configuration for the system from a cloud controller.
### END INIT INFO
# Check for missing binaries (stale symlinks should not happen)
# Note: Special treatment of stop for LSB conformance
CLOUDINIT_BIN=/usr/bin/cloud-init
test -x $CLOUDINIT_BIN || { echo "$CLOUDINIT_BIN not installed";
if [ "$1" = "stop" ]; then exit 0;
else exit 5; fi; }
# Check for existence of needed config file and read it
#CLOUDINIT_CONFIG=/etc/cloud/cloud.cfg
#test -r $CLOUDINIT_CONFIG || { echo "$CLOUDINIT_CONFIG not existing";
# if [ "$1" = "stop" ]; then exit 0;
# else exit 6; fi; }
. /etc/rc.status
rc_reset
case "$1" in
start)
echo -n "Starting cloud-init "
startproc $CLOUDINIT_BIN start
rc_status -v
;;
stop)
echo -n "Shutting down cloud-init "
killall `basename $CLOUDINIT_BIN`
rc_status -v
;;
restart)
$0 stop
$0 start
rc_status
;;
status)
echo -n "Checking for service cloud-init"
[ -e /root/.ssh/authorized_keys ]
rc_status -v
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
rc_exit

View File

@ -19,7 +19,7 @@
%define component cloud-init
Name: %{component}
Version: 0.6.3
Version: 0.7.2
Release: 0
Summary: Cloud node initialization tool
License: GPL-3.0
@ -27,14 +27,13 @@ Group: System/Management
Url: http://launchpad.net/cloud-init/
Source0: %{component}-%{version}.tar.bz2
Source1: cloud.cfg.suse
Source2: cloud-init.init
Patch0: drop-MAAS-datasource.diff
Patch1: drop-python27-only-code.diff
Patch2: drop-ubuntu-default-username.diff
# backport fix from upstream version 0.7.1 for bug bnc#818306
Patch3: relative-authorized-keys-file.diff
Patch0: fixupSysVinit.patch
Patch1: slesHandler.diff
Patch2: openSUSEHandler.diff
Requires: python-boto
Requires: python-cheetah
Requires: python-prettytable
Requires: python-requests
Requires: python-xml
Requires: python-yaml
BuildRequires: filesystem
@ -51,36 +50,54 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildArch: noarch
%endif
%if 0%{?suse_version} && 0%{?suse_version} <= 1210
%define initsys sysvinit
%else
%define initsys systemd
%endif
%{py_requires}
%description
Cloud-init is an init script that initializes a cloud node (VM)
according to the fetched configuration data from the admin node.
Authors:
--------
Scott Moser <scott.moser@canonical.com>
%package doc
Summary: Cloud node initialization tool doc
Group: System/Management
Recommends: cloud-init = %version
%description doc
Documentation and examples for cloud-init tools
%package test
Summary: Cloud node initialization tool tests
Group: System/Management
Requires: cloud-init = %version
%description test
Unit tests for the cloud-init tools
%prep
%setup -q -n %{component}-%{version}
%patch0 -p1
%if 0%{?suse_version} <= 1130
%patch0
%patch1 -p1
%patch2 -p1
%if 0%{?suse_version} <= 1130
# disable ecdsa for SLE 11 (not available)
echo "ssh_genkeytypes: ['rsa', 'dsa']" >> %{S:1}
%endif
%patch2 -p1
%patch3 -p1
%build
python setup.py build
%install
python setup.py install --skip-build --root=%{buildroot} --prefix=%{_prefix} --record-rpm=INSTALLED_FILES --install-lib=%{python_sitelib}
python setup.py install --skip-build --root=%{buildroot} --prefix=%{_prefix} --record-rpm=INSTALLED_FILES --install-lib=%{python_sitelib} --init-system=%{initsys}
find %{buildroot} \( -name .gitignore -o -name .placeholder \) -delete
mv %{buildroot}/%{_sysconfdir}/init %{buildroot}/%{_sysconfdir}/cloud/
# from debian install script
for x in "%{buildroot}%{_bindir}/"*.py; do
[ -f "${x}" ] && mv "${x}" "${x%.py}"
@ -90,13 +107,22 @@ mkdir -p %{buildroot}%{_localstatedir}/lib/cloud
mkdir -p %{buildroot}%{_defaultdocdir}
mv %{buildroot}/usr/share/doc/%{component} %{buildroot}%{docdir}
cp -a %{S:1} %{buildroot}/%{_sysconfdir}/cloud/cloud.cfg
mkdir -p %{buildroot}/%{_initddir} %{buildroot}/%{_sbindir}
cp -a %SOURCE2 %{buildroot}/%{_initddir}/%{component}
ln -s %{_initddir}/%{component} %{buildroot}/%{_sbindir}/rc%{component}
# remove debian/ubuntu specific profile.d file (bnc#779553)
rm -f %{buildroot}%{_sysconfdir}/profile.d/Z99-cloud-locale-test.sh
# move sysvinit scripts into the "right" place
%if 0%{?suse_version} && 0%{?suse_version} <= 1210
mkdir -p %{buildroot}/%{_initddir}
mv %{buildroot}%{_sysconfdir}/rc.d/init.d/* %{buildroot}%{_initddir}/
mkdir -p %{buildroot}/%{_sbindir}
pushd "%{buildroot}%{_initddir}"
for iniF in *; do
ln -s "%{_initddir}/${iniF}" "%{buildroot}/%{_sbindir}/rc${iniF}"
done
popd
%endif
# remove duplicate files
%if 0%{?suse_version}
%fdupes %{buildroot}%{python_sitelib}
@ -108,14 +134,26 @@ rm -f %{buildroot}%{_sysconfdir}/profile.d/Z99-cloud-locale-test.sh
%{python_sitelib}/cloud_init*egg-info
%{_bindir}/cloud-init
%{_bindir}/cloud-init-per
%{_bindir}/cloud-init-cfg
%{_sbindir}/rc%{component}
%config(noreplace) %{_sysconfdir}/cloud/
%doc %{docdir}
/usr/lib/cloud-init
%attr(0755, root, root) %{_initddir}/%{component}
%if 0%{?suse_version} && 0%{?suse_version} <= 1210
%{_sbindir}/rc*
%attr(0755, root, root) %{_initddir}/*
%else
%dir /etc/systemd
%dir /etc/systemd/system
%{_sysconfdir}/systemd/system/*
%endif
%dir %attr(0755, root, root) %{_localstatedir}/lib/cloud
%files doc
%defattr(-,root,root)
%doc %{docdir}
%files test
%defattr(-,root,root)
%{python_sitelib}/tests
%postun
%insserv_cleanup

View File

@ -1,13 +0,0 @@
Index: cloud-init-0.6.3/cloudinit/__init__.py
===================================================================
--- cloud-init-0.6.3.orig/cloudinit/__init__.py
+++ cloud-init-0.6.3/cloudinit/__init__.py
@@ -29,7 +29,7 @@ cfg_env_name = "CLOUD_CFG"
cfg_builtin = """
log_cfgs: []
-datasource_list: ["NoCloud", "ConfigDrive", "OVF", "MAAS", "Ec2", "CloudStack"]
+datasource_list: ["NoCloud", "ConfigDrive", "OVF", "Ec2", "CloudStack"]
def_log_file: /var/log/cloud-init.log
syslog_fix_perms: syslog:adm
"""

View File

@ -1,22 +0,0 @@
Index: cloud-init-0.6.3/cloudinit/netinfo.py
===================================================================
--- cloud-init-0.6.3.orig/cloudinit/netinfo.py
+++ cloud-init-0.6.3/cloudinit/netinfo.py
@@ -24,7 +24,7 @@ import subprocess
def netdev_info(empty=""):
fields = ("hwaddr", "addr", "bcast", "mask")
- ifcfg_out = str(subprocess.check_output(["ifconfig", "-a"]))
+ ifcfg_out = str(subprocess.Popen(["ifconfig", "-a"], stdout=subprocess.PIPE).communicate()[0])
devs = {}
for line in ifcfg_out.splitlines():
if len(line) == 0:
@@ -70,7 +70,7 @@ def netdev_info(empty=""):
def route_info():
- route_out = str(subprocess.check_output(["route", "-n"]))
+ route_out = str(subprocess.Popen(["route", "-n"], stdout=subprocess.PIPE).communicate()[0])
routes = []
for line in route_out.splitlines()[1:]:
if not line:

View File

@ -1,39 +0,0 @@
Index: cloud-init-0.6.3/cloudinit/CloudConfig/cc_byobu.py
===================================================================
--- cloud-init-0.6.3.orig/cloudinit/CloudConfig/cc_byobu.py
+++ cloud-init-0.6.3/cloudinit/CloudConfig/cc_byobu.py
@@ -55,7 +55,7 @@ def handle(_name, cfg, _cloud, log, args
shcmd = ""
if mod_user:
- user = util.get_cfg_option_str(cfg, "user", "ubuntu")
+ user = util.get_cfg_option_str(cfg, "user", "root")
shcmd += " sudo -Hu \"%s\" byobu-launcher-%s" % (user, bl_inst)
shcmd += " || X=$(($X+1)); "
if mod_sys:
Index: cloud-init-0.6.3/cloudinit/CloudConfig/cc_set_passwords.py
===================================================================
--- cloud-init-0.6.3.orig/cloudinit/CloudConfig/cc_set_passwords.py
+++ cloud-init-0.6.3/cloudinit/CloudConfig/cc_set_passwords.py
@@ -44,7 +44,7 @@ def handle(_name, cfg, _cloud, log, args
expire = util.get_cfg_option_bool(chfg, 'expire', expire)
if not plist and password:
- user = util.get_cfg_option_str(cfg, "user", "ubuntu")
+ user = util.get_cfg_option_str(cfg, "user", "root")
plist = "%s:%s" % (user, password)
errors = []
Index: cloud-init-0.6.3/cloudinit/CloudConfig/cc_ssh_import_id.py
===================================================================
--- cloud-init-0.6.3.orig/cloudinit/CloudConfig/cc_ssh_import_id.py
+++ cloud-init-0.6.3/cloudinit/CloudConfig/cc_ssh_import_id.py
@@ -30,7 +30,7 @@ def handle(_name, cfg, _cloud, log, args
if len(args) > 1:
ids = args[1:]
else:
- user = util.get_cfg_option_str(cfg, "user", "ubuntu")
+ user = util.get_cfg_option_str(cfg, "user", "root")
ids = util.get_cfg_option_list_or_str(cfg, "ssh_import_id", [])
if len(ids) == 0:

52
fixupSysVinit.patch Normal file
View File

@ -0,0 +1,52 @@
--- sysvinit/cloud-config.orig
+++ sysvinit/cloud-config
@@ -27,8 +27,8 @@
# Provides: cloud-config
# Required-Start: cloud-init cloud-init-local
# Should-Start: $time
-# Required-Stop:
-# Should-Stop:
+# Required-Stop: $null
+# Should-Stop: $null
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The config cloud-init job
--- sysvinit/cloud-final.orig
+++ sysvinit/cloud-final
@@ -27,8 +27,8 @@
# Provides: cloud-final
# Required-Start: $all cloud-config
# Should-Start: $time
-# Required-Stop:
-# Should-Stop:
+# Required-Stop: $null
+# Should-Stop: $null
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The final cloud-init job
--- sysvinit/cloud-init.orig
+++ sysvinit/cloud-init
@@ -27,8 +27,8 @@
# Provides: cloud-init
# Required-Start: $local_fs $network $named $remote_fs cloud-init-local
# Should-Start: $time
-# Required-Stop:
-# Should-Stop:
+# Required-Stop: $null
+# Should-Stop: $null
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The initial cloud-init job (net and fs contingent)
--- sysvinit/cloud-init-local.orig
+++ sysvinit/cloud-init-local
@@ -27,8 +27,8 @@
# Provides: cloud-init-local
# Required-Start: $local_fs $remote_fs
# Should-Start: $time
-# Required-Stop:
-# Should-Stop:
+# Required-Stop: $null
+# Should-Stop: $null
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The initial cloud-init job (local fs contingent)

90
openSUSEHandler.diff Normal file
View File

@ -0,0 +1,90 @@
diff -urN cloud-init-0.7.2/cloudinit/distros/opensuse.py cloud-init-0.7.2.os/cloudinit/distros/opensuse.py
--- cloud-init-0.7.2/cloudinit/distros/opensuse.py 1969-12-31 19:00:00.000000000 -0500
+++ cloud-init-0.7.2.os/cloudinit/distros/opensuse.py 2013-06-15 06:26:15.312348359 -0400
@@ -0,0 +1,86 @@
+# vi: ts=4 expandtab
+#
+# Copyright (C) 2013 SUSE LLC
+#
+# Author: Robert Schweikert <rjschwei@suse.com>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+import os
+
+from cloudinit.distros import sles
+
+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) = self._read_conf(filename)
+ if 'HOSTNAME' in contents:
+ return contents['HOSTNAME']
+ else:
+ return default
+
+

View File

@ -1,13 +0,0 @@
Index: cloud-init-0.6.3/cloudinit/SshUtil.py
===================================================================
--- cloud-init-0.6.3.orig/cloudinit/SshUtil.py
+++ cloud-init-0.6.3/cloudinit/SshUtil.py
@@ -155,6 +155,8 @@ def setup_user_keys(keys, user, key_pref
akeys = ssh_cfg.get("AuthorizedKeysFile", "%h/.ssh/authorized_keys")
akeys = akeys.replace("%h", pwent.pw_dir)
akeys = akeys.replace("%u", user)
+ if not akeys.startswith('/'):
+ akeys = os.path.join(pwent.pw_dir, akeys)
authorized_keys = akeys
except Exception:
authorized_keys = '%s/.ssh/authorized_keys' % pwent.pw_dir

384
slesHandler.diff Normal file
View File

@ -0,0 +1,384 @@
diff -urN cloud-init-0.7.2.orig/cloudinit/config/cc_resolv_conf.py cloud-init-0.7.2/cloudinit/config/cc_resolv_conf.py
--- cloud-init-0.7.2.orig/cloudinit/config/cc_resolv_conf.py 2013-05-15 16:48:22.000000000 -0400
+++ cloud-init-0.7.2/cloudinit/config/cc_resolv_conf.py 2013-06-13 19:13:57.269300572 -0400
@@ -53,7 +53,7 @@
frequency = PER_INSTANCE
-distros = ['fedora', 'rhel']
+distros = ['fedora', 'opensuse', 'rhel', 'sles']
def generate_resolv_conf(cloud, log, params):
diff -urN cloud-init-0.7.2.orig/cloudinit/distros/__init__.py cloud-init-0.7.2/cloudinit/distros/__init__.py
--- cloud-init-0.7.2.orig/cloudinit/distros/__init__.py 2013-05-15 16:48:22.000000000 -0400
+++ cloud-init-0.7.2/cloudinit/distros/__init__.py 2013-06-13 19:23:03.874975271 -0400
@@ -38,7 +38,8 @@
OSFAMILIES = {
'debian': ['debian', 'ubuntu'],
- 'redhat': ['fedora', 'rhel']
+ 'redhat': ['fedora', 'rhel'],
+ 'suse' : ['opensuse', 'sles']
}
LOG = logging.getLogger(__name__)
diff -urN cloud-init-0.7.2.orig/cloudinit/distros/sles.py cloud-init-0.7.2/cloudinit/distros/sles.py
--- cloud-init-0.7.2.orig/cloudinit/distros/sles.py 1969-12-31 19:00:00.000000000 -0500
+++ cloud-init-0.7.2/cloudinit/distros/sles.py 2013-06-13 19:00:56.837634255 -0400
@@ -0,0 +1,212 @@
+# vi: ts=4 expandtab
+#
+# Copyright (C) 2013 SUSE LLC
+#
+# Author: Robert Schweikert <rjschwei@suse.com>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+import os
+
+from cloudinit import distros
+
+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(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'
+ tz_zone_dir = '/usr/share/zoneinfo'
+
+ 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 _adjust_resolve(self, dns_servers, search_servers):
+ try:
+ r_conf = ResolvConf(util.load_file(self.resolve_conf_fn))
+ r_conf.parse()
+ except IOError:
+ util.logexc(LOG,
+ "Failed at parsing %s reverting to an empty instance",
+ self.resolve_conf_fn)
+ r_conf = ResolvConf('')
+ r_conf.parse()
+ if dns_servers:
+ for s in dns_servers:
+ try:
+ r_conf.add_nameserver(s)
+ except ValueError:
+ util.logexc(LOG, "Failed at adding nameserver %s", s)
+ if search_servers:
+ for s in search_servers:
+ try:
+ r_conf.add_search_domain(s)
+ except ValueError:
+ util.logexc(LOG, "Failed at adding search domain %s", s)
+ util.write_file(self.resolve_conf_fn, str(r_conf), 0644)
+
+ def _write_network(self, settings):
+ # Convert debian settings to ifcfg format
+ entries = 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'
+ 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:
+ self._adjust_resolve(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,
+ }
+ util.update_sysconfig_file(out_fn, locale_cfg)
+
+ def _write_hostname(self, hostname, out_fn):
+ 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):
+ (_exists, contents) = self._read_conf(filename)
+ if 'HOSTNAME' in contents:
+ return contents['HOSTNAME']
+ else:
+ return default
+
+ def _read_conf(self, fn):
+ exists = False
+ try:
+ contents = util.load_file(fn).splitlines()
+ exists = True
+ except IOError:
+ contents = []
+ return (exists,
+ SysConf(contents))
+
+ 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):
+ # TODO(harlowja): move this code into
+ # the parent distro...
+ tz_file = os.path.join(self.tz_zone_dir, str(tz))
+ if not os.path.isfile(tz_file):
+ raise RuntimeError(("Invalid timezone %s,"
+ " no file found at %s") % (tz, tz_file))
+ # Adjust the sysconfig clock zone setting
+ clock_cfg = {
+ 'TIMEZONE': str(tz),
+ }
+ 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('-t')
+ # Do not check the keys, we assume that the initial repos configured
+ # in the image can be trusted
+ cmd.append('--no-gpg-checks')
+
+ # 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)
+
+
diff -urN cloud-init-0.7.2.orig/cloudinit/util.py cloud-init-0.7.2/cloudinit/util.py
--- cloud-init-0.7.2.orig/cloudinit/util.py 2013-05-15 16:48:22.000000000 -0400
+++ cloud-init-0.7.2/cloudinit/util.py 2013-06-13 19:27:57.877749273 -0400
@@ -1744,3 +1744,110 @@
mountinfo_path = '/proc/%s/mountinfo' % os.getpid()
lines = load_file(mountinfo_path).splitlines()
return parse_mount_info(path, lines, log)
+
+def translate_network(settings):
+ # Translate Debian based distro interface blobs as given in
+ # /etc/network/interfaces to an equivalent format for distributions
+ # that use ifcfg-* style (RedHat and SUSE). (copied from rhel.py)
+ # Get the standard cmd, args from the ubuntu format
+ entries = []
+ for line in settings.splitlines():
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ split_up = line.split(None, 1)
+ if len(split_up) <= 1:
+ continue
+ entries.append(split_up)
+ # Figure out where each iface section is
+ ifaces = []
+ consume = {}
+ for (cmd, args) in entries:
+ if cmd == 'iface':
+ if consume:
+ ifaces.append(consume)
+ consume = {}
+ consume[cmd] = args
+ else:
+ consume[cmd] = args
+ # Check if anything left over to consume
+ absorb = False
+ for (cmd, args) in consume.iteritems():
+ if cmd == 'iface':
+ absorb = True
+ if absorb:
+ ifaces.append(consume)
+ # Now translate
+ real_ifaces = {}
+ for info in ifaces:
+ if 'iface' not in info:
+ continue
+ iface_details = info['iface'].split(None)
+ dev_name = None
+ if len(iface_details) >= 1:
+ dev = iface_details[0].strip().lower()
+ if dev:
+ dev_name = dev
+ if not dev_name:
+ continue
+ iface_info = {}
+ if len(iface_details) >= 3:
+ proto_type = iface_details[2].strip().lower()
+ # Seems like this can be 'loopback' which we don't
+ # really care about
+ if proto_type in ['dhcp', 'static']:
+ iface_info['bootproto'] = proto_type
+ # These can just be copied over
+ for k in ['netmask', 'address', 'gateway', 'broadcast']:
+ if k in info:
+ val = info[k].strip().lower()
+ if val:
+ iface_info[k] = val
+ # Name server info provided??
+ if 'dns-nameservers' in info:
+ iface_info['dns-nameservers'] = info['dns-nameservers'].split()
+ # Name server search info provided??
+ if 'dns-search' in info:
+ iface_info['dns-search'] = info['dns-search'].split()
+ # Is any mac address spoofing going on??
+ if 'hwaddress' in info:
+ hw_info = info['hwaddress'].lower().strip()
+ hw_split = hw_info.split(None, 1)
+ if len(hw_split) == 2 and hw_split[0].startswith('ether'):
+ hw_addr = hw_split[1]
+ if hw_addr:
+ iface_info['hwaddress'] = hw_addr
+ real_ifaces[dev_name] = iface_info
+ # Check for those that should be started on boot via 'auto'
+ for (cmd, args) in entries:
+ if cmd == 'auto':
+ # Seems like auto can be like 'auto eth0 eth0:1' so just get the
+ # first part out as the device name
+ args = args.split(None)
+ if not args:
+ continue
+ dev_name = args[0].strip().lower()
+ if dev_name in real_ifaces:
+ real_ifaces[dev_name]['auto'] = True
+ return real_ifaces
+
+def update_sysconfig_file(self, fn, adjustments, allow_empty=False):
+ if not adjustments:
+ return
+ (exists, contents) = self._read_conf(fn)
+ updated_am = 0
+ for (k, v) in adjustments.items():
+ if v is None:
+ continue
+ v = str(v)
+ if len(v) == 0 and not allow_empty:
+ continue
+ contents[k] = v
+ updated_am += 1
+ if updated_am:
+ lines = [
+ str(contents),
+ ]
+ if not exists:
+ lines.insert(0, make_header())
+ write_file(fn, "\n".join(lines) + "\n", 0644)
diff -urN cloud-init-0.7.2.orig/templates/hosts.suse.tmpl cloud-init-0.7.2/templates/hosts.suse.tmpl
--- cloud-init-0.7.2.orig/templates/hosts.suse.tmpl 1969-12-31 19:00:00.000000000 -0500
+++ cloud-init-0.7.2/templates/hosts.suse.tmpl 2013-06-13 19:26:00.120234961 -0400
@@ -0,0 +1,25 @@
+#*
+ This file /etc/cloud/templates/hosts.suse.tmpl is only utilized
+ if enabled in cloud-config. Specifically, in order to enable it
+ you need to add the following to config:
+ manage_etc_hosts: True
+*#
+# Your system has configured 'manage_etc_hosts' as True.
+# As a result, if you wish for changes to this file to persist
+# then you will need to either
+# a.) make changes to the master file in /etc/cloud/templates/hosts.suse.tmpl
+# b.) change or remove the value of 'manage_etc_hosts' in
+# /etc/cloud/cloud.cfg or cloud-config from user-data
+#
+# The following lines are desirable for IPv4 capable hosts
+127.0.0.1 localhost
+
+# The following lines are desirable for IPv6 capable hosts
+::1 localhost ipv6-localhost ipv6-loopback
+fe00::0 ipv6-localnet
+
+ff00::0 ipv6-mcastprefix
+ff02::1 ipv6-allnodes
+ff02::2 ipv6-allrouters
+ff02::3 ipv6-allhosts
+