summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/control8
-rw-r--r--debian/dirs3
-rw-r--r--debian/install6
-rwxr-xr-xdebian/rules14
-rwxr-xr-xec2-fetch-credentials.py86
-rwxr-xr-xec2-run-user-data.py124
-rwxr-xr-xec2-set-apt-sources.py77
-rwxr-xr-xec2-set-defaults.py95
-rwxr-xr-xec2-set-hostname.py42
-rw-r--r--ec2init/__init__.py93
-rwxr-xr-xsetup.py21
11 files changed, 287 insertions, 282 deletions
diff --git a/debian/control b/debian/control
index a2812cae..b171f568 100644
--- a/debian/control
+++ b/debian/control
@@ -2,12 +2,14 @@ Source: ec2-init
Section: admin
Priority: extra
Maintainer: Soren Hansen <soren@ubuntu.com>
-Build-Depends: cdbs, debhelper (>= 5)
+Build-Depends: cdbs, debhelper (>= 5), debhelper (>= 5.0.38), python-all-dev (>= 2.3.5-11), python-central (>= 0.5.6)
+XS-Python-Version: all
Standards-Version: 3.8.0
Package: ec2-init
Architecture: i386 amd64
-Depends: python, procps, python-configobj, python-cheetah, python-apt, update-motd
-Description: Init scripts for EC2 instances,
+Depends: python, procps, python-configobj, python-cheetah, update-motd, ${python:Depends}
+XB-Python-Version: ${python:Versions}
+Description: Init scripts for EC2 instances
EC2 instances need special scripts to run during initialisation
to retrieve and install ssh keys and to let the user run various scripts.
diff --git a/debian/dirs b/debian/dirs
deleted file mode 100644
index 3c349733..00000000
--- a/debian/dirs
+++ /dev/null
@@ -1,3 +0,0 @@
-var/ec2
-usr/sbin
-etc/ec2-init
diff --git a/debian/install b/debian/install
index 33e2382f..7cea0e92 100644
--- a/debian/install
+++ b/debian/install
@@ -1,3 +1,3 @@
-debian/tmp/usr/sbin/*
-debian/tmp/etc/ec2-init/templates/*
-debian/ec2-config.cfg etc/ec2-init
+#debian/ec2-init/usr/bin/*
+#debian/ec2-init/etc/ec2-init/templates/*
+#debian/ec2-config.cfg etc/ec2-init
diff --git a/debian/rules b/debian/rules
index 488b93d9..a96b88fa 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,18 +1,10 @@
#!/usr/bin/make -f
+DEB_PYTHON_SYSTEM=pycentral
include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/python-distutils.mk
DEB_UPDATE_RCD_PARAMS:= start 15 2 3 4 5 . stop 20 1 .
-build/ec2-init::
- install -d debian/tmp/usr/sbin
- mkdir -p debian/tmp/var/ec2
- mkdir -p debian/tmp/etc/ec2-init/templates
- install -m 775 ec2-fetch-credentials.py debian/tmp/usr/sbin/ec2-fetch-credentials
- install -m 775 ec2-run-user-data.py debian/tmp/usr/sbin/ec2-run-user-data
- install -m 755 ec2-set-hostname.py debian/tmp/usr/sbin/ec2-set-hostname
- install -m 755 ec2-set-apt-sources.py debian/tmp/usr/sbin/ec2-set-apt-sources
- install -m755 ec2-get-info.py debian/tmp/usr/sbin/ec2-get-info
- install -m755 ec2-set-defaults.py debian/tmp/usr/sbin/ec2-set-defaults
- install -m755 templates/* debian/tmp/etc/ec2-init/templates
+binary-install/ec2-init::
dh_installinit -p ec2-init --name rightscale-init -- defaults 99 09
diff --git a/ec2-fetch-credentials.py b/ec2-fetch-credentials.py
index 05bc7a9c..9ebc4634 100755
--- a/ec2-fetch-credentials.py
+++ b/ec2-fetch-credentials.py
@@ -18,76 +18,42 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import urllib
import os
-import socket
-import sys
-from configobj import ConfigObj
+import pwd
-api_ver = '2008-02-01'
-metadata = None
-filename='/etc/ec2-init/ec2-config.cfg'
+import ec2init
-config = ConfigObj(filename)
-user = config['user']
-config_root = config['DISABLE_ROOT']
+def setup_user_keys(keys, user, key_prefix):
+ pwent = pwd.getpwnam(user)
-def get_ssh_keys():
- base_url = 'http://169.254.169.254/%s/meta-data' % api_ver
- data = urllib.urlopen('%s/public-keys/' % base_url).read()
- keyids = [line.split('=')[0] for line in data.split('\n')]
- return [urllib.urlopen('%s/public-keys/%d/openssh-key' % (base_url, int(keyid))).read().rstrip() for keyid in keyids]
+ os.umask(077)
+ if not os.path.exists('%s/.ssh' % pwent.pw_dir):
+ os.mkdir('%s/.ssh' % pwent.pw_dir)
-def setup_user_keys(k,user,filename):
- if not os.path.exists('/home/%s/.ssh' %(user)):
- os.mkdir('/home/%s/.ssh' %(user))
-
- authorized_keys = '/home/%s/.ssh/authorized_keys' % user
+ authorized_keys = '%s/.ssh/authorized_keys' % pwent.pw_dir
fp = open(authorized_keys, 'a')
- fp.write(''.join(['%s\n' % key for key in keys]))
+ fp.write(''.join(['%s%s\n' % (key_prefix, key) for key in keys]))
fp.close()
- os.system('chown -R %s:%s /home/%s/.ssh' %(user,user,user))
- os.system('touch %s' %(filename))
-def setup_root_user(k,root_config):
- if root_config == "1":
- if not os.path.exists('/root/.ssh'):
- os.mkdir('/root/.ssh/')
+ os.chown(authorized_keys, pwent.pw_uid, pwent.pw_gid)
- fp = open('/root/.ssh/authorized_keys', 'a')
- fp.write("command=\"echo \'Please login as the ubuntu user rather than root user.\';echo;sleep 10\" ")
- fp.write(''.join(['%s\n' % key for key in keys]))
- fp.close()
- elif root_config == "0":
- print "You choose to disable the root user, god help you."
- else:
- print "%s - I dont understand that opion."
+def main():
+ ec2 = ec2init.EC2Init()
-def checkServer():
- s = socket.socket()
- try:
- address = '169.254.169.254'
- port = 80
- s.connect((address,port))
- except socket.error, e:
- print "!!! Unable to connect to %s" % address
- sys.exit(0)
+ user = ec2.get_cfg_option_str('user')
+ disable_root = ec2.get_cfg_option_bool('disable_root')
-def get_ami_id():
- url = 'http://169.254.169.254/%s/meta-data' % api_ver
- ami_id = urllib.urlopen('%s/ami-id/' %url).read()
- return ami_id
+ keys = ec2.get_ssh_keys()
+
+ if user:
+ setup_user_keys(keys, user, '')
+
+ if disable_root:
+ key_prefix = 'command="echo \'Please login as the ubuntu user rather than root user.\';echo;sleep 10" '
+ else:
+ key_prefix = ''
-amid = get_ami_id()
-filename = '/var/ec2/.ssh-keys-ran.%s' %amid
-if os.path.exists(filename):
- print "ec2-fetch-credentials already ran....skipping."
-else:
- os.umask(077)
- if user == "":
- print "User must exist in %s" %(filename)
- sys.exit(0)
+ setup_root_user(keys, 'root', key_prefix)
- keys = get_ssh_keys()
- setup_user_keys(keys,user,filename)
- setup_root_user(keys,config_root)
+if __name__ == '__main__':
+ main()
diff --git a/ec2-run-user-data.py b/ec2-run-user-data.py
index 513c64ff..890bb2bf 100755
--- a/ec2-run-user-data.py
+++ b/ec2-run-user-data.py
@@ -1,9 +1,9 @@
#!/usr/bin/python
#
# Fetch and run user-data from EC2
-# Copyright 2008 Canonical Ltd.
+# Copyright 2009 Canonical Ltd.
#
-# Original-Author: Soren Hansen <soren@canonical.com>
+# Author: Soren Hansen <soren@canonical.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,54 +19,80 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+import email
import os
+import subprocess
import sys
import tempfile
-import urllib
-import socket
-from time import gmtime, strftime
-
-api_ver = '2008-02-01'
-metadata = None
-
-def checkServer():
- s = socket.socket()
- try:
- address = '169.254.169.254'
- port = 80
- s.connect((address,port))
- except socket.error, e:
- print "!!!! Unable to connect to %s" % address
- sys.exit(0)
-
-def get_user_data():
- url = 'http://169.254.169.254/%s/user-data' % api_ver
- fp = urllib.urlopen(url)
- data = fp.read()
+
+import ec2init
+
+content_type_handlers = { 'text/x-shellscript' : handle_shell_script,
+ 'text/x-ebs-mount-description' : handle_ebs_mount_description }
+
+def main():
+ ec2 = ec2init.EC2Init()
+
+ semaphore = '/var/lib/ec2/already-ran.%s' % amiId
+ amiId = ec2.get_ami_id()
+
+ if os.path.exists(semaphore):
+ print "ec2-run-user-data already ran for this instance."
+ return 0
+
+ user_data = ec2.get_user_data()
+
+ msg = email.message_from_string(user_data)
+ if msg.is_multipart():
+ handle_part(msg)
+ else:
+ handle_payload(user_data)
+
+ # Touch the semaphore file
+ file(semaphore, 'a').close()
+
+def handle_part(part):
+ if part.is_multipart():
+ for p in part.get_payload():
+ handle_part(p)
+ else:
+ if part.get_content_type() in content_type_handlers:
+ content_type_handlers[part.get_content_type](part.get_payload())
+ return
+
+ handle_unknown_payload(part.get_payload())
+
+def handle_unknown_payload(payload):
+ # Try to detect magic
+ if payload.startswith('#!'):
+ content_type_handlers['text/x-shellscript'](payload)
+
+def handle_ebs_mount_description(payload):
+ (volume_description, path) = payload.split(':')
+ (identifier_type, identifier) = volume_description.split('=')
+
+ if identifier_type == 'device':
+ device = identifier
+# Perhaps some day the volume id -> device path mapping
+# will be exposed through meta-data.
+# elif identifier_type == 'volume':
+# device = extract_device_name_from_meta_data
+ else:
+ return
+
+def handle_shell_script(payload):
+ (fd, path) = tempfile.mkstemp()
+ fp = os.fdopen(fd, 'a')
+ fp.write(payload)
fp.close()
- return data
-
-def get_ami_id():
- url = 'http://169.254.169.254/%s/meta-data' % api_ver
- ami_id = urllib.urlopen('%s/ami-id/' %url).read()
- return ami_id
-
-checkServer()
-user_data = get_user_data()
-amiId = get_ami_id()
-filename = '/var/ec2/.already-ran.%s' % amiId
-
-if os.path.exists(filename):
- print "ec2-run-user-data already ran for this instance."
- sys.exit(0)
-elif user_data.startswith('#!'):
- # run it
- (fp, path) = tempfile.mkstemp()
- os.write(fp,user_data)
- os.close(fp);
- os.chmod(path, 0700)
- status = os.system('%s | logger -t "user-data" ' % path)
- os.unlink(path)
- os.system('touch %s' %(filename))
-
-sys.exit(0)
+ os.chmod(path, 0700)
+
+ # Run the user data script and pipe its output to logger
+ user_data_process = subprocess.Popen([path], stdout=subprocess.PIPE)
+ logger_process = subprocess.Popen(['logger', '-t', 'user-data'], stdin=user_data_process.stdout)
+ logger_process.communicate()
+
+ os.unlink(path)
+
+if __name__ == '__main__':
+ main()
diff --git a/ec2-set-apt-sources.py b/ec2-set-apt-sources.py
index d48e5167..10fea8ec 100755
--- a/ec2-set-apt-sources.py
+++ b/ec2-set-apt-sources.py
@@ -19,70 +19,31 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os
-import sys
-import urllib
-import socket
-import apt
-import apt_pkg
+import subprocess
from Cheetah.Template import Template
-def checkServer():
- s = socket.socket()
- try:
- address = '169.254.169.254'
- port = 80
- s.connect((address,port))
- except socket.error, e:
- print "!!! Unable to connect to %s." % address
- sys.exit(0)
+import ec2init
-def detectZone():
- api_ver = '2008-02-01'
+def main():
+ ec2 = ec2init.EC2Init()
- base_url = 'http://169.254.169.254/%s/meta-data' % api_ver
- zone = urllib.urlopen('%s/placement/availability-zone' % base_url).read()
- if zone.startswith("us"):
- archive = "http://us.ec2.archive.ubuntu.com/ubuntu/"
- elif zone.startswith("eu"):
- archive = "http://eu.ec2.archive.ubuntu.com/ubuntu/"
+ mirror = ec2.get_mirror_for_availability_zone()
- return(archive)
+ if not os.path.exists("/var/run/ec2/sources.lists"):
+ t = os.popen("lsb_release -cs").read()
+ codename = t.strip()
-def updateList(filename):
- mirror = detectZone()
- if not os.path.exists("/var/ec2/sources.lists"):
- t = os.popen("lsb_release -c").read()
- codename = t.split()
- distro = codename[1]
-
- mp = {'mirror' : mirror, 'codename' : distro}
- t = Template(file="/etc/ec2-init/templates/sources.list.tmpl", searchList=[mp])
- f = open("/var/ec2/sources.list", "w")
- f.write('%s' %(t))
+ mp = { 'mirror' : mirror, 'codename' : codename }
+ t = Template(file='/etc/ec2-init/templates/sources.list.tmpl', searchList=[mp])
+ f = open("/var/run/ec2/sources.list", "w")
+ f.write(t.respond())
f.close()
- os.system("mv /etc/apt/sources.list /etc/apt/sources.list-ec2-init")
- os.symlink("/var/ec2/sources.list", "/etc/apt/sources.list")
- cache = apt.Cache(apt.progress.OpProgress())
- prog = apt.progress.FetchProgress()
- cache.update(prog)
-
- os.system('touch %s' %(filename))
-
-def get_ami_id():
- api_ver = '2008-02-01'
-
- url = 'http://169.254.169.254/%s/meta-data' % api_ver
- ami_id = urllib.urlopen('%s/ami-id/' %url).read()
- return ami_id
-
-
-checkServer()
-
-ami_id = get_ami_id()
-filename = '/var/ec2/.apt-already-ran.%s' %ami_id
+ if not os.path.exists("/etc/apt/sources.list-ec2-init"):
+ os.rename('/etc/apt/sources.list', '/etc/apt/sources.list-ec2-init')
+ os.symlink('/var/run/ec2/sources.list', '/etc/apt/sources.list')
+ aptget = subprocess.Popen(['apt-get', 'update'])
+ aptget.communicate()
-if os.path.exists(filename):
- print "ec2-set-apt-sources already ran....skipping."
-else:
- updateList(filename)
+if __name__ == '__main__':
+ main()
diff --git a/ec2-set-defaults.py b/ec2-set-defaults.py
index 410e57d8..eec696e4 100755
--- a/ec2-set-defaults.py
+++ b/ec2-set-defaults.py
@@ -19,66 +19,35 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import urllib
-import os
-import socket
-import time
-from Cheetah.Template import Template
-
-api_ver = '2008-02-01'
-metadata = None
-
-def checkServer():
- for x in range(30*60):
- s = socket.socket()
- try:
- address = '169.254.169.254'
- port = 80
- s.connect((address,port))
- s.close()
- return
- except socket.error, e:
- time.sleep(1)
-
-checkServer()
-
-base_url = 'http://169.254.169.254/%s/meta-data' % api_ver
-zone = urllib.urlopen('%s/placement/availability-zone' % base_url).read()
-
-if zone.startswith("us"):
- archive = "http://us.ec2.archive.ubuntu.com/ubuntu"
-elif zone.startswith("eu"):
- archive = "http://eu.ec2.archive.ubuntu.com/ubuntu"
-
-def set_language(location,filename):
- if location.startswith("us"):
- lang='en_US.UTF-8'
- elif location.startswith("eu"):
- lang='en_GB.UTF-8'
-
- os.system('locale-gen %s' %(lang))
-
- mp = {'lang' : lang }
- T = Template(file="/etc/ec2-init/templates/locale.tmpl", searchList=[mp])
- f = open("/var/ec2/locale", "w")
- f.write('%s' %(T))
- f.close()
-
- os.system("mv /etc/default/locale /etc/default/locale-ec2-init")
- os.system("ln -s /var/ec2/locale /etc/default/locale")
- os.system(". /etc/default/locale")
-
- os.system('touch %s' %(filename))
-
-def get_amid():
- url = 'http://169.254.169.254/%s/meta-data' % api_ver
- ami_id = urllib.urlopen('%s/ami-id/' %url).read()
- return ami_id
-
-ami = get_amid()
-filename = '/var/ec2/.defaults-already-ran.%s' %ami
-
-if os.path.exists(filename):
- print "ec2-set-defaults already ran...skipping"
-else:
- set_language(zone,filename)
+import subprocess
+
+import ec2init
+
+def get_location_from_availability_zone(availability_zone):
+ if availability.startswith('us-'):
+ return 'us'
+ elif availability.startswith('eu-'):
+ return 'eu'
+ raise Exception('Could not determine location')
+
+location_archive_map = {
+ 'us' : 'http://us.ec2.archive.ubuntu.com/ubuntu',
+ 'eu' : 'http://eu.ec2.archive.ubuntu.com/ubuntu'
+}
+
+location_locale_map = {
+ 'us' : 'en_US.UTF-8',
+ 'eu' : 'en_GB.UTF-8'
+}
+
+def main():
+ ec2 = ec2init.EC2Init()
+
+ location = get_location_from_availability_zone(ec2.get_availability_zone())
+
+ locale = location_locale_map[location]
+ subprocess.Popen(['locale-gen', locale]).communicate()
+ subprocess.Popen(['update-locale', locale]).communicate()
+
+if __name__ == '__main__':
+ main()
diff --git a/ec2-set-hostname.py b/ec2-set-hostname.py
index 108fe5da..985f4ada 100755
--- a/ec2-set-hostname.py
+++ b/ec2-set-hostname.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
#
-# Set up the hostname for ec2.
+# Fetch login credentials for EC2
# Copyright 2008 Canonical Ltd.
#
# Author: Chuck Short <chuck.short@canonical.com>
@@ -22,44 +22,22 @@ import urllib
import os
from Cheetah.Template import Template
-api_ver = '2008-02-01'
-metadata = None
+import ec2init
-def get_ami_id():
- api_ver = '2008-02-01'
- metadata = None
+def main():
+ ec2 = ec2init.EC2Init()
- url = 'http://169.254.169.254/%s/meta-data' % api_ver
- ami_id = urllib.urlopen('%s/ami-id/' %url).read()
- return ami_id
+ hostname = ec2.get_hostname()
-def set_hostname(filename):
- api_ver = '2008-02-01'
- metadata = None
-
- base_url = 'http://169.254.169.254/%s/meta-data' % api_ver
- my_hostname = urllib.urlopen('%s/local-hostname/' % base_url).read()
- os.system('hostname %s' % my_hostname)
+ subprocess.Popen(['hostname', hostname']).communicate()
# replace the ubuntu hostname in /etc/hosts
- mp = {'hostname': my_hostname}
+ mp = {'hostname': hostname}
t = Template(file="/etc/ec2-init/templates/hosts.tmpl", searchList=[mp])
- os.system("rm /etc/hosts")
f = open("/etc/hosts", "w")
- f.write('%s' %(t))
- f.close()
-
- os.system("rm /etc/hostname")
- f = open("/etc/hostname", "w")
- f.write('%s' %(my_hostname))
+ f.write(t.respond())
f.close()
- os.system('touch %s' %(filename))
-
-id = get_ami_id()
-filename = '/var/ec2/.hostname-already-ran.%s' %id
-if os.path.exists(filename):
- print "Hostname already set previously....skipping!"
-else:
- set_hostname(filename)
+if __name__ == '__main__':
+ main()
diff --git a/ec2init/__init__.py b/ec2init/__init__.py
new file mode 100644
index 00000000..3fa0de1d
--- /dev/null
+++ b/ec2init/__init__.py
@@ -0,0 +1,93 @@
+#
+# Common code for the EC2 initialisation scripts in Ubuntu
+# Copyright 2009 Canonical Ltd.
+#
+# Author: Soren Hansen <soren@canonical.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+from configobj import ConfigObj
+import os
+import socket
+
+import boto.utils
+
+class EC2Init():
+ api_ver = '2008-02-01'
+ filename = '/etc/ec2-init/ec2-config.cfg'
+
+ def __init__(self):
+ self.meta_data_base_url = 'http://169.254.169.254/%s/meta-data' % self.api_ver
+ self.user_data_base_url = 'http://169.254.169.254/%s/user-data' % self.api_ver
+ self.config = ConfigObj(filename)
+ self.wait_for_metadata_service()
+ bailout_command = self.get_cfg_option_str('bailout_command')
+ if bailout_command:
+ os.system(bailout_command)
+
+ def get_cfg_option_bool(self, key):
+ val = self.config[key]
+ if val.lower() in ['1', 'on', 'yes']:
+ return True
+ return False
+
+ def get_cfg_option_str(self, key):
+ return config[key]
+
+ def get_ssh_keys(self):
+ data = urllib.urlopen('%s/public-keys/' % self.meta_data_base_url).read()
+ keyids = [line.split('=')[0] for line in data.split('\n')]
+ return [urllib.urlopen('%s/public-keys/%d/openssh-key' % (self.meta_data_base_url, int(keyid))).read().rstrip() for keyid in keyids]
+
+ def get_user_data(self):
+ return boto.utils.get_instance_userdata()
+
+ def get_instance_metadata(self):
+ self.instance_metadata = getattr(self, 'instance_metadata', boto.utils.get_instance_metadata())
+ return self.instance_metadata
+
+ def get_ami_id(self):
+ return self.get_instance_metadata()['ami-id']
+
+ def get_availability_zone(self):
+ return self.get_instance_metadata()['availability-zone']
+
+ def get_hostname(self):
+ return self.get_instance_metadata()['local-hostname']
+
+ def get_mirror_for_availability_zone(self):
+ availability_zone = self.get_availability_zone()
+ if zone.startswith("us"):
+ return 'http://us.ec2.archive.ubuntu.com/ubuntu/'
+ elif zone.startswith("eu"):
+ return 'http://eu.ec2.archive.ubuntu.com/ubuntu/'
+
+ return 'http://archive.ubuntu.com/ubuntu/'
+
+ def wait_for_metadata_service(self):
+ timeout = 2
+ # This gives us about half an hour before we ultimately bail out
+ for x in range(10):
+ s = socket.socket()
+ try:
+ address = '169.254.169.254'
+ port = 80
+ s.connect((address,port))
+ s.close()
+ return True
+ except socket.error, e:
+ time.sleep(timeout)
+ timeout = timeout * 2
+ return False
diff --git a/setup.py b/setup.py
new file mode 100755
index 00000000..851e559f
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,21 @@
+from distutils.core import setup
+from glob import glob
+import os.path
+import subprocess
+
+setup(name='EC2-init',
+ version='0.5',
+ description='EC2 initialisation magic',
+ author='Soren Hansen',
+ author_email='soren@canonical.com',
+ url='http://launchpad.net/ec2-init/',
+ packages=['ec2init'],
+ scripts=['ec2-fetch-credentials.py',
+ 'ec2-get-info.py',
+ 'ec2-run-user-data.py',
+ 'ec2-set-apt-sources.py',
+ 'ec2-set-defaults.py',
+ 'ec2-set-hostname.py'],
+ data_files=[('/etc/ec2-init', ['debian/ec2-config.cfg']),
+ ('/etc/ec2-init/templates', glob('templates/*'))],
+ )