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