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