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 static org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils.requireNonNullElse;
12 import com.google.common.base.Optional;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.function.Consumer;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
22 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
23 import org.opendaylight.netvirt.neutronvpn.NeutronvpnManager;
24 import org.opendaylight.netvirt.neutronvpn.NeutronvpnUtils;
25 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createevpn.input.Evpn;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getevpn.output.EvpnInstances;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getevpn.output.EvpnInstancesBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.common.RpcError;
46 import org.opendaylight.yangtools.yang.common.RpcResult;
47 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50 import org.slf4j.helpers.FormattingTuple;
51 import org.slf4j.helpers.MessageFormatter;
54 public class NeutronEvpnManager {
55 private static final Logger LOG = LoggerFactory.getLogger(NeutronEvpnManager.class);
56 private final DataBroker dataBroker;
57 private final NeutronvpnManager neutronvpnManager;
58 private final NeutronvpnUtils neutronvpnUtils;
60 public NeutronEvpnManager(DataBroker dataBroker, NeutronvpnManager neutronvpnManager,
61 NeutronvpnUtils neutronvpnUtils) {
62 this.dataBroker = dataBroker;
63 this.neutronvpnManager = neutronvpnManager;
64 this.neutronvpnUtils = neutronvpnUtils;
67 @SuppressWarnings("checkstyle:IllegalCatch")
68 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
69 CreateEVPNOutputBuilder opBuilder = new CreateEVPNOutputBuilder();
70 SettableFuture<RpcResult<CreateEVPNOutput>> result = SettableFuture.create();
71 List<RpcError> errorList = new ArrayList<>();
73 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
75 for (Evpn vpn : requireNonNullElse(input.getEvpn(), Collections.<Evpn>emptyList())) {
76 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
77 errorList.add(RpcResultBuilder.newWarning(RpcError.ErrorType.PROTOCOL, "invalid-input",
78 formatAndLog(LOG::warn, "Creation of EVPN failed for VPN {} due to absence of RD/iRT/eRT input",
79 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())));
89 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
90 errorList.add(RpcResultBuilder.newWarning(RpcError.ErrorType.PROTOCOL, "invalid-input",
91 formatAndLog(LOG::warn,
92 "Creation of EVPN failed for VPN {} as another VPN with the same RD {} is already "
94 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
98 neutronvpnManager.createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
99 vpn.getImportRT(), vpn.getExportRT(), null /*router-id*/, null /*network-id*/,
100 vpnInstanceType, 0 /*l2vni*/);
101 } catch (Exception ex) {
102 errorList.add(RpcResultBuilder.newError(RpcError.ErrorType.APPLICATION,
103 formatAndLog(LOG::error, "Creation of EVPN failed for VPN {}", vpn.getId().getValue(), ex),
108 if (failurecount != 0) {
109 result.set(RpcResultBuilder.<CreateEVPNOutput>failed().withRpcErrors(errorList).build());
111 List<String> errorResponseList = new ArrayList<>();
112 if (!errorList.isEmpty()) {
113 for (RpcError rpcError : errorList) {
114 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
115 + ", ErrorMessage: " + rpcError.getMessage());
118 errorResponseList.add("EVPN creation successful with no errors");
120 opBuilder.setResponse(errorResponseList);
121 result.set(RpcResultBuilder.success(opBuilder.build()).build());
126 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
127 GetEVPNOutputBuilder opBuilder = new GetEVPNOutputBuilder();
128 SettableFuture<RpcResult<GetEVPNOutput>> result = SettableFuture.create();
129 Uuid inputVpnId = input.getId();
130 List<VpnInstance> vpns = new ArrayList<>();
131 if (inputVpnId == null) {
132 vpns = VpnHelper.getAllVpnInstances(dataBroker);
133 if (!vpns.isEmpty()) {
134 for (VpnInstance vpn : vpns) {
135 if (vpn.getIpv4Family().getRouteDistinguisher() != null
136 && vpn.getType() == VpnInstance.Type.L2) {
142 result.set(RpcResultBuilder.success(opBuilder.build()).build());
146 String name = inputVpnId.getValue();
147 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, name);
148 if (vpnInstance != null && vpnInstance.getIpv4Family().getRouteDistinguisher() != null
149 && vpnInstance.getType() == VpnInstance.Type.L2) {
150 vpns.add(vpnInstance);
152 result.set(RpcResultBuilder.<GetEVPNOutput>failed().withWarning(RpcError.ErrorType.PROTOCOL,
154 formatAndLog(LOG::error, "GetEVPN failed because VPN {} is not present", name)).build());
157 List<EvpnInstances> evpnList = new ArrayList<>();
158 for (VpnInstance vpnInstance : vpns) {
159 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
160 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
161 .class, new VpnMapKey(vpnId)).build();
162 EvpnInstancesBuilder evpn = new EvpnInstancesBuilder();
163 List<String> rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
164 List<String> ertList = new ArrayList<>();
165 List<String> irtList = new ArrayList<>();
166 for (VpnTarget vpnTarget : requireNonNullElse(vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget(),
167 Collections.<VpnTarget>emptyList())) {
168 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
169 ertList.add(vpnTarget.getVrfRTValue());
171 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
172 irtList.add(vpnTarget.getVrfRTValue());
174 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
175 ertList.add(vpnTarget.getVrfRTValue());
176 irtList.add(vpnTarget.getVrfRTValue());
179 evpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
181 Optional<VpnMap> optionalVpnMap =
182 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
184 if (optionalVpnMap.isPresent()) {
185 VpnMap vpnMap = optionalVpnMap.get();
186 evpn.setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
188 } catch (ReadFailedException e) {
189 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
190 result.set(RpcResultBuilder.<GetEVPNOutput>failed().withError(RpcError.ErrorType.APPLICATION,
191 "Error reading the VPN map for " + vpnMapIdentifier, e).build());
194 evpnList.add(evpn.build());
197 opBuilder.setEvpnInstances(evpnList);
198 result.set(RpcResultBuilder.success(opBuilder.build()).build());
202 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
203 List<RpcError> errorList = new ArrayList<>();
205 for (Uuid vpn : requireNonNullElse(input.getId(), Collections.<Uuid>emptyList())) {
206 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpn.getValue());
207 if (vpnInstance != null) {
208 neutronvpnManager.removeVpn(vpn);
210 errorList.add(RpcResultBuilder.newWarning(RpcError.ErrorType.PROTOCOL, "invalid-value",
211 formatAndLog(LOG::warn, "EVPN with vpnid: {} does not exist", vpn.getValue())));
214 List<String> errorResponseList = new ArrayList<>();
215 if (!errorList.isEmpty()) {
216 for (RpcError rpcError : errorList) {
217 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
218 + ", ErrorMessage: " + rpcError.getMessage());
221 errorResponseList.add("Deletion of EVPN operation successful");
223 DeleteEVPNOutputBuilder opBuilder = new DeleteEVPNOutputBuilder();
224 opBuilder.setResponse(errorResponseList);
225 SettableFuture<RpcResult<DeleteEVPNOutput>> result = SettableFuture.create();
226 result.set(RpcResultBuilder.success(opBuilder.build()).build());
230 private String formatAndLog(Consumer<String> logger, String template, Object arg) {
231 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
234 private String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
235 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
238 private String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
239 String message = tuple.getMessage();
240 logger.accept(message);