mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge pull request #3715 from esaunders/3737_ain_pause_resume
3737 Added pause/resume/shutdown functionality to AID
This commit is contained in:
commit
7a6c8d8a8f
@ -52,6 +52,14 @@ final class AinStatusDashboard extends javax.swing.JPanel implements Observer {
|
|||||||
autoIngestMonitor.addObserver(this);
|
autoIngestMonitor.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AutoIngestMonitor getMonitor() {
|
||||||
|
return autoIngestMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
AinStatusPanel getNodesStatusPanel() {
|
||||||
|
return nodesPanel;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
* WARNING: Do NOT modify this code. The content of this method is always
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
@ -143,9 +151,10 @@ final class AinStatusDashboard extends javax.swing.JPanel implements Observer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
if (arg instanceof AutoIngestNodeState)
|
if (arg instanceof AutoIngestNodeState) {
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
refreshTables();
|
refreshTables();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -74,8 +75,6 @@ final class AinStatusDashboardTopComponent extends TopComponent {
|
|||||||
tc.add(nodeTab);
|
tc.add(nodeTab);
|
||||||
tc.open();
|
tc.open();
|
||||||
}
|
}
|
||||||
tc.toFront();
|
|
||||||
tc.requestActive();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +114,19 @@ final class AinStatusDashboardTopComponent extends TopComponent {
|
|||||||
WindowManager.getDefault().setTopComponentFloating(this, true);
|
WindowManager.getDefault().setTopComponentFloating(this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current AutoIngestDashboard if there is one.
|
||||||
|
*
|
||||||
|
* @return the current AutoIngestDashboard or null if there is not one
|
||||||
|
*/
|
||||||
|
AinStatusDashboard getAinStatusDashboard() {
|
||||||
|
for (Component comp : getComponents()) {
|
||||||
|
if (comp instanceof AinStatusDashboard) {
|
||||||
|
return (AinStatusDashboard) comp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* This method is called from within the constructor to initialize the form.
|
||||||
* WARNING: Do NOT modify this code. The content of this method is always
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
@ -97,6 +97,7 @@ final class AinStatusNode extends AbstractNode {
|
|||||||
@Messages({"AinStatusNode.hostName.title=Host Name",
|
@Messages({"AinStatusNode.hostName.title=Host Name",
|
||||||
"AinStatusNode.status.title=Status",
|
"AinStatusNode.status.title=Status",
|
||||||
"AinStatusNode.status.running=Running",
|
"AinStatusNode.status.running=Running",
|
||||||
|
"AinStatusNode.status.pauseRequested=Pause Requested",
|
||||||
"AinStatusNode.status.pausedByUser=Paused By User",
|
"AinStatusNode.status.pausedByUser=Paused By User",
|
||||||
"AinStatusNode.status.pausedForError=Paused Due to System Error",
|
"AinStatusNode.status.pausedForError=Paused Due to System Error",
|
||||||
"AinStatusNode.status.startingup=Starting Up",
|
"AinStatusNode.status.startingup=Starting Up",
|
||||||
@ -129,6 +130,9 @@ final class AinStatusNode extends AbstractNode {
|
|||||||
case PAUSED_DUE_TO_SYSTEM_ERROR:
|
case PAUSED_DUE_TO_SYSTEM_ERROR:
|
||||||
status = Bundle.AinStatusNode_status_pausedForError();
|
status = Bundle.AinStatusNode_status_pausedForError();
|
||||||
break;
|
break;
|
||||||
|
case PAUSE_REQUESTED:
|
||||||
|
status = Bundle.AinStatusNode_status_pauseRequested();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -142,12 +146,11 @@ final class AinStatusNode extends AbstractNode {
|
|||||||
List<Action> actions = new ArrayList<>();
|
List<Action> actions = new ArrayList<>();
|
||||||
if (AutoIngestDashboard.isAdminAutoIngestDashboard()) {
|
if (AutoIngestDashboard.isAdminAutoIngestDashboard()) {
|
||||||
if (nodeState.getState() == AutoIngestNodeState.State.PAUSED_BY_REQUEST
|
if (nodeState.getState() == AutoIngestNodeState.State.PAUSED_BY_REQUEST
|
||||||
|| nodeState.getState() == AutoIngestNodeState.State.PAUSED_DUE_TO_SYSTEM_ERROR) {
|
|| nodeState.getState() == AutoIngestNodeState.State.PAUSED_DUE_TO_SYSTEM_ERROR
|
||||||
actions.add(new AutoIngestAdminActions.ResumeAction());
|
|| nodeState.getState() == AutoIngestNodeState.State.RUNNING) {
|
||||||
} else if (nodeState.getState() == AutoIngestNodeState.State.RUNNING){
|
actions.add(new AutoIngestAdminActions.AutoIngestNodeControlAction.PauseResumeAction(nodeState));
|
||||||
actions.add(new AutoIngestAdminActions.PauseAction());
|
|
||||||
}
|
}
|
||||||
actions.add(new AutoIngestAdminActions.ShutdownAction());
|
actions.add(new AutoIngestAdminActions.AutoIngestNodeControlAction.ShutdownAction(nodeState));
|
||||||
}
|
}
|
||||||
return actions.toArray(new Action[actions.size()]);
|
return actions.toArray(new Action[actions.size()]);
|
||||||
}
|
}
|
||||||
|
@ -99,12 +99,12 @@ final class AinStatusPanel extends javax.swing.JPanel implements ExplorerManager
|
|||||||
void refresh(AutoIngestMonitor monitor) {
|
void refresh(AutoIngestMonitor monitor) {
|
||||||
outline.setRowSelectionAllowed(false);
|
outline.setRowSelectionAllowed(false);
|
||||||
Node[] selectedNodes = explorerManager.getSelectedNodes();
|
Node[] selectedNodes = explorerManager.getSelectedNodes();
|
||||||
AinStatusNode autoIngestNode = new AinStatusNode(monitor);
|
AinStatusNode ainStatusNode = new AinStatusNode(monitor);
|
||||||
explorerManager.setRootContext(autoIngestNode);
|
explorerManager.setRootContext(ainStatusNode);
|
||||||
outline.setRowSelectionAllowed(true);
|
outline.setRowSelectionAllowed(true);
|
||||||
if (selectedNodes.length > 0 && autoIngestNode.getChildren().findChild(selectedNodes[0].getName()) != null && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
|
if (selectedNodes.length > 0 && ainStatusNode.getChildren().findChild(selectedNodes[0].getName()) != null && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
|
||||||
try {
|
try {
|
||||||
explorerManager.setSelectedNodes(new Node[]{autoIngestNode.getChildren().findChild(selectedNodes[0].getName())});
|
explorerManager.setSelectedNodes(new Node[]{ainStatusNode.getChildren().findChild(selectedNodes[0].getName())});
|
||||||
} catch (PropertyVetoException ignore) {
|
} catch (PropertyVetoException ignore) {
|
||||||
//Unable to select previously selected node
|
//Unable to select previously selected node
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,122 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.awt.Cursor;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.logging.Level;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.windows.WindowManager;
|
import org.openide.windows.WindowManager;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.AutoIngestNodeState;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
|
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
|
||||||
|
|
||||||
final class AutoIngestAdminActions {
|
final class AutoIngestAdminActions {
|
||||||
|
|
||||||
|
static abstract class AutoIngestNodeControlAction extends AbstractAction {
|
||||||
|
|
||||||
|
private final AutoIngestNodeState nodeState;
|
||||||
|
private final Logger logger = Logger.getLogger(AutoIngestNodeControlAction.class.getName());
|
||||||
|
|
||||||
|
AutoIngestNodeControlAction(AutoIngestNodeState nodeState, String title) {
|
||||||
|
super(title);
|
||||||
|
this.nodeState = nodeState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (nodeState != null) {
|
||||||
|
final AinStatusDashboardTopComponent tc = (AinStatusDashboardTopComponent) WindowManager.getDefault().findTopComponent(AinStatusDashboardTopComponent.PREFERRED_ID);
|
||||||
|
if (tc != null) {
|
||||||
|
AinStatusDashboard dashboard = tc.getAinStatusDashboard();
|
||||||
|
if (dashboard != null) {
|
||||||
|
dashboard.getNodesStatusPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
|
EventQueue.invokeLater(() -> {
|
||||||
|
try {
|
||||||
|
controlAutoIngestNode(dashboard);
|
||||||
|
} catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
|
||||||
|
logger.log(Level.WARNING, "Error sending control event to node", ex);
|
||||||
|
} finally {
|
||||||
|
dashboard.getNodesStatusPanel().setCursor(Cursor.getDefaultCursor());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void controlAutoIngestNode(AinStatusDashboard dashboard) throws AutoIngestMonitor.AutoIngestMonitorException;
|
||||||
|
|
||||||
|
AutoIngestNodeState getNodeState() {
|
||||||
|
return nodeState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"AutoIngestAdminActions.pause.title=Pause Node",
|
||||||
|
"AutoIngestAdminActions.resume.title=Resume Node"})
|
||||||
|
static final class PauseResumeAction extends AutoIngestNodeControlAction {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
PauseResumeAction(AutoIngestNodeState nodeState) {
|
||||||
|
super(nodeState, nodeState.getState() == AutoIngestNodeState.State.RUNNING
|
||||||
|
? Bundle.AutoIngestAdminActions_pause_title() : Bundle.AutoIngestAdminActions_resume_title());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone(); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void controlAutoIngestNode(AinStatusDashboard dashboard) throws AutoIngestMonitor.AutoIngestMonitorException {
|
||||||
|
if (getNodeState().getState() == AutoIngestNodeState.State.RUNNING) {
|
||||||
|
dashboard.getMonitor().pauseAutoIngestNode(getNodeState().getName());
|
||||||
|
} else {
|
||||||
|
dashboard.getMonitor().resumeAutoIngestNode(getNodeState().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"AutoIngestAdminActions.shutdown.title=Shutdown Node",
|
||||||
|
"AutoIngestAdminActions.shutdown.OK=OK", "AutoIngestAdminActions.shutdown.Cancel=Cancel",
|
||||||
|
"AutoIngestAdminActions.shutdown.consequences=This will cancel any currently running job on this host. Exiting while a job is running potentially leaves the case in an inconsistent or corrupted state."})
|
||||||
|
static final class ShutdownAction extends AutoIngestNodeControlAction {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
ShutdownAction(AutoIngestNodeState nodeState) {
|
||||||
|
super(nodeState, Bundle.AutoIngestAdminActions_shutdown_title());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone(); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void controlAutoIngestNode(AinStatusDashboard dashboard) throws AutoIngestMonitor.AutoIngestMonitorException {
|
||||||
|
Object[] options = {Bundle.AutoIngestAdminActions_shutdown_OK(),
|
||||||
|
Bundle.AutoIngestAdminActions_shutdown_Cancel()
|
||||||
|
};
|
||||||
|
|
||||||
|
int reply = JOptionPane.showOptionDialog(dashboard.getNodesStatusPanel(),
|
||||||
|
Bundle.AutoIngestAdminActions_shutdown_consequences(),
|
||||||
|
NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.ConfirmExitHeader"),
|
||||||
|
JOptionPane.DEFAULT_OPTION,
|
||||||
|
JOptionPane.WARNING_MESSAGE,
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
options[JOptionPane.NO_OPTION]);
|
||||||
|
|
||||||
|
if (reply == JOptionPane.OK_OPTION) {
|
||||||
|
dashboard.getMonitor().shutdownAutoIngestNode(getNodeState().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({"AutoIngestAdminActions.progressDialogAction.title=Ingest Progress"})
|
@NbBundle.Messages({"AutoIngestAdminActions.progressDialogAction.title=Ingest Progress"})
|
||||||
static final class ProgressDialogAction extends AbstractAction {
|
static final class ProgressDialogAction extends AbstractAction {
|
||||||
|
|
||||||
@ -152,65 +260,4 @@ final class AutoIngestAdminActions {
|
|||||||
return super.clone(); //To change body of generated methods, choose Tools | Templates.
|
return super.clone(); //To change body of generated methods, choose Tools | Templates.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({"AutoIngestAdminActions.pause.title=Pause Node"})
|
|
||||||
static final class PauseAction extends AbstractAction {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
PauseAction() {
|
|
||||||
super(Bundle.AutoIngestAdminActions_pause_title());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
//TODO JIRA-
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object clone() throws CloneNotSupportedException {
|
|
||||||
return super.clone(); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NbBundle.Messages({"AutoIngestAdminActions.resume.title=Resume Node"})
|
|
||||||
static final class ResumeAction extends AbstractAction {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
ResumeAction() {
|
|
||||||
super(Bundle.AutoIngestAdminActions_resume_title());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
//TODO JIRA-
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object clone() throws CloneNotSupportedException {
|
|
||||||
return super.clone(); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NbBundle.Messages({"AutoIngestAdminActions.shutdown.title=Shutdown Node"})
|
|
||||||
static final class ShutdownAction extends AbstractAction {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
ShutdownAction() {
|
|
||||||
super(Bundle.AutoIngestAdminActions_shutdown_title());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
//TODO JIRA-
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object clone() throws CloneNotSupportedException {
|
|
||||||
return super.clone(); //To change body of generated methods, choose Tools | Templates.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -852,7 +852,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
|||||||
case CASE_DELETED:
|
case CASE_DELETED:
|
||||||
updateExecutor.submit(new UpdateAllJobsTablesTask());
|
updateExecutor.submit(new UpdateAllJobsTablesTask());
|
||||||
break;
|
break;
|
||||||
case PAUSED_BY_REQUEST:
|
case PAUSED_BY_USER_REQUEST:
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.paused"));
|
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.paused"));
|
||||||
bnOptions.setEnabled(true);
|
bnOptions.setEnabled(true);
|
||||||
@ -881,6 +881,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
|||||||
case JOB_STATUS_UPDATED:
|
case JOB_STATUS_UPDATED:
|
||||||
updateExecutor.submit(new UpdateRunningJobsTablesTask());
|
updateExecutor.submit(new UpdateRunningJobsTablesTask());
|
||||||
break;
|
break;
|
||||||
|
case SHUTTING_DOWN:
|
||||||
|
LifecycleManager.getDefault().exit();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa
|
|||||||
AutoIngestJobsNode autoIngestNode = new AutoIngestJobsNode(jobsSnapshot, status);
|
AutoIngestJobsNode autoIngestNode = new AutoIngestJobsNode(jobsSnapshot, status);
|
||||||
explorerManager.setRootContext(autoIngestNode);
|
explorerManager.setRootContext(autoIngestNode);
|
||||||
outline.setRowSelectionAllowed(true);
|
outline.setRowSelectionAllowed(true);
|
||||||
if (selectedNodes.length > 0 && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
|
if (selectedNodes.length > 0 && autoIngestNode.getChildren().findChild(selectedNodes[0].getName()) != null && outline.isFocusable()) { //don't allow saved selections of empty nodes to be restored
|
||||||
try {
|
try {
|
||||||
explorerManager.setSelectedNodes(new Node[]{autoIngestNode.getChildren().findChild(selectedNodes[0].getName())});
|
explorerManager.setSelectedNodes(new Node[]{autoIngestNode.getChildren().findChild(selectedNodes[0].getName())});
|
||||||
} catch (PropertyVetoException ignore) {
|
} catch (PropertyVetoException ignore) {
|
||||||
|
@ -93,6 +93,7 @@ import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.Shar
|
|||||||
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
|
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
|
||||||
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
|
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
|
||||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.AutoIngestJobException;
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.AutoIngestJobException;
|
||||||
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestNodeControlEvent.ControlEventType;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestJob;
|
import org.sleuthkit.autopsy.ingest.IngestJob;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
|
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
||||||
@ -133,7 +134,10 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
Event.JOB_COMPLETED.toString(),
|
Event.JOB_COMPLETED.toString(),
|
||||||
Event.CASE_PRIORITIZED.toString(),
|
Event.CASE_PRIORITIZED.toString(),
|
||||||
Event.JOB_STARTED.toString(),
|
Event.JOB_STARTED.toString(),
|
||||||
Event.REPORT_STATE.toString()}));
|
Event.REPORT_STATE.toString(),
|
||||||
|
ControlEventType.PAUSE.toString(),
|
||||||
|
ControlEventType.RESUME.toString(),
|
||||||
|
ControlEventType.SHUTDOWN.toString()}));
|
||||||
private static final long JOB_STATUS_EVENT_INTERVAL_SECONDS = 10;
|
private static final long JOB_STATUS_EVENT_INTERVAL_SECONDS = 10;
|
||||||
private static final String JOB_STATUS_PUBLISHING_THREAD_NAME = "AIM-job-status-event-publisher-%d";
|
private static final String JOB_STATUS_PUBLISHING_THREAD_NAME = "AIM-job-status-event-publisher-%d";
|
||||||
private static final long MAX_MISSED_JOB_STATUS_UPDATES = 10;
|
private static final long MAX_MISSED_JOB_STATUS_UPDATES = 10;
|
||||||
@ -281,6 +285,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
handleRemoteCaseDeletedEvent((AutoIngestCaseDeletedEvent) event);
|
handleRemoteCaseDeletedEvent((AutoIngestCaseDeletedEvent) event);
|
||||||
} else if (event instanceof AutoIngestRequestNodeStateEvent) {
|
} else if (event instanceof AutoIngestRequestNodeStateEvent) {
|
||||||
handleRemoteRequestNodeStateEvent();
|
handleRemoteRequestNodeStateEvent();
|
||||||
|
} else if (event instanceof AutoIngestNodeControlEvent) {
|
||||||
|
handleRemoteNodeControlEvent((AutoIngestNodeControlEvent) event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,6 +410,28 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
eventPublisher.publishRemotely(lastPublishedStateEvent);
|
eventPublisher.publishRemotely(lastPublishedStateEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleRemoteNodeControlEvent(AutoIngestNodeControlEvent event) {
|
||||||
|
if (event.getNodeName().compareToIgnoreCase(LOCAL_HOST_NAME) == 0) {
|
||||||
|
switch (event.getControlEventType()) {
|
||||||
|
case PAUSE:
|
||||||
|
pause();
|
||||||
|
break;
|
||||||
|
case RESUME:
|
||||||
|
resume();
|
||||||
|
break;
|
||||||
|
case SHUTDOWN:
|
||||||
|
shutDown();
|
||||||
|
// Notify the front end (if any) to shutdown.
|
||||||
|
setChanged();
|
||||||
|
notifyObservers(Event.SHUTTING_DOWN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SYS_LOGGER.log(Level.WARNING, "Received unsupported control event: {0}", event.getControlEventType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuts down auto ingest.
|
* Shuts down auto ingest.
|
||||||
*/
|
*/
|
||||||
@ -418,6 +446,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
eventPublisher.removeSubscriber(EVENT_LIST, instance);
|
eventPublisher.removeSubscriber(EVENT_LIST, instance);
|
||||||
stopInputFolderScans();
|
stopInputFolderScans();
|
||||||
stopJobProcessing();
|
stopJobProcessing();
|
||||||
|
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.SHUTDOWN, AutoIngestManager.LOCAL_HOST_NAME));
|
||||||
eventPublisher.closeRemoteEventChannel();
|
eventPublisher.closeRemoteEventChannel();
|
||||||
cleanupJobs();
|
cleanupJobs();
|
||||||
|
|
||||||
@ -1695,14 +1724,13 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
* object.
|
* object.
|
||||||
*/
|
*/
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers(Event.PAUSED_BY_REQUEST);
|
notifyObservers(Event.PAUSED_BY_USER_REQUEST);
|
||||||
|
|
||||||
/**
|
|
||||||
* Publish an event to let remote listeners know that the
|
|
||||||
* node has been paused.
|
|
||||||
*/
|
|
||||||
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.PAUSED_BY_REQUEST, AutoIngestManager.LOCAL_HOST_NAME));
|
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Publish an event to let remote listeners know that a pause
|
||||||
|
* has been requested.
|
||||||
|
*/
|
||||||
|
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.PAUSE_REQUESTED, AutoIngestManager.LOCAL_HOST_NAME));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1745,18 +1773,22 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
* if auto ingest is shutting down.
|
* if auto ingest is shutting down.
|
||||||
*/
|
*/
|
||||||
private void pauseIfRequested() throws InterruptedException {
|
private void pauseIfRequested() throws InterruptedException {
|
||||||
|
if (State.SHUTTING_DOWN == state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (pauseLock) {
|
synchronized (pauseLock) {
|
||||||
if (pauseRequested) {
|
if (pauseRequested) {
|
||||||
SYS_LOGGER.log(Level.INFO, "Job processing paused by request");
|
SYS_LOGGER.log(Level.INFO, "Job processing paused by request");
|
||||||
pauseRequested = false;
|
pauseRequested = false;
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers(Event.PAUSED_BY_REQUEST);
|
notifyObservers(Event.PAUSED_BY_USER_REQUEST);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publish an event to let remote listeners know that the
|
* Publish an event to let remote listeners know that the
|
||||||
* node has been paused.
|
* node has been paused.
|
||||||
*/
|
*/
|
||||||
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.PAUSED_BY_REQUEST, AutoIngestManager.LOCAL_HOST_NAME));
|
eventPublisher.publishRemotely(lastPublishedStateEvent = new AutoIngestNodeStateEvent(Event.PAUSED_BY_USER_REQUEST, AutoIngestManager.LOCAL_HOST_NAME));
|
||||||
|
|
||||||
pauseLock.wait();
|
pauseLock.wait();
|
||||||
SYS_LOGGER.log(Level.INFO, "Job processing resumed after pause request");
|
SYS_LOGGER.log(Level.INFO, "Job processing resumed after pause request");
|
||||||
@ -1780,6 +1812,10 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
* if auto ingest is shutting down.
|
* if auto ingest is shutting down.
|
||||||
*/
|
*/
|
||||||
private void pauseForSystemError() throws InterruptedException {
|
private void pauseForSystemError() throws InterruptedException {
|
||||||
|
if (State.SHUTTING_DOWN == state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (pauseLock) {
|
synchronized (pauseLock) {
|
||||||
SYS_LOGGER.log(Level.SEVERE, "Job processing paused for system error");
|
SYS_LOGGER.log(Level.SEVERE, "Job processing paused for system error");
|
||||||
setChanged();
|
setChanged();
|
||||||
@ -3061,12 +3097,14 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
|||||||
JOB_COMPLETED,
|
JOB_COMPLETED,
|
||||||
CASE_PRIORITIZED,
|
CASE_PRIORITIZED,
|
||||||
CASE_DELETED,
|
CASE_DELETED,
|
||||||
PAUSED_BY_REQUEST,
|
PAUSE_REQUESTED,
|
||||||
|
PAUSED_BY_USER_REQUEST,
|
||||||
PAUSED_FOR_SYSTEM_ERROR,
|
PAUSED_FOR_SYSTEM_ERROR,
|
||||||
RESUMED,
|
RESUMED,
|
||||||
STARTING_UP,
|
STARTING_UP,
|
||||||
RUNNING,
|
RUNNING,
|
||||||
SHUTTING_DOWN,
|
SHUTTING_DOWN,
|
||||||
|
SHUTDOWN,
|
||||||
REPORT_STATE
|
REPORT_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ import org.sleuthkit.autopsy.events.AutopsyEventException;
|
|||||||
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
||||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingStatus;
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingStatus;
|
||||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.Event;
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.Event;
|
||||||
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestNodeControlEvent.ControlEventType;
|
||||||
/**
|
/**
|
||||||
* An auto ingest monitor responsible for monitoring and reporting the
|
* An auto ingest monitor responsible for monitoring and reporting the
|
||||||
* processing of auto ingest jobs.
|
* processing of auto ingest jobs.
|
||||||
@ -61,10 +62,12 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
|||||||
AutoIngestManager.Event.CASE_PRIORITIZED.toString(),
|
AutoIngestManager.Event.CASE_PRIORITIZED.toString(),
|
||||||
AutoIngestManager.Event.JOB_STARTED.toString(),
|
AutoIngestManager.Event.JOB_STARTED.toString(),
|
||||||
AutoIngestManager.Event.RUNNING.toString(),
|
AutoIngestManager.Event.RUNNING.toString(),
|
||||||
AutoIngestManager.Event.PAUSED_BY_REQUEST.toString(),
|
AutoIngestManager.Event.PAUSE_REQUESTED.toString(),
|
||||||
|
AutoIngestManager.Event.PAUSED_BY_USER_REQUEST.toString(),
|
||||||
AutoIngestManager.Event.PAUSED_FOR_SYSTEM_ERROR.toString(),
|
AutoIngestManager.Event.PAUSED_FOR_SYSTEM_ERROR.toString(),
|
||||||
AutoIngestManager.Event.STARTING_UP.toString(),
|
AutoIngestManager.Event.STARTING_UP.toString(),
|
||||||
AutoIngestManager.Event.SHUTTING_DOWN.toString(),
|
AutoIngestManager.Event.SHUTTING_DOWN.toString(),
|
||||||
|
AutoIngestManager.Event.SHUTDOWN.toString(),
|
||||||
AutoIngestManager.Event.RESUMED.toString()}));
|
AutoIngestManager.Event.RESUMED.toString()}));
|
||||||
private final AutopsyEventPublisher eventPublisher;
|
private final AutopsyEventPublisher eventPublisher;
|
||||||
private CoordinationService coordinationService;
|
private CoordinationService coordinationService;
|
||||||
@ -221,9 +224,10 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
|||||||
* @param event A node state change event.
|
* @param event A node state change event.
|
||||||
*/
|
*/
|
||||||
private void handleAutoIngestNodeStateEvent(AutoIngestNodeStateEvent event) {
|
private void handleAutoIngestNodeStateEvent(AutoIngestNodeStateEvent event) {
|
||||||
if (event.getEventType() == AutoIngestManager.Event.SHUTTING_DOWN) {
|
AutoIngestNodeState oldNodeState = null;
|
||||||
|
if (event.getEventType() == AutoIngestManager.Event.SHUTDOWN) {
|
||||||
// Remove node from collection.
|
// Remove node from collection.
|
||||||
nodeStates.remove(event.getNodeName());
|
oldNodeState = nodeStates.remove(event.getNodeName());
|
||||||
} else {
|
} else {
|
||||||
// Otherwise either create an entry for the given node name or update
|
// Otherwise either create an entry for the given node name or update
|
||||||
// an existing entry in the map.
|
// an existing entry in the map.
|
||||||
@ -231,7 +235,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
|||||||
}
|
}
|
||||||
setChanged();
|
setChanged();
|
||||||
// Trigger a dashboard refresh.
|
// Trigger a dashboard refresh.
|
||||||
notifyObservers(nodeStates.get(event.getNodeName()));
|
notifyObservers(oldNodeState == null ? nodeStates.get(event.getNodeName()) : oldNodeState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -522,6 +526,45 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given control event to the given node.
|
||||||
|
*
|
||||||
|
* @param eventType The type of control event to send.
|
||||||
|
* @param nodeName The name of the node to send it to.
|
||||||
|
*/
|
||||||
|
private void sendControlEventToNode(ControlEventType eventType, String nodeName) {
|
||||||
|
new Thread(() -> {
|
||||||
|
eventPublisher.publishRemotely(new AutoIngestNodeControlEvent(eventType, nodeName));
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the specified node to pause.
|
||||||
|
*
|
||||||
|
* @param nodeName
|
||||||
|
*/
|
||||||
|
void pauseAutoIngestNode(String nodeName) {
|
||||||
|
sendControlEventToNode(ControlEventType.PAUSE, nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the specified node to resume.
|
||||||
|
*
|
||||||
|
* @param nodeName
|
||||||
|
*/
|
||||||
|
void resumeAutoIngestNode(String nodeName) {
|
||||||
|
sendControlEventToNode(ControlEventType.RESUME, nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the specified node to shutdown.
|
||||||
|
*
|
||||||
|
* @param nodeName
|
||||||
|
*/
|
||||||
|
void shutdownAutoIngestNode(String nodeName) {
|
||||||
|
sendControlEventToNode(ControlEventType.SHUTDOWN, nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A task that queries the coordination service for auto ingest manifest
|
* A task that queries the coordination service for auto ingest manifest
|
||||||
* node data and converts it to auto ingest jobs for publication top its
|
* node data and converts it to auto ingest jobs for publication top its
|
||||||
@ -677,6 +720,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
|||||||
STARTING_UP,
|
STARTING_UP,
|
||||||
SHUTTING_DOWN,
|
SHUTTING_DOWN,
|
||||||
RUNNING,
|
RUNNING,
|
||||||
|
PAUSE_REQUESTED,
|
||||||
PAUSED_BY_REQUEST,
|
PAUSED_BY_REQUEST,
|
||||||
PAUSED_DUE_TO_SYSTEM_ERROR,
|
PAUSED_DUE_TO_SYSTEM_ERROR,
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
@ -697,7 +741,7 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
|||||||
case RUNNING:
|
case RUNNING:
|
||||||
nodeState = State.RUNNING;
|
nodeState = State.RUNNING;
|
||||||
break;
|
break;
|
||||||
case PAUSED_BY_REQUEST:
|
case PAUSED_BY_USER_REQUEST:
|
||||||
nodeState = State.PAUSED_BY_REQUEST;
|
nodeState = State.PAUSED_BY_REQUEST;
|
||||||
break;
|
break;
|
||||||
case PAUSED_FOR_SYSTEM_ERROR:
|
case PAUSED_FOR_SYSTEM_ERROR:
|
||||||
@ -706,6 +750,9 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
|
|||||||
case RESUMED:
|
case RESUMED:
|
||||||
nodeState = State.RUNNING;
|
nodeState = State.RUNNING;
|
||||||
break;
|
break;
|
||||||
|
case PAUSE_REQUESTED:
|
||||||
|
nodeState = State.PAUSE_REQUESTED;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
nodeState = State.UNKNOWN;
|
nodeState = State.UNKNOWN;
|
||||||
break;
|
break;
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2018 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event published to pause, resume or shutdown an AIN.
|
||||||
|
*/
|
||||||
|
final class AutoIngestNodeControlEvent extends AutopsyEvent implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of available controls.
|
||||||
|
*/
|
||||||
|
enum ControlEventType {
|
||||||
|
PAUSE,
|
||||||
|
RESUME,
|
||||||
|
SHUTDOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final String nodeName;
|
||||||
|
private final ControlEventType eventType;
|
||||||
|
|
||||||
|
AutoIngestNodeControlEvent(ControlEventType eventType, String nodeName) {
|
||||||
|
super(eventType.toString(), null, null);
|
||||||
|
this.eventType = eventType;
|
||||||
|
this.nodeName = nodeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getNodeName() {
|
||||||
|
return nodeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlEventType getControlEventType() {
|
||||||
|
return eventType;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user