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