Merge branch 'master' into merge

Change-Id: I163ecf699b554e33f4db938c66b73c9911e51135
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DistributedSecurityGroupStore.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DistributedSecurityGroupStore.java
index ec12967..f4fbf52 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DistributedSecurityGroupStore.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DistributedSecurityGroupStore.java
@@ -171,7 +171,7 @@
                             event.newValue().value()));
                     break;
                 case REMOVE:
-                    log.debug("OpenStack security group removed {}", event.newValue());
+                    log.debug("OpenStack security group removed {}", event.oldValue());
                     eventExecutor.execute(() ->
                             notifyDelegate(new OpenstackSecurityGroupEvent(
                                     OPENSTACK_SECURITY_GROUP_REMOVED,
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
index a6f54bd..8c45d4c 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
@@ -45,15 +45,18 @@
 import org.onosproject.net.packet.PacketService;
 import org.onosproject.openstacknetworking.api.Constants;
 import org.onosproject.openstacknetworking.api.InstancePort;
+import org.onosproject.openstacknetworking.api.InstancePortAdminService;
 import org.onosproject.openstacknetworking.api.InstancePortEvent;
 import org.onosproject.openstacknetworking.api.InstancePortListener;
-import org.onosproject.openstacknetworking.api.InstancePortService;
 import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
 import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
 import org.onosproject.openstacknetworking.api.OpenstackRouterService;
+import org.onosproject.openstacknetworking.api.PreCommitPortService;
 import org.onosproject.openstacknode.api.OpenstackNode;
 import org.onosproject.openstacknode.api.OpenstackNodeEvent;
 import org.onosproject.openstacknode.api.OpenstackNodeListener;
@@ -61,6 +64,7 @@
 import org.openstack4j.model.network.ExternalGateway;
 import org.openstack4j.model.network.IP;
 import org.openstack4j.model.network.NetFloatingIP;
+import org.openstack4j.model.network.Port;
 import org.openstack4j.model.network.Router;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
@@ -87,6 +91,7 @@
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_CONTROL_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
+import static org.onosproject.openstacknetworking.api.OpenstackNetworkEvent.Type.OPENSTACK_PORT_PRE_REMOVE;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort;
@@ -124,7 +129,7 @@
     protected OpenstackNodeService osNodeService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    protected InstancePortService instancePortService;
+    protected InstancePortAdminService instancePortService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected ClusterService clusterService;
@@ -141,6 +146,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected ComponentConfigService configService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected PreCommitPortService preCommitPortService;
+
     //@Property(name = ARP_MODE, value = DEFAULT_ARP_MODE_STR,
     //        label = "ARP processing mode, broadcast | proxy (default)")
     protected String arpMode = DEFAULT_ARP_MODE_STR;
@@ -150,6 +158,7 @@
     private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
     private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
     private final InstancePortListener instPortListener = new InternalInstancePortListener();
+    private final OpenstackNetworkListener osNetworkListener = new InternalNetworkEventListener();
 
     private ApplicationId appId;
     private NodeId localNodeId;
@@ -166,6 +175,7 @@
         localNodeId = clusterService.getLocalNode().id();
         osRouterService.addListener(osRouterListener);
         osNodeService.addListener(osNodeListener);
+        osNetworkService.addListener(osNetworkListener);
         instancePortService.addListener(instPortListener);
         leadershipService.runForLeadership(appId.name());
         packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
@@ -178,6 +188,7 @@
         instancePortService.removeListener(instPortListener);
         osRouterService.removeListener(osRouterListener);
         osNodeService.removeListener(osNodeListener);
+        osNetworkService.removeListener(osNetworkListener);
         instancePortService.removeListener(instPortListener);
         leadershipService.withdraw(appId.name());
         eventExecutor.shutdown();
@@ -433,9 +444,9 @@
                 return;
             }
 
-            if (portId == null || fip.getPortId() == null) {
+            if (portId == null || (install && fip.getPortId() == null)) {
                 log.trace("Unknown target ARP request for {}, ignore it",
-                        fip.getFloatingIpAddress());
+                                                    fip.getFloatingIpAddress());
                 return;
             }
 
@@ -448,6 +459,16 @@
                 return;
             }
 
+            if (install) {
+                preCommitPortService.subscribePreCommit(instPort.portId(),
+                        OPENSTACK_PORT_PRE_REMOVE, this.getClass().getName());
+                log.info("Subscribed the port {} on listening pre-remove event", instPort.portId());
+            } else {
+                preCommitPortService.unsubscribePreCommit(instPort.portId(),
+                        OPENSTACK_PORT_PRE_REMOVE, instancePortService, this.getClass().getName());
+                log.info("Unsubscribed the port {} on listening pre-remove event", instPort.portId());
+            }
+
             setArpRule(fip, targetMac, gw, install);
         }
     }
@@ -486,8 +507,8 @@
         }
     }
 
-    private void setFakeGatewayArpRule(Router router, boolean install) {
-        setFakeGatewayArpRule(router.getExternalGatewayInfo(), install);
+    private void setFakeGatewayArpRuleByRouter(Router router, boolean install) {
+        setFakeGatewayArpRuleByGateway(router.getExternalGatewayInfo(), install);
     }
 
     private Set<IP> getExternalGatewaySnatIps(ExternalGateway extGw) {
@@ -500,47 +521,89 @@
                 .collect(Collectors.toSet());
     }
 
-    private void setFakeGatewayArpRule(ExternalGateway extGw, boolean install) {
+    private void setFakeGatewayArpRuleByGateway(ExternalGateway extGw, boolean install) {
         if (ARP_BROADCAST_MODE.equals(getArpMode())) {
 
             if (extGw == null) {
                 return;
             }
 
-            Set<IP> ips = getExternalGatewaySnatIps(extGw);
+            setFakeGatewayArpRuleByIps(getExternalGatewaySnatIps(extGw), install);
+        }
+    }
 
-            ips.forEach(ip -> {
-                TrafficSelector selector = DefaultTrafficSelector.builder()
-                        .matchEthType(EthType.EtherType.ARP.ethType().toShort())
-                        .matchArpOp(ARP.OP_REQUEST)
-                        .matchArpTpa(Ip4Address.valueOf(ip.getIpAddress()))
-                        .build();
+    private void setFakeGatewayArpRuleByIps(Set<IP> ips, boolean install) {
+        ips.forEach(ip -> {
+            TrafficSelector selector = DefaultTrafficSelector.builder()
+                    .matchEthType(EthType.EtherType.ARP.ethType().toShort())
+                    .matchArpOp(ARP.OP_REQUEST)
+                    .matchArpTpa(Ip4Address.valueOf(ip.getIpAddress()))
+                    .build();
 
-                TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                        .setArpOp(ARP.OP_REPLY)
-                        .setArpSha(MacAddress.valueOf(gatewayMac))
-                        .setArpSpa(Ip4Address.valueOf(ip.getIpAddress()))
-                        .setOutput(PortNumber.IN_PORT)
-                        .build();
+            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                    .setArpOp(ARP.OP_REPLY)
+                    .setArpSha(MacAddress.valueOf(gatewayMac))
+                    .setArpSpa(Ip4Address.valueOf(ip.getIpAddress()))
+                    .setOutput(PortNumber.IN_PORT)
+                    .build();
 
-                osNodeService.completeNodes(GATEWAY).forEach(n ->
-                        osFlowRuleService.setRule(
-                                appId,
-                                n.intgBridge(),
-                                selector,
-                                treatment,
-                                PRIORITY_ARP_GATEWAY_RULE,
-                                GW_COMMON_TABLE,
-                                install
-                        )
-                );
+            osNodeService.completeNodes(GATEWAY).forEach(n ->
+                    osFlowRuleService.setRule(
+                            appId,
+                            n.intgBridge(),
+                            selector,
+                            treatment,
+                            PRIORITY_ARP_GATEWAY_RULE,
+                            GW_COMMON_TABLE,
+                            install
+                    )
+            );
 
-                if (install) {
-                    log.info("Install ARP Rule for Gateway Snat {}", ip.getIpAddress());
-                } else {
-                    log.info("Uninstall ARP Rule for Gateway Snat {}", ip.getIpAddress());
-                }
-            });
+            if (install) {
+                log.info("Install ARP Rule for Gateway Snat {}", ip.getIpAddress());
+            } else {
+                log.info("Uninstall ARP Rule for Gateway Snat {}", ip.getIpAddress());
+            }
+        });
+    }
+
+    /**
+     * An internal network event listener, intended to uninstall ARP rules for
+     * routing the packets destined to external gateway.
+     */
+    private class InternalNetworkEventListener implements OpenstackNetworkListener {
+
+        @Override
+        public boolean isRelevant(OpenstackNetworkEvent event) {
+            Port osPort = event.port();
+            if (osPort == null || osPort.getFixedIps() == null) {
+                return false;
+            }
+
+            // do not allow to proceed without leadership
+            NodeId leader = leadershipService.getLeader(appId.name());
+            return Objects.equals(localNodeId, leader) &&
+                    DEVICE_OWNER_ROUTER_GW.equals(osPort.getDeviceOwner());
+        }
+
+        @Override
+        public void event(OpenstackNetworkEvent event) {
+            switch (event.type()) {
+                case OPENSTACK_PORT_CREATED:
+                case OPENSTACK_PORT_UPDATED:
+                    eventExecutor.execute(() ->
+                        setFakeGatewayArpRuleByIps((Set<IP>) event.port().getFixedIps(), true)
+                    );
+                    break;
+                case OPENSTACK_PORT_REMOVED:
+                    eventExecutor.execute(() ->
+                        setFakeGatewayArpRuleByIps((Set<IP>) event.port().getFixedIps(), false)
+                    );
+                    break;
+                default:
+                    // do nothing
+                    break;
+            }
         }
     }
 
@@ -566,25 +629,25 @@
                 case OPENSTACK_ROUTER_CREATED:
                     eventExecutor.execute(() ->
                         // add a router with external gateway
-                        setFakeGatewayArpRule(event.subject(), true)
+                        setFakeGatewayArpRuleByRouter(event.subject(), true)
                     );
                     break;
                 case OPENSTACK_ROUTER_REMOVED:
                     eventExecutor.execute(() ->
                         // remove a router with external gateway
-                        setFakeGatewayArpRule(event.subject(), false)
+                        setFakeGatewayArpRuleByRouter(event.subject(), false)
                     );
                     break;
                 case OPENSTACK_ROUTER_GATEWAY_ADDED:
                     eventExecutor.execute(() ->
                         // add a gateway manually after adding a router
-                        setFakeGatewayArpRule(event.externalGateway(), true)
+                        setFakeGatewayArpRuleByGateway(event.externalGateway(), true)
                     );
                     break;
                 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
                     eventExecutor.execute(() ->
                         // remove a gateway from an existing router
-                        setFakeGatewayArpRule(event.externalGateway(), false)
+                        setFakeGatewayArpRuleByGateway(event.externalGateway(), false)
                     );
                     break;
                 case OPENSTACK_FLOATING_IP_ASSOCIATED:
@@ -807,7 +870,7 @@
 
             osRouterService.routers().stream()
                     .filter(router -> router.getExternalGatewayInfo() != null)
-                    .forEach(router -> setFakeGatewayArpRule(router, install));
+                    .forEach(router -> setFakeGatewayArpRuleByRouter(router, install));
         }
     }
 }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
index 173b6bf..4423bd3 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
@@ -27,6 +27,7 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
+import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.LeadershipService;
 import org.onosproject.cluster.NodeId;
@@ -85,6 +86,7 @@
 import static org.onosproject.openstacknetworking.api.OpenstackNetworkEvent.Type.OPENSTACK_PORT_PRE_REMOVE;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValueAsBoolean;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
@@ -101,6 +103,8 @@
     private static final String ERR_FLOW = "Failed set flows for floating IP %s: ";
     private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type %s";
 
+    private static final String USE_SECURITY_GROUP = "useSecurityGroup";
+
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected CoreService coreService;
 
@@ -114,6 +118,9 @@
     protected ClusterService clusterService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected ComponentConfigService componentConfigService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected OpenstackNodeService osNodeService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -879,14 +886,22 @@
                     NetFloatingIP fip =
                             associatedFloatingIp(instPort, osRouterAdminService.floatingIps());
 
+                    boolean sgFlag = getPropertyValueAsBoolean(
+                            componentConfigService.getProperties(
+                                    OpenstackSecurityGroupHandler.class.getName()),
+                            USE_SECURITY_GROUP);
+
                     if (fip != null) {
-
-                        instancePortService.updateInstancePort(instPort.updateState(REMOVE_PENDING));
-
+                        instancePortService.updateInstancePort(
+                                            instPort.updateState(REMOVE_PENDING));
                         eventExecutor.execute(() ->
                                 updateFipStore(instancePortService.instancePort(event.port().getId())));
                     } else {
-                        instancePortService.removeInstancePort(instPort.portId());
+                        // FIXME: we have dependency with security group, need to
+                        // find a better way to remove this dependency
+                        if (!sgFlag) {
+                            instancePortService.removeInstancePort(instPort.portId());
+                        }
                     }
                     break;
                 default:
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
index 114cc44..550fc37 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
@@ -41,9 +41,9 @@
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.ExtensionSelector;
 import org.onosproject.openstacknetworking.api.InstancePort;
+import org.onosproject.openstacknetworking.api.InstancePortAdminService;
 import org.onosproject.openstacknetworking.api.InstancePortEvent;
 import org.onosproject.openstacknetworking.api.InstancePortListener;
-import org.onosproject.openstacknetworking.api.InstancePortService;
 import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
@@ -51,6 +51,7 @@
 import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupEvent;
 import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupListener;
 import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupService;
+import org.onosproject.openstacknetworking.api.PreCommitPortService;
 import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
 import org.onosproject.openstacknode.api.OpenstackNode;
 import org.onosproject.openstacknode.api.OpenstackNodeEvent;
@@ -88,6 +89,8 @@
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_DROP_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_HOOK_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_RULE;
+import static org.onosproject.openstacknetworking.api.InstancePort.State.REMOVE_PENDING;
+import static org.onosproject.openstacknetworking.api.OpenstackNetworkEvent.Type.OPENSTACK_PORT_PRE_REMOVE;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.computeCtMaskFlag;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.computeCtStateFlag;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.niciraConnTrackTreatmentBuilder;
@@ -112,7 +115,7 @@
     protected CoreService coreService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    protected InstancePortService instancePortService;
+    protected InstancePortAdminService instancePortService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected MastershipService mastershipService;
@@ -141,6 +144,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected ClusterService clusterService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected PreCommitPortService preCommitPortService;
+
     private final InstancePortListener instancePortListener =
                                         new InternalInstancePortListener();
     private final OpenstackNetworkListener osNetworkListener =
@@ -255,6 +261,16 @@
             final String action = install ? "Installed " : "Removed ";
             log.debug(action + "security group rule ID : " + sgId);
         });
+
+        if (install) {
+            preCommitPortService.subscribePreCommit(instPort.portId(),
+                    OPENSTACK_PORT_PRE_REMOVE, this.getClass().getName());
+            log.info("Subscribed the port {} on listening pre-remove event", instPort.portId());
+        } else {
+            preCommitPortService.unsubscribePreCommit(instPort.portId(),
+                    OPENSTACK_PORT_PRE_REMOVE, instancePortService, this.getClass().getName());
+            log.info("Unsubscribed the port {} on listening pre-remove event", instPort.portId());
+        }
     }
 
     private void updateSecurityGroupRule(InstancePort instPort, Port port,
@@ -715,9 +731,11 @@
 
             switch (event.type()) {
                 case OPENSTACK_PORT_PRE_REMOVE:
-                    eventExecutor.execute(() -> {
-                        setSecurityGroupRules(instPort, osPort, false);
-                    });
+                    instancePortService.updateInstancePort(
+                                        instPort.updateState(REMOVE_PENDING));
+                    eventExecutor.execute(() ->
+                        setSecurityGroupRules(instPort, osPort, false)
+                    );
                     break;
                 default:
                     // do nothing for the other events
@@ -803,8 +821,8 @@
                                 securityGroupRuleToRemove.getId());
                     });
                     break;
-                case OPENSTACK_SECURITY_GROUP_CREATED:
                 case OPENSTACK_SECURITY_GROUP_REMOVED:
+                case OPENSTACK_SECURITY_GROUP_CREATED:
                 default:
                     // do nothing
                     break;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
index daad9d1..008f484 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
@@ -276,6 +276,21 @@
     private void setFakeGatewayArpRule(Subnet osSubnet, boolean install, OpenstackNode osNode) {
 
         if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+
+            // do not remove fake gateway ARP rules, if there is another gateway
+            // which has the same subnet that to be removed
+            // this only occurs if we have duplicated subnets associated with
+            // different networks
+            if (!install) {
+                long numOfDupGws = osNetworkService.subnets().stream()
+                        .filter(s -> !s.getId().equals(osSubnet.getId()))
+                        .filter(s -> s.getGateway().equals(osSubnet.getGateway()))
+                        .count();
+                if (numOfDupGws > 0) {
+                    return;
+                }
+            }
+
             String gateway = osSubnet.getGateway();
 
             TrafficSelector selector = DefaultTrafficSelector.builder()
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
index 4f4e570..b755017 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
@@ -452,6 +452,20 @@
     }
 
     /**
+     * Obtains the boolean property value with specified property key name.
+     *
+     * @param properties    a collection of properties
+     * @param name          key name
+     * @return mapping value
+     */
+    public static boolean getPropertyValueAsBoolean(Set<ConfigProperty> properties, String name) {
+        Optional<ConfigProperty> property =
+                properties.stream().filter(p -> p.name().equals(name)).findFirst();
+
+        return property.map(ConfigProperty::asBoolean).orElse(false);
+    }
+
+    /**
      * Prints out the JSON string in pretty format.
      *
      * @param mapper        Object mapper