Merge pull request #4690 from rcordovano/4922-delete-orphan-manifest-nodes

4922 delete orphan manifest nodes
This commit is contained in:
Richard Cordovano 2019-04-09 15:51:31 -04:00 committed by GitHub
commit 4e3530e3c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 414 additions and 64 deletions

View File

@ -0,0 +1,58 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 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.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Collects the auto ingest job node data stored in the manifest file
* coordination service nodes.
*/
final class AutoIngestJobNodeDataCollector {
private static final Logger logger = Logger.getLogger(AutoIngestJobNodeDataCollector.class.getName());
static List<AutoIngestJobNodeData> getNodeData() throws CoordinationServiceException, InterruptedException {
final CoordinationService coordinationService = CoordinationService.getInstance();
final List<String> nodePaths = coordinationService.getNodeList(CoordinationService.CategoryNode.MANIFESTS);
final List<AutoIngestJobNodeData> nodeDataList = new ArrayList<>();
for (String nodePath : nodePaths) {
try {
final byte[] nodeBytes = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, nodePath);
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(nodeBytes);
nodeDataList.add(nodeData);
} catch (AutoIngestJobNodeData.InvalidDataException ex) {
logger.log(Level.WARNING, String.format("Error reading node data from manifest file coordination service node %s", nodePath), ex); // NON-NLS
}
}
return nodeDataList;
}
/**
* Prevents instantiation of this utility class.
*/
private AutoIngestJobNodeDataCollector() {
}
}

View File

@ -19,39 +19,60 @@
package org.sleuthkit.autopsy.experimental.autoingest;
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import javax.swing.AbstractAction;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.progress.AppFrameProgressBar;
import org.sleuthkit.autopsy.progress.ProgressIndicator;
import org.sleuthkit.autopsy.progress.TaskCancellable;
/**
* An action class that kicks off a cancellable case nodes cleanup task that
* runs in a background thread and reports progress using an application frame
* progress bar.
* A base class for action classes that kick off a cancellable task that runs in
* a background thread and reports progress using an application frame progress
* bar.
*/
final class CaseNodesCleanupAction extends AbstractAction {
abstract class BackgroundTaskAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private final String progressDisplayName;
/**
* Constructs the base class part of action classes that kick off a
* cancellable task that runs in a background thread and reports progress
* using an application frame progress bar.
*
* @param actionName The name of the action.
* @param progressDisplayName The display name for the progress bar.
*/
BackgroundTaskAction(String actionName, String progressDisplayName) {
super(actionName);
this.progressDisplayName = progressDisplayName;
}
@Override
@NbBundle.Messages({
"CaseNodesCleanupAction.progressDisplayName=Cleanup Case Znodes"
})
public void actionPerformed(ActionEvent event) {
final AppFrameProgressBar progress = new AppFrameProgressBar(Bundle.CaseNodesCleanupAction_progressDisplayName());
final AppFrameProgressBar progress = new AppFrameProgressBar(progressDisplayName);
final TaskCancellable taskCanceller = new TaskCancellable(progress);
progress.setCancellationBehavior(taskCanceller);
final Runnable task = new CaseNodesCleanupTask(progress);
final Runnable task = getTask(progress);
final FutureTask<Void> future = new FutureTask<>(task, null);
taskCanceller.setFuture(future);
new Thread(future).start();
}
/**
* Gets the background task to be executed. The task is expected to report
* its progress using the supplied progress indicator and to check for
* cancellation by checking to see if the thread it is running in has been
* interrupted.
*
* @param progress A progress indicator for the task.
*
* @return The Runnnable task.
*/
abstract Runnable getTask(ProgressIndicator progress);
@Override
public CaseNodesCleanupAction clone() throws CloneNotSupportedException {
public BackgroundTaskAction clone() throws CloneNotSupportedException {
super.clone();
throw new CloneNotSupportedException();
}

View File

@ -255,4 +255,5 @@ AinStatusDashboard.nodeStatusTableTitle.text=Auto Ingest Nodes
AinStatusDashboard.healthMonitorButton.text=Health Monitor
CasesDashboardTopComponent.refreshButton.text=Refresh
AutoIngestCasesDeletionDialog.jLabel1.text=Progress
CasesDashboardTopComponent.cleanCaseNodesButton.text=Clean Case Znodes
CasesDashboardTopComponent.deleteOrphanCaseNodesButton.text=Delete Orphan Case Znodes
CasesDashboardTopComponent.deleteOrphanManifestNodesButton.text=Delete Orphan Manifest Znodes

View File

@ -138,12 +138,6 @@ AutoIngestJobsNode.status.text=Status
AutoIngestJobsPanel.waitNode.text=Please Wait...
AutoIngestMetricsDialog.initReportText=Select a date above and click the 'Generate Metrics Report' button to generate\na metrics report.
AutoIngestMetricsDialog.title.text=Auto Ingest Metrics
CaseNodesCleanupAction.progressDisplayName=Cleanup Case Znodes
CaseNodesCleanupTask.progress.connectingToCoordSvc=Connecting to the coordination service...
# {0} - node path
CaseNodesCleanupTask.progress.deletingOrphanedCaseNode=Deleting orphaned case node {0}...
CaseNodesCleanupTask.progress.gettingCaseNodesListing=Querying coordination service for case nodes...
CaseNodesCleanupTask.progress.startMessage=Starting orphaned case znode cleanup...
ConfirmationDialog.DoNotDelete=Do not delete
ConfirmationDialog.Delete=Permanently delete
ConfirmationDialog.DeleteAreYouSure=The entire case will be removed. Are you sure you want to delete case
@ -210,6 +204,18 @@ DeleteCaseTask.progress.parsingManifest=Parsing manifest file {0}...
# {0} - manifest file path
DeleteCaseTask.progress.releasingManifestLock=Releasing lock on the manifest file {0}...
DeleteCaseTask.progress.startMessage=Starting deletion...
DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes
DeleteOrphanCaseNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service
# {0} - node path
DeleteOrphanCaseNodesTask.progress.deletingOrphanedCaseNode=Deleting orphaned case znode {0}
DeleteOrphanCaseNodesTask.progress.gettingCaseNodesListing=Querying coordination service for case znodes
DeleteOrphanCaseNodesTask.progress.startMessage=Starting orphaned case znode cleanup
DeleteOrphanManifestNodesAction.progressDisplayName=Cleanup Manifest File Znodes
DeleteOrphanManifestNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service
# {0} - node path
DeleteOrphanManifestNodesTask.progress.deletingOrphanedManifestNode=Deleting orphaned manifest file znode {0}
DeleteOrphanManifestNodesTask.progress.gettingManifestNodes=Querying the coordination service for manifest file znodes
DeleteOrphanManifestNodesTask.progress.startMessage=Starting orphaned manifest file znode cleanup
HINT_CasesDashboardTopComponent=This is an adminstrative dashboard for multi-user cases
OpenAutoIngestLogAction.deletedLogErrorMsg=The case auto ingest log has been deleted.
OpenAutoIngestLogAction.logOpenFailedErrorMsg=Failed to open case auto ingest log. See application log for details.
@ -446,4 +452,5 @@ AinStatusDashboard.nodeStatusTableTitle.text=Auto Ingest Nodes
AinStatusDashboard.healthMonitorButton.text=Health Monitor
CasesDashboardTopComponent.refreshButton.text=Refresh
AutoIngestCasesDeletionDialog.jLabel1.text=Progress
CasesDashboardTopComponent.cleanCaseNodesButton.text=Clean Case Znodes
CasesDashboardTopComponent.deleteOrphanCaseNodesButton.text=Delete Orphan Case Znodes
CasesDashboardTopComponent.deleteOrphanManifestNodesButton.text=Delete Orphan Manifest Znodes

View File

@ -20,10 +20,12 @@
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>
<Component id="refreshButton" linkSize="3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cleanCaseNodesButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="313" max="32767" attributes="0"/>
<Component id="deleteOrphanCaseNodesButton" linkSize="3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteOrphanManifestNodesButton" linkSize="3" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="caseBrowserScrollPane" max="32767" attributes="0"/>
@ -40,8 +42,9 @@
<Component id="caseBrowserScrollPane" pref="246" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="refreshButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cleanCaseNodesButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="refreshButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteOrphanCaseNodesButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteOrphanManifestNodesButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -63,14 +66,24 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
<Component class="javax.swing.JButton" name="cleanCaseNodesButton">
<Component class="javax.swing.JButton" name="deleteOrphanCaseNodesButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="CasesDashboardTopComponent.cleanCaseNodesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="CasesDashboardTopComponent.deleteOrphanCaseNodesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cleanCaseNodesButtonActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteOrphanCaseNodesButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="deleteOrphanManifestNodesButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="CasesDashboardTopComponent.deleteOrphanManifestNodesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteOrphanManifestNodesButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>

View File

@ -119,7 +119,8 @@ public final class CasesDashboardTopComponent extends TopComponent implements Ex
refreshButton = new javax.swing.JButton();
caseBrowserScrollPane = new javax.swing.JScrollPane();
cleanCaseNodesButton = new javax.swing.JButton();
deleteOrphanCaseNodesButton = new javax.swing.JButton();
deleteOrphanManifestNodesButton = new javax.swing.JButton();
org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(CasesDashboardTopComponent.class, "CasesDashboardTopComponent.refreshButton.text")); // NOI18N
refreshButton.addActionListener(new java.awt.event.ActionListener() {
@ -128,10 +129,17 @@ public final class CasesDashboardTopComponent extends TopComponent implements Ex
}
});
org.openide.awt.Mnemonics.setLocalizedText(cleanCaseNodesButton, org.openide.util.NbBundle.getMessage(CasesDashboardTopComponent.class, "CasesDashboardTopComponent.cleanCaseNodesButton.text")); // NOI18N
cleanCaseNodesButton.addActionListener(new java.awt.event.ActionListener() {
org.openide.awt.Mnemonics.setLocalizedText(deleteOrphanCaseNodesButton, org.openide.util.NbBundle.getMessage(CasesDashboardTopComponent.class, "CasesDashboardTopComponent.deleteOrphanCaseNodesButton.text")); // NOI18N
deleteOrphanCaseNodesButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cleanCaseNodesButtonActionPerformed(evt);
deleteOrphanCaseNodesButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(deleteOrphanManifestNodesButton, org.openide.util.NbBundle.getMessage(CasesDashboardTopComponent.class, "CasesDashboardTopComponent.deleteOrphanManifestNodesButton.text")); // NOI18N
deleteOrphanManifestNodesButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteOrphanManifestNodesButtonActionPerformed(evt);
}
});
@ -145,12 +153,17 @@ public final class CasesDashboardTopComponent extends TopComponent implements Ex
.addGroup(layout.createSequentialGroup()
.addComponent(refreshButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cleanCaseNodesButton)
.addGap(0, 313, Short.MAX_VALUE))
.addComponent(deleteOrphanCaseNodesButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deleteOrphanManifestNodesButton)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(caseBrowserScrollPane)
.addContainerGap())))
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteOrphanCaseNodesButton, deleteOrphanManifestNodesButton, refreshButton});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
@ -159,22 +172,31 @@ public final class CasesDashboardTopComponent extends TopComponent implements Ex
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(refreshButton)
.addComponent(cleanCaseNodesButton))
.addComponent(deleteOrphanCaseNodesButton)
.addComponent(deleteOrphanManifestNodesButton))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {deleteOrphanCaseNodesButton, deleteOrphanManifestNodesButton, refreshButton});
}// </editor-fold>//GEN-END:initComponents
private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
caseBrowserPanel.displayCases();
}//GEN-LAST:event_refreshButtonActionPerformed
private void cleanCaseNodesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cleanCaseNodesButtonActionPerformed
new CaseNodesCleanupAction().actionPerformed(evt);
}//GEN-LAST:event_cleanCaseNodesButtonActionPerformed
private void deleteOrphanCaseNodesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteOrphanCaseNodesButtonActionPerformed
new DeleteOrphanCaseNodesAction().actionPerformed(evt);
}//GEN-LAST:event_deleteOrphanCaseNodesButtonActionPerformed
private void deleteOrphanManifestNodesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteOrphanManifestNodesButtonActionPerformed
new DeleteOrphanManifestNodesAction().actionPerformed(evt);
}//GEN-LAST:event_deleteOrphanManifestNodesButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane caseBrowserScrollPane;
private javax.swing.JButton cleanCaseNodesButton;
private javax.swing.JButton deleteOrphanCaseNodesButton;
private javax.swing.JButton deleteOrphanManifestNodesButton;
private javax.swing.JButton refreshButton;
// End of variables declaration//GEN-END:variables

View File

@ -0,0 +1,56 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 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 org.openide.util.NbBundle;
import org.sleuthkit.autopsy.progress.ProgressIndicator;
/**
* An action class that kicks off a cancellable orphaned case nodes deletion
* task that runs in a background thread and reports progress using an
* application frame progress bar.
*/
final class DeleteOrphanCaseNodesAction extends BackgroundTaskAction {
private static final long serialVersionUID = 1L;
/**
* Constructs an instance of an action class that kicks off a cancellable
* orphaned case nodes deletion task that runs in a background thread and
* reports progress using an application frame progress bar.
*/
@NbBundle.Messages({
"DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes"
})
DeleteOrphanCaseNodesAction() {
super(Bundle.DeleteOrphanCaseNodesAction_progressDisplayName(), Bundle.DeleteOrphanCaseNodesAction_progressDisplayName());
}
@Override
Runnable getTask(ProgressIndicator progress) {
return new DeleteOrphanCaseNodesTask(progress);
}
@Override
public DeleteOrphanCaseNodesAction clone() throws CloneNotSupportedException {
super.clone();
throw new CloneNotSupportedException();
}
}

View File

@ -31,53 +31,53 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.progress.ProgressIndicator;
/**
* Task for cleaning up case coordination service nodes for which there is no
* Task for deleting case coordination service nodes for which there is no
* longer a corresponding case.
*/
final class CaseNodesCleanupTask implements Runnable {
final class DeleteOrphanCaseNodesTask implements Runnable {
private static final Logger logger = AutoIngestDashboardLogger.getLogger();
private final ProgressIndicator progress;
/**
* Constucts an instance of a task for cleaning up case coordination service
* Constucts an instance of a task for deleting case coordination service
* nodes for which there is no longer a corresponding case.
*
* @param progress
*/
CaseNodesCleanupTask(ProgressIndicator progress) {
DeleteOrphanCaseNodesTask(ProgressIndicator progress) {
this.progress = progress;
}
@Override
@NbBundle.Messages({
"CaseNodesCleanupTask.progress.startMessage=Starting orphaned case znode cleanup...",
"CaseNodesCleanupTask.progress.connectingToCoordSvc=Connecting to the coordination service...",
"CaseNodesCleanupTask.progress.gettingCaseNodesListing=Querying coordination service for case nodes..."
"DeleteOrphanCaseNodesTask.progress.startMessage=Starting orphaned case znode cleanup",
"DeleteOrphanCaseNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service",
"DeleteOrphanCaseNodesTask.progress.gettingCaseNodesListing=Querying coordination service for case znodes"
})
public void run() {
progress.start(Bundle.CaseNodesCleanupTask_progress_startMessage());
progress.start(Bundle.DeleteOrphanCaseNodesTask_progress_startMessage());
try {
progress.progress(Bundle.CaseNodesCleanupTask_progress_connectingToCoordSvc());
logger.log(Level.INFO, "Connecting to the coordination service for orphan case node clean up"); // NON-NLS
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_connectingToCoordSvc());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_connectingToCoordSvc());
CoordinationService coordinationService;
try {
coordinationService = CoordinationService.getInstance();
} catch (CoordinationService.CoordinationServiceException ex) {
logger.log(Level.WARNING, "Error connecting to the coordination service", ex); // NON-NLS
logger.log(Level.SEVERE, "Error connecting to the coordination service", ex); //NON-NLS
return;
}
progress.progress(Bundle.CaseNodesCleanupTask_progress_gettingCaseNodesListing());
logger.log(Level.INFO, "Querying coordination service for case nodes for orphaned case node clean up"); // NON-NLS
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_gettingCaseNodesListing());
logger.log(Level.INFO, Bundle.DeleteOrphanCaseNodesTask_progress_gettingCaseNodesListing());
List<CaseNodeData> nodeDataList;
try {
nodeDataList = CaseNodeDataCollector.getNodeData();
} catch (CoordinationService.CoordinationServiceException ex) {
logger.log(Level.WARNING, "Error collecting case node data", ex); // NON-NLS
logger.log(Level.SEVERE, "Error collecting case node data", ex); //NON-NLS
return;
} catch (InterruptedException ex) {
logger.log(Level.WARNING, "Unexpected interrupt while collecting case node data", ex); // NON-NLS
} catch (InterruptedException unused) {
logger.log(Level.WARNING, "Task cancelled while collecting case node data"); //NON-NLS
return;
}
@ -100,8 +100,8 @@ final class CaseNodesCleanupTask implements Runnable {
nodePath = CoordinationServiceUtils.getCaseDirectoryNodePath(caseDirectoryPath);
deleteNode(coordinationService, caseName, nodePath);
} catch (InterruptedException ex) {
logger.log(Level.WARNING, String.format("Unexpected interrupt while deleting orphaned znode %s for %s", nodePath, caseName), ex); // NON-NLS
} catch (InterruptedException unused) {
logger.log(Level.WARNING, String.format("Task cancelled while deleting orphaned znode %s for %s", nodePath, caseName)); //NON-NLS
return;
}
}
@ -113,9 +113,9 @@ final class CaseNodesCleanupTask implements Runnable {
* where there is no call to get() on a Future<Void> associated with
* the task, so this ensures that any such errors get logged.
*/
logger.log(Level.SEVERE, "Unexpected error during orphan case znode cleanup", ex); // NON-NLS
logger.log(Level.SEVERE, "Unexpected error during orphan case znode cleanup", ex); //NON-NLS
throw ex;
} finally {
progress.finish();
}
@ -132,16 +132,16 @@ final class CaseNodesCleanupTask implements Runnable {
* interrupted during the delete operation.
*/
@NbBundle.Messages({
"# {0} - node path", "CaseNodesCleanupTask.progress.deletingOrphanedCaseNode=Deleting orphaned case node {0}..."
"# {0} - node path", "DeleteOrphanCaseNodesTask.progress.deletingOrphanedCaseNode=Deleting orphaned case znode {0}"
})
private void deleteNode(CoordinationService coordinationService, String caseName, String nodePath) throws InterruptedException {
try {
progress.progress(Bundle.CaseNodesCleanupTask_progress_deletingOrphanedCaseNode(nodePath));
logger.log(Level.INFO, String.format("Deleting orphaned case node %s for %s", nodePath, caseName)); // NON-NLS
progress.progress(Bundle.DeleteOrphanCaseNodesTask_progress_deletingOrphanedCaseNode(nodePath));
logger.log(Level.INFO, String.format("Deleting orphaned case node %s for %s", nodePath, caseName)); //NON-NLS
coordinationService.deleteNode(CoordinationService.CategoryNode.CASES, nodePath);
} catch (CoordinationService.CoordinationServiceException ex) {
if (!DeleteCaseUtils.isNoNodeException(ex)) {
logger.log(Level.SEVERE, String.format("Error deleting orphaned case node %s for %s", nodePath, caseName), ex); // NON-NLS
logger.log(Level.SEVERE, String.format("Error deleting orphaned case node %s for %s", nodePath, caseName), ex); //NON-NLS
}
}
}

View File

@ -0,0 +1,56 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 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 org.openide.util.NbBundle;
import org.sleuthkit.autopsy.progress.ProgressIndicator;
/**
* An action class that kicks off a cancellable orphaned manifest file nodes
* deletion task that runs in a background thread and reports progress using an
* application frame progress bar.
*/
public class DeleteOrphanManifestNodesAction extends BackgroundTaskAction {
private static final long serialVersionUID = 1L;
/**
* Constructs an instance of an action class that kicks off a cancellable
* orphaned manifest file nodes deletion task that runs in a background
* thread and reports progress using an application frame progress bar.
*/
@NbBundle.Messages({
"DeleteOrphanManifestNodesAction.progressDisplayName=Cleanup Manifest File Znodes"
})
DeleteOrphanManifestNodesAction() {
super(Bundle.DeleteOrphanManifestNodesAction_progressDisplayName(), Bundle.DeleteOrphanManifestNodesAction_progressDisplayName());
}
@Override
Runnable getTask(ProgressIndicator progress) {
return new DeleteOrphanManifestNodesTask(progress);
}
@Override
public DeleteOrphanManifestNodesAction clone() throws CloneNotSupportedException {
super.clone();
throw new CloneNotSupportedException();
}
}

View File

@ -0,0 +1,116 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 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.File;
import java.nio.file.Path;
import java.util.List;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.progress.ProgressIndicator;
/**
* A task class for cleaning up auto ingest job coordination service nodes for
* which there is no longer a corresponding manifest file.
*/
final class DeleteOrphanManifestNodesTask implements Runnable {
private static final Logger logger = Logger.getLogger(DeleteOrphanManifestNodesTask.class.getName());
private final ProgressIndicator progress;
/**
* Constucts an instance of a task for cleaning up case coordination service
* nodes for which there is no longer a corresponding case.
*
* @param progress
*/
DeleteOrphanManifestNodesTask(ProgressIndicator progress) {
this.progress = progress;
}
@Override
@NbBundle.Messages({
"DeleteOrphanManifestNodesTask.progress.startMessage=Starting orphaned manifest file znode cleanup",
"DeleteOrphanManifestNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service",
"DeleteOrphanManifestNodesTask.progress.gettingManifestNodes=Querying the coordination service for manifest file znodes",
"# {0} - node path", "DeleteOrphanManifestNodesTask.progress.deletingOrphanedManifestNode=Deleting orphaned manifest file znode {0}"
})
public void run() {
progress.start(Bundle.DeleteOrphanManifestNodesTask_progress_startMessage());
try {
progress.progress(Bundle.DeleteOrphanManifestNodesTask_progress_connectingToCoordSvc());
logger.log(Level.INFO, Bundle.DeleteOrphanManifestNodesTask_progress_connectingToCoordSvc());
CoordinationService coordinationService;
try {
coordinationService = CoordinationService.getInstance();
} catch (CoordinationService.CoordinationServiceException ex) {
logger.log(Level.SEVERE, "Error connecting to the coordination service", ex); // NON-NLS
return;
}
progress.progress(Bundle.DeleteOrphanManifestNodesTask_progress_gettingManifestNodes());
logger.log(Level.INFO, Bundle.DeleteOrphanManifestNodesTask_progress_gettingManifestNodes());
List<AutoIngestJobNodeData> nodeDataList;
try {
nodeDataList = AutoIngestJobNodeDataCollector.getNodeData();
} catch (CoordinationService.CoordinationServiceException ex) {
logger.log(Level.SEVERE, "Error collecting auto ingest job node data", ex); // NON-NLS
return;
} catch (InterruptedException unused) {
logger.log(Level.WARNING, "Task cancelled while collecting auto ingest job node data"); // NON-NLS
return;
}
for (AutoIngestJobNodeData nodeData : nodeDataList) {
final String caseName = nodeData.getCaseName();
final Path manifestFilePath = nodeData.getManifestFilePath();
final File manifestFile = manifestFilePath.toFile();
if (!manifestFile.exists()) {
try {
progress.progress(Bundle.DeleteOrphanManifestNodesTask_progress_deletingOrphanedManifestNode(manifestFilePath));
logger.log(Level.INFO, String.format("Deleting orphaned manifest file znode %s for %s", manifestFilePath, caseName));
coordinationService.deleteNode(CoordinationService.CategoryNode.MANIFESTS, manifestFilePath.toString());
} catch (CoordinationService.CoordinationServiceException ex) {
if (!DeleteCaseUtils.isNoNodeException(ex)) {
logger.log(Level.SEVERE, String.format("Error deleting %s znode for %s", manifestFilePath, caseName), ex); // NON-NLS
}
} catch (InterruptedException unused) {
logger.log(Level.WARNING, String.format("Task cancelled while deleting %s znode for %s", manifestFilePath, caseName)); // NON-NLS
return;
}
}
}
} catch (Exception ex) {
/*
* This is an unexpected runtime exceptions firewall. It is here
* because this task is designed to be able to be run in scenarios
* where there is no call to get() on a Future<Void> associated with
* the task, so this ensures that any such errors get logged.
*/
logger.log(Level.SEVERE, "Unexpected error deleting orphan manifest file znodes", ex); // NON-NLS
throw ex;
} finally {
progress.finish();
}
}
}