c60386324f57df85324a2e62edb71a88fc559229
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onosproject.ovsdb.controller.driver;
17
18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.google.common.base.Function;
20 import com.google.common.collect.ImmutableList;
21 import com.google.common.collect.Lists;
22 import com.google.common.collect.Maps;
23 import com.google.common.collect.Sets;
24 import com.google.common.util.concurrent.Futures;
25 import com.google.common.util.concurrent.ListenableFuture;
26 import com.google.common.util.concurrent.SettableFuture;
27
28 import io.netty.channel.Channel;
29
30 import org.onlab.packet.IpAddress;
31 import org.onosproject.net.DeviceId;
32 import org.onosproject.net.behaviour.ControllerInfo;
33 import org.onosproject.ovsdb.controller.OvsdbBridge;
34 import org.onosproject.ovsdb.controller.OvsdbBridgeName;
35 import org.onosproject.ovsdb.controller.OvsdbClientService;
36 import org.onosproject.ovsdb.controller.OvsdbConstant;
37 import org.onosproject.ovsdb.controller.OvsdbDatapathId;
38 import org.onosproject.ovsdb.controller.OvsdbNodeId;
39 import org.onosproject.ovsdb.controller.OvsdbPort;
40 import org.onosproject.ovsdb.controller.OvsdbPortName;
41 import org.onosproject.ovsdb.controller.OvsdbPortNumber;
42 import org.onosproject.ovsdb.controller.OvsdbRowStore;
43 import org.onosproject.ovsdb.controller.OvsdbStore;
44 import org.onosproject.ovsdb.controller.OvsdbTableStore;
45 import org.onosproject.ovsdb.controller.OvsdbTunnel;
46 import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
47 import org.onosproject.ovsdb.rfc.message.OperationResult;
48 import org.onosproject.ovsdb.rfc.message.TableUpdates;
49 import org.onosproject.ovsdb.rfc.notation.Condition;
50 import org.onosproject.ovsdb.rfc.notation.Mutation;
51 import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
52 import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
53 import org.onosproject.ovsdb.rfc.notation.Row;
54 import org.onosproject.ovsdb.rfc.notation.UUID;
55 import org.onosproject.ovsdb.rfc.operations.Delete;
56 import org.onosproject.ovsdb.rfc.operations.Insert;
57 import org.onosproject.ovsdb.rfc.operations.Mutate;
58 import org.onosproject.ovsdb.rfc.operations.Operation;
59 import org.onosproject.ovsdb.rfc.operations.Update;
60 import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
61 import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
62 import org.onosproject.ovsdb.rfc.schema.TableSchema;
63 import org.onosproject.ovsdb.rfc.table.Bridge;
64 import org.onosproject.ovsdb.rfc.table.Controller;
65 import org.onosproject.ovsdb.rfc.table.Interface;
66 import org.onosproject.ovsdb.rfc.table.OvsdbTable;
67 import org.onosproject.ovsdb.rfc.table.Port;
68 import org.onosproject.ovsdb.rfc.table.TableGenerator;
69 import org.onosproject.ovsdb.rfc.utils.ConditionUtil;
70 import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
71 import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil;
72 import org.onosproject.ovsdb.rfc.utils.MutationUtil;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76 import java.net.InetSocketAddress;
77 import java.util.ArrayList;
78 import java.util.Arrays;
79 import java.util.HashMap;
80 import java.util.HashSet;
81 import java.util.Iterator;
82 import java.util.List;
83 import java.util.Map;
84 import java.util.Set;
85 import java.util.concurrent.ConcurrentMap;
86 import java.util.concurrent.ExecutionException;
87 import java.util.concurrent.atomic.AtomicReference;
88 import java.util.stream.Collectors;
89
90 /**
91  * An representation of an ovsdb client.
92  */
93 public class DefaultOvsdbClient
94         implements OvsdbProviderService, OvsdbClientService {
95
96     private final Logger log = LoggerFactory
97             .getLogger(DefaultOvsdbClient.class);
98
99     private Channel channel;
100
101     private OvsdbAgent agent;
102     private boolean connected;
103     private OvsdbNodeId nodeId;
104     private Callback monitorCallBack;
105
106     private OvsdbStore ovsdbStore = new OvsdbStore();
107
108     private final Map<String, String> requestMethod = Maps.newHashMap();
109     private final Map<String, SettableFuture<? extends Object>> requestResult = Maps
110             .newHashMap();
111
112     private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
113     private final Set<OvsdbTunnel> ovsdbTunnels = new HashSet<OvsdbTunnel>();
114
115     /**
116      * Creates an OvsdbClient.
117      *
118      * @param nodeId ovsdb node id
119      */
120     public DefaultOvsdbClient(OvsdbNodeId nodeId) {
121         this.nodeId = nodeId;
122     }
123
124     @Override
125     public OvsdbNodeId nodeId() {
126         return nodeId;
127     }
128
129     @Override
130     public void setAgent(OvsdbAgent agent) {
131         if (this.agent == null) {
132             this.agent = agent;
133         }
134     }
135
136     @Override
137     public void setChannel(Channel channel) {
138         this.channel = channel;
139     }
140
141     @Override
142     public void setConnection(boolean connected) {
143         this.connected = connected;
144     }
145
146     @Override
147     public boolean isConnected() {
148         return this.connected;
149     }
150
151     @Override
152     public void nodeAdded() {
153         this.agent.addConnectedNode(nodeId, this);
154     }
155
156     @Override
157     public void nodeRemoved() {
158         this.agent.removeConnectedNode(nodeId);
159         channel.disconnect();
160     }
161
162     /**
163      * Gets the ovsdb table store.
164      *
165      * @param dbName the ovsdb database name
166      * @return ovsTableStore, empty if table store is find
167      */
168     private OvsdbTableStore getTableStore(String dbName) {
169         if (ovsdbStore == null) {
170             return null;
171         }
172         return ovsdbStore.getOvsdbTableStore(dbName);
173     }
174
175     /**
176      * Gets the ovsdb row store.
177      *
178      * @param dbName    the ovsdb database name
179      * @param tableName the ovsdb table name
180      * @return ovsRowStore, empty store if no rows exist in the table
181      */
182     private OvsdbRowStore getRowStore(String dbName, String tableName) {
183         OvsdbTableStore tableStore = getTableStore(dbName);
184         if (tableStore == null) {
185             return null;
186         }
187
188         OvsdbRowStore rowStore = tableStore.getRows(tableName);
189         if (rowStore == null) {
190             rowStore = new OvsdbRowStore();
191         }
192         return rowStore;
193     }
194
195     /**
196      * Gets the ovsdb row.
197      *
198      * @param dbName    the ovsdb database name
199      * @param tableName the ovsdb table name
200      * @param uuid      the key of the row
201      * @return row, empty if row is find
202      */
203     @Override
204     public Row getRow(String dbName, String tableName, String uuid) {
205         OvsdbTableStore tableStore = getTableStore(dbName);
206         if (tableStore == null) {
207             return null;
208         }
209         OvsdbRowStore rowStore = tableStore.getRows(tableName);
210         if (rowStore == null) {
211             return null;
212         }
213         return rowStore.getRow(uuid);
214     }
215
216     @Override
217     public void removeRow(String dbName, String tableName, String uuid) {
218         OvsdbTableStore tableStore = getTableStore(dbName);
219         if (tableStore == null) {
220             return;
221         }
222         OvsdbRowStore rowStore = tableStore.getRows(tableName);
223         if (rowStore == null) {
224             return;
225         }
226         rowStore.deleteRow(uuid);
227     }
228
229     @Override
230     public void updateOvsdbStore(String dbName, String tableName, String uuid,
231                                  Row row) {
232         OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName);
233         if (tableStore == null) {
234             tableStore = new OvsdbTableStore();
235         }
236         OvsdbRowStore rowStore = tableStore.getRows(tableName);
237         if (rowStore == null) {
238             rowStore = new OvsdbRowStore();
239         }
240         rowStore.insertRow(uuid, row);
241         tableStore.createOrUpdateTable(tableName, rowStore);
242         ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
243     }
244
245     @Override
246     public String getPortUuid(String portName, String bridgeUuid) {
247         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
248
249         Row bridgeRow = getRow(OvsdbConstant.DATABASENAME,
250                                OvsdbConstant.BRIDGE, bridgeUuid);
251
252         Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
253                                                          OvsdbTable.BRIDGE);
254         if (bridge != null) {
255             OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
256             @SuppressWarnings("unchecked")
257             Set<UUID> ports = setPorts.set();
258             if (ports == null || ports.size() == 0) {
259                 log.warn("The port uuid is null");
260                 return null;
261             }
262
263             for (UUID uuid : ports) {
264                 Row portRow = getRow(OvsdbConstant.DATABASENAME,
265                                      OvsdbConstant.PORT, uuid.value());
266                 Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
267                                                            OvsdbTable.PORT);
268                 if (port != null && portName.equalsIgnoreCase(port.getName())) {
269                     return uuid.value();
270                 }
271             }
272
273         }
274         return null;
275     }
276
277     @Override
278     public String getInterfaceUuid(String portUuid, String portName) {
279         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
280
281         Row portRow = getRow(OvsdbConstant.DATABASENAME, OvsdbConstant.PORT,
282                              portUuid);
283         Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
284                                                    OvsdbTable.PORT);
285
286         if (port != null) {
287             OvsdbSet setInterfaces = (OvsdbSet) port.getInterfacesColumn().data();
288             @SuppressWarnings("unchecked")
289             Set<UUID> interfaces = setInterfaces.set();
290
291             if (interfaces == null || interfaces.size() == 0) {
292                 log.warn("The interface uuid is null");
293                 return null;
294             }
295
296             for (UUID uuid : interfaces) {
297                 Row intfRow = getRow(OvsdbConstant.DATABASENAME,
298                                      OvsdbConstant.INTERFACE, uuid.value());
299                 Interface intf = (Interface) TableGenerator
300                         .getTable(dbSchema, intfRow, OvsdbTable.INTERFACE);
301                 if (intf != null && portName.equalsIgnoreCase(intf.getName())) {
302                     return uuid.value();
303                 }
304             }
305
306         }
307
308         return null;
309     }
310
311     @Override
312     public String getBridgeUuid(String bridgeName) {
313         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
314
315         OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
316                                              OvsdbConstant.BRIDGE);
317         if (rowStore == null) {
318             log.debug("The bridge uuid is null");
319             return null;
320         }
321
322         ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
323         if (bridgeTableRows == null) {
324             log.debug("The bridge uuid is null");
325             return null;
326         }
327
328         for (String uuid : bridgeTableRows.keySet()) {
329             Bridge bridge = (Bridge) TableGenerator
330                     .getTable(dbSchema, bridgeTableRows.get(uuid),
331                               OvsdbTable.BRIDGE);
332
333             if (bridge.getName().equals(bridgeName)) {
334                 return uuid;
335             }
336
337         }
338         return null;
339     }
340
341     @Override
342     public String getControllerUuid(String controllerName,
343                                     String controllerTarget) {
344         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
345         OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
346                                              OvsdbConstant.CONTROLLER);
347         if (rowStore == null) {
348             log.debug("The controller uuid is null");
349             return null;
350         }
351
352         ConcurrentMap<String, Row> controllerTableRows = rowStore.getRowStore();
353         if (controllerTableRows != null) {
354             for (String uuid : controllerTableRows.keySet()) {
355
356                 Controller controller = (Controller) TableGenerator
357                         .getTable(dbSchema, controllerTableRows.get(uuid),
358                                   OvsdbTable.CONTROLLER);
359                 String target = (String) controller.getTargetColumn().data();
360                 if (target.equalsIgnoreCase(controllerTarget)) {
361                     return uuid;
362                 }
363
364             }
365         }
366         return null;
367     }
368
369     @Override
370     public String getOvsUuid(String dbName) {
371         OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
372                                              OvsdbConstant.DATABASENAME);
373         if (rowStore == null) {
374             log.debug("The bridge uuid is null");
375             return null;
376         }
377         ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
378         if (ovsTableRows != null) {
379             for (String uuid : ovsTableRows.keySet()) {
380                 Row row = ovsTableRows.get(uuid);
381                 String tableName = row.tableName();
382                 if (tableName.equals(dbName)) {
383                     return uuid;
384                 }
385             }
386         }
387         return null;
388     }
389
390     @Override
391     public void createPort(String bridgeName, String portName) {
392         String bridgeUuid = getBridgeUuid(bridgeName);
393         if (bridgeUuid == null) {
394             log.error("Can't find bridge {} in {}", bridgeName,
395                       nodeId.getIpAddress());
396             return;
397         }
398
399         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
400         String portUuid = getPortUuid(portName, bridgeUuid);
401
402         Port port = (Port) TableGenerator
403                 .createTable(dbSchema, OvsdbTable.PORT);
404
405         port.setName(portName);
406         if (portUuid == null) {
407             insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE,
408                          "ports", bridgeUuid, port.getRow());
409         } else {
410             updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow());
411         }
412
413         return;
414     }
415
416     @Override
417     public void dropPort(String bridgeName, String portName) {
418         String bridgeUuid = getBridgeUuid(bridgeName);
419         if (bridgeUuid == null) {
420             log.error("Could not find Bridge {} in {}", bridgeName, nodeId);
421             return;
422         }
423
424         String portUuid = getPortUuid(portName, bridgeUuid);
425         if (portUuid != null) {
426             log.info("Port {} delete", portName);
427             deleteConfig(OvsdbConstant.PORT, "_uuid", portUuid,
428                          OvsdbConstant.BRIDGE, "ports");
429         }
430     }
431
432     @Override
433     public void createBridge(String bridgeName) {
434         log.debug("create bridge {}", bridgeName);
435
436         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
437         if (dbSchema == null) {
438             log.warn("The schema is null");
439             return;
440         }
441
442         Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema,
443                                                             OvsdbTable.BRIDGE);
444         if (bridge == null) {
445             log.debug("Can not create bridge");
446             return;
447         }
448
449         Set<String> failModes = new HashSet<>();
450         failModes.add("secure");
451         bridge.setFailMode(failModes);
452
453         Set<String> protocols = new HashSet<>();
454         protocols.add(OvsdbConstant.OPENFLOW13);
455         bridge.setProtocols(protocols);
456
457         String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME);
458         if (ovsUuid == null) {
459             log.warn("The Open_vSwitch is null");
460             return;
461         }
462
463         String bridgeUuid = getBridgeUuid(bridgeName);
464         if (bridgeUuid == null) {
465             log.debug("Create a new bridge");
466
467             bridge.setName(bridgeName);
468             bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
469                                       OvsdbConstant.DATABASENAME, "bridges",
470                                       ovsUuid, bridge.getRow());
471
472             if (bridgeUuid != null) {
473                 Port port = (Port) TableGenerator.createTable(dbSchema,
474                                                               OvsdbTable.PORT);
475                 if (port != null) {
476                     log.debug("the port is not null");
477                     port.setName(bridgeName);
478
479                     insertConfig(OvsdbConstant.PORT, "_uuid", "Bridge", "ports", bridgeUuid,
480                                  port.getRow());
481                 }
482             }
483
484         } else {
485             log.info("Update a bridge");
486             updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid, bridge.getRow());
487         }
488
489         setControllerAuto(bridgeUuid);
490         log.info("Create bridge success");
491     }
492
493     @Override
494     public void createBridge(String bridgeName, String dpid, String exPortName) {
495         log.debug("create bridge {}", bridgeName);
496
497         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
498         if (dbSchema == null) {
499             log.warn("The schema is null");
500             return;
501         }
502
503         Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema,
504                                                             OvsdbTable.BRIDGE);
505         if (bridge == null) {
506             log.debug("Can not create bridge");
507             return;
508         }
509
510         Set<String> failModes = new HashSet<>();
511         failModes.add("secure");
512         bridge.setFailMode(failModes);
513
514         Set<String> protocols = new HashSet<>();
515         protocols.add(OvsdbConstant.OPENFLOW13);
516         bridge.setProtocols(protocols);
517
518         String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME);
519         if (ovsUuid == null) {
520             log.warn("The Open_vSwitch is null");
521             return;
522         }
523
524         String bridgeUuid = getBridgeUuid(bridgeName);
525         if (bridgeUuid == null) {
526             log.debug("Create a new bridge");
527
528             bridge.setName(bridgeName);
529             if (dpid != null) {
530                 Map<String, String> options = new HashMap<>();
531                 options.put("datapath-id", dpid);
532                 bridge.setOtherConfig(options);
533             }
534             bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
535                                       OvsdbConstant.DATABASENAME, "bridges",
536                                       ovsUuid, bridge.getRow());
537
538             if (bridgeUuid != null) {
539                 Port port = (Port) TableGenerator.createTable(dbSchema,
540                                                               OvsdbTable.PORT);
541                 if (port != null) {
542                     log.debug("the port is not null");
543                     port.setName(bridgeName);
544
545                     insertConfig(OvsdbConstant.PORT, "_uuid", "Bridge", "ports", bridgeUuid,
546                                  port.getRow());
547                 }
548             }
549
550         } else {
551             log.info("Update a bridge");
552             updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid, bridge.getRow());
553         }
554         // Create external port
555         if (exPortName != null) {
556             createPort(bridgeName, exPortName);
557         }
558
559         setControllerAuto(bridgeUuid);
560         log.info("Create bridge success");
561     }
562
563     @Override
564     public boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers) {
565
566         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
567         String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME);
568
569         if (dbSchema == null || ovsUuid == null) {
570             log.warn("Couldn't find database Open_vSwitch");
571             return false;
572         }
573
574         String bridgeUuid = getBridgeUuid(bridgeName);
575         if (bridgeUuid != null) {
576             log.warn("Bridge {} is already exist", bridgeName);
577             // remove existing one and re-create?
578             return false;
579         }
580
581         Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema, OvsdbTable.BRIDGE);
582         bridge.setName(bridgeName);
583
584         Set<String> failMode = new HashSet<>(Arrays.asList("secure"));
585         bridge.setFailMode(failMode);
586
587         Set<String> protocols = new HashSet<>(Arrays.asList(OvsdbConstant.OPENFLOW13));
588         bridge.setProtocols(protocols);
589
590         Map<String, String> options = new HashMap<>();
591         options.put("datapath-id", dpid);
592         bridge.setOtherConfig(options);
593
594         bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
595                                   OvsdbConstant.DATABASENAME, "bridges",
596                                   ovsUuid, bridge.getRow());
597
598         if (bridgeUuid != null) {
599             createPort(bridgeName, bridgeName);
600         } else {
601             log.warn("Failed to create bridge {} on {}", bridgeName, nodeId.toString());
602             return false;
603         }
604
605         setControllersWithUUID(UUID.uuid(bridgeUuid), controllers);
606         return true;
607     }
608
609     /**
610      * Sets the bridge's controller automatically.
611      * <p/>
612      * The connection is a TCP connection to the local ONOS instance's IP
613      * and the default OpenFlow port.
614      *
615      * @param bridgeUuid bridge uuid
616      */
617     private void setControllerAuto(String bridgeUuid) {
618         IpAddress ipAddress = IpAddress.valueOf(((InetSocketAddress) channel.localAddress()).getAddress());
619         ControllerInfo controllerInfo = new ControllerInfo(ipAddress, OvsdbConstant.OFPORT, "tcp");
620         log.debug("Automatically setting controller for bridge {} to {}",
621                   bridgeUuid, controllerInfo.target());
622         setControllersWithUUID(UUID.uuid(bridgeUuid), ImmutableList.of(controllerInfo));
623     }
624
625     @Override
626     public void setControllersWithUUID(UUID bridgeUuid, List<ControllerInfo> controllers) {
627
628         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
629         if (dbSchema == null) {
630             log.debug("There is no schema");
631             return;
632         }
633         List<Controller> oldControllers = getControllers(bridgeUuid);
634         if (oldControllers == null) {
635             log.warn("There are no controllers");
636             return;
637         }
638
639         Set<UUID> newControllerUuids = new HashSet<>();
640
641         Set<ControllerInfo> newControllers = new HashSet<>(controllers);
642         List<Controller> removeControllers = new ArrayList<>();
643         oldControllers.forEach(controller -> {
644             ControllerInfo controllerInfo = new ControllerInfo((String) controller.getTargetColumn().data());
645             if (newControllers.contains(controllerInfo)) {
646                 newControllers.remove(controllerInfo);
647                 newControllerUuids.add(controller.getRow().uuid());
648             } else {
649                 removeControllers.add(controller);
650             }
651         });
652         OvsdbRowStore controllerRowStore = getRowStore(OvsdbConstant.DATABASENAME,
653                                                        OvsdbConstant.CONTROLLER);
654         if (controllerRowStore == null) {
655             log.debug("There is no controller table");
656             return;
657         }
658
659         removeControllers.forEach(c -> deleteConfig(OvsdbConstant.CONTROLLER, "_uuid", c.getRow().uuid().value(),
660                                                     OvsdbConstant.BRIDGE, "controller"));
661
662         newControllers.stream().map(c -> {
663             Controller controller = (Controller) TableGenerator
664                     .createTable(dbSchema, OvsdbTable.CONTROLLER);
665             controller.setTarget(c.target());
666             return controller;
667         }).forEach(c -> {
668             String uuid = insertConfig(OvsdbConstant.CONTROLLER, "_uuid",
669                                        OvsdbConstant.BRIDGE, "controller", bridgeUuid.value(),
670                                        c.getRow());
671             newControllerUuids.add(UUID.uuid(uuid));
672
673         });
674
675         OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
676                                              OvsdbConstant.BRIDGE);
677         if (rowStore == null) {
678             log.debug("There is no bridge table");
679             return;
680         }
681
682         Row bridgeRow = rowStore.getRow(bridgeUuid.value());
683         Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
684         bridge.setController(OvsdbSet.ovsdbSet(newControllerUuids));
685         updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid.value(), bridge.getRow());
686     }
687
688     @Override
689     public void setControllersWithDeviceId(DeviceId deviceId, List<ControllerInfo> controllers) {
690         setControllersWithUUID(getBridgeUUID(deviceId), controllers);
691     }
692
693     @Override
694     public void dropBridge(String bridgeName) {
695         String bridgeUUID = getBridgeUuid(bridgeName);
696         if (bridgeUUID == null) {
697             log.warn("Could not find bridge in node", nodeId.getIpAddress());
698             return;
699         }
700         deleteConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUUID,
701                      OvsdbConstant.DATABASENAME, "bridges");
702     }
703
704     @Override
705     public void createTunnel(IpAddress srcIp, IpAddress dstIp) {
706         String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
707         if (bridgeUuid == null) {
708             log.warn("Could not find bridge {} and Could not create tunnel. ",
709                      OvsdbConstant.INTEGRATION_BRIDGE);
710             return;
711         }
712
713         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
714         String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
715         String portUuid = getPortUuid(portName, bridgeUuid);
716
717         Port port = (Port) TableGenerator
718                 .createTable(dbSchema, OvsdbTable.PORT);
719         if (port != null) {
720             port.setName(portName);
721         }
722
723         if (portUuid == null) {
724             portUuid = insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE,
725                                     "ports", bridgeUuid, port.getRow());
726         } else {
727             updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow());
728         }
729
730         // When a tunnel is created, A row is inserted into port table and
731         // interface table of the ovsdb node.
732         // and the following step is to get the interface uuid from local store
733         // in controller node.
734         // but it need spend some time synchronising data between node and
735         // controller.
736         // so loop to judge if interfaceUUid is null is necessary.
737         String interfaceUuid = null;
738         for (int i = 0; i < 10; i++) {
739             interfaceUuid = getInterfaceUuid(portUuid, portName);
740             if (interfaceUuid == null) {
741                 try {
742                     Thread.sleep(500);
743                 } catch (InterruptedException e) {
744                     log.warn("Interrupted while waiting to get interfaceUuid");
745                     Thread.currentThread().interrupt();
746                 }
747             } else {
748                 break;
749             }
750         }
751
752         if (interfaceUuid != null) {
753
754             Interface tunInterface = (Interface) TableGenerator
755                     .createTable(dbSchema, OvsdbTable.INTERFACE);
756
757             if (tunInterface != null) {
758
759                 tunInterface.setType(OvsdbConstant.TYPEVXLAN);
760                 Map<String, String> options = Maps.newHashMap();
761                 options.put("key", "flow");
762                 options.put("local_ip", srcIp.toString());
763                 options.put("remote_ip", dstIp.toString());
764                 tunInterface.setOptions(options);
765                 updateConfig(OvsdbConstant.INTERFACE, "_uuid", interfaceUuid,
766                              tunInterface.getRow());
767                 log.info("Tunnel added success", tunInterface);
768
769             }
770         }
771
772         return;
773     }
774
775     @Override
776     public boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options) {
777
778         String bridgeUuid  = getBridgeUuid(bridgeName);
779         if (bridgeUuid == null) {
780             log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
781             return false;
782         }
783
784         if (getPortUuid(portName, bridgeUuid) != null) {
785             log.warn("Port {} already exists", portName);
786             // remove existing one and re-create?
787             return false;
788         }
789
790         ArrayList<Operation> operations = Lists.newArrayList();
791         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
792
793         // insert a new port to the port table
794         Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
795         port.setName(portName);
796         Insert portInsert = new Insert(dbSchema.getTableSchema("Port"), "Port", port.getRow());
797         portInsert.getRow().put("interfaces", UUID.uuid("Interface"));
798         operations.add(portInsert);
799
800         // update the bridge table
801         Condition condition = ConditionUtil.equals("_uuid", UUID.uuid(bridgeUuid));
802         Mutation mutation = MutationUtil.insert("ports", UUID.uuid("Port"));
803         List<Condition> conditions = new ArrayList<>(Arrays.asList(condition));
804         List<Mutation> mutations = new ArrayList<>(Arrays.asList(mutation));
805         operations.add(new Mutate(dbSchema.getTableSchema("Bridge"), conditions, mutations));
806
807         // insert a tunnel interface
808         Interface intf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
809         intf.setName(portName);
810         intf.setType(tunnelType);
811         intf.setOptions(options);
812         Insert intfInsert = new Insert(dbSchema.getTableSchema("Interface"), "Interface", intf.getRow());
813         operations.add(intfInsert);
814
815         transactConfig(OvsdbConstant.DATABASENAME, operations);
816         return true;
817     }
818
819     @Override
820     public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
821         String bridgeName = OvsdbConstant.INTEGRATION_BRIDGE;
822         String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
823         String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
824         if (bridgeUuid == null) {
825             log.warn("Could not find bridge {} in {}", bridgeName,
826                      nodeId.getIpAddress());
827             return;
828         }
829
830         String portUUID = getPortUuid(portName, bridgeUuid);
831         if (portUUID != null) {
832             log.info("Delete tunnel");
833             deleteConfig(OvsdbConstant.PORT, "_uuid", portUUID,
834                          OvsdbConstant.BRIDGE, "ports");
835         }
836
837         return;
838     }
839
840     /**
841      * Delete transact config.
842      *
843      * @param childTableName   child table name
844      * @param childColumnName  child column name
845      * @param childUuid        child row uuid
846      * @param parentTableName  parent table name
847      * @param parentColumnName parent column
848      */
849     private void deleteConfig(String childTableName, String childColumnName,
850                               String childUuid, String parentTableName,
851                               String parentColumnName) {
852         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
853         TableSchema childTableSchema = dbSchema.getTableSchema(childTableName);
854
855         ArrayList<Operation> operations = Lists.newArrayList();
856         if (parentTableName != null && parentColumnName != null) {
857             TableSchema parentTableSchema = dbSchema
858                     .getTableSchema(parentTableName);
859             ColumnSchema parentColumnSchema = parentTableSchema
860                     .getColumnSchema(parentColumnName);
861             List<Mutation> mutations = Lists.newArrayList();
862             Mutation mutation = MutationUtil.delete(parentColumnSchema.name(),
863                                                     UUID.uuid(childUuid));
864             mutations.add(mutation);
865             List<Condition> conditions = Lists.newArrayList();
866             Condition condition = ConditionUtil.includes(parentColumnName,
867                                                          UUID.uuid(childUuid));
868             conditions.add(condition);
869             Mutate op = new Mutate(parentTableSchema, conditions, mutations);
870             operations.add(op);
871         }
872
873         List<Condition> conditions = Lists.newArrayList();
874         Condition condition = ConditionUtil.equals(childColumnName, UUID.uuid(childUuid));
875         conditions.add(condition);
876         Delete del = new Delete(childTableSchema, conditions);
877         operations.add(del);
878         transactConfig(OvsdbConstant.DATABASENAME, operations);
879
880         return;
881     }
882
883     /**
884      * Update transact config.
885      *
886      * @param tableName  table name
887      * @param columnName column name
888      * @param uuid       uuid
889      * @param row        the config data
890      */
891     private void updateConfig(String tableName, String columnName, String uuid,
892                               Row row) {
893         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
894         TableSchema tableSchema = dbSchema.getTableSchema(tableName);
895
896         List<Condition> conditions = Lists.newArrayList();
897         Condition condition = ConditionUtil.equals(columnName, UUID.uuid(uuid));
898         conditions.add(condition);
899
900         Update update = new Update(tableSchema, row, conditions);
901
902         ArrayList<Operation> operations = Lists.newArrayList();
903         operations.add(update);
904
905         transactConfig(OvsdbConstant.DATABASENAME, operations);
906     }
907
908     /**
909      * Insert transact config.
910      *
911      * @param childTableName   child table name
912      * @param childColumnName  child column name
913      * @param parentTableName  parent table name
914      * @param parentColumnName parent column
915      * @param parentUuid       parent uuid
916      * @param row              the config data
917      * @return uuid, empty if no uuid is find
918      */
919     private String insertConfig(String childTableName, String childColumnName,
920                                 String parentTableName, String parentColumnName,
921                                 String parentUuid, Row row) {
922         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
923         TableSchema tableSchema = dbSchema.getTableSchema(childTableName);
924
925         String namedUuid = childTableName;
926         Insert insert = new Insert(tableSchema, namedUuid, row);
927
928         ArrayList<Operation> operations = Lists.newArrayList();
929         operations.add(insert);
930
931         if (parentTableName != null && parentColumnName != null) {
932             TableSchema parentTableSchema = dbSchema
933                     .getTableSchema(parentTableName);
934             ColumnSchema parentColumnSchema = parentTableSchema
935                     .getColumnSchema(parentColumnName);
936
937             List<Mutation> mutations = Lists.newArrayList();
938             Mutation mutation = MutationUtil.insert(parentColumnSchema.name(),
939                                                     UUID.uuid(namedUuid));
940             mutations.add(mutation);
941
942             List<Condition> conditions = Lists.newArrayList();
943             Condition condition = ConditionUtil.equals("_uuid",
944                                                        UUID.uuid(parentUuid));
945             conditions.add(condition);
946
947             Mutate op = new Mutate(parentTableSchema, conditions, mutations);
948             operations.add(op);
949         }
950         if (childTableName.equalsIgnoreCase(OvsdbConstant.PORT)) {
951             log.info("Handle port insert");
952             Insert intfInsert = handlePortInsertTable(OvsdbConstant.INTERFACE,
953                                                       row);
954
955             if (intfInsert != null) {
956                 operations.add(intfInsert);
957             }
958
959             Insert ins = (Insert) operations.get(0);
960             ins.getRow().put("interfaces",
961                              UUID.uuid(OvsdbConstant.INTERFACE));
962         }
963
964         List<OperationResult> results;
965         try {
966             results = transactConfig(OvsdbConstant.DATABASENAME, operations)
967                     .get();
968
969             return results.get(0).getUuid().value();
970         } catch (InterruptedException e) {
971             log.warn("Interrupted while waiting to get result");
972             Thread.currentThread().interrupt();
973         } catch (ExecutionException e) {
974             log.error("Exception thrown while to get result");
975         }
976
977         return null;
978     }
979
980     /**
981      * Handles port insert.
982      *
983      * @param tableName ovsdb table interface
984      * @param portRow   row of port
985      * @return insert, empty if null
986      */
987     private Insert handlePortInsertTable(String tableName, Row portRow) {
988         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
989
990         TableSchema portTableSchema = dbSchema
991                 .getTableSchema(OvsdbConstant.PORT);
992         ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name");
993
994         String portName = (String) portRow.getColumn(portColumnSchema.name()).data();
995
996         Interface inf = (Interface) TableGenerator
997                 .createTable(dbSchema, OvsdbTable.INTERFACE);
998
999         inf.setName(portName);
1000
1001         TableSchema intfTableSchema = dbSchema
1002                 .getTableSchema(OvsdbConstant.INTERFACE);
1003         Insert insert = new Insert(intfTableSchema, OvsdbConstant.INTERFACE,
1004                                    inf.getRow());
1005         return insert;
1006     }
1007
1008     /**
1009      * Gets tunnel name.
1010      *
1011      * @param tunnelType
1012      * @param dstIp      the remote ip address
1013      * @return tunnel name
1014      */
1015     private String getTunnelName(String tunnelType, IpAddress dstIp) {
1016         return tunnelType + "-" + dstIp.toString();
1017     }
1018
1019     @Override
1020     public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
1021         if (dbName == null) {
1022             return null;
1023         }
1024         DatabaseSchema databaseSchema = schema.get(dbName);
1025         if (databaseSchema == null) {
1026             List<String> dbNames = new ArrayList<String>();
1027             dbNames.add(dbName);
1028             Function<JsonNode, DatabaseSchema> rowFunction = new Function<JsonNode, DatabaseSchema>() {
1029                 @Override
1030                 public DatabaseSchema apply(JsonNode input) {
1031                     log.info("Get ovsdb database schema {}", dbName);
1032                     DatabaseSchema dbSchema = FromJsonUtil
1033                             .jsonNodeToDbSchema(dbName, input);
1034                     if (dbSchema == null) {
1035                         log.debug("Get ovsdb database schema error");
1036                         return null;
1037                     }
1038                     schema.put(dbName, dbSchema);
1039
1040                     return dbSchema;
1041                 }
1042             };
1043
1044             ListenableFuture<JsonNode> input = getSchema(dbNames);
1045             if (input != null) {
1046                 return Futures.transform(input, rowFunction);
1047             }
1048             return null;
1049         } else {
1050             return Futures.immediateFuture(databaseSchema);
1051         }
1052     }
1053
1054     @Override
1055     public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) {
1056         if (dbName == null) {
1057             return null;
1058         }
1059         DatabaseSchema dbSchema = schema.get(dbName);
1060         if (dbSchema != null) {
1061             Function<JsonNode, TableUpdates> rowFunction = new Function<JsonNode, TableUpdates>() {
1062                 @Override
1063                 public TableUpdates apply(JsonNode input) {
1064                     log.info("Get table updates");
1065                     TableUpdates updates = FromJsonUtil
1066                             .jsonNodeToTableUpdates(input, dbSchema);
1067                     if (updates == null) {
1068                         log.debug("Get table updates error");
1069                         return null;
1070                     }
1071                     return updates;
1072                 }
1073             };
1074             return Futures.transform(monitor(dbSchema, id), rowFunction);
1075         }
1076         return null;
1077     }
1078
1079     @Override
1080     public ListenableFuture<List<OperationResult>> transactConfig(String dbName,
1081                                                                   List<Operation> operations) {
1082         if (dbName == null) {
1083             return null;
1084         }
1085         DatabaseSchema dbSchema = schema.get(dbName);
1086         if (dbSchema != null) {
1087             Function<List<JsonNode>, List<OperationResult>> rowFunction = (input -> {
1088                 log.info("Get ovsdb operation result");
1089                 List<OperationResult> result = FromJsonUtil
1090                         .jsonNodeToOperationResult(input, operations);
1091
1092                 if (result == null) {
1093                     log.debug("The operation result is null");
1094                     return null;
1095                 }
1096                 return result;
1097             });
1098             return Futures.transform(transact(dbSchema, operations),
1099                                      rowFunction);
1100         }
1101         return null;
1102     }
1103
1104     @Override
1105     public ListenableFuture<JsonNode> getSchema(List<String> dbnames) {
1106         String id = java.util.UUID.randomUUID().toString();
1107         String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames);
1108
1109         SettableFuture<JsonNode> sf = SettableFuture.create();
1110         requestResult.put(id, sf);
1111         requestMethod.put(id, "getSchema");
1112
1113         channel.writeAndFlush(getSchemaString);
1114         return sf;
1115
1116     }
1117
1118     @Override
1119     public ListenableFuture<List<String>> echo() {
1120         String id = java.util.UUID.randomUUID().toString();
1121         String echoString = JsonRpcWriterUtil.echoStr(id);
1122
1123         SettableFuture<List<String>> sf = SettableFuture.create();
1124         requestResult.put(id, sf);
1125         requestMethod.put(id, "echo");
1126
1127         channel.writeAndFlush(echoString);
1128         return sf;
1129
1130     }
1131
1132     @Override
1133     public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema,
1134                                               String monitorId) {
1135         String id = java.util.UUID.randomUUID().toString();
1136         String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId,
1137                                                             dbSchema);
1138
1139         SettableFuture<JsonNode> sf = SettableFuture.create();
1140         requestResult.put(id, sf);
1141         requestMethod.put(id, "monitor");
1142
1143         channel.writeAndFlush(monitorString);
1144         return sf;
1145
1146     }
1147
1148     @Override
1149     public ListenableFuture<List<String>> listDbs() {
1150         String id = java.util.UUID.randomUUID().toString();
1151         String listDbsString = JsonRpcWriterUtil.listDbsStr(id);
1152
1153         SettableFuture<List<String>> sf = SettableFuture.create();
1154         requestResult.put(id, sf);
1155         requestMethod.put(id, "listDbs");
1156
1157         channel.writeAndFlush(listDbsString);
1158         return sf;
1159
1160     }
1161
1162     @Override
1163     public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema,
1164                                                      List<Operation> operations) {
1165         String id = java.util.UUID.randomUUID().toString();
1166         String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema,
1167                                                               operations);
1168
1169         SettableFuture<List<JsonNode>> sf = SettableFuture.create();
1170         requestResult.put(id, sf);
1171         requestMethod.put(id, "transact");
1172
1173         channel.writeAndFlush(transactString);
1174         return sf;
1175
1176     }
1177
1178     @SuppressWarnings({"rawtypes", "unchecked"})
1179     @Override
1180     public void processResult(JsonNode response) {
1181         log.debug("Handle result");
1182         String requestId = response.get("id").asText();
1183         SettableFuture sf = requestResult.get(requestId);
1184         if (sf == null) {
1185             log.debug("No such future to process");
1186             return;
1187         }
1188         String methodName = requestMethod.get(requestId);
1189
1190         Object result;
1191         result = FromJsonUtil.jsonResultParser(response, methodName);
1192
1193         sf.set(result);
1194         return;
1195     }
1196
1197     @Override
1198     public void processRequest(JsonNode requestJson) {
1199         log.debug("Handle request");
1200         if (requestJson.get("method").asText().equalsIgnoreCase("echo")) {
1201             log.debug("handle echo request");
1202
1203             String replyString = FromJsonUtil.getEchoRequestStr(requestJson);
1204             channel.writeAndFlush(replyString);
1205
1206             return;
1207         } else {
1208             FromJsonUtil
1209                     .jsonCallbackRequestParser(requestJson, monitorCallBack);
1210             return;
1211         }
1212     }
1213
1214     @Override
1215     public void setCallback(Callback monitorCallback) {
1216         this.monitorCallBack = monitorCallback;
1217     }
1218
1219     @Override
1220     public Set<OvsdbTunnel> getTunnels() {
1221         return ovsdbTunnels;
1222     }
1223
1224     @Override
1225     public Set<OvsdbBridge> getBridges() {
1226         Set<OvsdbBridge> ovsdbBridges = new HashSet<OvsdbBridge>();
1227         OvsdbTableStore tableStore = getTableStore(OvsdbConstant.DATABASENAME);
1228         if (tableStore == null) {
1229             return null;
1230         }
1231         OvsdbRowStore rowStore = tableStore.getRows(OvsdbConstant.BRIDGE);
1232         if (rowStore == null) {
1233             return null;
1234         }
1235         ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1236         for (String uuid : rows.keySet()) {
1237             Row row = getRow(OvsdbConstant.DATABASENAME, OvsdbConstant.BRIDGE,
1238                              uuid);
1239             OvsdbBridge ovsdbBridge = getOvsdbBridge(row);
1240             if (ovsdbBridge != null) {
1241                 ovsdbBridges.add(ovsdbBridge);
1242             }
1243         }
1244         return ovsdbBridges;
1245     }
1246
1247     @Override
1248     public Set<ControllerInfo> getControllers(DeviceId openflowDeviceId) {
1249         UUID bridgeUuid = getBridgeUUID(openflowDeviceId);
1250         if (bridgeUuid == null) {
1251             log.warn("bad bridge Uuid");
1252             return null;
1253         }
1254         List<Controller> controllers = getControllers(bridgeUuid);
1255         if (controllers == null) {
1256             log.warn("bad list of controllers");
1257             return null;
1258         }
1259         return controllers.stream().
1260                 map(controller -> new ControllerInfo(
1261                         (String) controller.getTargetColumn()
1262                                 .data())).collect(Collectors.toSet());
1263     }
1264
1265     private List<Controller> getControllers(UUID bridgeUuid) {
1266         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
1267         if (dbSchema == null) {
1268             return null;
1269         }
1270         OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
1271                                              OvsdbConstant.BRIDGE);
1272         if (rowStore == null) {
1273             log.debug("There is no bridge table");
1274             return null;
1275         }
1276
1277         Row bridgeRow = rowStore.getRow(bridgeUuid.value());
1278         Bridge bridge = (Bridge) TableGenerator.
1279                 getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
1280
1281         //FIXME remove log
1282         log.warn("type of controller column", bridge.getControllerColumn()
1283                 .data().getClass());
1284         Set<UUID> controllerUuids = (Set<UUID>) ((OvsdbSet) bridge
1285                 .getControllerColumn().data()).set();
1286 //        Set<String> controllerUuidStrings = (Set<String>) bridge.getControllerColumn().data();
1287
1288         OvsdbRowStore controllerRowStore = getRowStore(OvsdbConstant.DATABASENAME,
1289                                                        OvsdbConstant.CONTROLLER);
1290         if (controllerRowStore == null) {
1291             log.debug("There is no controller table");
1292             return null;
1293         }
1294
1295         List<Controller> ovsdbControllers = new ArrayList<>();
1296         ConcurrentMap<String, Row> controllerTableRows = controllerRowStore.getRowStore();
1297         controllerTableRows.forEach((key, row) -> {
1298             if (!controllerUuids.contains(UUID.uuid(key))) {
1299                 return;
1300             }
1301             Controller controller = (Controller) TableGenerator
1302                     .getTable(dbSchema, row, OvsdbTable.CONTROLLER);
1303             ovsdbControllers.add(controller);
1304         });
1305         return ovsdbControllers;
1306     }
1307
1308
1309     private UUID getBridgeUUID(DeviceId openflowDeviceId) {
1310         DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
1311         if (dbSchema == null) {
1312             return null;
1313         }
1314         OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
1315                                              OvsdbConstant.BRIDGE);
1316         if (rowStore == null) {
1317             log.debug("There is no bridge table");
1318             return null;
1319         }
1320
1321         ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
1322         final AtomicReference<UUID> uuid = new AtomicReference<>();
1323         for (Map.Entry<String, Row> entry : bridgeTableRows.entrySet()) {
1324             Bridge b = (Bridge) TableGenerator.getTable(dbSchema,
1325                                                         entry.getValue(),
1326                                                         OvsdbTable.BRIDGE);
1327             if (matchesDpid(b, openflowDeviceId)) {
1328                 uuid.set(UUID.uuid(entry.getKey()));
1329                 break;
1330             }
1331         }
1332         if (uuid.get() == null) {
1333             log.debug("There is no bridge for {}", openflowDeviceId);
1334         }
1335         return uuid.get();
1336
1337     }
1338
1339     private static boolean matchesDpid(Bridge b, DeviceId deviceId) {
1340         String ofDpid = deviceId.toString().replace("of:", "");
1341         Set ofDeviceIds = ((OvsdbSet) b.getDatapathIdColumn().data()).set();
1342         //TODO Set<String>
1343         return ofDeviceIds.contains(ofDpid);
1344     }
1345
1346     @Override
1347     public Set<OvsdbPort> getPorts() {
1348         Set<OvsdbPort> ovsdbPorts = new HashSet<OvsdbPort>();
1349         OvsdbTableStore tableStore = getTableStore(OvsdbConstant.DATABASENAME);
1350         if (tableStore == null) {
1351             return null;
1352         }
1353         OvsdbRowStore rowStore = tableStore.getRows(OvsdbConstant.INTERFACE);
1354         if (rowStore == null) {
1355             return null;
1356         }
1357         ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1358         for (String uuid : rows.keySet()) {
1359             Row row = getRow(OvsdbConstant.DATABASENAME,
1360                              OvsdbConstant.INTERFACE, uuid);
1361             OvsdbPort ovsdbPort = getOvsdbPort(row);
1362             if (ovsdbPort != null) {
1363                 ovsdbPorts.add(ovsdbPort);
1364             }
1365         }
1366         return ovsdbPorts;
1367     }
1368
1369     @Override
1370     public DatabaseSchema getDatabaseSchema(String dbName) {
1371         return schema.get(dbName);
1372     }
1373
1374     //Gets ovsdb port.
1375     private OvsdbPort getOvsdbPort(Row row) {
1376         DatabaseSchema dbSchema = getDatabaseSchema(OvsdbConstant.DATABASENAME);
1377         Interface intf = (Interface) TableGenerator
1378                 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1379         if (intf == null) {
1380             return null;
1381         }
1382         long ofPort = getOfPort(intf);
1383         String portName = intf.getName();
1384         if ((ofPort < 0) || (portName == null)) {
1385             return null;
1386         }
1387
1388         OvsdbPort ovsdbPort = new OvsdbPort(new OvsdbPortNumber(ofPort),
1389                                             new OvsdbPortName(portName));
1390         return ovsdbPort;
1391     }
1392
1393     ////Gets ovsdb bridge.
1394     private OvsdbBridge getOvsdbBridge(Row row) {
1395         DatabaseSchema dbSchema = getDatabaseSchema(OvsdbConstant.DATABASENAME);
1396         Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, row,
1397                                                          OvsdbTable.BRIDGE);
1398         if (bridge == null) {
1399             return null;
1400         }
1401
1402         OvsdbSet datapathIdSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
1403         @SuppressWarnings("unchecked")
1404         Set<String> datapathIds = datapathIdSet.set();
1405         if (datapathIds == null || datapathIds.size() == 0) {
1406             return null;
1407         }
1408         String datapathId = (String) datapathIds.toArray()[0];
1409         String bridgeName = bridge.getName();
1410         if ((datapathId == null) || (bridgeName == null)) {
1411             return null;
1412         }
1413
1414         OvsdbBridge ovsdbBridge = new OvsdbBridge(new OvsdbBridgeName(bridgeName),
1415                                                   new OvsdbDatapathId(datapathId));
1416         return ovsdbBridge;
1417     }
1418
1419     //Gets ofPort in the interface.
1420     private long getOfPort(Interface intf) {
1421         OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
1422         @SuppressWarnings("unchecked")
1423         Set<Integer> ofPorts = ofPortSet.set();
1424         while (ofPorts == null || ofPorts.size() <= 0) {
1425             log.debug("The ofport is null in {}", intf.getName());
1426             return -1;
1427         }
1428         // return (long) ofPorts.toArray()[0];
1429         Iterator<Integer> it = ofPorts.iterator();
1430         return Long.parseLong(it.next().toString());
1431     }
1432
1433     @Override
1434     public Set<OvsdbPort> getLocalPorts(Iterable<String> ifaceids) {
1435         Set<OvsdbPort> ovsdbPorts = new HashSet<OvsdbPort>();
1436         OvsdbTableStore tableStore = getTableStore(OvsdbConstant.DATABASENAME);
1437         if (tableStore == null) {
1438             return null;
1439         }
1440         OvsdbRowStore rowStore = tableStore.getRows(OvsdbConstant.INTERFACE);
1441         if (rowStore == null) {
1442             return null;
1443         }
1444         ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1445         for (String uuid : rows.keySet()) {
1446             Row row = getRow(OvsdbConstant.DATABASENAME,
1447                              OvsdbConstant.INTERFACE, uuid);
1448             DatabaseSchema dbSchema = getDatabaseSchema(OvsdbConstant.DATABASENAME);
1449             Interface intf = (Interface) TableGenerator
1450                     .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1451             if (intf == null || getIfaceid(intf) == null) {
1452                 continue;
1453             }
1454             String portName = intf.getName();
1455             Set<String> ifaceidSet = Sets.newHashSet(ifaceids);
1456             if (portName.startsWith("vxlan")
1457                     || !ifaceidSet.contains(getIfaceid(intf))) {
1458                 continue;
1459             }
1460             long ofPort = getOfPort(intf);
1461             if ((ofPort < 0) || (portName == null)) {
1462                 continue;
1463             }
1464
1465             OvsdbPort ovsdbPort = new OvsdbPort(new OvsdbPortNumber(ofPort),
1466                                                 new OvsdbPortName(portName));
1467             if (ovsdbPort != null) {
1468                 ovsdbPorts.add(ovsdbPort);
1469             }
1470         }
1471         return ovsdbPorts;
1472     }
1473
1474     private String getIfaceid(Interface intf) {
1475         OvsdbMap ovsdbMap = (OvsdbMap) intf.getExternalIdsColumn().data();
1476         @SuppressWarnings("unchecked")
1477         Map<String, String> externalIds = ovsdbMap.map();
1478         if (externalIds.isEmpty()) {
1479             log.warn("The external_ids is null");
1480             return null;
1481         }
1482         String ifaceid = externalIds
1483                 .get(OvsdbConstant.EXTERNAL_ID_INTERFACE_ID);
1484         if (ifaceid == null) {
1485             log.warn("The ifaceid is null");
1486             return null;
1487         }
1488         return ifaceid;
1489     }
1490
1491     @Override
1492     public void disconnect() {
1493         channel.disconnect();
1494         this.agent.removeConnectedNode(nodeId);
1495     }
1496 }