From 17f81e82963c36cc1c2d81605b827e298b846663 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Mon, 27 Nov 2023 12:43:11 -0500 Subject: [PATCH] Refactor pvcapid to use new configuration --- api-daemon/pvcapid.service | 2 +- api-daemon/pvcapid/Daemon.py | 188 +++++++++++++++++++++++++--------- api-daemon/pvcworkerd.service | 2 +- pvc.sample.conf | 12 ++- 4 files changed, 150 insertions(+), 54 deletions(-) diff --git a/api-daemon/pvcapid.service b/api-daemon/pvcapid.service index 34a6a80e..9446cae7 100644 --- a/api-daemon/pvcapid.service +++ b/api-daemon/pvcapid.service @@ -8,7 +8,7 @@ After = network-online.target Type = simple WorkingDirectory = /usr/share/pvc Environment = PYTHONUNBUFFERED=true -Environment = PVC_CONFIG_FILE=/etc/pvc/pvcapid.yaml +Environment = PVC_CONFIG_FILE=/etc/pvc/pvc.conf ExecStart = /usr/share/pvc/pvcapid.py Restart = on-failure diff --git a/api-daemon/pvcapid/Daemon.py b/api-daemon/pvcapid/Daemon.py index f558d02e..e0b681d6 100755 --- a/api-daemon/pvcapid/Daemon.py +++ b/api-daemon/pvcapid/Daemon.py @@ -54,67 +54,157 @@ def strtobool(stringv): ########################################################## # Parse the configuration file +config_file = None try: - pvcapid_config_file = os.environ["PVC_CONFIG_FILE"] + _config_file = "/etc/pvc/pvcapid.yaml" + if not os.path.exists(_config_file): + raise + config_file = _config_file + config_type = "legacy" except Exception: + pass +try: + _config_file = os.environ["PVC_CONFIG_FILE"] + if not os.path.exists(_config_file): + raise + config_file = _config_file + config_type = "current" +except Exception: + pass + +if not config_file: print( 'Error: The "PVC_CONFIG_FILE" environment variable must be set before starting pvcapid.' ) exit(1) -print('Loading configuration from file "{}"'.format(pvcapid_config_file)) -# Read in the config -try: - with open(pvcapid_config_file, "r") as cfgfile: - o_config = yaml.load(cfgfile, Loader=yaml.BaseLoader) -except Exception as e: - print("ERROR: Failed to parse configuration file: {}".format(e)) - exit(1) +def load_configuration_file(config_file): + print('Loading configuration from file "{}"'.format(config_file)) -try: - # Create the config object - config = { - "debug": strtobool(o_config["pvc"]["debug"]), - "coordinators": o_config["pvc"]["coordinators"], - "listen_address": o_config["pvc"]["api"]["listen_address"], - "listen_port": int(o_config["pvc"]["api"]["listen_port"]), - "auth_enabled": strtobool(o_config["pvc"]["api"]["authentication"]["enabled"]), - "auth_secret_key": o_config["pvc"]["api"]["authentication"]["secret_key"], - "auth_tokens": o_config["pvc"]["api"]["authentication"]["tokens"], - "ssl_enabled": strtobool(o_config["pvc"]["api"]["ssl"]["enabled"]), - "ssl_key_file": o_config["pvc"]["api"]["ssl"]["key_file"], - "ssl_cert_file": o_config["pvc"]["api"]["ssl"]["cert_file"], - "database_host": o_config["pvc"]["provisioner"]["database"]["host"], - "database_port": int(o_config["pvc"]["provisioner"]["database"]["port"]), - "database_name": o_config["pvc"]["provisioner"]["database"]["name"], - "database_user": o_config["pvc"]["provisioner"]["database"]["user"], - "database_password": o_config["pvc"]["provisioner"]["database"]["pass"], - "queue_host": o_config["pvc"]["provisioner"]["queue"]["host"], - "queue_port": o_config["pvc"]["provisioner"]["queue"]["port"], - "queue_path": o_config["pvc"]["provisioner"]["queue"]["path"], - "storage_hosts": o_config["pvc"]["provisioner"]["ceph_cluster"][ - "storage_hosts" - ], - "storage_domain": o_config["pvc"]["provisioner"]["ceph_cluster"][ - "storage_domain" - ], - "ceph_monitor_port": o_config["pvc"]["provisioner"]["ceph_cluster"][ - "ceph_monitor_port" - ], - "ceph_storage_secret_uuid": o_config["pvc"]["provisioner"]["ceph_cluster"][ - "ceph_storage_secret_uuid" - ], - } + # Read in the config + try: + with open(config_file, "r") as cfgfile: + o_config = yaml.load(cfgfile, Loader=yaml.BaseLoader) + except Exception as e: + print("ERROR: Failed to parse configuration file: {}".format(e)) + exit(1) - # Use coordinators as storage hosts if not explicitly specified - if not config["storage_hosts"]: - config["storage_hosts"] = config["coordinators"] + return o_config -except Exception as e: - print("ERROR: Failed to load configuration: {}".format(e)) - exit(1) +def get_configuration_current(config_file): + o_config = load_configuration_file(config_file) + try: + # Create the config object + config = { + "debug": strtobool(o_config["logging"].get("debug_logging", "False")), + "coordinators": o_config["cluster"]["all_coordinators"], + "listen_address": o_config["api"]["listen"]["address"], + "listen_port": int(o_config["api"]["listen"]["port"]), + "auth_enabled": strtobool( + o_config["api"]["authentication"].get("enabled", "False") + ), + "auth_secret_key": o_config["api"]["authentication"]["secret_key"], + "auth_source": o_config["api"]["authentication"]["source"], + "ssl_enabled": strtobool(o_config["api"]["ssl"].get("enabled", "False")), + "ssl_cert_file": o_config["api"]["ssl"]["certificate"], + "ssl_key_file": o_config["api"]["ssl"]["private_key"], + "database_port": o_config["database"]["postgres"]["port"], + "database_host": o_config["database"]["postgres"]["hostname"], + "database_name": o_config["database"]["postgres"]["credentials"]["api"][ + "database" + ], + "database_user": o_config["database"]["postgres"]["credentials"]["api"][ + "username" + ], + "database_password": o_config["database"]["postgres"]["credentials"]["api"][ + "password" + ], + "queue_port": o_config["database"]["keydb"]["port"], + "queue_host": o_config["database"]["keydb"]["hostname"], + "queue_path": o_config["database"]["keydb"]["path"], + "storage_domain": o_config["cluster"]["networks"]["storage"]["domain"], + "storage_hosts": o_config["ceph"].get("monitor_hosts", None), + "ceph_monitor_port": o_config["ceph"]["monitor_port"], + "ceph_storage_secret_uuid": o_config["ceph"]["secret_uuid"], + } + + # Use coordinators as storage hosts if not explicitly specified + if not config["storage_hosts"] or len(config["storage_hosts"]) < 1: + config["storage_hosts"] = config["coordinators"] + + # Set up our token list if specified + if config["auth_source"] == "token": + config["auth_tokens"] = o_config["api"]["token"] + else: + if config["auth_enabled"]: + print( + "WARNING: No authentication method provided; disabling authentication." + ) + config["auth_enabled"] = False + + except Exception as e: + print(f"ERROR: Failed to load configuration: {e}") + exit(1) + + return config + + +def get_configuration_legacy(config_file): + o_config = load_configuration_file(config_file) + try: + # Create the config object + config = { + "debug": strtobool(o_config["pvc"]["debug"]), + "coordinators": o_config["pvc"]["coordinators"], + "listen_address": o_config["pvc"]["api"]["listen_address"], + "listen_port": int(o_config["pvc"]["api"]["listen_port"]), + "auth_enabled": strtobool( + o_config["pvc"]["api"]["authentication"]["enabled"] + ), + "auth_secret_key": o_config["pvc"]["api"]["authentication"]["secret_key"], + "auth_tokens": o_config["pvc"]["api"]["authentication"]["tokens"], + "ssl_enabled": strtobool(o_config["pvc"]["api"]["ssl"]["enabled"]), + "ssl_key_file": o_config["pvc"]["api"]["ssl"]["key_file"], + "ssl_cert_file": o_config["pvc"]["api"]["ssl"]["cert_file"], + "database_host": o_config["pvc"]["provisioner"]["database"]["host"], + "database_port": int(o_config["pvc"]["provisioner"]["database"]["port"]), + "database_name": o_config["pvc"]["provisioner"]["database"]["name"], + "database_user": o_config["pvc"]["provisioner"]["database"]["user"], + "database_password": o_config["pvc"]["provisioner"]["database"]["pass"], + "queue_host": o_config["pvc"]["provisioner"]["queue"]["host"], + "queue_port": o_config["pvc"]["provisioner"]["queue"]["port"], + "queue_path": o_config["pvc"]["provisioner"]["queue"]["path"], + "storage_hosts": o_config["pvc"]["provisioner"]["ceph_cluster"][ + "storage_hosts" + ], + "storage_domain": o_config["pvc"]["provisioner"]["ceph_cluster"][ + "storage_domain" + ], + "ceph_monitor_port": o_config["pvc"]["provisioner"]["ceph_cluster"][ + "ceph_monitor_port" + ], + "ceph_storage_secret_uuid": o_config["pvc"]["provisioner"]["ceph_cluster"][ + "ceph_storage_secret_uuid" + ], + } + + # Use coordinators as storage hosts if not explicitly specified + if not config["storage_hosts"]: + config["storage_hosts"] = config["coordinators"] + + except Exception as e: + print("ERROR: Failed to load configuration: {}".format(e)) + exit(1) + + return config + + +if config_type == "legacy": + config = get_configuration_legacy(config_file) +else: + config = get_configuration_current(config_file) ########################################################## # Entrypoint diff --git a/api-daemon/pvcworkerd.service b/api-daemon/pvcworkerd.service index 655d9fdf..71127e12 100644 --- a/api-daemon/pvcworkerd.service +++ b/api-daemon/pvcworkerd.service @@ -8,7 +8,7 @@ After = network-online.target Type = simple WorkingDirectory = /usr/share/pvc Environment = PYTHONUNBUFFERED=true -Environment = PVC_CONFIG_FILE=/etc/pvc/pvcapid.yaml +Environment = PVC_CONFIG_FILE=/etc/pvc/pvc.conf ExecStart = /usr/share/pvc/pvcworkerd.sh Restart = on-failure diff --git a/pvc.sample.conf b/pvc.sample.conf index 75488a4e..525186b6 100644 --- a/pvc.sample.conf +++ b/pvc.sample.conf @@ -317,15 +317,18 @@ ceph: # Monitor port, usually 6789 monitor_port: 6789 + # Monitor host(s), enable only you want to use hosts other than the coordinators + #monitor_hosts: + # - pvchv1 + # - pvchv2 + # - pvchv3 + # Storage secret UUID, generated during Ansible cluster bootstrap secret_uuid: "" # API configuration api: - # Secret key for API cookies (long and secure password or UUID) - secret_key: "1234567890abcdefghijklmnopqrstuvwxyz" - # API listening configuration listen: @@ -341,6 +344,9 @@ api: # Enable or disable authentication enabled: yes + # Secret key for API cookies (long and secure password or UUID) + secret_key: "1234567890abcdefghijklmnopqrstuvwxyz" + # Authentication source (token, others in future) source: token