blob: cbb94ac846c3de82a8edce820a1baf1b9144ffa5 [file] [log] [blame]
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07003 *
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 */
16package org.onosproject.ovsdb.controller.driver;
17
andreaed976a42015-10-05 14:38:25 -070018import com.fasterxml.jackson.databind.JsonNode;
19import com.google.common.base.Function;
20import com.google.common.collect.Lists;
21import com.google.common.collect.Maps;
22import com.google.common.collect.Sets;
23import com.google.common.util.concurrent.Futures;
24import com.google.common.util.concurrent.ListenableFuture;
25import com.google.common.util.concurrent.SettableFuture;
lishuai6c56f5e2015-11-17 16:38:19 +080026
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070027import io.netty.channel.Channel;
lishuai6c56f5e2015-11-17 16:38:19 +080028
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070029import org.onlab.packet.IpAddress;
andreaed976a42015-10-05 14:38:25 -070030import org.onosproject.net.DeviceId;
Hyunsun Moon1251e192016-06-07 16:57:05 -070031import org.onosproject.net.behaviour.BridgeDescription;
andreaed976a42015-10-05 14:38:25 -070032import org.onosproject.net.behaviour.ControllerInfo;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070033import org.onosproject.ovsdb.controller.OvsdbBridge;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070034import org.onosproject.ovsdb.controller.OvsdbClientService;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070035import org.onosproject.ovsdb.controller.OvsdbNodeId;
36import org.onosproject.ovsdb.controller.OvsdbPort;
37import org.onosproject.ovsdb.controller.OvsdbPortName;
38import org.onosproject.ovsdb.controller.OvsdbPortNumber;
39import org.onosproject.ovsdb.controller.OvsdbRowStore;
40import org.onosproject.ovsdb.controller.OvsdbStore;
41import org.onosproject.ovsdb.controller.OvsdbTableStore;
42import org.onosproject.ovsdb.controller.OvsdbTunnel;
43import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
44import org.onosproject.ovsdb.rfc.message.OperationResult;
45import org.onosproject.ovsdb.rfc.message.TableUpdates;
46import org.onosproject.ovsdb.rfc.notation.Condition;
47import org.onosproject.ovsdb.rfc.notation.Mutation;
CNluciusa66c3972015-09-06 20:31:29 +080048import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070049import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
50import org.onosproject.ovsdb.rfc.notation.Row;
Jonathan Hart51539b82015-10-29 09:53:04 -070051import org.onosproject.ovsdb.rfc.notation.Uuid;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070052import org.onosproject.ovsdb.rfc.operations.Delete;
53import org.onosproject.ovsdb.rfc.operations.Insert;
54import org.onosproject.ovsdb.rfc.operations.Mutate;
55import org.onosproject.ovsdb.rfc.operations.Operation;
56import org.onosproject.ovsdb.rfc.operations.Update;
57import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
58import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
59import org.onosproject.ovsdb.rfc.schema.TableSchema;
60import org.onosproject.ovsdb.rfc.table.Bridge;
61import org.onosproject.ovsdb.rfc.table.Controller;
62import org.onosproject.ovsdb.rfc.table.Interface;
63import org.onosproject.ovsdb.rfc.table.OvsdbTable;
64import org.onosproject.ovsdb.rfc.table.Port;
65import org.onosproject.ovsdb.rfc.table.TableGenerator;
66import org.onosproject.ovsdb.rfc.utils.ConditionUtil;
67import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
68import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil;
69import org.onosproject.ovsdb.rfc.utils.MutationUtil;
70import org.slf4j.Logger;
71import org.slf4j.LoggerFactory;
72
andreaed976a42015-10-05 14:38:25 -070073import java.net.InetSocketAddress;
74import java.util.ArrayList;
Hyunsun Moon646d8c42015-10-08 20:32:44 -070075import java.util.Arrays;
andreaed976a42015-10-05 14:38:25 -070076import java.util.HashSet;
77import java.util.Iterator;
78import java.util.List;
79import java.util.Map;
80import java.util.Set;
81import java.util.concurrent.ConcurrentMap;
82import java.util.concurrent.ExecutionException;
83import java.util.concurrent.atomic.AtomicReference;
84import java.util.stream.Collectors;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070085
Hyunsun Moon1251e192016-06-07 16:57:05 -070086import static org.onosproject.ovsdb.controller.OvsdbConstant.*;
87
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070088/**
89 * An representation of an ovsdb client.
90 */
Hyunsun Moon1251e192016-06-07 16:57:05 -070091public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientService {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070092
Hyunsun Moon1251e192016-06-07 16:57:05 -070093 private final Logger log = LoggerFactory.getLogger(DefaultOvsdbClient.class);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070094
95 private Channel channel;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070096 private OvsdbAgent agent;
97 private boolean connected;
98 private OvsdbNodeId nodeId;
99 private Callback monitorCallBack;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700100 private OvsdbStore ovsdbStore = new OvsdbStore();
101
102 private final Map<String, String> requestMethod = Maps.newHashMap();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700103 private final Map<String, SettableFuture<? extends Object>> requestResult = Maps.newHashMap();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700104 private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
105 private final Set<OvsdbTunnel> ovsdbTunnels = new HashSet<OvsdbTunnel>();
106
107 /**
108 * Creates an OvsdbClient.
109 *
110 * @param nodeId ovsdb node id
111 */
112 public DefaultOvsdbClient(OvsdbNodeId nodeId) {
113 this.nodeId = nodeId;
114 }
115
116 @Override
117 public OvsdbNodeId nodeId() {
118 return nodeId;
119 }
120
121 @Override
122 public void setAgent(OvsdbAgent agent) {
123 if (this.agent == null) {
124 this.agent = agent;
125 }
126 }
127
128 @Override
129 public void setChannel(Channel channel) {
130 this.channel = channel;
131 }
132
133 @Override
134 public void setConnection(boolean connected) {
135 this.connected = connected;
136 }
137
138 @Override
139 public boolean isConnected() {
140 return this.connected;
141 }
142
143 @Override
144 public void nodeAdded() {
145 this.agent.addConnectedNode(nodeId, this);
146 }
147
148 @Override
149 public void nodeRemoved() {
150 this.agent.removeConnectedNode(nodeId);
151 channel.disconnect();
152 }
153
154 /**
155 * Gets the ovsdb table store.
156 *
157 * @param dbName the ovsdb database name
158 * @return ovsTableStore, empty if table store is find
159 */
160 private OvsdbTableStore getTableStore(String dbName) {
161 if (ovsdbStore == null) {
162 return null;
163 }
164 return ovsdbStore.getOvsdbTableStore(dbName);
165 }
166
167 /**
168 * Gets the ovsdb row store.
169 *
andreaed976a42015-10-05 14:38:25 -0700170 * @param dbName the ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700171 * @param tableName the ovsdb table name
Hyunsun Moon6125c612015-10-15 10:54:44 -0700172 * @return ovsRowStore, empty store if no rows exist in the table
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700173 */
174 private OvsdbRowStore getRowStore(String dbName, String tableName) {
175 OvsdbTableStore tableStore = getTableStore(dbName);
176 if (tableStore == null) {
177 return null;
178 }
Hyunsun Moon6125c612015-10-15 10:54:44 -0700179
180 OvsdbRowStore rowStore = tableStore.getRows(tableName);
181 if (rowStore == null) {
182 rowStore = new OvsdbRowStore();
183 }
184 return rowStore;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700185 }
186
187 /**
188 * Gets the ovsdb row.
189 *
andreaed976a42015-10-05 14:38:25 -0700190 * @param dbName the ovsdb database name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700191 * @param tableName the ovsdb table name
andreaed976a42015-10-05 14:38:25 -0700192 * @param uuid the key of the row
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700193 * @return row, empty if row is find
194 */
195 @Override
196 public Row getRow(String dbName, String tableName, String uuid) {
197 OvsdbTableStore tableStore = getTableStore(dbName);
198 if (tableStore == null) {
199 return null;
200 }
201 OvsdbRowStore rowStore = tableStore.getRows(tableName);
202 if (rowStore == null) {
203 return null;
204 }
205 return rowStore.getRow(uuid);
206 }
207
208 @Override
209 public void removeRow(String dbName, String tableName, String uuid) {
210 OvsdbTableStore tableStore = getTableStore(dbName);
211 if (tableStore == null) {
212 return;
213 }
214 OvsdbRowStore rowStore = tableStore.getRows(tableName);
215 if (rowStore == null) {
216 return;
217 }
218 rowStore.deleteRow(uuid);
219 }
220
221 @Override
222 public void updateOvsdbStore(String dbName, String tableName, String uuid,
223 Row row) {
224 OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName);
225 if (tableStore == null) {
226 tableStore = new OvsdbTableStore();
227 }
228 OvsdbRowStore rowStore = tableStore.getRows(tableName);
229 if (rowStore == null) {
230 rowStore = new OvsdbRowStore();
231 }
232 rowStore.insertRow(uuid, row);
233 tableStore.createOrUpdateTable(tableName, rowStore);
234 ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
235 }
236
237 @Override
238 public String getPortUuid(String portName, String bridgeUuid) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700239 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700240
Hyunsun Moon1251e192016-06-07 16:57:05 -0700241 Row bridgeRow = getRow(DATABASENAME, BRIDGE, bridgeUuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700242 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
243 OvsdbTable.BRIDGE);
244 if (bridge != null) {
245 OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
246 @SuppressWarnings("unchecked")
Jonathan Hart51539b82015-10-29 09:53:04 -0700247 Set<Uuid> ports = setPorts.set();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700248 if (ports == null || ports.size() == 0) {
249 log.warn("The port uuid is null");
250 return null;
251 }
252
Jonathan Hart51539b82015-10-29 09:53:04 -0700253 for (Uuid uuid : ports) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700254 Row portRow = getRow(DATABASENAME, PORT, uuid.value());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700255 Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
256 OvsdbTable.PORT);
257 if (port != null && portName.equalsIgnoreCase(port.getName())) {
258 return uuid.value();
259 }
260 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700261 }
262 return null;
263 }
264
265 @Override
266 public String getInterfaceUuid(String portUuid, String portName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700267 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700268
Hyunsun Moon1251e192016-06-07 16:57:05 -0700269 Row portRow = getRow(DATABASENAME, PORT, portUuid);
270 Port port = (Port) TableGenerator.getTable(dbSchema, portRow, OvsdbTable.PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700271
272 if (port != null) {
273 OvsdbSet setInterfaces = (OvsdbSet) port.getInterfacesColumn().data();
274 @SuppressWarnings("unchecked")
Jonathan Hart51539b82015-10-29 09:53:04 -0700275 Set<Uuid> interfaces = setInterfaces.set();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700276
277 if (interfaces == null || interfaces.size() == 0) {
278 log.warn("The interface uuid is null");
279 return null;
280 }
281
Jonathan Hart51539b82015-10-29 09:53:04 -0700282 for (Uuid uuid : interfaces) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700283 Row intfRow = getRow(DATABASENAME, INTERFACE, uuid.value());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700284 Interface intf = (Interface) TableGenerator
285 .getTable(dbSchema, intfRow, OvsdbTable.INTERFACE);
286 if (intf != null && portName.equalsIgnoreCase(intf.getName())) {
287 return uuid.value();
288 }
289 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700290 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700291 return null;
292 }
293
294 @Override
295 public String getBridgeUuid(String bridgeName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700296 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700297
Hyunsun Moon1251e192016-06-07 16:57:05 -0700298 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700299 if (rowStore == null) {
300 log.debug("The bridge uuid is null");
301 return null;
302 }
303
304 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
305 if (bridgeTableRows == null) {
306 log.debug("The bridge uuid is null");
307 return null;
308 }
309
310 for (String uuid : bridgeTableRows.keySet()) {
311 Bridge bridge = (Bridge) TableGenerator
Hyunsun Moon1251e192016-06-07 16:57:05 -0700312 .getTable(dbSchema, bridgeTableRows.get(uuid), OvsdbTable.BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700313 if (bridge.getName().equals(bridgeName)) {
314 return uuid;
315 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700316 }
317 return null;
318 }
319
320 @Override
Hyunsun Moon1251e192016-06-07 16:57:05 -0700321 public String getControllerUuid(String controllerName, String controllerTarget) {
322 DatabaseSchema dbSchema = schema.get(DATABASENAME);
323 OvsdbRowStore rowStore = getRowStore(DATABASENAME, CONTROLLER);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700324 if (rowStore == null) {
325 log.debug("The controller uuid is null");
326 return null;
327 }
328
329 ConcurrentMap<String, Row> controllerTableRows = rowStore.getRowStore();
330 if (controllerTableRows != null) {
331 for (String uuid : controllerTableRows.keySet()) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700332 Controller controller = (Controller) TableGenerator
333 .getTable(dbSchema, controllerTableRows.get(uuid),
334 OvsdbTable.CONTROLLER);
335 String target = (String) controller.getTargetColumn().data();
336 if (target.equalsIgnoreCase(controllerTarget)) {
337 return uuid;
338 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700339 }
340 }
341 return null;
342 }
343
344 @Override
345 public String getOvsUuid(String dbName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700346 OvsdbRowStore rowStore = getRowStore(DATABASENAME, DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700347 if (rowStore == null) {
348 log.debug("The bridge uuid is null");
349 return null;
350 }
351 ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
352 if (ovsTableRows != null) {
353 for (String uuid : ovsTableRows.keySet()) {
354 Row row = ovsTableRows.get(uuid);
355 String tableName = row.tableName();
356 if (tableName.equals(dbName)) {
357 return uuid;
358 }
359 }
360 }
361 return null;
362 }
363
364 @Override
365 public void createPort(String bridgeName, String portName) {
366 String bridgeUuid = getBridgeUuid(bridgeName);
367 if (bridgeUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700368 log.error("Can't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700369 return;
370 }
371
Hyunsun Moon1251e192016-06-07 16:57:05 -0700372 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700373 String portUuid = getPortUuid(portName, bridgeUuid);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700374 Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700375 port.setName(portName);
376 if (portUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700377 insertConfig(PORT, UUID, BRIDGE, PORTS, bridgeUuid, port.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700378 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700379 updateConfig(PORT, UUID, portUuid, port.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700380 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700381 }
382
383 @Override
384 public void dropPort(String bridgeName, String portName) {
385 String bridgeUuid = getBridgeUuid(bridgeName);
386 if (bridgeUuid == null) {
387 log.error("Could not find Bridge {} in {}", bridgeName, nodeId);
388 return;
389 }
390
391 String portUuid = getPortUuid(portName, bridgeUuid);
392 if (portUuid != null) {
393 log.info("Port {} delete", portName);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700394 deleteConfig(PORT, UUID, portUuid, BRIDGE, PORTS);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700395 }
396 }
397
Hyunsun Moon1251e192016-06-07 16:57:05 -0700398 @Deprecated
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700399 @Override
400 public void createBridge(String bridgeName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700401 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
402 .name(bridgeName)
403 .build();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700404
Hyunsun Moon1251e192016-06-07 16:57:05 -0700405 createBridge(ovsdbBridge);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700406 }
407
Hyunsun Moon1251e192016-06-07 16:57:05 -0700408 @Deprecated
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700409 @Override
lishuai6c56f5e2015-11-17 16:38:19 +0800410 public void createBridge(String bridgeName, String dpid, String exPortName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700411 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
412 .name(bridgeName)
413 .failMode(BridgeDescription.FailMode.SECURE)
414 .datapathId(dpid)
415 .disableInBand()
416 .controllers(Lists.newArrayList(localController()))
417 .build();
lishuai6c56f5e2015-11-17 16:38:19 +0800418
Hyunsun Moon1251e192016-06-07 16:57:05 -0700419 createBridge(ovsdbBridge);
lishuai6c56f5e2015-11-17 16:38:19 +0800420
lishuai6c56f5e2015-11-17 16:38:19 +0800421 if (exPortName != null) {
422 createPort(bridgeName, exPortName);
423 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700424 }
lishuai6c56f5e2015-11-17 16:38:19 +0800425
Hyunsun Moon1251e192016-06-07 16:57:05 -0700426 @Deprecated
427 @Override
428 public boolean createBridge(String bridgeName, String dpid, List<ControllerInfo> controllers) {
429 OvsdbBridge ovsdbBridge = OvsdbBridge.builder()
430 .name(bridgeName)
431 .failMode(BridgeDescription.FailMode.SECURE)
432 .datapathId(dpid)
433 .disableInBand()
434 .controllers(controllers)
435 .build();
436
437 return createBridge(ovsdbBridge);
lishuai6c56f5e2015-11-17 16:38:19 +0800438 }
439
440 @Override
Hyunsun Moon1251e192016-06-07 16:57:05 -0700441 public boolean createBridge(OvsdbBridge ovsdbBridge) {
442 DatabaseSchema dbSchema = schema.get(DATABASENAME);
443 String ovsUuid = getOvsUuid(DATABASENAME);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700444
445 if (dbSchema == null || ovsUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700446 log.error("Can't find database Open_vSwitch");
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700447 return false;
448 }
449
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700450 Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema, OvsdbTable.BRIDGE);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700451 bridge.setOtherConfig(ovsdbBridge.otherConfigs());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700452
Hyunsun Moon1251e192016-06-07 16:57:05 -0700453 if (ovsdbBridge.failMode().isPresent()) {
454 String failMode = ovsdbBridge.failMode().get().name().toLowerCase();
455 bridge.setFailMode(Sets.newHashSet(failMode));
Bob zhoue9795fd2016-05-12 20:18:45 +0800456 }
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700457
Hyunsun Moon1251e192016-06-07 16:57:05 -0700458 String bridgeUuid = getBridgeUuid(ovsdbBridge.name());
Hyunsun Moon98025542016-03-08 04:36:02 -0800459 if (bridgeUuid == null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700460 bridge.setName(ovsdbBridge.name());
461 bridgeUuid = insertConfig(
462 BRIDGE, UUID, DATABASENAME, BRIDGES,
463 ovsUuid, bridge.getRow());
Hyunsun Moon98025542016-03-08 04:36:02 -0800464 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700465 // update the bridge if it's already existing
466 updateConfig(BRIDGE, UUID, bridgeUuid, bridge.getRow());
Hyunsun Moon98025542016-03-08 04:36:02 -0800467 }
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700468
Hyunsun Moon1251e192016-06-07 16:57:05 -0700469 if (bridgeUuid == null) {
470 log.warn("Failed to create bridge {} on {}", ovsdbBridge.name(), nodeId);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700471 return false;
472 }
473
Hyunsun Moon1251e192016-06-07 16:57:05 -0700474 createPort(ovsdbBridge.name(), ovsdbBridge.name());
475 setControllersWithUuid(Uuid.uuid(bridgeUuid), ovsdbBridge.controllers());
476
477 log.info("Created bridge {}", ovsdbBridge.name());
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700478 return true;
479 }
480
Hyunsun Moon1251e192016-06-07 16:57:05 -0700481 @Override
482 public ControllerInfo localController() {
483 IpAddress ipAddress = IpAddress.valueOf(((InetSocketAddress)
484 channel.localAddress()).getAddress());
485 return new ControllerInfo(ipAddress, OFPORT, "tcp");
andreaed976a42015-10-05 14:38:25 -0700486 }
487
andreaed976a42015-10-05 14:38:25 -0700488 @Override
Jonathan Hart51539b82015-10-29 09:53:04 -0700489 public void setControllersWithUuid(Uuid bridgeUuid, List<ControllerInfo> controllers) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700490 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -0700491 if (dbSchema == null) {
492 log.debug("There is no schema");
493 return;
494 }
495 List<Controller> oldControllers = getControllers(bridgeUuid);
496 if (oldControllers == null) {
497 log.warn("There are no controllers");
498 return;
499 }
500
Jonathan Hart51539b82015-10-29 09:53:04 -0700501 Set<Uuid> newControllerUuids = new HashSet<>();
andreaed976a42015-10-05 14:38:25 -0700502
503 Set<ControllerInfo> newControllers = new HashSet<>(controllers);
504 List<Controller> removeControllers = new ArrayList<>();
505 oldControllers.forEach(controller -> {
506 ControllerInfo controllerInfo = new ControllerInfo((String) controller.getTargetColumn().data());
507 if (newControllers.contains(controllerInfo)) {
508 newControllers.remove(controllerInfo);
509 newControllerUuids.add(controller.getRow().uuid());
510 } else {
511 removeControllers.add(controller);
512 }
513 });
Hyunsun Moon1251e192016-06-07 16:57:05 -0700514 OvsdbRowStore controllerRowStore = getRowStore(DATABASENAME, CONTROLLER);
andreaed976a42015-10-05 14:38:25 -0700515 if (controllerRowStore == null) {
516 log.debug("There is no controller table");
517 return;
518 }
519
Hyunsun Moon1251e192016-06-07 16:57:05 -0700520 removeControllers.forEach(c -> deleteConfig(CONTROLLER, UUID, c.getRow().uuid().value(),
521 BRIDGE, "controller"));
andreaed976a42015-10-05 14:38:25 -0700522 newControllers.stream().map(c -> {
523 Controller controller = (Controller) TableGenerator
524 .createTable(dbSchema, OvsdbTable.CONTROLLER);
525 controller.setTarget(c.target());
526 return controller;
527 }).forEach(c -> {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700528 String uuid = insertConfig(CONTROLLER, UUID, BRIDGE, "controller", bridgeUuid.value(),
andreaed976a42015-10-05 14:38:25 -0700529 c.getRow());
Jonathan Hart51539b82015-10-29 09:53:04 -0700530 newControllerUuids.add(Uuid.uuid(uuid));
andreaed976a42015-10-05 14:38:25 -0700531
532 });
533
Hyunsun Moon1251e192016-06-07 16:57:05 -0700534 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -0700535 if (rowStore == null) {
536 log.debug("There is no bridge table");
537 return;
538 }
539
540 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
541 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
542 bridge.setController(OvsdbSet.ovsdbSet(newControllerUuids));
Hyunsun Moon1251e192016-06-07 16:57:05 -0700543 updateConfig(BRIDGE, UUID, bridgeUuid.value(), bridge.getRow());
andreaed976a42015-10-05 14:38:25 -0700544 }
545
andreaed976a42015-10-05 14:38:25 -0700546 @Override
547 public void setControllersWithDeviceId(DeviceId deviceId, List<ControllerInfo> controllers) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700548 setControllersWithUuid(getBridgeUuid(deviceId), controllers);
andreaed976a42015-10-05 14:38:25 -0700549 }
550
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700551 @Override
552 public void dropBridge(String bridgeName) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700553 String bridgeUuid = getBridgeUuid(bridgeName);
554 if (bridgeUuid == null) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700555 log.warn("Could not find bridge in node", nodeId.getIpAddress());
556 return;
557 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700558 deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, "bridges");
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700559 }
560
561 @Override
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700562 public boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options) {
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700563 String bridgeUuid = getBridgeUuid(bridgeName);
564 if (bridgeUuid == null) {
565 log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
566 return false;
567 }
568
569 if (getPortUuid(portName, bridgeUuid) != null) {
570 log.warn("Port {} already exists", portName);
571 // remove existing one and re-create?
572 return false;
573 }
574
575 ArrayList<Operation> operations = Lists.newArrayList();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700576 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700577
578 // insert a new port to the port table
579 Port port = (Port) TableGenerator.createTable(dbSchema, OvsdbTable.PORT);
580 port.setName(portName);
581 Insert portInsert = new Insert(dbSchema.getTableSchema("Port"), "Port", port.getRow());
Jonathan Hart51539b82015-10-29 09:53:04 -0700582 portInsert.getRow().put("interfaces", Uuid.uuid("Interface"));
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700583 operations.add(portInsert);
584
585 // update the bridge table
Hyunsun Moon1251e192016-06-07 16:57:05 -0700586 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
587 Mutation mutation = MutationUtil.insert(PORTS, Uuid.uuid("Port"));
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700588 List<Condition> conditions = new ArrayList<>(Arrays.asList(condition));
589 List<Mutation> mutations = new ArrayList<>(Arrays.asList(mutation));
590 operations.add(new Mutate(dbSchema.getTableSchema("Bridge"), conditions, mutations));
591
592 // insert a tunnel interface
593 Interface intf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
594 intf.setName(portName);
595 intf.setType(tunnelType);
596 intf.setOptions(options);
597 Insert intfInsert = new Insert(dbSchema.getTableSchema("Interface"), "Interface", intf.getRow());
598 operations.add(intfInsert);
599
Hyunsun Moon1251e192016-06-07 16:57:05 -0700600 transactConfig(DATABASENAME, operations);
Hyunsun Moon646d8c42015-10-08 20:32:44 -0700601 return true;
602 }
603
604 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700605 public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700606 String bridgeName = INTEGRATION_BRIDGE;
607 String portName = getTunnelName(TYPEVXLAN, dstIp);
608 String bridgeUuid = getBridgeUuid(INTEGRATION_BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700609 if (bridgeUuid == null) {
610 log.warn("Could not find bridge {} in {}", bridgeName,
611 nodeId.getIpAddress());
612 return;
613 }
614
Jonathan Hart51539b82015-10-29 09:53:04 -0700615 String portUuid = getPortUuid(portName, bridgeUuid);
616 if (portUuid != null) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700617 log.info("Delete tunnel");
Hyunsun Moon1251e192016-06-07 16:57:05 -0700618 deleteConfig(PORT, UUID, portUuid, BRIDGE, PORTS);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700619 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700620 }
621
622 /**
623 * Delete transact config.
624 *
andreaed976a42015-10-05 14:38:25 -0700625 * @param childTableName child table name
626 * @param childColumnName child column name
627 * @param childUuid child row uuid
628 * @param parentTableName parent table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700629 * @param parentColumnName parent column
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700630 */
631 private void deleteConfig(String childTableName, String childColumnName,
andreaed976a42015-10-05 14:38:25 -0700632 String childUuid, String parentTableName,
633 String parentColumnName) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700634 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700635 TableSchema childTableSchema = dbSchema.getTableSchema(childTableName);
636
637 ArrayList<Operation> operations = Lists.newArrayList();
638 if (parentTableName != null && parentColumnName != null) {
639 TableSchema parentTableSchema = dbSchema
640 .getTableSchema(parentTableName);
641 ColumnSchema parentColumnSchema = parentTableSchema
642 .getColumnSchema(parentColumnName);
643 List<Mutation> mutations = Lists.newArrayList();
644 Mutation mutation = MutationUtil.delete(parentColumnSchema.name(),
Jonathan Hart51539b82015-10-29 09:53:04 -0700645 Uuid.uuid(childUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700646 mutations.add(mutation);
647 List<Condition> conditions = Lists.newArrayList();
648 Condition condition = ConditionUtil.includes(parentColumnName,
Jonathan Hart51539b82015-10-29 09:53:04 -0700649 Uuid.uuid(childUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700650 conditions.add(condition);
651 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
652 operations.add(op);
653 }
654
655 List<Condition> conditions = Lists.newArrayList();
Jonathan Hart51539b82015-10-29 09:53:04 -0700656 Condition condition = ConditionUtil.isEqual(childColumnName, Uuid.uuid(childUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700657 conditions.add(condition);
658 Delete del = new Delete(childTableSchema, conditions);
659 operations.add(del);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700660 transactConfig(DATABASENAME, operations);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700661 }
662
663 /**
664 * Update transact config.
665 *
andreaed976a42015-10-05 14:38:25 -0700666 * @param tableName table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700667 * @param columnName column name
andreaed976a42015-10-05 14:38:25 -0700668 * @param uuid uuid
669 * @param row the config data
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700670 */
671 private void updateConfig(String tableName, String columnName, String uuid,
andreaed976a42015-10-05 14:38:25 -0700672 Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700673 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700674 TableSchema tableSchema = dbSchema.getTableSchema(tableName);
675
676 List<Condition> conditions = Lists.newArrayList();
Jonathan Hart51539b82015-10-29 09:53:04 -0700677 Condition condition = ConditionUtil.isEqual(columnName, Uuid.uuid(uuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700678 conditions.add(condition);
679
680 Update update = new Update(tableSchema, row, conditions);
681
682 ArrayList<Operation> operations = Lists.newArrayList();
683 operations.add(update);
684
Hyunsun Moon1251e192016-06-07 16:57:05 -0700685 transactConfig(DATABASENAME, operations);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700686 }
687
688 /**
689 * Insert transact config.
690 *
andreaed976a42015-10-05 14:38:25 -0700691 * @param childTableName child table name
692 * @param childColumnName child column name
693 * @param parentTableName parent table name
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700694 * @param parentColumnName parent column
andreaed976a42015-10-05 14:38:25 -0700695 * @param parentUuid parent uuid
696 * @param row the config data
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700697 * @return uuid, empty if no uuid is find
698 */
699 private String insertConfig(String childTableName, String childColumnName,
andreaed976a42015-10-05 14:38:25 -0700700 String parentTableName, String parentColumnName,
701 String parentUuid, Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700702 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700703 TableSchema tableSchema = dbSchema.getTableSchema(childTableName);
704
Sho SHIMIZUff18f8c2016-03-11 14:43:53 -0800705 Insert insert = new Insert(tableSchema, childTableName, row);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700706
707 ArrayList<Operation> operations = Lists.newArrayList();
708 operations.add(insert);
709
710 if (parentTableName != null && parentColumnName != null) {
711 TableSchema parentTableSchema = dbSchema
712 .getTableSchema(parentTableName);
713 ColumnSchema parentColumnSchema = parentTableSchema
714 .getColumnSchema(parentColumnName);
715
716 List<Mutation> mutations = Lists.newArrayList();
717 Mutation mutation = MutationUtil.insert(parentColumnSchema.name(),
Sho SHIMIZUff18f8c2016-03-11 14:43:53 -0800718 Uuid.uuid(childTableName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700719 mutations.add(mutation);
720
721 List<Condition> conditions = Lists.newArrayList();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700722 Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(parentUuid));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700723 conditions.add(condition);
724
725 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
726 operations.add(op);
727 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700728 if (childTableName.equalsIgnoreCase(PORT)) {
729 log.debug("Handle port insert");
730 Insert intfInsert = handlePortInsertTable(INTERFACE, row);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700731
732 if (intfInsert != null) {
733 operations.add(intfInsert);
734 }
735
736 Insert ins = (Insert) operations.get(0);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700737 ins.getRow().put("interfaces", Uuid.uuid(INTERFACE));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700738 }
739
740 List<OperationResult> results;
741 try {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700742 results = transactConfig(DATABASENAME, operations).get();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700743 return results.get(0).getUuid().value();
744 } catch (InterruptedException e) {
745 log.warn("Interrupted while waiting to get result");
746 Thread.currentThread().interrupt();
747 } catch (ExecutionException e) {
748 log.error("Exception thrown while to get result");
749 }
750
751 return null;
752 }
753
754 /**
755 * Handles port insert.
756 *
757 * @param tableName ovsdb table interface
andreaed976a42015-10-05 14:38:25 -0700758 * @param portRow row of port
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700759 * @return insert, empty if null
760 */
761 private Insert handlePortInsertTable(String tableName, Row portRow) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700762 DatabaseSchema dbSchema = schema.get(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700763
Hyunsun Moon1251e192016-06-07 16:57:05 -0700764 TableSchema portTableSchema = dbSchema.getTableSchema(PORT);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700765 ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name");
766
767 String portName = (String) portRow.getColumn(portColumnSchema.name()).data();
Hyunsun Moon1251e192016-06-07 16:57:05 -0700768 Interface inf = (Interface) TableGenerator.createTable(dbSchema, OvsdbTable.INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700769 inf.setName(portName);
770
Hyunsun Moon1251e192016-06-07 16:57:05 -0700771 TableSchema intfTableSchema = dbSchema.getTableSchema(INTERFACE);
772 return new Insert(intfTableSchema, INTERFACE, inf.getRow());
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700773 }
774
775 /**
776 * Gets tunnel name.
777 *
Hyunsun Moon1251e192016-06-07 16:57:05 -0700778 * @param tunnelType tunnel type
andreaed976a42015-10-05 14:38:25 -0700779 * @param dstIp the remote ip address
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700780 * @return tunnel name
781 */
782 private String getTunnelName(String tunnelType, IpAddress dstIp) {
783 return tunnelType + "-" + dstIp.toString();
784 }
785
786 @Override
787 public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
788 if (dbName == null) {
789 return null;
790 }
791 DatabaseSchema databaseSchema = schema.get(dbName);
792 if (databaseSchema == null) {
793 List<String> dbNames = new ArrayList<String>();
794 dbNames.add(dbName);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700795 Function<JsonNode, DatabaseSchema> rowFunction = input -> {
796 log.debug("Get ovsdb database schema {}", dbName);
797 DatabaseSchema dbSchema = FromJsonUtil.jsonNodeToDbSchema(dbName, input);
798 if (dbSchema == null) {
799 log.debug("Get ovsdb database schema error");
800 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700801 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700802 schema.put(dbName, dbSchema);
803 return dbSchema;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700804 };
805
806 ListenableFuture<JsonNode> input = getSchema(dbNames);
807 if (input != null) {
808 return Futures.transform(input, rowFunction);
809 }
810 return null;
811 } else {
812 return Futures.immediateFuture(databaseSchema);
813 }
814 }
815
816 @Override
817 public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) {
818 if (dbName == null) {
819 return null;
820 }
821 DatabaseSchema dbSchema = schema.get(dbName);
822 if (dbSchema != null) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700823 Function<JsonNode, TableUpdates> rowFunction = input -> {
824 log.debug("Get table updates");
825 TableUpdates updates = FromJsonUtil.jsonNodeToTableUpdates(input, dbSchema);
826 if (updates == null) {
827 log.debug("Get table updates error");
828 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700829 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700830 return updates;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700831 };
832 return Futures.transform(monitor(dbSchema, id), rowFunction);
833 }
834 return null;
835 }
836
837 @Override
838 public ListenableFuture<List<OperationResult>> transactConfig(String dbName,
839 List<Operation> operations) {
840 if (dbName == null) {
841 return null;
842 }
843 DatabaseSchema dbSchema = schema.get(dbName);
844 if (dbSchema != null) {
andreaed976a42015-10-05 14:38:25 -0700845 Function<List<JsonNode>, List<OperationResult>> rowFunction = (input -> {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700846 log.debug("Get ovsdb operation result");
847 List<OperationResult> result = FromJsonUtil.jsonNodeToOperationResult(input, operations);
andreaed976a42015-10-05 14:38:25 -0700848 if (result == null) {
849 log.debug("The operation result is null");
850 return null;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700851 }
andreaed976a42015-10-05 14:38:25 -0700852 return result;
853 });
Hyunsun Moon1251e192016-06-07 16:57:05 -0700854 return Futures.transform(transact(dbSchema, operations), rowFunction);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700855 }
856 return null;
857 }
858
859 @Override
860 public ListenableFuture<JsonNode> getSchema(List<String> dbnames) {
861 String id = java.util.UUID.randomUUID().toString();
862 String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames);
863
864 SettableFuture<JsonNode> sf = SettableFuture.create();
865 requestResult.put(id, sf);
866 requestMethod.put(id, "getSchema");
867
868 channel.writeAndFlush(getSchemaString);
869 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700870 }
871
872 @Override
873 public ListenableFuture<List<String>> echo() {
874 String id = java.util.UUID.randomUUID().toString();
875 String echoString = JsonRpcWriterUtil.echoStr(id);
876
877 SettableFuture<List<String>> sf = SettableFuture.create();
878 requestResult.put(id, sf);
879 requestMethod.put(id, "echo");
880
881 channel.writeAndFlush(echoString);
882 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700883 }
884
885 @Override
886 public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema,
887 String monitorId) {
888 String id = java.util.UUID.randomUUID().toString();
889 String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId,
890 dbSchema);
891
892 SettableFuture<JsonNode> sf = SettableFuture.create();
893 requestResult.put(id, sf);
894 requestMethod.put(id, "monitor");
895
896 channel.writeAndFlush(monitorString);
897 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700898 }
899
900 @Override
901 public ListenableFuture<List<String>> listDbs() {
902 String id = java.util.UUID.randomUUID().toString();
903 String listDbsString = JsonRpcWriterUtil.listDbsStr(id);
904
905 SettableFuture<List<String>> sf = SettableFuture.create();
906 requestResult.put(id, sf);
907 requestMethod.put(id, "listDbs");
908
909 channel.writeAndFlush(listDbsString);
910 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700911 }
912
913 @Override
914 public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema,
915 List<Operation> operations) {
916 String id = java.util.UUID.randomUUID().toString();
917 String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema,
918 operations);
919
920 SettableFuture<List<JsonNode>> sf = SettableFuture.create();
921 requestResult.put(id, sf);
922 requestMethod.put(id, "transact");
923
924 channel.writeAndFlush(transactString);
925 return sf;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700926 }
927
andreaed976a42015-10-05 14:38:25 -0700928 @SuppressWarnings({"rawtypes", "unchecked"})
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700929 @Override
930 public void processResult(JsonNode response) {
931 log.debug("Handle result");
932 String requestId = response.get("id").asText();
933 SettableFuture sf = requestResult.get(requestId);
934 if (sf == null) {
935 log.debug("No such future to process");
936 return;
937 }
938 String methodName = requestMethod.get(requestId);
Hyunsun Moon1251e192016-06-07 16:57:05 -0700939 sf.set(FromJsonUtil.jsonResultParser(response, methodName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700940 }
941
942 @Override
943 public void processRequest(JsonNode requestJson) {
944 log.debug("Handle request");
945 if (requestJson.get("method").asText().equalsIgnoreCase("echo")) {
946 log.debug("handle echo request");
947
948 String replyString = FromJsonUtil.getEchoRequestStr(requestJson);
949 channel.writeAndFlush(replyString);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700950 } else {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700951 FromJsonUtil.jsonCallbackRequestParser(requestJson, monitorCallBack);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700952 }
953 }
954
955 @Override
956 public void setCallback(Callback monitorCallback) {
957 this.monitorCallBack = monitorCallback;
958 }
959
960 @Override
961 public Set<OvsdbTunnel> getTunnels() {
962 return ovsdbTunnels;
963 }
964
965 @Override
966 public Set<OvsdbBridge> getBridges() {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700967 Set<OvsdbBridge> ovsdbBridges = new HashSet<>();
968 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700969 if (tableStore == null) {
970 return null;
971 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700972 OvsdbRowStore rowStore = tableStore.getRows(BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700973 if (rowStore == null) {
974 return null;
975 }
976 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
977 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -0700978 Row row = getRow(DATABASENAME, BRIDGE, uuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -0700979 OvsdbBridge ovsdbBridge = getOvsdbBridge(row);
980 if (ovsdbBridge != null) {
981 ovsdbBridges.add(ovsdbBridge);
982 }
983 }
984 return ovsdbBridges;
985 }
986
987 @Override
andreaed976a42015-10-05 14:38:25 -0700988 public Set<ControllerInfo> getControllers(DeviceId openflowDeviceId) {
Jonathan Hart51539b82015-10-29 09:53:04 -0700989 Uuid bridgeUuid = getBridgeUuid(openflowDeviceId);
andreaed976a42015-10-05 14:38:25 -0700990 if (bridgeUuid == null) {
991 log.warn("bad bridge Uuid");
992 return null;
993 }
994 List<Controller> controllers = getControllers(bridgeUuid);
995 if (controllers == null) {
996 log.warn("bad list of controllers");
997 return null;
998 }
Hyunsun Moon1251e192016-06-07 16:57:05 -0700999 return controllers.stream().map(controller -> new ControllerInfo(
1000 (String) controller.getTargetColumn()
1001 .data())).collect(Collectors.toSet());
andreaed976a42015-10-05 14:38:25 -07001002 }
1003
Jonathan Hart51539b82015-10-29 09:53:04 -07001004 private List<Controller> getControllers(Uuid bridgeUuid) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001005 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -07001006 if (dbSchema == null) {
1007 return null;
1008 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001009 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -07001010 if (rowStore == null) {
1011 log.debug("There is no bridge table");
1012 return null;
1013 }
1014
1015 Row bridgeRow = rowStore.getRow(bridgeUuid.value());
1016 Bridge bridge = (Bridge) TableGenerator.
1017 getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
1018
1019 //FIXME remove log
1020 log.warn("type of controller column", bridge.getControllerColumn()
1021 .data().getClass());
Jonathan Hart51539b82015-10-29 09:53:04 -07001022 Set<Uuid> controllerUuids = (Set<Uuid>) ((OvsdbSet) bridge
andreaed976a42015-10-05 14:38:25 -07001023 .getControllerColumn().data()).set();
andreaed976a42015-10-05 14:38:25 -07001024
Hyunsun Moon1251e192016-06-07 16:57:05 -07001025 OvsdbRowStore controllerRowStore = getRowStore(DATABASENAME, CONTROLLER);
andreaed976a42015-10-05 14:38:25 -07001026 if (controllerRowStore == null) {
1027 log.debug("There is no controller table");
1028 return null;
1029 }
1030
1031 List<Controller> ovsdbControllers = new ArrayList<>();
1032 ConcurrentMap<String, Row> controllerTableRows = controllerRowStore.getRowStore();
1033 controllerTableRows.forEach((key, row) -> {
Jonathan Hart51539b82015-10-29 09:53:04 -07001034 if (!controllerUuids.contains(Uuid.uuid(key))) {
andreaed976a42015-10-05 14:38:25 -07001035 return;
1036 }
1037 Controller controller = (Controller) TableGenerator
1038 .getTable(dbSchema, row, OvsdbTable.CONTROLLER);
1039 ovsdbControllers.add(controller);
1040 });
1041 return ovsdbControllers;
1042 }
1043
1044
Jonathan Hart51539b82015-10-29 09:53:04 -07001045 private Uuid getBridgeUuid(DeviceId openflowDeviceId) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001046 DatabaseSchema dbSchema = schema.get(DATABASENAME);
andreaed976a42015-10-05 14:38:25 -07001047 if (dbSchema == null) {
1048 return null;
1049 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001050 OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
andreaed976a42015-10-05 14:38:25 -07001051 if (rowStore == null) {
1052 log.debug("There is no bridge table");
1053 return null;
1054 }
1055
1056 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
Jonathan Hart51539b82015-10-29 09:53:04 -07001057 final AtomicReference<Uuid> uuid = new AtomicReference<>();
andreaed976a42015-10-05 14:38:25 -07001058 for (Map.Entry<String, Row> entry : bridgeTableRows.entrySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001059 Bridge bridge = (Bridge) TableGenerator.getTable(
1060 dbSchema,
1061 entry.getValue(),
1062 OvsdbTable.BRIDGE);
1063
1064 if (matchesDpid(bridge, openflowDeviceId)) {
Jonathan Hart51539b82015-10-29 09:53:04 -07001065 uuid.set(Uuid.uuid(entry.getKey()));
andreaed976a42015-10-05 14:38:25 -07001066 break;
1067 }
1068 }
1069 if (uuid.get() == null) {
1070 log.debug("There is no bridge for {}", openflowDeviceId);
1071 }
1072 return uuid.get();
andreaed976a42015-10-05 14:38:25 -07001073 }
1074
1075 private static boolean matchesDpid(Bridge b, DeviceId deviceId) {
1076 String ofDpid = deviceId.toString().replace("of:", "");
1077 Set ofDeviceIds = ((OvsdbSet) b.getDatapathIdColumn().data()).set();
1078 //TODO Set<String>
1079 return ofDeviceIds.contains(ofDpid);
1080 }
1081
1082 @Override
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001083 public Set<OvsdbPort> getPorts() {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001084 Set<OvsdbPort> ovsdbPorts = new HashSet<>();
1085 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001086 if (tableStore == null) {
1087 return null;
1088 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001089 OvsdbRowStore rowStore = tableStore.getRows(INTERFACE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001090 if (rowStore == null) {
1091 return null;
1092 }
1093 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1094 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001095 Row row = getRow(DATABASENAME, INTERFACE, uuid);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001096 OvsdbPort ovsdbPort = getOvsdbPort(row);
1097 if (ovsdbPort != null) {
1098 ovsdbPorts.add(ovsdbPort);
1099 }
1100 }
1101 return ovsdbPorts;
1102 }
1103
1104 @Override
1105 public DatabaseSchema getDatabaseSchema(String dbName) {
1106 return schema.get(dbName);
1107 }
1108
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001109 private OvsdbPort getOvsdbPort(Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001110 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001111 Interface intf = (Interface) TableGenerator
1112 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1113 if (intf == null) {
1114 return null;
1115 }
1116 long ofPort = getOfPort(intf);
1117 String portName = intf.getName();
1118 if ((ofPort < 0) || (portName == null)) {
1119 return null;
1120 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001121 return new OvsdbPort(new OvsdbPortNumber(ofPort), new OvsdbPortName(portName));
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001122 }
1123
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001124 private OvsdbBridge getOvsdbBridge(Row row) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001125 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
1126 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, row, OvsdbTable.BRIDGE);
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001127 if (bridge == null) {
1128 return null;
1129 }
1130
1131 OvsdbSet datapathIdSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
1132 @SuppressWarnings("unchecked")
1133 Set<String> datapathIds = datapathIdSet.set();
1134 if (datapathIds == null || datapathIds.size() == 0) {
1135 return null;
1136 }
1137 String datapathId = (String) datapathIds.toArray()[0];
1138 String bridgeName = bridge.getName();
1139 if ((datapathId == null) || (bridgeName == null)) {
1140 return null;
1141 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001142 return OvsdbBridge.builder().name(bridgeName).datapathId(datapathId).build();
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001143 }
1144
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001145 private long getOfPort(Interface intf) {
1146 OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
1147 @SuppressWarnings("unchecked")
1148 Set<Integer> ofPorts = ofPortSet.set();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001149 if (ofPorts == null || ofPorts.size() <= 0) {
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001150 log.debug("The ofport is null in {}", intf.getName());
1151 return -1;
1152 }
1153 // return (long) ofPorts.toArray()[0];
1154 Iterator<Integer> it = ofPorts.iterator();
1155 return Long.parseLong(it.next().toString());
1156 }
CNluciusa66c3972015-09-06 20:31:29 +08001157
1158 @Override
1159 public Set<OvsdbPort> getLocalPorts(Iterable<String> ifaceids) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001160 Set<OvsdbPort> ovsdbPorts = new HashSet<>();
1161 OvsdbTableStore tableStore = getTableStore(DATABASENAME);
CNluciusa66c3972015-09-06 20:31:29 +08001162 if (tableStore == null) {
1163 return null;
1164 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001165 OvsdbRowStore rowStore = tableStore.getRows(INTERFACE);
CNluciusa66c3972015-09-06 20:31:29 +08001166 if (rowStore == null) {
1167 return null;
1168 }
1169 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1170 for (String uuid : rows.keySet()) {
Hyunsun Moon1251e192016-06-07 16:57:05 -07001171 Row row = getRow(DATABASENAME, INTERFACE, uuid);
1172 DatabaseSchema dbSchema = getDatabaseSchema(DATABASENAME);
CNluciusa66c3972015-09-06 20:31:29 +08001173 Interface intf = (Interface) TableGenerator
1174 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1175 if (intf == null || getIfaceid(intf) == null) {
1176 continue;
1177 }
1178 String portName = intf.getName();
Hyunsun Moon1251e192016-06-07 16:57:05 -07001179 if (portName == null) {
1180 continue;
1181 }
CNluciusa66c3972015-09-06 20:31:29 +08001182 Set<String> ifaceidSet = Sets.newHashSet(ifaceids);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001183 if (portName.startsWith(TYPEVXLAN) || !ifaceidSet.contains(getIfaceid(intf))) {
CNluciusa66c3972015-09-06 20:31:29 +08001184 continue;
1185 }
1186 long ofPort = getOfPort(intf);
Hyunsun Moon1251e192016-06-07 16:57:05 -07001187 if (ofPort < 0) {
CNluciusa66c3972015-09-06 20:31:29 +08001188 continue;
1189 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001190 ovsdbPorts.add(new OvsdbPort(new OvsdbPortNumber(ofPort),
1191 new OvsdbPortName(portName)));
CNluciusa66c3972015-09-06 20:31:29 +08001192 }
1193 return ovsdbPorts;
1194 }
1195
1196 private String getIfaceid(Interface intf) {
1197 OvsdbMap ovsdbMap = (OvsdbMap) intf.getExternalIdsColumn().data();
1198 @SuppressWarnings("unchecked")
1199 Map<String, String> externalIds = ovsdbMap.map();
1200 if (externalIds.isEmpty()) {
1201 log.warn("The external_ids is null");
1202 return null;
1203 }
Hyunsun Moon1251e192016-06-07 16:57:05 -07001204 String ifaceid = externalIds.get(EXTERNAL_ID_INTERFACE_ID);
CNluciusa66c3972015-09-06 20:31:29 +08001205 if (ifaceid == null) {
1206 log.warn("The ifaceid is null");
1207 return null;
1208 }
1209 return ifaceid;
1210 }
Hyunsun Moon5fb20a52015-09-25 17:02:33 -07001211
1212 @Override
1213 public void disconnect() {
1214 channel.disconnect();
1215 this.agent.removeConnectedNode(nodeId);
1216 }
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001217}