From: Rashmi Pujar Date: Fri, 22 Jan 2016 19:35:00 +0000 (-0500) Subject: Integration of vpnintent bundle functionality X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=vpnservice.git;a=commitdiff_plain;h=35b858a5b9f14e52a8dfe28a22dae2e15a10b51a Integration of vpnintent bundle functionality Change-Id: I0a55cc2b67635a09a5200ecd2bc7451004f898a0 Signed-off-by: Rashmi Pujar --- diff --git a/distribution/karaf/pom.xml b/distribution/karaf/pom.xml index 3fdedb91..c6f059b9 100644 --- a/distribution/karaf/pom.xml +++ b/distribution/karaf/pom.xml @@ -22,7 +22,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL 3.1.1 - odl-vpnservice-core + diff --git a/vpnintent/api/src/main/yang/vpnintent.yang b/vpnintent/api/src/main/yang/vpnintent.yang index e9a971db..f0884e4d 100644 --- a/vpnintent/api/src/main/yang/vpnintent.yang +++ b/vpnintent/api/src/main/yang/vpnintent.yang @@ -88,5 +88,46 @@ module vpnintent { container mpls-labels { uses labels; - } + } + + rpc add-vpn-endpoint{ + description + "Add VPN endpoint."; + input { + leaf vpn-name { + type string; + description "VPN name"; + mandatory true; + } + uses endpoint-fields; + } + } + + rpc remove-vpn-endpoint{ + description + "Remove VPN endpoint."; + input { + leaf vpn-name { + type string; + description "VPN name"; + mandatory true; + } + leaf site-name{ + type string; + description "VPN member site name."; + } + } + } + + rpc remove-vpn{ + description + "Remove VPN and its endpoints."; + input { + leaf vpn-name { + type string; + description "VPN name"; + mandatory true; + } + } + } } diff --git a/vpnintent/impl/pom.xml b/vpnintent/impl/pom.xml index ab00412e..0be7d94b 100644 --- a/vpnintent/impl/pom.xml +++ b/vpnintent/impl/pom.xml @@ -25,11 +25,6 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL - - org.opendaylight.vpnservice - mdsalutil-api - ${project.version} - ${project.groupId} vpnintent-api diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java index 99d0edc9..dda5447d 100644 --- a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java +++ b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/IntentServiceManager.java @@ -15,6 +15,7 @@ import java.util.UUID; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.nic.utils.MdsalUtils; +import org.opendaylight.vpnservice.utils.IidFactory; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.constraints.rev150122.FailoverType; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents; import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder; @@ -57,7 +58,7 @@ public class IntentServiceManager { public static final String FAST_REROUTE = "fast-reroute"; public static final String SLOW_REROUTE = "slow-reroute"; private final DataBroker dataBroker; - private static final InstanceIdentifier INTENTS_IID = InstanceIdentifier.builder(Intents.class).build(); + private static final InstanceIdentifier INTENTS_IID = IidFactory.getIntentsIid(); private MdsalUtils mdsal; public IntentServiceManager(DataBroker dataBroker) { diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/VpnintentProvider.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/VpnintentProvider.java index 715c1735..1618bb1e 100644 --- a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/VpnintentProvider.java +++ b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/impl/VpnintentProvider.java @@ -7,41 +7,74 @@ */ package org.opendaylight.vpnservice.impl; +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.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; +import org.opendaylight.nic.mapping.api.IntentMappingService; +import org.opendaylight.nic.utils.MdsalUtils; +import org.opendaylight.vpnservice.utils.IidFactory; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.AddVpnEndpointInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.FailoverType; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabelsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnEndpointInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnintentService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntentsKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Preconditions; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; -public class VpnintentProvider implements BindingAwareProvider, AutoCloseable { +public class VpnintentProvider implements VpnintentService, BindingAwareProvider, AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(VpnintentProvider.class); - public static final InstanceIdentifier VPN_INTENT_IID = InstanceIdentifier.builder(Vpns.class).build(); - public static final InstanceIdentifier LABELS_IID = InstanceIdentifier.builder(MplsLabels.class).build(); + public static final InstanceIdentifier LABELS_IID = IidFactory.getMplsLabelsIid(); + public static final InstanceIdentifier VPN_IID = IidFactory.getVpnsIid(); + public static final InstanceIdentifier VPN_INTENT_IID = IidFactory.getVpnIntentIid(); + public static final InstanceIdentifier ENDPOINT_IID = IidFactory.getEndpointIid(); private DataBroker dataBroker; + private IntentMappingService intentMappingService; + private BindingAwareBroker.RpcRegistration rpcRegistration = null; + private MdsalUtils mdsal; @Override public void onSessionInitiated(ProviderContext session) { LOG.info("VpnintentProvider Session Initiated"); dataBroker = session.getSALService(DataBroker.class); + rpcRegistration = session.addRpcImplementation(VpnintentService.class, this); + this.mdsal = new MdsalUtils(this.dataBroker); + + // Load IntentMappingService Reference + loadIntentMappingServiceReference(); Vpns vpns = new VpnsBuilder().build(); MplsLabels labels = new MplsLabelsBuilder().build(); // Initialize MD-SAL data store for vpn-intents and mpls-labels - initDatastore(LogicalDatastoreType.CONFIGURATION, VPN_INTENT_IID, vpns); + initDatastore(LogicalDatastoreType.CONFIGURATION, VPN_IID, vpns); initDatastore(LogicalDatastoreType.OPERATIONAL, LABELS_IID, labels); } @@ -69,4 +102,176 @@ public class VpnintentProvider implements BindingAwareProvider, AutoCloseable { }); LOG.info("initDatastore: data populated: {}, {}, {}", store, iid, object); } + + @Override + public Future> removeVpn(RemoveVpnInput input) { + InstanceIdentifier vpnIdentifier = InstanceIdentifier.builder(Vpns.class) + .child(VpnIntents.class, new VpnIntentsKey(input.getVpnName())).build(); + MappingServiceManager msManager = new MappingServiceManager(intentMappingService); + MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker); + + VpnIntents vpn = getVpn(input.getVpnName()); + + if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) { + for (Endpoint endpoint : vpn.getEndpoint()) { + // Release MPLS label + mplsManager.deleteLabel(endpoint); + + // Remove all intents related to this endpoint + IntentServiceManager intentManager = new IntentServiceManager(dataBroker); + intentManager.removeIntentsByEndpoint(endpoint.getSiteName()); + + // Remove info from Mapping Service + msManager.delete(endpoint.getSiteName()); + } + } + + mdsal.delete(LogicalDatastoreType.CONFIGURATION, vpnIdentifier); + LOG.info("Deleted VPN {}", input.getVpnName()); + return Futures.immediateFuture(RpcResultBuilder. success().build()); + } + + @Override + public Future> addVpnEndpoint(AddVpnEndpointInput input) { + Endpoint currentEndpoint = new EndpointBuilder().setIpPrefix(input.getIpPrefix()) + .setSiteName(input.getSiteName()).setSwitchPortId(input.getSwitchPortId()) + .setKey(new EndpointKey(input.getSiteName())).build(); + VpnIntents vpn = getVpn(input.getVpnName()); + String failOverType = null; + if (vpn.isPathProtection() && vpn.getFailoverType()!= null) { + if (vpn.getFailoverType().equals(FailoverType.FastReroute)) { + failOverType = IntentServiceManager.FAST_REROUTE; + } else if(vpn.getFailoverType().equals(FailoverType.SlowReroute)) { + failOverType = IntentServiceManager.SLOW_REROUTE; + } + } + + MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker); + + // Get unique MPLS label + Long mplsLabel = mplsManager.getUniqueLabel(currentEndpoint); + + // Add info into Mapping Service + MappingServiceManager msManager = new MappingServiceManager(intentMappingService); + msManager.add(currentEndpoint.getSiteName(), extractIP(currentEndpoint.getIpPrefix()), + currentEndpoint.getSwitchPortId(), mplsLabel, null); + + if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) { + IntentServiceManager intentManager = new IntentServiceManager(dataBroker); + + for (Endpoint member : vpn.getEndpoint()) { + // Create mesh of Intents + intentManager.addIntent(member.getSiteName(), currentEndpoint.getSiteName(), + IntentServiceManager.ACTION_ALLOW, failOverType); + intentManager.addIntent(currentEndpoint.getSiteName(), member.getSiteName(), + IntentServiceManager.ACTION_ALLOW, failOverType); + } + } + // Associate endpoint with VPN + addEndpointToVpn(vpn, currentEndpoint); + + return Futures.immediateFuture(RpcResultBuilder. success().build()); + } + + /** + * @param IpPrefix + * object + * @return String representation of IP prefix + */ + private String extractIP(IpPrefix ipPrefix) { + String ip = null; + if (ipPrefix.getIpv4Prefix() != null) { + ip = ipPrefix.getIpv4Prefix().getValue(); + } else if (ipPrefix.getIpv6Prefix() != null) { + ip = ipPrefix.getIpv6Prefix().getValue(); + } + return ip; + } + + /** + * @param vpnName + * VPN name + * @return VPN instance + */ + private VpnIntents getVpn(String vpnName) { + InstanceIdentifier identifier = InstanceIdentifier.builder(Vpns.class) + .child(VpnIntents.class, new VpnIntentsKey(vpnName)).build(); + + VpnIntents vpnIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, identifier); + Preconditions.checkNotNull(vpnIntents); + return vpnIntents; + } + + @Override + public Future> removeVpnEndpoint(RemoveVpnEndpointInput input) { + Endpoint endpoint = getEndpoint(input.getVpnName(), input.getSiteName()); + + // Release MPLS label + MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker); + mplsManager.deleteLabel(endpoint); + + // Remove all intents related to this endpoint + IntentServiceManager intentManager = new IntentServiceManager(dataBroker); + intentManager.removeIntentsByEndpoint(input.getSiteName()); + + // Remove endpoint from VPN + removeEndpointFromVpn(input.getVpnName(), input.getSiteName()); + + return Futures.immediateFuture(RpcResultBuilder. success().build()); + } + + /** + * @param siteName + * Site name of the VPN member + * @return VPN member (Endpoint) + */ + private Endpoint getEndpoint(String vpnName, String siteName) { + InstanceIdentifier endpointID = InstanceIdentifier.builder(Vpns.class) + .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName)) + .build(); + + return mdsal.read(LogicalDatastoreType.CONFIGURATION, endpointID); + } + + /** + * @param vpnName + * VPN name + * @param siteName + * Site name + */ + private void removeEndpointFromVpn(String vpnName, String siteName) { + InstanceIdentifier identifier = InstanceIdentifier.builder(Vpns.class) + .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName)) + .build(); + + mdsal.delete(LogicalDatastoreType.CONFIGURATION, identifier); + LOG.info("Deleted VPN member : {} from VPN: {}", siteName, vpnName); + } + + /** + * @param vpn + * VPN + * @param vpnMember + * VPN member (endpoint) + */ + private void addEndpointToVpn(VpnIntents vpn, Endpoint vpnMember) { + InstanceIdentifier identifier = InstanceIdentifier.builder(Vpns.class) + .child(VpnIntents.class, vpn.getKey()) + .child(Endpoint.class, vpnMember.getKey()).build(); + + mdsal.put(LogicalDatastoreType.CONFIGURATION, identifier, vpnMember); + LOG.info("Added VPN member : {} to VPN: {}", vpnMember.getSiteName(), vpn.getVpnName()); + } + + /** + * Load IntentMappingService reference + */ + private void loadIntentMappingServiceReference() { + ServiceReference serviceReference = getBundleCtx().getServiceReference(IntentMappingService.class); + intentMappingService = (IntentMappingService) getBundleCtx().getService(serviceReference); + } + + private BundleContext getBundleCtx() { + return FrameworkUtil.getBundle(this.getClass()).getBundleContext(); + } } diff --git a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/utils/IidFactory.java b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/utils/IidFactory.java index d05b69f2..e08cf67f 100644 --- a/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/utils/IidFactory.java +++ b/vpnintent/impl/src/main/java/org/opendaylight/vpnservice/utils/IidFactory.java @@ -8,9 +8,13 @@ package org.opendaylight.vpnservice.utils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.Label; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; public class IidFactory { @@ -22,4 +26,20 @@ public class IidFactory { public static InstanceIdentifier