First stab at docker provider

Huh... That was easy.
This commit is contained in:
Anders Ingemann 2015-12-09 19:00:06 +01:00 committed by Anders Ingemann
parent 3de0aceb65
commit 4a509aba76
12 changed files with 196 additions and 3 deletions

View file

@ -24,12 +24,14 @@ def load_volume(data, bootloader):
from bootstrapvz.common.fs.virtualdiskimage import VirtualDiskImage from bootstrapvz.common.fs.virtualdiskimage import VirtualDiskImage
from bootstrapvz.common.fs.virtualharddisk import VirtualHardDisk from bootstrapvz.common.fs.virtualharddisk import VirtualHardDisk
from bootstrapvz.common.fs.virtualmachinedisk import VirtualMachineDisk from bootstrapvz.common.fs.virtualmachinedisk import VirtualMachineDisk
from bootstrapvz.common.fs.folder import Folder
volume_backing = {'raw': LoopbackVolume, volume_backing = {'raw': LoopbackVolume,
's3': LoopbackVolume, 's3': LoopbackVolume,
'vdi': VirtualDiskImage, 'vdi': VirtualDiskImage,
'vhd': VirtualHardDisk, 'vhd': VirtualHardDisk,
'vmdk': VirtualMachineDisk, 'vmdk': VirtualMachineDisk,
'ebs': EBSVolume 'ebs': EBSVolume,
'folder': Folder
}.get(data['backing']) }.get(data['backing'])
# Instantiate the partition map # Instantiate the partition map

View file

@ -31,6 +31,13 @@ properties:
tarball: {type: boolean} tarball: {type: boolean}
workspace: workspace:
$ref: '#/definitions/path' $ref: '#/definitions/path'
variant:
type: string
enum:
- minbase
- buildd
- fakechroot
- scratchbox
required: [workspace] required: [workspace]
additionalProperties: false additionalProperties: false
image: image:
@ -50,6 +57,7 @@ properties:
- pvgrub - pvgrub
- grub - grub
- extlinux - extlinux
- none
charmap: {type: string} charmap: {type: string}
hostname: hostname:
type: string type: string

View file

@ -0,0 +1,24 @@
from bootstrapvz.base.fs.volume import Volume
class Folder(Volume):
# Override the states this volume can be in (i.e. we can't "format" or "attach" it)
events = [{'name': 'create', 'src': 'nonexistent', 'dst': 'attached'},
{'name': 'delete', 'src': 'attached', 'dst': 'deleted'},
]
extension = 'chroot'
def create(self, path):
self.fsm.create(path=path)
def _before_create(self, e):
import os
self.path = e.path
os.mkdir(self.path)
def _before_delete(self, e):
from shutil import rmtree
rmtree(self.path)
del self.path

View file

@ -16,6 +16,7 @@ from tasks import network
from tasks import initd from tasks import initd
from tasks import ssh from tasks import ssh
from tasks import kernel from tasks import kernel
from tasks import folder
def get_standard_groups(manifest): def get_standard_groups(manifest):
@ -94,6 +95,9 @@ ssh_group = [ssh.AddOpenSSHPackage,
def get_network_group(manifest): def get_network_group(manifest):
if manifest.bootstrapper.get('variant', None) == 'minbase':
# minbase has no networking
return []
group = [network.ConfigureNetworkIF, group = [network.ConfigureNetworkIF,
network.RemoveDNSInfo] network.RemoveDNSInfo]
if manifest.system.get('hostname', False): if manifest.system.get('hostname', False):
@ -182,6 +186,7 @@ rollback_map = {workspace.CreateWorkspace: workspace.DeleteWorkspace,
partitioning.MapPartitions: partitioning.UnmapPartitions, partitioning.MapPartitions: partitioning.UnmapPartitions,
filesystem.CreateMountDir: filesystem.DeleteMountDir, filesystem.CreateMountDir: filesystem.DeleteMountDir,
filesystem.MountRoot: filesystem.UnmountRoot, filesystem.MountRoot: filesystem.UnmountRoot,
folder.Create: folder.Delete,
} }

View file

@ -21,6 +21,8 @@ def get_bootstrap_args(info):
executable = ['debootstrap'] executable = ['debootstrap']
arch = info.manifest.system.get('userspace_architecture', info.manifest.system.get('architecture')) arch = info.manifest.system.get('userspace_architecture', info.manifest.system.get('architecture'))
options = ['--arch=' + arch] options = ['--arch=' + arch]
if 'variant' in info.manifest.bootstrapper:
options.append('--variant=' + info.manifest.bootstrapper['variant'])
if len(info.include_packages) > 0: if len(info.include_packages) > 0:
options.append('--include=' + ','.join(info.include_packages)) options.append('--include=' + ','.join(info.include_packages))
if len(info.exclude_packages) > 0: if len(info.exclude_packages) > 0:
@ -53,8 +55,8 @@ class MakeTarball(Task):
else: else:
from ..tools import log_call from ..tools import log_call
status, out, err = log_call(executable + options + ['--make-tarball=' + info.tarball] + arguments) status, out, err = log_call(executable + options + ['--make-tarball=' + info.tarball] + arguments)
if status != 1: if status not in [0, 1]: # variant=minbase exits with 0
msg = 'debootstrap exited with status {status}, it should exit with status 1'.format(status=status) msg = 'debootstrap exited with status {status}, it should exit with status 0 or 1'.format(status=status)
raise TaskError(msg) raise TaskError(msg)

View file

@ -0,0 +1,27 @@
from bootstrapvz.base import Task
from bootstrapvz.common import phases
import volume
import workspace
class Create(Task):
description = 'Creating volume folder'
phase = phases.volume_creation
successors = [volume.Attach]
@classmethod
def run(cls, info):
import os.path
info.root = os.path.join(info.workspace, 'root')
info.volume.create(info.root)
class Delete(Task):
description = 'Deleting volume folder'
phase = phases.cleaning
successors = [workspace.DeleteWorkspace]
@classmethod
def run(cls, info):
info.volume.delete()
del info.root

View file

@ -0,0 +1,34 @@
from bootstrapvz.common.tasks import folder
from bootstrapvz.common.tasks import filesystem
from bootstrapvz.common.tasks import locale
from bootstrapvz.common import task_groups
import tasks.commands
import tasks.image
def validate_manifest(data, validator, error):
import os.path
schema_path = os.path.normpath(os.path.join(os.path.dirname(__file__), 'manifest-schema.yml'))
validator(data, schema_path)
def resolve_tasks(taskset, manifest):
taskset.update(task_groups.get_base_group(manifest))
taskset.update([folder.Create,
filesystem.CopyMountTable,
locale.SetTimezone,
filesystem.RemoveMountTable,
folder.Delete,
])
taskset.update(task_groups.get_network_group(manifest))
taskset.update(task_groups.get_apt_group(manifest))
taskset.update(task_groups.security_group)
taskset.update(task_groups.cleanup_group)
taskset.update([tasks.commands.AddRequiredCommands,
tasks.image.CreateImage,
])
def resolve_rollback_tasks(taskset, manifest, completed, counter_task):
taskset.update(task_groups.get_standard_rollback_tasks(completed))

View file

@ -0,0 +1,32 @@
---
$schema: http://json-schema.org/draft-04/schema#
title: Docker manifest
type: object
properties:
provider:
type: object
properties:
repository:
type: string
tag:
type: string
required: [repository, tag]
system:
type: object
properties:
bootloader:
type: string
enum: [none]
volume:
type: object
properties:
backing:
type: string
enum: [folder]
partitions:
type: object
properties:
type:
type: string
enum: [none]
required: [backing]

View file

@ -0,0 +1,13 @@
from bootstrapvz.base import Task
from bootstrapvz.common import phases
from bootstrapvz.common.tasks import host
class AddRequiredCommands(Task):
description = 'Adding commands required for docker'
phase = phases.preparation
successors = [host.CheckExternalCommands]
@classmethod
def run(cls, info):
info.host_dependencies['docker'] = 'docker.io'

View file

@ -0,0 +1,20 @@
from bootstrapvz.base import Task
from bootstrapvz.common import phases
from bootstrapvz.common.tasks import image
from bootstrapvz.common.tools import log_check_call
class CreateImage(Task):
description = 'Creating docker image'
phase = phases.image_registration
predecessors = [image.MoveImage]
@classmethod
def run(cls, info):
from pipes import quote
tar_cmd = ['tar', '--create', '--numeric-owner',
'--directory', info.volume.path, '.']
docker_cmd = ['docker', 'import', '-',
info.manifest.provider['repository'] + ':' + info.manifest.provider['tag']]
cmd = ' '.join(map(quote, tar_cmd)) + ' | ' + ' '.join(map(quote, docker_cmd))
[info._docker['container_id']] = log_check_call(cmd, shell=True)

View file

@ -0,0 +1,26 @@
---
provider:
name: docker
repository: bootstrap-vz
tag: latest
bootstrapper:
workspace: /target
variant: minbase
image:
name: debian-{system.release}-{system.architecture}-{%y}{%m}{%d}
description: Debian {system.release} {system.architecture}
system:
release: jessie
architecture: amd64
bootloader: none
charmap: UTF-8
locale: en_US
timezone: UTC
packages: {}
volume:
backing: folder
partitions:
type: none
root:
filesystem: ext4
size: 1GiB