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