2 * Copyright (c) 2016 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
9 package org.opendaylight.netvirt.elan.l2gw.listeners;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.HashSet;
15 import java.util.Objects;
17 import java.util.function.BiPredicate;
18 import java.util.function.Predicate;
19 import javax.annotation.PostConstruct;
20 import javax.annotation.PreDestroy;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.opendaylight.genius.datastoreutils.hwvtep.HwvtepAbstractDataTreeChangeListener;
25 import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
26 import org.opendaylight.genius.utils.hwvtep.HwvtepHACache;
27 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
28 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
29 import org.opendaylight.infrautils.utils.concurrent.Executors;
30 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
31 import org.opendaylight.mdsal.binding.api.DataBroker;
32 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
33 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
34 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
35 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
36 import org.opendaylight.netvirt.elan.l2gw.MdsalEvent;
37 import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
38 import org.opendaylight.netvirt.elan.l2gw.ha.listeners.HAOpClusteredListener;
39 import org.opendaylight.netvirt.elan.l2gw.recovery.impl.L2GatewayServiceRecoveryHandler;
40 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
41 import org.opendaylight.netvirt.elan.l2gw.utils.L2GatewayConnectionUtils;
42 import org.opendaylight.netvirt.elan.l2gw.utils.L2GatewayUtils;
43 import org.opendaylight.netvirt.elan.l2gw.utils.L2gwServiceProvider;
44 import org.opendaylight.netvirt.elan.l2gw.utils.StaleVlanBindingsCleaner;
45 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
46 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
47 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayCache;
48 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
49 import org.opendaylight.serviceutils.srm.RecoverableListener;
50 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIps;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
66 * Listener to handle physical switch updates.
69 public class HwvtepPhysicalSwitchListener
70 extends HwvtepAbstractDataTreeChangeListener<PhysicalSwitchAugmentation, HwvtepPhysicalSwitchListener>
71 implements ClusteredDataTreeChangeListener<PhysicalSwitchAugmentation>, RecoverableListener {
73 /** The Constant LOG. */
74 private static final Logger LOG = LoggerFactory.getLogger(HwvtepPhysicalSwitchListener.class);
76 private static final BiPredicate<L2GatewayDevice, InstanceIdentifier<Node>> DEVICE_NOT_CACHED_OR_PARENT_CONNECTED =
77 (l2GatewayDevice, globalIid) -> {
78 return l2GatewayDevice == null || l2GatewayDevice.getHwvtepNodeId() == null
79 || !Objects.equals(l2GatewayDevice.getHwvtepNodeId(),
80 globalIid.firstKeyOf(Node.class).getNodeId().getValue());
83 private static final Predicate<PhysicalSwitchAugmentation> TUNNEL_IP_AVAILABLE =
84 phySwitch -> !HwvtepHAUtil.isEmpty(phySwitch.nonnullTunnelIps().values());
86 private static final Predicate<PhysicalSwitchAugmentation> TUNNEL_IP_NOT_AVAILABLE = TUNNEL_IP_AVAILABLE.negate();
88 private static final BiPredicate<PhysicalSwitchAugmentation, L2GatewayDevice> TUNNEL_IP_CHANGED =
89 (phySwitchAfter, existingDevice) -> {
90 return TUNNEL_IP_AVAILABLE.test(phySwitchAfter)
92 existingDevice.getTunnelIp(), phySwitchAfter.nonnullTunnelIps().get(0).getTunnelIpsKey());
95 /** The data broker. */
96 private final DataBroker dataBroker;
97 private final ManagedNewTransactionRunner txRunner;
99 /** The itm rpc service. */
100 private final ItmRpcService itmRpcService;
102 private final ElanClusterUtils elanClusterUtils;
104 private final HwvtepHACache hwvtepHACache = HwvtepHACache.getInstance();
106 private final L2gwServiceProvider l2gwServiceProvider;
108 private final BiPredicate<L2GatewayDevice, InstanceIdentifier<Node>> childConnectedAfterParent =
109 (l2GwDevice, globalIid) -> {
110 return !hwvtepHACache.isHAParentNode(globalIid)
111 && l2GwDevice != null;
112 // FIXME: The following call to equals compares different types (String and InstanceIdentifier) and
113 // thus will always return false. I don't know what the intention is here so commented out for now.
114 //&& !Objects.equals(l2GwDevice.getHwvtepNodeId(), globalIid);
117 private final Predicate<L2GatewayDevice> alreadyHasL2Gwids =
119 return l2GwDevice != null && HwvtepHAUtil.isEmpty(l2GwDevice.getL2GatewayIds());
122 private final BiPredicate<L2GatewayDevice, InstanceIdentifier<Node>> parentConnectedAfterChild =
123 (l2GwDevice, globalIid) -> {
124 InstanceIdentifier<Node> existingIid = globalIid;
125 if (l2GwDevice != null && l2GwDevice.getHwvtepNodeId() != null) {
126 existingIid = HwvtepHAUtil.convertToInstanceIdentifier(l2GwDevice.getHwvtepNodeId());
128 return hwvtepHACache.isHAParentNode(globalIid)
129 && l2GwDevice != null
130 // FIXME: The following call to equals compares different types (String and InstanceIdentifier) and
131 // thus will always return false. I don't know what the intention is here so commented out for now.
132 //&& !Objects.equals(l2GwDevice.getHwvtepNodeId(), globalIid)
133 && Objects.equals(globalIid, hwvtepHACache.getParent(existingIid));
137 private final HAOpClusteredListener haOpClusteredListener;
139 private final L2GatewayCache l2GatewayCache;
141 private final StaleVlanBindingsCleaner staleVlanBindingsCleaner;
143 private final L2GwTransportZoneListener transportZoneListener;
146 * Instantiates a new hwvtep physical switch listener.
147 * @param l2GatewayServiceRecoveryHandler L2GatewayServiceRecoveryHandler
148 * @param serviceRecoveryRegistry ServiceRecoveryRegistry
149 * @param dataBroker DataBroker
150 * @param itmRpcService ItmRpcService
151 * @param elanClusterUtils ElanClusterUtils
152 * @param l2gwServiceProvider L2gwServiceProvider
153 * @param haListener HAOpClusteredListener
154 * @param l2GatewayCache L2GatewayCache
155 * @param staleVlanBindingsCleaner StaleVlanBindingsCleaner
158 public HwvtepPhysicalSwitchListener(final L2GatewayServiceRecoveryHandler l2GatewayServiceRecoveryHandler,
159 final ServiceRecoveryRegistry serviceRecoveryRegistry,
160 final DataBroker dataBroker, ItmRpcService itmRpcService,
161 ElanClusterUtils elanClusterUtils, L2gwServiceProvider l2gwServiceProvider,
162 HAOpClusteredListener haListener, L2GatewayCache l2GatewayCache,
163 StaleVlanBindingsCleaner staleVlanBindingsCleaner,
164 L2GwTransportZoneListener transportZoneListener) {
166 super(dataBroker, DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
167 InstanceIdentifier.create(NetworkTopology.class)
168 .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID)).child(Node.class)
169 .augmentation(PhysicalSwitchAugmentation.class)),
170 Executors.newListeningSingleThreadExecutor("HwvtepPhysicalSwitchListener", LOG));
172 this.dataBroker = dataBroker;
173 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
174 this.itmRpcService = itmRpcService;
175 this.elanClusterUtils = elanClusterUtils;
176 this.l2gwServiceProvider = l2gwServiceProvider;
177 this.staleVlanBindingsCleaner = staleVlanBindingsCleaner;
178 this.haOpClusteredListener = haListener;
179 this.l2GatewayCache = l2GatewayCache;
180 this.transportZoneListener = transportZoneListener;
181 serviceRecoveryRegistry.addRecoverableListener(l2GatewayServiceRecoveryHandler.buildServiceRegistryKey(),
188 ResourceBatchingManager.getInstance().registerDefaultBatchHandlers(this.dataBroker);
189 //RegisterListener is called from L2GatewayConnectionListener
190 //registerListener();
194 public void register() {
195 LOG.info("Registering HwvtepPhysicalSwitchListener in Overwritten Method");
200 public void registerListener() {
201 LOG.info("Registering HwvtepPhysicalSwitchListener");
205 public void deregisterListener() {
206 LOG.info("Deregistering HwvtepPhysicalSwitchListener");
212 public void close() {
214 Executors.shutdownAndAwaitTermination(getExecutorService());
218 protected void removed(InstanceIdentifier<PhysicalSwitchAugmentation> identifier,
219 PhysicalSwitchAugmentation phySwitchDeleted) {
220 NodeId nodeId = getNodeId(identifier);
221 String psName = phySwitchDeleted.getHwvtepNodeName().getValue();
222 LOG.info("Received physical switch {} removed event for node {}", psName, nodeId.getValue());
224 L2GatewayDevice l2GwDevice = l2GatewayCache.get(psName);
225 if (l2GwDevice != null) {
226 if (!L2GatewayConnectionUtils.isGatewayAssociatedToL2Device(l2GwDevice)) {
227 l2GatewayCache.remove(psName);
228 LOG.info("HwvtepPhysicalSwitchListener {} details removed from L2Gateway Cache", psName);
230 LOG.error("HwvtepPhysicalSwitchListener {} details are not removed from L2Gateway "
231 + " Cache as it has L2Gateway reference", psName);
234 l2GwDevice.setConnected(false);
235 //ElanL2GwCacheUtils.removeL2GatewayDeviceFromAllElanCache(psName);
237 LOG.error("HwvtepPhysicalSwitchListener Unable to find L2 Gateway details for {}", psName);
242 * Upon update checks if the tunnels Ip was null earlier and it got newly added.
243 * In that case simply call add.
244 * If not then check if Tunnel Ip has been updated from an old value to new value.
245 * If yes. delete old ITM tunnels of odl Tunnel Ipand add new ITM tunnels with new Tunnel
246 * IP then call added ().
248 * @param identifier iid
249 * @param phySwitchBefore ps Node before update
250 * @param phySwitchAfter ps Node after update
253 protected void updated(InstanceIdentifier<PhysicalSwitchAugmentation> identifier,
254 PhysicalSwitchAugmentation phySwitchBefore, PhysicalSwitchAugmentation phySwitchAfter) {
255 NodeId nodeId = getNodeId(identifier);
256 LOG.trace("Received PhysicalSwitch Update Event for node {}: PhysicalSwitch Before: {}, "
257 + "PhysicalSwitch After: {}", nodeId.getValue(), phySwitchBefore, phySwitchAfter);
258 String psName = getPsName(identifier);
259 if (psName == null) {
260 LOG.error("PhysicalSwitchListener Could not find the physical switch name for node {}", nodeId.getValue());
263 L2GatewayDevice existingDevice = l2GatewayCache.get(psName);
264 if (!Objects.equals(phySwitchAfter.getTunnelIps(), phySwitchBefore.getTunnelIps())) {
265 LOG.info("PhysicalSwitchListener Received physical switch update for {} before teps {} after teps {}",
266 nodeId.getValue(), phySwitchBefore.getTunnelIps(), phySwitchAfter.getTunnelIps());
268 InstanceIdentifier<Node> globalNodeIid = getManagedByNodeIid(identifier);
270 if (DEVICE_NOT_CACHED_OR_PARENT_CONNECTED.test(existingDevice, globalNodeIid)) {
271 if (TUNNEL_IP_AVAILABLE.test(phySwitchAfter)) {
272 added(identifier, phySwitchAfter);
275 if (!Objects.equals(phySwitchAfter.getTunnelIps(), phySwitchBefore.getTunnelIps())
276 && TUNNEL_IP_CHANGED.test(phySwitchAfter, existingDevice)) {
278 final String hwvtepId = existingDevice.getHwvtepNodeId();
279 elanClusterUtils.runOnlyInOwnerNode(existingDevice.getDeviceName(),
280 "handling Physical Switch add create itm tunnels ",
282 LOG.info("PhysicalSwitchListener Deleting itm tunnels for {}", existingDevice.getDeviceName());
283 L2GatewayUtils.deleteItmTunnels(itmRpcService, hwvtepId,
284 existingDevice.getDeviceName(), existingDevice.getTunnelIp());
285 Thread.sleep(10000L);//TODO remove these sleeps
286 LOG.info("Creating itm tunnels for device {}", existingDevice.getDeviceName());
287 ElanL2GatewayUtils.createItmTunnels(dataBroker, itmRpcService, hwvtepId, psName,
288 phySwitchAfter.getTunnelIps().get(0).getTunnelIpsKey());
289 return Collections.emptyList();
293 Thread.sleep(20000L);//TODO remove the sleep by using better itm api to detect finish of prev op
294 } catch (InterruptedException e) {
295 LOG.error("Interrupted ");
297 existingDevice.setTunnelIps(new HashSet<>());
298 added(identifier, phySwitchAfter);
304 protected void added(InstanceIdentifier<PhysicalSwitchAugmentation> identifier,
305 final PhysicalSwitchAugmentation phySwitchAdded) {
306 String globalNodeId = getManagedByNodeId(identifier);
307 final InstanceIdentifier<Node> globalNodeIid = getManagedByNodeIid(identifier);
308 NodeId nodeId = getNodeId(identifier);
309 if (TUNNEL_IP_NOT_AVAILABLE.test(phySwitchAdded)) {
310 LOG.error("PhysicalSwitchListener Could not find the /tunnel ips for node {}", nodeId.getValue());
313 final String psName = getPsName(identifier);
314 LOG.info("PhysicalSwitchListener Received physical switch added event received for node {} {}",
315 nodeId.getValue(), phySwitchAdded.getTunnelIps());
317 haOpClusteredListener.runAfterNodeIsConnected(globalNodeIid, (node) -> {
318 LOG.info("PhysicalSwitchListener Global oper node found for {}", nodeId.getValue());
319 if (!node.isPresent()) {
320 LOG.error("PhysicalSwitchListener Global node is absent {}", globalNodeId);
323 HAOpClusteredListener.addToCacheIfHAChildNode(globalNodeIid, node.get());
324 L2GatewayDevice l2GwDevice = l2GatewayCache.get(psName);
325 if (hwvtepHACache.isHAEnabledDevice(globalNodeIid)) {
326 InstanceIdentifier<Node> parent = hwvtepHACache.getParent(globalNodeIid);
327 if (l2GwDevice == null || !Objects.equals(parent.firstKeyOf(Node.class).getNodeId().getValue(),
328 l2GwDevice.getHwvtepNodeId())) {
329 Collection<TunnelIps> tunnelIps = phySwitchAdded.nonnullTunnelIps().values();
330 if (tunnelIps != null && !tunnelIps.isEmpty()) {
331 l2GatewayCache.updateL2GatewayCache(psName,
332 parent.firstKeyOf(Node.class).getNodeId().getValue(),
333 new ArrayList<>(phySwitchAdded.nonnullTunnelIps().values()));
335 return;//TODO provision l2gw
337 LOG.info("PhysicalSwitchListener Ha enabled device {} connected skip update cache", globalNodeIid);
341 LOG.info("PhysicalSwitchListener Updating cache for node {} existing {}",
342 globalNodeId, (l2GwDevice != null ? l2GwDevice.getDeviceName() : null));
343 if (childConnectedAfterParent.test(l2GwDevice, globalNodeIid)) {
344 LOG.info("PhysicalSwitchListener Device {} {} is already Connected by {}",
345 psName, globalNodeId, l2GwDevice.getHwvtepNodeId());
348 InstanceIdentifier<Node> existingIid = globalNodeIid;
349 if (l2GwDevice != null && l2GwDevice.getHwvtepNodeId() != null) {
350 existingIid = HwvtepHAUtil.convertToInstanceIdentifier(l2GwDevice.getHwvtepNodeId());
352 if (parentConnectedAfterChild.test(l2GwDevice, globalNodeIid)
353 && alreadyHasL2Gwids.test(l2GwDevice)) {
354 LOG.error("PhysicalSwitchListener Child node {} having l2gw configured became ha node "
355 + " removing the l2device {} from all elan cache and provision parent node {}",
356 existingIid, psName, globalNodeIid);
357 ElanL2GwCacheUtils.removeL2GatewayDeviceFromAllElanCache(l2GwDevice.getHwvtepNodeId());
360 Collection<TunnelIps> tunnelIps = phySwitchAdded.nonnullTunnelIps().values();
361 if (tunnelIps != null && !tunnelIps.isEmpty()) {
362 l2GatewayCache.updateL2GatewayCache(psName, globalNodeId,
363 new ArrayList<>(phySwitchAdded.nonnullTunnelIps().values()));
364 l2GwDevice = l2GatewayCache.get(psName);
365 handleAdd(l2GwDevice, identifier, phySwitchAdded);
367 /*elanClusterUtils.runOnlyInOwnerNode(psName + ":" + "tunnelIp",
368 "Update config tunnels IP ", () -> {
369 List<ListenableFuture<Void>> result = new ArrayList<>();
371 updateConfigTunnelIp(identifier, phySwitchAdded, result);
372 } catch (ReadFailedException e) {
373 LOG.error("PhysicalSwitchListener Failed to update tunnel ips {}", identifier);
388 private void handleAdd(L2GatewayDevice l2GwDevice,
389 InstanceIdentifier<PhysicalSwitchAugmentation> identifier,
390 PhysicalSwitchAugmentation phySwitchAdded) {
391 LOG.info("PhysicalSwitchListener Handle add of tunnel ips {} psNode {} device {}",
392 phySwitchAdded.getTunnelIps(), identifier.firstKeyOf(Node.class).getNodeId(), l2GwDevice);
393 final String psName = l2GwDevice.getDeviceName();
394 final String hwvtepNodeId = l2GwDevice.getHwvtepNodeId();
395 Set<IpAddress> tunnelIps = l2GwDevice.getTunnelIps();
396 if (tunnelIps != null) {
397 //TODO add logical switch and mcast put itm tep event and update mcast
398 hwvtepHACache.addDebugEvent(new MdsalEvent("ps add provision", l2GwDevice.getHwvtepNodeId()));
399 for (final IpAddress tunnelIpAddr : tunnelIps) {
400 if (L2GatewayConnectionUtils.isGatewayAssociatedToL2Device(l2GwDevice)) {
401 LOG.info("PhysicalSwitchListener L2Gateway {} associated for {} physical switch "
402 + " creating ITM tunnels for {}",
403 l2GwDevice.getL2GatewayIds(), psName, tunnelIpAddr);
404 l2gwServiceProvider.provisionItmAndL2gwConnection(l2GwDevice, psName, hwvtepNodeId, tunnelIpAddr);
406 LOG.info("l2gw.provision.skip hwvtepNodeId: {} psName : {}", hwvtepNodeId, psName);
409 InstanceIdentifier<Node> globalNodeIid = HwvtepSouthboundUtils.createInstanceIdentifier(
410 new NodeId(hwvtepNodeId));
411 HwvtepHACache.getInstance().setTepIpOfNode(globalNodeIid, tunnelIps.iterator().next());
412 elanClusterUtils.runOnlyInOwnerNode(psName, "Stale entry cleanup", () -> {
413 InstanceIdentifier<Node> psIid = HwvtepSouthboundUtils.createInstanceIdentifier(
414 HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepNodeId), psName));
415 staleVlanBindingsCleaner.scheduleStaleCleanup(psName, globalNodeIid, psIid);
416 transportZoneListener.createL2gwZeroDayConfig();
417 return Collections.emptyList();
428 * @return the node id
430 private static NodeId getNodeId(InstanceIdentifier<PhysicalSwitchAugmentation> identifier) {
431 return identifier.firstKeyOf(Node.class).getNodeId();
434 private static String getManagedByNodeId(InstanceIdentifier<PhysicalSwitchAugmentation> identifier) {
435 String psNodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
436 if (psNodeId.contains(HwvtepHAUtil.PHYSICALSWITCH)) {
437 return psNodeId.substring(0, psNodeId.indexOf(HwvtepHAUtil.PHYSICALSWITCH));
443 private static InstanceIdentifier<Node> getManagedByNodeIid(
444 InstanceIdentifier<PhysicalSwitchAugmentation> identifier) {
445 String psNodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
446 if (psNodeId.contains(HwvtepHAUtil.PHYSICALSWITCH)) {
447 psNodeId = psNodeId.substring(0, psNodeId.indexOf(HwvtepHAUtil.PHYSICALSWITCH));
448 return identifier.firstIdentifierOf(Topology.class).child(Node.class, new NodeKey(new NodeId(psNodeId)));
454 private static String getPsName(InstanceIdentifier<PhysicalSwitchAugmentation> identifier) {
455 String psNodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
456 if (psNodeId.contains(HwvtepHAUtil.PHYSICALSWITCH)) {
457 return psNodeId.substring(psNodeId.indexOf(HwvtepHAUtil.PHYSICALSWITCH) + HwvtepHAUtil.PHYSICALSWITCH
463 /*private void updateConfigTunnelIp(InstanceIdentifier<PhysicalSwitchAugmentation> identifier,
464 PhysicalSwitchAugmentation phySwitchAdded,
465 List<ListenableFuture<Void>> result)
466 throws ReadFailedException {
467 if (phySwitchAdded.getTunnelIps() != null) {
468 result.add(txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
469 Optional<PhysicalSwitchAugmentation> existingSwitch = tx.read(
470 LogicalDatastoreType.CONFIGURATION, identifier).checkedGet();
471 PhysicalSwitchAugmentationBuilder psBuilder = new PhysicalSwitchAugmentationBuilder();
472 if (existingSwitch.isPresent()) {
473 psBuilder = new PhysicalSwitchAugmentationBuilder(existingSwitch.get());
475 psBuilder.setTunnelIps(phySwitchAdded.getTunnelIps());
476 tx.put(LogicalDatastoreType.CONFIGURATION, identifier, psBuilder.build(), true);
477 LOG.trace("Updating config tunnel ips {}", identifier);