Repository: metron
Updated Branches:
  refs/heads/feature/METRON-1554-pcap-query-panel 77570464b -> 165c0e716


METRON-1555 Update REST to run YARN and MR jobs (merrimanr) closes 
apache/metron#1019


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

Branch: refs/heads/feature/METRON-1554-pcap-query-panel
Commit: 165c0e716342d743460123a9de6303178ed32830
Parents: 7757046
Author: merrimanr <merrim...@gmail.com>
Authored: Tue Jun 26 10:18:01 2018 -0500
Committer: rmerriman <merrim...@gmail.com>
Committed: Tue Jun 26 10:18:01 2018 -0500

----------------------------------------------------------------------
 dependencies_with_url.csv                       |   1 +
 .../package/scripts/params/params_linux.py      |  10 ++
 .../package/scripts/params/status_params.py     |   6 +
 .../CURRENT/package/scripts/rest_commands.py    |  37 ++++
 .../CURRENT/package/scripts/rest_master.py      |   4 +
 .../apache/metron/rest/model/PcapResponse.java  |  38 +++++
 .../rest/model/pcap/FixedPcapRequest.java       | 115 +++++++++++++
 .../metron/rest/model/pcap/PcapRequest.java     |  91 ++++++++++
 metron-interface/metron-rest/README.md          |   8 +
 metron-interface/metron-rest/pom.xml            |  33 ++++
 .../apache/metron/rest/MetronRestConstants.java |   3 +
 .../apache/metron/rest/config/PcapConfig.java   |  35 ++++
 .../metron/rest/controller/PcapController.java  |  53 ++++++
 .../apache/metron/rest/service/PcapService.java |  27 +++
 .../rest/service/impl/PcapServiceImpl.java      | 120 +++++++++++++
 .../src/main/resources/application.yml          |   6 +-
 .../metron-rest/src/main/scripts/metron-rest.sh |   2 +-
 .../apache/metron/rest/config/TestConfig.java   |   7 +
 .../PcapControllerIntegrationTest.java          | 129 ++++++++++++++
 .../apache/metron/rest/mock/MockPcapJob.java    |  97 +++++++++++
 .../rest/service/impl/PcapServiceImplTest.java  | 167 +++++++++++++++++++
 21 files changed, 987 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/dependencies_with_url.csv
----------------------------------------------------------------------
diff --git a/dependencies_with_url.csv b/dependencies_with_url.csv
index df3bcd2..9fe3b2a 100644
--- a/dependencies_with_url.csv
+++ b/dependencies_with_url.csv
@@ -206,6 +206,7 @@ 
io.confluent:kafka-avro-serializer:jar:1.0:compile,ASLv2,https://github.com/conf
 
io.confluent:kafka-schema-registry-client:jar:1.0:compile,ASLv2,https://github.com/confluentinc/schema-registry/
 io.netty:netty-all:jar:4.0.23.Final:compile,ASLv2,
 io.netty:netty-all:jar:4.0.23.Final:provided,ASLv2,
+io.netty:netty-all:jar:4.1.23.Final:compile,ASLv2,
 io.netty:netty:jar:3.10.5.Final:compile,Apache License, Version 
2.0,http://netty.io/
 io.netty:netty:jar:3.6.2.Final:compile,Apache License, Version 
2.0,http://netty.io/
 io.netty:netty:jar:3.7.0.Final:compile,Apache License, Version 
2.0,http://netty.io/

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py
----------------------------------------------------------------------
diff --git 
a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py
 
b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py
index f44d05f..a2d8185 100755
--- 
a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py
+++ 
b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/params_linux.py
@@ -39,6 +39,8 @@ import status_params
 config = Script.get_config()
 tmp_dir = Script.get_tmp_dir()
 
+hdp_version = default("/commandParams/version", None)
+
 hostname = config['hostname']
 metron_home = status_params.metron_home
 
@@ -357,3 +359,11 @@ metron_apps_indexed_hdfs_dir = 
format(format(config['configurations']['metron-in
 bolt_hdfs_rotation_policy = 
config['configurations']['metron-indexing-env']['bolt_hdfs_rotation_policy']
 bolt_hdfs_rotation_policy_units = 
config['configurations']['metron-indexing-env']['bolt_hdfs_rotation_policy_units']
 bolt_hdfs_rotation_policy_count = 
config['configurations']['metron-indexing-env']['bolt_hdfs_rotation_policy_count']
+
+# Pcap
+pcap_hdfs_dir = format("{metron_apps_hdfs_dir}/pcap")
+pcap_configured_flag_file = status_params.pcap_configured_flag_file
+
+# MapReduce
+metron_user_hdfs_dir = '/user/' + metron_user
+metron_user_hdfs_dir_configured_flag_file = 
status_params.metron_user_hdfs_dir_configured_flag_file

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py
----------------------------------------------------------------------
diff --git 
a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py
 
b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py
index ed2edfb..cb26a87 100644
--- 
a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py
+++ 
b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/params/status_params.py
@@ -114,3 +114,9 @@ metron_user = 
config['configurations']['metron-env']['metron_user']
 
 metron_principal_name = 
config['configurations']['metron-env']['metron_principal_name']
 metron_keytab_path = 
config['configurations']['metron-env']['metron_service_keytab']
+
+# Pcap
+pcap_configured_flag_file = metron_zookeeper_config_path + 
'/../metron_pcap_configured'
+
+# MapReduce
+metron_user_hdfs_dir_configured_flag_file = metron_zookeeper_config_path + 
'/../metron_user_hdfs_dir_configured'
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_commands.py
----------------------------------------------------------------------
diff --git 
a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_commands.py
 
b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_commands.py
index e97af05..73bafbb 100755
--- 
a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_commands.py
+++ 
b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_commands.py
@@ -37,6 +37,8 @@ class RestCommands:
     __kafka_acl_configured = False
     __hbase_configured = False
     __hbase_acl_configured = False
+    __pcap_configured = False
+    __metron_user_hdfs_dir_configured = False
 
     def __init__(self, params):
         if params is None:
@@ -46,6 +48,8 @@ class RestCommands:
         self.__kafka_acl_configured = 
os.path.isfile(self.__params.rest_kafka_acl_configured_flag_file)
         self.__hbase_configured = 
os.path.isfile(self.__params.rest_hbase_configured_flag_file)
         self.__hbase_acl_configured = 
os.path.isfile(self.__params.rest_hbase_acl_configured_flag_file)
+        self.__pcap_configured = 
os.path.isfile(self.__params.pcap_configured_flag_file)
+        self.__metron_user_hdfs_dir_configured = 
os.path.isfile(self.__params.metron_user_hdfs_dir_configured_flag_file)
         Directory(params.metron_rest_pid_dir,
                   mode=0755,
                   owner=params.metron_user,
@@ -74,6 +78,12 @@ class RestCommands:
     def is_hbase_acl_configured(self):
         return self.__hbase_acl_configured
 
+    def is_pcap_configured(self):
+        return self.__pcap_configured
+
+    def is_metron_user_hdfs_dir_configured(self):
+        return self.__metron_user_hdfs_dir_configured
+
     def set_kafka_configured(self):
         metron_service.set_configured(self.__params.metron_user, 
self.__params.rest_kafka_configured_flag_file, "Setting Kafka configured to 
True for rest")
 
@@ -86,6 +96,12 @@ class RestCommands:
     def set_hbase_acl_configured(self):
         metron_service.set_configured(self.__params.metron_user, 
self.__params.rest_hbase_acl_configured_flag_file, "Setting HBase ACL 
configured to True for rest")
 
+    def set_pcap_configured(self):
+        metron_service.set_configured(self.__params.metron_user, 
self.__params.pcap_configured_flag_file, "Setting Pcap configured to True")
+
+    def set_metron_user_hdfs_dir_configured(self):
+        metron_service.set_configured(self.__params.metron_user, 
self.__params.metron_user_hdfs_dir_configured_flag_file, "Setting Metron user 
HDFS directory configured to True")
+
     def init_kafka_topics(self):
         Logger.info('Creating Kafka topics for rest')
         metron_service.init_kafka_topics(self.__params, self.__get_topics())
@@ -100,6 +116,26 @@ class RestCommands:
         groups = ['metron-rest']
         metron_service.init_kafka_acl_groups(self.__params, groups)
 
+    def init_pcap(self):
+        Logger.info("Creating HDFS location for Pcap")
+        self.__params.HdfsResource(self.__params.pcap_hdfs_dir,
+                                   type="directory",
+                                   action="create_on_execute",
+                                   owner=self.__params.metron_user,
+                                   group=self.__params.metron_group,
+                                   mode=0755,
+                                   )
+
+    def create_metron_user_hdfs_dir(self):
+        Logger.info("Creating HDFS location for Metron user")
+        self.__params.HdfsResource(self.__params.metron_user_hdfs_dir,
+                                   type="directory",
+                                   action="create_on_execute",
+                                   owner=self.__params.metron_user,
+                                   group=self.__params.metron_group,
+                                   mode=0755,
+                                   )
+
     def start_rest_application(self):
         """
         Start the REST application
@@ -125,6 +161,7 @@ class RestCommands:
           "export METRON_INDEX_CP={metron_indexing_classpath};"
           "export METRON_LOG_DIR={metron_log_dir};"
           "export METRON_PID_FILE={pid_file};"
+          "export HDP_VERSION={hdp_version};"
           "{metron_home}/bin/metron-rest.sh;"
           "unset METRON_JDBC_PASSWORD;"
         ))

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_master.py
----------------------------------------------------------------------
diff --git 
a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_master.py
 
b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_master.py
index 2f2d3f9..c842214 100755
--- 
a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_master.py
+++ 
b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/scripts/rest_master.py
@@ -51,6 +51,10 @@ class RestMaster(Script):
             commands.init_kafka_topics()
         if not commands.is_hbase_configured():
             commands.create_hbase_tables()
+        if not commands.is_pcap_configured():
+            commands.init_pcap()
+        if not commands.is_metron_user_hdfs_dir_configured():
+            commands.create_metron_user_hdfs_dir()
         if params.security_enabled and not commands.is_hbase_acl_configured():
             commands.set_hbase_acls()
         if params.security_enabled and not commands.is_kafka_acl_configured():

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/PcapResponse.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/PcapResponse.java
 
b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/PcapResponse.java
new file mode 100644
index 0000000..1d33675
--- /dev/null
+++ 
b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/PcapResponse.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PcapResponse {
+
+  private List<byte[]> pcaps = new ArrayList<>();
+
+  public List<byte[]> getPcaps(){
+    if(pcaps == null) {
+      return new ArrayList<>();
+    } else {
+      return pcaps;
+    }
+  }
+
+  public void setPcaps(List<byte[]> pcaps) {
+    this.pcaps = pcaps;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/pcap/FixedPcapRequest.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/pcap/FixedPcapRequest.java
 
b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/pcap/FixedPcapRequest.java
new file mode 100644
index 0000000..758340b
--- /dev/null
+++ 
b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/pcap/FixedPcapRequest.java
@@ -0,0 +1,115 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.model.pcap;
+
+public class FixedPcapRequest extends PcapRequest {
+
+  private String ipSrcAddr;
+  private String ipDstAddr;
+  private Integer ipSrcPort;
+  private Integer ipDstPort;
+  private String protocol;
+  private String packetFilter;
+  private Boolean includeReverse = false;
+
+  public String getIpSrcAddr() {
+    return ipSrcAddr;
+  }
+
+  public void setIpSrcAddr(String ipSrcAddr) {
+    this.ipSrcAddr = ipSrcAddr;
+  }
+
+  public String getIpDstAddr() {
+    return ipDstAddr;
+  }
+
+  public void setIpDstAddr(String ipDstAddr) {
+    this.ipDstAddr = ipDstAddr;
+  }
+
+  public Integer getIpSrcPort() {
+    return ipSrcPort;
+  }
+
+  public void setIpSrcPort(Integer ipSrcPort) {
+    this.ipSrcPort = ipSrcPort;
+  }
+
+  public Integer getIpDstPort() {
+    return ipDstPort;
+  }
+
+  public void setIpDstPort(Integer ipDstPort) {
+    this.ipDstPort = ipDstPort;
+  }
+
+  public String getProtocol() {
+    return protocol;
+  }
+
+  public void setProtocol(String protocol) {
+    this.protocol = protocol;
+  }
+
+  public String getPacketFilter() {
+    return packetFilter;
+  }
+
+  public void setPacketFilter(String packetFilter) {
+    this.packetFilter = packetFilter;
+  }
+
+  public Boolean getIncludeReverse() {
+    return includeReverse;
+  }
+
+  public void setIncludeReverse(Boolean includeReverse) {
+    this.includeReverse = includeReverse;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    FixedPcapRequest fixedPcapRequest = (FixedPcapRequest) o;
+
+    return (super.equals(o)) &&
+            (getIpSrcAddr() != null ? 
getIpSrcAddr().equals(fixedPcapRequest.getIpSrcAddr()) : 
fixedPcapRequest.getIpSrcAddr() != null) &&
+            (getIpDstAddr() != null ? 
getIpDstAddr().equals(fixedPcapRequest.getIpDstAddr()) : 
fixedPcapRequest.getIpDstAddr() != null) &&
+            (getIpSrcPort() != null ? 
getIpSrcPort().equals(fixedPcapRequest.getIpSrcPort()) : 
fixedPcapRequest.getIpSrcPort() != null) &&
+            (getIpDstPort() != null ? 
getIpDstPort().equals(fixedPcapRequest.getIpDstPort()) : 
fixedPcapRequest.getIpDstPort() != null) &&
+            (getProtocol() != null ? 
getProtocol().equals(fixedPcapRequest.getProtocol()) : 
fixedPcapRequest.getProtocol() != null) &&
+            (getPacketFilter() != null ? 
getPacketFilter().equals(fixedPcapRequest.getPacketFilter()) : 
fixedPcapRequest.getPacketFilter() != null) &&
+            (getIncludeReverse() != null ? 
getIncludeReverse().equals(fixedPcapRequest.getIncludeReverse()) : 
fixedPcapRequest.getIncludeReverse() != null);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + (getIpSrcAddr() != null ? getIpSrcAddr().hashCode() 
: 0);
+    result = 31 * result + (getIpDstAddr() != null ? getIpDstAddr().hashCode() 
: 0);
+    result = 31 * result + (getIpSrcPort() != null ? getIpSrcPort().hashCode() 
: 0);
+    result = 31 * result + (getIpDstPort() != null ? getIpDstPort().hashCode() 
: 0);
+    result = 31 * result + (getProtocol() != null ? getProtocol().hashCode() : 
0);
+    result = 31 * result + (getPacketFilter() != null ? 
getPacketFilter().hashCode() : 0);
+    result = 31 * result + (getIncludeReverse() != null ? 
getIncludeReverse().hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/pcap/PcapRequest.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/pcap/PcapRequest.java
 
b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/pcap/PcapRequest.java
new file mode 100644
index 0000000..6062f94
--- /dev/null
+++ 
b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/pcap/PcapRequest.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.model.pcap;
+
+public class PcapRequest {
+
+  private String baseOutputPath;
+  private String basePath;
+  private Long startTime = 0L;
+  private Long endTime = System.currentTimeMillis();
+  private Integer numReducers = 1;
+
+  public String getBaseOutputPath() {
+    return baseOutputPath;
+  }
+
+  public void setBaseOutputPath(String baseOutputPath) {
+    this.baseOutputPath = baseOutputPath;
+  }
+
+  public String getBasePath() {
+    return basePath;
+  }
+
+  public void setBasePath(String basePath) {
+    this.basePath = basePath;
+  }
+
+  public Long getStartTime() {
+    return startTime;
+  }
+
+  public void setStartTime(Long startTime) {
+    this.startTime = startTime;
+  }
+
+  public Long getEndTime() {
+    return endTime;
+  }
+
+  public void setEndTime(Long endTime) {
+    this.endTime = endTime;
+  }
+
+  public Integer getNumReducers() {
+    return numReducers;
+  }
+
+  public void setNumReducers(Integer numReducers) {
+    this.numReducers = numReducers;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    PcapRequest pcapRequest = (PcapRequest) o;
+
+    return (getBaseOutputPath() != null ? 
getBaseOutputPath().equals(pcapRequest.getBaseOutputPath()) : 
pcapRequest.getBaseOutputPath() != null) &&
+            (getBasePath() != null ? 
getBasePath().equals(pcapRequest.getBasePath()) : pcapRequest.getBasePath() == 
null) &&
+            (getStartTime() != null ? 
getStartTime().equals(pcapRequest.getStartTime()) : pcapRequest.getStartTime() 
== null) &&
+            (getEndTime() != null ? 
getEndTime().equals(pcapRequest.getEndTime()) : pcapRequest.getEndTime() == 
null) &&
+            (getNumReducers() != null ? 
getNumReducers().equals(pcapRequest.getNumReducers()) : 
pcapRequest.getNumReducers() == null);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = getBaseOutputPath() != null ? getBaseOutputPath().hashCode() 
: 0;
+    result = 31 * result + (getBasePath() != null ? getBasePath().hashCode() : 
0);
+    result = 31 * result + (getStartTime() != null ? getStartTime().hashCode() 
: 0);
+    result = 31 * result + (getEndTime() != null ? getEndTime().hashCode() : 
0);
+    result = 31 * result + (getNumReducers() != null ? 
getNumReducers().hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/README.md
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/README.md 
b/metron-interface/metron-rest/README.md
index 2a6a0e0..016c6f9 100644
--- a/metron-interface/metron-rest/README.md
+++ b/metron-interface/metron-rest/README.md
@@ -241,6 +241,7 @@ Request and Response objects are JSON formatted.  The JSON 
schemas are available
 | [ `GET /api/v1/metaalert/add/alert`](#get-apiv1metaalertaddalert)|
 | [ `GET /api/v1/metaalert/remove/alert`](#get-apiv1metaalertremovealert)|
 | [ `GET 
/api/v1/metaalert/update/status/{guid}/{status}`](#get-apiv1metaalertupdatestatusguidstatus)|
+| [ `GET /api/v1/pcap/fixed`](#get-apiv1pcapfixed)|
 | [ `GET /api/v1/search/search`](#get-apiv1searchsearch)|
 | [ `POST /api/v1/search/search`](#get-apiv1searchsearch)|
 | [ `POST /api/v1/search/group`](#get-apiv1searchgroup)|
@@ -485,6 +486,13 @@ Request and Response objects are JSON formatted.  The JSON 
schemas are available
   * Returns:
     * 200 - Returns 'true' if the status changed and 'false' if it did not.
 
+### `POST /api/v1/pcap/fixed`
+  * Description: Executes a Fixed Pcap Query.
+  * Input:
+    * fixedPcapRequest - A Fixed Pcap Request which includes fixed filter 
fields like ip source address and protocol.
+  * Returns:
+    * 200 - Returns a PcapResponse containing an array of pcaps.
+
 ### `POST /api/v1/search/search`
   * Description: Searches the indexing store. GUIDs must be quoted to ensure 
correct results.
   * Input:

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/pom.xml
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/pom.xml 
b/metron-interface/metron-rest/pom.xml
index 9c9c372..6e9553e 100644
--- a/metron-interface/metron-rest/pom.xml
+++ b/metron-interface/metron-rest/pom.xml
@@ -170,6 +170,28 @@
                 </exclusion>
             </exclusions>
         </dependency>
+      <dependency>
+        <groupId>org.apache.hadoop</groupId>
+        <artifactId>hadoop-yarn-client</artifactId>
+        <version>${global_hadoop_version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.hadoop</groupId>
+        <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
+        <version>${global_hadoop_version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
         <dependency>
             <groupId>org.apache.metron</groupId>
             <artifactId>metron-hbase-client</artifactId>
@@ -372,6 +394,17 @@
             <artifactId>org.eclipse.persistence.jpa</artifactId>
             <version>${eclipse.link.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.metron</groupId>
+            <artifactId>metron-pcap</artifactId>
+            <version>${project.parent.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
     </dependencies>
 
     <dependencyManagement>

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
index c4873f9..0989d12 100644
--- 
a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
+++ 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java
@@ -74,4 +74,7 @@ public class MetronRestConstants {
   public static final String USER_SETTINGS_HBASE_CF_SPRING_PROPERTY = 
"user.settings.cf";
 
   public static final String LOGGING_SYSTEM_PROPERTY = 
"org.springframework.boot.logging.LoggingSystem";
+
+  public static final String PCAP_INPUT_PATH_SPRING_PROPERTY = 
"pcap.input.path";
+  public static final String PCAP_OUTPUT_PATH_SPRING_PROPERTY = 
"pcap.output.path";
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/config/PcapConfig.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/config/PcapConfig.java
 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/config/PcapConfig.java
new file mode 100644
index 0000000..8da5f96
--- /dev/null
+++ 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/config/PcapConfig.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.config;
+
+import org.apache.metron.pcap.mr.PcapJob;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import static org.apache.metron.rest.MetronRestConstants.TEST_PROFILE;
+
+@Configuration
+@Profile("!" + TEST_PROFILE)
+public class PcapConfig {
+
+  @Bean
+  public PcapJob pcapJob() {
+    return new PcapJob();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/PcapController.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/PcapController.java
 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/PcapController.java
new file mode 100644
index 0000000..11ff1cd
--- /dev/null
+++ 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/PcapController.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.controller;
+
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.metron.rest.model.PcapResponse;
+import org.apache.metron.rest.model.pcap.FixedPcapRequest;
+import org.apache.metron.rest.RestException;
+import org.apache.metron.rest.service.PcapService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+
+@RestController
+@RequestMapping("/api/v1/pcap")
+public class PcapController {
+
+  @Autowired
+  private PcapService pcapQueryService;
+
+  @ApiOperation(value = "Executes a Fixed Pcap Query.")
+  @ApiResponses(value = { @ApiResponse(message = "Returns a PcapResponse 
containing an array of pcaps.", code = 200)})
+  @RequestMapping(value = "/fixed", method = RequestMethod.POST)
+  ResponseEntity<PcapResponse> fixed(@ApiParam(name="fixedPcapRequest", 
value="A Fixed Pcap Request"
+          + " which includes fixed filter fields like ip source address and 
protocol.", required=true)@RequestBody FixedPcapRequest fixedPcapRequest) 
throws RestException {
+    PcapResponse pcapsResponse = pcapQueryService.fixed(fixedPcapRequest);
+    return new ResponseEntity<>(pcapsResponse, HttpStatus.OK);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/PcapService.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/PcapService.java
 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/PcapService.java
new file mode 100644
index 0000000..ce8372c
--- /dev/null
+++ 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/PcapService.java
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.service;
+
+import org.apache.metron.rest.RestException;
+import org.apache.metron.rest.model.PcapResponse;
+import org.apache.metron.rest.model.pcap.FixedPcapRequest;
+
+public interface PcapService {
+
+  PcapResponse fixed(FixedPcapRequest fixedPcapRequest) throws RestException;
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/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
new file mode 100644
index 0000000..4dae1e5
--- /dev/null
+++ 
b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/PcapServiceImpl.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.metron.common.Constants;
+import org.apache.metron.common.hadoop.SequenceFileIterable;
+import org.apache.metron.common.utils.timestamp.TimestampConverters;
+import org.apache.metron.pcap.PcapHelper;
+import org.apache.metron.pcap.filter.fixed.FixedPcapFilter;
+import org.apache.metron.pcap.mr.PcapJob;
+import org.apache.metron.rest.MetronRestConstants;
+import org.apache.metron.rest.RestException;
+import org.apache.metron.rest.model.PcapResponse;
+import org.apache.metron.rest.model.pcap.FixedPcapRequest;
+import org.apache.metron.rest.service.PcapService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class PcapServiceImpl implements PcapService {
+
+  private Environment environment;
+  private Configuration configuration;
+  private PcapJob pcapJob;
+
+  @Autowired
+  public PcapServiceImpl(Environment environment, Configuration configuration, 
PcapJob pcapJob) {
+    this.environment = environment;
+    this.configuration = configuration;
+    this.pcapJob = pcapJob;
+  }
+
+  @Override
+  public PcapResponse fixed(FixedPcapRequest fixedPcapRequest) throws 
RestException {
+    if (fixedPcapRequest.getBasePath() == null) {
+      
fixedPcapRequest.setBasePath(environment.getProperty(MetronRestConstants.PCAP_INPUT_PATH_SPRING_PROPERTY));
+    }
+    if (fixedPcapRequest.getBaseOutputPath() == null) {
+      
fixedPcapRequest.setBaseOutputPath(environment.getProperty(MetronRestConstants.PCAP_OUTPUT_PATH_SPRING_PROPERTY));
+    }
+    PcapResponse response = new PcapResponse();
+    SequenceFileIterable results;
+    try {
+      results = pcapJob.query(
+              new Path(fixedPcapRequest.getBasePath()),
+              new Path(fixedPcapRequest.getBaseOutputPath()),
+              
TimestampConverters.MILLISECONDS.toNanoseconds(fixedPcapRequest.getStartTime()),
+              
TimestampConverters.MILLISECONDS.toNanoseconds(fixedPcapRequest.getEndTime()),
+              fixedPcapRequest.getNumReducers(),
+              getFixedFields(fixedPcapRequest),
+              configuration,
+              getFileSystem(),
+              new FixedPcapFilter.Configurator()
+      );
+      if (results != null) {
+        List<byte[]> pcaps = new ArrayList<>();
+        results.iterator().forEachRemaining(pcaps::add);
+        response.setPcaps(pcaps);
+      }
+    } catch (IOException | ClassNotFoundException | InterruptedException e) {
+      throw new RestException(e);
+    }
+    return response;
+  }
+
+  protected Map<String, String> getFixedFields(FixedPcapRequest 
fixedPcapRequest) {
+    Map<String, String> fixedFields = new HashMap<>();
+    if (fixedPcapRequest.getIpSrcAddr() != null) {
+      fixedFields.put(Constants.Fields.SRC_ADDR.getName(), 
fixedPcapRequest.getIpSrcAddr());
+    }
+    if (fixedPcapRequest.getIpDstAddr() != null) {
+      fixedFields.put(Constants.Fields.DST_ADDR.getName(), 
fixedPcapRequest.getIpDstAddr());
+    }
+    if (fixedPcapRequest.getIpSrcPort() != null) {
+      fixedFields.put(Constants.Fields.SRC_PORT.getName(), 
fixedPcapRequest.getIpSrcPort().toString());
+    }
+    if (fixedPcapRequest.getIpDstPort() != null) {
+      fixedFields.put(Constants.Fields.DST_PORT.getName(), 
fixedPcapRequest.getIpDstPort().toString());
+    }
+    if (fixedPcapRequest.getProtocol() != null) {
+      fixedFields.put(Constants.Fields.PROTOCOL.getName(), 
fixedPcapRequest.getProtocol());
+    }
+    if (fixedPcapRequest.getIncludeReverse() != null) {
+      fixedFields.put(Constants.Fields.INCLUDES_REVERSE_TRAFFIC.getName(), 
fixedPcapRequest.getIncludeReverse().toString());
+    }
+    if (fixedPcapRequest.getPacketFilter() != null) {
+      fixedFields.put(PcapHelper.PacketFields.PACKET_FILTER.getName(), 
fixedPcapRequest.getPacketFilter());
+    }
+    return fixedFields;
+  }
+
+  protected FileSystem getFileSystem() throws IOException {
+    return FileSystem.get(configuration);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/main/resources/application.yml
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/main/resources/application.yml 
b/metron-interface/metron-rest/src/main/resources/application.yml
index 97359b9..df67ab3 100644
--- a/metron-interface/metron-rest/src/main/resources/application.yml
+++ b/metron-interface/metron-rest/src/main/resources/application.yml
@@ -71,4 +71,8 @@ spring.jpa.generate-ddl: true
 user:
   settings:
     table: user_settings
-    cf: cf
\ No newline at end of file
+    cf: cf
+
+pcap:
+  input.path: /apps/metron/pcap
+  output.path: /tmp
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/main/scripts/metron-rest.sh
----------------------------------------------------------------------
diff --git a/metron-interface/metron-rest/src/main/scripts/metron-rest.sh 
b/metron-interface/metron-rest/src/main/scripts/metron-rest.sh
index 2c7c75b..cf7bf58 100644
--- a/metron-interface/metron-rest/src/main/scripts/metron-rest.sh
+++ b/metron-interface/metron-rest/src/main/scripts/metron-rest.sh
@@ -110,7 +110,7 @@ fi
 echo "METRON_REST_CLASSPATH=${METRON_REST_CLASSPATH}"
 
 echo "Starting application"
-${JAVA_HOME}/bin/java ${METRON_JVMFLAGS} \
+${JAVA_HOME}/bin/java -Dhdp.version=${HDP_VERSION} ${METRON_JVMFLAGS} \
 -cp ${METRON_REST_CLASSPATH} \
 org.apache.metron.rest.MetronRestApplication \
 ${METRON_SPRING_OPTIONS} >> ${METRON_LOG_DIR}/metron-rest.log 2>&1 & echo $! > 
${METRON_PID_FILE};

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/config/TestConfig.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/config/TestConfig.java
 
b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/config/TestConfig.java
index 008f3fc..a9e70d2 100644
--- 
a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/config/TestConfig.java
+++ 
b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/config/TestConfig.java
@@ -37,7 +37,9 @@ import org.apache.metron.integration.ComponentRunner;
 import org.apache.metron.integration.UnableToStartException;
 import org.apache.metron.integration.components.KafkaComponent;
 import org.apache.metron.integration.components.ZKServerComponent;
+import org.apache.metron.pcap.mr.PcapJob;
 import org.apache.metron.rest.RestException;
+import org.apache.metron.rest.mock.MockPcapJob;
 import org.apache.metron.rest.mock.MockStormCLIClientWrapper;
 import org.apache.metron.rest.mock.MockStormRestTemplate;
 import org.apache.metron.rest.service.impl.StormCLIWrapper;
@@ -185,4 +187,9 @@ public class TestConfig {
   public UserSettingsClient userSettingsClient() throws RestException, 
IOException {
     return new UserSettingsClient(new 
MockHBaseTableProvider().addToCache("user_settings", "cf"), 
Bytes.toBytes("cf"));
   }
+
+  @Bean
+  public PcapJob mockPcapJob() {
+    return new MockPcapJob();
+  }
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/PcapControllerIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/PcapControllerIntegrationTest.java
 
b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/PcapControllerIntegrationTest.java
new file mode 100644
index 0000000..5e4875a
--- /dev/null
+++ 
b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/PcapControllerIntegrationTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.controller;
+
+import org.adrianwalker.multilinestring.Multiline;
+import org.apache.metron.common.Constants;
+import org.apache.metron.common.utils.JSONUtils;
+import org.apache.metron.pcap.PcapHelper;
+import org.apache.metron.pcap.filter.fixed.FixedPcapFilter;
+import org.apache.metron.rest.mock.MockPcapJob;
+import org.apache.metron.rest.model.PcapResponse;
+import org.apache.metron.rest.service.PcapService;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.metron.rest.MetronRestConstants.TEST_PROFILE;
+import static 
org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static 
org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
+import static 
org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
+import static 
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles(TEST_PROFILE)
+public class PcapControllerIntegrationTest {
+
+  /**
+   {
+   "basePath": "/apps/metron/pcap",
+   "baseOutputPath": "/tmp",
+   "endTime": 10,
+   "includeReverse": "true",
+   "ipDstAddr": "192.168.1.1",
+   "ipDstPort": "1000",
+   "ipSrcAddr": "192.168.1.2",
+   "ipSrcPort": "2000",
+   "numReducers": 2,
+   "packetFilter": "filter",
+   "protocol": "TCP",
+   "startTime": 1
+   }
+   */
+  @Multiline
+  public static String fixedJson;
+
+  @Autowired
+  private PcapService pcapService;
+
+  @Autowired
+  private WebApplicationContext wac;
+
+  private MockMvc mockMvc;
+
+  private String pcapUrl = "/api/v1/pcap";
+  private String user = "user";
+  private String password = "password";
+
+  @Before
+  public void setup() throws Exception {
+    this.mockMvc = 
MockMvcBuilders.webAppContextSetup(this.wac).apply(springSecurity()).build();
+  }
+
+  @Test
+  public void testSecurity() throws Exception {
+    this.mockMvc.perform(post(pcapUrl + 
"/fixed").with(csrf()).contentType(MediaType.parseMediaType("application/json;charset=UTF-8")).content(fixedJson))
+            .andExpect(status().isUnauthorized());
+  }
+
+  @Test
+  public void testFixed() throws Exception {
+    MockPcapJob mockPcapJob = (MockPcapJob) wac.getBean("mockPcapJob");
+    List<byte[]> results = Arrays.asList("pcap1".getBytes(), 
"pcap2".getBytes());
+    mockPcapJob.setResults(results);
+
+    PcapResponse expectedReponse = new PcapResponse();
+    expectedReponse.setPcaps(results);
+    this.mockMvc.perform(post(pcapUrl + "/fixed").with(httpBasic(user, 
password)).with(csrf()).contentType(MediaType.parseMediaType("application/json;charset=UTF-8")).content(fixedJson))
+            .andExpect(status().isOk())
+            
.andExpect(content().contentType(MediaType.parseMediaType("application/json;charset=UTF-8")))
+            
.andExpect(content().json(JSONUtils.INSTANCE.toJSON(expectedReponse, false)));
+
+    Assert.assertEquals("/apps/metron/pcap", mockPcapJob.getBasePath());
+    Assert.assertEquals("/tmp", mockPcapJob.getBaseOutputPath());
+    Assert.assertEquals(1, mockPcapJob.getStartTime());
+    Assert.assertEquals(10, mockPcapJob.getEndTime());
+    Assert.assertEquals(2, mockPcapJob.getNumReducers());
+    Assert.assertTrue(mockPcapJob.getFilterImpl() instanceof 
FixedPcapFilter.Configurator);
+    Map<String, String> actualFixedFields = mockPcapJob.getFixedFields();
+    Assert.assertEquals("192.168.1.2", 
actualFixedFields.get(Constants.Fields.SRC_ADDR.getName()));
+    Assert.assertEquals("2000", 
actualFixedFields.get(Constants.Fields.SRC_PORT.getName()));
+    Assert.assertEquals("192.168.1.1", 
actualFixedFields.get(Constants.Fields.DST_ADDR.getName()));
+    Assert.assertEquals("1000", 
actualFixedFields.get(Constants.Fields.DST_PORT.getName()));
+    Assert.assertEquals("true", 
actualFixedFields.get(Constants.Fields.INCLUDES_REVERSE_TRAFFIC.getName()));
+    Assert.assertEquals("TCP", 
actualFixedFields.get(Constants.Fields.PROTOCOL.getName()));
+    Assert.assertEquals("filter", 
actualFixedFields.get(PcapHelper.PacketFields.PACKET_FILTER.getName()));
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockPcapJob.java
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockPcapJob.java
 
b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockPcapJob.java
new file mode 100644
index 0000000..3aa9ce3
--- /dev/null
+++ 
b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockPcapJob.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.mock;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.metron.common.hadoop.SequenceFileIterable;
+import org.apache.metron.pcap.filter.PcapFilterConfigurator;
+import org.apache.metron.pcap.mr.PcapJob;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Matchers.anyList;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class MockPcapJob extends PcapJob {
+
+  private String basePath;
+  private String baseOutputPath;
+  private long beginNS;
+  private long endNS;
+  private int numReducers;
+  private Map<String, String> fixedFields;
+  private PcapFilterConfigurator filterImpl;
+  private SequenceFileIterable sequenceFileIterable;
+
+  public MockPcapJob() {
+    sequenceFileIterable = mock(SequenceFileIterable.class);
+  }
+
+  @SuppressWarnings(value = "unchecked")
+  @Override
+  public <T> SequenceFileIterable query(Path basePath, Path baseOutputPath, 
long beginNS, long endNS, int numReducers, T fields, Configuration conf, 
FileSystem fs, PcapFilterConfigurator<T> filterImpl) throws IOException, 
ClassNotFoundException, InterruptedException {
+    this.basePath = basePath.toString();
+    this.baseOutputPath = baseOutputPath.toString();
+    this.beginNS = beginNS;
+    this.endNS = endNS;
+    this.numReducers = numReducers;
+    if (fields instanceof Map) {
+      this.fixedFields = (Map<String, String>) fields;
+    }
+    this.filterImpl = filterImpl;
+    return sequenceFileIterable;
+  }
+
+  public void setResults(List<byte[]> pcaps) {
+    when(sequenceFileIterable.iterator()).thenReturn(pcaps.iterator());
+  }
+
+  public String getBasePath() {
+    return basePath;
+  }
+
+  public String getBaseOutputPath() {
+    return baseOutputPath;
+  }
+
+  public long getStartTime() {
+    return beginNS / 1000000;
+  }
+
+  public long getEndTime() {
+    return endNS / 1000000;
+  }
+
+  public int getNumReducers() {
+    return numReducers;
+  }
+
+  public Map<String, String> getFixedFields() {
+    return fixedFields;
+  }
+
+  public PcapFilterConfigurator getFilterImpl() {
+    return filterImpl;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/165c0e71/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
new file mode 100644
index 0000000..b6f2ea8
--- /dev/null
+++ 
b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/service/impl/PcapServiceImplTest.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.metron.rest.service.impl;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.metron.common.Constants;
+import org.apache.metron.common.hadoop.SequenceFileIterable;
+import org.apache.metron.pcap.PcapHelper;
+import org.apache.metron.pcap.filter.fixed.FixedPcapFilter;
+import org.apache.metron.pcap.mr.PcapJob;
+import org.apache.metron.rest.MetronRestConstants;
+import org.apache.metron.rest.RestException;
+import org.apache.metron.rest.model.PcapResponse;
+import org.apache.metron.rest.model.pcap.FixedPcapRequest;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.core.env.Environment;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+@SuppressWarnings("ALL")
+public class PcapServiceImplTest {
+  @Rule
+  public final ExpectedException exception = ExpectedException.none();
+
+  Environment environment;
+  Configuration configuration;
+  PcapJob pcapJob;
+
+  @Before
+  public void setUp() throws Exception {
+    environment = mock(Environment.class);
+    pcapJob = mock(PcapJob.class);
+    configuration = mock(Configuration.class);
+
+    
when(environment.getProperty(MetronRestConstants.PCAP_INPUT_PATH_SPRING_PROPERTY)).thenReturn("/input/path");
+    
when(environment.getProperty(MetronRestConstants.PCAP_OUTPUT_PATH_SPRING_PROPERTY)).thenReturn("/output/path");
+  }
+
+
+  @Test
+  public void fixedShouldProperlyCallPcapJobQuery() throws Exception {
+    FixedPcapRequest fixedPcapRequest = new FixedPcapRequest();
+    fixedPcapRequest.setBaseOutputPath("baseOutputPath");
+    fixedPcapRequest.setBasePath("basePath");
+    fixedPcapRequest.setStartTime(1L);
+    fixedPcapRequest.setEndTime(2L);
+    fixedPcapRequest.setNumReducers(2);
+    fixedPcapRequest.setIpSrcAddr("ip_src_addr");
+    fixedPcapRequest.setIpDstAddr("ip_dst_addr");
+    fixedPcapRequest.setIpSrcPort(1000);
+    fixedPcapRequest.setIpDstPort(2000);
+    fixedPcapRequest.setProtocol("tcp");
+    fixedPcapRequest.setPacketFilter("filter");
+    fixedPcapRequest.setIncludeReverse(true);
+
+    PcapServiceImpl pcapService = spy(new PcapServiceImpl(environment, 
configuration, pcapJob));
+    FileSystem fileSystem = mock(FileSystem.class);
+    doReturn(fileSystem).when(pcapService).getFileSystem();
+    Map<String, String> expectedFields = new HashMap<String, String>() {{
+      put(Constants.Fields.SRC_ADDR.getName(), "ip_src_addr");
+      put(Constants.Fields.DST_ADDR.getName(), "ip_dst_addr");
+      put(Constants.Fields.SRC_PORT.getName(), "1000");
+      put(Constants.Fields.DST_PORT.getName(), "2000");
+      put(Constants.Fields.PROTOCOL.getName(), "tcp");
+      put(Constants.Fields.INCLUDES_REVERSE_TRAFFIC.getName(), "true");
+      put(PcapHelper.PacketFields.PACKET_FILTER.getName(), "filter");
+    }};
+    List<byte[]> expectedPcaps = Arrays.asList("pcap1".getBytes(), 
"pcap2".getBytes());
+    SequenceFileIterable results = mock(SequenceFileIterable.class);
+    when(results.iterator()).thenReturn(expectedPcaps.iterator());
+    when(pcapJob.query(eq(new Path("basePath")),
+            eq(new Path("baseOutputPath")),
+            eq(1000000L),
+            eq(2000000L),
+            eq(2),
+            eq(expectedFields),
+            eq(configuration),
+            any(FileSystem.class),
+            any(FixedPcapFilter.Configurator.class))).thenReturn(results);
+
+    PcapResponse pcapsResponse = pcapService.fixed(fixedPcapRequest);
+    Assert.assertEquals(expectedPcaps, pcapsResponse.getPcaps());
+  }
+
+  @Test
+  public void fixedShouldProperlyCallPcapJobQueryWithDefaults() throws 
Exception {
+    FixedPcapRequest fixedPcapRequest = new FixedPcapRequest();
+
+    PcapServiceImpl pcapService = spy(new PcapServiceImpl(environment, 
configuration, pcapJob));
+    FileSystem fileSystem = mock(FileSystem.class);
+    doReturn(fileSystem).when(pcapService).getFileSystem();
+    Map<String, String> expectedFields = new HashMap<String, String>() {{
+      put(Constants.Fields.INCLUDES_REVERSE_TRAFFIC.getName(), "false");
+    }};
+    List<byte[]> expectedPcaps = Arrays.asList("pcap1".getBytes(), 
"pcap2".getBytes());
+    SequenceFileIterable results = mock(SequenceFileIterable.class);
+    when(results.iterator()).thenReturn(expectedPcaps.iterator());
+    when(pcapJob.query(eq(new Path("/input/path")),
+            eq(new Path("/output/path")),
+            eq(0L),
+            eq(fixedPcapRequest.getEndTime() * 1000000),
+            eq(1),
+            eq(expectedFields),
+            eq(configuration),
+            any(FileSystem.class),
+            any(FixedPcapFilter.Configurator.class))).thenReturn(results);
+
+    PcapResponse pcapsResponse = pcapService.fixed(fixedPcapRequest);
+    Assert.assertEquals(expectedPcaps, pcapsResponse.getPcaps());
+  }
+
+  @Test
+  public void fixedShouldThrowRestException() throws Exception {
+    exception.expect(RestException.class);
+    exception.expectMessage("some exception");
+
+    FixedPcapRequest fixedPcapRequest = new FixedPcapRequest();
+
+    PcapServiceImpl pcapService = spy(new PcapServiceImpl(environment, 
configuration, pcapJob));
+    FileSystem fileSystem = mock(FileSystem.class);
+    doReturn(fileSystem).when(pcapService).getFileSystem();
+
+    when(pcapJob.query(any(),
+            any(),
+            eq(0L),
+            eq(fixedPcapRequest.getEndTime() * 1000000),
+            eq(1),
+            any(),
+            any(),
+            any(FileSystem.class),
+            any(FixedPcapFilter.Configurator.class))).thenThrow(new 
IOException("some exception"));
+
+    pcapService.fixed(fixedPcapRequest);
+  }
+}

Reply via email to