def main(): fingertip.util.log.nicer() # warn if there is no reflink support path = fingertip.util.path.MACHINES fingertip.util.log.debug(f"checking reflink support for {path}") if not fingertip.util.reflink.is_supported(path): fingertip.util.log.warning( f"Reflink not supported for machines directory ('{path}'), " f"Copy-on-Write not possible, YOU DON'T WANT THIS! " f"See README.md, section 'CoW' on why and how to enable it.") args = sys.argv[1:] if not args: fingertip.util.log.error('no plugin specified') sys.exit(1) subcmds = [ list(ws) for x, ws in itertools.groupby(args, lambda w: w != '+') if x ] first_step, *rest_of_the_steps = [parse_subcmd(*sc) for sc in subcmds] first_step_cmd, first_step_args, first_step_kwargs = first_step m = fingertip.build(first_step_cmd, *first_step_args, **first_step_kwargs) for step_cmd, step_args, step_kwargs in rest_of_the_steps: m = m.apply(step_cmd, *step_args, **step_kwargs) fingertip.util.log.plain()
def main(): # Start with plain to get output from setup wizard fingertip.util.log.plain() if (sys.argv[1:] not in (['cleanup', 'periodic'], ['filesystem', 'cleanup'])): fingertip.util.reflink.storage_setup_wizard() fingertip.util.cleanup_job.schedule() fingertip.util.log.nicer() args = sys.argv[1:] if not args: info = """ Name: fingertip - a tool to control VMs/containers Usage: fingertip os.fedora + script.debug myscript.sh # checkpoint-powered debugger fingertip os.fedora --version=34 + script.debug myscript.sh # install Fedora 34 and debug a script fingertip os.fedora + ssh # install Fedora and SSH into it fingertip cleanup machines all # empty your ~/.cache/fingertip/machines often, at least after each update fingertip cleanup everything # clean ~/.cache/fingertip occasionally""" print(textwrap.dedent(info).lstrip()) sys.exit(1) subcmds = [ list(ws) for x, ws in itertools.groupby(args, lambda w: w != '+') if x ] first_step, *rest_of_the_steps = [parse_subcmd(*sc) for sc in subcmds] first_step_cmd, first_step_args, first_step_kwargs = first_step m = fingertip.build(first_step_cmd, *first_step_args, **first_step_kwargs, fingertip_last_step=(not rest_of_the_steps)) for i, (step_cmd, step_args, step_kwargs) in enumerate(rest_of_the_steps): last_step = i == len(rest_of_the_steps) - 1 m = m.apply(step_cmd, *step_args, **step_kwargs, fingertip_last_step=last_step) if m: success_log = m fingertip.util.log.plain() DEBUG = os.getenv('FINGERTIP_DEBUG') == '1' msg = (f'For more details, check {success_log} ' 'or set FINGERTIP_DEBUG=1.' if not DEBUG else f'Logfile: {success_log}') fingertip.util.log.info(f'Success. {msg}') else: msg = f'Success, no log. Rerun with FINGERTIP_DEBUG=1 for more info.'
def main(m=None): m = m or fingertip.build('backend.qemu', ram_size='128M') if hasattr(m, 'qemu'): m = m.apply(install_in_qemu).apply(first_boot) elif hasattr(m, 'container'): # podman-criu: https://github.com/checkpoint-restore/criu/issues/596 m = m.apply(m.container.from_image, 'alpine') else: raise NotImplementedError() with m: def prepare(): m('apk add python3') m.hooks.ansible_prepare.append(prepare) #m.hooks.ansible_prepare.append(lambda: m('apk add python3')) return m
def main(): fingertip.util.log.nicer() args = sys.argv[1:] subcmds = [ list(ws) for x, ws in itertools.groupby(args, lambda w: w != '+') if x ] first_step, *rest_of_the_steps = [parse_subcmd(*sc) for sc in subcmds] first_step_cmd, first_step_args, first_step_kwargs = first_step m = fingertip.build(first_step_cmd, *first_step_args, **first_step_kwargs) for step_cmd, step_args, step_kwargs in rest_of_the_steps: m = m.apply(step_cmd, *step_args, **step_kwargs) fingertip.util.log.plain()
def main(): # Start with plain to get output from setup wizard fingertip.util.log.plain() if (sys.argv[1:] not in (['cleanup', 'periodic'], ['filesystem', 'cleanup'])): fingertip.util.reflink.storage_setup_wizard() fingertip.util.cleanup_job.schedule() fingertip.util.log.nicer() args = sys.argv[1:] if not args: fingertip.util.log.error('no plugin specified') sys.exit(1) subcmds = [ list(ws) for x, ws in itertools.groupby(args, lambda w: w != '+') if x ] first_step, *rest_of_the_steps = [parse_subcmd(*sc) for sc in subcmds] first_step_cmd, first_step_args, first_step_kwargs = first_step m = fingertip.build(first_step_cmd, *first_step_args, **first_step_kwargs, fingertip_last_step=(not rest_of_the_steps)) for i, (step_cmd, step_args, step_kwargs) in enumerate(rest_of_the_steps): last_step = i == len(rest_of_the_steps) - 1 m = m.apply(step_cmd, *step_args, **step_kwargs, fingertip_last_step=last_step) if m: success_log = m fingertip.util.log.plain() DEBUG = os.getenv('FINGERTIP_DEBUG') == '1' msg = (f'For more details, check {success_log} ' 'or set FINGERTIP_DEBUG=1.' if not DEBUG else f'Logfile: {success_log}') fingertip.util.log.info(f'Success. {msg}') else: msg = f'Success, no log. Rerun with FINGERTIP_DEBUG=1 for more info.'
#!/usr/bin/python3 import fingertip BASES = dict( podman_centos=lambda: fingertip.build('backend.podman-criu', 'centos'), podman_fedora=lambda: fingertip.build('backend.podman-criu', 'fedora'), podman_fedorO=lambda: (fingertip.build('backend.podman-criu').apply('os.fedora', updates=False)), podman_alpine=lambda: (fingertip.build('backend.podman-criu').apply('os.alpine')), podman_ubuntu=lambda: (fingertip.build('backend.podman-criu', 'ubuntu').apply( 'exec', 'apt update && apt install -y python')), qemu_alpine=lambda: (fingertip.build('os.alpine').apply('unseal').apply( '.hooks.disable_cache')), qemu_fedora=lambda: fingertip.build('os.fedora'), qemu_fedorO=lambda: fingertip.build('os.fedora', updates=False), ) TESTS = dict( xtrue=lambda m: m.apply('exec', 'true'), again=lambda m: m.apply('exec', 'true'), nsave=lambda m: m.apply('exec', 'true', transient=True), xtend=lambda m: m.apply('exec', 'true').apply('exec', 'true'), false=lambda m: m.apply('exec', 'false', no_check=True), uname=lambda m: m.apply('ansible', 'command', 'uname -a'), patch=lambda m: m.apply( 'ansible', 'package', name='patch', state='present'), execs=lambda m: m.apply('self_test.exec'), greet=lambda m: m.apply('self_test.greeting'), prmpt=lambda m: m.apply('self_test.prompts'),
#!/usr/bin/python3 import fingertip DEBIAN = ('http://cdimage.debian.org/cdimage/openstack/10.5.1-20200830/' 'debian-10.5.1-20200830-openstack-amd64.qcow2') BASES = dict( podman_centos=lambda: fingertip.build('backend.podman-criu', 'centos'), podman_alpine=lambda: (fingertip.build('backend.podman-criu').apply('os.alpine')), podman_ubuntu=lambda: (fingertip.build('backend.podman-criu', 'ubuntu').apply( 'exec', 'apt update && apt install -y python')), qemu_alpine=lambda: (fingertip.build('os.alpine').apply('unseal').apply( '.hooks.disable_cache')), qemu_fedora=lambda: fingertip.build('os.fedora'), qemu_debian=lambda: (fingertip.build('backend.qemu', ram_min='512M').apply( 'os.cloud-init', url=DEBIAN)), ) TESTS = dict( xtrue=lambda m: m.apply('exec', 'true'), again=lambda m: m.apply('exec', 'true'), nsave=lambda m: m.apply('exec', 'true', transient=True), xtend=lambda m: m.apply('exec', 'true').apply('exec', 'true'), false=lambda m: m.apply('exec', 'false', check=False), uname=lambda m: m.apply('ansible', 'command', 'uname -a'), patch=lambda m: m.apply( 'ansible', 'package', name='patch', state='present'), execs=lambda m: m.apply('self_test.exec'), greet=lambda m: m.apply('self_test.greeting'),
def main(m=None, url=None): m = m or fingertip.build('backend.qemu') assert url assert hasattr(m, 'qemu') # because we have no idea how to unseal it later m.sealed = False m.expiration.cap('4h') image_file = os.path.join(m.path, os.path.basename(url)) if '://' in url: m.log.info(f'fetching {url}...') m.http_cache.fetch(url, image_file) else: m.log.info(f'copying {url}...') reflink.auto(url, image_file) m.expiration.depend_on_a_file(url) m.log.info('resizing image...') run = m.log.pipe_powered(subprocess.run, stdout=logging.INFO, stderr=logging.ERROR) run(['qemu-img', 'resize', image_file, m.qemu.disk_size], check=True) m.qemu._image_to_clone = image_file m.qemu.virtio_scsi = True # in case it's Linux <5 with m: hostname = url.rsplit('/', 1)[-1].rsplit('.', 1)[0].replace('.', '_') hostname = hostname.replace('x86_64', '') fqdn = hostname + '.fingertip.local' meta_data = META_TEMPLATE.format(FQDN=fqdn, HOSTNAME=hostname, SSH_PUBKEY=m.ssh.pubkey) meta_file = os.path.join(m.path, 'meta-data') with open(meta_file, 'w') as f: f.write(meta_data) m.http_cache.serve_local_file('/cloud-init/meta-data', meta_file) user_data = USER_TEMPLATE.format(FQDN=fqdn, HOSTNAME=hostname, SSH_PUBKEY=m.ssh.pubkey) user_file = os.path.join(m.path, 'user-data') with open(user_file, 'w') as f: f.write(user_data) m.http_cache.serve_local_file('/cloud-init/user-data', user_file) init_url = m.http_cache.internal_url + '/cloud-init/' seed = ['-smbios', f'type=1,serial=ds=nocloud-net;s={init_url}'] m.qemu.run(load=None, extra_args=seed) m.console.expect_exact('cloud-config final message') m.console.sendline('') m.console.sendline('') m.console.expect(f'login:'******'root') m.console.expect('Password: '******'fingertip') m.console.sendline(' echo prompt" "detection\n') m.console.expect_exact('prompt detection') m.prompt = re.search(r'\n(.+?) echo prompt', m.console.before).group(1) m.log.debug(f'm.prompt = {repr(m.prompt)}') m.console.sendline('') m.console.expect_exact(m.prompt) m.ram.safeguard = '512M' # sane for 2020, and it's overrideable anyway def login(username='******', password='******'): m.console.expect(f'login: '******'Password: '******'hwclock -s')) m.log.info('cloud-init finished') return m