You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by rm...@apache.org on 2018/08/10 13:27:22 UTC

metron git commit: METRON-1702 Reload a running job in the UI (merrimanr) closes apache/metron#1156

Repository: metron
Updated Branches:
  refs/heads/feature/METRON-1554-pcap-query-panel b29833cc5 -> 05316a4d9


METRON-1702 Reload a running job in the UI (merrimanr) closes apache/metron#1156


Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/05316a4d
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/05316a4d
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/05316a4d

Branch: refs/heads/feature/METRON-1554-pcap-query-panel
Commit: 05316a4d989d7546058e73b3a75eef435f2608a0
Parents: b29833c
Author: merrimanr <me...@gmail.com>
Authored: Fri Aug 10 08:27:06 2018 -0500
Committer: rmerriman <me...@gmail.com>
Committed: Fri Aug 10 08:27:06 2018 -0500

----------------------------------------------------------------------
 .../src/app/pcap/model/pcap.request.ts          |  4 +-
 .../pcap-filters/pcap-filters.component.spec.ts | 60 +++++++++++++-
 .../pcap/pcap-filters/pcap-filters.component.ts | 26 ++++--
 .../pcap/pcap-panel/pcap-panel.component.html   |  2 +-
 .../pcap-panel/pcap-panel.component.spec.ts     | 37 +++++++++
 .../app/pcap/pcap-panel/pcap-panel.component.ts | 87 +++++++++++++-------
 .../src/app/pcap/service/pcap.service.spec.ts   | 44 ++++++++++
 .../src/app/pcap/service/pcap.service.ts        | 15 ++++
 .../rest/service/impl/PcapServiceImpl.java      | 10 +--
 .../rest/service/impl/PcapServiceImplTest.java  | 36 ++++----
 10 files changed, 254 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts b/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts
index d00a6ac..8afc963 100644
--- a/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts
@@ -20,9 +20,9 @@ export class PcapRequest {
   startTimeMs: number = 0;
   endTimeMs: number = 150000000000000000;
   ipSrcAddr: string = '';
-  ipSrcPort: number = 0;
+  ipSrcPort: number;
   ipDstAddr: string = '';
-  ipDstPort: number = 0;
+  ipDstPort: number;
   protocol: string = '';
   packetFilter: string = '';
   includeReverse: boolean = false;

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts
index 4336b22..c1d8664 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts
@@ -21,7 +21,7 @@ import { By } from '@angular/platform-browser';
 
 import { PcapFiltersComponent } from './pcap-filters.component';
 import { FormsModule } from '../../../../node_modules/@angular/forms';
-import { Component, Input, Output, EventEmitter, DebugElement } from '@angular/core';
+import { Component, Input, Output, EventEmitter, DebugElement, SimpleChange } from '@angular/core';
 import { PcapRequest } from '../model/pcap.request';
 
 @Component({
@@ -171,6 +171,14 @@ describe('PcapFiltersComponent', () => {
     component.onSubmit();
   });
 
+  it('Port fields should be missing by default', () => {
+    component.search.emit = (model: PcapRequest) => {
+      expect(model.ipSrcPort).toBeFalsy();
+      expect(model.ipDstPort).toBeFalsy();
+    };
+    component.onSubmit();
+  });
+
   it('Filter should have an output called search', () => {
     component.search.subscribe((filterModel) => {
       expect(filterModel).toBeDefined();
@@ -194,14 +202,60 @@ describe('PcapFiltersComponent', () => {
     expect(fixture.componentInstance.model.hasOwnProperty('startTimeMs')).toBeTruthy();
     expect(fixture.componentInstance.model.hasOwnProperty('endTimeMs')).toBeTruthy();
     expect(fixture.componentInstance.model.hasOwnProperty('ipSrcAddr')).toBeTruthy();
-    expect(fixture.componentInstance.model.hasOwnProperty('ipSrcPort')).toBeTruthy();
+    expect(fixture.componentInstance.model.hasOwnProperty('ipSrcPort')).toBeFalsy();
     expect(fixture.componentInstance.model.hasOwnProperty('ipDstAddr')).toBeTruthy();
-    expect(fixture.componentInstance.model.hasOwnProperty('ipDstPort')).toBeTruthy();
+    expect(fixture.componentInstance.model.hasOwnProperty('ipDstPort')).toBeFalsy();
     expect(fixture.componentInstance.model.hasOwnProperty('protocol')).toBeTruthy();
     expect(fixture.componentInstance.model.hasOwnProperty('packetFilter')).toBeTruthy();
     expect(fixture.componentInstance.model.hasOwnProperty('includeReverse')).toBeTruthy();
   });
 
+  it('should update request on changes', () => {
+
+    let startTimeStr = '2220-12-12 12:12:12';
+    let endTimeStr = '2320-03-13 13:13:13';
+
+    let newModel = {
+      startTimeMs: new Date(startTimeStr).getTime(),
+      endTimeMs: new Date(endTimeStr).getTime(),
+      ipSrcPort: 9345,
+      ipDstPort: 8989
+    };
+    component.model.startTimeMs = new Date(startTimeStr).getTime();
+    component.model.endTimeMs = new Date(endTimeStr).getTime();
+
+    component.ngOnChanges({
+      model: new SimpleChange(null, newModel, false)
+    });
+
+    expect(component.startTimeStr).toBe(startTimeStr);
+    expect(component.endTimeStr).toBe(endTimeStr);
+    expect(component.ipSrcPort).toBe('9345');
+    expect(component.ipDstPort).toBe('8989');
+  });
+
+  it('should update request on changes with missing port filters', () => {
+
+    let startTimeStr = '2220-12-12 12:12:12';
+    let endTimeStr = '2320-03-13 13:13:13';
+
+    let newModel = {
+      startTimeMs: new Date(startTimeStr).getTime(),
+      endTimeMs: new Date(endTimeStr).getTime()
+    };
+    component.model.startTimeMs = new Date(startTimeStr).getTime();
+    component.model.endTimeMs = new Date(endTimeStr).getTime();
+
+    component.ngOnChanges({
+      model: new SimpleChange(null, newModel, false)
+    });
+
+    expect(component.startTimeStr).toBe(startTimeStr);
+    expect(component.endTimeStr).toBe(endTimeStr);
+    expect(component.ipSrcPort).toBe('');
+    expect(component.ipDstPort).toBe('');
+  });
+
   describe('Filter validation', () => {
 
     function setup() {

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts
index 5bbdb67..20a8c2b 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts
@@ -15,7 +15,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
+import {Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges} from '@angular/core';
 import * as moment from 'moment/moment';
 import { DEFAULT_TIMESTAMP_FORMAT } from '../../utils/constants';
 
@@ -26,9 +26,10 @@ import { PcapRequest } from '../model/pcap.request';
   templateUrl: './pcap-filters.component.html',
   styleUrls: ['./pcap-filters.component.scss']
 })
-export class PcapFiltersComponent implements OnInit {
+export class PcapFiltersComponent implements OnInit, OnChanges {
 
   @Input() queryRunning: boolean = true;
+  @Input() model: PcapRequest = new PcapRequest();
   @Output() search: EventEmitter<PcapRequest> = new EventEmitter<PcapRequest>();
 
   startTimeStr: string;
@@ -36,8 +37,6 @@ export class PcapFiltersComponent implements OnInit {
   ipSrcPort: string = '';
   ipDstPort: string = '';
 
-  model = new PcapRequest();
-
   constructor() { }
 
   ngOnInit() {
@@ -48,11 +47,26 @@ export class PcapFiltersComponent implements OnInit {
     this.endTimeStr = moment(endTime).format(DEFAULT_TIMESTAMP_FORMAT);
   }
 
+  ngOnChanges(changes: SimpleChanges): void {
+    if (changes['model']) {
+      this.startTimeStr = moment(changes['model'].currentValue.startTimeMs).format(DEFAULT_TIMESTAMP_FORMAT);
+      this.endTimeStr = moment(changes['model'].currentValue.endTimeMs).format(DEFAULT_TIMESTAMP_FORMAT);
+      let newIpSrcPort = changes['model'].currentValue.ipSrcPort;
+      this.ipSrcPort = newIpSrcPort ? newIpSrcPort.toString() : '';
+      let newIpDstPort = changes['model'].currentValue.ipDstPort;
+      this.ipDstPort = newIpDstPort ? newIpDstPort.toString() : '';
+    }
+  }
+
   onSubmit() {
     this.model.startTimeMs = new Date(this.startTimeStr).getTime();
     this.model.endTimeMs = new Date(this.endTimeStr).getTime();
-    this.model.ipSrcPort = +this.ipSrcPort;
-    this.model.ipDstPort = +this.ipDstPort;
+    if (this.ipSrcPort !== '') {
+      this.model.ipSrcPort = +this.ipSrcPort;
+    }
+    if (this.ipDstPort !== '') {
+      this.model.ipDstPort = +this.ipDstPort;
+    }
 
     this.search.emit(this.model);
   }

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html
index 0dda268..6b18a5f 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.html
@@ -13,7 +13,7 @@
   -->
 <div class="panel my-4">
   <div class="panel-header">
-    <app-pcap-filters [queryRunning]="queryRunning" (search)="onSearch($event)"></app-pcap-filters>
+    <app-pcap-filters [queryRunning]="queryRunning" [model]="pcapRequest" (search)="onSearch($event)"></app-pcap-filters>
   </div>
   <div *ngIf="queryRunning" class="pcap-progress-wrapper">
     <div class="progress pcap-progress-background">

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
index 9dacc7f..fe4df1e 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
@@ -26,6 +26,7 @@ import { PcapPagination } from '../model/pcap-pagination';
 import { By } from '../../../../node_modules/@angular/platform-browser';
 import { PcapRequest } from '../model/pcap.request';
 import { defer } from 'rxjs/observable/defer';
+import {Observable} from "rxjs/Observable";
 import {RestError} from "../../model/rest-error";
 
 @Component({
@@ -34,6 +35,7 @@ import {RestError} from "../../model/rest-error";
 })
 class FakeFilterComponent {
   @Input() queryRunning: boolean;
+  @Input() model: PcapRequest;
 }
 
 @Component({
@@ -46,6 +48,9 @@ class FakePcapListComponent {
 }
 
 class FakePcapService {
+
+  getRunningJob() {}
+
   getDownloadUrl() {
     return '';
   }
@@ -76,6 +81,8 @@ describe('PcapPanelComponent', () => {
 
   beforeEach(() => {
     pcapService = TestBed.get(PcapService);
+    pcapService.getRunningJob = jasmine.createSpy('getRunningJob')
+            .and.returnValue(Observable.of([]));
     fixture = TestBed.createComponent(PcapPanelComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
@@ -517,4 +524,34 @@ describe('PcapPanelComponent', () => {
 
     expect(component.errorMsg).toEqual('Response message: error message. Something went wrong retrieving pdml results!');
   }));
+
+  it('should load running job on init', fakeAsync(() => {
+    const searchResponse = new PcapStatusResponse();
+    searchResponse.jobId = '42';
+
+    pcapService.getRunningJob = jasmine.createSpy('getRunningJob').and.returnValue(
+            defer(() => Promise.resolve([searchResponse]))
+    );
+    component.updateStatus = jasmine.createSpy('updateStatus');
+    component.startPolling = jasmine.createSpy('startPolling');
+
+    const pcapRequest = new PcapRequest();
+    pcapRequest.ipSrcAddr = 'ip_src_addr';
+    pcapService.getPcapRequest = jasmine.createSpy('getPcapRequest').and.returnValue(
+            defer(() => Promise.resolve(pcapRequest))
+    );
+
+    expect(component.queryRunning).toEqual(false);
+    expect(component.pcapRequest).toEqual(new PcapRequest());
+
+    component.ngOnInit();
+
+    tick();
+
+    expect(component.queryRunning).toEqual(true);
+    expect(component.updateStatus).toHaveBeenCalled();
+    expect(component.startPolling).toHaveBeenCalledWith('42');
+    expect(pcapService.getPcapRequest).toHaveBeenCalledWith('42');
+    expect(component.pcapRequest).toEqual(pcapRequest)
+  }));
 });

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
index b11d9df..7c88007 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
@@ -15,7 +15,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { Component, Input, OnDestroy } from '@angular/core';
+import { Component, OnInit, OnDestroy, Input } from '@angular/core';
 
 import { PcapService } from '../service/pcap.service';
 import { PcapStatusResponse } from '../model/pcap-status-response';
@@ -23,14 +23,14 @@ import { PcapRequest } from '../model/pcap.request';
 import { Pdml } from '../model/pdml';
 import { Subscription } from 'rxjs/Rx';
 import { PcapPagination } from '../model/pcap-pagination';
-import {RestError} from "../../model/rest-error";
+import { RestError } from "../../model/rest-error";
 
 @Component({
   selector: 'app-pcap-panel',
   templateUrl: './pcap-panel.component.html',
   styleUrls: ['./pcap-panel.component.scss']
 })
-export class PcapPanelComponent implements OnDestroy {
+export class PcapPanelComponent implements OnInit, OnDestroy {
 
   @Input() pdml: Pdml = null;
   @Input() pcapRequest: PcapRequest;
@@ -49,6 +49,22 @@ export class PcapPanelComponent implements OnDestroy {
 
   constructor(private pcapService: PcapService) { }
 
+  ngOnInit() {
+    this.pcapRequest = new PcapRequest();
+    this.pcapService.getRunningJob().subscribe((statusResponses: PcapStatusResponse[]) => {
+      if (statusResponses.length > 0) {
+        // Assume the first job in the list is the running job
+        this.queryRunning = true;
+        let statusResponse = statusResponses[0];
+        this.updateStatus(statusResponse);
+        this.startPolling(statusResponse.jobId);
+        this.pcapService.getPcapRequest(statusResponse.jobId).subscribe((pcapRequest: PcapRequest) => {
+          this.pcapRequest = pcapRequest;
+        });
+      }
+    });
+  }
+
   changePage(page) {
     this.pagination.selectedPage = page;
     this.pcapService.getPackets(this.queryId, this.pagination.selectedPage).toPromise().then(pdml => {
@@ -70,41 +86,48 @@ export class PcapPanelComponent implements OnDestroy {
         this.errorMsg = submitResponse.description;
         this.queryRunning = false;
       } else {
-        this.queryId = id;
-        this.errorMsg = null;
-        this.statusSubscription = this.pcapService.pollStatus(id).subscribe((statusResponse: PcapStatusResponse) => {
-          if ('SUCCEEDED' === statusResponse.jobStatus) {
-            this.pagination.total = statusResponse.pageTotal;
-            this.statusSubscription.unsubscribe();
-            this.queryRunning = false;
-            this.pcapService.getPackets(id, this.pagination.selectedPage).toPromise().then(pdml => {
-              this.pdml = pdml;
-            }, (error: RestError) => {
-              if (error.responseCode === 404) {
-                this.errorMsg = 'No results returned';
-              } else {
-                this.errorMsg = `Response message: ${error.message}. Something went wrong retrieving pdml results!`;
-              }
-            });
-          } else if ('FAILED' === statusResponse.jobStatus) {
-            this.statusSubscription.unsubscribe();
-            this.queryRunning = false;
-            this.errorMsg = `Query status: ${statusResponse.jobStatus}. Check your filter criteria and try again!`;
-          } else if (this.progressWidth < 100) {
-            this.progressWidth = Math.trunc(statusResponse.percentComplete);
-          }
-        }, (error: any) => {
-          this.statusSubscription.unsubscribe();
-          this.queryRunning = false;
-          this.errorMsg = `Response message: ${error.message}. Something went wrong with your status request!`;
-        });
+        this.startPolling(id);
       }
     }, (error: any) => {
-      this.queryRunning = false;
       this.errorMsg = `Response message: ${error.message}. Something went wrong with your query submission!`;
     });
   }
 
+  startPolling(id: string) {
+    this.queryId = id;
+    this.errorMsg = null;
+    this.statusSubscription = this.pcapService.pollStatus(id).subscribe((statusResponse: PcapStatusResponse) => {
+      this.updateStatus(statusResponse);
+    }, (error: any) => {
+      this.statusSubscription.unsubscribe();
+      this.queryRunning = false;
+      this.errorMsg = `Response message: ${error.message}. Something went wrong with your status request!`;
+    });
+  }
+
+  updateStatus(statusResponse: PcapStatusResponse) {
+    if ('SUCCEEDED' === statusResponse.jobStatus) {
+      this.pagination.total = statusResponse.pageTotal;
+      this.statusSubscription.unsubscribe();
+      this.queryRunning = false;
+      this.pcapService.getPackets(this.queryId, this.pagination.selectedPage).toPromise().then(pdml => {
+        this.pdml = pdml;
+      }, (error: RestError) => {
+        if (error.responseCode === 404) {
+          this.errorMsg = 'No results returned';
+        } else {
+          this.errorMsg = `Response message: ${error.message}. Something went wrong retrieving pdml results!`;
+        }
+      });
+    } else if ('FAILED' === statusResponse.jobStatus) {
+      this.statusSubscription.unsubscribe();
+      this.queryRunning = false;
+      this.errorMsg = `Query status: ${statusResponse.jobStatus}. Check your filter criteria and try again!`;
+    } else if (this.progressWidth < 100) {
+      this.progressWidth = Math.trunc(statusResponse.percentComplete);
+    }
+  }
+
   getDownloadUrl() {
     return this.pcapService.getDownloadUrl(this.queryId, this.pagination.selectedPage);
   }

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.spec.ts b/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.spec.ts
index c8cb937..e7ac5ff 100644
--- a/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.spec.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.spec.ts
@@ -140,6 +140,50 @@ describe('PcapService', () => {
     ));
   });
 
+  describe('getRunningJob()', () => {
+    it('should return an Observable<PcapStatusResponse>', inject(
+            [PcapService, XHRBackend],
+            (pcapService, mockBackend) => {
+              const responseMock: PcapStatusResponse = fakePcapStatusResponse;
+              let response;
+
+              mockBackend.connections.subscribe(connection => {
+                expect(connection.request.url).toMatch(
+                        /\/api\/v1\/pcap\?state=RUNNING/
+                );
+                connection.mockRespond(
+                        new Response(new ResponseOptions({ body: responseMock }))
+                );
+              });
+
+              pcapService.getRunningJob().subscribe(r => (response = r));
+              expect(response).toBeTruthy();
+            }
+    ));
+  });
+
+  describe('getPcapRequest()', () => {
+    it('should return an Observable<PcapRequest>', inject(
+            [PcapService, XHRBackend],
+            (pcapService, mockBackend) => {
+              const responseMock: PcapRequest = fakePcapRequest;
+              let response;
+
+              mockBackend.connections.subscribe(connection => {
+                expect(connection.request.url).toMatch(
+                        /\/api\/v1\/pcap\/job_1234567890123_4567\/config/
+                );
+                connection.mockRespond(
+                        new Response(new ResponseOptions({ body: responseMock }))
+                );
+              });
+
+              pcapService.getPcapRequest(jobId).subscribe(r => (response = r));
+              expect(response).toBeTruthy();
+            }
+    ));
+  });
+
   describe('getDownloadUrl()', () => {
     it('should return a url with the correct page to download the pdml', inject(
       [PcapService],

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts b/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts
index 85ed9cc..d4efc42 100644
--- a/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/service/pcap.service.ts
@@ -53,12 +53,27 @@ export class PcapService {
           .map(HttpUtil.extractData)
           .catch(HttpUtil.handleError);
     }
+
+    public getRunningJob(): Observable<PcapStatusResponse[]> {
+      return this.http.get(`/api/v1/pcap?state=RUNNING`,
+              new RequestOptions({headers: new Headers(this.defaultHeaders)}))
+              .map(HttpUtil.extractData)
+              .catch(HttpUtil.handleError);
+    }
+
     public getPackets(id: string, pageId: number): Observable<Pdml> {
         return this.http.get(`/api/v1/pcap/${id}/pdml?page=${pageId}`, new RequestOptions({headers: new Headers(this.defaultHeaders)}))
             .map(HttpUtil.extractData)
             .catch(HttpUtil.handleError);
     }
 
+    public getPcapRequest(id: string): Observable<PcapRequest> {
+      return this.http.get(`/api/v1/pcap/${id}/config`,
+              new RequestOptions({headers: new Headers(this.defaultHeaders)}))
+              .map(HttpUtil.extractData)
+              .catch(HttpUtil.handleError);
+    }
+
     public getDownloadUrl(id: string, pageId: number) {
       return `/api/v1/pcap/${id}/raw?page=${pageId}`;
     }

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/PcapServiceImpl.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/PcapServiceImpl.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/PcapServiceImpl.java
index f3af0dd..ae3f807 100644
--- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/PcapServiceImpl.java
+++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/PcapServiceImpl.java
@@ -222,19 +222,19 @@ public class PcapServiceImpl implements PcapService {
         Map<String, Object> jobConfiguration = statusable.getConfiguration();
         configuration.put(PcapOptions.BASE_PATH.getKey(), PcapOptions.BASE_PATH.get(jobConfiguration, String.class));
         configuration.put(PcapOptions.FINAL_OUTPUT_PATH.getKey(), PcapOptions.FINAL_OUTPUT_PATH.get(jobConfiguration, String.class));
-        configuration.put(PcapOptions.START_TIME_MS.getKey(), PcapOptions.START_TIME_MS.get(jobConfiguration, String.class));
-        configuration.put(PcapOptions.END_TIME_MS.getKey(), PcapOptions.END_TIME_MS.get(jobConfiguration, String.class));
+        configuration.put(PcapOptions.START_TIME_MS.getKey(), PcapOptions.START_TIME_MS.get(jobConfiguration, Long.class));
+        configuration.put(PcapOptions.END_TIME_MS.getKey(), PcapOptions.END_TIME_MS.get(jobConfiguration, Long.class));
         configuration.put(PcapOptions.NUM_REDUCERS.getKey(), PcapOptions.NUM_REDUCERS.get(jobConfiguration, Integer.class));
 
         boolean isFixedFilter = PcapOptions.FILTER_IMPL.get(jobConfiguration, PcapFilterConfigurator.class) instanceof FixedPcapFilter.Configurator;
         if (isFixedFilter) {
           configuration.put(FixedPcapOptions.IP_SRC_ADDR.getKey(), FixedPcapOptions.IP_SRC_ADDR.get(jobConfiguration, String.class));
           configuration.put(FixedPcapOptions.IP_DST_ADDR.getKey(), FixedPcapOptions.IP_DST_ADDR.get(jobConfiguration, String.class));
-          configuration.put(FixedPcapOptions.IP_SRC_PORT.getKey(), FixedPcapOptions.IP_SRC_PORT.get(jobConfiguration, String.class));
-          configuration.put(FixedPcapOptions.IP_DST_PORT.getKey(), FixedPcapOptions.IP_DST_PORT.get(jobConfiguration, String.class));
+          configuration.put(FixedPcapOptions.IP_SRC_PORT.getKey(), FixedPcapOptions.IP_SRC_PORT.get(jobConfiguration, Integer.class));
+          configuration.put(FixedPcapOptions.IP_DST_PORT.getKey(), FixedPcapOptions.IP_DST_PORT.get(jobConfiguration, Integer.class));
           configuration.put(FixedPcapOptions.PROTOCOL.getKey(), FixedPcapOptions.PROTOCOL.get(jobConfiguration, String.class));
           configuration.put(FixedPcapOptions.PACKET_FILTER.getKey(), FixedPcapOptions.PACKET_FILTER.get(jobConfiguration, String.class));
-          configuration.put(FixedPcapOptions.INCLUDE_REVERSE.getKey(), FixedPcapOptions.INCLUDE_REVERSE.get(jobConfiguration, String.class));
+          configuration.put(FixedPcapOptions.INCLUDE_REVERSE.getKey(), FixedPcapOptions.INCLUDE_REVERSE.get(jobConfiguration, Boolean.class));
         } else {
           configuration.put(QueryPcapOptions.QUERY.getKey(), QueryPcapOptions.QUERY.get(jobConfiguration, String.class));
         }

http://git-wip-us.apache.org/repos/asf/metron/blob/05316a4d/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/PcapServiceImplTest.java
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/PcapServiceImplTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/PcapServiceImplTest.java
index 2552df7..d539c71 100644
--- a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/PcapServiceImplTest.java
+++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/PcapServiceImplTest.java
@@ -671,18 +671,18 @@ public class PcapServiceImplTest {
     pcapService.submit("user", fixedPcapRequest);
 
     Map<String, Object> configuration = pcapService.getConfiguration("user", "jobId");
-    Assert.assertEquals("basePath", PcapOptions.BASE_PATH.get(configuration, String.class));
-    Assert.assertEquals("finalOutputPath", PcapOptions.FINAL_OUTPUT_PATH.get(configuration, String.class));
-    Assert.assertEquals(1L, PcapOptions.START_TIME_MS.get(configuration, Long.class).longValue());
-    Assert.assertEquals(2L, PcapOptions.END_TIME_MS.get(configuration, Long.class).longValue());
-    Assert.assertEquals(2, PcapOptions.NUM_REDUCERS.get(configuration, Integer.class).intValue());
-    Assert.assertEquals("ip_src_addr", FixedPcapOptions.IP_SRC_ADDR.get(configuration, String.class));
-    Assert.assertEquals("ip_dst_addr", FixedPcapOptions.IP_DST_ADDR.get(configuration, String.class));
-    Assert.assertEquals(1000, FixedPcapOptions.IP_SRC_PORT.get(configuration, Integer.class).intValue());
-    Assert.assertEquals(2000, FixedPcapOptions.IP_DST_PORT.get(configuration, Integer.class).intValue());
-    Assert.assertEquals("tcp", FixedPcapOptions.PROTOCOL.get(configuration, String.class));
-    Assert.assertEquals("filter", FixedPcapOptions.PACKET_FILTER.get(configuration, String.class));
-    Assert.assertEquals(true, FixedPcapOptions.INCLUDE_REVERSE.get(configuration, Boolean.class));
+    Assert.assertEquals("basePath", configuration.get(PcapOptions.BASE_PATH.getKey()));
+    Assert.assertEquals("finalOutputPath", configuration.get(PcapOptions.FINAL_OUTPUT_PATH.getKey()));
+    Assert.assertEquals(1L, configuration.get(PcapOptions.START_TIME_MS.getKey()));
+    Assert.assertEquals(2L, configuration.get(PcapOptions.END_TIME_MS.getKey()));
+    Assert.assertEquals(2, configuration.get(PcapOptions.NUM_REDUCERS.getKey()));
+    Assert.assertEquals("ip_src_addr", configuration.get(FixedPcapOptions.IP_SRC_ADDR.getKey()));
+    Assert.assertEquals("ip_dst_addr", configuration.get(FixedPcapOptions.IP_DST_ADDR.getKey()));
+    Assert.assertEquals(1000, configuration.get(FixedPcapOptions.IP_SRC_PORT.getKey()));
+    Assert.assertEquals(2000, configuration.get(FixedPcapOptions.IP_DST_PORT.getKey()));
+    Assert.assertEquals("tcp", configuration.get(FixedPcapOptions.PROTOCOL.getKey()));
+    Assert.assertEquals("filter", configuration.get(FixedPcapOptions.PACKET_FILTER.getKey()));
+    Assert.assertEquals(true, configuration.get(FixedPcapOptions.INCLUDE_REVERSE.getKey()));
   }
 
   @Test
@@ -708,12 +708,12 @@ public class PcapServiceImplTest {
     pcapService.submit("user", queryPcapRequest);
 
     Map<String, Object> configuration = pcapService.getConfiguration("user", "jobId");
-    Assert.assertEquals("basePath", PcapOptions.BASE_PATH.get(configuration, String.class));
-    Assert.assertEquals("finalOutputPath", PcapOptions.FINAL_OUTPUT_PATH.get(configuration, String.class));
-    Assert.assertEquals(1L, PcapOptions.START_TIME_MS.get(configuration, Long.class).longValue());
-    Assert.assertEquals(2L, PcapOptions.END_TIME_MS.get(configuration, Long.class).longValue());
-    Assert.assertEquals(2, PcapOptions.NUM_REDUCERS.get(configuration, Integer.class).intValue());
-    Assert.assertEquals("query", QueryPcapOptions.QUERY.get(configuration, String.class));
+    Assert.assertEquals("basePath", configuration.get(PcapOptions.BASE_PATH.getKey()));
+    Assert.assertEquals("finalOutputPath", configuration.get(PcapOptions.FINAL_OUTPUT_PATH.getKey()));
+    Assert.assertEquals(1L, configuration.get(PcapOptions.START_TIME_MS.getKey()));
+    Assert.assertEquals(2L, configuration.get(PcapOptions.END_TIME_MS.getKey()));
+    Assert.assertEquals(2, configuration.get(PcapOptions.NUM_REDUCERS.getKey()));
+    Assert.assertEquals("query", configuration.get(QueryPcapOptions.QUERY.getKey()));
   }
 
   @Test