| @@ -0,0 +1 @@ | |||
| __pycache__ | |||
| @@ -1,58 +1,31 @@ | |||
| from argparse import ArgumentParser | |||
| import yaml | |||
| import os | |||
| from weir import zfs, process | |||
| from .build import build | |||
| # from weir import zfs, process | |||
| from .image import command_image_build | |||
| import sys | |||
| from .zfs import zfs_init | |||
| def clone(self, name, props={}, force=False): | |||
| url = zfs._urlsplit(self.name) | |||
| url_1 = zfs._urlsplit(name) | |||
| if url.netloc != url_1.netloc: | |||
| raise ValueError('Clone has to happen on the same host') | |||
| cmd = ['zfs', 'clone'] | |||
| for prop, value in props.items(): | |||
| cmd.append('-o') | |||
| cmd.append(prop + '=' + str(value)) | |||
| cmd.append(url.path) | |||
| cmd.append(url_1.path) | |||
| process.check_call(cmd, netloc=url.netloc) | |||
| zfs.ZFSSnapshot.clone = clone | |||
| def command_build(args): | |||
| fname = os.path.join(args.focker_dir, 'Fockerfile.yml') | |||
| print('fname:', fname) | |||
| if not os.path.exists(fname): | |||
| raise ValueError('No Fockerfile.yml could be found in the specified directory') | |||
| with open(fname, 'r') as f: | |||
| spec = yaml.safe_load(f) | |||
| print('spec:', spec) | |||
| build(spec) | |||
| def create_parser(): | |||
| parser_top = ArgumentParser() | |||
| subparsers_top = parser_top.add_subparsers() | |||
| def run(args): | |||
| pass | |||
| subparsers = subparsers_top.add_parser('image').add_subparsers() | |||
| parser = subparsers.add_parser('build') | |||
| parser.set_defaults(func=command_image_build) | |||
| parser.add_argument('focker_dir', type=str) | |||
| return parser_top | |||
| def create_parser(): | |||
| parser = ArgumentParser() | |||
| subparsers = parser.add_subparsers() | |||
| parser_build = subparsers.add_parser('build') | |||
| parser_build.set_defaults(func=command_build) | |||
| parser_build.add_argument('focker_dir', type=str) | |||
| parser_run = subparsers.add_parser('run') | |||
| parser_run.set_defaults(func=run) | |||
| parser_rm = subparsers.add_parser('rm') | |||
| parser_rmi = subparsers.add_parser('rmi') | |||
| parser_ps = subparsers.add_parser('ps') | |||
| parser_images = subparsers.add_parser('images') | |||
| return parser | |||
| def main(): | |||
| zfs_init() | |||
| parser = create_parser() | |||
| args = parser.parse_args() | |||
| if not hasattr(args, 'func'): | |||
| sys.exit('You must choose a mode') | |||
| args.func(args) | |||
| parser = create_parser() | |||
| args = parser.parse_args() | |||
| if not hasattr(args, 'func'): | |||
| raise ValueError('You must choose the mode') | |||
| args.func(args) | |||
| if __name__ == '__main__': | |||
| main() | |||
| @@ -1,4 +1,6 @@ | |||
| from .zfs import * | |||
| import os | |||
| import yaml | |||
| def process_step(step, name): | |||
| @@ -17,8 +19,19 @@ def process_steps(steps, name): | |||
| def build(spec): | |||
| if 'base' not in spec: | |||
| raise ValueError('Missing base specification') | |||
| base = spec.base | |||
| base = zfs_snapshot_by_tag_or_name(base) | |||
| base = spec['base'] | |||
| base = zfs_snapshot_by_tag_or_sha256(base) | |||
| root = '/'.join(base.split('/')[:-1]) | |||
| print('base:', base, 'root:', root) | |||
| def command_image_build(args): | |||
| fname = os.path.join(args.focker_dir, 'Fockerfile') | |||
| print('fname:', fname) | |||
| if not os.path.exists(fname): | |||
| raise ValueError('No Fockerfile could be found in the specified directory') | |||
| with open(fname, 'r') as f: | |||
| spec = yaml.safe_load(f) | |||
| print('spec:', spec) | |||
| build(spec) | |||
| @@ -1,10 +1,12 @@ | |||
| import subprocess | |||
| import csv | |||
| import io | |||
| import os | |||
| def zfs_run(command): | |||
| out = subprocess.check_output(command) | |||
| # print('Running:', command) | |||
| out = subprocess.check_output(command, stderr=subprocess.STDOUT) | |||
| return out | |||
| @@ -20,15 +22,42 @@ def zfs_get_type(name): | |||
| return lst[0][1] | |||
| def zfs_snapshot_by_tag_or_name(s): | |||
| lst = zfs_parse_output(['zfs', 'list', '-o', 'name,focker:tags,type', '-H']) | |||
| lst = list(filter(lambda a: (a[0] == s or s in a[1].split(' ') and a[2] == 'snapshot'))) | |||
| def zfs_snapshot_by_tag_or_sha256(s): | |||
| lst = zfs_parse_output(['zfs', 'list', '-o', 'focker:sha256,focker:tags,type,name', '-H', '-t', 'snapshot']) | |||
| lst = list(filter(lambda a: (a[0] == s or s in a[1].split(' ')) and a[2] == 'snapshot', lst)) | |||
| if len(lst) == 0: | |||
| raise ValueError('Reference not found: ' + s) | |||
| if len(lst) > 1: | |||
| raise ValueError('Ambiguous reference: ' + s) | |||
| return lst[0][0] | |||
| return lst[0][3] | |||
| def zfs_clone(name, target_name): | |||
| zfs_run(['zfs', 'clone', name, target_name]) | |||
| def zfs_exists(name): | |||
| try: | |||
| zfs_run(['zfs', 'list', name]) | |||
| except subprocess.CalledProcessError as e: | |||
| return False | |||
| return True | |||
| def zfs_init(): | |||
| poolname = zfs_parse_output(['zfs', 'list', '-H', '/']) | |||
| if len(poolname) == 0: | |||
| raise ValueError('Not a ZFS root') | |||
| poolname = poolname[0][0].split('/')[0] | |||
| print('poolname:', poolname) | |||
| for path in ['/focker', '/focker/images', '/focker/volumes', '/focker/jails']: | |||
| if not os.path.exists(path): | |||
| os.mkdir(path) | |||
| if not zfs_exists(poolname + '/focker'): | |||
| zfs_run(['zfs', 'create', '-o', 'canmount=off', '-o', 'mountpoint=/focker', poolname + '/focker']) | |||
| if not zfs_exists(poolname + '/focker/images'): | |||
| zfs_run(['zfs', 'create', '-o', 'canmount=off', poolname + '/focker/images']) | |||
| if not zfs_exists(poolname + '/focker/volumes'): | |||
| zfs_run(['zfs', 'create', '-o', 'canmount=off', poolname + '/focker/volumes']) | |||
| if not zfs_exists(poolname + '/focker/volumes'): | |||
| zfs_run(['zfs', 'create', '-o', 'canmount=off', poolname + '/focker/jails']) | |||