Skip to content

Commit

Permalink
Merge pull request #296 from DUNE-DAQ/revert-239-plasorak/recursive-s…
Browse files Browse the repository at this point in the history
…tatuses

Revert "Recursive statuses"
  • Loading branch information
plasorak authored Nov 1, 2024
2 parents 26639ae + f1ede06 commit 01ffbdf
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 45 deletions.
18 changes: 13 additions & 5 deletions src/drunc/controller/children_interface/grpc_child.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,21 @@ def start_listening(self, bdesc):
)

def get_status(self, token) -> Response:
return send_command(
controller = self.controller,
token = token,
command = 'status',
data = None
from druncschema.controller_pb2 import Status
from drunc.utils.grpc_utils import unpack_any

status = unpack_any(
send_command(
controller = self.controller,
token = token,
command = 'get_status',
data = None
).data,
Status
)

return status

def terminate(self):
if self.channel:
self.channel.close()
Expand Down
12 changes: 2 additions & 10 deletions src/drunc/controller/children_interface/rest_api_child.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,22 +446,14 @@ def get_endpoint(self):

def get_status(self, token):
from druncschema.controller_pb2 import Status
from druncschema.request_response_pb2 import Response, ResponseFlag
from drunc.utils.grpc_utils import pack_to_any

status = Status(
return Status(
name = self.name,
state = self.state.get_operational_state(),
sub_state = 'idle' if not self.state.get_executing_command() else 'executing_cmd',
in_error = self.state.in_error() or not self.commander.ping(), # meh
included = self.state.included(),
)
return Response(
name = self.name,
token = None,
data = pack_to_any(status),
flag = ResponseFlag.EXECUTED_SUCCESSFULLY,
children = [],
)

def propagate_command(self, command:str, data, token:Token) -> Response:
from druncschema.request_response_pb2 import ResponseFlag
Expand Down
82 changes: 77 additions & 5 deletions src/drunc/controller/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,26 @@ def __init__(self, configuration, name:str, session:str, token:Token):
),

CommandDescription(
name = 'status',
name = 'get_children_status',
data_type = ['generic_pb2.PlainText','None'],
help = 'Get the status of all the children. Only get the status from the child if provided in the request.',
return_type = 'controller_pb2.ChildrenStatus'
),

CommandDescription(
name = 'get_status',
data_type = ['None'],
help = 'Get the status of self',
return_type = 'controller_pb2.Status'
),

CommandDescription(
name = 'ls',
data_type = ['None'],
help = 'List the children',
return_type = 'generic_pb2.PlainTextVector'
),

CommandDescription(
name = 'describe_fsm',
data_type = ['generic_pb2.PlainText', 'None'],
Expand Down Expand Up @@ -433,17 +447,75 @@ def propagate_to_child(child, command, command_data, token, response_lock, respo
action=ActionType.READ,
system=SystemType.CONTROLLER
) # 2nd step
@unpack_request_data_to(pass_token=True) # 3rd step
def get_children_status(self, token:Token) -> Response:
#from drunc.controller.utils import get_status_message
cs = []
for n in self.children_nodes:
try:
cs += [n.get_status(token)]
except Exception as e: # TEMPORARY hack
from druncschema.controller_pb2 import Status
cs += [
Status(
name = n.name,
state = 'unknown',
sub_state = 'unknown',
in_error = True,
)
]

@unpack_request_data_to(None, pass_token=True) # 3rd step
def status(self, token:Token) -> Response:
response = ChildrenStatus(
children_status = cs
)
return Response(
name = self.name,
token = None,
data = pack_to_any(response),
flag = ResponseFlag.EXECUTED_SUCCESSFULLY,
children = [],
)

# ORDER MATTERS!
@broadcasted # outer most wrapper 1st step
@authentified_and_authorised(
action=ActionType.READ,
system=SystemType.CONTROLLER
) # 2nd step
@unpack_request_data_to(None) # 3rd step
def get_status(self) -> Response:
from drunc.controller.utils import get_status_message
status = get_status_message(self.stateful_node)
status.name = self.name

return Response (
name = self.name,
token = token,
token = None,
data = pack_to_any(status),
flag = ResponseFlag.EXECUTED_SUCCESSFULLY,
children = [n.get_status(token) for n in self.children_nodes]
children = [],
)


# ORDER MATTERS!
@broadcasted # outer most wrapper 1st step
@authentified_and_authorised(
action=ActionType.READ,
system=SystemType.CONTROLLER
) # 2nd step
@unpack_request_data_to(None) # 3rd step
def ls(self) -> PlainTextVector:
nodes = [node.name for node in self.children_nodes]
response = PlainTextVector(
text = nodes
)

return Response (
name = self.name,
token = None,
data = pack_to_any(response),
flag = ResponseFlag.EXECUTED_SUCCESSFULLY,
children = [],
)


Expand Down
10 changes: 8 additions & 2 deletions src/drunc/controller/controller_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ def describe_fsm(self, key:str=None) -> Description: # key can be: a state name,
input = PlainText(text = key)
return self.send_command('describe_fsm', data = input, outformat = FSMCommandsDescription)

def status(self) -> Description:
return self.send_command('status', outformat = Status)
def ls(self) -> Description:
return self.send_command('ls', outformat = PlainTextVector)

def get_status(self) -> Description:
return self.send_command('get_status', outformat = Status)

def get_children_status(self) -> Description:
return self.send_command('get_children_status', outformat = ChildrenStatus)

def take_control(self) -> Description:
return self.send_command('take_control', outformat = PlainText)
Expand Down
45 changes: 34 additions & 11 deletions src/drunc/controller/interface/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ def list_transitions(obj:ControllerContext, all:bool) -> None:
obj.print('\nUse [yellow]help <command>[/] for more information on a command.\n')



@click.command('ls')
@click.pass_obj
def ls(obj:ControllerContext) -> None:
children = obj.get_driver('controller').ls().data
if not children: return
obj.print(children.text)



@click.command('wait')
@click.argument("sleep_time", type=int, default=1)
@click.pass_obj
Expand All @@ -38,7 +48,7 @@ def wait(obj:ControllerContext, sleep_time:int) -> None:
@click.pass_obj
def status(obj:ControllerContext) -> None:
from druncschema.controller_pb2 import Status, ChildrenStatus
statuses = obj.get_driver('controller').status()
status = obj.get_driver('controller').get_status().data

if not status: return

Expand All @@ -51,18 +61,31 @@ def status(obj:ControllerContext) -> None:
t.add_column('Substate')
t.add_column('In error', justify='center')
t.add_column('Included', justify='center')
t.add_row(
status.name,
status.state,
status.sub_state,
format_bool(status.in_error, false_is_good = True),
format_bool(status.included),
)

def add_status_to_table(status, table, prefix):
table.add_row(
prefix+status.name,
status.data.state,
status.data.sub_state,
format_bool(status.data.in_error, false_is_good = True),
format_bool(status.data.included),
statuses = obj.get_driver('controller').get_children_status().data

if not statuses:
statuses = []

how_many = len(statuses.children_status)

for i, c_status in enumerate(statuses.children_status):
first_column = tree_prefix(i, how_many)+c_status.name

t.add_row(
first_column,
c_status.state,
c_status.sub_state,
format_bool(c_status.in_error, false_is_good=True),
format_bool(c_status.included)
)
for child in status.children:
add_status_to_table(child, table, prefix=prefix+' ')
add_status_to_table(statuses, t, prefix='')
obj.print(t)
obj.print_status_summary()
return
Expand Down
5 changes: 3 additions & 2 deletions src/drunc/controller/interface/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ def controller_shell(ctx, controller_address:str, log_level:str) -> None:
transitions = ctx.obj.get_driver('controller').describe_fsm(key="all-transitions").data

from drunc.controller.interface.commands import (
describe, status, connect, take_control, surrender_control, who_am_i, who_is_in_charge, fsm, include, exclude, wait
list_transitions, ls, status, connect, take_control, surrender_control, who_am_i, who_is_in_charge, fsm, include, exclude, wait
)

ctx.command.add_command(describe, 'describe')
ctx.command.add_command(list_transitions, 'list-transitions')
ctx.command.add_command(ls, 'ls')
ctx.command.add_command(status, 'status')
ctx.command.add_command(connect, 'connect')
ctx.command.add_command(take_control, 'take-control')
Expand Down
4 changes: 2 additions & 2 deletions src/drunc/controller/interface/shell_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ def controller_setup(ctx, controller_address):

ctx.print('Connected to the controller')

# children = ctx.get_driver('controller').ls().data
# ctx.print(f'{desc.name}.{desc.session}\'s children :family:: {children.text}')
children = ctx.get_driver('controller').ls().data
ctx.print(f'{desc.name}.{desc.session}\'s children :family:: {children.text}')

ctx.info(f'Taking control of the controller as {ctx.get_token()}')
try:
Expand Down
5 changes: 3 additions & 2 deletions src/drunc/unified_shell/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,11 @@ def cleanup():


from drunc.controller.interface.commands import (
describe, status, connect, take_control, surrender_control, who_am_i, who_is_in_charge, fsm, include, exclude, wait
list_transitions, ls, status, connect, take_control, surrender_control, who_am_i, who_is_in_charge, fsm, include, exclude, wait
)

ctx.command.add_command(describe, 'describe')
ctx.command.add_command(list_transitions, 'list-transitions')
ctx.command.add_command(ls, 'ls')
ctx.command.add_command(status, 'status')
ctx.command.add_command(connect, 'connect')
ctx.command.add_command(take_control, 'take-control')
Expand Down
13 changes: 7 additions & 6 deletions src/drunc/utils/shell_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def get_driver(self, name:str=None) -> GRPCDriver:
raise DruncShellException(f'More than one driver in this context')
return list(self._drivers.values())[0]
except KeyError:
self._log.error(f'Controller-specific commands cannot be sent until the session is booted')
self._log.error(f'FSM Commands cannot be sent until the Session is booted')
raise SystemExit(1) # used to avoid having to catch multiple Attribute errors when this function gets called

def get_token(self) -> Token:
Expand Down Expand Up @@ -302,12 +302,13 @@ def critical(self, *args, **kwargs) -> None:


def print_status_summary(self) -> None:
status = self.get_driver('controller').status().data
if status.in_error:
self.print(f"[red] FSM is in error ({status})[/red], not currently accepting new commands.")
status = self.get_driver('controller').get_status().data.state
available_actions = [command.name.replace("_", "-") for command in self.get_driver('controller').describe_fsm().data.commands]
if status.find('(') == -1:
self.print(f"Current FSM status is [green]{status}[/green]. Available transitions are [green]{'[/green], [green]'.join(available_actions)}[/green].")
else:
available_actions = [command.name for command in self.get_driver('controller').describe_fsm().data.commands]
self.print(f"Current FSM status is [green]{status.state}[/green]. Available transitions are [green]{'[/green], [green]'.join(available_actions)}[/green].")
self.print(f"[red] FSM is in error ({status})[/red], not currently accepting new commands.")
return


def create_dummy_token_from_uname() -> Token:
Expand Down

0 comments on commit 01ffbdf

Please sign in to comment.