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