From 0a88d844c95c8eccf5dd7ec162433b2c401e0ebc Mon Sep 17 00:00:00 2001 From: Maharacha Date: Thu, 7 Nov 2024 10:33:00 +0100 Subject: [PATCH] Revisions 30,31 (#85) * add sora to available chains * generate a node-key when installing (#82) * fix hyperbridge deployment * Validate chain spec files on config change (#84) * Validate chain spec files on config-change * Use sora instead of main when setting config service-args (#86) * Use sora instead of main when setting config service-args * Prepare sora for support for more networks * Make sora future proof for other networks --------- Co-authored-by: kaioh33 Co-authored-by: kaioh33 <81778538+gflow33@users.noreply.github.com> Co-authored-by: A Ahmad <57046949+abbaahmad@users.noreply.github.com> --- src/charm.py | 24 +++++++++++++++++------- src/docker.py | 10 ++++++---- src/service_args.py | 12 ++++++++++++ src/utils.py | 23 ++++++++++++++++++----- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/charm.py b/src/charm.py index 77d741d..10216b4 100755 --- a/src/charm.py +++ b/src/charm.py @@ -91,6 +91,7 @@ def _on_install(self, event: ops.InstallEvent) -> None: self.unit.status = ops.MaintenanceStatus("Installing binary") utils.install_binary(self.config, service_args_obj.chain_name) utils.download_wasm_runtime(self.config.get('wasm-runtime-url')) + utils.generate_node_key() # Install polkadot.service file self.unit.status = ops.MaintenanceStatus("Installing service") source_path = Path(self.charm_dir / 'templates/etc/systemd/system/polkadot.service') @@ -127,15 +128,24 @@ def _on_config_changed(self, event: ops.ConfigChangedEvent) -> None: self._stored.service_args = self.config.get('service-args') if self._stored.chain_spec_url != self.config.get('chain-spec-url'): - self.unit.status = ops.MaintenanceStatus("Updating chain spec") - utils.update_service_args(service_args_obj.service_args_string) - self._stored.chain_spec_url = self.config.get('chain-spec-url') + try: + self.unit.status = ops.MaintenanceStatus("Updating chain spec") + utils.update_service_args(service_args_obj.service_args_string) + self._stored.chain_spec_url = self.config.get('chain-spec-url') + except ValueError as e: + self.unit.status = ops.BlockedStatus(str(e)) + event.defer() + return if self._stored.local_relaychain_spec_url != self.config.get('local-relaychain-spec-url'): - self.unit.status = ops.MaintenanceStatus("Updating relaychain spec") - utils.update_service_args(service_args_obj.service_args_string) - self._stored.local_relaychain_spec_url = self.config.get('local-relaychain-spec-url') - + try: + self.unit.status = ops.MaintenanceStatus("Updating relaychain spec") + utils.update_service_args(service_args_obj.service_args_string) + self._stored.local_relaychain_spec_url = self.config.get('local-relaychain-spec-url') + except ValueError as e: + self.unit.status = ops.BlockedStatus(str(e)) + event.defer() + return if self._stored.wasm_runtime_url != self.config.get('wasm-runtime-url'): self.unit.status = ops.MaintenanceStatus("Updating wasm runtime") utils.download_wasm_runtime(self.config.get('wasm-runtime-url')) diff --git a/src/docker.py b/src/docker.py index 7943516..e51074d 100644 --- a/src/docker.py +++ b/src/docker.py @@ -12,9 +12,9 @@ class Docker(): - def __init__(self, chain_name, docker_tag): - self.chain_name = chain_name - self.docker_tag = docker_tag + def __init__(self, chain_name: str, docker_tag: str): + self.chain_name: str = chain_name + self.docker_tag: str = docker_tag def extract_resources_from_docker(self): if self.chain_name in ['spiritnet', 'peregrine', 'peregrine-stg-kilt']: @@ -71,12 +71,14 @@ def extract_resources_from_docker(self): self.__extract_from_docker('opentensor/subtensor', 'usr/local/bin/node-subtensor') elif self.chain_name in ['peaq', 'krest']: self.__extract_from_docker('peaq/parachain', 'usr/local/bin/peaq-node') - elif self.chain_name == 'hyperbridge-nexus': + elif self.chain_name == 'nexus': self.__extract_from_docker('polytopelabs/hyperbridge', './hyperbridge') elif self.chain_name == 'litentry': self.__extract_from_docker('litentry/litentry-parachain', '/usr/local/bin/litentry-collator') elif self.chain_name == 'laos': self.__extract_from_docker('freeverseio/laos-node', '/usr/bin/laos') + elif self.chain_name.startswith('sora'): + self.__extract_from_docker('sora2/substrate', 'usr/local/bin/framenode') else: raise ValueError(f"{self.chain_name} is not a supported chain using Docker!") diff --git a/src/service_args.py b/src/service_args.py index 1f8c0d1..f09d19d 100644 --- a/src/service_args.py +++ b/src/service_args.py @@ -120,6 +120,8 @@ def __customize_service_args(self): self.__aleph_zero() elif self.chain_name in ['crust-mainnet', 'crust-maxwell', 'crust-rocky']: self.__crust() + elif self.chain_name.startswith('sora'): + self.__sora() # The chain spec configs should be applied after hardcoded chain customizations above since this should override any hardcoded --chain overrides. if self._chain_spec_url: @@ -144,3 +146,13 @@ def __crust(self): self.__set_chain_name('maxwell', 0) elif self.chain_name == 'crust-rocky': self.__set_chain_name('rocky', 0) + + def __sora(self): + ''' + Everything after 'sora-' will be used as the chain name. + Examples: + --chain=sora-main -> --chain=main + --chain=sora-another-network -> --chain=another-network + ''' + chain_name = self.chain_name.split('-', 1)[1] + self.__set_chain_name(chain_name, 0) diff --git a/src/utils.py b/src/utils.py index bb9a5de..bfc734e 100644 --- a/src/utils.py +++ b/src/utils.py @@ -11,6 +11,7 @@ import time import logging import re +import json import constants as c from pathlib import Path from ops.model import ConfigData @@ -202,12 +203,17 @@ def download_chain_spec(url: str, filename: Path) -> None: """Download a chain spec file from a given URL to a given filepath.""" if not c.CHAIN_SPEC_DIR.exists(): c.CHAIN_SPEC_DIR.mkdir(parents=True) - try: - download_file(url, Path(c.CHAIN_SPEC_DIR, filename)) - except ValueError as e: - logger.error(f'Failed to download chain spec: {e}') - raise e + download_file(url, Path(c.CHAIN_SPEC_DIR, filename)) + validate_file(Path(c.CHAIN_SPEC_DIR, filename), file_type='json') + +def validate_file(filename: Path, file_type: str): + if file_type == 'json': + try: + file_obj = open(filename, 'r') + _ = json.load(file_obj) + except json.JSONDecodeError as e: + raise ValueError(f"Validating chain spec {filename} failed with error: {e}") def download_wasm_runtime(url): if not url: @@ -353,6 +359,13 @@ def write_node_key_file(key): sp.run(['chmod', '0600', c.NODE_KEY_FILE], check=False) +def generate_node_key(): + command = [c.BINARY_FILE, 'key', 'generate-node-key', '--file', c.NODE_KEY_FILE] + sp.run(command, check=False) + sp.run(['chown', f'{c.USER}:{c.USER}', c.NODE_KEY_FILE], check=False) + sp.run(['chmod', '0600', c.NODE_KEY_FILE], check=False) + + def get_disk_usage(path: Path) -> str: if not path.exists(): return ''