summaryrefslogtreecommitdiff
path: root/cloudinit
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit')
-rw-r--r--cloudinit/cloud.py2
-rw-r--r--cloudinit/distros/__init__.py21
-rw-r--r--cloudinit/distros/ubuntu.py23
-rw-r--r--cloudinit/handlers/boot_hook.py14
-rw-r--r--cloudinit/handlers/cloud_config.py4
-rw-r--r--cloudinit/handlers/shell_script.py5
-rw-r--r--cloudinit/handlers/upstart_job.py7
-rw-r--r--cloudinit/helpers.py41
-rw-r--r--cloudinit/log.py2
-rw-r--r--cloudinit/sources/DataSourceCloudStack.py2
-rw-r--r--cloudinit/sources/DataSourceConfigDrive.py4
-rw-r--r--cloudinit/sources/DataSourceMAAS.py14
-rw-r--r--cloudinit/sources/DataSourceNoCloud.py3
-rw-r--r--cloudinit/sources/DataSourceOVF.py12
-rw-r--r--cloudinit/sources/__init__.py23
-rw-r--r--cloudinit/stages.py98
-rw-r--r--cloudinit/transforms/__init__.py2
-rw-r--r--cloudinit/transforms/cc_apt_update_upgrade.py12
-rw-r--r--cloudinit/transforms/cc_bootcmd.py8
-rw-r--r--cloudinit/transforms/cc_byobu.py2
-rw-r--r--cloudinit/transforms/cc_ca_certs.py13
-rw-r--r--cloudinit/transforms/cc_chef.py3
-rw-r--r--cloudinit/transforms/cc_disable_ec2_metadata.py3
-rw-r--r--cloudinit/transforms/cc_final_message.py4
-rw-r--r--cloudinit/transforms/cc_foo.py6
-rw-r--r--cloudinit/transforms/cc_grub_dpkg.py4
-rw-r--r--cloudinit/transforms/cc_keys_to_console.py23
-rw-r--r--cloudinit/transforms/cc_landscape.py3
-rw-r--r--cloudinit/transforms/cc_locale.py2
-rw-r--r--cloudinit/transforms/cc_mcollective.py9
-rw-r--r--cloudinit/transforms/cc_mounts.py15
-rw-r--r--cloudinit/transforms/cc_phone_home.py36
-rw-r--r--cloudinit/transforms/cc_puppet.py17
-rw-r--r--cloudinit/transforms/cc_resizefs.py38
-rw-r--r--cloudinit/transforms/cc_rightscale_userdata.py16
-rw-r--r--cloudinit/transforms/cc_rsyslog.py14
-rw-r--r--cloudinit/transforms/cc_runcmd.py9
-rw-r--r--cloudinit/transforms/cc_salt_minion.py7
-rw-r--r--cloudinit/transforms/cc_scripts_per_boot.py5
-rw-r--r--cloudinit/transforms/cc_scripts_per_instance.py5
-rw-r--r--cloudinit/transforms/cc_scripts_per_once.py5
-rw-r--r--cloudinit/transforms/cc_scripts_user.py9
-rw-r--r--cloudinit/transforms/cc_set_hostname.py2
-rw-r--r--cloudinit/transforms/cc_set_passwords.py10
-rw-r--r--cloudinit/transforms/cc_ssh.py22
-rw-r--r--cloudinit/transforms/cc_ssh_import_id.py8
-rw-r--r--cloudinit/transforms/cc_timezone.py8
-rw-r--r--cloudinit/transforms/cc_update_etc_hosts.py22
-rw-r--r--cloudinit/transforms/cc_update_hostname.py4
-rw-r--r--cloudinit/transforms/cc_welcome.py6
-rw-r--r--cloudinit/user_data.py13
-rw-r--r--cloudinit/util.py48
52 files changed, 388 insertions, 300 deletions
diff --git a/cloudinit/cloud.py b/cloudinit/cloud.py
index b2dfc749..8372d123 100644
--- a/cloudinit/cloud.py
+++ b/cloudinit/cloud.py
@@ -23,8 +23,6 @@
import copy
import os
-from cloudinit import distros
-from cloudinit import helpers
from cloudinit import log as logging
LOG = logging.getLogger(__name__)
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
index 90607668..fd4c70c1 100644
--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -20,29 +20,32 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from StringIO import StringIO
+
import abc
import copy
from cloudinit import importer
+from cloudinit import log as logging
from cloudinit import util
-from StringIO import StringIO
-
# TODO: Make this via config??
IFACE_ACTIONS = {
'up': ['ifup', '--all'],
'down': ['ifdown', '--all'],
}
+LOG = logging.getLogger(__name__)
+
class Distro(object):
__metaclass__ = abc.ABCMeta
- def __init__(self, cfg, runner):
+ def __init__(self, name, cfg, runner):
self._runner = runner
- self._cfg = util.get_cfg_by_path(cfg, ('system_info', ), {})
- self.name = self._cfg.pop("distro", 'generic')
+ self._cfg = cfg
+ self.name = name
@abc.abstractmethod
def install_packages(self, pkglist):
@@ -135,10 +138,9 @@ class Distro(object):
action, cmd)
(_out, err) = util.subp(cmd)
if len(err):
- LOG.warn("Running %s resulted in stderr output: %s",
- IF_UP_CMD, err)
+ LOG.warn("Running %s resulted in stderr output: %s", cmd, err)
return True
- except util.ProcessExecutionError as exc:
+ except util.ProcessExecutionError:
util.logexc(LOG, "Running %s failed", cmd)
return False
@@ -152,7 +154,8 @@ def fetch(distro_name, mods=(__name__, )):
except RuntimeError:
pass
if not mod:
- raise RuntimeError("No distribution found for distro %s" % (distro_name))
+ raise RuntimeError("No distribution found for distro %s"
+ % (distro_name))
distro_cls = getattr(mod, 'Distro')
return distro_cls
diff --git a/cloudinit/distros/ubuntu.py b/cloudinit/distros/ubuntu.py
index 6b0aff47..9252a1c4 100644
--- a/cloudinit/distros/ubuntu.py
+++ b/cloudinit/distros/ubuntu.py
@@ -20,17 +20,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from StringIO import StringIO
-
import os
-import socket
from cloudinit import distros
from cloudinit import log as logging
-from cloudinit import templater
from cloudinit import util
-from cloudinit.settings import (PER_INSTANCE)
+from cloudinit.settings import PER_INSTANCE
LOG = logging.getLogger(__name__)
@@ -65,9 +61,11 @@ class Distro(distros.Distro):
try:
util.write_file(fn, "%s\n" % hostname, 0644)
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."
+ 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_file)
if "/etc/hostname" in update_files:
LOG.debug("Setting hostname to %s", hostname)
@@ -91,7 +89,8 @@ class Distro(distros.Distro):
def set_timezone(self, tz):
tz_file = os.path.join("/usr/share/zoneinfo", tz)
if not os.path.isfile(tz_file):
- raise Exception("Invalid timezone %s, no file found at %s" % (tz, tz_file))
+ raise Exception(("Invalid timezone %s,"
+ " no file found at %s") % (tz, tz_file))
tz_contents = "%s\n" % tz
util.write_file("/etc/timezone", tz_contents)
# TODO, this should be in a rhel distro subclass??
@@ -101,9 +100,6 @@ class Distro(distros.Distro):
# This ensures that the correct tz will be used for the system
util.copy(tz_file, "/etc/localtime")
- def name(self):
- return "ubuntu"
-
# apt_get top level command (install, update...), and args to pass it
def _apt_get(self, tlc, args=None):
e = os.environ.copy()
@@ -116,4 +112,5 @@ class Distro(distros.Distro):
util.subp(cmd, env=e, capture=False)
def _update_package_sources(self):
- self.runner.run("update-sources", self._apt_get, ["update"], freq=PER_INSTANCE) \ No newline at end of file
+ self._runner.run("update-sources", self._apt_get,
+ ["update"], freq=PER_INSTANCE) \ No newline at end of file
diff --git a/cloudinit/handlers/boot_hook.py b/cloudinit/handlers/boot_hook.py
index c75aeb72..b3aab366 100644
--- a/cloudinit/handlers/boot_hook.py
+++ b/cloudinit/handlers/boot_hook.py
@@ -32,9 +32,9 @@ LOG = logging.getLogger(__name__)
class BootHookPartHandler(ud.PartHandler):
- def __init__(self, boothook_dir, instance_id):
+ def __init__(self, paths, instance_id, **_kwargs):
ud.PartHandler.__init__(self, PER_ALWAYS)
- self.boothook_dir = boothook_dir
+ self.boothook_dir = paths.get_ipath("boothooks")
self.instance_id = instance_id
def list_types(self):
@@ -54,13 +54,15 @@ class BootHookPartHandler(ud.PartHandler):
start = len(prefix) + 1
filepath = os.path.join(self.boothook_dir, filename)
- util.write_file(filepath, payload[start:], 0700)
+ contents = payload[start:]
+ util.write_file(filepath, contents, 0700)
try:
env = os.environ.copy()
- env['INSTANCE_ID'] = str(self.instance_id)
+ if self.instance_id:
+ env['INSTANCE_ID'] = str(self.instance_id)
util.subp([filepath], env=env)
- except util.ProcessExecutionError as e:
+ except util.ProcessExecutionError:
util.logexc(LOG, "Boothooks script %s execution error", filepath)
- except Exception as e:
+ except Exception:
util.logexc(LOG, ("Boothooks unknown "
"error when running %s"), filepath)
diff --git a/cloudinit/handlers/cloud_config.py b/cloudinit/handlers/cloud_config.py
index f0e88eeb..12d1bd96 100644
--- a/cloudinit/handlers/cloud_config.py
+++ b/cloudinit/handlers/cloud_config.py
@@ -30,10 +30,10 @@ LOG = logging.getLogger(__name__)
class CloudConfigPartHandler(ud.PartHandler):
- def __init__(self, cloud_fn):
+ def __init__(self, paths, **_kwargs):
ud.PartHandler.__init__(self, PER_ALWAYS)
self.cloud_buf = []
- self.cloud_fn = cloud_fn
+ self.cloud_fn = paths.get_ipath("cloud_config")
def list_types(self):
return [
diff --git a/cloudinit/handlers/shell_script.py b/cloudinit/handlers/shell_script.py
index 564e4623..f6e2ef16 100644
--- a/cloudinit/handlers/shell_script.py
+++ b/cloudinit/handlers/shell_script.py
@@ -32,10 +32,9 @@ LOG = logging.getLogger(__name__)
class ShellScriptPartHandler(ud.PartHandler):
-
- def __init__(self, script_dir):
+ def __init__(self, paths, **_kwargs):
ud.PartHandler.__init__(self, PER_ALWAYS)
- self.script_dir = script_dir
+ self.script_dir = paths.get_ipath_cur('scripts')
def list_types(self):
return [
diff --git a/cloudinit/handlers/upstart_job.py b/cloudinit/handlers/upstart_job.py
index 568a644a..059a4851 100644
--- a/cloudinit/handlers/upstart_job.py
+++ b/cloudinit/handlers/upstart_job.py
@@ -33,9 +33,9 @@ LOG = logging.getLogger(__name__)
class UpstartJobPartHandler(ud.PartHandler):
- def __init__(self, upstart_dir):
+ def __init__(self, paths, **_kwargs):
ud.PartHandler.__init__(self, PER_INSTANCE)
- self.upstart_dir = upstart_dir
+ self.upstart_dir = paths.upstart_conf_d
def list_types(self):
return [
@@ -46,6 +46,9 @@ class UpstartJobPartHandler(ud.PartHandler):
if ctype in ud.CONTENT_SIGNALS:
return
+ if not self.upstart_dir:
+ return
+
filename = util.clean_filename(filename)
(_name, ext) = os.path.splitext(filename)
if not ext:
diff --git a/cloudinit/helpers.py b/cloudinit/helpers.py
index 2ecda3e9..c276a54c 100644
--- a/cloudinit/helpers.py
+++ b/cloudinit/helpers.py
@@ -30,11 +30,6 @@ from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE)
from cloudinit import log as logging
from cloudinit import util
-from cloudinit.user_data import boot_hook as bh_part
-from cloudinit.user_data import cloud_config as cc_part
-from cloudinit.user_data import shell_script as ss_part
-from cloudinit.user_data import upstart_job as up_part
-
LOG = logging.getLogger(__name__)
@@ -77,7 +72,7 @@ class FileSemaphores(object):
sem_file = self._get_path(name, freq)
try:
util.del_file(sem_file)
- except (IOError, OSError) as e:
+ except (IOError, OSError):
util.logexc(LOG, "Failed deleting semaphore %s", sem_file)
return False
return True
@@ -99,7 +94,7 @@ class FileSemaphores(object):
contents = "%s: %s\n" % (os.getpid(), time())
try:
util.write_file(sem_file, contents)
- except (IOError, OSError) as e:
+ except (IOError, OSError):
util.logexc(LOG, "Failed writing semaphore file %s", sem_file)
return None
return sem_file
@@ -162,9 +157,10 @@ class Runners(object):
class ContentHandlers(object):
- def __init__(self, paths):
+ def __init__(self, paths, iid=None):
self.paths = paths
self.registered = {}
+ self.iid = iid
def __contains__(self, item):
return self.is_registered(item)
@@ -191,34 +187,9 @@ class ContentHandlers(object):
def iteritems(self):
return self.registered.iteritems()
- def _get_default_handlers(self):
- def_handlers = []
-
- cc_path = self.paths.get_ipath("cloud_config")
- if cc_path:
- cc_h = cc_part.CloudConfigPartHandler(cc_path)
- def_handlers.append(cc_h)
-
- sc_path = self.paths.get_ipath_cur('scripts')
- if sc_path:
- ss_h = ss_part.ShellScriptPartHandler(sc_path)
- def_handlers.append(ss_h)
-
- bh_path = self.paths.get_ipath("boothooks")
- if bh_path:
- bh_h = bh_part.BootHookPartHandler(bh_path)
- def_handlers.append(bh_h)
-
- upstart_pth = self.paths.upstart_conf_d
- if upstart_pth:
- up_h = up_part.UpstartJobPartHandler(upstart_pth)
- def_handlers.append(up_h)
-
- return def_handlers
-
- def register_defaults(self):
+ def register_defaults(self, defs):
registered = set()
- for mod in self._get_default_handlers():
+ for mod in defs:
for t in mod.list_types():
if not self.is_registered(t):
self.registered[t] = mod
diff --git a/cloudinit/log.py b/cloudinit/log.py
index c247eb9e..5fcb77ef 100644
--- a/cloudinit/log.py
+++ b/cloudinit/log.py
@@ -56,7 +56,7 @@ def setupBasicLogging():
cfile = logging.FileHandler('/var/log/cloud-init.log')
cfile.setFormatter(logging.Formatter(DEF_CON_FORMAT))
cfile.setLevel(DEBUG)
- root.addHandle(cfile)
+ root.addHandler(cfile)
except (IOError, OSError):
# Likely that u can't write to that file...
# Make console now have DEBUG??
diff --git a/cloudinit/sources/DataSourceCloudStack.py b/cloudinit/sources/DataSourceCloudStack.py
index 791df68f..27217e65 100644
--- a/cloudinit/sources/DataSourceCloudStack.py
+++ b/cloudinit/sources/DataSourceCloudStack.py
@@ -79,7 +79,7 @@ class DataSourceCloudStack(sources.DataSource):
tot_time = (time.time() - start)
LOG.debug("Crawl of metadata service took %s", int(tot_time))
return True
- except Exception as e:
+ except Exception:
util.logexc(LOG, ('Failed fetching from metadata '
'service %s'), self.metadata_address)
return False
diff --git a/cloudinit/sources/DataSourceConfigDrive.py b/cloudinit/sources/DataSourceConfigDrive.py
index 176b62b0..7450572f 100644
--- a/cloudinit/sources/DataSourceConfigDrive.py
+++ b/cloudinit/sources/DataSourceConfigDrive.py
@@ -51,8 +51,8 @@ class DataSourceConfigDrive(sources.DataSource):
self.seed_dir = os.path.join(paths.seed_dir, 'config_drive')
def __str__(self):
- mstr = "%s[%s]" % (util.obj_name(self), self.dsmode)
- mstr += " [seed=%s]" % (self.seed)
+ mstr = "%s [%s]" % (util.obj_name(self), self.dsmode)
+ mstr += "[seed=%s]" % (self.seed)
return mstr
def get_data(self):
diff --git a/cloudinit/sources/DataSourceMAAS.py b/cloudinit/sources/DataSourceMAAS.py
index 27196265..9e639649 100644
--- a/cloudinit/sources/DataSourceMAAS.py
+++ b/cloudinit/sources/DataSourceMAAS.py
@@ -18,9 +18,9 @@
# 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
import errno
import oauth.oauth as oauth
+import os
import time
import urllib2
@@ -48,7 +48,7 @@ class DataSourceMAAS(sources.DataSource):
self.seed_dir = os.path.join(paths.seed_dir, 'maas')
def __str__(self):
- return "%s[%s]" % (util.obj_name(self), self.base_url)
+ return "%s [%s]" % (util.obj_name(self), self.base_url)
def get_data(self):
mcfg = self.ds_cfg
@@ -122,9 +122,10 @@ class DataSourceMAAS(sources.DataSource):
starttime = time.time()
check_url = "%s/%s/meta-data/instance-id" % (url, MD_VERSION)
- url = util.wait_for_url(urls=[check_url], max_wait=max_wait,
- timeout=timeout, status_cb=LOG.warn,
- headers_cb=self.md_headers)
+ urls = [check_url]
+ url = uhelp.wait_for_url(urls=urls, max_wait=max_wait,
+ timeout=timeout, status_cb=LOG.warn,
+ headers_cb=self.md_headers)
if url:
LOG.info("Using metadata source: '%s'", url)
@@ -185,7 +186,8 @@ def read_maas_seed_url(seed_url, header_cb=None, timeout=None,
headers = {}
try:
(resp, sc) = uhelp.readurl(url, headers=headers, timeout=timeout)
- md[name] = resp
+ if uhelp.ok_http_code(sc):
+ md[name] = resp
except urllib2.HTTPError as e:
if e.code != 404:
raise
diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py
index 84d0f99d..2b016d1c 100644
--- a/cloudinit/sources/DataSourceNoCloud.py
+++ b/cloudinit/sources/DataSourceNoCloud.py
@@ -106,7 +106,8 @@ class DataSourceNoCloud(sources.DataSource):
if e.errno != errno.ENOENT:
raise
except util.MountFailedError:
- util.logexc(LOG, "Failed to mount %s when looking for seed", dev)
+ util.logexc(LOG, ("Failed to mount %s"
+ " when looking for data"), dev)
# There was no indication on kernel cmdline or data
# in the seeddir suggesting this handler should be used.
diff --git a/cloudinit/sources/DataSourceOVF.py b/cloudinit/sources/DataSourceOVF.py
index bb0f46c2..258d8d03 100644
--- a/cloudinit/sources/DataSourceOVF.py
+++ b/cloudinit/sources/DataSourceOVF.py
@@ -21,10 +21,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from xml.dom import minidom
+
import base64
import os
import re
-import tempfile
from cloudinit import log as logging
from cloudinit import sources
@@ -51,7 +51,7 @@ class DataSourceOVF(sources.DataSource):
ud = ""
defaults = {
- "instance-id": "iid-dsovf"
+ "instance-id": "iid-dsovf",
}
(seedfile, contents) = get_ovf_env(self.paths.seed_dir)
@@ -198,7 +198,7 @@ def transport_iso9660(require_iso=True):
for dev in devs:
fullp = os.path.join("/dev/", dev)
- if (fullp in mounted or
+ if (fullp in mounts or
not cdmatch.match(dev) or os.path.isdir(fullp)):
continue
@@ -210,7 +210,8 @@ def transport_iso9660(require_iso=True):
continue
try:
- (fname, contents) = utils.mount_cb(fullp, get_ovf_env, mtype="iso9660")
+ (fname, contents) = util.mount_cb(fullp,
+ get_ovf_env, mtype="iso9660")
except util.MountFailedError:
util.logexc(LOG, "Failed mounting %s", fullp)
continue
@@ -265,7 +266,8 @@ def get_properties(contents):
raise XmlError("No 'PropertySection's")
props = {}
- propElems = find_child(propSections[0], lambda n: n.localName == "Property")
+ propElems = find_child(propSections[0],
+ (lambda n: n.localName == "Property"))
for elem in propElems:
key = elem.attributes.getNamedItemNS(envNsURI, "key").value
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index 08669f5d..beb0f3d7 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -22,10 +22,9 @@
from cloudinit import importer
from cloudinit import log as logging
+from cloudinit import user_data as ud
from cloudinit import util
-from cloudinit.user_data import processor as ud_proc
-
DEP_FILESYSTEM = "FILESYSTEM"
DEP_NETWORK = "NETWORK"
DS_PREFIX = 'DataSource'
@@ -42,7 +41,6 @@ class DataSource(object):
self.sys_cfg = sys_cfg
self.distro = distro
self.paths = paths
- self.userdata_proc = ud_proc.UserDataProcessor(paths)
self.userdata = None
self.metadata = None
self.userdata_raw = None
@@ -55,7 +53,7 @@ class DataSource(object):
def get_userdata(self):
if self.userdata is None:
raw_data = self.get_userdata_raw()
- self.userdata = self.userdata_proc.process(raw_data)
+ self.userdata = ud.UserDataProcessor(self.paths).process(raw_data)
return self.userdata
def get_userdata_raw(self):
@@ -73,7 +71,7 @@ class DataSource(object):
if not self.metadata or 'public-keys' not in self.metadata:
return keys
- if isinstance(self.metadata['public-keys'], (str)):
+ if isinstance(self.metadata['public-keys'], (basestring, str)):
return str(self.metadata['public-keys']).splitlines()
if isinstance(self.metadata['public-keys'], (list, set)):
@@ -84,11 +82,12 @@ class DataSource(object):
# lp:506332 uec metadata service responds with
# data that makes boto populate a string for 'klist' rather
# than a list.
- if isinstance(klist, (str)):
+ if isinstance(klist, (str, basestring)):
klist = [klist]
if isinstance(klist, (list, set)):
for pkey in klist:
- # there is an empty string at the end of the keylist, trim it
+ # There is an empty string at
+ # the end of the keylist, trim it
if pkey:
keys.append(pkey)
@@ -159,13 +158,14 @@ def find_source(sys_cfg, distro, paths, ds_deps, cfg_list, pkg_list):
ds_list = list_sources(cfg_list, ds_deps, pkg_list)
ds_names = [util.obj_name(f) for f in ds_list]
LOG.info("Searching for data source in: %s", ds_names)
+
for cls in ds_list:
ds = util.obj_name(cls)
try:
s = cls(distro, sys_cfg, paths)
if s.get_data():
return (s, ds)
- except Exception as e:
+ except Exception:
util.logexc(LOG, "Getting data from %s failed", ds)
msg = "Did not find any data source, searched classes: %s" % (ds_names)
@@ -178,7 +178,8 @@ def find_source(sys_cfg, distro, paths, ds_deps, cfg_list, pkg_list):
# return an ordered list of classes that match
def list_sources(cfg_list, depends, pkg_list):
src_list = []
- LOG.info("Looking for for data source in: %s, %s that match %s", cfg_list, pkg_list, depends)
+ LOG.info(("Looking for for data source in: %s,"
+ " %s that matches %s"), cfg_list, pkg_list, depends)
for ds_coll in cfg_list:
ds_name = str(ds_coll)
if not ds_name.startswith(DS_PREFIX):
@@ -201,8 +202,8 @@ def list_sources(cfg_list, depends, pkg_list):
if not cls_matches:
continue
src_list.extend(cls_matches)
- LOG.debug("Found a match for data source %s in %s with matches %s",
- ds_name, mod, cls_matches)
+ LOG.debug(("Found a match for data source %s"
+ " in %s with matches %s"), ds_name, mod, cls_matches)
break
return src_list
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
index 2615d59f..b9076881 100644
--- a/cloudinit/stages.py
+++ b/cloudinit/stages.py
@@ -31,19 +31,23 @@ try:
except ImportError:
ConfigObj = None
-from cloudinit.settings import (PER_INSTANCE, FREQUENCIES)
from cloudinit.settings import (OLD_CLOUD_CONFIG)
+from cloudinit.settings import (PER_INSTANCE, FREQUENCIES)
+
+from cloudinit.handlers import boot_hook as bh_part
+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 import cloud
from cloudinit import distros
-from cloudinit import modules
from cloudinit import helpers
from cloudinit import importer
from cloudinit import log as logging
from cloudinit import sources
-from cloudinit import util
-
+from cloudinit import transforms
from cloudinit import user_data as ud
+from cloudinit import util
LOG = logging.getLogger(__name__)
@@ -73,12 +77,19 @@ class Init(object):
def distro(self):
if not self._distro:
d_cfg = util.get_cfg_by_path(self.cfg, ('system_info'), {})
+ # Ensure its a dictionary
+ if not isinstance(d_cfg, (dict)):
+ d_cfg = {}
# Ensure not modified indirectly
d_cfg = copy.deepcopy(d_cfg)
+ # Remove this since its path config, not distro config
d_cfg.pop('paths', None)
- distro_cls = distros.fetch(sys_cfg.pop('distro', 'ubuntu'))
+ # Try to find the right class to use
+ distro_name = d_cfg.pop('distro', 'ubuntu')
+ distro_cls = distros.fetch(distro_name)
LOG.debug("Using distro class %s", distro_cls)
- distro = distro_cls(d_cfg, helpers.Runners(self.paths))
+ distro = distro_cls(distro_name, d_cfg,
+ helpers.Runners(self.paths))
self._distro = distro
return self._distro
@@ -93,7 +104,8 @@ class Init(object):
@property
def paths(self):
if not self._paths:
- path_info = util.get_cfg_by_path(self.cfg, ('system_info', 'paths'), {})
+ path_info = util.get_cfg_by_path(self.cfg,
+ ('system_info', 'paths'), {})
# Ensure not modified indirectly
path_info = copy.deepcopy(path_info)
self._paths = helpers.Paths(path_info, self.datasource)
@@ -156,7 +168,7 @@ class Init(object):
# by using the instance link, if purge_cache was called
# the file wont exist
return pickle.loads(util.load_file(pickled_fn))
- except Exception as e:
+ except Exception:
util.logexc(LOG, "Failed loading pickled datasource from %s",
pickled_fn)
return None
@@ -166,7 +178,7 @@ class Init(object):
try:
contents = pickle.dumps(self.datasource)
util.write_file(pickled_fn, contents, mode=0400)
- except Exception as e:
+ except Exception:
util.logexc(LOG, "Failed pickling datasource to %s", pickled_fn)
return False
@@ -192,7 +204,8 @@ class Init(object):
# (which will affect user-data handlers down the line...)
sys_cfg = copy.deepcopy(self.cfg)
ds_deps = copy.deepcopy(self.ds_deps)
- (ds, dsname) = sources.find_source(sys_cfg, self.distro, self.paths,
+ (ds, dsname) = sources.find_source(sys_cfg, self.distro,
+ self.paths,
ds_deps, cfg_list, pkg_list)
LOG.debug("Loaded datasource %s - %s", dsname, ds)
self.datasource = ds
@@ -270,6 +283,20 @@ class Init(object):
processed_ud = "%s" % (self.datasource.get_userdata())
util.write_file(self.paths.get_ipath('userdata'), processed_ud, 0600)
+ def _default_userdata_handlers(self):
+ opts = {
+ 'paths': self.paths,
+ 'instance_id': self.datasource.get_instance_id(),
+ }
+ # TODO Hmmm, should we dynamically import these??
+ def_handlers = [
+ cc_part.CloudConfigPartHandler(**opts),
+ ss_part.ShellScriptPartHandler(**opts),
+ bh_part.BootHookPartHandler(**opts),
+ up_part.UpstartJobPartHandler(**opts),
+ ]
+ return def_handlers
+
def consume(self, frequency=PER_INSTANCE):
cdir = self.paths.get_cpath("handlers")
idir = self.paths.get_ipath("handlers")
@@ -279,8 +306,11 @@ class Init(object):
sys.path.insert(0, cdir)
sys.path.insert(0, idir)
+ # Ensure datasource fetched before activation (just incase)
+ ud_obj = self.datasource.get_userdata()
+
# This keeps track of all the active handlers
- c_handlers = helpers.ContentHandlers(self.paths)
+ c_handlers = helpers.ContentHandlers(paths=self.paths)
# Add handlers in cdir
potential_handlers = util.find_modules(cdir)
@@ -292,13 +322,10 @@ class Init(object):
except:
util.logexc(LOG, "Failed to register handler from %s", fname)
- def_handlers = c_handlers.register_defaults()
- if def_handlers:
- LOG.debug("Registered default handlers for %s", def_handlers)
-
-
- # Ensure userdata fetched before activation (just incase)
- ud_obj = self.datasource.get_userdata()
+ def_handlers = self._default_userdata_handlers()
+ applied_def_handlers = c_handlers.register_defaults(def_handlers)
+ if applied_def_handlers:
+ LOG.debug("Registered default handlers: %s", applied_def_handlers)
# Form our cloud interface
data = self.cloudify()
@@ -334,11 +361,11 @@ class Init(object):
class Transforms(object):
- def __init__(self, cloudobj, cfgfile=None):
- self.datasource = cloudobj.datasource
+ def __init__(self, init, cfgfile=None):
+ self.datasource = init.fetch()
self.cfgfile = cfgfile
- self.basecfg = copy.deepcopy(cloudobj.cfg)
- self.cloudobj = cloudobj
+ self.basecfg = copy.deepcopy(init.cfg)
+ self.init = init
# Created on first use
self._cachedcfg = None
@@ -409,25 +436,28 @@ class Transforms(object):
(item, util.obj_name(item)))
return module_list
- def _transforms_modules(self, raw_mods):
+ def _fixup_transforms(self, raw_mods):
mostly_mods = []
for raw_mod in raw_mods:
raw_name = raw_mod['mod']
freq = raw_mod.get('freq')
run_args = raw_mod.get('args') or []
- mod_name = modules.form_module_name(raw_name)
+ mod_name = transforms.form_module_name(raw_name)
if not mod_name:
continue
if freq and freq not in FREQUENCIES:
- LOG.warn("Config specified module %s has an unknown frequency %s", raw_name, freq)
+ LOG.warn(("Config specified transform %s"
+ " has an unknown frequency %s"), raw_name, freq)
# Reset it so when ran it will get set to a known value
freq = None
- mod = modules.fixup_module(importer.import_module(mod_name))
+ mod = transforms.fixup_module(importer.import_module(mod_name))
mostly_mods.append([mod, raw_name, freq, run_args])
return mostly_mods
def _run_transforms(self, mostly_mods):
failures = []
+ d_name = self.init.distro.name
+ c_cloud = self.init.cloudify()
for (mod, name, freq, args) in mostly_mods:
try:
# Try the modules frequency, otherwise fallback to a known one
@@ -436,17 +466,17 @@ class Transforms(object):
if not freq in FREQUENCIES:
freq = PER_INSTANCE
worked_distros = mod.distros
- if worked_distros and self.cloud.distro.name() not in worked_distros:
- LOG.warn(("Module %s is verified on %s distros"
+ if (worked_distros and d_name not in worked_distros):
+ LOG.warn(("Transform %s is verified on %s distros"
" but not on %s distro. It may or may not work"
- " correctly."), name, worked_distros,
- self.cloud.distro.name())
+ " correctly."), name, worked_distros, d_name)
# Deep copy the config so that modules can't alter it
+ # Use the transforms logger and not our own
func_args = [name, copy.deepcopy(self.cfg),
- self.cloudobj, LOG, args]
- # This name will affect the semphapore name created
+ c_cloud, transforms.LOG, args]
+ # This name will affect the semaphore name created
run_name = "config-%s" % (name)
- self.cloudobj.run(run_name, mod.handle, func_args, freq=freq)
+ c_cloud.run(run_name, mod.handle, func_args, freq=freq)
except Exception as e:
util.logexc(LOG, "Running %s failed", mod)
failures.append((name, e))
@@ -454,5 +484,5 @@ class Transforms(object):
def run(self, name):
raw_mods = self._read_transforms(name)
- mostly_mods = self._transforms_modules(raw_mods)
+ mostly_mods = self._fixup_transforms(raw_mods)
return self._run_transforms(mostly_mods)
diff --git a/cloudinit/transforms/__init__.py b/cloudinit/transforms/__init__.py
index 8275b375..40affc4b 100644
--- a/cloudinit/transforms/__init__.py
+++ b/cloudinit/transforms/__init__.py
@@ -44,7 +44,7 @@ def fixup_module(mod, def_freq=PER_INSTANCE):
else:
freq = mod.frequency
if freq and freq not in FREQUENCIES:
- LOG.warn("Module %s has an unknown frequency %s", mod, freq)
+ LOG.warn("Transform %s has an unknown frequency %s", mod, freq)
if not hasattr(mod, 'handle'):
def empty_handle(_name, _cfg, _cloud, _log, _args):
pass
diff --git a/cloudinit/transforms/cc_apt_update_upgrade.py b/cloudinit/transforms/cc_apt_update_upgrade.py
index c4a543ed..a4e058c6 100644
--- a/cloudinit/transforms/cc_apt_update_upgrade.py
+++ b/cloudinit/transforms/cc_apt_update_upgrade.py
@@ -71,7 +71,7 @@ def handle(_name, cfg, cloud, log, _args):
except:
util.logexc(log, "Failed to run debconf-set-selections")
- pkglist = util.get_cfg_option_list_or_str(cfg, 'packages', [])
+ pkglist = util.get_cfg_option_list(cfg, 'packages', [])
errors = []
if update or len(pkglist) or upgrade:
@@ -96,7 +96,9 @@ def handle(_name, cfg, cloud, log, _args):
errors.append(e)
if len(errors):
- raise errors[0]
+ log.warn("%s failed with exceptions, re-raising the last one",
+ len(errors))
+ raise errors[-1]
def mirror2lists_fileprefix(mirror):
@@ -186,7 +188,8 @@ def add_sources(srclist, template_params=None):
try:
util.write_file(ent['filename'], source + "\n", omode="ab")
except:
- errorlist.append([source, "failed write to file %s" % ent['filename']])
+ errorlist.append([source,
+ "failed write to file %s" % ent['filename']])
return errorlist
@@ -219,9 +222,10 @@ def find_apt_mirror(cloud, cfg):
doms.extend((".localdomain", "",))
mirror_list = []
+ distro = cloud.distro.name
mirrorfmt = "http://%s-mirror%s/%s" % (distro, "%s", distro)
for post in doms:
- mirror_list.append(mirrorfmt % post)
+ mirror_list.append(mirrorfmt % (post))
mirror = util.search_for_mirror(mirror_list)
diff --git a/cloudinit/transforms/cc_bootcmd.py b/cloudinit/transforms/cc_bootcmd.py
index a2efad32..80afb5e7 100644
--- a/cloudinit/transforms/cc_bootcmd.py
+++ b/cloudinit/transforms/cc_bootcmd.py
@@ -30,7 +30,8 @@ frequency = PER_ALWAYS
def handle(name, cfg, cloud, log, _args):
if "bootcmd" not in cfg:
- log.debug("Skipping module named %s, no 'bootcomd' key in configuration", name)
+ log.debug(("Skipping transform named %s,"
+ " no 'bootcomd' key in configuration"), name)
return
with tempfile.NamedTemporaryFile(suffix=".sh") as tmpf:
@@ -39,7 +40,7 @@ def handle(name, cfg, cloud, log, _args):
tmpf.write(content)
tmpf.flush()
except:
- log.warn("Failed to shellify bootcmd")
+ util.logexc(log, "Failed to shellify bootcmd")
raise
try:
@@ -48,5 +49,6 @@ def handle(name, cfg, cloud, log, _args):
cmd = ['/bin/sh', tmpf.name]
util.subp(cmd, env=env, capture=False)
except:
- log.warn("Failed to run commands from bootcmd")
+ util.logexc(log,
+ ("Failed to run bootcmd transform %s"), name)
raise
diff --git a/cloudinit/transforms/cc_byobu.py b/cloudinit/transforms/cc_byobu.py
index 38586174..741aa934 100644
--- a/cloudinit/transforms/cc_byobu.py
+++ b/cloudinit/transforms/cc_byobu.py
@@ -30,7 +30,7 @@ def handle(name, cfg, _cloud, log, args):
value = util.get_cfg_option_str(cfg, "byobu_by_default", "")
if not value:
- log.debug("Skipping module named %s, no 'byobu' values found", name)
+ log.debug("Skipping transform named %s, no 'byobu' values found", name)
return
if value == "user" or value == "system":
diff --git a/cloudinit/transforms/cc_ca_certs.py b/cloudinit/transforms/cc_ca_certs.py
index 8ca9a200..e0802bfe 100644
--- a/cloudinit/transforms/cc_ca_certs.py
+++ b/cloudinit/transforms/cc_ca_certs.py
@@ -23,6 +23,8 @@ CA_CERT_FILENAME = "cloud-init-ca-certs.crt"
CA_CERT_CONFIG = "/etc/ca-certificates.conf"
CA_CERT_SYSTEM_PATH = "/etc/ssl/certs/"
+distros = ['ubuntu']
+
def update_ca_certs():
"""
@@ -70,22 +72,25 @@ def handle(name, cfg, _cloud, log, _args):
"""
# If there isn't a ca-certs section in the configuration don't do anything
if "ca-certs" not in cfg:
- log.debug("Skipping module named %s, no 'ca-certs' key in configuration", name)
+ log.debug(("Skipping transform named %s,"
+ " no 'ca-certs' key in configuration"), name)
return
+
ca_cert_cfg = cfg['ca-certs']
# If there is a remove-defaults option set to true, remove the system
# default trusted CA certs first.
if ca_cert_cfg.get("remove-defaults", False):
- log.debug("removing default certificates")
+ log.debug("Removing default certificates")
remove_default_ca_certs()
# If we are given any new trusted CA certs to add, add them.
if "trusted" in ca_cert_cfg:
- trusted_certs = util.get_cfg_option_list_or_str(ca_cert_cfg, "trusted")
+ trusted_certs = util.get_cfg_option_list(ca_cert_cfg, "trusted")
if trusted_certs:
- log.debug("adding %d certificates" % len(trusted_certs))
+ log.debug("Adding %d certificates" % len(trusted_certs))
add_ca_certs(trusted_certs)
# Update the system with the new cert configuration.
+ log.debug("Updating certificates")
update_ca_certs()
diff --git a/cloudinit/transforms/cc_chef.py b/cloudinit/transforms/cc_chef.py
index 12c2f539..473e5f8b 100644
--- a/cloudinit/transforms/cc_chef.py
+++ b/cloudinit/transforms/cc_chef.py
@@ -31,7 +31,8 @@ def handle(name, cfg, cloud, log, _args):
# If there isn't a chef key in the configuration don't do anything
if 'chef' not in cfg:
- log.debug("Skipping module named %s, no 'chef' key in configuration", name)
+ log.debug(("Skipping transform named %s,"
+ " no 'chef' key in configuration"), name)
return
chef_cfg = cfg['chef']
diff --git a/cloudinit/transforms/cc_disable_ec2_metadata.py b/cloudinit/transforms/cc_disable_ec2_metadata.py
index 4d2a7f55..3c0dd57b 100644
--- a/cloudinit/transforms/cc_disable_ec2_metadata.py
+++ b/cloudinit/transforms/cc_disable_ec2_metadata.py
@@ -28,5 +28,6 @@ reject_cmd = ['route', 'add', '-host', '169.254.169.254', 'reject']
def handle(_name, cfg, _cloud, _log, _args):
- if util.get_cfg_option_bool(cfg, "disable_ec2_metadata", False):
+ disabled = util.get_cfg_option_bool(cfg, "disable_ec2_metadata", False)
+ if disabled:
util.subp(reject_cmd)
diff --git a/cloudinit/transforms/cc_final_message.py b/cloudinit/transforms/cc_final_message.py
index dc4ae34c..c257b6d0 100644
--- a/cloudinit/transforms/cc_final_message.py
+++ b/cloudinit/transforms/cc_final_message.py
@@ -32,7 +32,7 @@ final_message_def = ("Cloud-init v. {{version}} finished at {{timestamp}}."
" Up {{uptime}} seconds.")
-def handle(name, cfg, cloud, log, args):
+def handle(_name, cfg, cloud, log, args):
msg_in = None
if len(args) != 0:
@@ -60,7 +60,7 @@ def handle(name, cfg, cloud, log, args):
# Use stdout, stderr or the logger??
content = templater.render_string(msg_in, subs)
sys.stderr.write("%s\n" % (content))
- except Exception as e:
+ except Exception:
util.logexc(log, "Failed to render final message template")
boot_fin_fn = cloud.paths.boot_finished
diff --git a/cloudinit/transforms/cc_foo.py b/cloudinit/transforms/cc_foo.py
index 8007f981..99135704 100644
--- a/cloudinit/transforms/cc_foo.py
+++ b/cloudinit/transforms/cc_foo.py
@@ -45,8 +45,8 @@ from cloudinit.settings import PER_INSTANCE
# informational purposes. If non existent all distros are assumed and
# no warning occurs.
-frequency = settings.PER_INSTANCE
+frequency = PER_INSTANCE
-def handle(name, _cfg, _cloud, _log, _args):
- print("Hi from %s" % (name))
+def handle(name, _cfg, _cloud, log, _args):
+ log.debug("Hi from transform %s", name)
diff --git a/cloudinit/transforms/cc_grub_dpkg.py b/cloudinit/transforms/cc_grub_dpkg.py
index c048d5cc..02f05ce3 100644
--- a/cloudinit/transforms/cc_grub_dpkg.py
+++ b/cloudinit/transforms/cc_grub_dpkg.py
@@ -54,9 +54,9 @@ def handle(_name, cfg, _cloud, log, _args):
# now idevs and idevs_empty are set to determined values
# or, those set by user
- dconf_sel = ("grub-pc grub-pc/install_devices string %s\n"
+ dconf_sel = (("grub-pc grub-pc/install_devices string %s\n"
"grub-pc grub-pc/install_devices_empty boolean %s\n") %
- (idevs, idevs_empty)
+ (idevs, idevs_empty))
log.debug("Setting grub debconf-set-selections with '%s','%s'" %
(idevs, idevs_empty))
diff --git a/cloudinit/transforms/cc_keys_to_console.py b/cloudinit/transforms/cc_keys_to_console.py
index 2f2a5297..e974375f 100644
--- a/cloudinit/transforms/cc_keys_to_console.py
+++ b/cloudinit/transforms/cc_keys_to_console.py
@@ -18,23 +18,34 @@
# 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.settings import PER_INSTANCE
from cloudinit import util
frequency = PER_INSTANCE
+# This is a tool that cloud init provides
+helper_tool = '/usr/lib/cloud-init/write-ssh-key-fingerprints'
+
-def handle(_name, cfg, _cloud, log, _args):
- cmd = ['/usr/lib/cloud-init/write-ssh-key-fingerprints']
- fp_blacklist = util.get_cfg_option_list_or_str(cfg,
+def handle(name, cfg, _cloud, log, _args):
+ if not os.path.exists(helper_tool):
+ log.warn(("Unable to activate transform %s,"
+ " helper tool not found at %s"), name, helper_tool)
+ return
+
+ fp_blacklist = util.get_cfg_option_list(cfg,
"ssh_fp_console_blacklist", [])
- key_blacklist = util.get_cfg_option_list_or_str(cfg,
+ key_blacklist = util.get_cfg_option_list(cfg,
"ssh_key_console_blacklist", ["ssh-dss"])
+
try:
+ cmd = [helper_tool]
cmd.append(','.join(fp_blacklist))
cmd.append(','.join(key_blacklist))
- (stdout, stderr) = util.subp(cmd)
+ (stdout, _stderr) = util.subp(cmd)
util.write_file('/dev/console', stdout)
except:
- log.warn("Writing keys to console failed!")
+ log.warn("Writing keys to /dev/console failed!")
raise
diff --git a/cloudinit/transforms/cc_landscape.py b/cloudinit/transforms/cc_landscape.py
index 48491992..19948d0e 100644
--- a/cloudinit/transforms/cc_landscape.py
+++ b/cloudinit/transforms/cc_landscape.py
@@ -55,7 +55,8 @@ def handle(name, cfg, _cloud, log, _args):
/etc/landscape/client.conf
"""
if not ConfigObj:
- log.warn("'ConfigObj' support not enabled, running %s disabled", name)
+ log.warn(("'ConfigObj' support not available,"
+ " running transform %s disabled"), name)
return
ls_cloudcfg = cfg.get("landscape", {})
diff --git a/cloudinit/transforms/cc_locale.py b/cloudinit/transforms/cc_locale.py
index 3fb4c5d9..7f273123 100644
--- a/cloudinit/transforms/cc_locale.py
+++ b/cloudinit/transforms/cc_locale.py
@@ -49,7 +49,7 @@ def handle(name, cfg, cloud, log, args):
"/etc/default/locale")
if not locale:
- log.debug(("Skipping module named %s, "
+ log.debug(("Skipping transform named %s, "
"no 'locale' configuration found"), name)
return
diff --git a/cloudinit/transforms/cc_mcollective.py b/cloudinit/transforms/cc_mcollective.py
index aeeda9d2..5464fe8c 100644
--- a/cloudinit/transforms/cc_mcollective.py
+++ b/cloudinit/transforms/cc_mcollective.py
@@ -19,13 +19,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from ConfigParser import ConfigParser
from StringIO import StringIO
-import os
-
+from cloudinit import cfg as config
from cloudinit import util
-from cloudinit import cfg
pubcert_file = "/etc/mcollective/ssl/server-public.pem"
pricert_file = "/etc/mcollective/ssl/server-private.pem"
@@ -35,7 +32,7 @@ def handle(name, cfg, cloud, log, _args):
# If there isn't a mcollective key in the configuration don't do anything
if 'mcollective' not in cfg:
- log.debug(("Skipping module named %s, "
+ log.debug(("Skipping transform named %s, "
"no 'mcollective' key in configuration"), name)
return
@@ -47,7 +44,7 @@ def handle(name, cfg, cloud, log, _args):
# ... and then update the mcollective configuration
if 'conf' in mcollective_cfg:
# Create object for reading server.cfg values
- mcollective_config = cfg.DefaultingConfigParser()
+ mcollective_config = config.DefaultingConfigParser()
# Read server.cfg values from original file in order to be able to mix
# the rest up
old_contents = util.load_file('/etc/mcollective/server.cfg')
diff --git a/cloudinit/transforms/cc_mounts.py b/cloudinit/transforms/cc_mounts.py
index babcbda1..44182b87 100644
--- a/cloudinit/transforms/cc_mounts.py
+++ b/cloudinit/transforms/cc_mounts.py
@@ -20,7 +20,6 @@
from string import whitespace # pylint: disable=W0402
-import os
import re
from cloudinit import util
@@ -28,7 +27,7 @@ from cloudinit import util
# shortname matches 'sda', 'sda1', 'xvda', 'hda', 'sdb', xvdb, vda, vdd1
shortname_filter = r"^[x]{0,1}[shv]d[a-z][0-9]*$"
shortname = re.compile(shortname_filter)
-ws = re.compile("[%s]+" % whitespace)
+ws = re.compile("[%s]+" % (whitespace))
def is_mdname(name):
@@ -65,13 +64,14 @@ def handle(_name, cfg, cloud, log, _args):
continue
startname = str(cfgmnt[i][0])
- LOG.debug("Attempting to determine the real name of %s", startname)
+ log.debug("Attempting to determine the real name of %s", startname)
# workaround, allow user to specify 'ephemeral'
# rather than more ec2 correct 'ephemeral0'
if startname == "ephemeral":
cfgmnt[i][0] = "ephemeral0"
- log.debug("Adjusted mount option %s name from ephemeral to ephemeral0", (i + 1))
+ log.debug(("Adjusted mount option %s "
+ "name from ephemeral to ephemeral0"), (i + 1))
if is_mdname(startname):
newname = cloud.device_name_to_device(startname)
@@ -136,7 +136,8 @@ def handle(_name, cfg, cloud, log, _args):
break
if cfgmnt_has:
- log.debug("Not including %s, already previously included", startname)
+ log.debug(("Not including %s, already"
+ " previously included"), startname)
continue
cfgmnt.append(defmnt)
@@ -159,7 +160,7 @@ def handle(_name, cfg, cloud, log, _args):
dirs = []
for line in actlist:
# write 'comment' in the fs_mntops, entry, claiming this
- line[3] = "%s,comment=cloudconfig" % line[3]
+ line[3] = "%s,%s" % (line[3], comment)
if line[2] == "swap":
needswap = True
if line[1].startswith("/"):
@@ -168,7 +169,7 @@ def handle(_name, cfg, cloud, log, _args):
fstab_lines = []
fstab = util.load_file("/etc/fstab")
- for line in fstab.read().splitlines():
+ for line in fstab.splitlines():
try:
toks = ws.split(line)
if toks[3].find(comment) != -1:
diff --git a/cloudinit/transforms/cc_phone_home.py b/cloudinit/transforms/cc_phone_home.py
index 36af6dfa..98ff2b85 100644
--- a/cloudinit/transforms/cc_phone_home.py
+++ b/cloudinit/transforms/cc_phone_home.py
@@ -24,9 +24,8 @@ from cloudinit import util
from cloudinit.settings import PER_INSTANCE
-from time import sleep
-
frequency = PER_INSTANCE
+
post_list_all = ['pub_key_dsa', 'pub_key_rsa', 'pub_key_ecdsa',
'instance_id', 'hostname']
@@ -49,7 +48,7 @@ def handle(name, cfg, cloud, log, args):
ph_cfg = cfg['phone_home']
if 'url' not in ph_cfg:
- log.warn(("Skipping module named %s, "
+ log.warn(("Skipping transform named %s, "
"no 'url' found in 'phone_home' configuration"), name)
return
@@ -60,7 +59,8 @@ def handle(name, cfg, cloud, log, args):
tries = int(tries)
except:
tries = 10
- util.logexc(log, "Configuration entry 'tries' is not an integer, using %s", tries)
+ util.logexc(log, ("Configuration entry 'tries'"
+ " is not an integer, using %s instead"), tries)
if post_list == "all":
post_list = post_list_all
@@ -75,23 +75,37 @@ def handle(name, cfg, cloud, log, args):
'pub_key_ecdsa': '/etc/ssh/ssh_host_ecdsa_key.pub',
}
- for n, path in pubkeys.iteritems():
+ for (n, path) in pubkeys.iteritems():
try:
all_keys[n] = util.load_file(path)
except:
- util.logexc(log, "%s: failed to open, can not phone home that data", path)
+ util.logexc(log, ("%s: failed to open, can not"
+ " phone home that data"), path)
submit_keys = {}
for k in post_list:
if k in all_keys:
submit_keys[k] = all_keys[k]
else:
- submit_keys[k] = "N/A"
- log.warn("Requested key %s from 'post' configuration list not available", k)
+ submit_keys[k] = None
+ log.warn(("Requested key %s from 'post'"
+ " configuration list not available"), k)
- url = templater.render_string(url, {'INSTANCE_ID': all_keys['instance_id']})
+ # Get them read to be posted
+ real_submit_keys = {}
+ for (k, v) in submit_keys.iteritems():
+ if v is None:
+ real_submit_keys[k] = 'N/A'
+ else:
+ real_submit_keys[k] = str(v)
+ # Incase the url is parameterized
+ url_params = {
+ 'INSTANCE_ID': all_keys['instance_id'],
+ }
+ url = templater.render_string(url, url_params)
try:
- uhelp.readurl(url, data=submit_keys, retries=tries, sec_between=3)
+ uhelp.readurl(url, data=real_submit_keys, retries=tries, sec_between=3)
except:
- util.logexc(log, "Failed to post phone home data to %s in %s tries", url, tries)
+ util.logexc(log, ("Failed to post phone home data to"
+ " %s in %s tries"), url, tries)
diff --git a/cloudinit/transforms/cc_puppet.py b/cloudinit/transforms/cc_puppet.py
index 0a21a929..76cc9732 100644
--- a/cloudinit/transforms/cc_puppet.py
+++ b/cloudinit/transforms/cc_puppet.py
@@ -24,31 +24,32 @@ import os
import pwd
import socket
+from cloudinit import cfg as config
from cloudinit import util
-from cloudinit import cfg
def handle(name, cfg, cloud, log, _args):
# If there isn't a puppet key in the configuration don't do anything
if 'puppet' not in cfg:
- log.debug(("Skipping module named %s,"
+ log.debug(("Skipping transform named %s,"
" no 'puppet' configuration found"), name)
return
puppet_cfg = cfg['puppet']
# Start by installing the puppet package ...
- cloud.distro.install_packages(("puppet",))
+ cloud.distro.install_packages(["puppet"])
# ... and then update the puppet configuration
if 'conf' in puppet_cfg:
# Add all sections from the conf object to puppet.conf
contents = util.load_file('/etc/puppet/puppet.conf')
# Create object for reading puppet.conf values
- puppet_config = cfg.DefaultingConfigParser()
+ puppet_config = config.DefaultingConfigParser()
# Read puppet.conf values from original file in order to be able to
# mix the rest up. First clean them up (TODO is this really needed??)
- cleaned_contents = '\n'.join([i.lstrip() for i in contents.splitlines()])
+ cleaned_lines = [i.lstrip() for i in contents.splitlines()]
+ cleaned_contents = '\n'.join(cleaned_lines)
puppet_config.readfp(StringIO(cleaned_contents),
filename='/etc/puppet/puppet.conf')
for (cfg_name, cfg) in puppet_cfg['conf'].iteritems():
@@ -81,7 +82,8 @@ def handle(name, cfg, cloud, log, _args):
puppet_config.set(cfg_name, o, v)
# We got all our config as wanted we'll rename
# the previous puppet.conf and create our new one
- util.rename('/etc/puppet/puppet.conf', '/etc/puppet/puppet.conf.old')
+ util.rename('/etc/puppet/puppet.conf',
+ '/etc/puppet/puppet.conf.old')
contents = puppet_config.stringify()
util.write_file('/etc/puppet/puppet.conf', contents)
@@ -91,7 +93,8 @@ def handle(name, cfg, cloud, log, _args):
'-e', 's/^START=.*/START=yes/',
'/etc/default/puppet'], capture=False)
elif os.path.exists('/bin/systemctl'):
- util.subp(['/bin/systemctl', 'enable', 'puppet.service'], capture=False)
+ util.subp(['/bin/systemctl', 'enable', 'puppet.service'],
+ capture=False)
elif os.path.exists('/sbin/chkconfig'):
util.subp(['/sbin/chkconfig', 'puppet', 'on'], capture=False)
else:
diff --git a/cloudinit/transforms/cc_resizefs.py b/cloudinit/transforms/cc_resizefs.py
index daaf4da9..fe012417 100644
--- a/cloudinit/transforms/cc_resizefs.py
+++ b/cloudinit/transforms/cc_resizefs.py
@@ -18,11 +18,8 @@
# 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 errno
import os
import stat
-import sys
-import tempfile
import time
from cloudinit import util
@@ -46,15 +43,18 @@ def nodeify_path(devpth, where, log):
if util.is_container():
log.debug("Inside container, ignoring mknod failure in resizefs")
return
- log.warn("Failed to make device node to resize %s at %s", where, devpth)
+ log.warn("Failed to make device node to resize %s at %s",
+ where, devpth)
raise
def get_fs_type(st_dev, path, log):
try:
- fs_type = util.find_devs_with(tag='TYPE', oformat='value',
+ dev_entries = util.find_devs_with(tag='TYPE', oformat='value',
no_cache=True, path=path)
- return fs_type
+ if not dev_entries:
+ return None
+ return dev_entries[0].strip()
except util.ProcessExecutionError:
util.logexc(log, ("Failed to get filesystem type"
" of maj=%s, min=%s for path %s"),
@@ -69,12 +69,16 @@ def handle(name, cfg, _cloud, log, args):
resize_root = util.get_cfg_option_str(cfg, "resize_rootfs", True)
if not util.translate_bool(resize_root):
- log.debug("Skipping module named %s, resizing disabled", name)
+ log.debug("Skipping transform named %s, resizing disabled", name)
return
# TODO is the directory ok to be used??
resize_root_d = util.get_cfg_option_str(cfg, "resize_rootfs_tmp", "/run")
util.ensure_dir(resize_root_d)
+
+ # TODO: allow what is to be resized to
+ # be configurable??
+ resize_what = "/"
with util.SilentTemporaryFile(prefix="cloudinit.resizefs.",
dir=resize_root_d, delete=True) as tfh:
devpth = tfh.name
@@ -86,23 +90,25 @@ def handle(name, cfg, _cloud, log, args):
# auto deletion
tfh.unlink_now()
- # TODO: allow what is to be resized to
- # be configurable??
- st_dev = nodeify_path(devpth, "/", log)
- fs_type = get_fs_type(st_dev, devpath, log)
+ st_dev = nodeify_path(devpth, resize_what, log)
+ fs_type = get_fs_type(st_dev, devpth, log)
+ if not fs_type:
+ log.warn("Could not determine filesystem type of %s", resize_what)
+ return
resizer = None
- fstype_lc = fstype.lower()
+ fstype_lc = fs_type.lower()
for (pfix, root_cmd) in resize_fs_prefixes_cmds:
if fstype_lc.startswith(pfix):
resizer = root_cmd
break
if not resizer:
- log.warn("Not resizing unknown filesystem type %s", fs_type)
+ log.warn("Not resizing unknown filesystem type %s for %s",
+ fs_type, resize_what)
return
- log.debug("Resizing using %s", resizer)
+ log.debug("Resizing %s (%s) using %s", resize_what, fs_type, resizer)
resize_cmd = [resizer, devpth]
if resize_root == "noblock":
@@ -125,8 +131,8 @@ def do_resize(resize_cmd, log):
start = time.time()
try:
util.subp(resize_cmd)
- except util.ProcessExecutionError as e:
- util.logexc(log, "Failed to resize filesystem (using %s)", resize_cmd)
+ except util.ProcessExecutionError:
+ util.logexc(log, "Failed to resize filesystem (cmd=%s)", resize_cmd)
raise
tot_time = int(time.time() - start)
log.debug("Resizing took %s seconds", tot_time)
diff --git a/cloudinit/transforms/cc_rightscale_userdata.py b/cloudinit/transforms/cc_rightscale_userdata.py
index cde11b54..40d76c89 100644
--- a/cloudinit/transforms/cc_rightscale_userdata.py
+++ b/cloudinit/transforms/cc_rightscale_userdata.py
@@ -53,16 +53,19 @@ def handle(name, _cfg, cloud, log, _args):
try:
ud = cloud.get_userdata_raw()
except:
- log.warn("Failed to get raw userdata in module %s", name)
+ log.warn("Failed to get raw userdata in transform %s", name)
return
try:
mdict = parse_qs(ud)
if not mdict or not my_hookname in mdict:
- log.debug("Skipping module %s, did not find %s in parsed raw userdata", name, my_hookname)
+ log.debug(("Skipping transform %s, "
+ "did not find %s in parsed"
+ " raw userdata"), name, my_hookname)
return
except:
- log.warn("Failed to parse query string %s into a dictionary", ud)
+ util.logexc(log, ("Failed to parse query string %s"
+ " into a dictionary"), ud)
raise
wrote_fns = []
@@ -83,7 +86,8 @@ def handle(name, _cfg, cloud, log, _args):
wrote_fns.append(fname)
except Exception as e:
captured_excps.append(e)
- util.logexc(log, "%s failed to read %s and write %s", my_name, url, fname)
+ util.logexc(log, "%s failed to read %s and write %s",
+ my_name, url, fname)
if wrote_fns:
log.debug("Wrote out rightscale userdata to %s files", len(wrote_fns))
@@ -93,6 +97,6 @@ def handle(name, _cfg, cloud, log, _args):
log.debug("%s urls were skipped or failed", skipped)
if captured_excps:
- log.warn("%s failed with exceptions, re-raising the last one", len(captured_excps))
+ log.warn("%s failed with exceptions, re-raising the last one",
+ len(captured_excps))
raise captured_excps[-1]
-
diff --git a/cloudinit/transforms/cc_rsyslog.py b/cloudinit/transforms/cc_rsyslog.py
index ccbe68ff..71b74711 100644
--- a/cloudinit/transforms/cc_rsyslog.py
+++ b/cloudinit/transforms/cc_rsyslog.py
@@ -36,7 +36,8 @@ def handle(name, cfg, cloud, log, _args):
# process 'rsyslog'
if not 'rsyslog' in cfg:
- log.debug("Skipping module named %s, no 'rsyslog' key in configuration", name)
+ log.debug(("Skipping transform named %s,"
+ " no 'rsyslog' key in configuration"), name)
return
def_dir = cfg.get('rsyslog_dir', DEF_DIR)
@@ -62,15 +63,16 @@ def handle(name, cfg, cloud, log, _args):
if not filename.startswith("/"):
filename = os.path.join(def_dir, filename)
+ # Truncate filename first time you see it
omode = "ab"
- # truncate filename first time you see it
if filename not in files:
omode = "wb"
files.append(filename)
try:
- util.write_file(filename, content + "\n", omode=omode)
- except Exception as e:
+ contents = "%s\n" % (content)
+ util.write_file(filename, contents, omode=omode)
+ except Exception:
util.logexc(log, "Failed to write to %s", filename)
# Attempt to restart syslogd
@@ -87,8 +89,8 @@ def handle(name, cfg, cloud, log, _args):
log.debug("Restarting rsyslog")
util.subp(['service', 'rsyslog', 'restart'])
restarted = True
- except Exception as e:
- util.logexc("Failed restarting rsyslog")
+ except Exception:
+ util.logexc(log, "Failed restarting rsyslog")
if restarted:
# This only needs to run if we *actually* restarted
diff --git a/cloudinit/transforms/cc_runcmd.py b/cloudinit/transforms/cc_runcmd.py
index 19c0e721..31a254a5 100644
--- a/cloudinit/transforms/cc_runcmd.py
+++ b/cloudinit/transforms/cc_runcmd.py
@@ -25,13 +25,14 @@ from cloudinit import util
def handle(name, cfg, cloud, log, _args):
if "runcmd" not in cfg:
- log.debug("Skipping module named %s, no 'runcmd' key in configuration", name)
+ log.debug(("Skipping transform named %s,"
+ " no 'runcmd' key in configuration"), name)
return
- outfile = os.path.join(cloud.get_ipath('scripts'), "runcmd")
+ out_fn = os.path.join(cloud.get_ipath('scripts'), "runcmd")
cmd = cfg["runcmd"]
try:
content = util.shellify(cmd)
- util.write_file(outfile, content, 0700)
+ util.write_file(out_fn, content, 0700)
except:
- util.logexc(log, "Failed to shellify %s into file %s", cmd, outfile)
+ util.logexc(log, "Failed to shellify %s into file %s", cmd, out_fn)
diff --git a/cloudinit/transforms/cc_salt_minion.py b/cloudinit/transforms/cc_salt_minion.py
index 47cbc194..d05d2a1e 100644
--- a/cloudinit/transforms/cc_salt_minion.py
+++ b/cloudinit/transforms/cc_salt_minion.py
@@ -21,16 +21,17 @@ from cloudinit import util
# Note: see http://saltstack.org/topics/installation/
-def handle(name, cfg, cloud, _log, _args):
+def handle(name, cfg, cloud, log, _args):
# If there isn't a salt key in the configuration don't do anything
if 'salt_minion' not in cfg:
- log.debug("Skipping module named %s, no 'salt_minion' key in configuration", name)
+ log.debug(("Skipping transform named %s,"
+ " no 'salt_minion' key in configuration"), name)
return
salt_cfg = cfg['salt_minion']
# Start by installing the salt package ...
- cloud.distro.install_packages(("salt",))
+ cloud.distro.install_packages(["salt"])
# Ensure we can configure files at the right dir
config_dir = salt_cfg.get("config_dir", '/etc/salt')
diff --git a/cloudinit/transforms/cc_scripts_per_boot.py b/cloudinit/transforms/cc_scripts_per_boot.py
index bcdf4400..364e1d02 100644
--- a/cloudinit/transforms/cc_scripts_per_boot.py
+++ b/cloudinit/transforms/cc_scripts_per_boot.py
@@ -29,12 +29,13 @@ frequency = PER_ALWAYS
script_subdir = 'per-boot'
-def handle(_name, _cfg, cloud, log, _args):
+def handle(name, _cfg, cloud, log, _args):
# Comes from the following:
# https://forums.aws.amazon.com/thread.jspa?threadID=96918
runparts_path = os.path.join(cloud.get_cpath(), 'scripts', script_subdir)
try:
util.runparts(runparts_path)
except:
- log.warn("Failed to run-parts(%s) in %s", script_subdir, runparts_path)
+ log.warn("Failed to run transform %s (%s in %s)",
+ name, script_subdir, runparts_path)
raise
diff --git a/cloudinit/transforms/cc_scripts_per_instance.py b/cloudinit/transforms/cc_scripts_per_instance.py
index 8d6609a1..d75ab47d 100644
--- a/cloudinit/transforms/cc_scripts_per_instance.py
+++ b/cloudinit/transforms/cc_scripts_per_instance.py
@@ -29,12 +29,13 @@ frequency = PER_INSTANCE
script_subdir = 'per-instance'
-def handle(_name, _cfg, cloud, log, _args):
+def handle(name, _cfg, cloud, log, _args):
# Comes from the following:
# https://forums.aws.amazon.com/thread.jspa?threadID=96918
runparts_path = os.path.join(cloud.get_cpath(), 'scripts', script_subdir)
try:
util.runparts(runparts_path)
except:
- log.warn("Failed to run-parts(%s) in %s", script_subdir, runparts_path)
+ log.warn("Failed to run transform %s (%s in %s)",
+ name, script_subdir, runparts_path)
raise
diff --git a/cloudinit/transforms/cc_scripts_per_once.py b/cloudinit/transforms/cc_scripts_per_once.py
index dbcec05d..80f8c325 100644
--- a/cloudinit/transforms/cc_scripts_per_once.py
+++ b/cloudinit/transforms/cc_scripts_per_once.py
@@ -29,12 +29,13 @@ frequency = PER_ONCE
script_subdir = 'per-once'
-def handle(_name, _cfg, cloud, log, _args):
+def handle(name, _cfg, cloud, log, _args):
# Comes from the following:
# https://forums.aws.amazon.com/thread.jspa?threadID=96918
runparts_path = os.path.join(cloud.get_cpath(), 'scripts', script_subdir)
try:
util.runparts(runparts_path)
except:
- log.warn("Failed to run-parts(%s) in %s", script_subdir, runparts_path)
+ log.warn("Failed to run transform %s (%s in %s)",
+ name, script_subdir, runparts_path)
raise
diff --git a/cloudinit/transforms/cc_scripts_user.py b/cloudinit/transforms/cc_scripts_user.py
index 1e438ee6..f4fe3a2a 100644
--- a/cloudinit/transforms/cc_scripts_user.py
+++ b/cloudinit/transforms/cc_scripts_user.py
@@ -26,14 +26,17 @@ from cloudinit.settings import PER_INSTANCE
frequency = PER_INSTANCE
+script_subdir = 'scripts'
-def handle(_name, _cfg, cloud, log, _args):
+
+def handle(name, _cfg, cloud, log, _args):
# This is written to by the user data handlers
# Ie, any custom shell scripts that come down
# go here...
- runparts_path = os.path.join(cloud.get_ipath_cur(), "scripts")
+ runparts_path = os.path.join(cloud.get_ipath_cur(), script_subdir)
try:
util.runparts(runparts_path)
except:
- log.warn("Failed to run-parts(%s) in %s", "user-data", runparts_path)
+ log.warn("Failed to run transform %s (%s in %s)",
+ name, script_subdir, runparts_path)
raise
diff --git a/cloudinit/transforms/cc_set_hostname.py b/cloudinit/transforms/cc_set_hostname.py
index fa2b59c2..3ac8a8fa 100644
--- a/cloudinit/transforms/cc_set_hostname.py
+++ b/cloudinit/transforms/cc_set_hostname.py
@@ -24,7 +24,7 @@ from cloudinit import util
def handle(name, cfg, cloud, log, _args):
if util.get_cfg_option_bool(cfg, "preserve_hostname", False):
log.debug(("Configuration option 'preserve_hostname' is set,"
- " not setting the hostname in %s"), name)
+ " not setting the hostname in transform %s"), name)
return
(hostname, _fqdn) = util.get_hostname_fqdn(cfg, cloud)
diff --git a/cloudinit/transforms/cc_set_passwords.py b/cloudinit/transforms/cc_set_passwords.py
index 4f2cdb97..c0cc4e84 100644
--- a/cloudinit/transforms/cc_set_passwords.py
+++ b/cloudinit/transforms/cc_set_passwords.py
@@ -22,7 +22,7 @@ import sys
from cloudinit import util
-from string import letters, digits
+from string import letters, digits # pylint: disable=W0402
# We are removing certain 'painful' letters/numbers
pw_set = (letters.translate(None, 'loLOI') +
@@ -71,11 +71,13 @@ def handle(_name, cfg, cloud, log, args):
util.subp(['chpasswd'], ch_in)
except Exception as e:
errors.append(e)
- util.logexc(log, "Failed to set passwords with chpasswd for %s", users)
+ util.logexc(log,
+ "Failed to set passwords with chpasswd for %s", users)
if len(randlist):
- sys.stderr.write("%s\n%s\n" % ("Set the following 'random' passwords\n",
- '\n'.join(randlist)))
+ blurb = ("Set the following 'random' passwords\n",
+ '\n'.join(randlist))
+ sys.stderr.write("%s\n%s\n" % blurb)
if expire:
expired_users = []
diff --git a/cloudinit/transforms/cc_ssh.py b/cloudinit/transforms/cc_ssh.py
index db6848d9..3c2b3622 100644
--- a/cloudinit/transforms/cc_ssh.py
+++ b/cloudinit/transforms/cc_ssh.py
@@ -65,8 +65,7 @@ def handle(_name, cfg, cloud, log, _args):
tgt_fn = key2file[key][0]
tgt_perms = key2file[key][1]
util.write_file(tgt_fn, val, tgt_perms)
-
- cmd = 'o=$(ssh-keygen -yf "%s") && echo "$o" root@localhost > "%s"'
+
for priv, pub in priv2pub.iteritems():
if pub in cfg['ssh_keys'] or not priv in cfg['ssh_keys']:
continue
@@ -78,11 +77,15 @@ def handle(_name, cfg, cloud, log, _args):
util.subp(cmd, capture=False)
log.debug("Generated a key for %s from %s", pair[0], pair[1])
except:
- util.logexc(log, "Failed generated a key for %s from %s", pair[0], pair[1])
+ util.logexc(log, ("Failed generated a key"
+ " for %s from %s"), pair[0], pair[1])
else:
# if not, generate them
- for keytype in util.get_cfg_option_list_or_str(cfg, 'ssh_genkeytypes', generate_keys):
- keyfile = '/etc/ssh/ssh_host_%s_key' % keytype
+ genkeys = util.get_cfg_option_list(cfg,
+ 'ssh_genkeytypes',
+ generate_keys)
+ for keytype in genkeys:
+ keyfile = '/etc/ssh/ssh_host_%s_key' % (keytype)
if not os.path.exists(keyfile):
cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile]
try:
@@ -90,26 +93,27 @@ def handle(_name, cfg, cloud, log, _args):
with util.SeLinuxGuard("/etc/ssh", recursive=True):
util.subp(cmd, capture=False)
except:
- util.logexc(log, "Failed generating key type %s to file %s", keytype, keyfile)
+ util.logexc(log, ("Failed generating key type"
+ " %s to file %s"), keytype, keyfile)
try:
user = util.get_cfg_option_str(cfg, 'user')
disable_root = util.get_cfg_option_bool(cfg, "disable_root", True)
disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts",
- DISABLE_ROOT_OPTS)
+ DISABLE_ROOT_OPTS)
keys = cloud.get_public_ssh_keys() or []
if "ssh_authorized_keys" in cfg:
cfgkeys = cfg["ssh_authorized_keys"]
keys.extend(cfgkeys)
- apply_credentials(keys, user, disable_root, disable_root_opts, log)
+ apply_credentials(keys, user, disable_root, disable_root_opts)
except:
util.logexc(log, "Applying ssh credentials failed!")
def apply_credentials(keys, user, disable_root,
- disable_root_opts=DISABLE_ROOT_OPTS, log=None):
+ disable_root_opts=DISABLE_ROOT_OPTS):
keys = set(keys)
if user:
diff --git a/cloudinit/transforms/cc_ssh_import_id.py b/cloudinit/transforms/cc_ssh_import_id.py
index 019413d4..d57e4665 100644
--- a/cloudinit/transforms/cc_ssh_import_id.py
+++ b/cloudinit/transforms/cc_ssh_import_id.py
@@ -33,10 +33,14 @@ def handle(name, cfg, _cloud, log, args):
ids = args[1:]
else:
user = util.get_cfg_option_str(cfg, "user", "ubuntu")
- ids = util.get_cfg_option_list_or_str(cfg, "ssh_import_id", [])
+ ids = util.get_cfg_option_list(cfg, "ssh_import_id", [])
if len(ids) == 0:
- log.debug("Skipping module named %s, no ids found to import", name)
+ log.debug("Skipping transform named %s, no ids found to import", name)
+ return
+
+ if not user:
+ log.debug("Skipping transform named %s, no user found to import", name)
return
cmd = ["sudo", "-Hu", user, "ssh-import-id"] + ids
diff --git a/cloudinit/transforms/cc_timezone.py b/cloudinit/transforms/cc_timezone.py
index 02cbf2dc..747c436c 100644
--- a/cloudinit/transforms/cc_timezone.py
+++ b/cloudinit/transforms/cc_timezone.py
@@ -18,20 +18,22 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from cloudinit import util
+
from cloudinit.settings import PER_INSTANCE
frequency = PER_INSTANCE
-def handle(_name, cfg, cloud, log, args):
+def handle(name, cfg, cloud, log, args):
if len(args) != 0:
timezone = args[0]
else:
timezone = util.get_cfg_option_str(cfg, "timezone", False)
if not timezone:
- log.debug("Skipping module named %s, no 'timezone' specified", name)
+ log.debug("Skipping transform named %s, no 'timezone' specified", name)
return
-
+
# Let the distro handle settings its timezone
cloud.distro.set_timezone(timezone)
diff --git a/cloudinit/transforms/cc_update_etc_hosts.py b/cloudinit/transforms/cc_update_etc_hosts.py
index 361097a6..d0e56183 100644
--- a/cloudinit/transforms/cc_update_etc_hosts.py
+++ b/cloudinit/transforms/cc_update_etc_hosts.py
@@ -30,22 +30,30 @@ def handle(name, cfg, cloud, log, _args):
manage_hosts = util.get_cfg_option_str(cfg, "manage_etc_hosts", False)
if util.translate_bool(manage_hosts, addons=['template']):
(hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
- # Render from template file
if not hostname:
- log.warn("Option 'manage_etc_hosts' was set, but no hostname was found")
+ log.warn(("Option 'manage_etc_hosts' was set,"
+ " but no hostname was found"))
return
- tpl_fn_name = cloud.get_template_filename("hosts.%s" % (cloud.distro.name()))
+
+ # Render from a template file
+ distro_n = cloud.distro.name
+ tpl_fn_name = cloud.get_template_filename("hosts.%s" % (distro_n))
if not tpl_fn_name:
- raise Exception("No hosts template could be found for distro %s" % (cloud.distro.name()))
+ raise Exception(("No hosts template could be"
+ " found for distro %s") % (distro_n))
+
templater.render_to_file(tpl_fn_name, '/etc/hosts',
{'hostname': hostname, 'fqdn': fqdn})
+
elif manage_hosts == "localhost":
- log.debug("Managing localhost in /etc/hosts")
(hostname, fqdn) = util.get_hostname_fqdn(cfg, cloud)
if not hostname:
- log.warn("Option 'manage_etc_hosts' was set, but no hostname was found")
+ log.warn(("Option 'manage_etc_hosts' was set,"
+ " but no hostname was found"))
return
+
+ log.debug("Managing localhost in /etc/hosts")
cloud.distro.update_etc_hosts(hostname, fqdn)
else:
log.debug(("Configuration option 'manage_etc_hosts' is not set,"
- " not managing /etc/hosts in %s"), name)
+ " not managing /etc/hosts in transform %s"), name)
diff --git a/cloudinit/transforms/cc_update_hostname.py b/cloudinit/transforms/cc_update_hostname.py
index 439bdcb3..58444fab 100644
--- a/cloudinit/transforms/cc_update_hostname.py
+++ b/cloudinit/transforms/cc_update_hostname.py
@@ -18,6 +18,8 @@
# 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 util
from cloudinit.settings import PER_ALWAYS
@@ -27,7 +29,7 @@ frequency = PER_ALWAYS
def handle(name, cfg, cloud, log, _args):
if util.get_cfg_option_bool(cfg, "preserve_hostname", False):
log.debug(("Configuration option 'preserve_hostname' is set,"
- " not updating the hostname in %s"), name)
+ " not updating the hostname in transform %s"), name)
return
(hostname, _fqdn) = util.get_hostname_fqdn(cfg, cloud)
diff --git a/cloudinit/transforms/cc_welcome.py b/cloudinit/transforms/cc_welcome.py
index 0db71125..04691d21 100644
--- a/cloudinit/transforms/cc_welcome.py
+++ b/cloudinit/transforms/cc_welcome.py
@@ -35,9 +35,9 @@ welcome_message_def = ("Cloud-init v. {{version}} starting stage {{stage}} at "
frequency = PER_ALWAYS
-def handle(name, cfg, cloud, log, args):
+def handle(_name, cfg, cloud, log, args):
- welcome_msg = util.get_cfg_option_str(cfg, "welcome_msg"):
+ welcome_msg = util.get_cfg_option_str(cfg, "welcome_msg")
if not welcome_msg:
tpl_fn = cloud.get_template_filename("welcome_msg")
if tpl_fn:
@@ -54,7 +54,7 @@ def handle(name, cfg, cloud, log, args):
'stage': stage,
'version': version.version_string(),
'uptime': util.uptime(),
- 'timestamp', util.time_rfc2822(),
+ 'timestamp': util.time_rfc2822(),
}
try:
contents = templater.render_string(welcome_msg, tpl_params)
diff --git a/cloudinit/user_data.py b/cloudinit/user_data.py
index 64fc2734..9915b8b0 100644
--- a/cloudinit/user_data.py
+++ b/cloudinit/user_data.py
@@ -22,14 +22,15 @@
import os
-import glob
import email
-
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from cloudinit import importer
from cloudinit import log as logging
+from cloudinit import url_helper
from cloudinit import util
from cloudinit.settings import (PER_ALWAYS, PER_INSTANCE, FREQUENCIES)
@@ -86,7 +87,7 @@ class UserDataProcessor(object):
self.paths = paths
def process(self, blob):
- base_msg = ud.convert_string(blob)
+ base_msg = convert_string(blob)
process_msg = MIMEMultipart()
self._process_msg(base_msg, process_msg)
return process_msg
@@ -105,7 +106,7 @@ class UserDataProcessor(object):
ctype_orig = UNDEF_TYPE
if ctype_orig in TYPE_NEEDED:
- ctype = ud.type_from_starts_with(payload)
+ ctype = type_from_starts_with(payload)
if ctype is None:
ctype = ctype_orig
@@ -158,7 +159,7 @@ class UserDataProcessor(object):
if not url_helper.ok_http_code(st):
content = ''
- new_msg = ud.convert_string(content)
+ new_msg = convert_string(content)
self._process_msg(new_msg, append_msg)
def _explode_archive(self, archive, append_msg):
@@ -179,7 +180,7 @@ class UserDataProcessor(object):
content = ent.get('content', '')
mtype = ent.get('type')
if not mtype:
- mtype = ud.type_from_starts_with(content, ARCHIVE_UNDEF_TYPE)
+ mtype = type_from_starts_with(content, ARCHIVE_UNDEF_TYPE)
maintype, subtype = mtype.split('/', 1)
if maintype == "text":
diff --git a/cloudinit/util.py b/cloudinit/util.py
index 7259d933..1f884df8 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -22,8 +22,8 @@
from StringIO import StringIO
+import copy as obj_copy
import contextlib
-import copy
import errno
import glob
import grp
@@ -35,12 +35,11 @@ import pwd
import random
import shutil
import socket
-import string
+import string # pylint: disable=W0402
import subprocess
import sys
import tempfile
import time
-import traceback
import types
import urlparse
@@ -171,7 +170,8 @@ def fork_cb(child_cb, *args):
child_cb(*args)
os._exit(0) # pylint: disable=W0212
except:
- logexc(LOG, "Failed forking and calling callback %s", obj_name(child_cb))
+ logexc(LOG, ("Failed forking and"
+ " calling callback %s"), obj_name(child_cb))
os._exit(1) # pylint: disable=W0212
else:
LOG.debug("Forked child %s who will run callback %s",
@@ -549,10 +549,11 @@ def load_yaml(blob, default=None, allowed=(dict,)):
converted = yaml.load(blob)
if not isinstance(converted, allowed):
# Yes this will just be caught, but thats ok for now...
- raise TypeError("Yaml load allows %s root types, but got %s instead" %
+ raise TypeError(("Yaml load allows %s root types,"
+ " but got %s instead") %
(allowed, obj_name(converted)))
loaded = converted
- except (yaml.YAMLError, TypeError, ValueError) as exc:
+ except (yaml.YAMLError, TypeError, ValueError):
logexc(LOG, "Failed loading yaml blob")
return loaded
@@ -833,15 +834,12 @@ def find_devs_with(criteria=None, oformat='device',
options.append(path)
cmd = blk_id_cmd + options
(out, _err) = subp(cmd)
- if path:
- return out.strip()
- else:
- entries = []
- for line in out.splitlines():
- line = line.strip()
- if line:
- entries.append(line)
- return entries
+ entries = []
+ for line in out.splitlines():
+ line = line.strip()
+ if line:
+ entries.append(line)
+ return entries
def load_file(fname, read_cb=None, quiet=False):
@@ -1109,7 +1107,7 @@ def mount_cb(device, callback, data=None, rw=False, mtype=None):
def get_builtin_cfg():
# Deep copy so that others can't modify
- return copy.deepcopy(CFG_BUILTIN)
+ return obj_copy.deepcopy(CFG_BUILTIN)
def sym_link(source, link):
@@ -1140,16 +1138,14 @@ def time_rfc2822():
def uptime():
+ uptime_str = '??'
try:
- uptimef = load_file("/proc/uptime").strip()
- if not uptimef:
- uptime = 'na'
- else:
- uptime = uptimef.split()[0]
+ contents = load_file("/proc/uptime").strip()
+ if contents:
+ uptime_str = contents.split()[0]
except:
logexc(LOG, "Unable to read uptime from /proc/uptime")
- uptime = '??'
- return uptime
+ return uptime_str
def ensure_file(path):
@@ -1261,7 +1257,8 @@ def shellify(cmdlist, add_header=True):
content = "%s%s\n" % (content, args)
else:
raise RuntimeError(("Unable to shellify type %s"
- " which is not a list or string") % (obj_name(args)))
+ " which is not a list or string")
+ % (obj_name(args)))
LOG.debug("Shellified %s to %s", cmdlist, content)
return content
@@ -1275,8 +1272,7 @@ def is_container():
try:
# try to run a helper program. if it returns true/zero
# then we're inside a container. otherwise, no
- cmd = [helper]
- subp(cmd, allowed_rc=[0])
+ subp([helper])
return True
except (IOError, OSError):
pass