From: Shai Haim Date: Wed, 22 Mar 2017 15:26:02 +0000 (+0200) Subject: implement unimgr api to netvirt dhcp allocation pool service X-Git-Tag: release/carbon~5 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=69d103303cc559cf8327ff85f44c1647b8cb3361;p=unimgr.git implement unimgr api to netvirt dhcp allocation pool service Change-Id: Ia9d4b2f8d96a9d65652671eb8a526e79682f5d92 Signed-off-by: Shai Haim --- diff --git a/legato-api/pom.xml b/legato-api/pom.xml index 0bd90df8..b6944554 100644 --- a/legato-api/pom.xml +++ b/legato-api/pom.xml @@ -46,11 +46,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL southbound-api ${ovsdb.version} - - org.opendaylight.netvirt - dhcpservice-api - ${vpnservice.version} - diff --git a/legato-api/src/main/yang/unimgr-dhcp.yang b/legato-api/src/main/yang/unimgr-dhcp.yang index 26f75bd7..73694f93 100644 --- a/legato-api/src/main/yang/unimgr-dhcp.yang +++ b/legato-api/src/main/yang/unimgr-dhcp.yang @@ -1,10 +1,10 @@ module unimgr-dhcp { namespace "urn:opendaylight:unimgr:unimgr-dhcp"; prefix "unimgr-dhcp"; - - import dhcp_allocation_pool { - prefix dhcp; - } + + import ietf-inet-types { prefix inet; revision-date "2013-07-15"; } + import ietf-yang-types { prefix yang; } + import mef-types { prefix mef-types; } revision "2016-12-14" { description "It provides required datastore containers to handle DHCP requests @@ -13,11 +13,63 @@ module unimgr-dhcp { container unimgr-dhcp { config true; description "contains non-neutron DHCP allocation"; - list network { - key "network-id"; - leaf network-id { - description "unimgr network id"; - type string; + list unimgr-services { + key "svc-id"; + leaf svc-id { + description "unimgr service id"; + type mef-types:retail-svc-id-type; + } + + list network { + key "network-id"; + leaf network-id { + description "unimgr network id"; + type string; + } + + list unimgr-allocations { + key "subnet"; + leaf subnet { + description "subnet for the dhcp to allocate ip addresses"; + type inet:ip-prefix; + } + + list unimgr-allocation-instance { + key "mac"; + leaf mac { + description "requesting mac"; + type yang:phys-address; + } + leaf allocated-ip { + description "allocated ip address"; + type inet:ip-address; + } + } + } + + list unimgr-allocation-pool { + key "subnet"; + leaf subnet { + description "subnet for the dhcp to allocate ip addresses"; + type inet:ip-prefix; + } + leaf allocate-from { + description "low allocation limit"; + type inet:ip-address; + } + leaf allocate-to { + description "high allocation limit"; + type inet:ip-address; + } + leaf gateway { + description "default gateway for dhcp allocation"; + type inet:ip-address; + } + leaf-list dns-servers { + description "dns server list"; + type inet:ip-address; + } + } } } } diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DhcpAllocationPoolListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DhcpAllocationPoolListener.java new file mode 100644 index 00000000..cdf3be67 --- /dev/null +++ b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DhcpAllocationPoolListener.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017 Hewlett Packard Enterprise, Co. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.unimgr.mef.netvirt; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.RetailSvcIdType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.unimgr.unimgr.dhcp.rev161214.UnimgrDhcp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.unimgr.unimgr.dhcp.rev161214.unimgr.dhcp.UnimgrServices; +import org.opendaylight.yang.gen.v1.urn.opendaylight.unimgr.unimgr.dhcp.rev161214.unimgr.dhcp.unimgr.services.Network; +import org.opendaylight.yang.gen.v1.urn.opendaylight.unimgr.unimgr.dhcp.rev161214.unimgr.dhcp.unimgr.services.network.UnimgrAllocationPool; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DhcpAllocationPoolListener extends UnimgrDataTreeChangeListener { + private static final Logger Log = LoggerFactory.getLogger(DhcpAllocationPoolListener.class); + private ListenerRegistration subnetListenerRegistration; + + public DhcpAllocationPoolListener(final DataBroker dataBroker) { + super(dataBroker); + registerListener(); + } + + public void registerListener() { + try { + final DataTreeIdentifier dataTreeIid = new DataTreeIdentifier<>( + LogicalDatastoreType.CONFIGURATION, + InstanceIdentifier.builder(UnimgrDhcp.class).child(UnimgrServices.class).child(Network.class) + .child(UnimgrAllocationPool.class).build()); + subnetListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this); + Log.info("DhcpAllocationPoolListener created and registered"); + } catch (final Exception e) { + Log.error("DhcpAllocationPoolListener registration failed !", e); + throw new IllegalStateException("DhcpAllocationPoolListener registration Listener failed.", e); + } + } + + @Override + public void close() throws Exception { + subnetListenerRegistration.close(); + } + + @Override + public void add(DataTreeModification newDataObject) { + if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) { + Log.info("Dhcp Allocation Pool {} created", newDataObject.getRootNode().getIdentifier()); + addDhcpAllocationPool(newDataObject); + } + } + + @Override + public void remove(DataTreeModification removedDataObject) { + if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) { + Log.info("Dhcp Allocation Pool {} deleted", removedDataObject.getRootNode().getIdentifier()); + removeDhcpAllocationPool(removedDataObject); + } + } + + @Override + public void update(DataTreeModification modifiedDataObject) { + if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) { + Log.info("subnet {} updated", modifiedDataObject.getRootNode().getIdentifier()); + Log.info("process as delete / create"); + } + } + + private void addDhcpAllocationPool(DataTreeModification newDataObject) { + String networkId = getAllocationPoolNetworkIdFromDataTreeMod(newDataObject); + RetailSvcIdType svcId = getAllocationPoolSvcIdFromDataTreeMod(newDataObject); + NetvirtUtils.createDhcpAllocationPool(dataBroker, newDataObject.getRootNode().getDataAfter(), networkId, svcId); + } + + private void removeDhcpAllocationPool(DataTreeModification removedDataObject) { + String networkId = getAllocationPoolNetworkIdFromDataTreeMod(removedDataObject); + RetailSvcIdType svcId = getAllocationPoolSvcIdFromDataTreeMod(removedDataObject); + IpPrefix subnet = getAllocationPoolSubnetFromDataTreeMod(removedDataObject); + NetvirtUtils.removeDhcpAllocationPool(dataBroker, networkId, svcId, subnet); + } + + private IpPrefix getAllocationPoolSubnetFromDataTreeMod( + DataTreeModification dataObject) { + return dataObject.getRootPath().getRootIdentifier().firstKeyOf(UnimgrAllocationPool.class) + .getSubnet(); + } + + private RetailSvcIdType getAllocationPoolSvcIdFromDataTreeMod( + DataTreeModification dataObject) { + return dataObject.getRootPath().getRootIdentifier().firstKeyOf(UnimgrServices.class).getSvcId(); + } + + private String getAllocationPoolNetworkIdFromDataTreeMod( + DataTreeModification dataObject) { + return dataObject.getRootPath().getRootIdentifier().firstKeyOf(Network.class).getNetworkId(); + } + +} diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefServicesUtils.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefServicesUtils.java index e58043c8..19d28f29 100644 --- a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefServicesUtils.java +++ b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefServicesUtils.java @@ -17,6 +17,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.Subnet; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.EvcElan; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpn; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpnBuilder; import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices; @@ -264,4 +265,36 @@ public class MefServicesUtils { return toReturn; } + public static Optional getOpMefServiceBySvcId(DataBroker dataBroker, RetailSvcIdType svcId) { + InstanceIdentifier mefServiceIdr = InstanceIdentifier.builder(MefServices.class) + .child(MefService.class, new MefServiceKey(svcId)).build(); + return MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, mefServiceIdr); + } + + public static VpnElans getVpnElanByIpUniId(List vpnElansList, String ipUniId) { + if (!vpnElansList.isEmpty()) { + for (VpnElans vpnElan : vpnElansList) { + if (vpnElan.getIpUniId() != null && vpnElan.getIpUniId().getValue().equals(ipUniId)) { + return vpnElan; + } + } + } + return null; + } + + public static String getNetworkIdFromOpMefService(MefService opMefService, String unimgrNetworkId) { + if (opMefService.getMefServiceChoice() instanceof EvcChoice) { + return ((EvcChoice) opMefService.getMefServiceChoice()).getEvc().getAugmentation(EvcElan.class) + .getElanId(); + } else if (opMefService.getMefServiceChoice() instanceof IpvcChoice) { + List vpnElansList = ((IpvcChoice) opMefService.getMefServiceChoice()).getIpvc() + .getAugmentation(IpvcVpn.class).getVpnElans(); + VpnElans vpnElan = MefServicesUtils.getVpnElanByIpUniId(vpnElansList, unimgrNetworkId); + if (vpnElan != null) { + return vpnElan.getElanId(); + } + } + return null; + } + } diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NetvirtUtils.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NetvirtUtils.java index 9202a910..61f8fed7 100644 --- a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NetvirtUtils.java +++ b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NetvirtUtils.java @@ -9,13 +9,22 @@ package org.opendaylight.unimgr.mef.netvirt; import java.math.BigInteger; +import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.EvcElan; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpn; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.EvcChoice; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.IpvcChoice; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.VpnElans; +import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.RetailSvcIdType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder; @@ -31,6 +40,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpc import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.DhcpAllocationPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.dhcp_allocation_pool.Network; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.dhcp_allocation_pool.NetworkKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.dhcp_allocation_pool.network.AllocationPool; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.dhcp_allocation_pool.network.AllocationPoolBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp_allocation_pool.rev161214.dhcp_allocation_pool.network.AllocationPoolKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstanceBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface; @@ -44,6 +59,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.unimgr.unimgr.dhcp.rev161214.unimgr.dhcp.unimgr.services.network.UnimgrAllocationPool; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVxlan; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; @@ -58,11 +74,13 @@ public class NetvirtUtils { private static final Logger logger = LoggerFactory.getLogger(NetvirtUtils.class); private static final long DEFAULT_MAC_TIMEOUT = 300; - public static void createElanInstance(DataBroker dataBroker, String instanceName, boolean isEtree, Long segmentationId) { + public static void createElanInstance(DataBroker dataBroker, String instanceName, boolean isEtree, + Long segmentationId) { createElanInstance(dataBroker, instanceName, isEtree, segmentationId, DEFAULT_MAC_TIMEOUT); } - public static void createElanInstance(DataBroker dataBroker, String instanceName, boolean isEtree, Long segmentationId, Long macTimeout) { + public static void createElanInstance(DataBroker dataBroker, String instanceName, boolean isEtree, + Long segmentationId, Long macTimeout) { ElanInstanceBuilder einstBuilder = createElanInstanceBuilder(instanceName, segmentationId, macTimeout); if (isEtree) { @@ -90,7 +108,8 @@ public class NetvirtUtils { saveElanInstance(instanceName, tx, einstBuilder); } - public static void updateElanInstance(String instanceName, WriteTransaction tx, Long segmentationId, Long macTimeout) { + public static void updateElanInstance(String instanceName, WriteTransaction tx, Long segmentationId, + Long macTimeout) { ElanInstanceBuilder einstBuilder = createElanInstanceBuilder(instanceName, segmentationId, macTimeout); saveElanInstance(instanceName, tx, einstBuilder); } @@ -143,8 +162,8 @@ public class NetvirtUtils { SplitHorizon sh = new SplitHorizonBuilder().setOverrideSplitHorizonProtection(true).build(); ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentIfaceName); interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class) - .addAugmentation(SplitHorizon.class, sh) - .addAugmentation(IfL2vlan.class, ifL2vlan).addAugmentation(ParentRefs.class, parentRefsBuilder.build()); + .addAugmentation(SplitHorizon.class, sh).addAugmentation(IfL2vlan.class, ifL2vlan) + .addAugmentation(ParentRefs.class, parentRefsBuilder.build()); return interfaceBuilder.build(); } @@ -156,7 +175,8 @@ public class NetvirtUtils { return createElanInstanceBuilder(instanceName, segmentationId, DEFAULT_MAC_TIMEOUT); } - private static ElanInstanceBuilder createElanInstanceBuilder(String instanceName, Long segmentationId, Long macTimeout) { + private static ElanInstanceBuilder createElanInstanceBuilder(String instanceName, Long segmentationId, + Long macTimeout) { if (segmentationId == null) { segmentationId = Long.valueOf(Math.abs((short) instanceName.hashCode())); } @@ -289,13 +309,64 @@ public class NetvirtUtils { } catch (InterruptedException e) { } } + public static void safeSleep(short sec) { try { Thread.yield(); - Thread.sleep(1000*sec); + Thread.sleep(1000 * sec); } catch (InterruptedException e) { } } + public static void createDhcpAllocationPool(DataBroker dataBroker, UnimgrAllocationPool unimgrAllocationPool, + String unimgrNetworkId, RetailSvcIdType svcId) { + String networkId = convertNetworkToNetvirtNetwork(dataBroker, unimgrNetworkId, svcId); + if (networkId != null) { + // add allocation pool to netvirt + MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, + createDhcpAllocationPoolInstanceIdentifier(networkId, unimgrAllocationPool.getKey().getSubnet()), + buildDhcpAllocationPool(unimgrAllocationPool)); + } else { + logger.warn("no network found for svc-id {}", svcId); + } + } + + public static void removeDhcpAllocationPool(DataBroker dataBroker, String unimgrNetworkId, RetailSvcIdType svcId, + IpPrefix subnet) { + String networkId = convertNetworkToNetvirtNetwork(dataBroker, unimgrNetworkId, svcId); + if (networkId != null) { + // remove allocation pool from netvirt + MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, + createDhcpAllocationPoolInstanceIdentifier(networkId, subnet)); + } else { + logger.warn("no network found for svc-id {}", svcId); + } + } + + private static String convertNetworkToNetvirtNetwork(DataBroker dataBroker, String unimgrNetworkId, + RetailSvcIdType svcId) { + Optional optionalOpMefService = MefServicesUtils.getOpMefServiceBySvcId(dataBroker, svcId); + if (!optionalOpMefService.isPresent()) { + logger.warn("no mef-service found for svc-id {}", svcId); + return null; + } + MefService opMefService = optionalOpMefService.get(); + return MefServicesUtils.getNetworkIdFromOpMefService(opMefService, unimgrNetworkId); + } + + private static InstanceIdentifier createDhcpAllocationPoolInstanceIdentifier(String networkId, + IpPrefix subnet) { + return InstanceIdentifier.builder(DhcpAllocationPool.class).child(Network.class, new NetworkKey(networkId)) + .child(AllocationPool.class, new AllocationPoolKey(subnet)).build(); + } + + private static AllocationPool buildDhcpAllocationPool(UnimgrAllocationPool unimgrAllocationPool) { + AllocationPool allocationPool = new AllocationPoolBuilder() + .setKey(new AllocationPoolKey(unimgrAllocationPool.getSubnet())) + .setSubnet(unimgrAllocationPool.getSubnet()).setAllocateFrom(unimgrAllocationPool.getAllocateFrom()) + .setAllocateTo(unimgrAllocationPool.getAllocateTo()).setDnsServers(unimgrAllocationPool.getDnsServers()) + .setGateway(unimgrAllocationPool.getGateway()).build(); + return allocationPool; + } } diff --git a/netvirt/src/main/resources/org/opendaylight/blueprint/netvirt-driver.xml b/netvirt/src/main/resources/org/opendaylight/blueprint/netvirt-driver.xml index fab4380c..c6ae4f89 100644 --- a/netvirt/src/main/resources/org/opendaylight/blueprint/netvirt-driver.xml +++ b/netvirt/src/main/resources/org/opendaylight/blueprint/netvirt-driver.xml @@ -58,5 +58,9 @@ + + + +