77 lines
2.5 KiB
Python

# -*- coding: utf-8 -*-
import os
import shutil
import tarfile
from . import crypto
from . import repo_local
from . import repo_publish
from . import utils
from .paths import LAYERS_DIR, PUB_LAYERS_DIR
DEFINITION_MEMBERS = {'layers', 'env', 'uid', 'gid', 'cmd', 'cwd', 'ready', 'halt', 'size', 'dlsize', 'hash'}
class Image:
def __init__(self, name, load_from_repo=True):
self.name = name
self.layer_path = os.path.join(LAYERS_DIR, name)
self.archive_path = os.path.join(PUB_LAYERS_DIR, f'{name}.tar.xz')
self.layers = [name]
self.env = {}
self.uid = None
self.gid = None
self.cmd = None
self.cwd = None
self.ready = None
self.halt = None
self.size = None
self.dlsize = None
self.hash = None
if load_from_repo:
self.set_definition(repo_local.get_image(name))
def set_definition(self, definition):
for key in DEFINITION_MEMBERS.intersection(definition):
setattr(self, key, definition[key])
def get_definition(self):
definition = {}
for key in DEFINITION_MEMBERS:
value = getattr(self, key)
if value:
definition[key] = value
return definition
def create(self, imagebuilder):
# Build the container from image file and save to local repository
# Chown is possible only when the process is running as root, for user namespaces, see https://linuxcontainers.org/lxc/manpages/man1/lxc-usernsexec.1.html
os.makedirs(self.layer_path, 0o755, True)
os.chown(self.layer_path, 100000, 100000)
imagebuilder.process_file()
repo_local.register_image(self.name, self.get_definition())
def delete(self):
repo_local.unregister_image(self.name)
try:
shutil.rmtree(self.layer_path)
except FileNotFoundError:
pass
def publish(self):
ctr = utils.TarSizeCounter()
os.makedirs(PUB_LAYERS_DIR, 0o755, True)
with tarfile.open(self.archive_path, 'w:xz') as tar:
tar.add(self.layer_path, self.name, filter=ctr.add_file)
self.size = ctr.size
self.dlsize = os.path.getsize(self.archive_path)
self.hash = crypto.hash_file(self.archive_path)
repo_publish.register_image(self.name, self.get_definition())
def unpublish(self):
repo_publish.unregister_image(self.name)
try:
os.unlink(self.archive_path)
except FileNotFoundError:
pass