Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor manual agent stop logic #2261

Closed
15 of 16 tasks
mssalvatore opened this issue Sep 8, 2022 · 2 comments · Fixed by #2349
Closed
15 of 16 tasks

Refactor manual agent stop logic #2261

mssalvatore opened this issue Sep 8, 2022 · 2 comments · Fixed by #2349

Comments

@mssalvatore
Copy link
Collaborator

mssalvatore commented Sep 8, 2022

Refactor

Component(s) to be refactored

  • monkey_island.cc.resources.stop_agent_check
  • monkey_island.cc.resources.stop_all_agents

Explanation

In order to know whether or not an agent has been manually killed and should stop, two pieces of information are required:

  1. The time that the user sent the terminate signal
  2. The start time of the agent (if depth == 0) or it's progenitor (if depth > 0)

If the agent or its progenitor was started before the terminate signal was sent, it should stop. The logic looks something like:

def agent_terminated(agent: Agent) -> bool:
    terminate_signal_time = self._simulation_repository.get_simuliation().terminate_signal_time
    if terminate_signal_time is None:
        return False

    progenitor = self._agent_repository.get_progenitor(agent)
    return progenitor.start_time <= stop_time

We can create an AgentSignals model and an AgentSignalsService to retrieve the status of those signals.

Currently, AgentSignals will only contain terminate, but we plan to add a signal to force kill agents in the future. Other signals can be easily added as the need arises.

AgentSignals model

class AgentSignals(InfectionMonkeyBaseModel):
    terminate: Optional[datetime]

AgentSignalsService

class AgentSignalsService:
    def __init__(self, simulation_repository: ISimulationRepository):
        ...

    def get_signals(self, agent: Agent) -> AgentSignals:
        ...

    def on_terminate_agents_signal(self, timestamp: datetime):
        ...

Tasks

  • Add TERMINATE_AGENTS to IslandEventTopic (0d) @ilija-lazoroski
  • Add a field to the Simulation model that contains a timestamp of when the stop button was pressed (0d) @ilija-lazoroski
  • Add new AgentSignalService with stubbed methods that do nothing and/or return dummy data (0d) @ilija-lazoroski
  • Add IAgentRepository.get_progenitor(descendant: Agent) -> agent (0d) @ilija-lazoroski
  • Subscribe AgentSignalsService.on_terminate_agents_signal to TERMINATE_AGENTS events. Update ISimulationRepository with the latest data. (0d) @ilija-lazoroski @cakekoa
  • Implement AgentSignalsService.get_signals() (See above logic to get started) (0d) @mssalvatore
  • Create a new resource for agent signals (/api/agent-signals) @cakekoa, @shreyamalviya (0d)
    • Implement POST /api/agent-signals/terminate-all (accepts a timestamp in the json body)
      • Publish TERMINATE_AGENTS with timestamp to IIslandEventQueue
    • Implement GET /api/agent-signals/<AGENT_ID> that returns AgentSignals
  • Modify the agent's calls to needs-to-stop to call GET /api/agent-signals/<AGENT_ID> (0d) @ilija-lazoroski
    • Add get_agent_signals() to IslandAPIClient
    • Call IslandAPIClient.get_agent_signals() from ControlChannel and check timestamp of terminate signal
  • Modify the UI to call POST /api/agent-signals/terminate-all (0d) - @shreyamalviya
  • Remove monkey_island.cc.resources.agent_controls (0.25d) - @VakarisZ, @mssalvatore
  • Move monkey_island.cc.models.AgentSignals to common (0d) - @ilija-lazoroski

Task dependencies

image

@VakarisZ
Copy link
Contributor

Finding progenitor is relevant only in the case where the shutdown signal travels from UI to island slower than the agent propagates 2 hops. It may be worth it to postpone it if finding a progenitor involves a lot of work. There's also a case when there's no progenitor and depth is not 0. In that case best we can do is just to compare timestamps

@mssalvatore
Copy link
Collaborator Author

mssalvatore commented Sep 13, 2022

Finding the progenitor is simple. Each agent has a reference to it's parent. You just follow them until you find an agent with parent == None.

A simple optimization might be

if agent.timestamp < stop_button_time:
    kill the agent
else:
    check progenitor timestamp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants