diff options
Diffstat (limited to 'cloudinit')
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 |