Use Topology Node in place of Inventory Node
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / impl / BridgeConfigurationManagerImpl.java
1 /*
2  * Copyright (C) 2013 Red Hat, Inc.
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  * Authors : Madhu Venugopal, Brent Salisbury, Sam Hague
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt.impl;
11
12 import org.opendaylight.neutron.spi.NeutronNetwork;
13 import org.opendaylight.ovsdb.lib.error.SchemaVersionMismatchException;
14 import org.opendaylight.ovsdb.lib.notation.Row;
15 import org.opendaylight.ovsdb.lib.notation.UUID;
16 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
20 import org.opendaylight.ovsdb.openstack.netvirt.api.MdsalConsumer;
21 import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager;
22 import org.opendaylight.ovsdb.openstack.netvirt.api.OvsdbConfigurationService;
23 import org.opendaylight.ovsdb.openstack.netvirt.api.Status;
24 import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode;
25 import org.opendaylight.ovsdb.openstack.netvirt.api.StatusWithUuid;
26 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
27 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
28 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
29 import org.opendaylight.ovsdb.schema.openvswitch.Port;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
31
32 import com.google.common.base.Preconditions;
33 import com.google.common.collect.Lists;
34 import com.google.common.collect.Maps;
35 import org.apache.commons.lang3.tuple.ImmutablePair;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Set;
43
44 public class BridgeConfigurationManagerImpl implements BridgeConfigurationManager {
45     static final Logger LOGGER = LoggerFactory.getLogger(BridgeConfigurationManagerImpl.class);
46
47     // The implementation for each of these services is resolved by the OSGi Service Manager
48     private volatile ConfigurationService configurationService;
49     private volatile NetworkingProviderManager networkingProviderManager;
50     private volatile OvsdbConfigurationService ovsdbConfigurationService;
51     //private volatile MdsalConsumer mdsalConsumer;
52
53     public BridgeConfigurationManagerImpl() {
54     }
55
56     @Override
57     public String getBridgeUuid(Node node, String bridgeName) {
58         //Preconditions.checkNotNull(mdsalConsumer);
59         /* TODO SB_MIGRATION */
60         try {
61              Map<String, Row> bridgeTable =
62                      ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
63             if (bridgeTable == null) {
64                 return null;
65             }
66             for (String key : bridgeTable.keySet()) {
67                 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeTable.get(key));
68                 if (bridge.getName().equals(bridgeName)) {
69                     return key;
70                 }
71             }
72         } catch (Exception e) {
73             LOGGER.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
74         }
75         return null;
76     }
77
78     @Override
79     public boolean isNodeNeutronReady(Node node) {
80         Preconditions.checkNotNull(configurationService);
81         return this.getBridgeUuid(node, configurationService.getIntegrationBridgeName()) != null;
82     }
83
84     @Override
85     public boolean isNodeOverlayReady(Node node) {
86         /* TODO SB_MIGRATION */
87         Preconditions.checkNotNull(ovsdbConfigurationService);
88         return this.isNodeNeutronReady(node)
89                && this.getBridgeUuid(node, configurationService.getNetworkBridgeName()) != null;
90     }
91
92     @Override
93     public boolean isPortOnBridge (Node node, Bridge bridge, String portName) {
94         /* TODO SB_MIGRATION */
95         Preconditions.checkNotNull(ovsdbConfigurationService);
96         for (UUID portsUUID : bridge.getPortsColumn().getData()) {
97             try {
98                 Row portRow = ovsdbConfigurationService.getRow(node,
99                                                         ovsdbConfigurationService.getTableName(node, Port.class),
100                                                         portsUUID.toString());
101
102                 Port port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
103                 if ((port != null) && port.getName().equalsIgnoreCase(portName)) {
104                     return true;
105                 }
106             } catch (Exception e) {
107                 LOGGER.error("Error getting port {} for bridge domain {}/{}", portsUUID, node, bridge.getName(), e);
108             }
109         }
110         return false;
111     }
112
113     @Override
114     public boolean isNodeTunnelReady(Node node) {
115         Preconditions.checkNotNull(configurationService);
116         Preconditions.checkNotNull(networkingProviderManager);
117
118         /* Is br-int created? */
119         Bridge intBridge = this.getBridge(node, configurationService.getIntegrationBridgeName());
120         if (intBridge == null) {
121             return false;
122         }
123
124         if (networkingProviderManager.getProvider(node).hasPerTenantTunneling()) {
125             /* Is br-net created? */
126             Bridge netBridge = this.getBridge(node, configurationService.getNetworkBridgeName());
127             if (netBridge == null) {
128                 return false;
129             }
130
131             if (!isNetworkPatchCreated(node, intBridge, netBridge)) {
132                 return false;
133             }
134         }
135         return true;
136     }
137
138     @Override
139     public boolean isNodeVlanReady(Node node, NeutronNetwork network) {
140         /* TODO SB_MIGRATION */
141         Preconditions.checkNotNull(ovsdbConfigurationService);
142         Preconditions.checkNotNull(networkingProviderManager);
143
144         /* is br-int created */
145         Bridge intBridge = this.getBridge(node, configurationService.getIntegrationBridgeName());
146         if (intBridge == null) {
147             LOGGER.trace("isNodeVlanReady: node: {}, br-int missing", node);
148             return false;
149         }
150
151         if (networkingProviderManager.getProvider(node).hasPerTenantTunneling()) {
152             /* is br-net created? */
153             Bridge netBridge = this.getBridge(node, configurationService.getNetworkBridgeName());
154
155             if (netBridge == null) {
156                 LOGGER.trace("isNodeVlanReady: node: {}, br-net missing", node);
157                 return false;
158             }
159
160             if (!isNetworkPatchCreated(node, intBridge, netBridge)) {
161                 LOGGER.trace("isNodeVlanReady: node: {}, patch missing", node);
162                 return false;
163             }
164
165             /* Check if physical device is added to br-net. */
166             String phyNetName = this.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
167             if (isPortOnBridge(node, netBridge, phyNetName)) {
168                 return true;
169             }
170         } else {
171             /* Check if physical device is added to br-int. */
172             String phyNetName = this.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
173             if (isPortOnBridge(node, intBridge, phyNetName)) {
174                 return true;
175             }
176         }
177
178         LOGGER.trace("isNodeVlanReady: node: {}, eth missing", node);
179         return false;
180     }
181
182     @Override
183     public void prepareNode(Node node) {
184         Preconditions.checkNotNull(networkingProviderManager);
185
186         try {
187             this.createIntegrationBridge(node);
188         } catch (Exception e) {
189             LOGGER.error("Error creating Integration Bridge on " + node.toString(), e);
190             return;
191         }
192         if (networkingProviderManager == null) {
193             LOGGER.error("Error creating internal network. Provider Network Manager unavailable");
194             return;
195         }
196         networkingProviderManager.getProvider(node).initializeFlowRules(node);
197     }
198
199     /*
200      * Check if the full network setup is available. If not, create it.
201      */
202     @Override
203     public boolean createLocalNetwork (Node node, NeutronNetwork network) {
204         boolean isCreated = false;
205         if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
206             if (!this.isNodeVlanReady(node, network)) {
207                 try {
208                     isCreated = this.createBridges(node, network);
209                 } catch (Exception e) {
210                     LOGGER.error("Error creating internal net network " + node, e);
211                 }
212             } else {
213                 isCreated = true;
214             }
215         } else if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN) ||
216                    network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE)) {
217             if (!this.isNodeTunnelReady(node)) {
218                 try {
219                     isCreated = this.createBridges(node, network);
220                 } catch (Exception e) {
221                     LOGGER.error("Error creating internal net network " + node, e);
222                 }
223             } else {
224                 isCreated = true;
225             }
226         }
227         return isCreated;
228     }
229
230     @Override
231     public String getPhysicalInterfaceName (Node node, String physicalNetwork) {
232         String phyIf = null;
233         /* TODO SB_MIGRATION */
234         try {
235             Map<String, Row> ovsTable =
236                     ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, OpenVSwitch.class));
237
238             if (ovsTable == null) {
239                 LOGGER.error("OpenVSwitch table is null for Node {} ", node);
240                 return null;
241             }
242
243             // Loop through all the Open_vSwitch rows looking for the first occurrence of other_config.
244             // The specification does not restrict the number of rows so we choose the first we find.
245             for (Row row : ovsTable.values()) {
246                 String providerMaps;
247                 OpenVSwitch ovsRow = ovsdbConfigurationService.getTypedRow(node, OpenVSwitch.class, row);
248                 Map<String, String> configs = ovsRow.getOtherConfigColumn().getData();
249
250                 if (configs == null) {
251                     LOGGER.debug("OpenVSwitch table is null for Node {} ", node);
252                     continue;
253                 }
254
255                 providerMaps = configs.get(configurationService.getProviderMappingsKey());
256                 if (providerMaps == null) {
257                     providerMaps = configurationService.getDefaultProviderMapping();
258                 }
259
260                 if (providerMaps != null) {
261                     for (String map : providerMaps.split(",")) {
262                         String[] pair = map.split(":");
263                         if (pair[0].equals(physicalNetwork)) {
264                             phyIf = pair[1];
265                             break;
266                         }
267                     }
268                 }
269
270                 if (phyIf != null) {
271                     break;
272                 }
273             }
274         } catch (Exception e) {
275             LOGGER.error("Unable to find physical interface for Node: {}, Network {}",
276                          node, physicalNetwork, e);
277         }
278
279         if (phyIf == null) {
280             LOGGER.error("Physical interface not found for Node: {}, Network {}",
281                          node, physicalNetwork);
282         }
283
284         return phyIf;
285     }
286
287     @Override
288     public List<String> getAllPhysicalInterfaceNames(Node node) {
289         List<String> phyIfName = Lists.newArrayList();
290         /* TODO SB_MIGRATION */
291         try {
292             Map<String, Row> ovsTable =
293                     ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, OpenVSwitch.class));
294
295             if (ovsTable == null) {
296                 LOGGER.error("OpenVSwitch table is null for Node {} ", node);
297                 return null;
298             }
299
300             // While there is only one entry in the HashMap, we can't access it by index...
301             for (Row row : ovsTable.values()) {
302                 String bridgeMaps;
303                 OpenVSwitch ovsRow = ovsdbConfigurationService.getTypedRow(node, OpenVSwitch.class, row);
304                 Map<String, String> configs = ovsRow.getOtherConfigColumn().getData();
305
306                 if (configs == null) {
307                     LOGGER.debug("OpenVSwitch table is null for Node {} ", node);
308                     continue;
309                 }
310
311                 bridgeMaps = configs.get(configurationService.getProviderMappingsKey());
312                 if (bridgeMaps == null) {
313                     bridgeMaps = configurationService.getDefaultProviderMapping();
314                 }
315
316                 if (bridgeMaps != null) {
317                     for (String map : bridgeMaps.split(",")) {
318                         String[] pair = map.split(":");
319                         phyIfName.add(pair[1]);
320                     }
321                 }
322             }
323         } catch (Exception e) {
324             LOGGER.error("Unable to find physical interface for Node: " + node, e);
325         }
326
327         LOGGER.debug("Physical interface for Node: {}, If: {}",
328                      node, phyIfName);
329
330         return phyIfName;
331     }
332
333     /**
334      * Returns the Bridge for a given node and bridgeName
335      */
336     public Bridge getBridge (Node node, String bridgeName) {
337         /* TODO SB_MIGRATION */
338         Preconditions.checkNotNull(ovsdbConfigurationService);
339         try {
340             Map<String, Row> bridgeTable =
341                     ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
342             if (bridgeTable != null) {
343                 for (String key : bridgeTable.keySet()) {
344                     Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeTable.get(key));
345                     if (bridge.getName().equals(bridgeName)) {
346                         return bridge;
347                     }
348                 }
349             }
350         } catch (Exception e) {
351             LOGGER.error("Error getting Bridge Identifier for {} / {}", node, bridgeName, e);
352         }
353
354         return null;
355     }
356
357     /**
358      * Returns true if a patch port exists between the Integration Bridge and Network Bridge
359      */
360     private boolean isNetworkPatchCreated (Node node, Bridge intBridge, Bridge netBridge) {
361         Preconditions.checkNotNull(configurationService);
362
363         boolean isPatchCreated = false;
364
365         String portName = configurationService.getPatchPortName(new ImmutablePair<>(intBridge, netBridge));
366         if (isPortOnBridge(node, intBridge, portName)) {
367             portName = configurationService.getPatchPortName(new ImmutablePair<>(netBridge, intBridge));
368             if (isPortOnBridge(node, netBridge, portName)) {
369                 isPatchCreated = true;
370             }
371         }
372
373         return isPatchCreated;
374     }
375
376     /**
377      * Creates the Integration Bridge
378      */
379     private void createIntegrationBridge (Node node) throws Exception {
380         Preconditions.checkNotNull(configurationService);
381
382         String brInt = configurationService.getIntegrationBridgeName();
383
384         Status status = this.addBridge(node, brInt, null, null);
385         if (!status.isSuccess()) {
386             LOGGER.debug("Integration Bridge Creation Status: {}", status);
387         }
388     }
389
390     /**
391      * Create and configure bridges for all network types and OpenFlow versions.
392      *
393        OF 1.0 vlan:
394        Bridge br-int
395             Port patch-net
396                 Interface patch-net
397                     type: patch
398                     options: {peer=patch-int}
399             Port br-int
400                 Interface br-int
401                     type: internal
402        Bridge br-net
403             Port "eth1"
404                 Interface "eth1"
405             Port patch-int
406                 Interface patch-int
407                     type: patch
408                     options: {peer=patch-net}
409             Port br-net
410                 Interface br-net
411                     type: internal
412
413        OF 1.0 tunnel:
414        Bridge br-int
415             Port patch-net
416                 Interface patch-net
417                     type: patch
418                     options: {peer=patch-int}
419             Port br-int
420                 Interface br-int
421                     type: internal
422        Bridge "br-net"
423             Port patch-int
424                 Interface patch-int
425                     type: patch
426                     options: {peer=patch-net}
427             Port br-net
428                 Interface br-net
429                     type: internal
430
431        OF 1.3 vlan:
432        Bridge br-int
433             Port "eth1"
434                 Interface "eth1"
435             Port br-int
436                 Interface br-int
437                     type: internal
438
439        OF 1.3 tunnel:
440        Bridge br-int
441             Port br-int
442                 Interface br-int
443                     type: internal
444      */
445     private boolean createBridges(Node node, NeutronNetwork network) throws Exception {
446         Preconditions.checkNotNull(configurationService);
447         Preconditions.checkNotNull(networkingProviderManager);
448         Status status;
449
450         LOGGER.debug("createBridges: node: {}, network type: {}", node, network.getProviderNetworkType());
451
452         if (networkingProviderManager.getProvider(node).hasPerTenantTunneling()) { /* indicates OF 1.0 */
453             String brInt = configurationService.getIntegrationBridgeName();
454             String brNet = configurationService.getNetworkBridgeName();
455             String patchNet = configurationService.getPatchPortName(new ImmutablePair<>(brInt, brNet));
456             String patchInt = configurationService.getPatchPortName(new ImmutablePair<>(brNet, brInt));
457
458             status = this.addBridge(node, brInt, patchNet, patchInt);
459             if (!status.isSuccess()) {
460                 LOGGER.debug("{} Bridge Creation Status: {}", brInt, status);
461                 return false;
462             }
463             status = this.addBridge(node, brNet, patchInt, patchNet);
464             if (!status.isSuccess()) {
465                 LOGGER.debug("{} Bridge Creation Status: {}", brNet, status);
466                 return false;
467             }
468
469             /* For vlan network types add physical port to br-net. */
470             if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
471                 String phyNetName = this.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
472                 status = addPortToBridge(node, brNet, phyNetName);
473                 if (!status.isSuccess()) {
474                     LOGGER.debug("Add Port {} to Bridge {} Status: {}", phyNetName, brNet, status);
475                     return false;
476                 }
477             }
478         } else {
479             String brInt = configurationService.getIntegrationBridgeName();
480             status = this.addBridge(node, brInt, null, null);
481             if (!status.isSuccess()) {
482                 LOGGER.debug("{} Bridge Creation Status: {}", brInt, status);
483                 return false;
484             }
485
486             /* For vlan network types add physical port to br-int. */
487             if (network.getProviderNetworkType().equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) {
488                 String phyNetName = this.getPhysicalInterfaceName(node, network.getProviderPhysicalNetwork());
489                 status = addPortToBridge(node, brInt, phyNetName);
490                 if (!status.isSuccess()) {
491                     LOGGER.debug("Add Port {} to Bridge {} Status: {}", phyNetName, brInt, status);
492                     return false;
493                 }
494             }
495         }
496
497         LOGGER.debug("createNetNetwork: node: {}, status: success", node);
498         return true;
499     }
500
501     /**
502      * Add a Port to a Bridge
503      */
504     private Status addPortToBridge (Node node, String bridgeName, String portName) throws Exception {
505         /* TODO SB_MIGRATION */
506         Preconditions.checkNotNull(ovsdbConfigurationService);
507
508         LOGGER.debug("addPortToBridge: Adding port: {} to Bridge {}, Node {}", portName, bridgeName, node);
509
510         String bridgeUUID = this.getBridgeUuid(node, bridgeName);
511         if (bridgeUUID == null) {
512             LOGGER.error("addPortToBridge: Could not find Bridge {} in Node {}", bridgeName, node);
513             return new Status(StatusCode.NOTFOUND, "Could not find "+bridgeName+" in "+node);
514         }
515
516         /* Check if the port already exists. */
517         Row row = ovsdbConfigurationService
518                 .getRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), bridgeUUID);
519         Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, row);
520         if (bridge != null) {
521             if (isPortOnBridge(node, bridge, portName)) {
522                 LOGGER.debug("addPortToBridge: Port {} already in Bridge {}, Node {}", portName, bridgeName, node);
523                 return new Status(StatusCode.SUCCESS);
524             }
525         } else {
526             LOGGER.error("addPortToBridge: Could not find Port {} in Bridge {}, Node {}", portName, bridgeName, node);
527             return new Status(StatusCode.NOTFOUND, "Could not find "+portName+" in "+bridgeName);
528         }
529
530         Port port = ovsdbConfigurationService.createTypedRow(node, Port.class);
531         port.setName(portName);
532         StatusWithUuid statusWithUuid =
533                 ovsdbConfigurationService.insertRow(node, port.getSchema().getName(), bridgeUUID, port.getRow());
534         if (!statusWithUuid.isSuccess()) {
535             LOGGER.error("addPortToBridge: Failed to add Port {} in Bridge {}, Node {}", portName, bridgeName, node);
536             return statusWithUuid;
537         }
538
539         String portUUID = statusWithUuid.getUuid().toString();
540         String interfaceUUID = null;
541         int timeout = 6;
542         while ((interfaceUUID == null) && (timeout > 0)) {
543             Row portRow = ovsdbConfigurationService.getRow(node, port.getSchema().getName(), portUUID);
544             port = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
545             Set<UUID> interfaces = port.getInterfacesColumn().getData();
546             if (interfaces == null || interfaces.size() == 0) {
547                 // Wait for the OVSDB update to sync up the Local cache.
548                 Thread.sleep(500);
549                 timeout--;
550                 continue;
551             }
552             interfaceUUID = interfaces.toArray()[0].toString();
553             Row intf = ovsdbConfigurationService.getRow(node,
554                                                 ovsdbConfigurationService.getTableName(node, Interface.class), interfaceUUID);
555             if (intf == null) {
556                 interfaceUUID = null;
557             }
558         }
559
560         if (interfaceUUID == null) {
561             LOGGER.error("addPortToBridge: Cannot identify Interface for port {}/{}", portName, portUUID);
562             return new Status(StatusCode.INTERNALERROR);
563         }
564
565         return new Status(StatusCode.SUCCESS);
566     }
567
568     /**
569      * Add a Patch Port to a Bridge
570      */
571     private Status addPatchPort (Node node, String bridgeUUID, String portName, String peerPortName) throws Exception {
572         /* TODO SB_MIGRATION */
573         Preconditions.checkNotNull(ovsdbConfigurationService);
574
575         LOGGER.debug("addPatchPort: node: {}, bridgeUUID: {}, port: {}, peer: {}",
576                      node, bridgeUUID, portName, peerPortName);
577
578         /* Check if the port already exists. */
579         Row bridgeRow = ovsdbConfigurationService.getRow(node,
580                                                   ovsdbConfigurationService.getTableName(node, Bridge.class), bridgeUUID);
581         Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
582         if (bridge != null) {
583             if (isPortOnBridge(node, bridge, portName)) {
584                 LOGGER.debug("addPatchPort: Port {} already in Bridge, Node {}", portName, node);
585                 return new Status(StatusCode.SUCCESS);
586             }
587         } else {
588             LOGGER.error("addPatchPort: Could not find Port {} in Bridge, Node {}", portName, node);
589             return new Status(StatusCode.NOTFOUND, "Could not find "+portName+" in Bridge");
590         }
591
592         Port patchPort = ovsdbConfigurationService.createTypedRow(node, Port.class);
593         patchPort.setName(portName);
594         // Create patch port and interface
595         StatusWithUuid statusWithUuid =
596                 ovsdbConfigurationService.insertRow(node, patchPort.getSchema().getName(), bridgeUUID, patchPort.getRow());
597         if (!statusWithUuid.isSuccess()) {
598             return statusWithUuid;
599         }
600
601         String patchPortUUID = statusWithUuid.getUuid().toString();
602
603         String interfaceUUID = null;
604         int timeout = 6;
605         while ((interfaceUUID == null) && (timeout > 0)) {
606             Row portRow = ovsdbConfigurationService.getRow(node, patchPort.getSchema().getName(), patchPortUUID);
607             patchPort = ovsdbConfigurationService.getTypedRow(node, Port.class, portRow);
608             Set<UUID> interfaces = patchPort.getInterfacesColumn().getData();
609             if (interfaces == null || interfaces.size() == 0) {
610                 // Wait for the OVSDB update to sync up the Local cache.
611                 Thread.sleep(500);
612                 timeout--;
613                 continue;
614             }
615             interfaceUUID = interfaces.toArray()[0].toString();
616         }
617
618         if (interfaceUUID == null) {
619             return new Status(StatusCode.INTERNALERROR);
620         }
621
622         Interface intf = ovsdbConfigurationService.createTypedRow(node, Interface.class);
623         intf.setType("patch");
624         Map<String, String> options = Maps.newHashMap();
625         options.put("peer", peerPortName);
626         intf.setOptions(options);
627         return ovsdbConfigurationService.updateRow(node,
628                                             intf.getSchema().getName(),
629                                             patchPortUUID,
630                                             interfaceUUID,
631                                             intf.getRow());
632
633     }
634
635     /**
636      * Add Bridge to a Node
637      */
638     private Status addBridge(Node node, String bridgeName,
639                              String localPatchName, String remotePatchName) throws Exception {
640         Preconditions.checkNotNull(networkingProviderManager);
641         /* TODO SB_MIGRATION */
642
643         String bridgeUUID = getBridgeUuid(node, bridgeName);
644         Bridge bridge = ovsdbConfigurationService.createTypedRow(node, Bridge.class);
645         Set<String> failMode = new HashSet<>();
646         failMode.add("secure");
647         bridge.setFailMode(failMode);
648
649         Set<String> protocols = new HashSet<>();
650
651         /* ToDo: Plugin should expose an easy way to get the OVS Version or Schema Version
652          * or, alternatively it should not attempt to add set unsupported fields
653          */
654
655         try {
656             protocols.add(Constants.OPENFLOW13);
657             bridge.setProtocols(protocols);
658         } catch (SchemaVersionMismatchException e) {
659             LOGGER.info("Failed to add protocol.", e);
660         }
661
662         if (bridgeUUID == null) {
663             bridge.setName(bridgeName);
664
665             StatusWithUuid statusWithUuid = ovsdbConfigurationService.insertRow(node,
666                                                                          bridge.getSchema().getName(),
667                                                                          null,
668                                                                          bridge.getRow());
669             if (!statusWithUuid.isSuccess()) {
670                 return statusWithUuid;
671             }
672             bridgeUUID = statusWithUuid.getUuid().toString();
673             Port port = ovsdbConfigurationService.createTypedRow(node, Port.class);
674             port.setName(bridgeName);
675             Status status = ovsdbConfigurationService.insertRow(node, port.getSchema().getName(), bridgeUUID, port.getRow());
676             LOGGER.debug("addBridge: Inserting Bridge {} {} with protocols {} and status {}",
677                          bridgeName, bridgeUUID, protocols, status);
678         } else {
679             Status status = ovsdbConfigurationService.updateRow(node,
680                                                          bridge.getSchema().getName(),
681                                                          null,
682                                                          bridgeUUID,
683                                                          bridge.getRow());
684             LOGGER.debug("addBridge: Updating Bridge {} {} with protocols {} and status {}",
685                          bridgeName, bridgeUUID, protocols, status);
686         }
687
688         ovsdbConfigurationService.setOFController(node, bridgeUUID);
689
690         if (localPatchName != null &&
691             remotePatchName != null &&
692             networkingProviderManager.getProvider(node).hasPerTenantTunneling()) {
693             return addPatchPort(node, bridgeUUID, localPatchName, remotePatchName);
694         }
695         return new Status(StatusCode.SUCCESS);
696     }
697
698
699 }