diff options
-rwxr-xr-x | bin/cloud-init | 49 | ||||
-rw-r--r-- | cloudinit/stages.py | 19 | ||||
-rw-r--r-- | tests/unittests/test_userdata.py | 10 |
3 files changed, 49 insertions, 29 deletions
diff --git a/bin/cloud-init b/bin/cloud-init index 0b879876..d3ef092f 100755 --- a/bin/cloud-init +++ b/bin/cloud-init @@ -34,13 +34,15 @@ if os.path.exists(os.path.join(possible_topdir, "cloudinit", "__init__.py")): from cloudinit import log as logging from cloudinit import netinfo -from cloudinit import settings from cloudinit import sources from cloudinit import stages from cloudinit import templater from cloudinit import util from cloudinit import version +from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE, + CLOUD_CONFIG) + # Module section template MOD_SECTION_TPL = "cloud_%s_modules" @@ -54,9 +56,9 @@ QUERY_DATA_TYPES = [ # Frequency shortname to full name FREQ_SHORT_NAMES = { - 'instance': settings.PER_INSTANCE, - 'always': settings.PER_ALWAYS, - 'once': settings.PER_ONCE, + 'instance': PER_INSTANCE, + 'always': PER_ALWAYS, + 'once': PER_ONCE, } LOG = logging.getLogger() @@ -111,8 +113,15 @@ def main_init(name, args): deps = [sources.DEP_FILESYSTEM] if not args.local: - # TODO: What is this for?? - root_name = "%s.d" % (settings.CLOUD_CONFIG) + # See doc/kernel-cmdline.txt + # + # This is used in maas datasource, in "ephemeral" (read-only root) + # environment where the instance netboots to iscsi ro root. + # and the entity that controls the pxe config has to configure + # the maas datasource. + # + # Could be used elsewhere, only works on network based (not local). + root_name = "%s.d" % (CLOUD_CONFIG) target_fn = os.path.join(root_name, "91_kernel_cmdline_url.cfg") util.read_write_cmdline_url(target_fn) @@ -194,22 +203,34 @@ def main_init(name, args): init.fetch() except sources.DataSourceNotFoundException: util.logexc(LOG, "No instance datasource found!") - # TODO: Return 0 or 1?? - return 1 + # In the case of cloud-init (net mode) it is a bit + # more likely that the user would consider it + # failure if nothing was found. When using + # upstart it will also mentions job failure + # in console log if exit code is != 0. + if args.local: + return 0 + else: + return 1 # Stage 6 iid = init.instancify() LOG.debug("%s will now be targeting instance id: %s", name, iid) init.update() # Stage 7 try: + # Attempt to consume the data per instance. + # This may run user-data handlers and/or perform + # url downloads and such as needed. (ran, _results) = init.cloudify().run('consume_userdata', - init.consume, - args=[settings.PER_INSTANCE], - freq=settings.PER_INSTANCE) + init.consume_userdata, + args=[PER_INSTANCE], + freq=PER_INSTANCE) if not ran: - # Just consume anything that is set to run per - # always if nothing ran in the per instance section - init.consume(settings.PER_ALWAYS) + # Just consume anything that is set to run per-always + # if nothing ran in the per-instance code + # + # TODO: should this always happen?? (even if the above runs?) + init.consume_userdata(PER_ALWAYS) except Exception: util.logexc(LOG, "Consuming user data failed!") return 1 diff --git a/cloudinit/stages.py b/cloudinit/stages.py index 47f6e188..6689e4c9 100644 --- a/cloudinit/stages.py +++ b/cloudinit/stages.py @@ -192,13 +192,13 @@ class Init(object): cfg_list = self.cfg.get('datasource_list') or [] return (cfg_list, pkg_list) - def _get_data_source(self, local_only=False): + def _get_data_source(self): if self.datasource: return self.datasource ds = self._restore_from_cache() if ds: LOG.debug("Restored from cache, datasource: %s", ds) - if not ds and not local_only: + if not ds: (cfg_list, pkg_list) = self._get_datasources() # Deep copy so that user-data handlers can not modify # (which will affect user-data handlers down the line...) @@ -209,11 +209,10 @@ class Init(object): cfg_list, pkg_list) LOG.debug("Loaded datasource %s - %s", dsname, ds) - if ds: - self.datasource = ds - # Ensure we adjust our path members datasource - # now that we have one (thus allowing ipath to be used) - self.paths.datasource = ds + self.datasource = ds + # Ensure we adjust our path members datasource + # now that we have one (thus allowing ipath to be used) + self.paths.datasource = ds return ds def _get_instance_subdirs(self): @@ -275,8 +274,8 @@ class Init(object): "%s\n" % (previous_iid)) return iid - def fetch(self, local_only=False): - return self._get_data_source(local_only) + def fetch(self): + return self._get_data_source() def instancify(self): return self._reflect_cur_instance() @@ -312,7 +311,7 @@ class Init(object): ] return def_handlers - def consume(self, frequency=PER_INSTANCE): + def consume_userdata(self, frequency=PER_INSTANCE): cdir = self.paths.get_cpath("handlers") idir = self._get_ipath("handlers") diff --git a/tests/unittests/test_userdata.py b/tests/unittests/test_userdata.py index eeddde7d..861642b6 100644 --- a/tests/unittests/test_userdata.py +++ b/tests/unittests/test_userdata.py @@ -68,7 +68,7 @@ class TestConsumeUserData(MockerTestCase): log_file = self.capture_log(logging.WARNING) ci.fetch() - ci.consume() + ci.consume_userdata() self.assertIn( "Unhandled non-multipart (text/x-not-multipart) userdata:", log_file.getvalue()) @@ -85,7 +85,7 @@ class TestConsumeUserData(MockerTestCase): log_file = self.capture_log(logging.WARNING) ci.fetch() - ci.consume() + ci.consume_userdata() self.assertIn( "Unhandled unknown content-type (text/plain)", log_file.getvalue()) @@ -104,7 +104,7 @@ class TestConsumeUserData(MockerTestCase): log_file = self.capture_log(logging.WARNING) ci.fetch() - ci.consume() + ci.consume_userdata() self.assertEqual("", log_file.getvalue()) def test_mime_text_x_shellscript(self): @@ -122,7 +122,7 @@ class TestConsumeUserData(MockerTestCase): log_file = self.capture_log(logging.WARNING) ci.fetch() - ci.consume() + ci.consume_userdata() self.assertEqual("", log_file.getvalue()) def test_mime_text_plain_shell(self): @@ -140,5 +140,5 @@ class TestConsumeUserData(MockerTestCase): log_file = self.capture_log(logging.WARNING) ci.fetch() - ci.consume() + ci.consume_userdata() self.assertEqual("", log_file.getvalue()) |