2 * Copyright © 2017 Ericsson India Global Services Pvt Ltd. 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.netvirt.neutronvpn.evpn.manager;
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import com.google.common.util.concurrent.SettableFuture;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.function.Consumer;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
19 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
20 import org.opendaylight.netvirt.neutronvpn.NeutronvpnManager;
21 import org.opendaylight.netvirt.neutronvpn.NeutronvpnUtils;
22 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
23 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
24 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createevpn.input.Evpn;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getevpn.output.EvpnInstances;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getevpn.output.EvpnInstancesBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.common.RpcError;
43 import org.opendaylight.yangtools.yang.common.RpcResult;
44 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47 import org.slf4j.helpers.FormattingTuple;
48 import org.slf4j.helpers.MessageFormatter;
51 public class NeutronEvpnManager {
52 private static final Logger LOG = LoggerFactory.getLogger(NeutronEvpnManager.class);
53 private final DataBroker dataBroker;
54 private final NeutronvpnManager neutronvpnManager;
55 private final NeutronvpnUtils neutronvpnUtils;
57 public NeutronEvpnManager(DataBroker dataBroker, NeutronvpnManager neutronvpnManager,
58 NeutronvpnUtils neutronvpnUtils) {
59 this.dataBroker = dataBroker;
60 this.neutronvpnManager = neutronvpnManager;
61 this.neutronvpnUtils = neutronvpnUtils;
64 @SuppressWarnings("checkstyle:IllegalCatch")
65 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
66 CreateEVPNOutputBuilder opBuilder = new CreateEVPNOutputBuilder();
67 SettableFuture<RpcResult<CreateEVPNOutput>> result = SettableFuture.create();
68 List<RpcError> errorList = new ArrayList<>();
71 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
73 List<Evpn> vpns = input.getEvpn();
74 for (Evpn vpn : vpns) {
75 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
76 errorList.add(RpcResultBuilder.newWarning(RpcError.ErrorType.PROTOCOL, "invalid-input",
77 formatAndLog(LOG::warn, "Creation of EVPN failed for VPN {} due to absence of RD/iRT/eRT input",
78 vpn.getId().getValue())));
82 VpnInstance.Type vpnInstanceType = VpnInstance.Type.L2;
83 if (vpn.getRouteDistinguisher().size() > 1) {
84 errorList.add(RpcResultBuilder.newWarning(RpcError.ErrorType.PROTOCOL, "invalid-input",
85 formatAndLog(LOG::warn, "Creation of EVPN failed for VPN {} due to multiple RD input {}",
86 vpn.getId().getValue(), vpn.getRouteDistinguisher())));
90 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
91 errorList.add(RpcResultBuilder.newWarning(RpcError.ErrorType.PROTOCOL, "invalid-input",
92 formatAndLog(LOG::warn,
93 "Creation of EVPN failed for VPN {} as another VPN with the same RD {} is already "
95 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
100 neutronvpnManager.createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
101 vpn.getImportRT(), vpn.getExportRT(), null /*router-id*/, null /*network-id*/,
102 vpnInstanceType, 0 /*l2vni*/);
103 } catch (Exception ex) {
104 errorList.add(RpcResultBuilder.newError(RpcError.ErrorType.APPLICATION,
105 formatAndLog(LOG::error, "Creation of EVPN failed for VPN {}", vpn.getId().getValue(), ex),
110 if (failurecount != 0) {
111 result.set(RpcResultBuilder.<CreateEVPNOutput>failed().withRpcErrors(errorList).build());
113 List<String> errorResponseList = new ArrayList<>();
114 if (!errorList.isEmpty()) {
115 for (RpcError rpcError : errorList) {
116 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
117 + ", ErrorMessage: " + rpcError.getMessage());
120 errorResponseList.add("EVPN creation successful with no errors");
122 opBuilder.setResponse(errorResponseList);
123 result.set(RpcResultBuilder.success(opBuilder.build()).build());
128 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
129 GetEVPNOutputBuilder opBuilder = new GetEVPNOutputBuilder();
130 SettableFuture<RpcResult<GetEVPNOutput>> result = SettableFuture.create();
131 Uuid inputVpnId = input.getId();
132 List<VpnInstance> vpns = new ArrayList<>();
133 if (inputVpnId == null) {
134 vpns = VpnHelper.getAllVpnInstances(dataBroker);
135 if (!vpns.isEmpty()) {
136 for (VpnInstance vpn : vpns) {
137 if (vpn.getIpv4Family().getRouteDistinguisher() != null
138 && vpn.getType() == VpnInstance.Type.L2) {
144 result.set(RpcResultBuilder.success(opBuilder.build()).build());
148 String name = inputVpnId.getValue();
149 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, name);
150 if (vpnInstance != null && vpnInstance.getIpv4Family().getRouteDistinguisher() != null
151 && vpnInstance.getType() == VpnInstance.Type.L2) {
152 vpns.add(vpnInstance);
154 result.set(RpcResultBuilder.<GetEVPNOutput>failed().withWarning(RpcError.ErrorType.PROTOCOL,
156 formatAndLog(LOG::error, "GetEVPN failed because VPN {} is not present", name)).build());
159 List<EvpnInstances> evpnList = new ArrayList<>();
160 for (VpnInstance vpnInstance : vpns) {
161 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
162 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
163 .class, new VpnMapKey(vpnId)).build();
164 EvpnInstancesBuilder evpn = new EvpnInstancesBuilder();
165 List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
166 List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
167 List<String> ertList = new ArrayList<>();
168 List<String> irtList = new ArrayList<>();
169 for (VpnTarget vpnTarget : vpnTargetList) {
170 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
171 ertList.add(vpnTarget.getVrfRTValue());
173 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
174 irtList.add(vpnTarget.getVrfRTValue());
176 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
177 ertList.add(vpnTarget.getVrfRTValue());
178 irtList.add(vpnTarget.getVrfRTValue());
181 evpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
183 Optional<VpnMap> optionalVpnMap =
184 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
186 if (optionalVpnMap.isPresent()) {
187 VpnMap vpnMap = optionalVpnMap.get();
188 evpn.setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
190 } catch (ReadFailedException e) {
191 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
192 result.set(RpcResultBuilder.<GetEVPNOutput>failed().withError(RpcError.ErrorType.APPLICATION,
193 "Error reading the VPN map for " + vpnMapIdentifier, e).build());
196 evpnList.add(evpn.build());
199 opBuilder.setEvpnInstances(evpnList);
200 result.set(RpcResultBuilder.success(opBuilder.build()).build());
204 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
205 DeleteEVPNOutputBuilder opBuilder = new DeleteEVPNOutputBuilder();
206 SettableFuture<RpcResult<DeleteEVPNOutput>> result = SettableFuture.create();
207 List<RpcError> errorList = new ArrayList<>();
209 int failurecount = 0;
210 int warningcount = 0;
211 List<Uuid> vpns = input.getId();
212 for (Uuid vpn : vpns) {
215 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpn.getValue());
216 if (vpnInstance != null) {
217 neutronvpnManager.removeVpn(vpn);
219 errorList.add(RpcResultBuilder.newWarning(RpcError.ErrorType.PROTOCOL, "invalid-value",
220 formatAndLog(LOG::warn, "EVPN with vpnid: {} does not exist", vpn.getValue())));
224 if (failurecount != 0) {
225 result.set(RpcResultBuilder.<DeleteEVPNOutput>failed().withRpcErrors(errorList).build());
227 List<String> errorResponseList = new ArrayList<>();
228 if (!errorList.isEmpty()) {
229 for (RpcError rpcError : errorList) {
230 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
231 + ", ErrorMessage: " + rpcError.getMessage());
234 errorResponseList.add("Deletion of EVPN operation successful");
236 opBuilder.setResponse(errorResponseList);
237 result.set(RpcResultBuilder.success(opBuilder.build()).build());
242 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
243 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
246 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
247 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
250 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
251 String message = tuple.getMessage();
252 logger.accept(message);