# -*- coding: utf-8 -*- import os import sys from enum import Enum from lxcmgr import lxcmgr from .imagebuilder import ImageBuilder, ImageExistsError, ImageNotFoundError from .imagepacker import ImagePacker from .packer import PackageExistsError class BuildType(Enum): NORMAL = 1 FORCE = 2 SCRATCH = 3 METADATA = 4 class Image: def __init__(self): self.name = None self.conf = {} self.lxcfile = None self.build_dir = None self.build_type = BuildType.NORMAL self.pack = False def build_and_pack(self, lxcfile): self.lxcfile = lxcfile self.build_dir = os.path.dirname(lxcfile) self.conf['build'] = True builder = ImageBuilder(self) try: builder.build() # Packaging needs to happen in any case after a successful build in order to prevent outdated packages self.pack = True except ImageExistsError as e: # If container already exists and build hasn't been forced, rerun the build just for metadata which are still needed for packaging print('Image {} already exists, skipping build tasks'.format(e)) self.build_type = BuildType.METADATA builder.build() except ImageNotFoundError as e: # If one of the layers is missing, cleanup and die print('Image {} not found, can\'t build {}'.format(e, self.name)) builder.clean() sys.exit(1) except: # If build fails with another exception, cleanup (unless we were doing scratch build) and re-raise if not self.build_type == BuildType.SCRATCH: builder.clean() raise del self.conf['build'] # If we're doing a scratch build, regenerate the final LXC container configuration including ephemeral layer if self.build_type == BuildType.SCRATCH: lxcmgr.create_container(self.name, self.conf) else: try: packer = ImagePacker(self) packer.pack() except PackageExistsError as e: print('Package {} already exists, skipping packaging tasks'.format(e)) def remove(self): builder = ImageBuilder(self) builder.clean() packer = ImagePacker(self) packer.remove()