[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
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java
index 1264eb5..99f1f80 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java
@@ -18,6 +18,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.MacAddress;
 import org.onosproject.codec.CodecContext;
@@ -26,6 +27,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Collection;
 import java.util.HashMap;
 
 /**
@@ -79,7 +81,9 @@
             }
         }
         String id = portInfo.path(ID).asText();
-        String securityGroups = portInfo.path(SECURITY_GROUPS).asText();
+        ArrayNode securityGroupList = (ArrayNode) portInfo.path(SECURITY_GROUPS);
+        Collection<String> securityGroupIdList = Lists.newArrayList();
+        securityGroupList.forEach(securityGroup -> securityGroupIdList.add(securityGroup.asText()));
         String deviceId = portInfo.path(DEVICE_ID).asText();
 
         OpenstackPort.Builder openstackPortBuilder = OpenstackPort.builder();
@@ -96,12 +100,9 @@
                 .macAddress(MacAddress.valueOf(macStr))
                 .fixedIps(fixedIpMap)
                 .id(id)
-                .deviceId(deviceId);
+                .deviceId(deviceId)
+                .securityGroup(securityGroupIdList);
 
-        // FIX ME
-        if (!securityGroups.isEmpty()) {
-            openstackPortBuilder.securityGroup(securityGroups);
-        }
 
         OpenstackPort openstackPort = openstackPortBuilder.build();
 
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSecurityGroupCodec.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSecurityGroupCodec.java
new file mode 100644
index 0000000..ae9847e
--- /dev/null
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSecurityGroupCodec.java
@@ -0,0 +1,96 @@
+/*
+ * 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.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.openstackswitching.impl.OpenstackSecurityGroup;
+import org.onosproject.openstackswitching.impl.OpenstackSecurityGroupRule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+
+/**
+ * Encodes and decodes the Openstack Security Group.
+ */
+public class OpenstackSecurityGroupCodec extends JsonCodec<OpenstackSecurityGroup> {
+
+    private static Logger log = LoggerFactory
+            .getLogger(OpenstackSecurityGroupCodec.class);
+
+    private static final String SECURITY_GROUP = "security_group";
+    private static final String DESCRIPTION = "description";
+    private static final String ID = "id";
+    private static final String NAME = "name";
+    private static final String SECURITY_GROUP_RULES = "security_group_rules";
+    private static final String DIRECTION = "direction";
+    private static final String EHTERTYPE = "ethertype";
+    private static final String PORT_RANGE_MAX = "port_range_max";
+    private static final String PORT_RANGE_MIN = "port_range_min";
+    private static final String PROTOCOL = "protocol";
+    private static final String REMOTE_GROUP_ID = "remote_group_id";
+    private static final String REMOTE_IP_PREFIX = "remote_ip_prefix";
+    private static final String SECURITY_GROUP_ID = "security_group_id";
+    private static final String TENAN_ID = "tenant_id";
+
+    @Override
+    public OpenstackSecurityGroup decode(ObjectNode json, CodecContext context) {
+        JsonNode securityGroupNode = json.get(SECURITY_GROUP);
+        if (securityGroupNode == null) {
+            log.warn("SecurityGroup Json data is null");
+            return null;
+        }
+
+        String description = securityGroupNode.path(DESCRIPTION).asText();
+        String id = securityGroupNode.path(ID).asText();
+        String name = securityGroupNode.path(NAME).asText();
+        ArrayNode ruleInfoList = (ArrayNode) securityGroupNode.path(SECURITY_GROUP_RULES);
+        Collection<OpenstackSecurityGroupRule> rules = Lists.newArrayList();
+        for (JsonNode ruleInfo: ruleInfoList) {
+            OpenstackSecurityGroupRule openstackSecurityGroupRule =
+                    OpenstackSecurityGroupRule.builder()
+                        .direction(ruleInfo.path(DIRECTION).asText())
+                        .etherType(ruleInfo.path(EHTERTYPE).asText())
+                        .id(ruleInfo.path(ID).asText())
+                        .portRangeMax(ruleInfo.path(PORT_RANGE_MAX).asText())
+                        .portRangeMin(ruleInfo.path(PORT_RANGE_MIN).asText())
+                        .protocol(ruleInfo.path(PROTOCOL).asText())
+                        .remoteGroupId(ruleInfo.path(REMOTE_GROUP_ID).asText())
+                        .remoteIpPrefix(ruleInfo.path(REMOTE_IP_PREFIX).asText())
+                        .securityGroupId(ruleInfo.path(SECURITY_GROUP_ID).asText())
+                        .tenantId(ruleInfo.path(TENAN_ID).asText())
+                        .build();
+
+            rules.add(openstackSecurityGroupRule);
+        }
+        String tenantId = securityGroupNode.path(TENAN_ID).asText();
+
+        OpenstackSecurityGroup openstackSecurityGroup = OpenstackSecurityGroup.builder()
+                .description(description)
+                .id(id)
+                .name(name)
+                .rules(rules)
+                .tenantId(tenantId)
+                .build();
+
+        return openstackSecurityGroup;
+    }
+}