From 893cda431447a319809e2dd9f4ebd41ea012997b Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Fri, 22 Jun 2012 17:30:28 +0200 Subject: [PATCH] Fix path to cloudinit directory The various path manipulations designed to search for the cloudinit directory do not work with the current installation script, or when heat-jeos is also installed. They also perform gratuitous manipulation of sys.path (causing warning messages) and may pick up the cloudinit files from a different location to the code that is actually running. Python already knows which heat package we are using - just look for the directory inside there. This patch also tidies up the code for generating the user data. Change-Id: I14add5f1670aea2562329ff1a1303320a35ff428 Signed-off-by: Zane Bitter --- heat/engine/instance.py | 65 ++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/heat/engine/instance.py b/heat/engine/instance.py index cae673b992..f49d4a094c 100644 --- a/heat/engine/instance.py +++ b/heat/engine/instance.py @@ -22,23 +22,11 @@ from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from novaclient.exceptions import NotFound +import heat from heat.engine.resources import Resource from heat.common import exception logger = logging.getLogger('heat.engine.instance') -# If ../heat/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'heat', '__init__.py')): - sys.path.insert(0, possible_topdir) - cloudinit_path = '%s/heat/%s/' % (possible_topdir, "cloudinit") -else: - for p in sys.path: - if 'heat' in p: - cloudinit_path = '%s/heat/%s/' % (p, "cloudinit") - break class Restarter(Resource): @@ -168,40 +156,37 @@ class Instance(Resource): def _build_userdata(self, userdata): if not self.mime_string: # Build mime multipart data blob for cloudinit userdata - mime_blob = MIMEMultipart() - fp = open('%s/%s' % (cloudinit_path, 'config'), 'r') - msg = MIMEText(fp.read(), _subtype='cloud-config') - fp.close() - msg.add_header('Content-Disposition', 'attachment', - filename='cloud-config') - mime_blob.attach(msg) - fp = open('%s/%s' % (cloudinit_path, 'part-handler.py'), 'r') - msg = MIMEText(fp.read(), _subtype='part-handler') - fp.close() - msg.add_header('Content-Disposition', 'attachment', - filename='part-handler.py') - mime_blob.attach(msg) + def make_subpart(content, filename, subtype=None): + if subtype is None: + subtype = os.path.splitext(filename)[0] + msg = MIMEText(content, _subtype=subtype) + msg.add_header('Content-Disposition', 'attachment', + filename=filename) + return msg + + def read_cloudinit_file(fn): + with open(os.path.join(heat.__path__[0], 'cloudinit', fn), + 'r') as fp: + return fp.read() + + attachments = [(read_cloudinit_file('config'), 'cloud-config'), + (read_cloudinit_file('part-handler.py'), + 'part-handler.py'), + (userdata, 'startup', 'x-shellscript')] if 'Metadata' in self.t: metadata = self.parsed_template()['Metadata'] - msg = MIMEText(json.dumps(metadata), - _subtype='x-cfninitdata') - msg.add_header('Content-Disposition', 'attachment', - filename='cfn-init-data') - mime_blob.attach(msg) + attachments.append((json.dumps(metadata), + 'cfn-init-data', 'x-cfninitdata')) 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) + attachments.append((self.stack.metadata_server, + 'cfn-metadata-server', 'x-cfninitdata')) + + subparts = [make_subpart(*args) for args in attachments] + mime_blob = MIMEMultipart(_subparts=subparts) - 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