Connect cfn utils to the remote server

The cfn_helper's `Metadata` class can now connect to the metadata server
prodived it's URL is known and available.

Engine will pass metadata server's URL via the User Data to the following file:

    /var/lib/cloud/data/cfn-metadata-server

If the file doesn't exist or the server is unreachable, cfntools will read
metadata from the `/var/lib/cloud/data/cfn-init-data` file as they did so far.

Note that Engine dosen't currently know the metadata server's URL so it's not
passing it to the instance yet.
This commit is contained in:
Tomas Sedovic 2012-05-03 16:19:17 +02:00
parent 25568e75c3
commit 47cf2132a2
3 changed files with 49 additions and 7 deletions

View File

@ -41,7 +41,8 @@ import rpmUtils.updates as rpmupdates
import rpmUtils.miscutils as rpmutils
import subprocess
import sys
from urllib2 import urlopen
from urlparse import urlparse, urlunparse
def to_boolean(b):
val = b.lower().strip() if isinstance(b, basestring) else b
@ -731,6 +732,8 @@ class ServicesHandler(object):
else:
self._monitor_services(handler, service_entries)
class MetadataServerConnectionError(Exception):
pass
class Metadata(object):
_metadata = None
@ -750,6 +753,35 @@ class Metadata(object):
self._is_local_metadata = True
self._metadata = None
def metadata_server_url(self):
"""
Return the url to the metadata server.
"""
try:
f = open("/var/lib/cloud/data/cfn-metadata-server")
server_url = f.read()
f.close()
except IOError:
return None
url_parts = list(urlparse(server_url))
url_parts[2] = '/stacks/%s/resources/%s' % (self.stack, self.resource)
return urlunparse(url_parts)
def remote_metadata(self):
"""
Connect to the metadata server and retreive the metadata from there.
"""
server_url = self.metadata_server_url()
if not server_url:
raise MetadataServerConnectionError()
try:
return urlopen(server_url).read()
except:
raise MetadataServerConnectionError()
def retrieve(self, meta_str=None):
"""
Read the metadata from the given filename
@ -757,9 +789,12 @@ class Metadata(object):
if meta_str:
self._data = meta_str
else:
f = open("/var/lib/cloud/data/cfn-init-data")
self._data = f.read()
f.close()
try:
self._data = self.remote_metadata()
except MetadataServerConnectionError:
f = open("/var/lib/cloud/data/cfn-init-data")
self._data = f.read()
f.close()
if isinstance(self._data, str):
self._metadata = json.loads(self._data)

View File

@ -108,13 +108,19 @@ class Instance(Resource):
filename='cfn-init-data')
mime_blob.attach(msg)
if self.stack.metadata_server:
msg = MIMEText(self.stack.metadata_server,
_subtype='x-cfninitdata')
msg.add_header('Content-Disposition', 'attachment',
filename='cfn-metadata-server')
mime_blob.attach(msg)
msg = MIMEText(userdata, _subtype='x-shellscript')
msg.add_header('Content-Disposition', 'attachment', filename='startup')
mime_blob.attach(msg)
self.mime_string = mime_blob.as_string()
return self.mime_string
return self.mime_string
def create(self):
def _null_callback(p, n, out):

View File

@ -48,7 +48,8 @@ class Stack(object):
self.doc = None
self.name = stack_name
self.parsed_template_id = 0
self.metadata_server = 'http://10.0.0.1'
# TODO(shadower) load this from a config file
#self.metadata_server = 'http://10.0.0.1'
self.parms['AWS::StackName'] = {"Description": "AWS StackName",
"Type": "String",