Skip to content

Commit

Permalink
Merge pull request #799 from skalenetwork/beta
Browse files Browse the repository at this point in the history
2.5.x stable
  • Loading branch information
DmytroNazarenko authored Nov 6, 2024
2 parents 45c62fc + 5c2414a commit 9e0c550
Show file tree
Hide file tree
Showing 29 changed files with 756 additions and 465 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- develop
- beta
- stable
- v*.*.*
- 'v*.*.*'

jobs:
create_release:
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,6 @@ Options:

- `--archive` - Run sync node in an archive node (disable block rotation)
- `--historic-state` - Enable historic state (works only in pair with --archive flag)
- `--catchup` - Add a flag to start sync node in catchup mode

#### Sync node update

Expand Down
2 changes: 1 addition & 1 deletion node_cli/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '2.4.1'
__version__ = '2.5.0'

if __name__ == "__main__":
print(__version__)
22 changes: 18 additions & 4 deletions node_cli/cli/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,17 @@ def init_node(env_file):
expose_value=False,
prompt='Are you sure you want to update SKALE node software?')
@click.option('--pull-config', 'pull_config_for_schain', hidden=True, type=str)
@click.option(
'--unsafe',
'unsafe_ok',
help='Allow unsafe update',
hidden=True,
is_flag=True
)
@click.argument('env_file')
@streamed_cmd
def update_node(env_file, pull_config_for_schain):
update(env_file, pull_config_for_schain)
def update_node(env_file, pull_config_for_schain, unsafe_ok):
update(env_file, pull_config_for_schain, unsafe_ok)


@node.command('signature', help='Get node signature for given validator id')
Expand Down Expand Up @@ -173,9 +180,16 @@ def remove_node_from_maintenance():
@click.option('--yes', is_flag=True, callback=abort_if_false,
expose_value=False,
prompt='Are you sure you want to turn off the node?')
@click.option(
'--unsafe',
'unsafe_ok',
help='Allow unsafe turn-off',
hidden=True,
is_flag=True
)
@streamed_cmd
def _turn_off(maintenance_on):
turn_off(maintenance_on)
def _turn_off(maintenance_on, unsafe_ok):
turn_off(maintenance_on, unsafe_ok)


@node.command('turn-on', help='Turn on the node')
Expand Down
4 changes: 2 additions & 2 deletions node_cli/cli/schains.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import click

from node_cli.utils.helper import abort_if_false, IP_TYPE
from node_cli.utils.helper import abort_if_false, URL_TYPE
from node_cli.core.schains import (
describe,
get_schain_firewall_rules,
Expand Down Expand Up @@ -87,7 +87,7 @@ def show_rules(schain_name: str) -> None:
prompt='Are you sure? Repair mode may corrupt working SKALE chain data.')
@click.option(
'--snapshot-from',
type=IP_TYPE,
type=URL_TYPE,
default=None,
hidden=True,
help='Ip of the node from to download snapshot from'
Expand Down
66 changes: 56 additions & 10 deletions node_cli/cli/sync_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from typing import Optional

import click

from node_cli.core.node import init_sync, update_sync
from node_cli.core.node import init_sync, update_sync, repair_sync
from node_cli.utils.helper import (
abort_if_false,
error_exit,
safe_load_texts,
streamed_cmd,
error_exit
URL_TYPE
)
from node_cli.utils.exit_codes import CLIExitCodes

Expand All @@ -50,31 +53,74 @@ def sync_node():
help=TEXTS['init']['archive'],
is_flag=True
)
@click.option(
'--catchup',
help=TEXTS['init']['catchup'],
is_flag=True
)
@click.option(
'--historic-state',
help=TEXTS['init']['historic_state'],
is_flag=True
)
@click.option(
'--snapshot-from',
type=URL_TYPE,
default=None,
hidden=True,
help='Ip of the node from to download snapshot from'
)
@streamed_cmd
def _init_sync(env_file, archive, catchup, historic_state):
def _init_sync(env_file, archive, historic_state, snapshot_from: Optional[str]):
if historic_state and not archive:
error_exit(
'--historic-state can be used only is combination with --archive',
exit_code=CLIExitCodes.FAILURE
)
init_sync(env_file, archive, catchup, historic_state)
init_sync(env_file, archive, historic_state, snapshot_from)


@sync_node.command('update', help='Update sync node from .env file')
@click.option('--yes', is_flag=True, callback=abort_if_false,
expose_value=False,
prompt='Are you sure you want to update SKALE node software?')
@click.option(
'--unsafe',
'unsafe_ok',
help='Allow unsafe update',
hidden=True,
is_flag=True
)
@click.argument('env_file')
@streamed_cmd
def _update_sync(env_file):
def _update_sync(env_file, unsafe_ok):
update_sync(env_file)


@sync_node.command('repair', help='Start sync node from empty database')
@click.option('--yes', is_flag=True, callback=abort_if_false,
expose_value=False,
prompt='Are you sure you want to start sync node from empty database?')
@click.option(
'--archive',
help=TEXTS['init']['archive'],
is_flag=True
)
@click.option(
'--historic-state',
help=TEXTS['init']['historic_state'],
is_flag=True
)
@click.option(
'--snapshot-from',
type=URL_TYPE,
default=None,
hidden=True,
help='Ip of the node from to download snapshot from'
)
@streamed_cmd
def _repair_sync(
archive: str,
historic_state: str,
snapshot_from: Optional[str] = None
) -> None:
repair_sync(
archive=archive,
historic_state=historic_state,
snapshot_from=snapshot_from
)
1 change: 1 addition & 0 deletions node_cli/configs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

NODE_DATA_PATH = os.path.join(SKALE_DIR, 'node_data')
SCHAIN_NODE_DATA_PATH = os.path.join(NODE_DATA_PATH, 'schains')
NODE_CLI_STATUS_FILENAME = 'node_cli.status'
NODE_CONFIG_PATH = os.path.join(NODE_DATA_PATH, 'node_config.json')
CONTAINER_CONFIG_PATH = os.path.join(SKALE_DIR, 'config')
CONTAINER_CONFIG_TMP_PATH = os.path.join(SKALE_TMP_DIR, 'config')
Expand Down
30 changes: 23 additions & 7 deletions node_cli/configs/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,22 @@

ROUTES = {
'v1': {
'node': ['info', 'register', 'maintenance-on', 'maintenance-off', 'signature',
'send-tg-notification', 'exit/start', 'exit/status', 'set-domain-name'],
'node': [
'info',
'register',
'maintenance-on',
'maintenance-off',
'signature',
'send-tg-notification',
'exit/start',
'exit/status',
'set-domain-name',
'update-safe',
],
'health': ['containers', 'schains', 'sgx'],
'schains': ['config', 'list', 'dkg-statuses', 'firewall-rules', 'repair', 'get'],
'ssl': ['status', 'upload'],
'wallet': ['info', 'send-eth']
'wallet': ['info', 'send-eth'],
}
}

Expand All @@ -40,8 +50,11 @@ class RouteNotFoundException(Exception):


def route_exists(blueprint, method, api_version):
return ROUTES.get(api_version) and ROUTES[api_version].get(blueprint) and \
method in ROUTES[api_version][blueprint]
return (
ROUTES.get(api_version)
and ROUTES[api_version].get(blueprint)
and method in ROUTES[api_version][blueprint]
)


def get_route(blueprint, method, api_version=CURRENT_API_VERSION, check=True):
Expand All @@ -53,5 +66,8 @@ def get_route(blueprint, method, api_version=CURRENT_API_VERSION, check=True):

def get_all_available_routes(api_version=CURRENT_API_VERSION):
routes = ROUTES[api_version]
return [get_route(blueprint, method, api_version) for blueprint in routes
for method in routes[blueprint]]
return [
get_route(blueprint, method, api_version)
for blueprint in routes
for method in routes[blueprint]
]
3 changes: 2 additions & 1 deletion node_cli/core/health.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ def get_sgx_info():
['Server URL', data['sgx_server_url']],
['SGXWallet Version', data['sgx_wallet_version']],
['Node SGX keyname', data['sgx_keyname']],
['Status', data['status_name']]
['Status HTTPS', data['status_https']],
['Status ZMQ', data['status_zmq']]
]
table = SingleTable(table_data)
print(table.table)
Expand Down
51 changes: 44 additions & 7 deletions node_cli/core/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
turn_on_op,
restore_op,
init_sync_op,
repair_sync_op,
update_sync_op
)
from node_cli.utils.print_formatters import (
Expand Down Expand Up @@ -92,6 +93,16 @@ class NodeStatuses(Enum):
NOT_CREATED = 5


def is_update_safe() -> bool:
status, payload = get_request(BLUEPRINT_NAME, 'update-safe')
if status == 'error':
return False
safe = payload['update_safe']
if not safe:
logger.info('Locked schains: %s', payload['unsafe_chains'])
return safe


@check_inited
@check_user
def register_node(name, p2p_ip,
Expand Down Expand Up @@ -175,8 +186,8 @@ def restore(backup_path, env_filepath, no_snapshot=False, config_only=False):
def init_sync(
env_filepath: str,
archive: bool,
catchup: bool,
historic_state: bool
historic_state: bool,
snapshot_from: str
) -> None:
configure_firewall_rules()
env = get_node_env(env_filepath, sync_node=True)
Expand All @@ -186,8 +197,8 @@ def init_sync(
env_filepath,
env,
archive,
catchup,
historic_state
historic_state,
snapshot_from
)
if not inited_ok:
error_exit(
Expand All @@ -206,7 +217,7 @@ def init_sync(

@check_inited
@check_user
def update_sync(env_filepath):
def update_sync(env_filepath: str, unsafe_ok: bool = False) -> None:
logger.info('Node update started')
configure_firewall_rules()
env = get_node_env(env_filepath, sync_node=True)
Expand All @@ -222,6 +233,25 @@ def update_sync(env_filepath):
logger.info('Node update finished')


@check_inited
@check_user
def repair_sync(
archive: bool,
historic_state: bool,
snapshot_from: str
) -> None:

env_params = extract_env_params(INIT_ENV_FILEPATH, sync_node=True)
schain_name = env_params['SCHAIN_NAME']
repair_sync_op(
schain_name=schain_name,
archive=archive,
historic_state=historic_state,
snapshot_from=snapshot_from
)
logger.info('Schain was started from scratch')


def get_node_env(
env_filepath,
inited_node=False,
Expand Down Expand Up @@ -259,7 +289,11 @@ def get_node_env(

@check_inited
@check_user
def update(env_filepath, pull_config_for_schain):
def update(env_filepath: str, pull_config_for_schain: str, unsafe_ok: bool = False) -> None:
if not unsafe_ok and not is_update_safe():
error_msg = 'Cannot update safely'
error_exit(error_msg, exit_code=CLIExitCodes.UNSAFE_UPDATE)

logger.info('Node update started')
configure_firewall_rules()
env = get_node_env(
Expand Down Expand Up @@ -388,7 +422,10 @@ def set_maintenance_mode_off():

@check_inited
@check_user
def turn_off(maintenance_on):
def turn_off(maintenance_on: bool = False, unsafe_ok: bool = False) -> None:
if not unsafe_ok and not is_update_safe():
error_msg = 'Cannot turn off safely'
error_exit(error_msg, exit_code=CLIExitCodes.UNSAFE_UPDATE)
if maintenance_on:
set_maintenance_mode_on()
turn_off_op()
Expand Down
Loading

0 comments on commit 9e0c550

Please sign in to comment.