Added management instance handler and some refactoring

- Added management instance handler to provide management network
  connectivity for the management network connected instance, currenly
  local managemenet network connectivity provided
- Renamed Dummy service to Default service
- Renamed CordVtnInstanceHandler to AbstractInstanceHandler and moved
  default VTN rule populations to DefaultInstanceHandler
- Removed workaround management network access code from OLT agent
  instance handler

Change-Id: I990c29b8ae41674d136fbc12f3c4e92167c8c74c
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java
new file mode 100644
index 0000000..0c19509
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/impl/service/DefaultInstanceHandler.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2016-present 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.opencord.cordvtn.impl.service;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+
+import org.apache.felix.scr.annotations.Deactivate;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.opencord.cordvtn.impl.AbstractInstanceHandler;
+import org.opencord.cordvtn.api.CordVtnNode;
+import org.opencord.cordvtn.api.Instance;
+import org.opencord.cordvtn.api.InstanceHandler;
+import org.onosproject.xosclient.api.VtnService;
+import org.opencord.cordvtn.impl.CordVtnPipeline;
+
+import java.util.Optional;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.DEFAULT;
+
+/**
+ * Provides network connectivity for default service instances.
+ */
+@Component(immediate = true)
+public class DefaultInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
+
+    @Activate
+    protected void activate() {
+        serviceType = Optional.of(DEFAULT);
+        eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-default", "event-handler"));
+        super.activate();
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        super.deactivate();
+    }
+
+    @Override
+    public void instanceDetected(Instance instance) {
+        log.info("Instance is detected {}", instance);
+
+        VtnService service = getVtnService(instance.serviceId());
+        if (service == null) {
+            log.warn("Failed to get VtnService for {}", instance);
+            return;
+        }
+        defaultConnectionRules(instance, service, true);
+    }
+
+    @Override
+    public void instanceRemoved(Instance instance) {
+        log.info("Instance is removed {}", instance);
+
+        VtnService service = getVtnService(instance.serviceId());
+        if (service == null) {
+            log.warn("Failed to get VtnService for {}", instance);
+            return;
+        }
+        defaultConnectionRules(instance, service, false);
+    }
+
+    private void defaultConnectionRules(Instance instance, VtnService service, boolean install) {
+        long vni = service.vni();
+        Ip4Prefix serviceIpRange = service.subnet().getIp4Prefix();
+
+        inPortRule(instance, install);
+        dstIpRule(instance, vni, install);
+        tunnelInRule(instance, vni, install);
+
+        if (install) {
+            directAccessRule(serviceIpRange, serviceIpRange, true);
+            serviceIsolationRule(serviceIpRange, true);
+        } else if (getInstances(service.id()).isEmpty()) {
+            directAccessRule(serviceIpRange, serviceIpRange, false);
+            serviceIsolationRule(serviceIpRange, false);
+        }
+    }
+
+    private void inPortRule(Instance instance, boolean install) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchInPort(instance.portNumber())
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPSrc(instance.ipAddress().toIpPrefix())
+                .build();
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .transition(CordVtnPipeline.TABLE_ACCESS_TYPE)
+                .build();
+
+
+        FlowRule flowRule = DefaultFlowRule.builder()
+                .fromApp(appId)
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+                .forDevice(instance.deviceId())
+                .forTable(CordVtnPipeline.TABLE_IN_PORT)
+                .makePermanent()
+                .build();
+
+        pipeline.processFlowRule(install, flowRule);
+
+        selector = DefaultTrafficSelector.builder()
+                .matchInPort(instance.portNumber())
+                .build();
+
+        treatment = DefaultTrafficTreatment.builder()
+                .transition(CordVtnPipeline.TABLE_IN_SERVICE)
+                .build();
+
+        flowRule = DefaultFlowRule.builder()
+                .fromApp(appId)
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(CordVtnPipeline.PRIORITY_LOW)
+                .forDevice(instance.deviceId())
+                .forTable(CordVtnPipeline.TABLE_IN_PORT)
+                .makePermanent()
+                .build();
+
+        pipeline.processFlowRule(install, flowRule);
+    }
+
+    private void dstIpRule(Instance instance, long vni, boolean install) {
+        Ip4Address tunnelIp = nodeManager.dpIp(instance.deviceId()).getIp4Address();
+
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPDst(instance.ipAddress().toIpPrefix())
+                .build();
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .setEthDst(instance.mac())
+                .setOutput(instance.portNumber())
+                .build();
+
+        FlowRule flowRule = DefaultFlowRule.builder()
+                .fromApp(appId)
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+                .forDevice(instance.deviceId())
+                .forTable(CordVtnPipeline.TABLE_DST_IP)
+                .makePermanent()
+                .build();
+
+        pipeline.processFlowRule(install, flowRule);
+
+        for (CordVtnNode node : nodeManager.completeNodes()) {
+            if (node.intBrId().equals(instance.deviceId())) {
+                continue;
+            }
+
+            ExtensionTreatment tunnelDst = pipeline.tunnelDstTreatment(node.intBrId(), tunnelIp);
+            if (tunnelDst == null) {
+                continue;
+            }
+
+            treatment = DefaultTrafficTreatment.builder()
+                    .setEthDst(instance.mac())
+                    .setTunnelId(vni)
+                    .extension(tunnelDst, node.intBrId())
+                    .setOutput(nodeManager.tunnelPort(node.intBrId()))
+                    .build();
+
+            flowRule = DefaultFlowRule.builder()
+                    .fromApp(appId)
+                    .withSelector(selector)
+                    .withTreatment(treatment)
+                    .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+                    .forDevice(node.intBrId())
+                    .forTable(CordVtnPipeline.TABLE_DST_IP)
+                    .makePermanent()
+                    .build();
+
+            pipeline.processFlowRule(install, flowRule);
+        }
+    }
+
+    private void tunnelInRule(Instance instance, long vni, boolean install) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchTunnelId(vni)
+                .matchEthDst(instance.mac())
+                .build();
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .setOutput(instance.portNumber())
+                .build();
+
+        FlowRule flowRule = DefaultFlowRule.builder()
+                .fromApp(appId)
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+                .forDevice(instance.deviceId())
+                .forTable(CordVtnPipeline.TABLE_TUNNEL_IN)
+                .makePermanent()
+                .build();
+
+        pipeline.processFlowRule(install, flowRule);
+    }
+
+    private void directAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange, boolean install) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPSrc(srcRange)
+                .matchIPDst(dstRange)
+                .build();
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .transition(CordVtnPipeline.TABLE_DST_IP)
+                .build();
+
+
+        nodeManager.completeNodes().stream().forEach(node -> {
+            FlowRule flowRuleDirect = DefaultFlowRule.builder()
+                    .fromApp(appId)
+                    .withSelector(selector)
+                    .withTreatment(treatment)
+                    .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
+                    .forDevice(node.intBrId())
+                    .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
+                    .makePermanent()
+                    .build();
+
+            pipeline.processFlowRule(install, flowRuleDirect);
+        });
+    }
+
+    private void serviceIsolationRule(Ip4Prefix dstRange, boolean install) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPDst(dstRange)
+                .build();
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .drop()
+                .build();
+
+        nodeManager.completeNodes().stream().forEach(node -> {
+            FlowRule flowRuleDirect = DefaultFlowRule.builder()
+                    .fromApp(appId)
+                    .withSelector(selector)
+                    .withTreatment(treatment)
+                    .withPriority(CordVtnPipeline.PRIORITY_LOW)
+                    .forDevice(node.intBrId())
+                    .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
+                    .makePermanent()
+                    .build();
+
+            pipeline.processFlowRule(install, flowRuleDirect);
+        });
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/DummyInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/DummyInstanceHandler.java
deleted file mode 100644
index 86a5f1b..0000000
--- a/src/main/java/org/opencord/cordvtn/impl/service/DummyInstanceHandler.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016-present 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.opencord.cordvtn.impl.service;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-
-import org.apache.felix.scr.annotations.Deactivate;
-import org.opencord.cordvtn.api.Instance;
-import org.opencord.cordvtn.api.InstanceHandler;
-import org.opencord.cordvtn.impl.CordVtnInstanceHandler;
-import org.onosproject.xosclient.api.VtnService;
-
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static org.onlab.util.Tools.groupedThreads;
-
-/**
- * Provides network connectivity for dummy service instances.
- */
-@Component(immediate = true)
-public class DummyInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
-
-    @Activate
-    protected void activate() {
-        serviceType = VtnService.ServiceType.DUMMY;
-        eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-dummy", "event-handler"));
-        super.activate();
-    }
-
-    @Deactivate
-    protected void deactivate() {
-        super.deactivate();
-    }
-
-    @Override
-    public void instanceDetected(Instance instance) {
-        super.instanceDetected(instance);
-    }
-
-    @Override
-    public void instanceRemoved(Instance instance) {
-        super.instanceRemoved(instance);
-    }
-}
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java
new file mode 100644
index 0000000..2e49a0b
--- /dev/null
+++ b/src/main/java/org/opencord/cordvtn/impl/service/ManagementInstanceHandler.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2016-present 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.opencord.cordvtn.impl.service;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.onlab.packet.Ethernet;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.xosclient.api.VtnService;
+import org.opencord.cordvtn.impl.AbstractInstanceHandler;
+import org.opencord.cordvtn.api.Instance;
+import org.opencord.cordvtn.api.InstanceHandler;
+import org.opencord.cordvtn.impl.CordVtnPipeline;
+
+import java.util.Optional;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.MANAGEMENT;
+
+/**
+ * Provides network connectivity for management network connected instances.
+ */
+@Component(immediate = true)
+public class ManagementInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
+
+    @Activate
+    protected void activate() {
+        serviceType = Optional.of(MANAGEMENT);
+        eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-mgmt", "event-handler"));
+        super.activate();
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        super.deactivate();
+    }
+
+    @Override
+    public void instanceDetected(Instance instance) {
+        log.info("Instance is detected {}", instance);
+
+        VtnService service = getVtnService(instance.serviceId());
+        if (service == null) {
+            log.warn("Failed to get VtnService for {}", instance);
+            return;
+        }
+        localMgmtNetworkRules(instance, service, true);
+    }
+
+    @Override
+    public void instanceRemoved(Instance instance) {
+        log.info("Instance is removed {}", instance);
+
+        VtnService service = getVtnService(instance.serviceId());
+        if (service == null) {
+            log.warn("Failed to get VtnService for {}", instance);
+            return;
+        }
+
+        // TODO check if any stale management network rules are
+        localMgmtNetworkRules(instance, service, false);
+    }
+
+    private void localMgmtNetworkRules(Instance instance, VtnService service, boolean install) {
+        managementPerInstanceRule(instance, install);
+        if (install) {
+            managementBaseRule(instance, service, true);
+        } else if (!hostService.getConnectedHosts(instance.deviceId()).stream()
+                .filter(host -> Instance.of(host).serviceId().equals(service.id()))
+                .findAny()
+                .isPresent()) {
+            managementBaseRule(instance, service, false);
+        }
+    }
+
+    private void managementBaseRule(Instance instance, VtnService service, boolean install) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_ARP)
+                .matchArpTpa(service.serviceIp().getIp4Address())
+                .build();
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .setOutput(PortNumber.LOCAL)
+                .build();
+
+        FlowRule flowRule = DefaultFlowRule.builder()
+                .fromApp(appId)
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
+                .forDevice(instance.deviceId())
+                .forTable(CordVtnPipeline.TABLE_ZERO)
+                .makePermanent()
+                .build();
+
+        pipeline.processFlowRule(install, flowRule);
+
+        selector = DefaultTrafficSelector.builder()
+                .matchInPort(PortNumber.LOCAL)
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPDst(service.subnet())
+                .build();
+
+        treatment = DefaultTrafficTreatment.builder()
+                .transition(CordVtnPipeline.TABLE_DST_IP)
+                .build();
+
+        flowRule = DefaultFlowRule.builder()
+                .fromApp(appId)
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
+                .forDevice(instance.deviceId())
+                .forTable(CordVtnPipeline.TABLE_ZERO)
+                .makePermanent()
+                .build();
+
+        pipeline.processFlowRule(install, flowRule);
+
+        selector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPDst(service.serviceIp().toIpPrefix())
+                .build();
+
+        treatment = DefaultTrafficTreatment.builder()
+                .setOutput(PortNumber.LOCAL)
+                .build();
+
+        flowRule = DefaultFlowRule.builder()
+                .fromApp(appId)
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
+                .forDevice(instance.deviceId())
+                .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
+                .makePermanent()
+                .build();
+
+        pipeline.processFlowRule(install, flowRule);
+    }
+
+    private void managementPerInstanceRule(Instance instance, boolean install) {
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchInPort(PortNumber.LOCAL)
+                .matchEthType(Ethernet.TYPE_ARP)
+                .matchArpTpa(instance.ipAddress().getIp4Address())
+                .build();
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .setOutput(instance.portNumber())
+                .build();
+
+        FlowRule flowRule = DefaultFlowRule.builder()
+                .fromApp(appId)
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
+                .forDevice(instance.deviceId())
+                .forTable(CordVtnPipeline.TABLE_ZERO)
+                .makePermanent()
+                .build();
+
+        pipeline.processFlowRule(install, flowRule);
+    }
+}
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java
index 7919c5a..b409e79 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/service/OltAgentInstanceHandler.java
@@ -19,42 +19,33 @@
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IpPrefix;
 
+import org.opencord.cordvtn.impl.AbstractInstanceHandler;
 import org.opencord.cordvtn.api.CordVtnConfig;
 import org.opencord.cordvtn.api.Instance;
 import org.opencord.cordvtn.api.InstanceHandler;
-import org.opencord.cordvtn.impl.CordVtnInstanceHandler;
 import org.onosproject.net.DeviceId;
-import org.onosproject.net.PortNumber;
 
 import org.onosproject.net.config.ConfigFactory;
 import org.onosproject.net.config.NetworkConfigEvent;
 import org.onosproject.net.config.NetworkConfigListener;
 import org.onosproject.net.config.basics.SubjectFactories;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.xosclient.api.VtnService;
 import org.opencord.cordconfig.access.AccessAgentConfig;
 import org.opencord.cordconfig.access.AccessAgentData;
-import org.opencord.cordvtn.impl.CordVtnPipeline;
 
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
 import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.OLT_AGENT;
 
 /**
  * Provides network connectivity for OLT agent instances.
  */
 @Component(immediate = true)
-public class OltAgentInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
+public class OltAgentInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
 
     private static final Class<AccessAgentConfig> CONFIG_CLASS = AccessAgentConfig.class;
     private ConfigFactory<DeviceId, AccessAgentConfig> configFactory =
@@ -67,12 +58,11 @@
             };
 
     private Map<DeviceId, AccessAgentData> oltAgentData = Maps.newConcurrentMap();
-    private IpPrefix mgmtIpRange = null;
 
     @Activate
     protected void activate() {
+        serviceType = Optional.of(OLT_AGENT);
         eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-olt", "event-handler"));
-        serviceType = VtnService.ServiceType.OLT_AGENT;
 
         configRegistry.registerConfigFactory(configFactory);
         configListener = new InternalConfigListener();
@@ -88,49 +78,15 @@
     @Override
     public void instanceDetected(Instance instance) {
         log.info("OLT agent instance detected {}", instance);
-
-        managementAccessRule(instance.deviceId(), true);
         // TODO implement
     }
 
     @Override
     public void instanceRemoved(Instance instance) {
         log.info("OLT agent instance removed {}", instance);
-
-        if (getInstances(instance.serviceId()).isEmpty()) {
-            nodeManager.completeNodes().stream().forEach(node ->
-                managementAccessRule(node.intBrId(), false));
-        }
-
         // TODO implement
     }
 
-    private void managementAccessRule(DeviceId deviceId, boolean install) {
-        // TODO remove this rule after long term management network is done
-        if (mgmtIpRange != null) {
-            TrafficSelector selector = DefaultTrafficSelector.builder()
-                    .matchEthType(Ethernet.TYPE_IPV4)
-                    .matchIPDst(mgmtIpRange)
-                    .build();
-
-            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                    .setOutput(PortNumber.LOCAL)
-                    .build();
-
-            FlowRule flowRule = DefaultFlowRule.builder()
-                    .fromApp(appId)
-                    .withSelector(selector)
-                    .withTreatment(treatment)
-                    .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
-                    .forDevice(deviceId)
-                    .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
-                    .makePermanent()
-                    .build();
-
-            pipeline.processFlowRule(install, flowRule);
-        }
-    }
-
     private void readAccessAgentConfig() {
 
         Set<DeviceId> deviceSubjects = configRegistry.getSubjects(DeviceId.class, CONFIG_CLASS);
@@ -142,20 +98,7 @@
         });
     }
 
-    @Override
-    protected void readConfiguration() {
-        CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
-        if (config == null) {
-            log.debug("No configuration found");
-            return;
-        }
-
-        osAccess = config.openstackAccess();
-        xosAccess = config.xosAccess();
-        mgmtIpRange = config.managementIpRange();
-    }
-
-    public class InternalConfigListener implements NetworkConfigListener {
+    private class InternalConfigListener implements NetworkConfigListener {
 
         @Override
         public void event(NetworkConfigEvent event) {
diff --git a/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java b/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java
index 46c4a01..e6fd643 100644
--- a/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java
+++ b/src/main/java/org/opencord/cordvtn/impl/service/VsgInstanceHandler.java
@@ -28,9 +28,9 @@
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
+import org.opencord.cordvtn.impl.AbstractInstanceHandler;
 import org.opencord.cordvtn.api.Instance;
 import org.opencord.cordvtn.api.InstanceHandler;
-import org.opencord.cordvtn.impl.CordVtnInstanceHandler;
 import org.opencord.cordvtn.impl.CordVtnInstanceManager;
 import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.HostId;
@@ -50,12 +50,10 @@
 import org.onosproject.net.host.DefaultHostDescription;
 import org.onosproject.net.host.HostDescription;
 import org.onosproject.xosclient.api.VtnPort;
-import org.onosproject.xosclient.api.VtnPortApi;
-import org.onosproject.xosclient.api.VtnPortId;
-import org.onosproject.xosclient.api.VtnService;
 import org.opencord.cordvtn.impl.CordVtnPipeline;
 
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -63,13 +61,14 @@
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
 import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
+import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.VSG;
 
 /**
  * Provides network connectivity for vSG instances.
  */
 @Component(immediate = true)
 @Service(value = VsgInstanceHandler.class)
-public final class VsgInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
+public final class VsgInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
 
     private static final String STAG = "stag";
     private static final String VSG_VM = "vsgVm";
@@ -82,7 +81,7 @@
 
     @Activate
     protected void activate() {
-        serviceType = VtnService.ServiceType.VSG;
+        serviceType = Optional.of(VSG);
         eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-vsg", "event-handler"));
         super.activate();
     }
@@ -100,7 +99,7 @@
             // find vsg vm for this vsg container
             String vsgVmId = instance.getAnnotation(VSG_VM);
             if (Strings.isNullOrEmpty(vsgVmId)) {
-                log.warn("Failed to find VSG VM for {}", instance);
+                log.warn("Failed to find vSG VM for {}", instance);
                 return;
             }
 
@@ -121,6 +120,9 @@
                 return;
             }
 
+            log.info("vSG VM detected {}", instance);
+
+            // insert vSG containers inside the vSG VM as a host
             vtnPort.addressPairs().entrySet().stream()
                     .forEach(pair -> addVsgContainer(
                             instance,
@@ -128,37 +130,35 @@
                             pair.getValue(),
                             getStag(vtnPort).toString()
                     ));
-            super.instanceDetected(instance);
         }
     }
 
     @Override
     public void instanceRemoved(Instance instance) {
-        if (isVsgContainer(instance)) {
-            log.info("vSG container vanished {}", instance);
-
-            // find vsg vm for this vsg container
-            String vsgVmId = instance.getAnnotation(VSG_VM);
-            if (Strings.isNullOrEmpty(vsgVmId)) {
-                log.warn("Failed to find VSG VM for {}", instance);
-                return;
-            }
-
-            Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
-            VtnPort vtnPort = getVtnPort(vsgVm);
-            if (vtnPort == null || getStag(vtnPort) == null) {
-                return;
-            }
-
-            populateVsgRules(vsgVm, getStag(vtnPort),
-                             nodeManager.dpPort(vsgVm.deviceId()),
-                             vtnPort.addressPairs().keySet(),
-                             false);
-
-        } else {
-            // TODO remove vsg vm related rules
-            super.instanceRemoved(instance);
+        if (!isVsgContainer(instance)) {
+            // nothing to do for the vSG VM itself
+            return;
         }
+
+        log.info("vSG container vanished {}", instance);
+
+        // find vsg vm for this vsg container
+        String vsgVmId = instance.getAnnotation(VSG_VM);
+        if (Strings.isNullOrEmpty(vsgVmId)) {
+            log.warn("Failed to find vSG VM for {}", instance);
+            return;
+        }
+
+        Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
+        VtnPort vtnPort = getVtnPort(vsgVm);
+        if (vtnPort == null || getStag(vtnPort) == null) {
+            return;
+        }
+
+        populateVsgRules(vsgVm, getStag(vtnPort),
+                         nodeManager.dpPort(vsgVm.deviceId()),
+                         vtnPort.addressPairs().keySet(),
+                         false);
     }
 
     /**
@@ -320,20 +320,6 @@
         }
     }
 
-    private VtnPort getVtnPort(Instance instance) {
-        checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
-        checkNotNull(xosAccess, XOS_ACCESS_ERROR);
-
-        VtnPortId vtnPortId = instance.portId();
-        VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
-        VtnPort vtnPort = portApi.vtnPort(vtnPortId, osAccess);
-        if (vtnPort == null) {
-            log.warn("Failed to get port information of {}", instance);
-            return null;
-        }
-        return vtnPort;
-    }
-
     // TODO get stag from XOS when XOS provides it, extract if from port name for now
     private VlanId getStag(VtnPort vtnPort) {
         checkNotNull(vtnPort);