[ONOS-3793] Implements the Openstack Security Group REST call parser

Change-Id: Ie6665d4ebae26e363853db28fb2a535c55f1e2ec
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackRestHandler.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackRestHandler.java
index 65014d1..edf14b0 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackRestHandler.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackRestHandler.java
@@ -26,6 +26,7 @@
 import org.onosproject.openstackswitching.OpenstackSubnet;
 import org.onosproject.openstackswitching.web.OpenstackNetworkCodec;
 import org.onosproject.openstackswitching.web.OpenstackPortCodec;
+import org.onosproject.openstackswitching.web.OpenstackSecurityGroupCodec;
 import org.onosproject.openstackswitching.web.OpenstackSubnetCodec;
 import org.slf4j.Logger;
 import javax.ws.rs.core.MediaType;
@@ -44,6 +45,21 @@
  */
 public class OpenstackRestHandler {
 
+    private static final String URI_NETWORKS = "networks";
+    private static final String URI_PORTS = "ports";
+    private static final String URI_SUBNETS = "subnets";
+    private static final String URI_SECURITY_GROUPS = "security-groups";
+    private static final String URI_TOKENS = "tokens";
+
+    private static final String PATH_NETWORKS = "networks";
+    private static final String PATH_PORTS = "ports";
+    private static final String PATH_SUBNETS = "subnets";
+    private static final String PATH_ACCESS = "access";
+    private static final String PATH_TOKEN = "token";
+    private static final String PATH_ID = "id";
+
+    private static final String HEADER_AUTH_TOKEN = "X-Auth-Token";
+
     private final Logger log = getLogger(getClass());
     private String neutronUrl;
     private String keystoneUrl;
@@ -70,9 +86,9 @@
      */
     public Collection<OpenstackNetwork> getNetworks() {
 
-        WebResource.Builder builder = getClientBuilder(neutronUrl + "networks");
+        WebResource.Builder builder = getClientBuilder(neutronUrl + URI_NETWORKS);
         String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
-                header("X-Auth-Token", getToken()).get(String.class);
+                header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
 
         log.debug("networks response:" + response);
 
@@ -80,7 +96,7 @@
         List<OpenstackNetwork> openstackNetworks = Lists.newArrayList();
         try {
             ObjectNode node = (ObjectNode) mapper.readTree(response);
-            ArrayNode networkList = (ArrayNode) node.path("networks");
+            ArrayNode networkList = (ArrayNode) node.path(PATH_NETWORKS);
             OpenstackNetworkCodec networkCodec = new OpenstackNetworkCodec();
             networkList.forEach(n -> openstackNetworks.add(networkCodec.decode((ObjectNode) n, null)));
         } catch (IOException e) {
@@ -100,15 +116,15 @@
      */
     public Collection<OpenstackPort> getPorts() {
 
-        WebResource.Builder builder = getClientBuilder(neutronUrl + "ports");
+        WebResource.Builder builder = getClientBuilder(neutronUrl + URI_PORTS);
         String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
-                header("X-Auth-Token", getToken()).get(String.class);
+                header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
 
         ObjectMapper mapper = new ObjectMapper();
         List<OpenstackPort> openstackPorts = Lists.newArrayList();
         try {
             ObjectNode node = (ObjectNode) mapper.readTree(response);
-            ArrayNode portList = (ArrayNode) node.path("ports");
+            ArrayNode portList = (ArrayNode) node.path(PATH_PORTS);
             OpenstackPortCodec portCodec = new OpenstackPortCodec();
             portList.forEach(p -> openstackPorts.add(portCodec.decode((ObjectNode) p, null)));
         } catch (IOException e) {
@@ -128,15 +144,15 @@
      */
     public Collection<OpenstackSubnet> getSubnets() {
 
-        WebResource.Builder builder = getClientBuilder(neutronUrl + "subnets");
+        WebResource.Builder builder = getClientBuilder(neutronUrl + URI_SUBNETS);
         String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
-                header("X-Auth-Token", getToken()).get(String.class);
+                header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
 
         ObjectMapper mapper = new ObjectMapper();
         List<OpenstackSubnet> subnets = Lists.newArrayList();
         try {
             ObjectNode node = (ObjectNode) mapper.readTree(response);
-            ArrayNode subnetList = (ArrayNode) node.path("subnets");
+            ArrayNode subnetList = (ArrayNode) node.path(PATH_SUBNETS);
             OpenstackSubnetCodec subnetCodec = new OpenstackSubnetCodec();
             subnetList.forEach(s -> subnets.add(subnetCodec.decode((ObjectNode) s, null)));
         } catch (IOException e) {
@@ -149,6 +165,30 @@
         return subnets;
     }
 
+    /**
+     * Extracts OpenstackSecurityGroup information for the ID.
+     *
+     * @param id Security Group ID
+     * @return OpenstackSecurityGroup object or null if fails
+     */
+    public OpenstackSecurityGroup getSecurityGroup(String id) {
+        WebResource.Builder builder = getClientBuilder(neutronUrl + URI_SECURITY_GROUPS + "/" + id);
+        String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
+                header(HEADER_AUTH_TOKEN, getToken()).get(String.class);
+
+        ObjectMapper mapper = new ObjectMapper();
+        OpenstackSecurityGroup securityGroup = null;
+        try {
+            ObjectNode node = (ObjectNode) mapper.readTree(response);
+            OpenstackSecurityGroupCodec sgCodec = new OpenstackSecurityGroupCodec();
+            securityGroup = sgCodec.decode(node, null);
+        } catch (IOException e) {
+            log.warn("getSecurityGroup()", e);
+        }
+
+        return securityGroup;
+    }
+
     private WebResource.Builder getClientBuilder(String uri) {
         Client client = Client.create();
         WebResource resource = client.resource(uri);
@@ -161,13 +201,13 @@
             String request = "{\"auth\": {\"tenantName\": \"admin\", " +
                     "\"passwordCredentials\":  {\"username\": \"" +
                     userName + "\",\"password\": \"" + pass + "\"}}}";
-            WebResource.Builder builder = getClientBuilder(keystoneUrl + "tokens");
+            WebResource.Builder builder = getClientBuilder(keystoneUrl + URI_TOKENS);
             String response = builder.accept(MediaType.APPLICATION_JSON).post(String.class, request);
 
             ObjectMapper mapper = new ObjectMapper();
             try {
                 ObjectNode node = (ObjectNode) mapper.readTree(response);
-                tokenId = node.path("access").path("token").path("id").asText();
+                tokenId = node.path(PATH_ACCESS).path(PATH_TOKEN).path(PATH_ID).asText();
             } catch (IOException e) {
                 log.warn("getToken()", e);
             }
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSecurityGroup.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSecurityGroup.java
new file mode 100644
index 0000000..756989f
--- /dev/null
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSecurityGroup.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2016 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstackswitching.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+
+/**
+ * Represents Openstack Security Group information.
+ */
+public final class OpenstackSecurityGroup {
+
+    private String description;
+    private String id;
+    private String name;
+    private Collection<OpenstackSecurityGroupRule> rules;
+    private String tenantId;
+
+    private OpenstackSecurityGroup(String description, String id, String name,
+                                   Collection<OpenstackSecurityGroupRule> rules,
+                                   String tenantId) {
+        this.description = description;
+        this.id = id;
+        this.name = name;
+        this.tenantId = tenantId;
+        this.rules = rules;
+    }
+
+    /**
+     * Returns the description of the security group.
+     *
+     * @return description
+     */
+    public String description() {
+        return this.description;
+    }
+
+    /**
+     * Returns ID of the security group.
+     *
+     * @return ID
+     */
+    public String id() {
+        return this.id;
+    }
+
+    /**
+     * Returns the name of the security group.
+     *
+     * @return name
+     */
+    public String name() {
+        return this.name;
+    }
+
+    /**
+     * Returns the list of the security group rules.
+     *
+     * @return Collection of OpenstackSecurityGroupRule objects
+     */
+    public Collection<OpenstackSecurityGroupRule> rules() {
+        return Collections.unmodifiableCollection(rules);
+    }
+
+    /**
+     * Returns the Tenant ID.
+     *
+     * @return tenant ID
+     */
+    public String tenantId() {
+        return this.tenantId;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sbuilder = new StringBuilder("Security Group :")
+                .append(description + ",")
+                .append(id + ",")
+                .append(name + ",");
+        rules.forEach(rule -> sbuilder.append(rule.toString()));
+        sbuilder.append(tenantId);
+
+        return sbuilder.toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o instanceof OpenstackSecurityGroup) {
+            OpenstackSecurityGroup that = (OpenstackSecurityGroup) o;
+
+            return this.description.equals(that.description) &&
+                    this.tenantId.equals(that.tenantId) &&
+                    this.id.equals(that.id) &&
+                    this.name.equals(that.name) &&
+                    this.rules.containsAll(that.rules);
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(description, tenantId, id, name, rules);
+    }
+
+    /**
+     * Returns the SecurityGroupRule builder object.
+     *
+     * @return builder object
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Represents the builder of the SecurityGroupRule.
+     *
+     */
+    public static final class Builder {
+        private String description;
+        private String id;
+        private String name;
+        private Collection<OpenstackSecurityGroupRule> rules;
+        private String tenantId;
+
+        /**
+         * Sets the description of the security group.
+         *
+         * @param description description
+         * @return builder object
+         */
+        public Builder description(String description) {
+            this.description = description;
+            return this;
+        }
+
+        /**
+         * Sets the ID of the security group.
+         *
+         * @param id ID
+         * @return builder object
+         */
+        public Builder id(String id) {
+            this.id = id;
+            return this;
+        }
+
+        /**
+         * Sets the name of the security group.
+         *
+         * @param name name
+         * @return builder object
+         */
+        public Builder name(String name) {
+            this.name = name;
+            return this;
+        }
+
+        /**
+         * Sets Security Group rules.
+         *
+         * @param rules security group rules
+         * @return builder object
+         */
+        public Builder rules(Collection<OpenstackSecurityGroupRule> rules) {
+            this.rules = rules;
+            return this;
+        }
+
+        /**
+         * Sets the tenant ID of the security group.
+         *
+         * @param tenantId tenant ID
+         * @return builder object
+         */
+        public Builder tenantId(String tenantId) {
+            this.tenantId = tenantId;
+            return this;
+        }
+
+        /**
+         * Creates the OpenstackSecurityGroup object.
+         *
+         * @return OpenstackSecurityGroup object
+         */
+        public OpenstackSecurityGroup build() {
+            return new OpenstackSecurityGroup(description, id, name, rules, tenantId);
+        }
+    }
+}
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSecurityGroupRule.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSecurityGroupRule.java
new file mode 100644
index 0000000..8a738e6
--- /dev/null
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSecurityGroupRule.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstackswitching.impl;
+
+/**
+ * Represents Openstack Security Group Rules.
+ */
+public final class OpenstackSecurityGroupRule {
+
+    private String direction;
+    private String ethertype;
+    private String id;
+    private String portRangeMax;
+    private String portRangeMin;
+    private String protocol;
+    private String remoteGroupId;
+    private String remoteIpPrefix;
+    private String secuityGroupId;
+    private String tenantId;
+
+    private OpenstackSecurityGroupRule(String direction,
+                                       String ethertype,
+                                       String id,
+                                       String portRangeMax,
+                                       String portRangeMin,
+                                       String protocol,
+                                       String remoteGroupId,
+                                       String remoteIpPrefix,
+                                       String securityGroupId,
+                                       String tenantId) {
+        this.direction = direction;
+        this.ethertype = ethertype;
+        this.id = id;
+        this.portRangeMax = portRangeMax;
+        this.portRangeMin = portRangeMin;
+        this.protocol = protocol;
+        this.remoteGroupId = remoteGroupId;
+        this.remoteIpPrefix = remoteIpPrefix;
+        this.secuityGroupId = securityGroupId;
+        this.tenantId = tenantId;
+    }
+
+    /**
+     * Returns the builder object for the OpenstackSecurityGroupRule.
+     *
+     * @return OpenstackSecurityGroupRule builder object
+     */
+    public static OpenstackSecurityGroupRule.Builder builder() {
+        return new Builder();
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(" [")
+                .append(direction + ",")
+                .append(ethertype + ",")
+                .append(id + ",")
+                .append(portRangeMax + ",")
+                .append(portRangeMin + ",")
+                .append(protocol + ",'")
+                .append(remoteGroupId + ",")
+                .append(remoteIpPrefix + ",")
+                .append(secuityGroupId + ",")
+                .append(tenantId + "] ")
+                .toString();
+    }
+
+    /**
+     * Represents a security group rule builder object.
+     */
+    public static final class Builder {
+
+        private String direction;
+        private String etherType;
+        private String id;
+        private String portRangeMax;
+        private String portRangeMin;
+        private String protocol;
+        private String remoteGroupId;
+        private String remoteIpPrefix;
+        private String secuityGroupId;
+        private String tenantId;
+
+
+        /**
+         * Sets the direction of the security group rule.
+         *
+         * @param direction direction (ingress or egress)
+         * @return builder object
+         */
+        public Builder direction(String direction) {
+            this.direction = direction;
+            return this;
+        }
+
+        /**
+         * Sets the Ethernet Type.
+         *
+         * @param etherType Ethernet Type
+         * @return builder object
+         */
+        public Builder etherType(String etherType) {
+            this.etherType = etherType;
+            return this;
+        }
+
+        /**
+         * Sets the Security Group Rule ID.
+         *
+         * @param id security group rule ID
+         * @return builder object
+         */
+        public Builder id(String id) {
+            this.id = id;
+            return this;
+        }
+
+        /**
+         * Sets the port range max value.
+         *
+         * @param portRangeMax port range max value
+         * @return builder object
+         */
+        public Builder portRangeMax(String portRangeMax) {
+            this.portRangeMax = portRangeMax;
+            return this;
+        }
+
+        /**
+         * Sets the port range min value.
+         *
+         * @param portRangeMin port range min value
+         * @return builder object
+         */
+        public Builder portRangeMin(String portRangeMin) {
+            this.portRangeMin = portRangeMin;
+            return this;
+        }
+
+        /**
+         * Sets the protocol.
+         *
+         * @param protocol protocol
+         * @return builder object
+         */
+        public Builder protocol(String protocol) {
+            this.protocol = protocol;
+            return this;
+        }
+
+        /**
+         * Sets the remote security group ID.
+         *
+         * @param remoteGroupId remote security group ID
+         * @return builder
+         */
+        public Builder remoteGroupId(String remoteGroupId) {
+            this.remoteGroupId = remoteGroupId;
+            return this;
+        }
+
+        /**
+         * Sets the remote IP address as prefix.
+         *
+         * @param remoteIpPrefix remote IP address
+         * @return builder object
+         */
+        public Builder remoteIpPrefix(String remoteIpPrefix) {
+            this.remoteIpPrefix = remoteIpPrefix;
+            return this;
+        }
+
+        /**
+         * Sets the Security Group ID.
+         *
+         * @param securityGroupId security group ID
+         * @return builder object
+         */
+        public Builder securityGroupId(String securityGroupId) {
+            this.secuityGroupId = securityGroupId;
+            return this;
+        }
+
+        /**
+         * Sets the tenant ID.
+         *
+         * @param tenantId tenant ID
+         * @return builder object
+         */
+        public Builder tenantId(String tenantId) {
+            this.tenantId = tenantId;
+            return this;
+        }
+
+        /**
+         * Creates a OpenstackSecurityGroupRule instance.
+         *
+         * @return OpenstackSecurityGroupRule object
+         */
+        public OpenstackSecurityGroupRule build() {
+            return new OpenstackSecurityGroupRule(direction, etherType, id, portRangeMax,
+                    portRangeMin, protocol, remoteGroupId, remoteIpPrefix, secuityGroupId, tenantId);
+        }
+    }
+}
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingManager.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingManager.java
index 63c8f49..572a395 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingManager.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/impl/OpenstackSwitchingManager.java
@@ -176,6 +176,13 @@
                 && !openstackPort.deviceOwner().equals(DEVICE_OWNER_GATEWAY)) {
             registerDhcpInfo(openstackPort);
         }
+
+        if (!openstackPort.securityGroups().isEmpty()) {
+            openstackPort.securityGroups().forEach(sgId -> {
+                OpenstackSecurityGroup sg = restHandler.getSecurityGroup(sgId);
+                log.debug("SecurityGroup : {}", sg.toString());
+            });
+        }
     }
 
     @Override