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