Merge lp:~gpadgett/cloud-init/ovirt into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Greg Padgett
Status: Merged
Merged at revision: 809
Proposed branch: lp:~gpadgett/cloud-init/ovirt
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 173 lines (+63/-22)
5 files modified
cloudinit/distros/rhel.py (+53/-20)
cloudinit/sources/DataSourceConfigDrive.py (+3/-0)
cloudinit/sources/DataSourceNoCloud.py (+3/-0)
cloudinit/util.py (+1/-0)
tests/unittests/test_datasource/test_configdrive.py (+3/-2)
To merge this branch: bzr merge lp:~gpadgett/cloud-init/ovirt
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+155634@code.launchpad.net

Description of the change

This branch contains fixes found while investigating integration of cloud-init into oVirt. They're in 3 categories:
 - compatibility with systemd configuration management (as used in Fedora 18)
 - workaround for a 2.6 kernel quirk which prevented 'blkid' from displaying /dev/sr0 in some cases
 - writing sysconfig files in typical convention, with a newline preceding EOF, to make some parsers happy

To post a comment you must log in.
Revision history for this message
Scott Moser (smoser) wrote :

this looks fine to me, the only question i have is over 'blkid' usage and /dev/sr0.
I have one concern. At one point I was just trying 'mount /dev/sr0' and expecting that to time out quickly, but it turned out that that was taking 18 seconds to time out in a VM with an empty cd-rom. (see revision 350).
   I just want to make sure that we're not going todo something similar here. I suspect not, but would like to make sure that you've verified that boot speed is not affected significantly by this.

Reguarding the systemd changes, I largely have to blindly trust you.
Maybe Josh can sanity check?

Revision history for this message
Greg Padgett (gpadgett) wrote :

Thanks Scott. I tested the blkid calls to existing-but-empty and non-existing /dev/srX devices and didn't see any delays. Not as methodically, but I also did plenty of reboots with and without attached media and speed seemed fine. This was all on Fedora 18, RHEL 6.4, and Ubuntu 12.04 LTS--if you can think of other versions or tests to run I'd be more than happy to try it out.

I'd welcome a systemd sanity check as well. So far it seems good based on my testing and the "Changes for System Administrators" section of the F18 manual. You/others may notice that the code manually manipulates the /etc/localtime symlink instead of using timedatectl--this was done to avoid a timeout (dbus-related?) and errors that happen if timedatectl is called during startup.

Revision history for this message
Joshua Harlow (harlowja) wrote :

Since I don't have access to RHEL7 yet I am hoping it works there.

Otherwise seems fine to me.

Revision history for this message
Greg Padgett (gpadgett) wrote :

> Since I don't have access to RHEL7 yet I am hoping it works there.

I'm hoping the same, I don't see a reason why it wouldn't.

> Otherwise seems fine to me.

Great, thanks.

Is there anything else I can do to help get this one in?

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'cloudinit/distros/rhel.py'
--- cloudinit/distros/rhel.py 2013-03-07 19:54:25 +0000
+++ cloudinit/distros/rhel.py 2013-03-26 22:14:53 +0000
@@ -47,8 +47,10 @@
47 # See: http://tiny.cc/6r99fw47 # See: http://tiny.cc/6r99fw
48 clock_conf_fn = "/etc/sysconfig/clock"48 clock_conf_fn = "/etc/sysconfig/clock"
49 locale_conf_fn = '/etc/sysconfig/i18n'49 locale_conf_fn = '/etc/sysconfig/i18n'
50 systemd_locale_conf_fn = '/etc/locale.conf'
50 network_conf_fn = "/etc/sysconfig/network"51 network_conf_fn = "/etc/sysconfig/network"
51 hostname_conf_fn = "/etc/sysconfig/network"52 hostname_conf_fn = "/etc/sysconfig/network"
53 systemd_hostname_conf_fn = "/etc/hostname"
52 network_script_tpl = '/etc/sysconfig/network-scripts/ifcfg-%s'54 network_script_tpl = '/etc/sysconfig/network-scripts/ifcfg-%s'
53 resolve_conf_fn = "/etc/resolv.conf"55 resolve_conf_fn = "/etc/resolv.conf"
54 tz_local_fn = "/etc/localtime"56 tz_local_fn = "/etc/localtime"
@@ -143,21 +145,36 @@
143 ]145 ]
144 if not exists:146 if not exists:
145 lines.insert(0, util.make_header())147 lines.insert(0, util.make_header())
146 util.write_file(fn, "\n".join(lines), 0644)148 util.write_file(fn, "\n".join(lines) + "\n", 0644)
149
150 def _dist_uses_systemd(self):
151 # Fedora 18 and RHEL 7 were the first adopters in their series
152 (dist, vers) = util.system_info()['dist'][:2]
153 major = (int)(vers.split('.')[0])
154 return ((dist.startswith('Red Hat Enterprise Linux') and major >= 7)
155 or (dist.startswith('Fedora') and major >= 18))
147156
148 def apply_locale(self, locale, out_fn=None):157 def apply_locale(self, locale, out_fn=None):
149 if not out_fn:158 if self._dist_uses_systemd():
150 out_fn = self.locale_conf_fn159 if not out_fn:
160 out_fn = self.systemd_locale_conf_fn
161 out_fn = self.systemd_locale_conf_fn
162 else:
163 if not out_fn:
164 out_fn = self.locale_conf_fn
151 locale_cfg = {165 locale_cfg = {
152 'LANG': locale,166 'LANG': locale,
153 }167 }
154 self._update_sysconfig_file(out_fn, locale_cfg)168 self._update_sysconfig_file(out_fn, locale_cfg)
155169
156 def _write_hostname(self, hostname, out_fn):170 def _write_hostname(self, hostname, out_fn):
157 host_cfg = {171 if self._dist_uses_systemd():
158 'HOSTNAME': hostname,172 util.subp(['hostnamectl', 'set-hostname', str(hostname)])
159 }173 else:
160 self._update_sysconfig_file(out_fn, host_cfg)174 host_cfg = {
175 'HOSTNAME': hostname,
176 }
177 self._update_sysconfig_file(out_fn, host_cfg)
161178
162 def _select_hostname(self, hostname, fqdn):179 def _select_hostname(self, hostname, fqdn):
163 # See: http://bit.ly/TwitgL180 # See: http://bit.ly/TwitgL
@@ -167,15 +184,25 @@
167 return hostname184 return hostname
168185
169 def _read_system_hostname(self):186 def _read_system_hostname(self):
170 return (self.network_conf_fn,187 if self._dist_uses_systemd():
171 self._read_hostname(self.network_conf_fn))188 host_fn = self.systemd_hostname_conf_fn
189 else:
190 host_fn = self.hostname_conf_fn
191 return (host_fn, self._read_hostname(host_fn))
172192
173 def _read_hostname(self, filename, default=None):193 def _read_hostname(self, filename, default=None):
174 (_exists, contents) = self._read_conf(filename)194 if self._dist_uses_systemd():
175 if 'HOSTNAME' in contents:195 (out, _err) = util.subp(['hostname'])
176 return contents['HOSTNAME']196 if len(out):
197 return out
198 else:
199 return default
177 else:200 else:
178 return default201 (_exists, contents) = self._read_conf(filename)
202 if 'HOSTNAME' in contents:
203 return contents['HOSTNAME']
204 else:
205 return default
179206
180 def _read_conf(self, fn):207 def _read_conf(self, fn):
181 exists = False208 exists = False
@@ -200,13 +227,19 @@
200 if not os.path.isfile(tz_file):227 if not os.path.isfile(tz_file):
201 raise RuntimeError(("Invalid timezone %s,"228 raise RuntimeError(("Invalid timezone %s,"
202 " no file found at %s") % (tz, tz_file))229 " no file found at %s") % (tz, tz_file))
203 # Adjust the sysconfig clock zone setting230 if self._dist_uses_systemd():
204 clock_cfg = {231 # Currently, timedatectl complains if invoked during startup
205 'ZONE': str(tz),232 # so for compatibility, create the link manually.
206 }233 util.del_file(self.tz_local_fn)
207 self._update_sysconfig_file(self.clock_conf_fn, clock_cfg)234 util.sym_link(tz_file, self.tz_local_fn)
208 # This ensures that the correct tz will be used for the system235 else:
209 util.copy(tz_file, self.tz_local_fn)236 # Adjust the sysconfig clock zone setting
237 clock_cfg = {
238 'ZONE': str(tz),
239 }
240 self._update_sysconfig_file(self.clock_conf_fn, clock_cfg)
241 # This ensures that the correct tz will be used for the system
242 util.copy(tz_file, self.tz_local_fn)
210243
211 def package_command(self, command, args=None, pkgs=None):244 def package_command(self, command, args=None, pkgs=None):
212 if pkgs is None:245 if pkgs is None:
213246
=== modified file 'cloudinit/sources/DataSourceConfigDrive.py'
--- cloudinit/sources/DataSourceConfigDrive.py 2013-03-07 21:27:47 +0000
+++ cloudinit/sources/DataSourceConfigDrive.py 2013-03-26 22:14:53 +0000
@@ -258,6 +258,9 @@
258 * labeled with 'config-2'258 * labeled with 'config-2'
259 """259 """
260260
261 # Query optical drive to get it in blkid cache for 2.6 kernels
262 util.find_devs_with(path="/dev/sr0")
263
261 by_fstype = (util.find_devs_with("TYPE=vfat") +264 by_fstype = (util.find_devs_with("TYPE=vfat") +
262 util.find_devs_with("TYPE=iso9660"))265 util.find_devs_with("TYPE=iso9660"))
263 by_label = util.find_devs_with("LABEL=config-2")266 by_label = util.find_devs_with("LABEL=config-2")
264267
=== modified file 'cloudinit/sources/DataSourceNoCloud.py'
--- cloudinit/sources/DataSourceNoCloud.py 2013-03-07 21:27:47 +0000
+++ cloudinit/sources/DataSourceNoCloud.py 2013-03-26 22:14:53 +0000
@@ -87,6 +87,9 @@
8787
88 label = self.ds_cfg.get('fs_label', "cidata")88 label = self.ds_cfg.get('fs_label', "cidata")
89 if label is not None:89 if label is not None:
90 # Query optical drive to get it in blkid cache for 2.6 kernels
91 util.find_devs_with(path="/dev/sr0")
92
90 fslist = util.find_devs_with("TYPE=vfat")93 fslist = util.find_devs_with("TYPE=vfat")
91 fslist.extend(util.find_devs_with("TYPE=iso9660"))94 fslist.extend(util.find_devs_with("TYPE=iso9660"))
9295
9396
=== modified file 'cloudinit/util.py'
--- cloudinit/util.py 2013-03-19 13:32:04 +0000
+++ cloudinit/util.py 2013-03-26 22:14:53 +0000
@@ -408,6 +408,7 @@
408 'release': platform.release(),408 'release': platform.release(),
409 'python': platform.python_version(),409 'python': platform.python_version(),
410 'uname': platform.uname(),410 'uname': platform.uname(),
411 'dist': platform.linux_distribution(),
411 }412 }
412413
413414
414415
=== modified file 'tests/unittests/test_datasource/test_configdrive.py'
--- tests/unittests/test_datasource/test_configdrive.py 2013-01-17 00:46:30 +0000
+++ tests/unittests/test_datasource/test_configdrive.py 2013-03-26 22:14:53 +0000
@@ -259,8 +259,9 @@
259 def test_find_candidates(self):259 def test_find_candidates(self):
260 devs_with_answers = {}260 devs_with_answers = {}
261261
262 def my_devs_with(criteria):262 def my_devs_with(*args, **kwargs):
263 return devs_with_answers[criteria]263 criteria = args[0] if len(args) else kwargs.pop('criteria', None)
264 return devs_with_answers.get(criteria, [])
264265
265 def my_is_partition(dev):266 def my_is_partition(dev):
266 return dev[-1] in "0123456789" and not dev.startswith("sr")267 return dev[-1] in "0123456789" and not dev.startswith("sr")