From a59eba66ede19aa85f53a1d2b67c3ffd8860b449 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 21 Aug 2014 13:46:41 -0400 Subject: use url_helper to combine url This seems cleaner, to avoid duplicate '/' being added. --- cloudinit/sources/DataSourceCloudStack.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'cloudinit') diff --git a/cloudinit/sources/DataSourceCloudStack.py b/cloudinit/sources/DataSourceCloudStack.py index 08f661e4..1bbeca59 100644 --- a/cloudinit/sources/DataSourceCloudStack.py +++ b/cloudinit/sources/DataSourceCloudStack.py @@ -78,7 +78,8 @@ class DataSourceCloudStack(sources.DataSource): (max_wait, timeout) = self._get_url_settings() - urls = [self.metadata_address + "/latest/meta-data/instance-id"] + urls = [uhelp.combine_url(self.metadata_address, + 'latest/meta-data/instance-id')] start_time = time.time() url = uhelp.wait_for_url(urls=urls, max_wait=max_wait, timeout=timeout, status_cb=LOG.warn) -- cgit v1.2.3 From d8c8a87f9b4c314bc39f5987602c02d3861f329f Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 21 Aug 2014 14:04:25 -0400 Subject: settings: fix typo resulting in OpenStack and GCE not running. LP: #1329583 --- ChangeLog | 2 ++ cloudinit/settings.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'cloudinit') diff --git a/ChangeLog b/ChangeLog index c52d83b7..4d8d6427 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,8 @@ - status/result json: remove 'end' entry which was always null - systemd: make cloud-init block ssh service startup to guarantee keys are generated. [Jordan Evans] (LP: #1333920) + - default settings: fix typo resulting in OpenStack and GCE not working + unless config explicitly provided (LP: #1329583) [Garrett Holmstrom]) 0.7.5: - open 0.7.5 - Add a debug log message around import failures diff --git a/cloudinit/settings.py b/cloudinit/settings.py index 37d4958b..5efcb0b0 100644 --- a/cloudinit/settings.py +++ b/cloudinit/settings.py @@ -37,7 +37,7 @@ CFG_BUILTIN = { 'OVF', 'MAAS', 'GCE', - 'OpenStack' + 'OpenStack', 'Ec2', 'CloudSigma', 'CloudStack', -- cgit v1.2.3 From 589f740909b40d814a4b802263e61ff2b5c35b24 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Thu, 21 Aug 2014 16:26:43 -0400 Subject: fix rendering resolv.conf if no 'options' are provided this makes some changes to the cc_resolv_conf to make its generate_resolv_conf method more easily callable (for future test). Also sets it up so that 'options' is always defined when the template is rendered. LP: #1328953 --- ChangeLog | 1 + cloudinit/config/cc_resolv_conf.py | 29 ++++++++++++++++++----------- templates/resolv.conf.tmpl | 2 +- 3 files changed, 20 insertions(+), 12 deletions(-) (limited to 'cloudinit') diff --git a/ChangeLog b/ChangeLog index 4d8d6427..4d326b31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,7 @@ are generated. [Jordan Evans] (LP: #1333920) - default settings: fix typo resulting in OpenStack and GCE not working unless config explicitly provided (LP: #1329583) [Garrett Holmstrom]) + - fix rendering resolv.conf if no 'options' are provided (LP: #1328953) 0.7.5: - open 0.7.5 - Add a debug log message around import failures diff --git a/cloudinit/config/cc_resolv_conf.py b/cloudinit/config/cc_resolv_conf.py index 879b62b1..bbaa6c63 100644 --- a/cloudinit/config/cc_resolv_conf.py +++ b/cloudinit/config/cc_resolv_conf.py @@ -49,23 +49,22 @@ # +from cloudinit import log as logging from cloudinit.settings import PER_INSTANCE from cloudinit import templater from cloudinit import util +LOG = logging.getLogger(__name__) + frequency = PER_INSTANCE distros = ['fedora', 'rhel', 'sles'] -def generate_resolv_conf(cloud, log, params): - template_fn = cloud.get_template_filename('resolv.conf') - if not template_fn: - log.warn("No template found, not rendering /etc/resolv.conf") - return - +def generate_resolv_conf(template_fn, params, target_fname="/etc/resolv.conf"): flags = [] false_flags = [] + if 'options' in params: for key, val in params['options'].iteritems(): if type(val) == bool: @@ -77,12 +76,15 @@ def generate_resolv_conf(cloud, log, params): for flag in flags + false_flags: del params['options'][flag] + if not params.get('options'): + params['options'] = {} + params['flags'] = flags - log.debug("Writing resolv.conf from template %s" % template_fn) - templater.render_to_file(template_fn, '/etc/resolv.conf', params) + LOG.debug("Writing resolv.conf from template %s" % template_fn) + templater.render_to_file(template_fn, target_fname, params) -def handle(name, cfg, _cloud, log, _args): +def handle(name, cfg, cloud, log, _args): """ Handler for resolv.conf @@ -102,8 +104,13 @@ def handle(name, cfg, _cloud, log, _args): " 'manage_resolv_conf' present but set to False"), name) return - if not "resolv_conf" in cfg: + if "resolv_conf" not in cfg: log.warn("manage_resolv_conf True but no parameters provided!") - generate_resolv_conf(_cloud, log, cfg["resolv_conf"]) + template_fn = cloud.get_template_filename('resolv.conf') + if not template_fn: + log.warn("No template found, not rendering /etc/resolv.conf") + return + + generate_resolv_conf(template_fn=template_fn, params=cfg["resolv_conf"]) return diff --git a/templates/resolv.conf.tmpl b/templates/resolv.conf.tmpl index 6f908f30..1300156c 100644 --- a/templates/resolv.conf.tmpl +++ b/templates/resolv.conf.tmpl @@ -21,7 +21,7 @@ domain {{domain}} sortlist {% for sort in sortlist %}{{sort}} {% endfor %} {% endif %} -{% if options is defined or flags is defined %} +{% if options or flags %} options {% for flag in flags %}{{flag}} {% endfor %} {% for key, value in options.iteritems() -%} -- cgit v1.2.3 From d723c17b7abe5263d879d748dade763034cce476 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Fri, 22 Aug 2014 11:40:25 -0400 Subject: ec2_utils.py: get_instance_metadata explicitly add trailing / This change works around a bug in CloudStack's EC2 api implementation. That is filed upstream at [1]. The fix is safe for openstack and EC2 use cases as well. EC2 and OpenStacks' EC2 metadata service both return a list with access to either of: /latest/meta-data /latest/meta-data/ Additionally, the responses explicitly contain a trailing '/' for items that have a child. The ec2_utils code then just re-uses the trailng / there. Thus, only the top level request for 'meta-data/' needs the explicit fix. This also changes test cases. Those test cases failed without fixing them. If ever this regressed, those would fail again. -- [1] https://issues.apache.org/jira/browse/CLOUDSTACK-7405 LP: #1356855 --- cloudinit/ec2_utils.py | 4 +++- tests/unittests/test_datasource/test_openstack.py | 4 ++-- tests/unittests/test_ec2_util.py | 8 ++++---- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'cloudinit') diff --git a/cloudinit/ec2_utils.py b/cloudinit/ec2_utils.py index a7c9c9ab..0c751140 100644 --- a/cloudinit/ec2_utils.py +++ b/cloudinit/ec2_utils.py @@ -166,7 +166,9 @@ def get_instance_metadata(api_version='latest', metadata_address='http://169.254.169.254', ssl_details=None, timeout=5, retries=5): md_url = url_helper.combine_url(metadata_address, api_version) - md_url = url_helper.combine_url(md_url, 'meta-data') + # Note, 'meta-data' explicitly has trailing /. + # this is required for CloudStack (LP: #1356855) + md_url = url_helper.combine_url(md_url, 'meta-data/') caller = functools.partial(util.read_file_or_url, ssl_details=ssl_details, timeout=timeout, retries=retries) diff --git a/tests/unittests/test_datasource/test_openstack.py b/tests/unittests/test_datasource/test_openstack.py index c088bb55..f43cbec8 100644 --- a/tests/unittests/test_datasource/test_openstack.py +++ b/tests/unittests/test_datasource/test_openstack.py @@ -88,7 +88,7 @@ def _register_uris(version, ec2_files, ec2_meta, os_files): path = uri.path.lstrip("/") if path in ec2_files: return (200, headers, ec2_files.get(path)) - if path == 'latest/meta-data': + if path == 'latest/meta-data/': buf = StringIO() for (k, v) in ec2_meta.items(): if isinstance(v, (list, tuple)): @@ -97,7 +97,7 @@ def _register_uris(version, ec2_files, ec2_meta, os_files): buf.write("%s" % (k)) buf.write("\n") return (200, headers, buf.getvalue()) - if path.startswith('latest/meta-data'): + if path.startswith('latest/meta-data/'): value = None pieces = path.split("/") if path.endswith("/"): diff --git a/tests/unittests/test_ec2_util.py b/tests/unittests/test_ec2_util.py index 700254a3..84aa002e 100644 --- a/tests/unittests/test_ec2_util.py +++ b/tests/unittests/test_ec2_util.py @@ -44,7 +44,7 @@ class TestEc2Util(helpers.HttprettyTestCase): @hp.activate def test_metadata_fetch_no_keys(self): - base_url = 'http://169.254.169.254/%s/meta-data' % (self.VERSION) + base_url = 'http://169.254.169.254/%s/meta-data/' % (self.VERSION) hp.register_uri(hp.GET, base_url, status=200, body="\n".join(['hostname', 'instance-id', @@ -62,7 +62,7 @@ class TestEc2Util(helpers.HttprettyTestCase): @hp.activate def test_metadata_fetch_key(self): - base_url = 'http://169.254.169.254/%s/meta-data' % (self.VERSION) + base_url = 'http://169.254.169.254/%s/meta-data/' % (self.VERSION) hp.register_uri(hp.GET, base_url, status=200, body="\n".join(['hostname', 'instance-id', @@ -83,7 +83,7 @@ class TestEc2Util(helpers.HttprettyTestCase): @hp.activate def test_metadata_fetch_with_2_keys(self): - base_url = 'http://169.254.169.254/%s/meta-data' % (self.VERSION) + base_url = 'http://169.254.169.254/%s/meta-data/' % (self.VERSION) hp.register_uri(hp.GET, base_url, status=200, body="\n".join(['hostname', 'instance-id', @@ -108,7 +108,7 @@ class TestEc2Util(helpers.HttprettyTestCase): @hp.activate def test_metadata_fetch_bdm(self): - base_url = 'http://169.254.169.254/%s/meta-data' % (self.VERSION) + base_url = 'http://169.254.169.254/%s/meta-data/' % (self.VERSION) hp.register_uri(hp.GET, base_url, status=200, body="\n".join(['hostname', 'instance-id', -- cgit v1.2.3