92 lines
3.1 KiB
Python
Executable File
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)
|