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