Vxlan/Gre co-existence,Alarms,tunnelstate,TR fixes
[vpnservice.git] / itm / itm-impl / src / main / java / org / opendaylight / vpnservice / itm / rpc / ItmManagerRpcService.java
index c3adcc40e2b9255c54844940b04e56d8b7678248..26b007a9db7f421fcc3402c3875415697b5ffce5 100644 (file)
 package org.opendaylight.vpnservice.itm.rpc;
 
 import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Future;
 
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeMplsOverGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVtepsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVtepsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelAddWorker;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelDeleteWorker;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.vpnservice.itm.impl.ItmUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.Tunnel;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.TunnelKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.AddExternalTunnelEndpointInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.BuildExternalTunnelFromDpnsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveExternalTunnelEndpointInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveExternalTunnelFromDpnsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 
 public class ItmManagerRpcService implements ItmRpcService {
 
-   private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
-        DataBroker dataBroker;
-        public ItmManagerRpcService(DataBroker dataBroker) {
+    private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
+    DataBroker dataBroker;
+    private IMdsalApiManager mdsalManager;
+
+
+    public void setMdsalManager(IMdsalApiManager mdsalManager) {
+        this.mdsalManager = mdsalManager;
+    }
+
+    IdManagerService idManagerService;
+
+    public ItmManagerRpcService(DataBroker dataBroker, IdManagerService idManagerService) {
         this.dataBroker = dataBroker;
+        this.idManagerService = idManagerService;
+    }
+
+    @Override
+    public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
+        RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
+        BigInteger sourceDpn = input.getSourceDpid() ;
+        BigInteger destinationDpn = input.getDestinationDpid() ;
+        InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
+                TunnelList.class)
+                .child(InternalTunnel.class, new InternalTunnelKey(destinationDpn, sourceDpn, input.getTunnelType()));
+
+        Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+
+        if( tnl != null && tnl.isPresent())
+        {
+            InternalTunnel tunnel = tnl.get();
+            GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
+            output.setInterfaceName(tunnel.getTunnelInterfaceName()) ;
+            resultBld = RpcResultBuilder.success();
+            resultBld.withResult(output.build()) ;
+        }else {
+            resultBld = RpcResultBuilder.failed();
+        }
+
+        return Futures.immediateFuture(resultBld.build());
     }
-        
-     @Override
-     public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
-         RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
-         BigInteger sourceDpn = input.getSourceDpid() ;
-         BigInteger destinationDpn = input.getDestinationDpid() ;
-         InstanceIdentifier<Tunnel> path = InstanceIdentifier.create(
-                 TunnelList.class)
-                     .child(Tunnel.class, new TunnelKey(destinationDpn, sourceDpn));      
-         
-         Optional<Tunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
-
-         if( tnl != null && tnl.isPresent())
-         {
-              Tunnel tunnel = tnl.get();
-              GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
-              output.setInterfaceName(tunnel.getTunnelInterfaceName()) ;
-              resultBld = RpcResultBuilder.success();
-              resultBld.withResult(output.build()) ;
-         }else {
-             resultBld = RpcResultBuilder.failed();
-         }
-         
-         return Futures.immediateFuture(resultBld.build());
-     }
 
 
     @Override
     public Future<RpcResult<Void>> removeExternalTunnelEndpoint(
             RemoveExternalTunnelEndpointInput input) {
-        // TODO Auto-generated method stub
-        return null;
+        //Ignore the Futures for now
+        final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+        List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
+        ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService,meshedDpnList , input.getDestinationIp(), input.getTunnelType());
+        result.set(RpcResultBuilder.<Void>success().build());
+        return result;
     }
 
     @Override
@@ -96,7 +117,8 @@ public class ItmManagerRpcService implements ItmRpcService {
             RemoveExternalTunnelFromDpnsInput input) {
         //Ignore the Futures for now
         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
-//        ItmExternalTunnelDeleteWorker.buildTunnelsFromDpnToExternalEndPoint(dataBroker, input.getDpnId(), null, input.getDestinationIp());
+        List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDPNTEPListFromDPNId(dataBroker, input.getDpnId()) ;
+        ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService, cfgDpnList, input.getDestinationIp(), input.getTunnelType());
         result.set(RpcResultBuilder.<Void>success().build());
         return result;
     }
@@ -106,7 +128,7 @@ public class ItmManagerRpcService implements ItmRpcService {
             BuildExternalTunnelFromDpnsInput input) {
         //Ignore the Futures for now
         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
-        List<ListenableFuture<Void>> extTunnelResultList = ItmExternalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(dataBroker, input.getDpnId(), input.getDestinationIp(), input.getTunnelType());
+        List<ListenableFuture<Void>> extTunnelResultList = ItmExternalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(dataBroker, idManagerService,input.getDpnId(), input.getDestinationIp(), input.getTunnelType());
         for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
             Futures.addCallback(extTunnelResult, new FutureCallback<Void>(){
 
@@ -134,7 +156,8 @@ public class ItmManagerRpcService implements ItmRpcService {
 
         //Ignore the Futures for now
         final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
-    //    ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker, null, input.getDestinationIp()) ;
+        List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
+        ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker, idManagerService,meshedDpnList, input.getDestinationIp(), input.getTunnelType()) ;
         result.set(RpcResultBuilder.<Void>success().build());
         return result;
     }
@@ -144,26 +167,405 @@ public class ItmManagerRpcService implements ItmRpcService {
             GetExternalTunnelInterfaceNameInput input) {
         final SettableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> result = SettableFuture.create() ;
         RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
-        BigInteger sourceDpn = input.getSourceDpid() ;
-        IpAddress destinationIp = input.getDestinationIp() ;
+        String sourceNode = input.getSourceNode();
+        String dstNode = input.getDestinationNode();
         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
                 ExternalTunnelList.class)
-                    .child(ExternalTunnel.class, new ExternalTunnelKey(destinationIp, sourceDpn));      
-        
+                .child(ExternalTunnel.class, new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType()));
+
         Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
 
         if( ext != null && ext.isPresent())
         {
-             ExternalTunnel exTunnel = ext.get();
-             GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ;
-             output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ;
-             resultBld = RpcResultBuilder.success();
-             resultBld.withResult(output.build()) ;
+            ExternalTunnel exTunnel = ext.get();
+            GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ;
+            output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ;
+            resultBld = RpcResultBuilder.success();
+            resultBld.withResult(output.build()) ;
         }else {
             resultBld = RpcResultBuilder.failed();
         }
-        
+
+        return Futures.immediateFuture(resultBld.build());
+    }
+
+    @Override
+    public Future<RpcResult<java.lang.Void>> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
+        LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}", input.getDpnId() , input.getServiceId(), input.getInstruction());
+        final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+        int serviceId = input.getServiceId() ;
+        List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
+        byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+        // Flags Byte
+        byte Flags = (byte) 0x08;
+        vxLANHeader[0] = Flags;
+
+        // Extract the serviceId details and imprint on the VxLAN Header
+        vxLANHeader[4] = (byte) (serviceId >> 16);
+        vxLANHeader[5] = (byte) (serviceId >> 8);
+        vxLANHeader[6] = (byte) (serviceId >> 0);
+
+        // Matching metadata
+//        mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
+//                new BigInteger(1, vxLANHeader),
+//                MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
+
+        Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+                getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5, String.format("%s:%d","ITM Flow Entry ",serviceId),
+                0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
+
+        ListenableFuture<Void> installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
+        Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
+
+            @Override
+            public void onSuccess(Void aVoid) {
+                result.set(RpcResultBuilder.<Void>success().build());
+            }
+
+            @Override
+            public void onFailure(Throwable error) {
+                String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
+                LOG.error("create terminating service actions failed. {}. {}", msg, error);
+                result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+            }
+        });
+       // result.set(RpcResultBuilder.<Void>success().build());
+        return result;
+    }
+
+    @Override
+    public Future<RpcResult<java.lang.Void>> removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
+        LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}", input.getDpnId(), input.getServiceId());
+        final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+        Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+                getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5, String.format("%s:%d","ITM Flow Entry ",input.getServiceId()),
+                0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),getTunnelMatchesForServiceId(input.getServiceId()), null );
+
+        ListenableFuture<Void> installFlowResult = mdsalManager.removeFlow(input.getDpnId(), terminatingServiceTableFlow);
+        Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
+
+            @Override
+            public void onSuccess(Void aVoid) {
+                result.set(RpcResultBuilder.<Void>success().build());
+            }
+
+            @Override
+            public void onFailure(Throwable error) {
+                String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
+                LOG.error("remove terminating service actions failed. {}. {}", msg, error);
+                result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+            }
+        });
+        //result.set(RpcResultBuilder.<Void>success().build());
+
+        return result ;
+    }
+
+
+    public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
+        List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+        byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+        // Flags Byte
+        byte Flags = (byte) 0x08;
+        vxLANHeader[0] = Flags;
+
+        // Extract the serviceId details and imprint on the VxLAN Header
+        vxLANHeader[4] = (byte) (serviceId >> 16);
+        vxLANHeader[5] = (byte) (serviceId >> 8);
+        vxLANHeader[6] = (byte) (serviceId >> 0);
+
+        // Matching metadata
+        mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[]{
+                BigInteger.valueOf(serviceId)}));
+
+        return mkMatches;
+    }
+
+    private String getFlowRef(long termSvcTable, int svcId) {
+        return new StringBuffer().append(termSvcTable).append(svcId).toString();
+    }
+
+    @Override
+    public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
+            GetInternalOrExternalInterfaceNameInput input) {
+        RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = RpcResultBuilder.failed();
+        BigInteger srcDpn = input.getSourceDpid() ;
+        String srcNode = srcDpn.toString();
+        IpAddress dstIp = input.getDestinationIp() ;
+        InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(
+                ExternalTunnelList.class)
+                .child(ExternalTunnel.class, new ExternalTunnelKey(String.valueOf(dstIp), srcDpn.toString(), TunnelTypeMplsOverGre.class));
+
+        Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
+
+        if( ext != null && ext.isPresent())
+        {
+            ExternalTunnel extTunnel = ext.get();
+            GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(extTunnel.getTunnelInterfaceName() );
+            resultBld = RpcResultBuilder.success();
+            resultBld.withResult(output.build()) ;
+        } else {
+            List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker);
+            // Look for external tunnels if not look for internal tunnel
+            for (DPNTEPsInfo teps : meshedDpnList) {
+                TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
+                if (dstIp.equals(firstEndPt.getIpAddress())) {
+                    InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
+                            TunnelList.class)
+                            .child(InternalTunnel.class, new InternalTunnelKey(teps.getDPNID(), srcDpn, input.getTunnelType()));
+
+                    Optional<InternalTunnel>
+                            tnl =
+                            ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+                    if (tnl != null && tnl.isPresent()) {
+                        InternalTunnel tunnel = tnl.get();
+                        GetInternalOrExternalInterfaceNameOutputBuilder
+                                output =
+                                new GetInternalOrExternalInterfaceNameOutputBuilder()
+                                        .setInterfaceName(tunnel.getTunnelInterfaceName());
+                        resultBld = RpcResultBuilder.success();
+                        resultBld.withResult(output.build());
+                        break;
+                    }
+                }
+            }
+        }
         return Futures.immediateFuture(resultBld.build());
+    }
+
+    @Override
+    public Future<RpcResult<java.lang.Void>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
+        final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+        try {
+            final IpAddress hwIp = input.getIpAddress();
+            final String node_id = input.getNodeId();
+            InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
+            Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
+            if (tZonesOptional.isPresent()) {
+                TransportZones tZones = tZonesOptional.get();
+                if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
+                    LOG.error("No teps configured");
+                    result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
+                    return result;
+                }
+                String transportZone = tZones.getTransportZone().get(0).getZoneName();
+                if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
+                    result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
+                    return result;
+                }
+                SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
+                DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id);
+                InstanceIdentifier<DeviceVteps> path =
+                                InstanceIdentifier.builder(TransportZones.class)
+                                                .child(TransportZone.class, new TransportZoneKey(transportZone))
+                                                .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
+                WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+                //TO DO: add retry if it fails
+                t.delete(LogicalDatastoreType.CONFIGURATION, path);
+
+                ListenableFuture<Void> futureCheck = t.submit();
+                Futures.addCallback(futureCheck, new FutureCallback<Void>() {
+
+                    @Override
+                    public void onSuccess(Void aVoid) {
+                        result.set(RpcResultBuilder.<Void>success().build());
+                    }
+
+                    @Override
+                    public void onFailure(Throwable error) {
+                        String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
+                        LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
+                        result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+                    }
+                });
+            }
+            return result;
+        } catch (Exception e) {
+            RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
+                            withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
+            return Futures.immediateFuture(resultBuilder.build());
+        }
+    }
+
+    @Override
+    public Future<RpcResult<java.lang.Void>> addL2GwDevice(AddL2GwDeviceInput input) {
+
+        final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+        try {
+            final IpAddress hwIp = input.getIpAddress();
+            final String node_id = input.getNodeId();
+            InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
+            Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
+            if (tZonesOptional.isPresent()) {
+                TransportZones tZones = tZonesOptional.get();
+                if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
+                    LOG.error("No teps configured");
+                    result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
+                    return result;
+                }
+                String transportZone = tZones.getTransportZone().get(0).getZoneName();
+                if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
+                    result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
+                    return result;
+                }
+                SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
+                DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id);
+                InstanceIdentifier<DeviceVteps> path =
+                        InstanceIdentifier.builder(TransportZones.class)
+                                .child(TransportZone.class, new TransportZoneKey(transportZone))
+                                .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
+                DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp).setNodeId(
+                                node_id).setTopologyId(input.getTopologyId()).build();
+                WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+                //TO DO: add retry if it fails
+                t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
+
+                ListenableFuture<Void> futureCheck = t.submit();
+                Futures.addCallback(futureCheck, new FutureCallback<Void>() {
+
+                    @Override
+                    public void onSuccess(Void aVoid) {
+                        result.set(RpcResultBuilder.<Void>success().build());
+                    }
+
+                    @Override
+                    public void onFailure(Throwable error) {
+                        String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
+                        LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
+                        result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+                    }
+                });
+            }
+            else {
+                result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
+                return result;
+            }
+            return result;
+        } catch (Exception e) {
+            RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
+                    withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
+            return Futures.immediateFuture(resultBuilder.build());
+        }
+    }
+
+    @Override
+    public Future<RpcResult<java.lang.Void>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input)
+    {
+        final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+        try {
+            final IpAddress hwIp = input.getIpAddress();
+            final List<String> node_id = input.getNodeId();
+            InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
+            Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
+            if (tZonesOptional.isPresent()) {
+                TransportZones tZones = tZonesOptional.get();
+                if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
+                    LOG.error("No teps configured");
+                    result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
+                    return result;
+                }
+                String transportZone = tZones.getTransportZone().get(0).getZoneName();
+                if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
+                    result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
+                    return result;
+                }
+                SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
+                DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id.get(0));
+                InstanceIdentifier<DeviceVteps> path =
+                                InstanceIdentifier.builder(TransportZones.class)
+                                                .child(TransportZone.class, new TransportZoneKey(transportZone))
+                                                .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
+                DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp).setNodeId(node_id.get(0)).setTopologyId(input.getTopologyId()).build();
+                WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+                LOG.trace("writing hWvtep{}",deviceVtep);
+                t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
+                if(node_id.size() == 2) {
+                    LOG.trace("second node-id {}",node_id.get(1));
+                    DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, node_id.get(1));
+                    InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier.builder(TransportZones.class)
+                                    .child(TransportZone.class, new TransportZoneKey(transportZone))
+                                    .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey2).build();
+                    DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().setKey(deviceVtepKey2).setIpAddress(hwIp).setNodeId(node_id.get(1))
+                                    .setTopologyId(input.getTopologyId()).build();
+                    LOG.trace("writing {}",deviceVtep2);
+                    t.put(LogicalDatastoreType.CONFIGURATION, path2, deviceVtep2, true);
+                }ListenableFuture<Void> futureCheck = t.submit();
+                Futures.addCallback(futureCheck, new FutureCallback<Void>() {
+                    @Override
+                    public void onSuccess(Void aVoid) {
+                        result.set(RpcResultBuilder.<Void>success().build());
+                    }
+                    @Override
+                    public void onFailure(Throwable error) {
+                        String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
+                        LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
+                        result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+                    }
+                });
+            }
+            return result;
+        } catch (Exception e) {
+            RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
+                            withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
+            return Futures.immediateFuture(resultBuilder.build());
+        }
+    }
+    @Override
+    public Future<RpcResult<Void>> deleteL2GwMlagDevice(DeleteL2GwMlagDeviceInput input) {
+        final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+        try {
+            final IpAddress hwIp = input.getIpAddress();
+            final List<String> node_id = input.getNodeId();
+            InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
+            Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
+            if (tZonesOptional.isPresent()) {
+                TransportZones tZones = tZonesOptional.get();
+                if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
+                    LOG.error("No teps configured");
+                    result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
+                    return result;
+                }
+                String transportZone = tZones.getTransportZone().get(0).getZoneName();
+                if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
+                    result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
+                    return result;
+                }
+                SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
+                DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id.get(0));
+                InstanceIdentifier<DeviceVteps> path =
+                                InstanceIdentifier.builder(TransportZones.class)
+                                                .child(TransportZone.class, new TransportZoneKey(transportZone))
+                                                .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
+                                                deviceVtepKey).build();
+                WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+                t.delete(LogicalDatastoreType.CONFIGURATION, path);
+                DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, node_id.get(1));
+                InstanceIdentifier<DeviceVteps> path2 =
+                                InstanceIdentifier.builder(TransportZones.class)
+                                                .child(TransportZone.class, new TransportZoneKey(transportZone))
+                                                .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
+                                                deviceVtepKey2).build();
+                t.delete(LogicalDatastoreType.CONFIGURATION, path2);
+                ListenableFuture<Void> futureCheck = t.submit();
+                Futures.addCallback(futureCheck, new FutureCallback<Void>() {
+                    @Override
+                    public void onSuccess(Void aVoid) {
+                        result.set(RpcResultBuilder.<Void>success().build());
+                    }
+                    @Override
+                    public void onFailure(Throwable error) {
+                        String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
+                        LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
+                        result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+                    }
+                });
+            }
+            return result;
+        } catch (Exception e) {
+            RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
+                            withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
+            return Futures.immediateFuture(resultBuilder.build());
+        }
     }
 }