summaryrefslogtreecommitdiff
path: root/cloudinit
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit')
-rw-r--r--cloudinit/config/cc_set_hostname.py10
-rw-r--r--cloudinit/config/cc_update_hostname.py8
-rw-r--r--cloudinit/distros/__init__.py58
-rw-r--r--cloudinit/distros/debian.py4
-rw-r--r--cloudinit/distros/rhel.py25
-rw-r--r--cloudinit/stages.py31
6 files changed, 103 insertions, 33 deletions
diff --git a/cloudinit/config/cc_set_hostname.py b/cloudinit/config/cc_set_hostname.py
index b0f27ebf..2b32fc94 100644
--- a/cloudinit/config/cc_set_hostname.py
+++ b/cloudinit/config/cc_set_hostname.py
@@ -27,9 +27,11 @@ def handle(name, cfg, cloud, log, _args):
" not setting the hostname in module %s"), name)
return
- (hostname, _fqdn) = util.get_hostname_fqdn(cfg, cloud)
+ (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
try:
- log.debug("Setting hostname to %s", hostname)
- cloud.distro.set_hostname(hostname)
+ log.debug("Setting the hostname to %s (%s)", fqdn, hostname)
+ cloud.distro.set_hostname(hostname, fqdn)
except Exception:
- util.logexc(log, "Failed to set hostname to %s", hostname)
+ util.logexc(log, "Failed to set the hostname to %s (%s)",
+ fqdn, hostname)
+ raise
diff --git a/cloudinit/config/cc_update_hostname.py b/cloudinit/config/cc_update_hostname.py
index 1d6679ea..52225cd8 100644
--- a/cloudinit/config/cc_update_hostname.py
+++ b/cloudinit/config/cc_update_hostname.py
@@ -32,10 +32,12 @@ def handle(name, cfg, cloud, log, _args):
" not updating the hostname in module %s"), name)
return
- (hostname, _fqdn) = util.get_hostname_fqdn(cfg, cloud)
+ (hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
try:
prev_fn = os.path.join(cloud.get_cpath('data'), "previous-hostname")
- cloud.distro.update_hostname(hostname, prev_fn)
+ log.debug("Updating hostname to %s (%s)", fqdn, hostname)
+ cloud.distro.update_hostname(hostname, fqdn, prev_fn)
except Exception:
- util.logexc(log, "Failed to set the hostname to %s", hostname)
+ util.logexc(log, "Failed to update the hostname to %s (%s)",
+ fqdn, hostname)
raise
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
index 869540d2..d2cb0a8b 100644
--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -58,11 +58,11 @@ class Distro(object):
return self._cfg.get(opt_name, default)
@abc.abstractmethod
- def set_hostname(self, hostname):
+ def set_hostname(self, hostname, fqdn=None):
raise NotImplementedError()
@abc.abstractmethod
- def update_hostname(self, hostname, prev_hostname_fn):
+ def update_hostname(self, hostname, fqdn, prev_hostname_fn):
raise NotImplementedError()
@abc.abstractmethod
@@ -81,7 +81,7 @@ class Distro(object):
def _get_arch_package_mirror_info(self, arch=None):
mirror_info = self.get_option("package_mirrors", [])
- if arch == None:
+ if not arch:
arch = self.get_primary_arch()
return _get_arch_package_mirror_info(mirror_info, arch)
@@ -283,8 +283,10 @@ class Distro(object):
# Ensure the dir is included and that
# it actually exists as a directory
sudoers_contents = ''
+ base_exists = False
if os.path.exists(sudo_base):
sudoers_contents = util.load_file(sudo_base)
+ base_exists = True
found_include = False
for line in sudoers_contents.splitlines():
line = line.strip()
@@ -299,18 +301,24 @@ class Distro(object):
found_include = True
break
if not found_include:
- sudoers_contents += "\n#includedir %s\n" % (path)
try:
- if not os.path.exists(sudo_base):
+ if not base_exists:
+ lines = [('# See sudoers(5) for more information'
+ ' on "#include" directives:'), '',
+ '# Added by cloud-init',
+ "#includedir %s" % (path), '']
+ sudoers_contents = "\n".join(lines)
util.write_file(sudo_base, sudoers_contents, 0440)
else:
- with open(sudo_base, 'a') as f:
- f.write(sudoers_contents)
- LOG.debug("added '#includedir %s' to %s" % (path, sudo_base))
+ lines = ['', '# Added by cloud-init',
+ "#includedir %s" % (path), '']
+ sudoers_contents = "\n".join(lines)
+ util.append_file(sudo_base, sudoers_contents)
+ LOG.debug("Added '#includedir %s' to %s" % (path, sudo_base))
except IOError as e:
util.logexc(LOG, "Failed to write %s" % sudo_base, e)
raise e
- util.ensure_dir(path, 0755)
+ util.ensure_dir(path, 0750)
def write_sudo_rules(self,
user,
@@ -425,12 +433,36 @@ def _get_arch_package_mirror_info(package_mirrors, arch):
# is the standard form used in the rest
# of cloud-init
def _normalize_groups(grp_cfg):
- if isinstance(grp_cfg, (str, basestring, list)):
+ if isinstance(grp_cfg, (str, basestring)):
+ grp_cfg = grp_cfg.strip().split(",")
+ if isinstance(grp_cfg, (list)):
c_grp_cfg = {}
- for i in util.uniq_merge(grp_cfg):
- c_grp_cfg[i] = []
+ for i in grp_cfg:
+ if isinstance(i, (dict)):
+ for k, v in i.items():
+ if k not in c_grp_cfg:
+ if isinstance(v, (list)):
+ c_grp_cfg[k] = list(v)
+ elif isinstance(v, (basestring, str)):
+ c_grp_cfg[k] = [v]
+ else:
+ raise TypeError("Bad group member type %s" %
+ util.obj_name(v))
+ else:
+ if isinstance(v, (list)):
+ c_grp_cfg[k].extend(v)
+ elif isinstance(v, (basestring, str)):
+ c_grp_cfg[k].append(v)
+ else:
+ raise TypeError("Bad group member type %s" %
+ util.obj_name(v))
+ elif isinstance(i, (str, basestring)):
+ if i not in c_grp_cfg:
+ c_grp_cfg[i] = []
+ else:
+ raise TypeError("Unknown group name type %s" %
+ util.obj_name(i))
grp_cfg = c_grp_cfg
-
groups = {}
if isinstance(grp_cfg, (dict)):
for (grp_name, grp_members) in grp_cfg.items():
diff --git a/cloudinit/distros/debian.py b/cloudinit/distros/debian.py
index cc7e53a0..ed4070b4 100644
--- a/cloudinit/distros/debian.py
+++ b/cloudinit/distros/debian.py
@@ -67,7 +67,7 @@ class Distro(distros.Distro):
else:
return distros.Distro._bring_up_interfaces(self, device_names)
- def set_hostname(self, hostname):
+ def set_hostname(self, hostname, fqdn=None):
self._write_hostname(hostname, "/etc/hostname")
LOG.debug("Setting hostname to %s", hostname)
util.subp(['hostname', hostname])
@@ -76,7 +76,7 @@ class Distro(distros.Distro):
# "" gives trailing newline.
util.write_file(out_fn, "%s\n" % str(hostname), 0644)
- def update_hostname(self, hostname, prev_fn):
+ def update_hostname(self, hostname, fqdn, prev_fn):
hostname_prev = self._read_hostname(prev_fn)
hostname_in_etc = self._read_hostname("/etc/hostname")
update_files = []
diff --git a/cloudinit/distros/rhel.py b/cloudinit/distros/rhel.py
index bf3c18d2..e4c27216 100644
--- a/cloudinit/distros/rhel.py
+++ b/cloudinit/distros/rhel.py
@@ -146,8 +146,13 @@ class Distro(distros.Distro):
lines.insert(0, _make_header())
util.write_file(fn, "\n".join(lines), 0644)
- def set_hostname(self, hostname):
- self._write_hostname(hostname, '/etc/sysconfig/network')
+ def set_hostname(self, hostname, fqdn=None):
+ # See: http://bit.ly/TwitgL
+ # Should be fqdn if we can use it
+ sysconfig_hostname = fqdn
+ if not sysconfig_hostname:
+ sysconfig_hostname = hostname
+ self._write_hostname(sysconfig_hostname, '/etc/sysconfig/network')
LOG.debug("Setting hostname to %s", hostname)
util.subp(['hostname', hostname])
@@ -165,28 +170,32 @@ class Distro(distros.Distro):
}
self._update_sysconfig_file(out_fn, host_cfg)
- def update_hostname(self, hostname, prev_file):
+ def update_hostname(self, hostname, fqdn, prev_file):
+ # See: http://bit.ly/TwitgL
+ # Should be fqdn if we can use it
+ sysconfig_hostname = fqdn
+ if not sysconfig_hostname:
+ sysconfig_hostname = hostname
hostname_prev = self._read_hostname(prev_file)
hostname_in_sys = self._read_hostname("/etc/sysconfig/network")
update_files = []
- if not hostname_prev or hostname_prev != hostname:
+ if not hostname_prev or hostname_prev != sysconfig_hostname:
update_files.append(prev_file)
if (not hostname_in_sys or
(hostname_in_sys == hostname_prev
- and hostname_in_sys != hostname)):
+ and hostname_in_sys != sysconfig_hostname)):
update_files.append("/etc/sysconfig/network")
for fn in update_files:
try:
- self._write_hostname(hostname, fn)
+ self._write_hostname(sysconfig_hostname, fn)
except:
util.logexc(LOG, "Failed to write hostname %s to %s",
- hostname, fn)
+ sysconfig_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])
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
index 4ed1a750..e0cf1cbe 100644
--- a/cloudinit/stages.py
+++ b/cloudinit/stages.py
@@ -36,6 +36,8 @@ from cloudinit.handlers import cloud_config as cc_part
from cloudinit.handlers import shell_script as ss_part
from cloudinit.handlers import upstart_job as up_part
+from cloudinit.sources import DataSourceNone
+
from cloudinit import cloud
from cloudinit import config
from cloudinit import distros
@@ -58,8 +60,16 @@ class Init(object):
self._cfg = None
self._paths = None
self._distro = None
- # Created only when a fetch occurs
- self.datasource = None
+ # Changed only when a fetch occurs
+ self.datasource = DataSourceNone.DataSourceNone({}, None, None)
+
+ def _reset(self, ds=False):
+ # Recreated on access
+ self._cfg = None
+ self._paths = None
+ self._distro = None
+ if ds:
+ self.datasource = DataSourceNone.DataSourceNone({}, None, None)
@property
def distro(self):
@@ -236,7 +246,7 @@ class Init(object):
self.datasource = ds
# Ensure we adjust our path members datasource
# now that we have one (thus allowing ipath to be used)
- self.paths.datasource = ds
+ self._reset()
return ds
def _get_instance_subdirs(self):
@@ -296,6 +306,10 @@ class Init(object):
util.write_file(iid_fn, "%s\n" % iid)
util.write_file(os.path.join(dp, 'previous-instance-id'),
"%s\n" % (previous_iid))
+ # Ensure needed components are regenerated
+ # after change of instance which may cause
+ # change of configuration
+ self._reset()
return iid
def fetch(self):
@@ -409,6 +423,17 @@ class Init(object):
handlers.call_end(mod, data, frequency)
called.append(mod)
+ # Perform post-consumption adjustments so that
+ # modules that run during the init stage reflect
+ # this consumed set.
+ #
+ # They will be recreated on future access...
+ self._reset()
+ # Note(harlowja): the 'active' datasource will have
+ # references to the previous config, distro, paths
+ # objects before the load of the userdata happened,
+ # this is expected.
+
class Modules(object):
def __init__(self, init, cfg_files=None):