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))
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!')
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!')
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)
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)