2 * Copyright (c) 2016 Cisco Systems, Inc. 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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.iface;
11 import javax.annotation.Nonnull;
12 import javax.annotation.Nullable;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.ExecutorService;
15 import com.google.common.base.Optional;
16 import com.google.common.base.Preconditions;
17 import com.google.common.base.Strings;
18 import com.google.common.eventbus.Subscribe;
19 import com.google.common.util.concurrent.AsyncFunction;
20 import com.google.common.util.concurrent.CheckedFuture;
21 import com.google.common.util.concurrent.Futures;
22 import com.google.common.util.concurrent.ListenableFuture;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand;
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.TapPortCommand;
30 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand;
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand.VhostUserCommandBuilder;
32 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.NodeOperEvent;
33 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent;
34 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations;
35 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
36 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint.InterfaceTypeChoice;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.LoopbackCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.TapCase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUserRole;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2Builder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.Interconnection;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.BridgeBased;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.BridgeBasedBuilder;
54 import org.opendaylight.yangtools.yang.binding.DataObject;
55 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
59 public class InterfaceManager implements AutoCloseable {
61 private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class);
62 private final MountedDataBrokerProvider mountDataProvider;
63 private final VppEndpointLocationProvider vppEndpointLocationProvider;
64 private final ExecutorService netconfWorker;
66 public InterfaceManager(@Nonnull MountedDataBrokerProvider mountDataProvider, @Nonnull DataBroker dataProvider,
67 @Nonnull ExecutorService netconfWorker) {
68 this.mountDataProvider = Preconditions.checkNotNull(mountDataProvider);
69 this.netconfWorker = Preconditions.checkNotNull(netconfWorker);
70 this.vppEndpointLocationProvider = new VppEndpointLocationProvider(dataProvider);
74 @SuppressWarnings("OptionalGetWithoutIsPresent")
75 public synchronized void vppEndpointChanged(VppEndpointConfEvent event) {
77 switch (event.getDtoModificationType()) {
79 vppEndpointCreated(event.getAfter().get()).get();
83 vppEndpointUpdated(event.getBefore().get(), event.getAfter().get()).get();
86 vppEndpointDeleted(event.getBefore().get()).get();
89 } catch (InterruptedException | ExecutionException e) {
90 LOG.error("Failed to update Vpp Endpoint. {}", event, e);
94 private ListenableFuture<Void> vppEndpointCreated(VppEndpoint vppEndpoint) {
95 InterfaceTypeChoice interfaceTypeChoice = vppEndpoint.getInterfaceTypeChoice();
96 LOG.trace("Creating VPP endpoint {}, type of {}", vppEndpoint, interfaceTypeChoice);
97 Optional<ConfigCommand> potentialIfaceCommand = Optional.absent();
98 if (interfaceTypeChoice instanceof VhostUserCase) {
99 potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT);
100 } else if (interfaceTypeChoice instanceof TapCase) {
101 potentialIfaceCommand = createTapInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT);
102 } else if (interfaceTypeChoice instanceof LoopbackCase){
103 potentialIfaceCommand = createLoopbackWithoutBdCommand(vppEndpoint, Operations.PUT);
106 if (!potentialIfaceCommand.isPresent()) {
107 LOG.debug("Interface/PUT command was not created for VppEndpoint point {}", vppEndpoint);
108 return Futures.immediateFuture(null);
110 ConfigCommand ifaceWithoutBdCommand = potentialIfaceCommand.get();
111 InstanceIdentifier<?> vppNodeIid = vppEndpoint.getVppNodePath();
112 Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
113 if (!potentialVppDataProvider.isPresent()) {
114 LOG.debug("Cannot get data broker for mount point {}", vppNodeIid);
115 return Futures.immediateFuture(null);
117 DataBroker vppDataBroker = potentialVppDataProvider.get();
118 return createInterfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid);
121 private ListenableFuture<Void> createInterfaceOnVpp(ConfigCommand createIfaceWithoutBdCommand, DataBroker vppDataBroker,
122 VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
123 final ReadWriteTransaction rwTx = vppDataBroker.newReadWriteTransaction();
124 createIfaceWithoutBdCommand.execute(rwTx);
125 LOG.trace("Creating Interface on VPP: {}", createIfaceWithoutBdCommand);
126 return Futures.transform(rwTx.submit(), new AsyncFunction<Void, Void>() {
129 public ListenableFuture<Void> apply(@Nonnull Void input) {
130 LOG.debug("Create interface on VPP command was successful. VPP: {} Command: {}", vppNodeIid,
131 createIfaceWithoutBdCommand);
132 return vppEndpointLocationProvider.createLocationForVppEndpoint(vppEndpoint);
137 private ListenableFuture<Void> vppEndpointUpdated(@Nonnull final VppEndpoint oldVppEndpoint,
138 @Nonnull final VppEndpoint newVppEndpoint)
139 throws ExecutionException, InterruptedException {
140 if(!oldVppEndpoint.equals(newVppEndpoint)) {
141 LOG.debug("Updating vpp endpoint, old EP: {} new EP: {}", oldVppEndpoint, newVppEndpoint);
142 return Futures.transform(vppEndpointDeleted(oldVppEndpoint), new AsyncFunction<Void, Void>() {
144 public ListenableFuture<Void> apply(@Nonnull Void input) throws Exception {
145 return vppEndpointCreated(newVppEndpoint);
149 LOG.debug("Update skipped, provided before/after vpp endpoints are equal");
150 return Futures.immediateFuture(null);
153 private ListenableFuture<Void> vppEndpointDeleted(@Nonnull VppEndpoint vppEndpoint) {
154 InterfaceTypeChoice interfaceTypeChoice = vppEndpoint.getInterfaceTypeChoice();
155 LOG.trace("Deleting VPP endpoint {}, type of {}", vppEndpoint, interfaceTypeChoice.toString());
156 Optional<ConfigCommand> potentialIfaceCommand = Optional.absent();
157 if (interfaceTypeChoice instanceof VhostUserCase) {
158 potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE);
159 } else if (interfaceTypeChoice instanceof TapCase) {
160 potentialIfaceCommand = createTapInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE);
161 } else if (interfaceTypeChoice instanceof LoopbackCase){
162 potentialIfaceCommand = createLoopbackWithoutBdCommand(vppEndpoint, Operations.DELETE);
165 if (!potentialIfaceCommand.isPresent()) {
166 LOG.debug("Interface/DELETE command was not created for VppEndpoint point {}", vppEndpoint);
167 return Futures.immediateFuture(null);
169 ConfigCommand ifaceWithoutBdCommand = potentialIfaceCommand.get();
170 InstanceIdentifier<?> vppNodeIid = vppEndpoint.getVppNodePath();
171 Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
172 if (!potentialVppDataProvider.isPresent()) {
173 LOG.debug("Cannot get data broker for mount point {}", vppNodeIid);
174 return Futures.immediateFuture(null);
176 DataBroker vppDataBroker = potentialVppDataProvider.get();
177 return deleteIfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid);
180 private ListenableFuture<Void> deleteIfaceOnVpp(ConfigCommand deleteIfaceWithoutBdCommand,
181 DataBroker vppDataBroker, VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
182 ReadWriteTransaction rwTx = vppDataBroker.newReadWriteTransaction();
183 deleteIfaceWithoutBdCommand.execute(rwTx);
184 LOG.trace("Deleting Interface on VPP: {}", deleteIfaceWithoutBdCommand);
186 return Futures.transform(rwTx.submit(), new AsyncFunction<Void, Void>() {
189 public ListenableFuture<Void> apply(Void input) {
190 LOG.debug("Delete interface on VPP command was successful: VPP: {} Command: {}", vppNodeIid,
191 deleteIfaceWithoutBdCommand);
192 return vppEndpointLocationProvider.deleteLocationForVppEndpoint(vppEndpoint);
198 public synchronized void vppNodeChanged(NodeOperEvent event) {
199 switch (event.getDtoModificationType()) {
201 if (event.isAfterConnected()) {
202 // TODO read VppEndpoints or cache them during vppEndpointChanged()
206 if (!event.isBeforeConnected() && event.isAfterConnected()) {
207 // TODO reconciliation - diff between disconnected snapshot and current snapshot
211 if (event.isBeforeConnected()) {
212 // TODO we could do snapshot of VppEndpoints
213 // which can be used for reconciliation
219 private static Optional<ConfigCommand> createInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp,
220 @Nonnull Operations operations) {
221 if (!hasNodeAndInterface(vppEp)) {
222 LOG.debug("Interface command is not created for {}", vppEp);
223 return Optional.absent();
225 VhostUserCommandBuilder builder = VhostUserCommand.builder();
226 builder.setName(vppEp.getVppInterfaceName());
227 InterfaceTypeChoice interfaceTypeChoice = vppEp.getInterfaceTypeChoice();
228 if (interfaceTypeChoice instanceof VhostUserCase) {
229 VhostUserCase vhostUserIface = (VhostUserCase) interfaceTypeChoice;
230 String socket = vhostUserIface.getSocket();
231 if (Strings.isNullOrEmpty(socket)) {
232 LOG.debug("Vhost user interface command is not created because socket is missing. {}", vppEp);
233 return Optional.absent();
235 builder.setSocket(socket);
236 builder.setRole(VhostUserRole.Client);
238 VhostUserCommand vhostUserCommand =
239 builder.setOperation(operations).setDescription(vppEp.getDescription()).build();
240 return Optional.of(vhostUserCommand);
243 private static Optional<ConfigCommand> createTapInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp,
244 @Nonnull Operations operation) {
245 if (!hasNodeAndInterface(vppEp)) {
246 LOG.debug("Interface command is not created for {}", vppEp);
247 return Optional.absent();
249 TapPortCommand.TapPortCommandBuilder builder = TapPortCommand.builder();
250 InterfaceTypeChoice interfaceTypeChoice = vppEp.getInterfaceTypeChoice();
251 if (interfaceTypeChoice instanceof TapCase) {
252 TapCase tapIface = (TapCase) interfaceTypeChoice;
253 String name = tapIface.getName();
254 if (Strings.isNullOrEmpty(name)) {
255 LOG.debug("Tap interface command is not created because name is missing. {}", vppEp);
256 return Optional.absent();
258 builder.setTapName(name);
259 builder.setPhysAddress(tapIface.getPhysicalAddress());
261 TapPortCommand tapPortCommand = builder
262 .setOperation(operation)
263 .setDescription(vppEp.getDescription())
264 .setInterfaceName(vppEp.getVppInterfaceName())
266 return Optional.of(tapPortCommand);
269 private static Optional<ConfigCommand> createLoopbackWithoutBdCommand(@Nonnull VppEndpoint vppEp,
270 @Nonnull Operations operation) {
271 if (!hasNodeAndInterface(vppEp)) {
272 LOG.debug("Interface command is not created for {}", vppEp);
273 return Optional.absent();
275 LoopbackCommand.LoopbackCommandBuilder builder = LoopbackCommand.builder();
276 LoopbackCase loopIface = (LoopbackCase) vppEp.getInterfaceTypeChoice();
278 builder.setPhysAddress(loopIface.getPhysAddress());
279 builder.setBvi(loopIface.isBvi());
280 builder.setIpAddress(loopIface.getIpAddress());
281 builder.setIpPrefix(loopIface.getIpPrefix());
283 LoopbackCommand loopbackCommand = builder
284 .setOperation(operation)
285 .setDescription(vppEp.getDescription())
286 .setInterfaceName(vppEp.getVppInterfaceName())
289 return Optional.of(loopbackCommand);
293 * Adds bridge domain to an interface if the interface exist.<br>
294 * It rewrites bridge domain in case it already exist.<br>
295 * {@link VppEndpointLocationProvider#VPP_ENDPOINT_LOCATION_PROVIDER} will update location
296 * when the interface is created successfully.<br>
297 * If the interface does not exist or other problems occur {@link ListenableFuture} will fail
298 * as {@link Futures#immediateFailedFuture(Throwable)} with {@link Exception}
299 * containing message in {@link Exception#getMessage()}
301 * @param bridgeDomainName bridge domain
302 * @param addrEpWithLoc {@link AddressEndpointWithLocation} containing
303 * {@link ExternalLocationCase} where
304 * {@link ExternalLocationCase#getExternalNodeMountPoint()} MUST NOT be {@code null}
305 * and {@link ExternalLocationCase#getExternalNodeConnector()} MUST NOT be {@code null}
306 * @return {@link ListenableFuture}
308 public synchronized @Nonnull ListenableFuture<Void> addBridgeDomainToInterface(@Nonnull String bridgeDomainName,
309 @Nonnull AddressEndpointWithLocation addrEpWithLoc, boolean enableBvi) {
310 ExternalLocationCase epLoc = resolveAndValidateLocation(addrEpWithLoc);
311 InstanceIdentifier<?> vppNodeIid = epLoc.getExternalNodeMountPoint();
312 String interfacePath = epLoc.getExternalNodeConnector();
314 Optional<InstanceIdentifier<Interface>> optInterfaceIid =
315 VppPathMapper.interfaceToInstanceIdentifier(interfacePath);
316 if (!optInterfaceIid.isPresent()) {
317 return Futures.immediateFailedFuture(
318 new Exception("Cannot resolve interface instance-identifier for interface path" + interfacePath));
320 InstanceIdentifier<Interface> interfaceIid = optInterfaceIid.get();
322 Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
323 if (!potentialVppDataProvider.isPresent()) {
324 return Futures.immediateFailedFuture(new Exception("Cannot get data broker for mount point " + vppNodeIid));
326 final DataBroker mountpoint = potentialVppDataProvider.get();
327 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
328 CheckedFuture<Optional<Interface>, ReadFailedException> futureIface =
329 rwTx.read(LogicalDatastoreType.CONFIGURATION, interfaceIid);
330 return Futures.transform(futureIface, new AsyncFunction<Optional<Interface>, Void>() {
333 public ListenableFuture<Void> apply(Optional<Interface> optIface) throws Exception {
334 if (!optIface.isPresent()) {
335 return Futures.immediateFailedFuture(new Exception("Interface "
336 + interfaceIid.firstKeyOf(Interface.class) + " does not exist on node " + vppNodeIid));
339 String existingBridgeDomain = resolveBridgeDomain(optIface.get());
340 if (bridgeDomainName.equals(existingBridgeDomain)) {
341 LOG.debug("Bridge domain {} already exists on interface {}", bridgeDomainName, interfacePath);
342 String bridgeDomainPath = VppPathMapper.bridgeDomainToRestPath(bridgeDomainName);
343 if (!bridgeDomainPath.equals(epLoc.getExternalNode())) {
344 return vppEndpointLocationProvider.replaceLocationForEndpoint(new ExternalLocationCaseBuilder()
345 .setExternalNode(bridgeDomainPath)
346 .setExternalNodeMountPoint(vppNodeIid)
347 .setExternalNodeConnector(interfacePath)
348 .build(), addrEpWithLoc.getKey());
350 return Futures.immediateFuture(null);
352 InstanceIdentifier<L2> l2Iid =
353 interfaceIid.builder().augmentation(VppInterfaceAugmentation.class).child(L2.class).build();
354 final ReadWriteTransaction rwTxRead = mountpoint.newReadWriteTransaction();
355 Optional<L2> optL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l2Iid, rwTxRead);
356 L2Builder l2Builder = (optL2.isPresent()) ? new L2Builder(optL2.get()) : new L2Builder();
357 L2 l2 = l2Builder.setInterconnection(new BridgeBasedBuilder()
358 .setBridgeDomain(bridgeDomainName)
359 .setBridgedVirtualInterface(enableBvi)
361 final ReadWriteTransaction rwTxPut = prepareTransactionAndPutData(mountpoint, l2, l2Iid);
362 LOG.debug("Adding bridge domain {} to interface {}", bridgeDomainName, interfacePath);
363 return Futures.transform(rwTxPut.submit(), new AsyncFunction<Void, Void>() {
366 public ListenableFuture<Void> apply(@Nonnull Void input) {
367 String bridgeDomainPath = VppPathMapper.bridgeDomainToRestPath(bridgeDomainName);
368 return vppEndpointLocationProvider.replaceLocationForEndpoint(new ExternalLocationCaseBuilder()
369 .setExternalNode(bridgeDomainPath)
370 .setExternalNodeMountPoint(vppNodeIid)
371 .setExternalNodeConnector(interfacePath)
372 .build(), addrEpWithLoc.getKey());
380 * Removes bridge domain (if exist) from an interface (if exist).<br>
381 * {@link VppEndpointLocationProvider#VPP_ENDPOINT_LOCATION_PROVIDER} will update endpoint
384 * If the interface does not exist or other problems occur {@link ListenableFuture} will fail
385 * as {@link Futures#immediateFailedFuture(Throwable)} with {@link Exception}
386 * containing message in {@link Exception#getMessage()}
388 * @param addrEpWithLoc {@link AddressEndpointWithLocation} containing
389 * {@link ExternalLocationCase} where
390 * {@link ExternalLocationCase#getExternalNodeMountPoint()} MUST NOT be {@code null}
391 * and {@link ExternalLocationCase#getExternalNodeConnector()} MUST NOT be {@code null}
392 * @return {@link ListenableFuture}
394 public synchronized @Nonnull ListenableFuture<Void> deleteBridgeDomainFromInterface(
395 @Nonnull AddressEndpointWithLocation addrEpWithLoc) {
396 ExternalLocationCase epLoc = resolveAndValidateLocation(addrEpWithLoc);
397 InstanceIdentifier<?> vppNodeIid = epLoc.getExternalNodeMountPoint();
398 String interfacePath = epLoc.getExternalNodeConnector();
400 Optional<InstanceIdentifier<Interface>> optInterfaceIid =
401 VppPathMapper.interfaceToInstanceIdentifier(interfacePath);
402 if (!optInterfaceIid.isPresent()) {
403 return Futures.immediateFailedFuture(
404 new Exception("Cannot resolve interface instance-identifier for interface path" + interfacePath));
406 InstanceIdentifier<Interface> interfaceIid = optInterfaceIid.get();
408 Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
409 if (!potentialVppDataProvider.isPresent()) {
410 return Futures.immediateFailedFuture(new Exception("Cannot get data broker for mount point " + vppNodeIid));
413 ReadWriteTransaction rwTx = potentialVppDataProvider.get().newReadWriteTransaction();
414 CheckedFuture<Optional<Interface>, ReadFailedException> futureIface =
415 rwTx.read(LogicalDatastoreType.CONFIGURATION, interfaceIid);
416 return Futures.transform(futureIface, new AsyncFunction<Optional<Interface>, Void>() {
419 public ListenableFuture<Void> apply(Optional<Interface> optIface) throws Exception {
420 if (!optIface.isPresent()) {
421 // interface does not exist so we consider job done
422 return Futures.immediateFuture(null);
424 String existingBridgeDomain = resolveBridgeDomain(optIface.get());
425 if (Strings.isNullOrEmpty(existingBridgeDomain)) {
426 LOG.debug("Bridge domain does not exist therefore it is considered as deleted for interface {}",
428 // bridge domain does not exist on interface so we consider job done
429 return vppEndpointLocationProvider.replaceLocationForEndpoint(new ExternalLocationCaseBuilder()
430 .setExternalNode(null)
431 .setExternalNodeMountPoint(vppNodeIid)
432 .setExternalNodeConnector(interfacePath)
433 .build(), addrEpWithLoc.getKey());
435 InstanceIdentifier<L2> l2Iid =
436 interfaceIid.builder().augmentation(VppInterfaceAugmentation.class).child(L2.class).build();
437 rwTx.delete(LogicalDatastoreType.CONFIGURATION, l2Iid);
438 LOG.debug("Deleting bridge domain from interface {}", interfacePath);
439 return Futures.transform(rwTx.submit(), new AsyncFunction<Void, Void>() {
442 public ListenableFuture<Void> apply(@Nonnull Void input) {
443 return vppEndpointLocationProvider.replaceLocationForEndpoint(new ExternalLocationCaseBuilder()
444 .setExternalNode(null)
445 .setExternalNodeMountPoint(vppNodeIid)
446 .setExternalNodeConnector(interfacePath)
447 .build(), addrEpWithLoc.getKey());
454 private static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
455 LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
456 if (!(locationType instanceof ExternalLocationCase)) {
457 throw new IllegalArgumentException("Endpoint does not have external location " + addrEpWithLoc);
459 ExternalLocationCase result = (ExternalLocationCase) locationType;
460 if (result.getExternalNodeMountPoint() == null || result.getExternalNodeConnector() == null) {
461 throw new IllegalArgumentException(
462 "Endpoint does not have external-node-mount-point or external-node-connector " + addrEpWithLoc);
467 private static @Nullable String resolveBridgeDomain(@Nonnull Interface iface) {
468 VppInterfaceAugmentation vppInterfaceAugmentation = iface.getAugmentation(VppInterfaceAugmentation.class);
469 L2 existingL2 = vppInterfaceAugmentation.getL2();
470 if (existingL2 != null) {
471 Interconnection interconnection = existingL2.getInterconnection();
472 if (interconnection instanceof BridgeBased) {
473 return ((BridgeBased) interconnection).getBridgeDomain();
479 private static boolean hasNodeAndInterface(VppEndpoint vppEp) {
480 if (vppEp.getVppNodePath() == null) {
481 LOG.debug("vpp-node is missing. {}", vppEp);
484 if (Strings.isNullOrEmpty(vppEp.getVppInterfaceName())) {
485 LOG.debug("vpp-interface-name is missing. {}", vppEp);
492 public void close() throws Exception {
493 vppEndpointLocationProvider.close();
496 // TODO workaround for netconf, remove when fixed
497 private synchronized <T extends DataObject> ReadWriteTransaction prepareTransactionAndPutData(final DataBroker mountpoint,
499 InstanceIdentifier<T> iid) {
500 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
502 rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, data);
504 catch (IllegalStateException e) {
505 LOG.error("Assuming netconf transaction failed, restarting ...", e.getMessage());
506 return prepareTransactionAndPutData(mountpoint, data, iid);