Example #1
0
def enable_cron_service(ask):
    for service in ('cron', 'cronie'):
        if not subprocess.call('systemctl list-unit-files {0}.service | '
                               'fgrep -q -s {0}.service'.format(service),
                               shell=True):
            cron_service = service
            break
    else:
        sys.stderr.write(
            'Warning: Could not determine name of cron service. Cron may not\n'
            '         be running, so PenguinDome crontab may not run.\n')
        return

    for check, action in (('enabled', 'enable'), ('active', 'start')):
        good = not subprocess.call(
            ('systemctl', '--quiet', 'is-{}'.format(check), cron_service))

        if good:
            continue

        if ask:
            prompt = 'Do you want to {} the {} service?'.format(
                action, cron_service)
            doit = get_bool(prompt, True)
            if not doit:
                return

        subprocess.check_call(('systemctl', action, cron_service))
Example #2
0
def main():
    os.chdir(top_dir)

    parser = argparse.ArgumentParser(
        description='Finalize installation of the PenguinDome client.', )
    parser.add_argument('--prefix',
                        metavar='PATH',
                        default='/',
                        help='The install prefix.')
    parser.add_argument(
        '-y',
        '--no-prompt',
        action='store_false',
        dest='prompt',
        help='Do not prompt the user before installing or replacing the '
        'crontab')

    args = parser.parse_args()

    cron_file = os.path.join(args.prefix, 'etc/cron.d/penguindome')
    cron_exists = os.path.exists(cron_file)

    if args.prompt:
        if cron_exists:
            prompt = 'Do you want to replace the crontab?'
        else:
            prompt = 'Do you want to install the crontab?'

        do_crontab = get_bool(prompt, not cron_exists)
    else:
        do_crontab = True

    if do_crontab:
        with NamedTemporaryFile('w+') as temp_cron_file:
            temp_cron_file.write(
                dedent('''\
                SHELL=/bin/bash
                * * * * * root {}/bin/client-cron &>/dev/null
            '''.format(top_dir)))
            temp_cron_file.flush()
            os.chmod(temp_cron_file.name, 0o644)

            # ensure the etc/cron.d directory exists
            os.makedirs(os.path.dirname(cron_file), exist_ok=True)
            shutil.copy(temp_cron_file.name, cron_file)

        print('Installed {}'.format(cron_file))

        cron_exists = True

    if cron_exists:
        enable_cron_service(args.prompt)

    print('Done!')
Example #3
0
def main(args):
    if args.yes:
        maybe_changed = partial(maybe_changed_extended, use_default=True)
    else:
        maybe_changed = maybe_changed_extended

    generate_key('server', gpg_user_ids['server'])
    generate_key('client', gpg_user_ids['client'])
    import_key('server', gpg_user_ids['client'])
    import_key('client', gpg_user_ids['server'])

    default = not (get_client_setting('loaded')
                   and get_server_setting('loaded'))

    do_config = default if args.yes else \
        get_bool('Do you want to configure things interactively?', default)

    server_changed = client_changed = False

    if do_config:
        if isinstance(get_server_setting('port'), int):
            # Otherwise, the settings file has been edited to make the port
            # either a list of ports or a mapping, and we don't want to try to
            # configure it here.
            server_changed |= maybe_changed(
                'server', 'port', get_int,
                'What port should the server listen on?')

        server_changed |= maybe_changed(
            'server', 'local_port', get_int,
            'What local-only port should the server use?')

        configure_ssl = True
        port = get_server_setting('port')
        if isinstance(port, dict):
            for port_number, port_settings in port.items():
                if 'ssl' in port_settings:
                    # If there are already port-specific SSL settings, then
                    # don't try to configure SSL in this script.
                    configure_ssl = False
        if configure_ssl:
            default = bool(
                get_server_setting('ssl:certificate', None)
                or get_server_setting('ssl:key', None))
            configure_ssl = maybe_get_bool(
                'Do you want the server to use SSL?', default, args.yes)
        if not configure_ssl:
            if get_server_setting('ssl:certificate', None):
                set_server_setting('ssl:certificate', None)
                server_changed = True
            if get_server_setting('ssl:key', None):
                set_server_setting('ssl:key', None)
                server_changed = True
        else:
            while True:
                server_changed |= maybe_changed('server', 'ssl:certificate',
                                                get_string,
                                                'SSL certificate file path:')
                if os.path.exists(get_server_setting('ssl:certificate')):
                    break
                print('That file does not exist.')

            while True:
                server_changed |= maybe_changed('server', 'ssl:key',
                                                get_string,
                                                'SSL key file path:')
                if os.path.exists(get_server_setting('ssl:key')):
                    break
                print('That file does not exist.')

        server_changed |= maybe_changed('server', 'database:host',
                                        get_string_or_list,
                                        'Database host:port:')
        if get_server_setting('database:host'):
            server_changed |= maybe_changed('server',
                                            'database:replicaset',
                                            get_string_none,
                                            'Replicaset name:',
                                            empty_ok=True)
        server_changed |= maybe_changed('server', 'database:name', get_string,
                                        'Database name:')
        server_changed |= maybe_changed('server',
                                        'database:username',
                                        get_string_none,
                                        'Database username:'******'database:username'):
            server_changed |= maybe_changed('server', 'database:password',
                                            get_string, 'Database password:'******'Server', maybe_changed)
        server_changed |= maybe_changed(
            'server', 'audit_cron:enabled', get_bool,
            'Do you want to enable the audit cron job?')

        if get_server_setting('audit_cron:enabled'):
            server_changed |= maybe_changed(
                'server', 'audit_cron:email', get_string,
                'What email address should get the audit output?')

        port = get_server_setting('port')
        if port == 443:
            sample_url = 'https://hostname'
        elif port == 80:
            sample_url = 'http://hostname'
        else:
            sample_url = 'http://hostname:{}'.format(port)
        prompt = 'URL base, e.g., {}, for clients to reach server:'.format(
            sample_url)

        client_changed |= maybe_changed('client', 'server_url', get_string,
                                        prompt)

        client_changed |= maybe_changed('client',
                                        'geolocation_api_key',
                                        get_string,
                                        'Google geolocation API key, if any:',
                                        empty_ok=True)
        prompter = partial(get_int, minimum=1)
        client_changed |= maybe_changed(
            'client', 'schedule:collect_interval', prompter,
            'How often (minutes) do you want to collect data?')
        client_changed |= maybe_changed(
            'client', 'schedule:submit_interval', prompter,
            'How often (minutes) do you want re-try submits?')

        client_changed |= configure_logging('Client', maybe_changed)

        save_server_settings()
        if server_changed:
            print('Saved server settings.')

        save_client_settings()
        if client_changed:
            print('Saved client settings.')

    service_file = '/etc/systemd/system/penguindome-server.service'
    service_exists = os.path.exists(service_file)
    default = not service_exists

    if service_exists:
        prompt = ("Do you want to replace the server's systemd "
                  "configuration?")
    else:
        prompt = 'Do you want to add the server to systemd?'

    do_service = maybe_get_bool(prompt, default, args.yes)

    if do_service and not args.skipsystemctl:
        with NamedTemporaryFile('w+') as temp_service_file:
            temp_service_file.write(
                dedent('''\
                [Unit]
                Description=PenguinDome Server
                After=network.target

                [Service]
                Type=simple
                ExecStart={server_exe}

                [Install]
                WantedBy=multi-user.target
            '''.format(server_exe=os.path.join(top_dir, 'bin', 'server'))))
            temp_service_file.flush()
            os.chmod(temp_service_file.name, 0o644)
            shutil.copy(temp_service_file.name, service_file)
        subprocess.check_output(('systemctl', 'daemon-reload'),
                                stderr=subprocess.STDOUT)
        service_exists = True

    if service_exists and not args.skipsystemctl:
        try:
            subprocess.check_output(
                ('systemctl', 'is-enabled', 'penguindome-server'),
                stderr=subprocess.STDOUT)
        except Exception:
            if maybe_get_bool('Do you want to enable the server?', True,
                              args.yes):
                subprocess.check_output(
                    ('systemctl', 'enable', 'penguindome-server'),
                    stderr=subprocess.STDOUT)
                is_enabled = True
            else:
                is_enabled = False
        else:
            is_enabled = True

        if is_enabled:
            try:
                subprocess.check_output(
                    ('systemctl', 'status', 'penguindome-server'),
                    stderr=subprocess.STDOUT)
            except Exception:
                if maybe_get_bool('Do you want to start the server?', True,
                                  args.yes):
                    subprocess.check_output(
                        ('systemctl', 'start', 'penguindome-server'),
                        stderr=subprocess.STDOUT)
            else:
                if maybe_get_bool('Do you want to restart the server?',
                                  server_changed, args.yes):
                    subprocess.check_output(
                        ('systemctl', 'restart', 'penguindome-server'),
                        stderr=subprocess.STDOUT)

        if get_server_setting('audit_cron:enabled'):
            cron_file = '/etc/cron.d/penguindome-audit'
            cron_exists = os.path.exists(cron_file)

            if cron_exists:
                prompt = 'Do you want to replace the audit crontab?'
            else:
                prompt = 'Do you want to install the audit crontab?'

            do_crontab = maybe_get_bool(prompt, args.audit_crontab
                                        or not cron_exists, args.audit_crontab
                                        or args.yes)

            if do_crontab:
                email = get_server_setting('audit_cron:email')
                minute = int(random.random() * 60)
                minute2 = (minute + 1) % 60

                crontab = dedent('''\
                    MAILTO={email}
                    {minute2} * * * * root "{top_dir}/bin/issues" audit --cron
                '''.format(minute2=minute2, email=email, top_dir=top_dir))

                with NamedTemporaryFile('w+') as temp_cron_file:
                    temp_cron_file.write(crontab)
                    temp_cron_file.flush()
                    os.chmod(temp_cron_file.name, 0o644)
                    shutil.copy(temp_cron_file.name, cron_file)

                print('Installed {}'.format(cron_file))

    if (client_changed
            or not glob.glob(os.path.join(releases_dir, '*.tar.asc'))
            and not args.skipbuildrelease):
        if client_changed:
            prompt = ('Do you want to build a release with the new client '
                      'settings?')
        else:
            prompt = 'Do you want to build a client release?'

        if maybe_get_bool(prompt, True, args.yes):
            # Sometimes sign fails the first time because of GnuPG weirdness.
            # The client_release script will call sign as well, but we call it
            # first just in case it fails the first time.
            try:
                subprocess.check_output((os.path.join('bin', 'sign'), ),
                                        stderr=subprocess.STDOUT)
            except Exception:
                pass
            subprocess.check_output((os.path.join('bin', 'client_release'), ),
                                    stderr=subprocess.STDOUT)

    print('Done!')
Example #4
0
def maybe_get_bool(prompt, default, use_default=False):
    if use_default:
        answer = 'yes' if default else 'no'
        print('{} {}'.format(prompt, answer))
        return default
    return get_bool(prompt, default)
Example #5
0
    dest='prompt',
    help='Do not prompt the user before installing or replacing the crontab',
)

args = parser.parse_args()

cron_file = os.path.join(args.prefix, 'etc/cron.d/penguindome')
cron_exists = os.path.exists(cron_file)

if args.prompt:
    if cron_exists:
        prompt = 'Do you want to replace the crontab?'
    else:
        prompt = 'Do you want to install the crontab?'

    do_crontab = get_bool(prompt, not cron_exists)
else:
    do_crontab = True

if do_crontab:
    with NamedTemporaryFile('w+') as temp_cron_file:
        temp_cron_file.write(
            dedent('''\
            SHELL=/bin/bash
            * * * * * root {}/bin/client-cron &>/dev/null
        '''.format(top_dir)))
        temp_cron_file.flush()
        os.chmod(temp_cron_file.name, 0o644)

        # ensure the etc/cron.d directory exists
        os.makedirs(os.path.dirname(cron_file), exist_ok=True)