Implement hvm support for ec2

This commit is contained in:
Anders Ingemann 2013-12-01 23:50:32 +01:00
parent 668b9896c1
commit 0a49901476
10 changed files with 156 additions and 119 deletions

View file

@ -1,6 +1,7 @@
from base import Task from base import Task
from common import phases from common import phases
import os from common.tasks import apt
import os.path
class BlackListModules(Task): class BlackListModules(Task):
@ -27,3 +28,65 @@ class DisableGetTTYs(Task):
for i in range(2, 7): for i in range(2, 7):
i = str(i) i = str(i)
sed_i(inittab_path, '^' + i + ttyx + i, '#' + i + ttyx + i) sed_i(inittab_path, '^' + i + ttyx + i, '#' + i + ttyx + i)
class InstallGrub(Task):
description = 'Installing grub'
phase = phases.system_modification
predecessors = [apt.AptUpgrade]
def run(self, info):
from common.fs.loopbackvolume import LoopbackVolume
from common.tools import log_check_call
boot_dir = os.path.join(info.root, 'boot')
grub_dir = os.path.join(boot_dir, 'grub')
from base.fs.partitionmaps.none import NoPartitions
from base.fs.partitionmaps.gpt import GPTPartitionMap
from common.fs import remount
p_map = info.volume.partition_map
def link_fn():
info.volume.link_dm_node()
if isinstance(p_map, NoPartitions):
p_map.root.device_path = info.volume.device_path
def unlink_fn():
info.volume.unlink_dm_node()
if isinstance(p_map, NoPartitions):
p_map.root.device_path = info.volume.device_path
# GRUB cannot deal with installing to loopback devices
# so we fake a real harddisk with dmsetup.
# Guide here: http://ebroder.net/2009/08/04/installing-grub-onto-a-disk-image/
if isinstance(info.volume, LoopbackVolume):
remount(info.volume, link_fn)
try:
[device_path] = log_check_call(['readlink', '-f', info.volume.device_path])
device_map_path = os.path.join(grub_dir, 'device.map')
partition_prefix = 'msdos'
if isinstance(p_map, GPTPartitionMap):
partition_prefix = 'gpt'
with open(device_map_path, 'w') as device_map:
device_map.write('(hd0) {device_path}\n'.format(device_path=device_path))
if not isinstance(p_map, NoPartitions):
for idx, partition in enumerate(info.volume.partition_map.partitions):
[partition_path] = log_check_call(['readlink', '-f', partition.device_path])
device_map.write('(hd0,{prefix}{idx}) {device_path}\n'
.format(device_path=partition_path, prefix=partition_prefix, idx=idx+1))
# Install grub
log_check_call(['/usr/sbin/chroot', info.root,
'/usr/sbin/grub-install',
# '--root-directory=' + info.root,
# '--boot-directory=' + boot_dir,
device_path])
log_check_call(['/usr/sbin/chroot', info.root, '/usr/sbin/update-grub'])
except Exception as e:
if isinstance(info.volume, LoopbackVolume):
remount(info.volume, unlink_fn)
raise e
if isinstance(info.volume, LoopbackVolume):
remount(info.volume, unlink_fn)

View file

@ -0,0 +1,50 @@
{
"provider": "ec2",
"virtualization": "hvm",
"credentials": {
// "access-key": null,
// "secret-key": null
},
"bootstrapper": {
"workspace": "/target"
},
"image": {
"name": "debian-{release}-{architecture}-{virtualization}-{%y}{%m}{%d}",
"description": "Debian {release} {architecture} AMI ({virtualization})"
},
"system": {
"release": "wheezy",
"architecture": "amd64",
"timezone": "UTC",
"locale": "en_US",
"charmap": "UTF-8"
},
"volume": {
"backing": "ebs",
"partitions": {
"type": "none",
"root": {
"size": 8192,
"filesystem": "ext4"
}
}
},
"plugins": {
"packages": {
"sources": {
"backports": [
"deb {apt_mirror} {release}-backports main",
"deb-src {apt_mirror} {release}-backports main"
]
},
"remote": [
"sudo",
{ "name": "cloud-init", "target": "{release}-backports" }
]
},
"cloud_init": {
"username": "admin"
}
}
}

View file

@ -50,7 +50,6 @@ def tasks(tasklist, manifest):
ami.AMIName, ami.AMIName,
connection.Connect, connection.Connect,
boot.ConfigureGrub,
common_boot.BlackListModules, common_boot.BlackListModules,
common_boot.DisableGetTTYs, common_boot.DisableGetTTYs,
security.EnableShadowConfig, security.EnableShadowConfig,
@ -68,6 +67,11 @@ def tasks(tasklist, manifest):
ami.RegisterAMI) ami.RegisterAMI)
if manifest.virtualization == 'pvm':
tasklist.add(boot.ConfigurePVGrub)
else:
tasklist.add(common_boot.InstallGrub)
backing_specific_tasks = {'ebs': [ebs.Create, backing_specific_tasks = {'ebs': [ebs.Create,
ebs.Attach, ebs.Attach,
common_filesystem.FStab, common_filesystem.FStab,

View file

@ -3,6 +3,7 @@
"title": "EC2 manifest", "title": "EC2 manifest",
"type": "object", "type": "object",
"properties": { "properties": {
"virtualization": { "enum": ["pvm", "hvm"] },
"image": { "image": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -151,52 +151,38 @@ class RegisterAMI(Task):
}} }}
def run(self, info): def run(self, info):
if info.manifest.volume['backing'] == 'ebs': registration_params = {'name': info.ami_name,
self.run_ebs(info) 'description': info.ami_description}
registration_params['architecture'] = {'i386': 'i386',
'amd64': 'x86_64'}.get(info.manifest.system['architecture'])
if info.manifest.volume['backing'] == 's3': if info.manifest.volume['backing'] == 's3':
self.run_s3(info) grub_boot_device = 'hd0'
registration_params['root_device_name'] = 'dev/sda1'
def run_ebs(self, info): else:
arch = {'i386': 'i386', 'amd64': 'x86_64'}.get(info.manifest.system['architecture'])
from base.fs.partitionmaps.none import NoPartitions from base.fs.partitionmaps.none import NoPartitions
if isinstance(info.volume.partition_map, NoPartitions): if isinstance(info.volume.partition_map, NoPartitions):
grub_boot_device = 'hd0' grub_boot_device = 'hd0'
root_device_name = '/dev/sda' registration_params['root_device_name'] = '/dev/sda'
else: else:
grub_boot_device = 'hd00' grub_boot_device = 'hd00'
root_idx = info.volume.partition_map.root.get_index() root_idx = info.volume.partition_map.root.get_index()
root_device_name = '/dev/sda{idx}'.format(idx=root_idx) registration_params['root_device_name'] = '/dev/sda{idx}'.format(idx=root_idx)
kernel_id = (self.kernel_mapping
.get(info.host['region'])
.get(grub_boot_device)
.get(info.manifest.system['architecture']))
from boto.ec2.blockdevicemapping import BlockDeviceType from boto.ec2.blockdevicemapping import BlockDeviceType
from boto.ec2.blockdevicemapping import BlockDeviceMapping from boto.ec2.blockdevicemapping import BlockDeviceMapping
block_device = BlockDeviceType(snapshot_id=info.snapshot.id, delete_on_termination=True, block_device = BlockDeviceType(snapshot_id=info.snapshot.id, delete_on_termination=True,
size=info.volume.partition_map.get_total_size()/1024) size=info.volume.partition_map.get_total_size()/1024)
block_device_map = BlockDeviceMapping() registration_params['block_device_map'] = BlockDeviceMapping()
block_device_map['/dev/sda'] = block_device registration_params['block_device_map']['/dev/sda'] = block_device
info.image = info.connection.register_image(name=info.ami_name, description=info.ami_description, if info.manifest.virtualization == 'hvm':
architecture=arch, kernel_id=kernel_id, registration_params['virtualization_type'] = 'hvm'
root_device_name=root_device_name, else:
block_device_map=block_device_map) registration_params['virtualization_type'] = 'paravirtual'
registration_params['kernel_id'] = (self.kernel_mapping
def run_s3(self, info):
arch = {'i386': 'i386', 'amd64': 'x86_64'}.get(info.manifest.system['architecture'])
kernel_id = (self.kernel_mapping
.get(info.host['region']) .get(info.host['region'])
.get('hd0') .get(grub_boot_device)
.get(info.manifest.system['architecture'])) .get(info.manifest.system['architecture']))
image_manifest = ('{bucket}/{ami_name}.manifest.xml' info.image = info.connection.register_image(**registration_params)
.format(bucket=info.manifest.image['bucket'],
ami_name=info.ami_name))
info.image = info.connection.register_image(name=info.ami_name, description=info.ami_description,
architecture=arch, kernel_id=kernel_id,
root_device_name='dev/sda1',
image_location=image_manifest)

View file

@ -3,8 +3,8 @@ from common import phases
import os import os
class ConfigureGrub(Task): class ConfigurePVGrub(Task):
description = 'Configuring grub' description = 'Creating grub config files for PVGrub'
phase = phases.system_modification phase = phases.system_modification
def run(self, info): def run(self, info):

View file

@ -26,7 +26,6 @@ class ImagePackages(Task):
include.add('openssh-server') include.add('openssh-server')
include.add('file') # Needed for the init scripts include.add('file') # Needed for the init scripts
include.add('dhcpcd') # isc-dhcp-client doesn't work properly with ec2 include.add('dhcpcd') # isc-dhcp-client doesn't work properly with ec2
if manifest.virtualization == 'pvm':
include.add('grub-pc') include.add('grub-pc')
exclude.add('isc-dhcp-client') exclude.add('isc-dhcp-client')

View file

@ -5,8 +5,7 @@ from common.tasks import loopback
from common.tasks import partitioning from common.tasks import partitioning
from common.tasks import filesystem from common.tasks import filesystem
from common.tasks import bootstrap from common.tasks import bootstrap
from tasks import boot from common.tasks import boot
from common.tasks import boot as common_boot
from common.tasks import security from common.tasks import security
from common.tasks import network from common.tasks import network
from common.tasks import initd from common.tasks import initd
@ -38,9 +37,9 @@ def tasks(tasklist, manifest):
loopback.Create, loopback.Create,
boot.ConfigureGrub, boot.InstallGrub,
common_boot.BlackListModules, boot.BlackListModules,
common_boot.DisableGetTTYs, boot.DisableGetTTYs,
security.EnableShadowConfig, security.EnableShadowConfig,
network.RemoveDNSInfo, network.RemoveDNSInfo,
network.ConfigureNetworkIF, network.ConfigureNetworkIF,

View file

@ -1,65 +0,0 @@
from base import Task
from common import phases
from common.tasks import apt
from common.fs.loopbackvolume import LoopbackVolume
class ConfigureGrub(Task):
description = 'Configuring grub'
phase = phases.system_modification
predecessors = [apt.AptUpgrade]
def run(self, info):
import os
from common.tools import log_check_call
boot_dir = os.path.join(info.root, 'boot')
grub_dir = os.path.join(boot_dir, 'grub')
from base.fs.partitionmaps.none import NoPartitions
from base.fs.partitionmaps.gpt import GPTPartitionMap
from common.fs import remount
p_map = info.volume.partition_map
def mk_remount_fn(fn):
def set_device_path():
fn()
if isinstance(p_map, NoPartitions):
p_map.root.device_path = info.volume.device_path
return set_device_path
link_fn = mk_remount_fn(info.volume.link_dm_node)
unlink_fn = mk_remount_fn(info.volume.unlink_dm_node)
# GRUB cannot deal with installing to loopback devices
# so we fake a real harddisk with dmsetup.
# Guide here: http://ebroder.net/2009/08/04/installing-grub-onto-a-disk-image/
if isinstance(info.volume, LoopbackVolume):
remount(info.volume, link_fn)
try:
[device_path] = log_check_call(['readlink', '-f', info.volume.device_path])
device_map_path = os.path.join(grub_dir, 'device.map')
partition_prefix = 'msdos'
if isinstance(p_map, GPTPartitionMap):
partition_prefix = 'gpt'
with open(device_map_path, 'w') as device_map:
device_map.write('(hd0) {device_path}\n'.format(device_path=device_path))
if not isinstance(p_map, NoPartitions):
for idx, partition in enumerate(info.volume.partition_map.partitions):
[partition_path] = log_check_call(['readlink', '-f', partition.device_path])
device_map.write('(hd0,{prefix}{idx}) {device_path}\n'
.format(device_path=partition_path, prefix=partition_prefix, idx=idx+1))
# Install grub
log_check_call(['/usr/sbin/chroot', info.root,
'/usr/sbin/grub-install',
# '--root-directory=' + info.root,
# '--boot-directory=' + boot_dir,
device_path])
log_check_call(['/usr/sbin/chroot', info.root, '/usr/sbin/update-grub'])
except Exception as e:
if isinstance(info.volume, LoopbackVolume):
remount(info.volume, unlink_fn)
raise e
if isinstance(info.volume, LoopbackVolume):
remount(info.volume, unlink_fn)