Command line user interface for the node component
Attributes
cli module-attribute
cli = NodeCLI()
imp_cli_utils module-attribute
imp_cli_utils = partial(import_module, 'fedbiomed.node.cli_utils')
Classes
DatasetArgumentParser
DatasetArgumentParser(subparser)
Bases: CLIArgumentParser
Initializes CLI options for dataset actions
Source code in fedbiomed/common/cli.py
def __init__(self, subparser: argparse.ArgumentParser):
self._subparser = subparser
# Parser that is going to be add using subparser
self._parser = None
Functions
add
add(args)
Adds datasets
Source code in fedbiomed/node/cli.py
def add(self, args):
"""Adds datasets"""
global add_database
add_database = imp_cli_utils().add_database
if args.mnist:
return add_database(interactive=False, path=args.mnist)
if args.file:
return self._add_dataset_from_file(path=args.file)
# All operation is handled by CLI utils add_database
return add_database()
delete
delete(args)
Deletes datasets
Source code in fedbiomed/node/cli.py
def delete(self, args):
"""Deletes datasets"""
cli_utils = imp_cli_utils()
if args.all:
return cli_utils.delete_all_database()
if args.mnist:
return cli_utils.delete_database(interactive=False)
return cli_utils.delete_database()
initialize
initialize()
Initializes dataset options for the node CLI
Source code in fedbiomed/node/cli.py
def initialize(self):
"""Initializes dataset options for the node CLI"""
self._parser = self._subparser.add_parser(
"dataset",
help="Dataset operations"
)
self._parser.set_defaults(func=self.default)
# Creates subparser of dataset option
dataset_subparsers = self._parser.add_subparsers()
# Add option
add = dataset_subparsers.add_parser(
"add",
help="Adds dataset"
)
# List option
list_ = dataset_subparsers.add_parser(
"list",
help="List datasets that are deployed in the node.")
# Delete option
delete = dataset_subparsers.add_parser(
"delete",
help="Deletes dataset that are deployed in the node.")
add.add_argument(
"--mnist",
"-m",
metavar="MNIST_DATA_PATH",
help="Deploys MNIST dataset by downloading form default source to given path.",
required=False
)
add.add_argument(
"--file",
"-fl",
required=False,
metavar="File that describes the dataset",
help="File path the dataset file desciptro. This option adds dataset by given file which is has"
"cutom format that describes the dataset.")
delete.add_argument(
"--all",
'-a',
required=False,
action="store_true",
help="Removes entire dataset database.")
delete.add_argument(
"--mnist",
'-m',
required=False,
action="store_true",
help="Removes MNIST dataset.")
add.set_defaults(func=self.add)
list_.set_defaults(func=self.list)
delete.set_defaults(func=self.delete)
list
list(unused_args)
List datasets
Parameters:
Name | Type | Description | Default |
---|---|---|---|
unused_args | Empty arguments since | required |
Source code in fedbiomed/node/cli.py
def list(self, unused_args):
"""List datasets
Args:
unused_args: Empty arguments since `list` command no positional args.
"""
dataset_manager = imp_cli_utils().dataset_manager
print('Listing your data available')
data = dataset_manager.list_my_data(verbose=True)
if len(data) == 0:
print('No data has been set up.')
GUIControl
GUIControl(subparser)
Bases: CLIArgumentParser
Source code in fedbiomed/common/cli.py
def __init__(self, subparser: argparse.ArgumentParser):
self._subparser = subparser
# Parser that is going to be add using subparser
self._parser = None
Functions
forward
forward(args, extra_args)
Forwards gui commands to ./script/fedbiomed_gui Extra arguments
TODO: Implement argument GUI parseing and execution
Source code in fedbiomed/node/cli.py
def forward(self, args, extra_args):
"""Forwards gui commands to ./script/fedbiomed_gui Extra arguments
TODO: Implement argument GUI parseing and execution
"""
# commad = []
# command.extend(['--data-folder', args.data_folder, '--port', args.port, '--host', args.host])
# if args.key_file:
# command.extend(['--key-file', args.key_file])
#
# if args.cert_file:
# command.extend(['--cert-file', args.cert_file])
#
# if args.recreate:
# command.append('--recreate')
#
# if args.debug:
# command.append('--debug')
gui_script = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'scripts', 'fedbiomed_gui'))
command = [gui_script, *extra_args]
process = subprocess.Popen(command)
try:
process.wait()
except KeyboardInterrupt:
try:
process.terminate()
except Exception:
pass
process.wait()
initialize
initialize()
Initializes GUI commands
Source code in fedbiomed/node/cli.py
def initialize(self):
"""Initializes GUI commands"""
self._parser = self._subparser.add_parser("gui", add_help=False, help="Action to manage Node user interface")
self._parser.set_defaults(func=self.forward)
NodeCLI
NodeCLI()
Bases: CommonCLI
Source code in fedbiomed/node/cli.py
def __init__(self):
super().__init__()
self._parser.prog = "fedbiomed_run node"
self.description = f"{__intro__} \nA CLI app for fedbiomed node component."
# Parent parser for parameters that are common for Node CLI actions
self.initialize()
Attributes
description instance-attribute
description = f'{__intro__}
A CLI app for fedbiomed node component.'
Functions
initialize
initialize()
Initializes node module
Source code in fedbiomed/node/cli.py
def initialize(self):
"""Initializes node module"""
class ConfigNameActionNode(ConfigNameAction):
_this = self
_component = ComponentType.NODE
def import_environ(self) -> 'fedbiomed.node.environ.Environ':
"""Imports dynamically node environ object"""
return importlib.import_module("fedbiomed.node.environ").environ
self._parser.add_argument(
"--config",
"-cf",
nargs="?",
action=ConfigNameActionNode,
default="config_node.ini",
help="Name of the config file that the CLI will be activated for. Default is 'config_node.ini'.")
super().initialize()
NodeControl
NodeControl(subparser)
Bases: CLIArgumentParser
CLI argument parser for starting the node
Source code in fedbiomed/common/cli.py
def __init__(self, subparser: argparse.ArgumentParser):
self._subparser = subparser
# Parser that is going to be add using subparser
self._parser = None
Functions
initialize
initialize()
Initializes missinon control argument parser
Source code in fedbiomed/node/cli.py
def initialize(self):
"""Initializes missinon control argument parser"""
start = self._subparser.add_parser("start", help="Starts the node")
start.set_defaults(func=self.start)
start.add_argument(
"--gpu",
action="store_true",
help="Activate GPU usage if the flag is present")
start.add_argument(
"--gpu-num",
"-gn",
type=int,
nargs="?",
required=False,
default=1,
help="Number of GPU that is going to be used")
start.add_argument(
"--gpu-only",
"-go",
action="store_true",
help="Node performs training only using GPU resources."
"This flag automatically activate GPU.")
start
start(args)
Starts the node
Source code in fedbiomed/node/cli.py
def start(self, args):
"""Starts the node"""
global start_node
intro()
environ = importlib.import_module("fedbiomed.node.environ").environ
# Define arguments
node_args = {
"gpu": (args.gpu is True) or (args.gpu_only is True),
"gpu_num": args.gpu_num,
"gpu_only": True if args.gpu_only else False}
p = Process(target=start_node, name='node-' + environ['NODE_ID'], args=(node_args,))
p.deamon = True
p.start()
logger.info("Node started as process with pid = " + str(p.pid))
try:
print('To stop press Ctrl + C.')
p.join()
except KeyboardInterrupt:
p.terminate()
time.sleep(1)
while p.is_alive():
logger.info("Terminating process id =" + str(p.pid))
time.sleep(1)
logger.info('Exited with code ' + str(p.exitcode))
sys.exit(0)
TrainingPlanArgumentParser
TrainingPlanArgumentParser(subparser)
Bases: CLIArgumentParser
Argument parser for training-plan operations
Source code in fedbiomed/common/cli.py
def __init__(self, subparser: argparse.ArgumentParser):
self._subparser = subparser
# Parser that is going to be add using subparser
self._parser = None
Functions
approve
approve(args)
Approves training plan
Source code in fedbiomed/node/cli.py
def approve(self, args):
"""Approves training plan"""
approve_training_plan = imp_cli_utils().approve_training_plan
approve_training_plan(id=args.id)
delete
delete(args)
Deletes training plan
Source code in fedbiomed/node/cli.py
def delete(self, args):
"""Deletes training plan"""
delete_training_plan = imp_cli_utils().delete_training_plan
delete_training_plan(id=args.id)
initialize
initialize()
Source code in fedbiomed/node/cli.py
def initialize(self):
self._parser = self._subparser.add_parser(
"training-plan",
help="CLI operations for TrainingPlans register/list/delete/approve/reject etc."
)
training_plan_suparsers = self._parser.add_subparsers()
self._parser.set_defaults(func=self.default)
common_reject_approve = argparse.ArgumentParser(add_help=False)
common_reject_approve.add_argument(
'--id',
type=str,
nargs='?',
required=False,
help='ID of the training plan that will be processed.'
)
update = training_plan_suparsers.add_parser(
"update", help="Updates training plan"
)
update.set_defaults(func=self.update)
register = training_plan_suparsers.add_parser(
"register", help="Registers training plans manually by selected file thorugh interactive browser."
)
register.set_defaults(func=self.register)
list = training_plan_suparsers.add_parser(
"list", help="Lists all saved/registered training plans with their status.")
list.set_defaults(func=self.list)
delete = training_plan_suparsers.add_parser(
"delete",
parents=[common_reject_approve],
help="Deletes interactively selected training plan from the database.")
delete.set_defaults(func=self.delete)
approve = training_plan_suparsers.add_parser(
"approve",
parents=[common_reject_approve],
help="Approves interactively selected training plans.")
approve.set_defaults(func=self.approve)
reject = training_plan_suparsers.add_parser(
"reject",
parents=[common_reject_approve],
help="Rejects interactively selected training plans.")
reject.add_argument(
"--notes",
type=str,
nargs="?",
required=False,
default="No notes provided.",
help="Note to explain why training plan is rejected."
)
reject.set_defaults(func=self.reject)
view = training_plan_suparsers.add_parser(
"view", help="View interactively selected training plans.")
view.set_defaults(func=self.view)
list
list()
Lists training plans
Source code in fedbiomed/node/cli.py
def list(self):
"""Lists training plans"""
tp_security_manager = imp_cli_utils().tp_security_manager
tp_security_manager.list_training_plans(verbose=True)
register
register()
Registers training plan
Source code in fedbiomed/node/cli.py
def register(self):
"""Registers training plan"""
register_training_plan = imp_cli_utils().register_training_plan
register_training_plan()
reject
reject(args)
Approves training plan
Source code in fedbiomed/node/cli.py
def reject(self, args):
"""Approves training plan"""
reject_training_plan = imp_cli_utils().reject_training_plan
reject_training_plan(id=args.id, notes=args.notes)
update
update()
Updates training plan
Source code in fedbiomed/node/cli.py
def update(self):
"""Updates training plan"""
update_training_plan = imp_cli_utils().update_training_plan
update_training_plan()
view
view()
Views training plan
Source code in fedbiomed/node/cli.py
def view(self):
"""Views training plan"""
view_training_plan = imp_cli_utils().view_training_plan
view_training_plan()
Functions
intro
intro()
Prints intro for the CLI
Source code in fedbiomed/node/cli.py
def intro():
"""Prints intro for the CLI"""
print(__intro__)
print('\t- 🆔 Your node ID:', os.environ['FEDBIOMED_ACTIVE_NODE_ID'], '\n')
start_node
start_node(node_args)
Starts the node
Source code in fedbiomed/node/cli.py
def start_node(node_args):
"""Starts the node"""
cli_utils = imp_cli_utils()
tp_security_manager = cli_utils.tp_security_manager
dataset_manager = cli_utils.dataset_manager
Node = importlib.import_module("fedbiomed.node.node").Node
environ = importlib.import_module("fedbiomed.node.environ").environ
try:
signal.signal(signal.SIGTERM, _node_signal_handler)
logger.info('Launching node...')
# Register default training plans and update hashes
if environ["TRAINING_PLAN_APPROVAL"]:
# This methods updates hashes if hashing algorithm has changed
tp_security_manager.check_hashes_for_registered_training_plans()
if environ["ALLOW_DEFAULT_TRAINING_PLANS"]:
logger.info('Loading default training plans')
tp_security_manager.register_update_default_training_plans()
else:
logger.warning('Training plan approval for train request is not activated. ' +
'This might cause security problems. Please, consider to enable training plan approval.')
logger.info('Starting communication channel with network')
_node = Node(dataset_manager=dataset_manager,
tp_security_manager=tp_security_manager,
node_args=node_args)
_node.start_messaging(_node_signal_trigger_term)
logger.info('Starting node to node router')
_node.start_protocol()
logger.info('Starting task manager')
_node.task_manager() # handling training tasks in queue
except FedbiomedError:
logger.critical("Node stopped.")
# we may add extra information for the user depending on the error
except Exception as exp:
# must send info to the researcher (no mqqt should be handled
# by the previous FedbiomedError)
_node.send_error(ErrorNumbers.FB300, extra_msg="Error = " + str(exp))
logger.critical("Node stopped.")