Example #1
0
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()
Example #2
0
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.'
Example #3
0
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
Example #4
0
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()
Example #5
0
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.'
Example #6
0
#!/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'),
Example #7
0
#!/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'),
Example #8
0
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