From dcf5001c0a92862f023c79cdc0039eaeaffaa40a Mon Sep 17 00:00:00 2001 From: Garrett Holmstrom Date: Sep 23 2012 02:53:03 +0000 Subject: Fix hostname persistence --- diff --git a/cloud-init-0.7.0-hostname-refactor.patch b/cloud-init-0.7.0-hostname-refactor.patch new file mode 100644 index 0000000..f8789e1 --- /dev/null +++ b/cloud-init-0.7.0-hostname-refactor.patch @@ -0,0 +1,223 @@ +Index: trunk/cloudinit/distros/__init__.py +=================================================================== +--- trunk.orig/cloudinit/distros/__init__.py ++++ trunk/cloudinit/distros/__init__.py +@@ -48,6 +48,7 @@ class Distro(object): + __metaclass__ = abc.ABCMeta + default_user = None + default_user_groups = None ++ default_hostname_conf_file = '/etc/hostname' + + def __init__(self, name, cfg, paths): + self._paths = paths +@@ -95,14 +96,69 @@ class Distro(object): + def get_option(self, opt_name, default=None): + return self._cfg.get(opt_name, default) + +- @abc.abstractmethod + def set_hostname(self, hostname): ++ conf_file = self.get_option('hostname_conf_file', ++ default=self.default_hostname_conf_file) ++ out_fn = self._paths.join(False, conf_file) ++ self._write_hostname(hostname, out_fn) ++ if out_fn == conf_file: ++ # We only do this if we are running in non-adjusted root mode ++ LOG.debug("Setting hostname to %s", hostname) ++ util.subp(['hostname', hostname]) ++ ++ def update_hostname(self, hostname, prev_hostname_fn): ++ conf_file = self.get_option('hostname_conf_file', ++ default=self.default_hostname_conf_file) ++ hostname_prev = self._read_hostname(prev_hostname_fn) ++ read_fn = self._paths.join(True, conf_file) ++ hostname_in_conf = self._read_hostname(read_fn) ++ update_files = [] ++ if not hostname_prev or hostname_prev != hostname: ++ update_files.append(prev_hostname_fn) ++ if (not hostname_in_conf or ++ (hostname_in_conf == hostname_prev ++ and hostname_in_conf != hostname)): ++ write_fn = self._paths.join(False, conf_file) ++ update_files.append(write_fn) ++ for fn in update_files: ++ try: ++ self._write_hostname(hostname, fn) ++ except: ++ util.logexc(LOG, "Failed to write hostname %s to %s", ++ hostname, fn) ++ if (hostname_in_conf and hostname_prev and ++ hostname_in_conf != hostname_prev): ++ LOG.debug(("Hostname in %s differs from that in %s; assuming " ++ "hostname is user-maintained"), prev_hostname_fn, conf_file) ++ if conf_file in update_files: ++ # We only do this if we are running in non-adjusted root mode ++ LOG.debug("Setting hostname to %s", hostname) ++ util.subp(["hostname", hostname]) ++ ++ @abc.abstractmethod ++ def _write_hostname(self, hostname, filename): + raise NotImplementedError() + ++ def _write_bare_hostname(self, hostname, out_fn): ++ # "" gives trailing newline. ++ util.write_file(out_fn, "%s\n" % str(hostname), 0644) ++ + @abc.abstractmethod +- def update_hostname(self, hostname, prev_hostname_fn): ++ def _read_hostname(self, filename, default=None): + raise NotImplementedError() + ++ def _read_bare_hostname(self, filename, default=None): ++ contents = util.load_file(filename, quiet=True) ++ for line in contents.splitlines(): ++ c_pos = line.find("#") ++ # Handle inline comments ++ if c_pos != -1: ++ line = line[0:c_pos] ++ line_c = line.strip() ++ if line_c: ++ return line_c ++ return default ++ + @abc.abstractmethod + def package_command(self, cmd, args=None): + raise NotImplementedError() +Index: trunk/cloudinit/distros/debian.py +=================================================================== +--- trunk.orig/cloudinit/distros/debian.py ++++ trunk/cloudinit/distros/debian.py +@@ -57,56 +57,11 @@ class Distro(distros.Distro): + net_fn = self._paths.join(False, "/etc/network/interfaces") + util.write_file(net_fn, settings) + +- def set_hostname(self, hostname): +- out_fn = self._paths.join(False, "/etc/hostname") +- self._write_hostname(hostname, out_fn) +- if out_fn == '/etc/hostname': +- # Only do this if we are running in non-adjusted root mode +- LOG.debug("Setting hostname to %s", hostname) +- util.subp(['hostname', hostname]) +- + def _write_hostname(self, hostname, out_fn): +- # "" gives trailing newline. +- util.write_file(out_fn, "%s\n" % str(hostname), 0644) +- +- def update_hostname(self, hostname, prev_fn): +- hostname_prev = self._read_hostname(prev_fn) +- read_fn = self._paths.join(True, "/etc/hostname") +- hostname_in_etc = self._read_hostname(read_fn) +- update_files = [] +- if not hostname_prev or hostname_prev != hostname: +- update_files.append(prev_fn) +- if (not hostname_in_etc or +- (hostname_in_etc == hostname_prev and +- hostname_in_etc != hostname)): +- write_fn = self._paths.join(False, "/etc/hostname") +- update_files.append(write_fn) +- for fn in update_files: +- try: +- self._write_hostname(hostname, fn) +- except: +- util.logexc(LOG, "Failed to write hostname %s to %s", +- hostname, fn) +- if (hostname_in_etc and hostname_prev and +- hostname_in_etc != hostname_prev): +- LOG.debug(("%s differs from /etc/hostname." +- " Assuming user maintained hostname."), prev_fn) +- if "/etc/hostname" in update_files: +- # Only do this if we are running in non-adjusted root mode +- LOG.debug("Setting hostname to %s", hostname) +- util.subp(['hostname', hostname]) ++ return self._write_bare_hostname(hostname, out_fn) + + def _read_hostname(self, filename, default=None): +- contents = util.load_file(filename, quiet=True) +- for line in contents.splitlines(): +- c_pos = line.find("#") +- # Handle inline comments +- if c_pos != -1: +- line = line[0:c_pos] +- line_c = line.strip() +- if line_c: +- return line_c +- return default ++ return self._read_bare_hostname(filename, default=default) + + def _get_localhost_ip(self): + # Note: http://www.leonardoborda.com/blog/127-0-1-1-ubuntu-debian/ +Index: trunk/cloudinit/distros/fedora.py +=================================================================== +--- trunk.orig/cloudinit/distros/fedora.py ++++ trunk/cloudinit/distros/fedora.py +@@ -30,3 +30,10 @@ LOG = logging.getLogger(__name__) + class Distro(rhel.Distro): + distro_name = 'fedora' + default_user = 'ec2-user' ++ default_hostname_conf_file = '/etc/hostname' ++ ++ def _write_hostname(self, hostname, out_fn): ++ return self._write_bare_hostname(hostname, out_fn) ++ ++ def _read_hostname(self, filename, default=None): ++ return self._read_bare_hostname(filename, default=default) +Index: trunk/cloudinit/distros/rhel.py +=================================================================== +--- trunk.orig/cloudinit/distros/rhel.py ++++ trunk/cloudinit/distros/rhel.py +@@ -57,6 +57,7 @@ D_QUOTE_CHARS = { + + + class Distro(distros.Distro): ++ default_hostname_conf_file = '/etc/sysconfig/network' + + def __init__(self, name, cfg, paths): + distros.Distro.__init__(self, name, cfg, paths) +@@ -128,14 +129,6 @@ class Distro(distros.Distro): + if nameservers or searchservers: + self._write_resolve(nameservers, searchservers) + +- def set_hostname(self, hostname): +- out_fn = self._paths.join(False, '/etc/sysconfig/network') +- self._write_hostname(hostname, out_fn) +- if out_fn == '/etc/sysconfig/network': +- # Only do this if we are running in non-adjusted root mode +- LOG.debug("Setting hostname to %s", hostname) +- util.subp(['hostname', hostname]) +- + def apply_locale(self, locale, out_fn=None): + if not out_fn: + out_fn = self._paths.join(False, '/etc/sysconfig/i18n') +@@ -151,33 +144,6 @@ class Distro(distros.Distro): + w_contents = "\n".join(contents.write()) + util.write_file(out_fn, w_contents, 0644) + +- def update_hostname(self, hostname, prev_file): +- hostname_prev = self._read_hostname(prev_file) +- read_fn = self._paths.join(True, "/etc/sysconfig/network") +- hostname_in_sys = self._read_hostname(read_fn) +- update_files = [] +- if not hostname_prev or hostname_prev != hostname: +- update_files.append(prev_file) +- if (not hostname_in_sys or +- (hostname_in_sys == hostname_prev +- and hostname_in_sys != hostname)): +- write_fn = self._paths.join(False, "/etc/sysconfig/network") +- update_files.append(write_fn) +- for fn in update_files: +- try: +- self._write_hostname(hostname, fn) +- except: +- util.logexc(LOG, "Failed to write hostname %s to %s", +- hostname, fn) +- if (hostname_in_sys and hostname_prev and +- hostname_in_sys != hostname_prev): +- LOG.debug(("%s differs from /etc/sysconfig/network." +- " Assuming user maintained hostname."), prev_file) +- if "/etc/sysconfig/network" in update_files: +- # Only do this if we are running in non-adjusted root mode +- LOG.debug("Setting hostname to %s", hostname) +- util.subp(['hostname', hostname]) +- + def _read_hostname(self, filename, default=None): + (_exists, contents) = self._read_conf(filename) + if 'HOSTNAME' in contents: diff --git a/cloud-init.spec b/cloud-init.spec index 688710e..b7db61a 100644 --- a/cloud-init.spec +++ b/cloud-init.spec @@ -13,6 +13,9 @@ Source0: %{name}-%{version}-bzr659.tar.gz Source1: cloud-init-fedora.cfg Source2: cloud-init-README.fedora Patch0: cloud-init-0.7.0-fedora.patch +# Make Fedora use the same hostname-updating code as Debian (/etc/hostname) +# https://code.launchpad.net/~gholms/cloud-init/hostname-refactor/+merge/125869 +Patch1: cloud-init-0.7.0-hostname-refactor.patch BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -48,6 +51,7 @@ ssh keys and to let the user run various scripts. %prep %setup -q -n %{name}-%{version}-bzr659 %patch0 -p1 +%patch1 -p1 cp -p %{SOURCE2} README.fedora @@ -127,6 +131,7 @@ fi %changelog * Sat Sep 22 2012 Garrett Holmstrom - 0.7.0-0.2.bzr659 - Rebased against upstream rev 659 +- Fixed hostname persistence * Mon Sep 17 2012 Garrett Holmstrom - 0.7.0-0.1.bzr650 - Rebased against upstream rev 650