mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-22 09:50:37 +00:00
Basic structure up and running
This commit is contained in:
commit
4dbdb387cd
15 changed files with 264 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.pyc
|
0
__init__.py
Normal file
0
__init__.py
Normal file
4
common/__init__.py
Normal file
4
common/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
from bootstrapinfo import BootstrapInformation
|
||||
from manifest import Manifest
|
||||
from task import Task
|
||||
from tasklist import TaskList
|
6
common/bootstrapinfo.py
Normal file
6
common/bootstrapinfo.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
|
||||
class BootstrapInformation(object):
|
||||
def __init__(self, manifest=None, args=None):
|
||||
self.manifest = manifest
|
||||
self.args = args
|
14
common/manifest.py
Normal file
14
common/manifest.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
import json
|
||||
|
||||
|
||||
class Manifest(object):
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.parse(json.load(open(self.path)))
|
||||
|
||||
def parse(self, data):
|
||||
self.volume = data['volume']
|
||||
self.system = data['system']
|
||||
|
||||
def validate(self):
|
||||
pass
|
10
common/task.py
Normal file
10
common/task.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
|
||||
class Task(object):
|
||||
name = None
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def run(self, info):
|
||||
print 'Running ' + self.__module__ + "." + self.__class__.__name__
|
15
common/tasklist.py
Normal file
15
common/tasklist.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
|
||||
class TaskList(list):
|
||||
def run(self, info):
|
||||
for task in self:
|
||||
task.run(info)
|
||||
|
||||
def before(self, task):
|
||||
pass
|
||||
|
||||
def replace(self, task):
|
||||
pass
|
||||
|
||||
def after(self, task):
|
||||
pass
|
18
debian-build-cloud
Executable file
18
debian-build-cloud
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
|
||||
def main():
|
||||
from argparse import ArgumentParser
|
||||
import ec2
|
||||
parser = ArgumentParser(description='Bootstrap Debian for the cloud.')
|
||||
parser.add_argument('--debug', action='store_true',
|
||||
help='Print debugging information')
|
||||
|
||||
subparsers = parser.add_subparsers(title='providers', description='supported providers', dest='provider')
|
||||
ec2.init_subparser(subparsers)
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
||||
if __name__ == '__main__' and __package__ is None:
|
||||
main()
|
1
ec2/__init__.py
Normal file
1
ec2/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from main import init_subparser
|
40
ec2/ec2.py
Normal file
40
ec2/ec2.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
from common import Task
|
||||
|
||||
|
||||
class GetCredentials(Task):
|
||||
def run(self, info):
|
||||
super(GetCredentials, self).run(info)
|
||||
info.ec2_credentials = self.get_ec2_credentials(info.args, info.manifest)
|
||||
return info
|
||||
|
||||
def get_ec2_credentials(self, args, manifest):
|
||||
from os import getenv
|
||||
# args override manifest override environment
|
||||
if(args.access_key and args.secret_key):
|
||||
return {'access_key': args.access_key,
|
||||
'secret_key': args.secret_key}
|
||||
if(manifest.credentials['access-key'] and manifest.credentials['secret-key']):
|
||||
return {'access_key': manifest.credentials['access-key'],
|
||||
'secret_key': manifest.credentials['secret-key']}
|
||||
if(getenv('EC2_ACCESS_KEY') and getenv('EC2_SECRET_KEY')):
|
||||
return {'access_key': getenv('EC2_ACCESS_KEY'),
|
||||
'secret_key': getenv('EC2_SECRET_KEY')}
|
||||
|
||||
if(bool(args.access_key) != bool(args.secret_key)):
|
||||
raise RuntimeError('Both the access key and secret key must be specified as arguments.')
|
||||
if(bool(manifest.credentials['access-key']) != bool(manifest.credentials['secret-key'])):
|
||||
raise RuntimeError('Both the access key and secret key must be specified in the manifest.')
|
||||
if(bool(getenv('EC2_ACCESS_KEY')) != bool(getenv('EC2_SECRET_KEY'))):
|
||||
raise RuntimeError('Both the access key and secret key must be specified as environment variables.')
|
||||
|
||||
raise RuntimeError('No ec2 credentials found.')
|
||||
|
||||
|
||||
class Connect(Task):
|
||||
def run(self, info):
|
||||
super(Connect, self).run(info)
|
||||
# import boto.ec2
|
||||
# info.ec2_connection = boto.ec2.connect_to_region(info.host['region'],
|
||||
# aws_access_key_id=info.ec2_credentials['access_key'],
|
||||
# aws_secret_access_key=info.ec2_credentials['secret_key'])
|
||||
return info
|
16
ec2/host.py
Normal file
16
ec2/host.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from common import Task
|
||||
|
||||
|
||||
class GetInfo(Task):
|
||||
def run(self, info):
|
||||
super(GetInfo, self).run(info)
|
||||
import urllib2
|
||||
import json
|
||||
# response = urllib2.urlopen('http://169.254.169.254/latest/dynamic/instance-identity/document')
|
||||
# info.host = json.load(response.read())
|
||||
return info
|
||||
|
||||
|
||||
class InstallPackages(Task):
|
||||
def run(self, info):
|
||||
pass
|
37
ec2/main.py
Normal file
37
ec2/main.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
|
||||
def init_subparser(subparsers):
|
||||
cmd = subparsers.add_parser('ec2', help='Bootstrap Debian for EC2')
|
||||
cmd.add_argument('--access-key', help='AWS Access Key', metavar='ID')
|
||||
cmd.add_argument('--secret-key', help='AWS Secret Key', metavar='KEY')
|
||||
cmd.add_argument('manifest', help='Manifest file to use for bootstrapping', metavar='MANIFEST')
|
||||
cmd.set_defaults(func=run)
|
||||
|
||||
|
||||
def run(args):
|
||||
from manifest import Manifest
|
||||
from common import BootstrapInformation
|
||||
manifest = Manifest(args.manifest)
|
||||
manifest.validate()
|
||||
|
||||
task_list = get_tasklist(manifest)
|
||||
|
||||
info = BootstrapInformation(manifest=manifest, args=args)
|
||||
task_list.run(info)
|
||||
|
||||
|
||||
def get_tasklist(manifest):
|
||||
from common import TaskList
|
||||
import packages
|
||||
import ec2
|
||||
import host
|
||||
task_list = TaskList()
|
||||
task_list.extend([packages.HostPackages(),
|
||||
packages.ImagePackages(),
|
||||
ec2.GetCredentials(),
|
||||
host.GetInfo(),
|
||||
ec2.Connect(),
|
||||
host.InstallPackages()
|
||||
])
|
||||
|
||||
return task_list
|
11
ec2/manifest.py
Normal file
11
ec2/manifest.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
import common
|
||||
|
||||
|
||||
class Manifest(common.Manifest):
|
||||
def parse(self, data):
|
||||
super(Manifest, self).parse(data)
|
||||
self.credentials = data["credentials"]
|
||||
self.virtualization = data["virtualization"]
|
||||
|
||||
def validate(self):
|
||||
super(Manifest, self).validate()
|
55
ec2/packages.py
Normal file
55
ec2/packages.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
from common import Task
|
||||
|
||||
|
||||
class HostPackages(Task):
|
||||
def run(self, info):
|
||||
super(HostPackages, self).run(info)
|
||||
info.host_pkg = self.get_host_packages(info.manifest)
|
||||
return info
|
||||
|
||||
def get_host_packages(self, manifest):
|
||||
packages = set(['debootstrap',
|
||||
# To make sure a volume is not busy before unmounting we need lsof
|
||||
'lsof',
|
||||
])
|
||||
if manifest.volume['filesystem'] == 'xfs':
|
||||
packages.add('xfsprogs')
|
||||
|
||||
return packages
|
||||
|
||||
|
||||
class ImagePackages(Task):
|
||||
def run(self, info):
|
||||
super(ImagePackages, self).run(info)
|
||||
info.image_pkg_include, info.image_pkg_exclude = self.get_image_packages(info.manifest)
|
||||
return info
|
||||
|
||||
def get_image_packages(self, manifest):
|
||||
# Add some basic packages we are going to need
|
||||
include = set(['udev',
|
||||
'openssh-server',
|
||||
# We could bootstrap without locales, but things just suck without them, error messages etc.
|
||||
'locales',
|
||||
# Needed for the init scripts
|
||||
'file',
|
||||
# isc-dhcp-client doesn't work properly with ec2
|
||||
'dhcpcd',
|
||||
])
|
||||
|
||||
if manifest.virtualization == 'pvm':
|
||||
include.add('grub-pc')
|
||||
|
||||
exclude = set(['isc-dhcp-client',
|
||||
'isc-dhcp-common',
|
||||
])
|
||||
|
||||
# In squeeze, we need a special kernel flavor for xen
|
||||
kernels = {'squeeze': {'amd64': 'linux-image-xen-amd64',
|
||||
'i386': 'linux-image-xen-686', },
|
||||
'wheezy': {'amd64': 'linux-image-amd64',
|
||||
'i386': 'linux-image-686', }, }
|
||||
include.add(kernels.get(manifest.system['release']).get(manifest.system['architecture']))
|
||||
|
||||
include = include.union(manifest.system['packages'])
|
||||
|
||||
return include, exclude
|
36
manifests/ec2-ebs-pvm.manifest.json
Normal file
36
manifests/ec2-ebs-pvm.manifest.json
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"provider" : "ec2",
|
||||
"virtualization": "pvm",
|
||||
"credentials" : {
|
||||
"access-key": null,
|
||||
"secret-key": null
|
||||
},
|
||||
|
||||
"bootstrapdir" : "/target",
|
||||
"image": {
|
||||
"name" : "debian-{release}-{architecture}-{virt}-{year}{month}{day}",
|
||||
"description": "Debian {release} {architecture} AMI ({virt})"
|
||||
},
|
||||
"system": {
|
||||
"architecture": "amd64",
|
||||
"release" : "wheezy",
|
||||
"timezone" : "UTC",
|
||||
"locale" : "en_US",
|
||||
"charmap" : "UTF-8",
|
||||
"packages" : []
|
||||
},
|
||||
"volume": {
|
||||
"backing" : "ebs",
|
||||
"filesystem": "ext4",
|
||||
"size" : "1G"
|
||||
},
|
||||
"plugins": {
|
||||
"admin-user": {
|
||||
"enabled": true
|
||||
},
|
||||
"build-metadata": {
|
||||
"enabled": false,
|
||||
"path": "/root/build-metadata-{ami_name}"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue