diff options
author | Scott Moser <smoser@ubuntu.com> | 2011-06-01 16:29:37 -0400 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2011-06-01 16:29:37 -0400 |
commit | 5864b795eee242b1fd7c5910abce69a931bb8738 (patch) | |
tree | d90f834be44e2bb687bf61f95e658393bff6440a /cloudinit | |
parent | 80301e1a4aa1a7396b2cb2d6c5d0e46b75a46a98 (diff) | |
parent | b7dfa8c9b75c74208f134dfd15538601fedc0258 (diff) | |
download | vyos-cloud-init-5864b795eee242b1fd7c5910abce69a931bb8738.tar.gz vyos-cloud-init-5864b795eee242b1fd7c5910abce69a931bb8738.zip |
support configurable urls for metadata service
Now, if a Eucalyptus install is in STATIC or SYSTEM mode,
the metadata service can still be used. In order to do that,
the user must configure their DNS so that 'instance-data' will
resolve to the cloud controller.
Thanks to Kieran Evans.
LP: #761847
Diffstat (limited to 'cloudinit')
-rw-r--r-- | cloudinit/DataSourceEc2.py | 87 | ||||
-rw-r--r-- | cloudinit/boto_utils.py | 8 |
2 files changed, 67 insertions, 28 deletions
diff --git a/cloudinit/DataSourceEc2.py b/cloudinit/DataSourceEc2.py index 9f1cf840..18c1ed50 100644 --- a/cloudinit/DataSourceEc2.py +++ b/cloudinit/DataSourceEc2.py @@ -27,10 +27,12 @@ import sys import boto_utils import os.path import errno +import urlparse class DataSourceEc2(DataSource.DataSource): api_ver = '2009-04-04' seeddir = seeddir + '/ec2' + metadata_address = "http://169.254.169.254" def __str__(self): return("DataSourceEc2") @@ -46,8 +48,8 @@ class DataSourceEc2(DataSource.DataSource): try: if not self.wait_for_metadata_service(): return False - self.userdata_raw = boto_utils.get_instance_userdata(self.api_ver) - self.metadata = boto_utils.get_instance_metadata(self.api_ver) + self.userdata_raw = boto_utils.get_instance_userdata(self.api_ver, None, self.metadata_address) + self.metadata = boto_utils.get_instance_metadata(self.api_ver, self.metadata_address) return True except Exception as e: print e @@ -100,30 +102,58 @@ class DataSourceEc2(DataSource.DataSource): log.warn("Failed to get timeout, using %s" % timeout) sleeptime = 1 - address = '169.254.169.254' + + def_mdurls = ["http://169.254.169.254", "http://instance-data:8773"] + try: + mdurls = mcfg.get("metadata_urls", def_mdurls) + except Exception as e: + mdurls = def_mdurls + util.logexc(log) + log.warn("Failed to get metadata URLs, using defaults") + starttime = time.time() - - url="http://%s/%s/meta-data/instance-id" % (address,self.api_ver) - for x in range(sleeps): - # given 100 sleeps, this ends up total sleep time of 1050 sec - sleeptime=int(x/5)+1 - reason = "" - try: - req = urllib2.Request(url) - resp = urllib2.urlopen(req, timeout=timeout) - if resp.read() != "": return True - reason = "empty data [%s]" % resp.getcode() - except urllib2.HTTPError as e: - reason = "http error [%s]" % e.code - except urllib2.URLError as e: - reason = "url error [%s]" % e.reason - - if x == 0: - log.warning("waiting for metadata service at %s\n" % url) - - log.warning(" %s [%02s/%s]: %s\n" % - (time.strftime("%H:%M:%S",time.gmtime()), x+1, sleeps, reason)) + # Remove addresses from the list that wont resolve. + filtered = [x for x in mdurls if try_to_resolve_metadata(x)] + + if set(filtered) != set(mdurls): + log.debug("removed the following from metadata urls: %s" % + list((set(mdurls) - set(filtered)))) + + if len(filtered): + mdurls = filtered + else: + log.warn("Empty metadata url list! using default list") + mdurls = def_mdurls + + log.debug("Searching the following metadata urls: %s" % mdurls) + + for x in range(sleeps): + for url in mdurls: + iurl="%s/%s/meta-data/instance-id" % (url, self.api_ver) + + # given 100 sleeps, this ends up total sleep time of 1050 sec + sleeptime=int(x/5)+1 + + reason = "" + try: + req = urllib2.Request(url) + resp = urllib2.urlopen(req, timeout=timeout) + if resp.read() != "": + self.metadata_address = url + log.debug("Using metadata source: '%s'" % url) + return True + reason = "empty data [%s]" % resp.getcode() + except urllib2.HTTPError as e: + reason = "http error [%s]" % e.code + except urllib2.URLError as e: + reason = "url error [%s]" % e.reason + + #not needed? Addresses being checked are displayed above + #if x == 0: + # log.warn("waiting for metadata service at %s" % url) + + log.warn("'%s' failed: %s" % (url, reason)) time.sleep(sleeptime) log.critical("giving up on md after %i seconds\n" % @@ -181,6 +211,15 @@ class DataSourceEc2(DataSource.DataSource): return True return False +def try_to_resolve_metadata(url): + try: + addr = urlparse.urlsplit(url).netloc.split(":")[0] + socket.getaddrinfo(addr, None) + return True + except Exception as e: + return False + + datasources = [ ( DataSourceEc2, ( DataSource.DEP_FILESYSTEM , DataSource.DEP_NETWORK ) ), ] diff --git a/cloudinit/boto_utils.py b/cloudinit/boto_utils.py index b38483fa..a2cb9ca6 100644 --- a/cloudinit/boto_utils.py +++ b/cloudinit/boto_utils.py @@ -60,7 +60,7 @@ def retry_url(url, retry_on_404=True): sys.stderr.write('Caught exception reading instance data, giving up\n') return '' -def get_instance_metadata(version='latest'): +def get_instance_metadata(version='latest',url='http://169.254.169.254'): """ Returns the instance metadata as a nested Python dictionary. Simple values (e.g. local_hostname, hostname, etc.) will be @@ -68,11 +68,11 @@ def get_instance_metadata(version='latest'): be stored in the dict as a list of string values. More complex fields such as public-keys and will be stored as nested dicts. """ - url = 'http://169.254.169.254/%s/meta-data/' % version + url = '%s/%s/meta-data/' % (url,version) return _get_instance_metadata(url) -def get_instance_userdata(version='latest', sep=None): - url = 'http://169.254.169.254/%s/user-data' % version +def get_instance_userdata(version='latest', sep=None,url='http://169.254.169.254'): + url = '%s/%s/user-data' % (url,version) user_data = retry_url(url, retry_on_404=False) if user_data: if sep: |