def add_trusted_host(arguments): if len(arguments) < 3: cli_error('You must pass at least the user name, password digest ' 'and the host UUID!') else: username = str(arguments.popleft()) digest = str(arguments.popleft()) host_uuid = try_parse_uuid(arguments.popleft()) node_map = proceed_with_node() if node_map is not None: # Finally, add user NodeApp.add_user(UserGroupUUID.safe_cast_uuid(gen_uuid()), username=str(username), digest=digest, is_trusted=True) _for_storage = True _for_restore = False NodeApp.add_host(username=username, hostname='Trusted: {}'.format(host_uuid), host_uuid=host_uuid, trusted_host_tuple=(_for_storage, _for_restore)) NodeApp.change_user(username, digest) print(u'Added Trusted Host {!r}'.format(username))
def add_user(arguments): node_map = proceed_with_node() if node_map is not None: if not arguments: cli_error('No user name passed') else: username_str = arguments.popleft() if arguments and arguments[0] == '--to-group': dummy = arguments.popleft() if not arguments: cli_error('Attempt to add user to group, ' 'but no group specified!') else: username = str(username_str) group_uuid = try_parse_uuid(arguments.popleft()) # Let's add the user to group NodeApp.add_user_to_group( username=username, group_uuid=UserGroupUUID.safe_cast_uuid(group_uuid)) print(u'Added user "{}" to the group "{}"' .format(username, group_uuid)) else: # Let's add the user to the system __add_new_regular_user(username_str, arguments)
def __test_web_upload_remove(op_upload, arguments): """Common code for CLI operations for web upload/web remove.""" op_name = 'upload' if op_upload else 'remove' if len(arguments) < 2: cli_error(u'You must pass at least 2 arguments to this command: ' u'the UUID of the group, and at least ' u'one filename to {op}.' .format(op=op_name)) else: group_uuid = UserGroupUUID.safe_cast_uuid( try_parse_uuid(arguments.popleft())) file_paths = [] while arguments: file_paths.append(arguments.popleft()) print(u'{} file paths for group {}:\n{}'.format( op_name.capitalize(), group_uuid, '\n'.join(file_paths))) node_map = proceed_with_node() chunk_storage = ChunkStorageBigDB(bdbw_factory=ds.BDB) with db.RDB() as rdbw: __test_upload_remove_files(group_uuid, file_paths, chunk_storage, op_upload, rdbw)
def save_connection_password(arguments): """ Generate digest for the connection password (for the current host) and save it. """ if len(arguments) < 1: cli_error('The host UUID and (optionally) the password ' 'should be passed as the arguments!') else: my_uuid = try_parse_uuid(arguments.popleft()) password = _get_password_from_arguments(arguments, repeat=True) proceed_with_host_uuid_cli(my_uuid) with db.RDB() as rdbw: my_host = Queries.Inhabitants.get_host_by_uuid(my_uuid, rdbw) my_username = my_host.username _digest = \ crypto.generate_digest(my_username, password, common_settings.HTTP_AUTH_REALM_NODE) Queries.Inhabitants.update_user_digest(my_username, _digest, rdbw) print(u'For host {host} (with user {user}), ' u'saving the following digest: {digest}' .format(host=my_uuid, user=my_username, digest=_digest))
def init_host(arguments): """ Initialize the host and run the first ever authentication. """ if len(arguments) < 2: cli_error('You must pass at least 2 arguments to this command.') else: my_listen_port_str, username = (arguments.popleft(), str(arguments.popleft())) password = _get_password_from_arguments(arguments) try: my_listen_port = int(my_listen_port_str) except ValueError: cli_error('Not an integer port number: %r', my_listen_port_str) if username is not None and password is not None: digest = \ crypto.generate_digest(username, password, common_settings.HTTP_AUTH_REALM_NODE) else: digest = None edition = uhost_settings.detect_edition() UHostApp.init_host(edition=edition, chunk_storage_cb=__create_chunk_storage, proceed_func=proceed_with_host_uuid_cli, on_end_func=__cli_handle_init_finish, username=username, digest=digest, my_listen_port=my_listen_port)
def greet_user(arguments): node_map = proceed_with_node() if node_map is not None: if not arguments: cli_error('No user name passed') elif len(arguments) < 1: cli_error('You must pass at least 1 arguments to this command: ' 'the name of the user.') else: username_str = arguments.popleft() with ds.FDB() as fdbw: FDBQueries.UserMessages.add_message( username=str(username_str), key='user_greeting {}'.format(gen_uuid()), body={ 'c': ('<p class="bold">{username}, welcome to our ' 'system</p>' '<p>This is a test message.</p>').format( username=username_str), 'en': ('<p class="bold">{username}, welcome to our ' 'system</p>' '<p>This is a test message.</p>').format( username=username_str), 'ru': (u'<p class="bold">Привет, {username}</p>' u'<p>Это тестовое сообщение.</p>').format( username=username_str) }, fdbw=fdbw) print(u'The greeting message has been sent to "{}"' .format(username_str))
def save_connection_password(arguments): """ Generate digest for the connection password (for the current host) and save it. """ if len(arguments) < 1: cli_error('The host UUID and (optionally) the password ' 'should be passed as the arguments!') else: my_uuid = try_parse_uuid(arguments.popleft()) password = _get_password_from_arguments(arguments, repeat=True) proceed_with_host_uuid_cli(my_uuid) with db.RDB() as rdbw: my_host = Queries.Inhabitants.get_host_by_uuid(my_uuid, rdbw) my_username = my_host.username _digest = \ crypto.generate_digest(my_username, password, common_settings.HTTP_AUTH_REALM_NODE) Queries.Inhabitants.update_user_digest(my_username, _digest, rdbw) print(u'For host {host} (with user {user}), ' u'saving the following digest: {digest}'.format(host=my_uuid, user=my_username, digest=_digest))
def select_files(arguments): """ Generate digest for the username. """ if len(arguments) < 3: cli_error('The host UUID, the backup name, and at least one directory ' 'with the files should be passed!') else: my_uuid, ds_name = (try_parse_uuid(arguments.popleft()), arguments.popleft()) proceed_with_host_uuid_cli(my_uuid) paths = __get_all_remaining_args(arguments) if not paths: cli_error('No paths passed!') else: host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage()) ugroup_uuid = host_app.host.user.base_group.uuid path_map = { k: { 'f+': ['all'], 'f-': [], 'stat': safe_stat(k) } for k in paths } host_app.select_paths_for_backup(ds_name=ds_name, ds_uuid=gen_uuid(), ugroup_uuid=ugroup_uuid, sync=False, paths_map=path_map)
def select_files(arguments): """ Generate digest for the username. """ if len(arguments) < 3: cli_error('The host UUID, the backup name, and at least one directory ' 'with the files should be passed!') else: my_uuid, ds_name = (try_parse_uuid(arguments.popleft()), arguments.popleft()) proceed_with_host_uuid_cli(my_uuid) paths = __get_all_remaining_args(arguments) if not paths: cli_error('No paths passed!') else: host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage()) ugroup_uuid = host_app.host.user.base_group.uuid path_map = {k: {'f+': ['all'], 'f-': [], 'stat': safe_stat(k)} for k in paths} host_app.select_paths_for_backup(ds_name=ds_name, ds_uuid=gen_uuid(), ugroup_uuid=ugroup_uuid, sync=False, paths_map=path_map)
def add_group(arguments): node_map = proceed_with_node() if node_map is not None: if len(arguments) < 1: cli_error('You must pass at least 1 argument to this command: ' 'the name of the group.') else: groupname_str = arguments.popleft() # Parse group UUID (optional) try: group_uuid = UUID(arguments[0]) # Parsed successfully arguments.popleft() except (IndexError, ValueError): group_uuid = gen_uuid() user_group = UserGroup(uuid=UserGroupUUID.safe_cast_uuid( group_uuid), name=str(groupname_str), private=False, enc_key=gen_rand_key()) NodeApp.add_ugroup(user_group) print(u'Added group "{}" with UUID {}' .format(groupname_str, group_uuid))
def use_password(arguments): """ Use the password given in the CLI. """ if len(arguments) < 1: cli_error('At least the password should be passed!') else: global PASSWORD PASSWORD = arguments.popleft()
def request_info_dataset_files(arguments): """ Request info on particular dataset. """ if len(arguments) < 2: cli_error('You must pass at least the host UUID ' 'and the dataset UUID to this command.') else: my_uuid, ds_uuid = (try_parse_uuid(arguments.popleft()), try_parse_uuid(arguments.popleft())) proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ @exceptions_logged(logger) @contract_epydoc def on_datasets_received(ds_uuid, dataset_files_dict): """ @type ds_uuid: UUID @type dataset_files_dict: dict """ try: print('The following files are present in the dataset {}:' .format(ds_uuid)) _format = u' {0:<36s} {1}' print(_format.format('File UUID', 'File path')) print(_format.format('-' * 36, '-' * len('File path'))) for root_dir in sorted(dataset_files_dict.iterkeys()): print(u" {}".format(root_dir)) for f in dataset_files_dict[root_dir]: print(_format.format(f.uuid, f.full_path)) except Exception: traceback.print_exc() finally: app.terminate_host() app.query_dataset_files(ds_uuid, on_datasets_received) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start) host_app.first_start() # But it is not yet started, until the reactor is launched as well. # Launch reactor host_app.start_reactor()
def request_info_dataset_files(arguments): """ Request info on particular dataset. """ if len(arguments) < 2: cli_error('You must pass at least the host UUID ' 'and the dataset UUID to this command.') else: my_uuid, ds_uuid = (try_parse_uuid(arguments.popleft()), try_parse_uuid(arguments.popleft())) proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ @exceptions_logged(logger) @contract_epydoc def on_datasets_received(ds_uuid, dataset_files_dict): """ @type ds_uuid: UUID @type dataset_files_dict: dict """ try: print('The following files are present in the dataset {}:'. format(ds_uuid)) _format = u' {0:<36s} {1}' print(_format.format('File UUID', 'File path')) print(_format.format('-' * 36, '-' * len('File path'))) for root_dir in sorted(dataset_files_dict.iterkeys()): print(u" {}".format(root_dir)) for f in dataset_files_dict[root_dir]: print(_format.format(f.uuid, f.full_path)) except Exception: traceback.print_exc() finally: app.terminate_host() app.query_dataset_files(ds_uuid, on_datasets_received) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start) host_app.first_start() # But it is not yet started, until the reactor is launched as well. # Launch reactor host_app.start_reactor()
def print_data_stats(arguments): """ Print the backup data statistics in the cloud. """ if len(arguments) < 3: cli_error('The host UUID, the dataset UUID (or asterisk), ' 'and the path (or asterisk)\n' 'should be passed as the arguments!') else: my_uuid, ds_uuid, path = (try_parse_uuid(arguments.popleft()), try_parse_uuid(arguments.popleft()), arguments.popleft()) proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ def on_data_stats_received(ds_uuid, path, data_stats): try: data_stats['chunk_ratio'] = \ float(data_stats['chunk_replicas_count']) / \ data_stats['chunk_count'] __print_data_stats(data_stats, ds_uuid, path) except Exception: traceback.print_exc() finally: app.terminate_host() app.query_data_replication_stats(ds_uuid if ds_uuid != '*' else None, path if path != '*' else None, on_data_stats_received) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start) host_app.first_start() # But it is not yet started, until the reactor is launched as well. # Launch reactor host_app.start_reactor()
def logs_action(arguments): """ Perform some action on the log files. """ global _LOG_ACTIONS if len(arguments) < 2: cli_error('At least the host UUID and the action should be passed!') else: my_uuid, action = (try_parse_uuid(arguments.popleft()), arguments.popleft()) if action not in _LOG_ACTIONS: cli_error('Action %r unsupported, only the following actions ' 'are supported: %s', action, ', '.join(imap('{!r}'.format, _LOG_ACTIONS))) else: proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ @exceptions_logged(logger) def on_action_completed(result): app.terminate_host() send_settings = uhost_settings.get_log_reporting_settings() app.action_with_error_logs(action=action, report_settings=send_settings, on_completed=on_action_completed) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start) host_app.first_start() # Launch reactor host_app.start_reactor()
def main(): """ Startup function. """ if len(sys.argv) == 1: cli_error('No arguments passed!') install_reactor(force_reactor_name='qt4') from host import settings as host_settings from . import cli # See host.cli for actually executed CLI commands. cli_mode(host_settings.HOST_VERSION_STRING)
def main(): """ Startup function. """ if len(sys.argv) == 1: cli_error("No arguments passed!") install_reactor(force_reactor_name="qt4") from host import settings as host_settings from . import cli # See host.cli for actually executed CLI commands. cli_mode(host_settings.HOST_VERSION_STRING)
def generate_digest(arguments): """ Generate digest for the username. """ if len(arguments) < 1: cli_error('The user name and (optionally) the password should be ' 'passed as the arguments!') else: username = arguments.popleft() password = _get_password_from_arguments(arguments) print('For username {0}, the digest is {1}'.format( username, crypto.generate_digest(str(username), password, common_settings.HTTP_AUTH_REALM_NODE)))
def _test_take_snapshot(arguments): if len(arguments) < 2: cli_error('Must pass the base host UUID and the directory path ' 'to take snapshot!') my_uuid = try_parse_uuid(arguments.popleft()) dir_path = arguments.popleft() print(u'Taking snapshot of {!r}'.format(dir_path)) proceed_with_host_uuid_cli(my_uuid) with db.RDB() as rdbw: host = Queries.Inhabitants.get_host_with_user_by_uuid(uuid, rdbw) UHostApp.take_base_directory_snapshot(dir_path, host.user.base_group.uuid)
def _test_make_backup_dir(arguments): """ Create a directory filled with dummy data files. """ if len(arguments) < 2: cli_error('Must pass the data variant and the directory path ' 'for the test data!') data_variant, backup_dir = (int(arguments.popleft()), arguments.popleft()) print(u'Making backup data in {:s} with variant {:d}' .format(backup_dir, data_variant)) # Create fake data from common.test.utils import _test_create_permdir _test_create_permdir(backup_dir, data_variant)
def _test_make_backup_dir(arguments): """ Create a directory filled with dummy data files. """ if len(arguments) < 2: cli_error('Must pass the data variant and the directory path ' 'for the test data!') data_variant, backup_dir = (int(arguments.popleft()), arguments.popleft()) print(u'Making backup data in {:s} with variant {:d}'.format( backup_dir, data_variant)) # Create fake data from common.test.utils import _test_create_permdir _test_create_permdir(backup_dir, data_variant)
def print_data_stats(arguments): """ Print the backup data statistics in the cloud. """ if len(arguments) < 3: cli_error('The host UUID, the dataset UUID (or asterisk), ' 'and the path (or asterisk)\n' 'should be passed as the arguments!') else: my_uuid, ds_uuid, path = (try_parse_uuid(arguments.popleft()), try_parse_uuid(arguments.popleft()), arguments.popleft()) proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ def on_data_stats_received(ds_uuid, path, data_stats): try: data_stats['chunk_ratio'] = \ float(data_stats['chunk_replicas_count']) / \ data_stats['chunk_count'] __print_data_stats(data_stats, ds_uuid, path) except Exception: traceback.print_exc() finally: app.terminate_host() app.query_data_replication_stats( ds_uuid if ds_uuid != '*' else None, path if path != '*' else None, on_data_stats_received) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start) host_app.first_start() # But it is not yet started, until the reactor is launched as well. # Launch reactor host_app.start_reactor()
def generate_digest(arguments): """ Generate digest for the username. """ if len(arguments) < 1: cli_error('The user name and (optionally) the password should be ' 'passed as the arguments!') else: username = arguments.popleft() password = _get_password_from_arguments(arguments) print('For username {0}, the digest is {1}' .format(username, crypto.generate_digest( str(username), password, common_settings.HTTP_AUTH_REALM_NODE)))
def add_host(arguments): if len(arguments) < 2: cli_error('You must pass at least the user name ' 'and the host UUID!') else: username = str(arguments.popleft()) host_uuid = try_parse_uuid(arguments.popleft()) node_map = proceed_with_node() if node_map is not None: NodeApp.add_host(username=username, hostname=str(host_uuid), host_uuid=host_uuid, trusted_host_tuple=None) print(u'Added host {} to "{}"'.format(host_uuid, username))
def proceed_with_node(): """ Read the node configuration for the node process. If needed, the database file is created and initialized as well. If it fails, it returns None and prints the reason of the failure (so the caller may not bother doing it). @returns: The port-to-node_settings mapping, like C{settings.get_my_nodes_settings()}; or None if failed for some reason. @rtype: dict, NoneType """ settings.configure_logging(postfix='common') node_settings_map = settings.get_my_nodes_settings() rel_db_url = settings.get_common().rel_db_url db.init(rel_db_url, SQLALCHEMY_ECHO) node_common_settings = settings.get_common() try: ds.init(fast_db_url=node_common_settings.fast_db_url, big_db_url=node_common_settings.big_db_url) except ds.MongoDBInitializationException as e: print(u'MongoDB problem: {}'.format(e)) else: # Create the database if the file is missing or 0 bytes long. if not db.RDB.is_schema_initialized: print('Initializing database schema...') try: db.create_node_db_schema() except Exception: cli_error('cannot create the RDB schema:\n%s', traceback.format_exc()) else: print('Successfully initialized.') else: # If the database is available, launch maintenance procedures. with db.RDB() as rdbw: Queries.System.maintenance(rdbw) logger.debug('Maintenance done') __migrate_if_needed() return node_settings_map
def test_web_download(arguments): node_map = proceed_with_node() if len(arguments) < 3: cli_error(u'You must pass at least 3 arguments to this command: ' u'the dataset UUID , ' u'base directory of the file, ' u'and the relative path of the file.' .format(op=op_name)) else: ds_uuid = try_parse_uuid(arguments.popleft()) base_dir = arguments.popleft() rel_path = arguments.popleft() edition = settings.get_common().edition print(u'Downloading file from dataset {}, base directory {}, ' u'path {}' .format(ds_uuid, base_dir, rel_path)) with db.RDB() as rdbw, ds.BDB() as bdbw: cr = data_ops.get_cryptographer(ds_uuid, edition, rdbw) file_data = data_ops.download_file(ds_uuid, base_dir, rel_path, edition, rdbw) result_filename = os.path.basename(rel_path) logger.debug('Writing to file %r %i bytes long', result_filename, file_data.size) with open(result_filename, 'wb') as fh: # Preallocate file if file_data.size: fh.seek(file_data.size - 1) fh.write('\x00') fh.seek(0) # Now write the file contents. try: for bl in data_ops.get_file_of_blocks_gen( file_data.blocks, cr, bdbw=bdbw): fh.write(bl) except BDBQueries.Chunks.NoChunkException as e: logger.error('Problem while downloading the file: %s', e) print(u'Error: file {!r} cannot be created!'.format( result_filename))
def set_setting(arguments): """ Set some host setting to the value. """ if len(arguments) < 3: cli_error('The host UUID, setting name and the value ' 'should be passed as the arguments!') else: (my_uuid, setting_name, setting_value) = (try_parse_uuid(arguments.popleft()), arguments.popleft(), arguments.popleft()) if setting_name not in Queries.Settings.ALL_SETTINGS: cli_error('Setting "%s" unsupported!', setting_name) else: proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ print('Modifying {!r} to {!r}'.format(setting_name, setting_value)) app.set_setting(setting_name, setting_value, on_received=lambda x: app.terminate_host()) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start, do_send_messages=False) host_app.first_start() # But it is not yet started, until the reactor is launched as well. # Launch reactor host_app.start_reactor()
def logs_action(arguments): """ Perform some action on the log files. """ global _LOG_ACTIONS if len(arguments) < 2: cli_error('At least the host UUID and the action should be passed!') else: my_uuid, action = (try_parse_uuid(arguments.popleft()), arguments.popleft()) if action not in _LOG_ACTIONS: cli_error( 'Action %r unsupported, only the following actions ' 'are supported: %s', action, ', '.join(imap('{!r}'.format, _LOG_ACTIONS))) else: proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ @exceptions_logged(logger) def on_action_completed(result): app.terminate_host() send_settings = uhost_settings.get_log_reporting_settings() app.action_with_error_logs(action=action, report_settings=send_settings, on_completed=on_action_completed) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start) host_app.first_start() # Launch reactor host_app.start_reactor()
def delete_dataset(arguments): """ Delete the dataset from the Node. """ global _LOG_ACTIONS if len(arguments) < 2: cli_error('At least the host UUID and the dataset UUID ' 'should be passed!') else: my_uuid, ds_uuid = (try_parse_uuid(arguments.popleft()), try_parse_uuid(arguments.popleft())) print('Trying to delete the dataset {}'.format(ds_uuid)) proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ @exceptions_logged(logger) def on_datasets_deleted(deleted_ds_uuids): print('Deleted the following backups successfully:') print('\n'.join(' {}'.format(u) for u in deleted_ds_uuids)) app.terminate_host() app.delete_datasets_from_node(ds_uuids_to_delete=[ds_uuid], on_completed=on_datasets_deleted) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start) host_app.first_start() # Launch reactor host_app.start_reactor()
def _get_password_from_arguments(arguments, repeat=False): """ Utilitary function to get a password either from CLI arguments, or interactively. @param repeat: Whether the password should be re-requested for confirmation. @type repeat: bool @rtype: str """ if arguments: password = arguments.popleft() else: password = getpass.getpass('Enter password: '******'Repeat password: '******'Passwords do not match!') return password
def __add_new_regular_user(username, arguments): if not arguments: cli_error('No digest string passed!') else: # Parse digest digest_str = arguments.popleft() try: digest = '{:040x}'.format(int(digest_str, 16)) except: cli_error('The argument \"{}\" is not a valid hexadecimal digest!' .format(digest_str)) if len(digest) != 40: cli_error('The digest argument should be a hexadecimal number ' 'up to 40 hexadigits long rather than {}!' .format(digest)) # Parse group UUID (optional) try: group_uuid = UUID(arguments[0]) # Parsed successfully arguments.popleft() except (IndexError, ValueError): group_uuid = gen_uuid() # Finally, add user NodeApp.add_user(UserGroupUUID.safe_cast_uuid(group_uuid), username=str(username), digest=digest, is_trusted=False) print(u'Added user "{}"'.format(username))
def proceed_with_host_uuid_cli(*args, **kwargs): """ Given the host UUID, run all the preparations which are needed to access the logging framework, do the database access, etc. The node which is used is (at the moment) ALWAYS taken from the default host.conf file. @todo: Some day we need to use the node settings from the DB. Should it be done here? """ h_i_exc = UHostApp.HostInitExceptions try: UHostApp.proceed_with_host_uuid(*args, **kwargs) except common_settings.UnreadableConfFileException as e: cli_error('Cannot read .conf file from {!r}!'.format(e.path)) except h_i_exc.IncorrectDefaultNodeSettingsException: cli_error('Default node settings in the .conf file are incorrect!') except h_i_exc.NoNodeUrlsException: cli_error('Configuration file should contain ' 'at least a single node url.') except h_i_exc.NoHostDbException as e: cli_error('Database is absent: %s', e.base_exc) except h_i_exc.DBInitializationIssue as e: cli_error('Could not initialize the DB: %s\n%s\n%s', e.base_exc, e.base_exc.base_exc, u'{}\n-------'.format(e.base_exc.msg) if __debug__ else '') except h_i_exc.UnknownIssue as e: cli_error('Unexpected error during the DB initialization: %s', e.base_exc) else: print('Successfully initialized.')
def start_restore(arguments): """ Start restore process. """ if len(arguments) < 4: cli_error("At least the host UUID, the target directory, " "the dataset UUID\n" "and at least one file full path from the dataset " "should be passed!") else: my_uuid = try_parse_uuid(arguments.popleft()) if arguments and arguments[0] in _SAS_OPTIONS: arguments.popleft() stay_alive_on_success = True else: stay_alive_on_success = False if arguments and arguments[0] in _SAF_OPTIONS: arguments.popleft() stay_alive_on_failure = True else: stay_alive_on_failure = False target_dir, ds_uuid = (arguments.popleft(), try_parse_uuid(arguments.popleft())) file_paths_to_restore = map(normpath_nodot, __get_all_remaining_args(arguments)) if not file_paths_to_restore: cli_error('No files are given!') proceed_with_host_uuid_cli(my_uuid) @exceptions_logged(logger) @contract_epydoc def on_reactor_start(app): """ @type app: UHostApp """ @exceptions_logged(logger) @contract_epydoc def on_restore_completed(restore_succeeded): """ @param restore_succeeded: whether the restore attempt has succeeded in overall. @type restore_succeeded: bool """ if restore_succeeded: print('Restore completed successfully!') else: print('The node disallowed the restore.') if (stay_alive_on_success if restore_succeeded else stay_alive_on_failure): print("Stayin' alive. Stayin' alive.") else: app.terminate_host() app.start_restore(file_paths_to_restore=file_paths_to_restore, ds_uuid=ds_uuid, restore_directory=target_dir, on_completed=on_restore_completed) # Launch the main host app host_app = UHostApp(my_uuid, uhost_settings.detect_edition(), __create_chunk_storage(), on_reactor_start=on_reactor_start, do_auto_start_backup=False) host_app.first_start() # Launch reactor host_app.start_reactor()
def cli_host_uuid_error(): """ This function is not exported, but used only inside this module. """ cli_error('You must pass at least the host UUID to this command.')