This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
misc-csiraut/publik-builder/publik-builder

92 lines
3.1 KiB
Python
Executable File

#!/usr/bin/python3
# Publik image builder
# 2018 Entr'ouvert
from contextlib import contextmanager
import argparse
import os
import shutil
import subprocess
import uuid
parser = argparse.ArgumentParser()
parser.add_argument('--release', type=str, default='stretch')
parser.add_argument('--prefix', type=str, default='publik')
parser.add_argument('--arch', type=str, default='amd64')
parser.add_argument('--clean', action='store_true')
parser.add_argument('--flavor', choices=['server', 'devinst', 'vanilla'], default='server')
parser.add_argument('--form', choices=['tar', 'xz', 'folder'], default='xz')
args = parser.parse_args()
options = vars(args)
options['mirror'] = 'http://httpredir.debian.org/debian/'
options['tag'] = '{release}-{arch}'.format(**options)
options['cachedir'] = '/var/cache/publik-builder'
options['output_dir'] = os.getcwd()
options['output'] = '{output_dir}/{prefix}-{tag}'.format(**options)
if os.getuid():
raise(Exception('please with sudo (or as root)'))
def run(cmd):
subprocess.run(cmd, shell=True, check=True)
@contextmanager
def mount_chroot(path):
run('mount -t proc /proc {}/proc'.format(path))
run('mount --bind /sys {}/sys'.format(path))
run('mount --bind /dev {}/dev'.format(path))
run('mount --bind /tmp {}/tmp'.format(path))
try:
yield
finally:
run('umount {}/tmp'.format(path))
run('umount {}/dev'.format(path))
run('umount {}/sys'.format(path))
run('umount {}/proc'.format(path))
rootfs = os.path.join(options['cachedir'], options['tag'])
if args.clean and os.path.isdir(rootfs):
shutil.rmtree(rootfs)
if not os.path.isdir(rootfs):
if not os.path.isdir(options['cachedir']):
os.makedirs(options['cachedir'])
options['rootfs'] = rootfs
run('debootstrap --foreign {release} {rootfs}'.format(**options))
run('DEBOOTSTRAP_DIR={rootfs}/debootstrap debootstrap --second-stage --arch {arch} --second-stage-target {rootfs} {mirror}'.format(**options))
workdir = os.path.join('/tmp/publik-builder', str(uuid.uuid4()))
if not os.path.isdir('/tmp/publik-builder'):
os.makedirs('/tmp/publik-builder')
options['workdir'] = workdir
print('copying base to workdir {}'.format(workdir))
run('cp -r {} {}'.format(rootfs, workdir))
if args.flavor != 'none':
if args.flavor == 'devinst':
raise(Exception('not implemented'))
script = '/var/lib/publik-builder/flavors/%s' % args.flavor
if not os.path.isfile(script):
script = './flavors/%s' % args.flavor
if not os.path.isfile:
raise(Exception('cannot find {}'.format(script)))
rscript = '{}/usr/local/bin/publik-bootstrap'.format(workdir)
shutil.copyfile(script, rscript)
run('chmod +x {}'.format(rscript))
with mount_chroot(workdir):
run('chroot {} publik-bootstrap'.format(workdir))
run('chroot {} apt-get clean'.format(workdir))
if args.form == 'tar':
run('cd {workdir} && tar cf {output}.tar ./'.format(**options))
elif args.form == 'xz':
run('cd {workdir} && tar cfJ {output}.tar.xz ./'.format(**options))
elif args.form == 'folder':
folder = '{output_dir}/{prefix}-{tag}'.format(**options)
shutil.move(workdir, folder)