1. Update with smosers code review and comments (and put some of those comments into the files)

2. Rename consume() to consume_userdata() as it helps in figuring out what this does.
3. Fixup the tests due to #2
This commit is contained in:
Joshua Harlow 2012-06-28 15:13:19 -07:00
parent 29cad69e2e
commit a47bfae2ee
3 changed files with 49 additions and 29 deletions

View File

@ -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 log as logging
from cloudinit import netinfo from cloudinit import netinfo
from cloudinit import settings
from cloudinit import sources from cloudinit import sources
from cloudinit import stages from cloudinit import stages
from cloudinit import templater from cloudinit import templater
from cloudinit import util from cloudinit import util
from cloudinit import version from cloudinit import version
from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE,
CLOUD_CONFIG)
# Module section template # Module section template
MOD_SECTION_TPL = "cloud_%s_modules" MOD_SECTION_TPL = "cloud_%s_modules"
@ -54,9 +56,9 @@ QUERY_DATA_TYPES = [
# Frequency shortname to full name # Frequency shortname to full name
FREQ_SHORT_NAMES = { FREQ_SHORT_NAMES = {
'instance': settings.PER_INSTANCE, 'instance': PER_INSTANCE,
'always': settings.PER_ALWAYS, 'always': PER_ALWAYS,
'once': settings.PER_ONCE, 'once': PER_ONCE,
} }
LOG = logging.getLogger() LOG = logging.getLogger()
@ -111,8 +113,15 @@ def main_init(name, args):
deps = [sources.DEP_FILESYSTEM] deps = [sources.DEP_FILESYSTEM]
if not args.local: if not args.local:
# TODO: What is this for?? # See doc/kernel-cmdline.txt
root_name = "%s.d" % (settings.CLOUD_CONFIG) #
# 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") target_fn = os.path.join(root_name, "91_kernel_cmdline_url.cfg")
util.read_write_cmdline_url(target_fn) util.read_write_cmdline_url(target_fn)
@ -194,22 +203,34 @@ def main_init(name, args):
init.fetch() init.fetch()
except sources.DataSourceNotFoundException: except sources.DataSourceNotFoundException:
util.logexc(LOG, "No instance datasource found!") util.logexc(LOG, "No instance datasource found!")
# TODO: Return 0 or 1?? # In the case of cloud-init (net mode) it is a bit
return 1 # 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 # Stage 6
iid = init.instancify() iid = init.instancify()
LOG.debug("%s will now be targeting instance id: %s", name, iid) LOG.debug("%s will now be targeting instance id: %s", name, iid)
init.update() init.update()
# Stage 7 # Stage 7
try: 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', (ran, _results) = init.cloudify().run('consume_userdata',
init.consume, init.consume_userdata,
args=[settings.PER_INSTANCE], args=[PER_INSTANCE],
freq=settings.PER_INSTANCE) freq=PER_INSTANCE)
if not ran: if not ran:
# Just consume anything that is set to run per # Just consume anything that is set to run per-always
# always if nothing ran in the per instance section # if nothing ran in the per-instance code
init.consume(settings.PER_ALWAYS) #
# TODO: should this always happen?? (even if the above runs?)
init.consume_userdata(PER_ALWAYS)
except Exception: except Exception:
util.logexc(LOG, "Consuming user data failed!") util.logexc(LOG, "Consuming user data failed!")
return 1 return 1

View File

@ -192,13 +192,13 @@ class Init(object):
cfg_list = self.cfg.get('datasource_list') or [] cfg_list = self.cfg.get('datasource_list') or []
return (cfg_list, pkg_list) return (cfg_list, pkg_list)
def _get_data_source(self, local_only=False): def _get_data_source(self):
if self.datasource: if self.datasource:
return self.datasource return self.datasource
ds = self._restore_from_cache() ds = self._restore_from_cache()
if ds: if ds:
LOG.debug("Restored from cache, datasource: %s", 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() (cfg_list, pkg_list) = self._get_datasources()
# Deep copy so that user-data handlers can not modify # Deep copy so that user-data handlers can not modify
# (which will affect user-data handlers down the line...) # (which will affect user-data handlers down the line...)
@ -209,11 +209,10 @@ class Init(object):
cfg_list, cfg_list,
pkg_list) pkg_list)
LOG.debug("Loaded datasource %s - %s", dsname, ds) LOG.debug("Loaded datasource %s - %s", dsname, ds)
if ds: self.datasource = ds
self.datasource = ds # Ensure we adjust our path members datasource
# Ensure we adjust our path members datasource # now that we have one (thus allowing ipath to be used)
# now that we have one (thus allowing ipath to be used) self.paths.datasource = ds
self.paths.datasource = ds
return ds return ds
def _get_instance_subdirs(self): def _get_instance_subdirs(self):
@ -275,8 +274,8 @@ class Init(object):
"%s\n" % (previous_iid)) "%s\n" % (previous_iid))
return iid return iid
def fetch(self, local_only=False): def fetch(self):
return self._get_data_source(local_only) return self._get_data_source()
def instancify(self): def instancify(self):
return self._reflect_cur_instance() return self._reflect_cur_instance()
@ -312,7 +311,7 @@ class Init(object):
] ]
return def_handlers return def_handlers
def consume(self, frequency=PER_INSTANCE): def consume_userdata(self, frequency=PER_INSTANCE):
cdir = self.paths.get_cpath("handlers") cdir = self.paths.get_cpath("handlers")
idir = self._get_ipath("handlers") idir = self._get_ipath("handlers")

View File

@ -68,7 +68,7 @@ class TestConsumeUserData(MockerTestCase):
log_file = self.capture_log(logging.WARNING) log_file = self.capture_log(logging.WARNING)
ci.fetch() ci.fetch()
ci.consume() ci.consume_userdata()
self.assertIn( self.assertIn(
"Unhandled non-multipart (text/x-not-multipart) userdata:", "Unhandled non-multipart (text/x-not-multipart) userdata:",
log_file.getvalue()) log_file.getvalue())
@ -85,7 +85,7 @@ class TestConsumeUserData(MockerTestCase):
log_file = self.capture_log(logging.WARNING) log_file = self.capture_log(logging.WARNING)
ci.fetch() ci.fetch()
ci.consume() ci.consume_userdata()
self.assertIn( self.assertIn(
"Unhandled unknown content-type (text/plain)", "Unhandled unknown content-type (text/plain)",
log_file.getvalue()) log_file.getvalue())
@ -104,7 +104,7 @@ class TestConsumeUserData(MockerTestCase):
log_file = self.capture_log(logging.WARNING) log_file = self.capture_log(logging.WARNING)
ci.fetch() ci.fetch()
ci.consume() ci.consume_userdata()
self.assertEqual("", log_file.getvalue()) self.assertEqual("", log_file.getvalue())
def test_mime_text_x_shellscript(self): def test_mime_text_x_shellscript(self):
@ -122,7 +122,7 @@ class TestConsumeUserData(MockerTestCase):
log_file = self.capture_log(logging.WARNING) log_file = self.capture_log(logging.WARNING)
ci.fetch() ci.fetch()
ci.consume() ci.consume_userdata()
self.assertEqual("", log_file.getvalue()) self.assertEqual("", log_file.getvalue())
def test_mime_text_plain_shell(self): def test_mime_text_plain_shell(self):
@ -140,5 +140,5 @@ class TestConsumeUserData(MockerTestCase):
log_file = self.capture_log(logging.WARNING) log_file = self.capture_log(logging.WARNING)
ci.fetch() ci.fetch()
ci.consume() ci.consume_userdata()
self.assertEqual("", log_file.getvalue()) self.assertEqual("", log_file.getvalue())