2 * Copyright (c) 2016 Inocybe Technologies and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.vpnservice.impl;
10 import java.util.concurrent.Future;
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
14 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
15 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
16 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
17 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
18 import org.opendaylight.nic.mapping.api.IntentMappingService;
19 import org.opendaylight.nic.utils.MdsalUtils;
20 import org.opendaylight.vpnservice.utils.IidFactory;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.AddVpnEndpointInput;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.FailoverType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabelsBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnEndpointInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnintentService;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnsBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntentsKey;
36 import org.opendaylight.yangtools.yang.binding.DataObject;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.common.RpcResult;
39 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
40 import org.osgi.framework.BundleContext;
41 import org.osgi.framework.FrameworkUtil;
42 import org.osgi.framework.ServiceReference;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 import com.google.common.base.Preconditions;
47 import com.google.common.util.concurrent.FutureCallback;
48 import com.google.common.util.concurrent.Futures;
50 public class VpnintentProvider implements VpnintentService, BindingAwareProvider, AutoCloseable {
52 private static final Logger LOG = LoggerFactory.getLogger(VpnintentProvider.class);
53 public static final InstanceIdentifier<MplsLabels> LABELS_IID = IidFactory.getMplsLabelsIid();
54 public static final InstanceIdentifier<Vpns> VPN_IID = IidFactory.getVpnsIid();
55 public static final InstanceIdentifier<VpnIntents> VPN_INTENT_IID = IidFactory.getVpnIntentIid();
56 public static final InstanceIdentifier<Endpoint> ENDPOINT_IID = IidFactory.getEndpointIid();
58 private DataBroker dataBroker;
59 private IntentMappingService intentMappingService;
60 private BindingAwareBroker.RpcRegistration<VpnintentService> rpcRegistration = null;
61 private MdsalUtils mdsal;
64 public void onSessionInitiated(ProviderContext session) {
65 LOG.info("VpnintentProvider Session Initiated");
66 dataBroker = session.getSALService(DataBroker.class);
67 rpcRegistration = session.addRpcImplementation(VpnintentService.class, this);
68 this.mdsal = new MdsalUtils(this.dataBroker);
70 // Load IntentMappingService Reference
71 loadIntentMappingServiceReference();
73 Vpns vpns = new VpnsBuilder().build();
74 MplsLabels labels = new MplsLabelsBuilder().build();
76 // Initialize MD-SAL data store for vpn-intents and mpls-labels
77 initDatastore(LogicalDatastoreType.CONFIGURATION, VPN_IID, vpns);
78 initDatastore(LogicalDatastoreType.OPERATIONAL, LABELS_IID, labels);
82 public void close() throws Exception {
83 LOG.info("VpnintentProvider Closed");
86 private <T extends DataObject> void initDatastore(LogicalDatastoreType store, InstanceIdentifier<T> iid, T object) {
87 // Put data to MD-SAL data store
88 WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
89 transaction.put(store, iid, object);
91 // Perform the tx.submit asynchronously
92 Futures.addCallback(transaction.submit(), new FutureCallback<Void>() {
94 public void onSuccess(final Void result) {
95 LOG.info("initDatastore for VPN-Intents: transaction succeeded");
99 public void onFailure(final Throwable throwable) {
100 LOG.error("initDatastore for VPN-Intents: transaction failed");
103 LOG.info("initDatastore: data populated: {}, {}, {}", store, iid, object);
107 public Future<RpcResult<Void>> removeVpn(RemoveVpnInput input) {
108 InstanceIdentifier<VpnIntents> vpnIdentifier = InstanceIdentifier.builder(Vpns.class)
109 .child(VpnIntents.class, new VpnIntentsKey(input.getVpnName())).build();
110 MappingServiceManager msManager = new MappingServiceManager(intentMappingService);
111 MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
113 VpnIntents vpn = getVpn(input.getVpnName());
115 if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) {
116 for (Endpoint endpoint : vpn.getEndpoint()) {
117 // Release MPLS label
118 mplsManager.deleteLabel(endpoint);
120 // Remove all intents related to this endpoint
121 IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
122 intentManager.removeIntentsByEndpoint(endpoint.getSiteName());
124 // Remove info from Mapping Service
125 msManager.delete(endpoint.getSiteName());
129 mdsal.delete(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
130 LOG.info("Deleted VPN {}", input.getVpnName());
131 return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
135 public Future<RpcResult<Void>> addVpnEndpoint(AddVpnEndpointInput input) {
136 Endpoint currentEndpoint = new EndpointBuilder().setIpPrefix(input.getIpPrefix())
137 .setSiteName(input.getSiteName()).setSwitchPortId(input.getSwitchPortId())
138 .setKey(new EndpointKey(input.getSiteName())).build();
139 VpnIntents vpn = getVpn(input.getVpnName());
140 String failOverType = null;
141 if (vpn.isPathProtection() && vpn.getFailoverType()!= null) {
142 if (vpn.getFailoverType().equals(FailoverType.FastReroute)) {
143 failOverType = IntentServiceManager.FAST_REROUTE;
144 } else if(vpn.getFailoverType().equals(FailoverType.SlowReroute)) {
145 failOverType = IntentServiceManager.SLOW_REROUTE;
149 MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
151 // Get unique MPLS label
152 Long mplsLabel = mplsManager.getUniqueLabel(currentEndpoint);
154 // Add info into Mapping Service
155 MappingServiceManager msManager = new MappingServiceManager(intentMappingService);
156 msManager.add(currentEndpoint.getSiteName(), extractIP(currentEndpoint.getIpPrefix()),
157 currentEndpoint.getSwitchPortId(), mplsLabel, null);
159 if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) {
160 IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
162 for (Endpoint member : vpn.getEndpoint()) {
163 // Create mesh of Intents
164 intentManager.addIntent(member.getSiteName(), currentEndpoint.getSiteName(),
165 IntentServiceManager.ACTION_ALLOW, failOverType);
166 intentManager.addIntent(currentEndpoint.getSiteName(), member.getSiteName(),
167 IntentServiceManager.ACTION_ALLOW, failOverType);
170 // Associate endpoint with VPN
171 addEndpointToVpn(vpn, currentEndpoint);
173 return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
179 * @return String representation of IP prefix
181 private String extractIP(IpPrefix ipPrefix) {
183 if (ipPrefix.getIpv4Prefix() != null) {
184 ip = ipPrefix.getIpv4Prefix().getValue();
185 } else if (ipPrefix.getIpv6Prefix() != null) {
186 ip = ipPrefix.getIpv6Prefix().getValue();
194 * @return VPN instance
196 private VpnIntents getVpn(String vpnName) {
197 InstanceIdentifier<VpnIntents> identifier = InstanceIdentifier.builder(Vpns.class)
198 .child(VpnIntents.class, new VpnIntentsKey(vpnName)).build();
200 VpnIntents vpnIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, identifier);
201 Preconditions.checkNotNull(vpnIntents);
206 public Future<RpcResult<Void>> removeVpnEndpoint(RemoveVpnEndpointInput input) {
207 Endpoint endpoint = getEndpoint(input.getVpnName(), input.getSiteName());
209 // Release MPLS label
210 MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
211 mplsManager.deleteLabel(endpoint);
213 // Remove all intents related to this endpoint
214 IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
215 intentManager.removeIntentsByEndpoint(input.getSiteName());
217 // Remove endpoint from VPN
218 removeEndpointFromVpn(input.getVpnName(), input.getSiteName());
220 return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
225 * Site name of the VPN member
226 * @return VPN member (Endpoint)
228 private Endpoint getEndpoint(String vpnName, String siteName) {
229 InstanceIdentifier<Endpoint> endpointID = InstanceIdentifier.builder(Vpns.class)
230 .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName))
233 return mdsal.read(LogicalDatastoreType.CONFIGURATION, endpointID);
242 private void removeEndpointFromVpn(String vpnName, String siteName) {
243 InstanceIdentifier<Endpoint> identifier = InstanceIdentifier.builder(Vpns.class)
244 .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName))
247 mdsal.delete(LogicalDatastoreType.CONFIGURATION, identifier);
248 LOG.info("Deleted VPN member : {} from VPN: {}", siteName, vpnName);
255 * VPN member (endpoint)
257 private void addEndpointToVpn(VpnIntents vpn, Endpoint vpnMember) {
258 InstanceIdentifier<Endpoint> identifier = InstanceIdentifier.builder(Vpns.class)
259 .child(VpnIntents.class, vpn.getKey())
260 .child(Endpoint.class, vpnMember.getKey()).build();
262 mdsal.put(LogicalDatastoreType.CONFIGURATION, identifier, vpnMember);
263 LOG.info("Added VPN member : {} to VPN: {}", vpnMember.getSiteName(), vpn.getVpnName());
267 * Load IntentMappingService reference
269 private void loadIntentMappingServiceReference() {
270 ServiceReference<?> serviceReference = getBundleCtx().getServiceReference(IntentMappingService.class);
271 intentMappingService = (IntentMappingService) getBundleCtx().getService(serviceReference);
274 private BundleContext getBundleCtx() {
275 return FrameworkUtil.getBundle(this.getClass()).getBundleContext();