-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor: decompose draksetup commands into separate files and remove…
… postupgrade command (#925) * Refactor: decompose draksetup commands into separate files * Oops... forgotten __init__.py * Fix paths * Ok, let's have a single point where package dir is evaluated * Ok, fixing that one place
- Loading branch information
Showing
22 changed files
with
1,811 additions
and
1,696 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .main import main | ||
|
||
__all__ = ["main"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .main import main | ||
|
||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import logging | ||
import os | ||
|
||
import click | ||
|
||
from drakrun.lib.install_info import InstallInfo | ||
from drakrun.lib.networking import ( | ||
delete_all_vm_networks, | ||
delete_legacy_iptables, | ||
delete_vm_network, | ||
stop_dnsmasq, | ||
) | ||
from drakrun.lib.paths import VOLUME_DIR | ||
from drakrun.lib.storage import get_storage_backend | ||
from drakrun.lib.util import safe_delete | ||
from drakrun.lib.vm import VirtualMachine, delete_vm_conf, get_all_vm_conf | ||
|
||
from .util.profile_builder import cleanup_profile_files | ||
from .util.systemd import stop_all_drakruns | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
@click.command(help="Cleanup the changes made by draksetup") | ||
def cleanup(): | ||
install_info = InstallInfo.try_load() | ||
|
||
if install_info is None: | ||
log.error("The cleanup has been performed") | ||
return | ||
|
||
stop_all_drakruns() | ||
|
||
backend = get_storage_backend(install_info) | ||
vm_ids = get_all_vm_conf() | ||
|
||
for vm_id in vm_ids: | ||
vm = VirtualMachine(backend, vm_id) | ||
vm.destroy() | ||
|
||
delete_vm_network(vm_id=vm_id) | ||
stop_dnsmasq(vm_id=vm_id) | ||
backend.delete_vm_volume(vm_id) | ||
delete_vm_conf(vm_id) | ||
|
||
delete_legacy_iptables() | ||
delete_all_vm_networks() | ||
|
||
safe_delete(os.path.join(VOLUME_DIR, "snapshot.sav")) | ||
cleanup_profile_files() | ||
|
||
InstallInfo.delete() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import click | ||
|
||
from drakrun.lib.networking import delete_all_vm_networks, delete_legacy_iptables | ||
|
||
|
||
@click.command(help="Cleanup changes in iptables and bridges") | ||
def cleanup_network(): | ||
delete_legacy_iptables() | ||
delete_all_vm_networks() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
import configparser | ||
import logging | ||
import sysconfig | ||
from pathlib import Path | ||
from typing import List, Optional | ||
|
||
import click | ||
|
||
from drakrun.lib.bindings.systemd import ( | ||
enable_service, | ||
start_service, | ||
systemctl_daemon_reload, | ||
) | ||
from drakrun.lib.config import DrakrunConfig, load_config, update_config | ||
from drakrun.lib.minio import get_minio_client | ||
from drakrun.lib.paths import ETC_DIR, PACKAGE_DIR | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
MINIO_ENV_CONFIG_FILE = Path("/etc/default/minio") | ||
SYSTEMD_SERVICE_PATH = Path("/etc/systemd/system") | ||
|
||
|
||
def apply_local_minio_service_config(config: DrakrunConfig): | ||
parser = configparser.ConfigParser(strict=False, allow_no_value=True) | ||
minio_env = "[DEFAULT]\n" + MINIO_ENV_CONFIG_FILE.read_text() | ||
parser.read_string(minio_env) | ||
config.minio.access_key = parser.get("DEFAULT", "MINIO_ROOT_USER") | ||
config.minio.secret_key = parser.get("DEFAULT", "MINIO_ROOT_PASSWORD") | ||
return config | ||
|
||
|
||
@click.command(help="Pre-installation activities") | ||
@click.option("--s3-address", default=None, help="S3 endpoint address") | ||
@click.option("--s3-access-key", default=None, help="S3 access key") | ||
@click.option("--s3-secret-key", default=None, help="S3 secret key") | ||
@click.option( | ||
"--s3-secure", default=False, is_flag=True, help="S3 enable secure connection" | ||
) | ||
@click.option( | ||
"--s3-make-buckets", | ||
default=True, | ||
is_flag=True, | ||
help="Auto-create S3 buckets: karton, drakrun", | ||
) | ||
@click.option("--redis-host", default=None, help="Redis host") | ||
@click.option("--redis-port", default=None, help="Redis port") | ||
@click.option( | ||
"--only", | ||
type=click.Choice(["web", "system", "drakrun"]), | ||
multiple=True, | ||
help="Create configuration only for specific service for multi-node configuration", | ||
) | ||
@click.option( | ||
"--unattended", | ||
default=False, | ||
is_flag=True, | ||
help="Don't prompt for values, expect required parameters in arguments", | ||
) | ||
def init( | ||
s3_address: Optional[str], | ||
s3_access_key: Optional[str], | ||
s3_secret_key: Optional[str], | ||
s3_secure: bool, | ||
s3_make_buckets: bool, | ||
redis_host: Optional[str], | ||
redis_port: Optional[str], | ||
only: List[str], | ||
unattended: bool, | ||
): | ||
# Simple activities handled by deb packages before | ||
# In the future, consider splitting this to remove hard dependency on systemd etc | ||
drakrun_dir = Path(ETC_DIR) | ||
scripts_dir = drakrun_dir / "scripts" | ||
data_dir = PACKAGE_DIR / "data" | ||
|
||
drakrun_dir.mkdir(exist_ok=True) | ||
scripts_dir.mkdir(exist_ok=True) | ||
|
||
def create_configuration_file(config_file_name, target_dir=drakrun_dir): | ||
target_path = target_dir / config_file_name | ||
if target_path.exists(): | ||
log.info(f"{target_path} already created.") | ||
return target_path | ||
|
||
config_data = (data_dir / config_file_name).read_text() | ||
target_path.write_text(config_data) | ||
log.info(f"Created {target_path}.") | ||
return target_path | ||
|
||
drakrun_config_path = create_configuration_file("config.ini") | ||
|
||
try: | ||
config = load_config() | ||
except Exception: | ||
import traceback | ||
|
||
traceback.print_exc() | ||
click.echo( | ||
"Failed to load currently installed configuration. " | ||
f"Fix {drakrun_config_path.as_posix()} or remove file to reconfigure it " | ||
f"from scratch and run 'draksetup init' again.", | ||
err=True, | ||
) | ||
raise click.Abort() | ||
|
||
def apply_setting(message, current_value, option_value, hide_input=False): | ||
if option_value is not None: | ||
# If option value is already provided: just return option_value | ||
return option_value | ||
if unattended: | ||
# If unattended and no option value: just leave current value | ||
return current_value | ||
default_value = current_value or None | ||
input_value = click.prompt( | ||
message, default=default_value, hide_input=hide_input | ||
) | ||
if input_value is None: | ||
# If input not provided and no reasonable default found: leave current value | ||
return current_value | ||
else: | ||
# Else: provide input value | ||
return input_value | ||
|
||
config.redis.host = apply_setting( | ||
"Provide redis hostname", config.redis.host, redis_host | ||
) | ||
config.redis.port = apply_setting( | ||
"Provide redis port", config.redis.port, redis_port | ||
) | ||
config.minio.address = apply_setting( | ||
"Provide S3 (MinIO) address", config.minio.address, s3_address | ||
) | ||
|
||
minio_env_applied = False | ||
if MINIO_ENV_CONFIG_FILE.exists(): | ||
log.info( | ||
f"Found {MINIO_ENV_CONFIG_FILE.as_posix()} file with MinIO credentials" | ||
) | ||
if unattended or click.confirm( | ||
f"Do you want to import credentials from {MINIO_ENV_CONFIG_FILE.as_posix()} file?", | ||
default=True, | ||
): | ||
apply_local_minio_service_config(config) | ||
minio_env_applied = True | ||
|
||
if not minio_env_applied: | ||
config.minio.access_key = apply_setting( | ||
"Provide S3 (MinIO) access key", config.minio.access_key, s3_access_key | ||
) | ||
config.minio.secret_key = apply_setting( | ||
"Provide S3 (MinIO) secret key", config.minio.secret_key, s3_secret_key | ||
) | ||
|
||
config.minio.secure = s3_secure | ||
update_config(config) | ||
log.info(f"Updated {drakrun_config_path.as_posix()}.") | ||
|
||
mc = get_minio_client(config) | ||
|
||
def check_s3_bucket(bucket_name): | ||
if not mc.bucket_exists(bucket_name): | ||
if s3_make_buckets: | ||
log.info(f"Bucket '{bucket_name}' doesn't exist, creating one...") | ||
mc.make_bucket(bucket_name) | ||
else: | ||
click.echo( | ||
f"Bucket '{bucket_name}' doesn't exist. " | ||
"Create proper S3 buckets to continue.", | ||
err=True, | ||
) | ||
raise click.Abort() | ||
|
||
check_s3_bucket("drakrun") | ||
check_s3_bucket(config.minio.bucket) | ||
|
||
def is_component_to_init(component_name): | ||
return not only or component_name in only | ||
|
||
def get_scripts_bin_path(): | ||
scripts_path = Path(sysconfig.get_path("scripts")) | ||
if scripts_path == Path("/usr/bin"): | ||
# pip installs global scripts in different path than | ||
# pointed by sysconfig | ||
return Path("/usr/local/bin") | ||
return scripts_path | ||
|
||
def fix_exec_start(config_file_name): | ||
""" | ||
This function fixes ExecStart entry to point at correct virtualenv bin directory | ||
ExecStart=/usr/local/bin/karton-system --config-file /etc/drakrun/config.ini | ||
""" | ||
systemd_config_path = SYSTEMD_SERVICE_PATH / config_file_name | ||
systemd_config = systemd_config_path.read_text() | ||
current_exec_start = next( | ||
line | ||
for line in systemd_config.splitlines() | ||
if line.startswith("ExecStart=") | ||
) | ||
current_exec_path_str = current_exec_start.split("=")[1].split()[0] | ||
current_exec_path = Path(current_exec_path_str) | ||
new_exec_path = get_scripts_bin_path() / current_exec_path.name | ||
if current_exec_path != new_exec_path: | ||
systemd_config = systemd_config.replace( | ||
current_exec_path_str, new_exec_path.as_posix() | ||
) | ||
systemd_config_path.write_text(systemd_config) | ||
log.info( | ||
f"{systemd_config_path}: Replaced {current_exec_path} with {new_exec_path}" | ||
) | ||
return systemd_config_path | ||
|
||
if is_component_to_init("drakrun"): | ||
create_configuration_file("hooks.txt") | ||
create_configuration_file("[email protected]", target_dir=SYSTEMD_SERVICE_PATH) | ||
fix_exec_start("[email protected]") | ||
create_configuration_file("cfg.template", target_dir=(drakrun_dir / "scripts")) | ||
|
||
if is_component_to_init("system"): | ||
create_configuration_file( | ||
"drak-system.service", target_dir=SYSTEMD_SERVICE_PATH | ||
) | ||
fix_exec_start("drak-system.service") | ||
|
||
if is_component_to_init("web"): | ||
create_configuration_file("uwsgi.ini") | ||
create_configuration_file("drak-web.service", target_dir=SYSTEMD_SERVICE_PATH) | ||
fix_exec_start("drak-web.service") | ||
|
||
systemctl_daemon_reload() | ||
|
||
# drakrun is going to be enabled after complete install/postinstall setup | ||
if is_component_to_init("system"): | ||
log.info("Starting drak-system service") | ||
enable_service("drak-system") | ||
start_service("drak-system") | ||
if is_component_to_init("web"): | ||
log.info("Starting drak-web service") | ||
enable_service("drak-web") | ||
start_service("drak-web") |
Oops, something went wrong.