apply checkstyle check during build for neutron-ovsdb
[groupbasedpolicy.git] / neutron-ovsdb / src / main / java / org / opendaylight / groupbasedpolicy / neutron / ovsdb / OvsdbNodeListener.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.groupbasedpolicy.neutron.ovsdb;
9
10 import com.google.common.base.Function;
11 import com.google.common.base.Strings;
12 import com.google.common.collect.ImmutableList;
13 import com.google.common.collect.Lists;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.MoreExecutors;
17
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Objects;
23 import java.util.Set;
24
25 import javax.annotation.Nonnull;
26
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
29 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
30 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper;
33 import org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.NeutronOvsdbIidFactory;
34 import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
35 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.ovsdb.params.rev160812.IntegrationBridgeSetting;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeSystem;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow13;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsKey;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
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.NodeBuilder;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
63 import org.opendaylight.yangtools.yang.binding.DataObject;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67
68 public class OvsdbNodeListener extends DataTreeChangeHandler<Node> {
69
70     static final String BRIDGE_SEPARATOR = "/bridge/";
71     static final String NEUTRON_PROVIDER_MAPPINGS_KEY = "provider_mappings";
72     private static final Logger LOG = LoggerFactory.getLogger(OvsdbNodeListener.class);
73     private static final String OF_SEPARATOR = ":";
74     private static final String OF_INVENTORY_PREFIX = "openflow";
75     private static IntegrationBridgeSetting intBrSettings;
76
77     private final Map<OvsdbBridgeRef, String> providerPortNameByBridgeRef = new HashMap<>();
78     private final Map<InstanceIdentifier<Node>, NeutronBridgeWithExtPort> bridgeByNodeIid = new HashMap<>();
79
80     public OvsdbNodeListener(DataBroker dataProvider, IntegrationBridgeSetting brSettings) {
81         super(dataProvider);
82         intBrSettings = brSettings;
83         this.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
84                 InstanceIdentifier.create(NetworkTopology.class)
85                     .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
86                     .child(Node.class)));
87     }
88
89     @Override
90     protected void onWrite(DataObjectModification<Node> rootNode, InstanceIdentifier<Node> rootIdentifier) {
91         Node node = rootNode.getDataAfter();
92         OvsdbNodeAugmentation ovsdbNode = node.getAugmentation(OvsdbNodeAugmentation.class);
93         if (ovsdbNode != null) {
94             LOG.trace("OVSDB node created: {} \n {}", rootIdentifier, node);
95             DataObjectModification<OpenvswitchOtherConfigs>
96                 ovsOtherConfigModification = getProviderMappingsModification(rootNode);
97             boolean integrationBridgePresent = false;
98             if (isProviderPortNameChanged(ovsOtherConfigModification) && ovsdbNode.getManagedNodeEntry() != null) {
99                 String newProviderPortName = getProviderPortName(ovsOtherConfigModification.getDataAfter());
100                 LOG.debug("provider_mappings created {} on node {}", newProviderPortName, node.getNodeId().getValue());
101                 for (ManagedNodeEntry mngdNodeEntry : ovsdbNode.getManagedNodeEntry()) {
102                     OvsdbBridgeRef bridgeRef = mngdNodeEntry.getBridgeRef();
103                     providerPortNameByBridgeRef.put(bridgeRef, newProviderPortName);
104                     LOG.trace("Added Provider port name {} by OVSDB bridge ref {}", newProviderPortName,
105                             mngdNodeEntry.getBridgeRef());
106                     NodeKey managedNodeKey = bridgeRef.getValue().firstKeyOf(Node.class);
107                     if (intBrSettings != null && managedNodeKey.getNodeId().getValue()
108                         .equals(intBrSettings.getName())) {
109                         integrationBridgePresent = true;
110                     }
111                 }
112             }
113             if (intBrSettings != null && !integrationBridgePresent) {
114                 final Node bridge = createBridge(rootIdentifier,
115                         managerToControllerEntries(ovsdbNode.getManagerEntry()), intBrSettings.getName());
116                 InstanceIdentifier<Node> bridgeNodeIid = NeutronOvsdbIidFactory.nodeIid(
117                         rootIdentifier.firstKeyOf(Topology.class).getTopologyId(), bridge.getNodeId());
118                 WriteTransaction writeTx = dataProvider.newWriteOnlyTransaction();
119                 writeTx.merge(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid, bridge, true);
120                 Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
121
122                     @Override
123                     public void onSuccess(Void result) {
124                         LOG.info("Bridge {} written to datastore." + bridge.getNodeId().getValue());
125                     }
126
127                     @Override
128                     public void onFailure(Throwable throwable) {
129                         LOG.error("Failed to write bridge {}. Message: {}" + bridge.getNodeId().getValue(),
130                                 throwable.getMessage());
131                     }
132                 }, MoreExecutors.directExecutor());
133             }
134         }
135         OvsdbBridgeAugmentation ovsdbBridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
136         if (ovsdbBridge != null) {
137             LOG.trace("OVSDB bridge created: {} \n {}", rootIdentifier, node);
138             Set<DataObjectModification<OvsdbTerminationPointAugmentation>> ovsdbTpModifications =
139                     getOvsdbTpModifications(rootNode);
140             NodeId ofNodeId = buildOfNodeId(ovsdbBridge);
141             if (!ovsdbTpModifications.isEmpty() && ofNodeId != null) {
142                 NeutronBridgeWithExtPort bridge = getBridge(rootIdentifier);
143                 bridge.ofNodeId = ofNodeId;
144                 LOG.trace("OF node {} representing OVSDB bridge {}", ofNodeId.getValue(), node.getNodeId().getValue());
145             }
146             for (DataObjectModification<OvsdbTerminationPointAugmentation> ovsdbTpModification : ovsdbTpModifications) {
147                 OvsdbTerminationPointAugmentation newOvsdbTp = ovsdbTpModification.getDataAfter();
148                 if (ovsdbBridge.getBridgeName().getValue().equals(newOvsdbTp.getName())) {
149                     LOG.trace("Termination Point {} same as Bridge {}. Not processing", newOvsdbTp.getName(),
150                             ovsdbBridge.getBridgeName().getValue());
151                     continue;
152                 }
153                 String portName = newOvsdbTp.getName();
154                 Long ofport = newOvsdbTp.getOfport();
155                 if (isOfportOrNameChanged(ovsdbTpModification) && portName != null && ofport != null) {
156                     NeutronBridgeWithExtPort bridge = getBridge(rootIdentifier);
157                     bridge.ofportByName.put(ofport, portName);
158                     LOG.trace("OVSDB termination point with ofport {} and port-name {} created.", ofport, portName);
159                     // port name is same as provider port name so the termination point represents
160                     // external port
161                     if (portName.equals(providerPortNameByBridgeRef.get(new OvsdbBridgeRef(rootIdentifier)))) {
162                         NodeConnectorId ofNcId = buildOfNodeConnectorId(newOvsdbTp, ofNodeId);
163                         bridge.externalIfaces.add(ofNcId);
164                         InventoryHelper.addOfOverlayExternalPort(bridge.ofNodeId, ofNcId, dataProvider);
165                         LOG.debug("Added of-overlay external-interface {} to node {}", ofNcId.getValue(),
166                                 bridge.ofNodeId);
167                         traceBridge(rootIdentifier);
168                     }
169                 }
170             }
171         }
172     }
173
174     @Override
175     protected void onDelete(DataObjectModification<Node> rootNode, InstanceIdentifier<Node> rootIdentifier) {
176         LOG.trace("Not implemented - OVSDB element deleted: {} \n {}", rootIdentifier, rootNode.getDataBefore());
177     }
178
179     @Override
180     protected void onSubtreeModified(DataObjectModification<Node> rootNode, InstanceIdentifier<Node> rootIdentifier) {
181         Node node = rootNode.getDataAfter();
182         OvsdbBridgeAugmentation ovsdbBridge = node.getAugmentation(OvsdbBridgeAugmentation.class);
183         if (ovsdbBridge != null) {
184             LOG.trace("OVSDB bridge updated: {} \n before {} \n after {}", rootIdentifier, rootNode.getDataBefore(),
185                     rootNode.getDataAfter());
186             Set<DataObjectModification<OvsdbTerminationPointAugmentation>> ovsdbTpModifications =
187                     getOvsdbTpModifications(rootNode);
188             NodeId ofNodeId = buildOfNodeId(ovsdbBridge);
189             if (!ovsdbTpModifications.isEmpty() && ofNodeId != null) {
190                 NeutronBridgeWithExtPort bridge = getBridge(rootIdentifier);
191                 if (bridge.ofNodeId != null && !bridge.ofNodeId.equals(ofNodeId)) {
192                     LOG.debug("OVSDB bridge {} has changed datapath-id. \n  Old: {} \n  New: {}",
193                             node.getNodeId().getValue(), bridge.ofNodeId.getValue(), ofNodeId.getValue());
194                     bridge.ofNodeId = ofNodeId;
195                 }
196             }
197             for (DataObjectModification<OvsdbTerminationPointAugmentation> ovsdbTpModification : ovsdbTpModifications) {
198                 OvsdbTerminationPointAugmentation newOvsdbTp = ovsdbTpModification.getDataAfter();
199
200                 if (newOvsdbTp == null) {
201                     LOG.trace("Termination Point is null. Not processing");
202                     continue;
203                 }
204
205                 if (ovsdbBridge.getBridgeName().getValue().equals(newOvsdbTp.getName())) {
206                     LOG.trace("Termination Point {} same as Bridge {}. Not processing", newOvsdbTp.getName(),
207                             ovsdbBridge.getBridgeName().getValue());
208                     continue;
209                 }
210                 String portName = newOvsdbTp.getName();
211                 Long ofport = newOvsdbTp.getOfport();
212                 if (isOfportOrNameChanged(ovsdbTpModification) && portName != null && ofport != null) {
213                     NeutronBridgeWithExtPort bridge = getBridge(rootIdentifier);
214                     bridge.ofportByName.put(ofport, portName);
215                     LOG.trace("OVSDB termination point with ofport {} and port-name {} created.", ofport, portName);
216                     // port name is same as provider port name so the termination point represents
217                     // external port
218                     if (portName.equals(providerPortNameByBridgeRef.get(new OvsdbBridgeRef(rootIdentifier)))) {
219                         NodeConnectorId ofNcId = buildOfNodeConnectorId(newOvsdbTp, ofNodeId);
220                         bridge.externalIfaces.add(ofNcId);
221                         InventoryHelper.addOfOverlayExternalPort(bridge.ofNodeId, ofNcId, dataProvider);
222                         LOG.debug("Added of-overlay external-interface {} to node {}", ofNcId.getValue(),
223                                 bridge.ofNodeId);
224                         traceBridge(rootIdentifier);
225                     }
226                 }
227             }
228         }
229     }
230
231     private NeutronBridgeWithExtPort getBridge(InstanceIdentifier<Node> nodeIid) {
232         NeutronBridgeWithExtPort bridge = bridgeByNodeIid.get(nodeIid);
233         if (bridge == null) {
234             bridge = new NeutronBridgeWithExtPort();
235             bridgeByNodeIid.put(nodeIid, bridge);
236         }
237         return bridge;
238     }
239
240     @SuppressWarnings("unchecked")
241     private static Set<DataObjectModification<OvsdbTerminationPointAugmentation>> getOvsdbTpModifications(
242             DataObjectModification<Node> rootNode) {
243         Set<DataObjectModification<OvsdbTerminationPointAugmentation>> modifications = new HashSet<>();
244         for (DataObjectModification<? extends DataObject> modifiedChild : rootNode.getModifiedChildren()) {
245             if (TerminationPoint.class.isAssignableFrom(modifiedChild.getDataType())) {
246                 DataObjectModification<OvsdbTerminationPointAugmentation> modifiedAugmentation =
247                         ((DataObjectModification<TerminationPoint>) modifiedChild)
248                             .getModifiedAugmentation(OvsdbTerminationPointAugmentation.class);
249                 if (modifiedAugmentation != null) {
250                     modifications.add(modifiedAugmentation);
251                 }
252             }
253         }
254         return modifications;
255     }
256
257     private static boolean isOfportOrNameChanged(
258             DataObjectModification<OvsdbTerminationPointAugmentation> ovsdbTpModification) {
259         if (ovsdbTpModification == null) {
260             return false;
261         }
262         OvsdbTerminationPointAugmentation oldTp = ovsdbTpModification.getDataBefore();
263         OvsdbTerminationPointAugmentation newTp = ovsdbTpModification.getDataAfter();
264         if (oldTp != null && newTp != null) {
265             if (oldTp.getOfport() != null && newTp.getOfport() != null && !Objects.equals(oldTp.getOfport(),
266                 newTp.getOfport())) {
267                 return true;
268             }
269             if (!(Strings.nullToEmpty(oldTp.getName())).equals(Strings.nullToEmpty(newTp.getName()))) {
270                 return true;
271             }
272         }
273         if (isOfportOrNameNotNull(oldTp)) {
274             return true;
275         }
276         if (isOfportOrNameNotNull(newTp)) {
277             return true;
278         }
279         return false;
280     }
281
282     private static boolean isOfportOrNameNotNull(OvsdbTerminationPointAugmentation tp) {
283         if (tp != null) {
284             if (tp.getOfport() != null) {
285                 return true;
286             }
287             if (tp.getName() != null) {
288                 return true;
289             }
290         }
291         return false;
292     }
293
294     private static DataObjectModification<OpenvswitchOtherConfigs> getProviderMappingsModification(
295             DataObjectModification<Node> rootNode) {
296         DataObjectModification<OvsdbNodeAugmentation> modifiedOvsdbNode =
297                 rootNode.getModifiedAugmentation(OvsdbNodeAugmentation.class);
298         if (modifiedOvsdbNode == null) {
299             return null;
300         }
301         return modifiedOvsdbNode.getModifiedChildListItem(OpenvswitchOtherConfigs.class,
302                 new OpenvswitchOtherConfigsKey(NEUTRON_PROVIDER_MAPPINGS_KEY));
303     }
304
305     private static boolean isProviderPortNameChanged(DataObjectModification<OpenvswitchOtherConfigs> ovsConfig) {
306         if (ovsConfig == null) {
307             return false;
308         }
309         OpenvswitchOtherConfigs oldConfig = ovsConfig.getDataBefore();
310         OpenvswitchOtherConfigs newConfig = ovsConfig.getDataAfter();
311         if (oldConfig != null && newConfig != null) {
312             if (!(Strings.nullToEmpty(oldConfig.getOtherConfigValue())
313                 .equals(Strings.nullToEmpty(newConfig.getOtherConfigValue())))) {
314                 return true;
315             }
316         } else if (oldConfig != null && !Strings.isNullOrEmpty(oldConfig.getOtherConfigValue())) {
317             return true;
318         } else if (newConfig != null && !Strings.isNullOrEmpty(newConfig.getOtherConfigValue())) {
319             return true;
320         }
321         return false;
322     }
323
324     private static @Nonnull String getProviderPortName(OpenvswitchOtherConfigs config) {
325         if (NEUTRON_PROVIDER_MAPPINGS_KEY.equals(config.getOtherConfigKey()) && config.getOtherConfigValue() != null) {
326             String otherConfig = config.getOtherConfigValue();
327             String[] elements = otherConfig.split(":");
328             if (elements.length == 2) {
329                 return elements[1];
330             }
331         }
332         return "";
333     }
334
335     /**
336      * Extracts IP address from URI.
337      *
338      * @param uri in format protocol:ip:port
339      * @return IPv4 or IPv6 address as {@link String}.
340      */
341     private static @Nonnull String getIpAddrFromUri(Uri uri) {
342         String otherConfig = uri.getValue();
343         String[] elements = otherConfig.split(":");
344         // IPv6 expression also contains colons
345         if (elements.length < 3) {
346             return "";
347         }
348         StringBuilder sb = new StringBuilder();
349         // first (protocol) and last (port) elements are filtered
350         for (int i = 1; i < elements.length - 1; i++) {
351             sb.append(elements[i]);
352         }
353         return sb.toString();
354     }
355
356     private List<ControllerEntry> managerToControllerEntries(List<ManagerEntry> managerEntries) {
357         return Lists.transform(managerEntries, new Function<ManagerEntry, ControllerEntry>() {
358
359             @Override
360             public ControllerEntry apply(ManagerEntry managerEntry) {
361                 String ipAddr = getIpAddrFromUri(managerEntry.getTarget());
362                 Uri uri = new Uri(intBrSettings.getOpenflowProtocol() + OF_SEPARATOR + ipAddr + OF_SEPARATOR
363                         + intBrSettings.getOpenflowPort());
364                 return new ControllerEntryBuilder().setTarget(new Uri(uri)).build();
365             }
366         });
367     }
368
369     private Node createBridge(InstanceIdentifier<Node> managedByIid, List<ControllerEntry> controllerEntries,
370             String bridgeName) {
371         OvsdbBridgeAugmentation br = new OvsdbBridgeAugmentationBuilder()
372             .setBridgeName(new OvsdbBridgeName(bridgeName))
373             .setManagedBy(new OvsdbNodeRef(managedByIid))
374             .setControllerEntry(controllerEntries)
375             .setDatapathType(DatapathTypeSystem.class)
376             .setProtocolEntry(
377                     ImmutableList.of(new ProtocolEntryBuilder().setProtocol(
378                             OvsdbBridgeProtocolOpenflow13.class).build()))
379             .build();
380         NodeKey managerNodeKey = managedByIid.firstKeyOf(Node.class);
381         return new NodeBuilder().setNodeId(
382                 new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId(
383                         managerNodeKey.getNodeId().getValue() + BRIDGE_SEPARATOR + bridgeName))
384             .addAugmentation(OvsdbBridgeAugmentation.class, br)
385             .build();
386     }
387
388     private static NodeId buildOfNodeId(OvsdbBridgeAugmentation ovsdbBridge) {
389         if (ovsdbBridge.getDatapathId() == null) {
390             return null;
391         }
392         Long macLong = InventoryHelper.getLongFromDpid(ovsdbBridge.getDatapathId().getValue());
393         return new NodeId(OF_INVENTORY_PREFIX + OF_SEPARATOR + String.valueOf(macLong));
394     }
395
396     private static NodeConnectorId buildOfNodeConnectorId(OvsdbTerminationPointAugmentation terminationPoint,
397             NodeId nodeId) {
398         if (terminationPoint.getOfport() == null) {
399             return null;
400         }
401         return new NodeConnectorId(nodeId.getValue() + OF_SEPARATOR + String.valueOf(terminationPoint.getOfport()));
402     }
403
404     private void traceBridge(InstanceIdentifier<Node> identifier) {
405         if (LOG.isTraceEnabled()) {
406             NeutronBridgeWithExtPort bridge = bridgeByNodeIid.get(identifier);
407             if (bridge == null) {
408                 LOG.trace("Bridge does not exist: {}", identifier);
409                 return;
410             }
411             String providerPortName = providerPortNameByBridgeRef.get(new OvsdbBridgeRef(identifier));
412             LOG.trace("State of bridge:\n  ID: {} \n  providerPortName: {} \n  {}", identifier, providerPortName,
413                     bridge);
414         }
415     }
416
417     private class NeutronBridgeWithExtPort {
418
419         NodeId ofNodeId;
420         Set<NodeConnectorId> externalIfaces = new HashSet<>();
421         Map<Long, String> ofportByName = new HashMap<>();
422
423         @Override
424         public String toString() {
425             return "NeutronBridgeWithExtPort:\n  ofNodeId=" + ofNodeId + "\n  externalIfaces=" + externalIfaces
426                     + ",\n  ofportByName=" + ofportByName;
427         }
428     }
429
430 }