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