blob: a271f93e337d3e31f6ea8fcc827e591e35145110 [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
18import io.netty.channel.Channel;
19
20import java.net.InetSocketAddress;
21import java.util.ArrayList;
22import java.util.HashSet;
23import java.util.Iterator;
24import java.util.List;
25import java.util.Map;
26import java.util.Set;
27import java.util.concurrent.ConcurrentMap;
28import java.util.concurrent.ExecutionException;
29
30import org.onlab.packet.IpAddress;
31import 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;
49import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
50import org.onosproject.ovsdb.rfc.notation.Row;
51import org.onosproject.ovsdb.rfc.notation.UUID;
52import org.onosproject.ovsdb.rfc.operations.Delete;
53import org.onosproject.ovsdb.rfc.operations.Insert;
54import org.onosproject.ovsdb.rfc.operations.Mutate;
55import org.onosproject.ovsdb.rfc.operations.Operation;
56import org.onosproject.ovsdb.rfc.operations.Update;
57import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
58import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
59import org.onosproject.ovsdb.rfc.schema.TableSchema;
60import org.onosproject.ovsdb.rfc.table.Bridge;
61import org.onosproject.ovsdb.rfc.table.Controller;
62import org.onosproject.ovsdb.rfc.table.Interface;
63import org.onosproject.ovsdb.rfc.table.OvsdbTable;
64import org.onosproject.ovsdb.rfc.table.Port;
65import org.onosproject.ovsdb.rfc.table.TableGenerator;
66import org.onosproject.ovsdb.rfc.utils.ConditionUtil;
67import org.onosproject.ovsdb.rfc.utils.FromJsonUtil;
68import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil;
69import org.onosproject.ovsdb.rfc.utils.MutationUtil;
70import org.slf4j.Logger;
71import org.slf4j.LoggerFactory;
72
73import com.fasterxml.jackson.databind.JsonNode;
74import com.google.common.base.Function;
75import com.google.common.collect.Lists;
76import com.google.common.collect.Maps;
77import com.google.common.util.concurrent.Futures;
78import com.google.common.util.concurrent.ListenableFuture;
79import com.google.common.util.concurrent.SettableFuture;
80
81/**
82 * An representation of an ovsdb client.
83 */
84public class DefaultOvsdbClient
85 implements OvsdbProviderService, OvsdbClientService {
86
87 private final Logger log = LoggerFactory
88 .getLogger(DefaultOvsdbClient.class);
89
90 private Channel channel;
91
92 private OvsdbAgent agent;
93 private boolean connected;
94 private OvsdbNodeId nodeId;
95 private Callback monitorCallBack;
96
97 private OvsdbStore ovsdbStore = new OvsdbStore();
98
99 private final Map<String, String> requestMethod = Maps.newHashMap();
100 private final Map<String, SettableFuture<? extends Object>> requestResult = Maps
101 .newHashMap();
102
103 private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
104 private final Set<OvsdbTunnel> ovsdbTunnels = new HashSet<OvsdbTunnel>();
105
106 /**
107 * Creates an OvsdbClient.
108 *
109 * @param nodeId ovsdb node id
110 */
111 public DefaultOvsdbClient(OvsdbNodeId nodeId) {
112 this.nodeId = nodeId;
113 }
114
115 @Override
116 public OvsdbNodeId nodeId() {
117 return nodeId;
118 }
119
120 @Override
121 public void setAgent(OvsdbAgent agent) {
122 if (this.agent == null) {
123 this.agent = agent;
124 }
125 }
126
127 @Override
128 public void setChannel(Channel channel) {
129 this.channel = channel;
130 }
131
132 @Override
133 public void setConnection(boolean connected) {
134 this.connected = connected;
135 }
136
137 @Override
138 public boolean isConnected() {
139 return this.connected;
140 }
141
142 @Override
143 public void nodeAdded() {
144 this.agent.addConnectedNode(nodeId, this);
145 }
146
147 @Override
148 public void nodeRemoved() {
149 this.agent.removeConnectedNode(nodeId);
150 channel.disconnect();
151 }
152
153 /**
154 * Gets the ovsdb table store.
155 *
156 * @param dbName the ovsdb database name
157 * @return ovsTableStore, empty if table store is find
158 */
159 private OvsdbTableStore getTableStore(String dbName) {
160 if (ovsdbStore == null) {
161 return null;
162 }
163 return ovsdbStore.getOvsdbTableStore(dbName);
164 }
165
166 /**
167 * Gets the ovsdb row store.
168 *
169 * @param dbName the ovsdb database name
170 * @param tableName the ovsdb table name
171 *
172 * @return ovsRowStore, empty if row store is find
173 */
174 private OvsdbRowStore getRowStore(String dbName, String tableName) {
175 OvsdbTableStore tableStore = getTableStore(dbName);
176 if (tableStore == null) {
177 return null;
178 }
179 return tableStore.getRows(tableName);
180 }
181
182 /**
183 * Gets the ovsdb row.
184 *
185 * @param dbName the ovsdb database name
186 * @param tableName the ovsdb table name
187 * @param uuid the key of the row
188 * @return row, empty if row is find
189 */
190 @Override
191 public Row getRow(String dbName, String tableName, String uuid) {
192 OvsdbTableStore tableStore = getTableStore(dbName);
193 if (tableStore == null) {
194 return null;
195 }
196 OvsdbRowStore rowStore = tableStore.getRows(tableName);
197 if (rowStore == null) {
198 return null;
199 }
200 return rowStore.getRow(uuid);
201 }
202
203 @Override
204 public void removeRow(String dbName, String tableName, String uuid) {
205 OvsdbTableStore tableStore = getTableStore(dbName);
206 if (tableStore == null) {
207 return;
208 }
209 OvsdbRowStore rowStore = tableStore.getRows(tableName);
210 if (rowStore == null) {
211 return;
212 }
213 rowStore.deleteRow(uuid);
214 }
215
216 @Override
217 public void updateOvsdbStore(String dbName, String tableName, String uuid,
218 Row row) {
219 OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName);
220 if (tableStore == null) {
221 tableStore = new OvsdbTableStore();
222 }
223 OvsdbRowStore rowStore = tableStore.getRows(tableName);
224 if (rowStore == null) {
225 rowStore = new OvsdbRowStore();
226 }
227 rowStore.insertRow(uuid, row);
228 tableStore.createOrUpdateTable(tableName, rowStore);
229 ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
230 }
231
232 @Override
233 public String getPortUuid(String portName, String bridgeUuid) {
234 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
235
236 Row bridgeRow = getRow(OvsdbConstant.DATABASENAME,
237 OvsdbConstant.BRIDGE, bridgeUuid);
238
239 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow,
240 OvsdbTable.BRIDGE);
241 if (bridge != null) {
242 OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
243 @SuppressWarnings("unchecked")
244 Set<UUID> ports = setPorts.set();
245 if (ports == null || ports.size() == 0) {
246 log.warn("The port uuid is null");
247 return null;
248 }
249
250 for (UUID uuid : ports) {
251 Row portRow = getRow(OvsdbConstant.DATABASENAME,
252 OvsdbConstant.PORT, uuid.value());
253 Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
254 OvsdbTable.PORT);
255 if (port != null && portName.equalsIgnoreCase(port.getName())) {
256 return uuid.value();
257 }
258 }
259
260 }
261 return null;
262 }
263
264 @Override
265 public String getInterfaceUuid(String portUuid, String portName) {
266 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
267
268 Row portRow = getRow(OvsdbConstant.DATABASENAME, OvsdbConstant.PORT,
269 portUuid);
270 Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
271 OvsdbTable.PORT);
272
273 if (port != null) {
274 OvsdbSet setInterfaces = (OvsdbSet) port.getInterfacesColumn().data();
275 @SuppressWarnings("unchecked")
276 Set<UUID> interfaces = setInterfaces.set();
277
278 if (interfaces == null || interfaces.size() == 0) {
279 log.warn("The interface uuid is null");
280 return null;
281 }
282
283 for (UUID uuid : interfaces) {
284 Row intfRow = getRow(OvsdbConstant.DATABASENAME,
285 OvsdbConstant.INTERFACE, uuid.value());
286 Interface intf = (Interface) TableGenerator
287 .getTable(dbSchema, intfRow, OvsdbTable.INTERFACE);
288 if (intf != null && portName.equalsIgnoreCase(intf.getName())) {
289 return uuid.value();
290 }
291 }
292
293 }
294
295 return null;
296 }
297
298 @Override
299 public String getBridgeUuid(String bridgeName) {
300 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
301
302 OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
303 OvsdbConstant.BRIDGE);
304 if (rowStore == null) {
305 log.debug("The bridge uuid is null");
306 return null;
307 }
308
309 ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore();
310 if (bridgeTableRows == null) {
311 log.debug("The bridge uuid is null");
312 return null;
313 }
314
315 for (String uuid : bridgeTableRows.keySet()) {
316 Bridge bridge = (Bridge) TableGenerator
317 .getTable(dbSchema, bridgeTableRows.get(uuid),
318 OvsdbTable.BRIDGE);
319
320 if (bridge.getName().equals(bridgeName)) {
321 return uuid;
322 }
323
324 }
325 return null;
326 }
327
328 @Override
329 public String getControllerUuid(String controllerName,
330 String controllerTarget) {
331 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
332 OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
333 OvsdbConstant.CONTROLLER);
334 if (rowStore == null) {
335 log.debug("The controller uuid is null");
336 return null;
337 }
338
339 ConcurrentMap<String, Row> controllerTableRows = rowStore.getRowStore();
340 if (controllerTableRows != null) {
341 for (String uuid : controllerTableRows.keySet()) {
342
343 Controller controller = (Controller) TableGenerator
344 .getTable(dbSchema, controllerTableRows.get(uuid),
345 OvsdbTable.CONTROLLER);
346 String target = (String) controller.getTargetColumn().data();
347 if (target.equalsIgnoreCase(controllerTarget)) {
348 return uuid;
349 }
350
351 }
352 }
353 return null;
354 }
355
356 @Override
357 public String getOvsUuid(String dbName) {
358 OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME,
359 OvsdbConstant.DATABASENAME);
360 if (rowStore == null) {
361 log.debug("The bridge uuid is null");
362 return null;
363 }
364 ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore();
365 if (ovsTableRows != null) {
366 for (String uuid : ovsTableRows.keySet()) {
367 Row row = ovsTableRows.get(uuid);
368 String tableName = row.tableName();
369 if (tableName.equals(dbName)) {
370 return uuid;
371 }
372 }
373 }
374 return null;
375 }
376
377 @Override
378 public void createPort(String bridgeName, String portName) {
379 String bridgeUuid = getBridgeUuid(bridgeName);
380 if (bridgeUuid == null) {
381 log.error("Can't find bridge {} in {}", bridgeName,
382 nodeId.getIpAddress());
383 return;
384 }
385
386 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
387 String portUuid = getPortUuid(portName, bridgeUuid);
388
389 Port port = (Port) TableGenerator
390 .createTable(dbSchema, OvsdbTable.PORT);
391
392 port.setName(portName);
393 if (portUuid == null) {
394 insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE,
395 "ports", bridgeUuid, port.getRow());
396 } else {
397 updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow());
398 }
399
400 return;
401 }
402
403 @Override
404 public void dropPort(String bridgeName, String portName) {
405 String bridgeUuid = getBridgeUuid(bridgeName);
406 if (bridgeUuid == null) {
407 log.error("Could not find Bridge {} in {}", bridgeName, nodeId);
408 return;
409 }
410
411 String portUuid = getPortUuid(portName, bridgeUuid);
412 if (portUuid != null) {
413 log.info("Port {} delete", portName);
414 deleteConfig(OvsdbConstant.PORT, "_uuid", portUuid,
415 OvsdbConstant.BRIDGE, "ports");
416 }
417 }
418
419 @Override
420 public void createBridge(String bridgeName) {
421 log.debug("create bridge {}", bridgeName);
422
423 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
424 if (dbSchema == null) {
425 log.warn("The schema is null");
426 return;
427 }
428
429 Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema,
430 OvsdbTable.BRIDGE);
431 if (bridge == null) {
432 log.debug("Can not create bridge");
433 return;
434 }
435
436 Set<String> failModes = new HashSet<>();
437 failModes.add("secure");
438 bridge.setFailMode(failModes);
439
440 Set<String> protocols = new HashSet<>();
441 protocols.add(OvsdbConstant.OPENFLOW13);
442 bridge.setProtocols(protocols);
443
444 String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME);
445 if (ovsUuid == null) {
446 log.warn("The Open_vSwitch is null");
447 return;
448 }
449
450 String bridgeUuid = getBridgeUuid(bridgeName);
451 if (bridgeUuid == null) {
452 log.debug("Create a new bridge");
453
454 bridge.setName(bridgeName);
455 bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
456 OvsdbConstant.DATABASENAME, "bridges",
457 ovsUuid, bridge.getRow());
458
459 if (bridgeUuid != null) {
460 Port port = (Port) TableGenerator.createTable(dbSchema,
461 OvsdbTable.PORT);
462 if (port != null) {
463 log.debug("the port is not null");
464 port.setName(bridgeName);
465
466 insertConfig(OvsdbConstant.PORT, "_uuid", "Bridge", "ports", bridgeUuid,
467 port.getRow());
468 }
469 }
470
471 } else {
472 log.info("Update a bridge");
473 updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid, bridge.getRow());
474 }
475
476 setController(bridgeUuid);
477 log.info("Create bridge success");
478 }
479
480 /**
481 * Sets the Controller.
482 *
483 * @param bridgeUuid bridge uuid
484 */
485 private void setController(String bridgeUuid) {
486 String controllerUuid = null;
487 String iPAddress = IpAddress.valueOf(((InetSocketAddress) channel
488 .localAddress())
489 .getAddress()
490 .getHostAddress())
491 .toString();
492
493 String target = "tcp:" + iPAddress + ":" + OvsdbConstant.OFPORT;
494 log.debug("controller IP {}: port {}", iPAddress, OvsdbConstant.OFPORT);
495
496 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
497 Controller controller = (Controller) TableGenerator
498 .createTable(dbSchema, OvsdbTable.CONTROLLER);
499
500 if (controller != null) {
501 controller.setTarget(target);
502 controllerUuid = getControllerUuid(OvsdbConstant.CONTROLLER, target);
503 if (controllerUuid == null) {
504
505 insertConfig(OvsdbConstant.CONTROLLER, "_uuid",
506 OvsdbConstant.BRIDGE, "controller", bridgeUuid,
507 controller.getRow());
508
509 } else {
510
511 Bridge bridge = (Bridge) TableGenerator
512 .createTable(dbSchema, OvsdbTable.BRIDGE);
513 Set<UUID> controllerUuids = new HashSet<>();
514 controllerUuids.add(UUID.uuid(controllerUuid));
515 bridge.setController(controllerUuids);
516 updateConfig(OvsdbConstant.CONTROLLER, "_uuid", bridgeUuid, bridge.getRow());
517
518 }
519 }
520
521 }
522
523 @Override
524 public void dropBridge(String bridgeName) {
525 String bridgeUUID = getBridgeUuid(bridgeName);
526 if (bridgeUUID == null) {
527 log.warn("Could not find bridge in node", nodeId.getIpAddress());
528 return;
529 }
530 deleteConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUUID,
531 OvsdbConstant.DATABASENAME, "bridges");
532 }
533
534 @Override
535 public void createTunnel(IpAddress srcIp, IpAddress dstIp) {
536 String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
537 if (bridgeUuid == null) {
538 log.warn("Could not find bridge {} and Could not create tunnel. ",
539 OvsdbConstant.INTEGRATION_BRIDGE);
540 return;
541 }
542
543 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
544 String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
545 String portUuid = getPortUuid(portName, bridgeUuid);
546
547 Port port = (Port) TableGenerator
548 .createTable(dbSchema, OvsdbTable.PORT);
549 if (port != null) {
550 port.setName(portName);
551 }
552
553 if (portUuid == null) {
554 portUuid = insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE,
555 "ports", bridgeUuid, port.getRow());
556 } else {
557 updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow());
558 }
559
560 // When a tunnel is created, A row is inserted into port table and
561 // interface table of the ovsdb node.
562 // and the following step is to get the interface uuid from local store
563 // in controller node.
564 // but it need spend some time synchronising data between node and
565 // controller.
566 // so loop to judge if interfaceUUid is null is necessary.
567 String interfaceUuid = null;
568 for (int i = 0; i < 10; i++) {
569 interfaceUuid = getInterfaceUuid(portUuid, portName);
570 if (interfaceUuid == null) {
571 try {
572 Thread.sleep(500);
573 } catch (InterruptedException e) {
574 log.warn("Interrupted while waiting to get interfaceUuid");
575 Thread.currentThread().interrupt();
576 }
577 } else {
578 break;
579 }
580 }
581
582 if (interfaceUuid != null) {
583
584 Interface tunInterface = (Interface) TableGenerator
585 .createTable(dbSchema, OvsdbTable.INTERFACE);
586
587 if (tunInterface != null) {
588
589 tunInterface.setType(OvsdbConstant.TYPEVXLAN);
590 Map<String, String> options = Maps.newHashMap();
591 options.put("key", "flow");
592 options.put("local_ip", srcIp.toString());
593 options.put("remote_ip", dstIp.toString());
594 tunInterface.setOptions(options);
595 updateConfig(OvsdbConstant.INTERFACE, "_uuid", interfaceUuid,
596 tunInterface.getRow());
597 log.info("Tunnel added success", tunInterface);
598
599 }
600 }
601
602 return;
603 }
604
605 @Override
606 public void dropTunnel(IpAddress srcIp, IpAddress dstIp) {
607 String bridgeName = OvsdbConstant.INTEGRATION_BRIDGE;
608 String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp);
609 String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE);
610 if (bridgeUuid == null) {
611 log.warn("Could not find bridge {} in {}", bridgeName,
612 nodeId.getIpAddress());
613 return;
614 }
615
616 String portUUID = getPortUuid(portName, bridgeUuid);
617 if (portUUID != null) {
618 log.info("Delete tunnel");
619 deleteConfig(OvsdbConstant.PORT, "_uuid", portUUID,
620 OvsdbConstant.BRIDGE, "ports");
621 }
622
623 return;
624 }
625
626 /**
627 * Delete transact config.
628 *
629 * @param childTableName child table name
630 * @param childColumnName child column name
631 * @param childUuid child row uuid
632 * @param parentTableName parent table name
633 * @param parentColumnName parent column
634 *
635 */
636 private void deleteConfig(String childTableName, String childColumnName,
637 String childUuid, String parentTableName,
638 String parentColumnName) {
639 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
640 TableSchema childTableSchema = dbSchema.getTableSchema(childTableName);
641
642 ArrayList<Operation> operations = Lists.newArrayList();
643 if (parentTableName != null && parentColumnName != null) {
644 TableSchema parentTableSchema = dbSchema
645 .getTableSchema(parentTableName);
646 ColumnSchema parentColumnSchema = parentTableSchema
647 .getColumnSchema(parentColumnName);
648 List<Mutation> mutations = Lists.newArrayList();
649 Mutation mutation = MutationUtil.delete(parentColumnSchema.name(),
650 UUID.uuid(childUuid));
651 mutations.add(mutation);
652 List<Condition> conditions = Lists.newArrayList();
653 Condition condition = ConditionUtil.includes(parentColumnName,
654 UUID.uuid(childUuid));
655 conditions.add(condition);
656 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
657 operations.add(op);
658 }
659
660 List<Condition> conditions = Lists.newArrayList();
661 Condition condition = ConditionUtil.equals(childColumnName, UUID.uuid(childUuid));
662 conditions.add(condition);
663 Delete del = new Delete(childTableSchema, conditions);
664 operations.add(del);
665 transactConfig(OvsdbConstant.DATABASENAME, operations);
666
667 return;
668 }
669
670 /**
671 * Update transact config.
672 *
673 * @param tableName table name
674 * @param columnName column name
675 * @param uuid uuid
676 * @param row the config data
677 *
678 */
679 private void updateConfig(String tableName, String columnName, String uuid,
680 Row row) {
681 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
682 TableSchema tableSchema = dbSchema.getTableSchema(tableName);
683
684 List<Condition> conditions = Lists.newArrayList();
685 Condition condition = ConditionUtil.equals(columnName, UUID.uuid(uuid));
686 conditions.add(condition);
687
688 Update update = new Update(tableSchema, row, conditions);
689
690 ArrayList<Operation> operations = Lists.newArrayList();
691 operations.add(update);
692
693 transactConfig(OvsdbConstant.DATABASENAME, operations);
694 }
695
696 /**
697 * Insert transact config.
698 *
699 * @param childTableName child table name
700 * @param childColumnName child column name
701 * @param parentTableName parent table name
702 * @param parentColumnName parent column
703 * @param parentUuid parent uuid
704 * @param row the config data
705 *
706 * @return uuid, empty if no uuid is find
707 */
708 private String insertConfig(String childTableName, String childColumnName,
709 String parentTableName, String parentColumnName,
710 String parentUuid, Row row) {
711 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
712 TableSchema tableSchema = dbSchema.getTableSchema(childTableName);
713
714 String namedUuid = childTableName;
715 Insert insert = new Insert(tableSchema, namedUuid, row);
716
717 ArrayList<Operation> operations = Lists.newArrayList();
718 operations.add(insert);
719
720 if (parentTableName != null && parentColumnName != null) {
721 TableSchema parentTableSchema = dbSchema
722 .getTableSchema(parentTableName);
723 ColumnSchema parentColumnSchema = parentTableSchema
724 .getColumnSchema(parentColumnName);
725
726 List<Mutation> mutations = Lists.newArrayList();
727 Mutation mutation = MutationUtil.insert(parentColumnSchema.name(),
728 UUID.uuid(namedUuid));
729 mutations.add(mutation);
730
731 List<Condition> conditions = Lists.newArrayList();
732 Condition condition = ConditionUtil.equals("_uuid",
733 UUID.uuid(parentUuid));
734 conditions.add(condition);
735
736 Mutate op = new Mutate(parentTableSchema, conditions, mutations);
737 operations.add(op);
738 }
739 if (childTableName.equalsIgnoreCase(OvsdbConstant.PORT)) {
740 log.info("Handle port insert");
741 Insert intfInsert = handlePortInsertTable(OvsdbConstant.INTERFACE,
742 row);
743
744 if (intfInsert != null) {
745 operations.add(intfInsert);
746 }
747
748 Insert ins = (Insert) operations.get(0);
749 ins.getRow().put("interfaces",
750 UUID.uuid(OvsdbConstant.INTERFACE));
751 }
752
753 List<OperationResult> results;
754 try {
755 results = transactConfig(OvsdbConstant.DATABASENAME, operations)
756 .get();
757
758 return results.get(0).getUuid().value();
759 } catch (InterruptedException e) {
760 log.warn("Interrupted while waiting to get result");
761 Thread.currentThread().interrupt();
762 } catch (ExecutionException e) {
763 log.error("Exception thrown while to get result");
764 }
765
766 return null;
767 }
768
769 /**
770 * Handles port insert.
771 *
772 * @param tableName ovsdb table interface
773 * @param portRow row of port
774 *
775 * @return insert, empty if null
776 */
777 private Insert handlePortInsertTable(String tableName, Row portRow) {
778 DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME);
779
780 TableSchema portTableSchema = dbSchema
781 .getTableSchema(OvsdbConstant.PORT);
782 ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name");
783
784 String portName = (String) portRow.getColumn(portColumnSchema.name()).data();
785
786 Interface inf = (Interface) TableGenerator
787 .createTable(dbSchema, OvsdbTable.INTERFACE);
788
789 inf.setName(portName);
790
791 TableSchema intfTableSchema = dbSchema
792 .getTableSchema(OvsdbConstant.INTERFACE);
793 Insert insert = new Insert(intfTableSchema, OvsdbConstant.INTERFACE,
794 inf.getRow());
795 return insert;
796 }
797
798 /**
799 * Gets tunnel name.
800 *
801 * @param tunnelType
802 * @param dstIp the remote ip address
803 *
804 * @return tunnel name
805 */
806 private String getTunnelName(String tunnelType, IpAddress dstIp) {
807 return tunnelType + "-" + dstIp.toString();
808 }
809
810 @Override
811 public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) {
812 if (dbName == null) {
813 return null;
814 }
815 DatabaseSchema databaseSchema = schema.get(dbName);
816 if (databaseSchema == null) {
817 List<String> dbNames = new ArrayList<String>();
818 dbNames.add(dbName);
819 Function<JsonNode, DatabaseSchema> rowFunction = new Function<JsonNode, DatabaseSchema>() {
820 @Override
821 public DatabaseSchema apply(JsonNode input) {
822 log.info("Get ovsdb database schema", dbName);
823 DatabaseSchema dbSchema = FromJsonUtil
824 .jsonNodeToDbSchema(dbName, input);
825 if (dbSchema == null) {
826 log.debug("Get ovsdb database schema error");
827 return null;
828 }
829 schema.put(dbName, dbSchema);
830
831 return dbSchema;
832 }
833 };
834
835 ListenableFuture<JsonNode> input = getSchema(dbNames);
836 if (input != null) {
837 return Futures.transform(input, rowFunction);
838 }
839 return null;
840 } else {
841 return Futures.immediateFuture(databaseSchema);
842 }
843 }
844
845 @Override
846 public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) {
847 if (dbName == null) {
848 return null;
849 }
850 DatabaseSchema dbSchema = schema.get(dbName);
851 if (dbSchema != null) {
852 Function<JsonNode, TableUpdates> rowFunction = new Function<JsonNode, TableUpdates>() {
853 @Override
854 public TableUpdates apply(JsonNode input) {
855 log.info("Get table updates");
856 TableUpdates updates = FromJsonUtil
857 .jsonNodeToTableUpdates(input, dbSchema);
858 if (updates == null) {
859 log.debug("Get table updates error");
860 return null;
861 }
862 return updates;
863 }
864 };
865 return Futures.transform(monitor(dbSchema, id), rowFunction);
866 }
867 return null;
868 }
869
870 @Override
871 public ListenableFuture<List<OperationResult>> transactConfig(String dbName,
872 List<Operation> operations) {
873 if (dbName == null) {
874 return null;
875 }
876 DatabaseSchema dbSchema = schema.get(dbName);
877 if (dbSchema != null) {
878 Function<List<JsonNode>, List<OperationResult>> rowFunction =
879 new Function<List<JsonNode>, List<OperationResult>>() {
880 @Override
881 public List<OperationResult> apply(List<JsonNode> input) {
882 log.info("Get ovsdb operation result");
883 List<OperationResult> result = FromJsonUtil
884 .jsonNodeToOperationResult(input, operations);
885
886 if (result == null) {
887 log.debug("The operation result is null");
888 return null;
889 }
890 return result;
891 }
892 };
893 return Futures.transform(transact(dbSchema, operations),
894 rowFunction);
895 }
896 return null;
897 }
898
899 @Override
900 public ListenableFuture<JsonNode> getSchema(List<String> dbnames) {
901 String id = java.util.UUID.randomUUID().toString();
902 String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames);
903
904 SettableFuture<JsonNode> sf = SettableFuture.create();
905 requestResult.put(id, sf);
906 requestMethod.put(id, "getSchema");
907
908 channel.writeAndFlush(getSchemaString);
909 return sf;
910
911 }
912
913 @Override
914 public ListenableFuture<List<String>> echo() {
915 String id = java.util.UUID.randomUUID().toString();
916 String echoString = JsonRpcWriterUtil.echoStr(id);
917
918 SettableFuture<List<String>> sf = SettableFuture.create();
919 requestResult.put(id, sf);
920 requestMethod.put(id, "echo");
921
922 channel.writeAndFlush(echoString);
923 return sf;
924
925 }
926
927 @Override
928 public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema,
929 String monitorId) {
930 String id = java.util.UUID.randomUUID().toString();
931 String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId,
932 dbSchema);
933
934 SettableFuture<JsonNode> sf = SettableFuture.create();
935 requestResult.put(id, sf);
936 requestMethod.put(id, "monitor");
937
938 channel.writeAndFlush(monitorString);
939 return sf;
940
941 }
942
943 @Override
944 public ListenableFuture<List<String>> listDbs() {
945 String id = java.util.UUID.randomUUID().toString();
946 String listDbsString = JsonRpcWriterUtil.listDbsStr(id);
947
948 SettableFuture<List<String>> sf = SettableFuture.create();
949 requestResult.put(id, sf);
950 requestMethod.put(id, "listDbs");
951
952 channel.writeAndFlush(listDbsString);
953 return sf;
954
955 }
956
957 @Override
958 public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema,
959 List<Operation> operations) {
960 String id = java.util.UUID.randomUUID().toString();
961 String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema,
962 operations);
963
964 SettableFuture<List<JsonNode>> sf = SettableFuture.create();
965 requestResult.put(id, sf);
966 requestMethod.put(id, "transact");
967
968 channel.writeAndFlush(transactString);
969 return sf;
970
971 }
972
973 @SuppressWarnings({ "rawtypes", "unchecked" })
974 @Override
975 public void processResult(JsonNode response) {
976 log.debug("Handle result");
977 String requestId = response.get("id").asText();
978 SettableFuture sf = requestResult.get(requestId);
979 if (sf == null) {
980 log.debug("No such future to process");
981 return;
982 }
983 String methodName = requestMethod.get(requestId);
984
985 Object result;
986 result = FromJsonUtil.jsonResultParser(response, methodName);
987
988 sf.set(result);
989 return;
990 }
991
992 @Override
993 public void processRequest(JsonNode requestJson) {
994 log.debug("Handle request");
995 if (requestJson.get("method").asText().equalsIgnoreCase("echo")) {
996 log.debug("handle echo request");
997
998 String replyString = FromJsonUtil.getEchoRequestStr(requestJson);
999 channel.writeAndFlush(replyString);
1000
1001 return;
1002 } else {
1003 FromJsonUtil
1004 .jsonCallbackRequestParser(requestJson, monitorCallBack);
1005 return;
1006 }
1007 }
1008
1009 @Override
1010 public void setCallback(Callback monitorCallback) {
1011 this.monitorCallBack = monitorCallback;
1012 }
1013
1014 @Override
1015 public Set<OvsdbTunnel> getTunnels() {
1016 return ovsdbTunnels;
1017 }
1018
1019 @Override
1020 public Set<OvsdbBridge> getBridges() {
1021 Set<OvsdbBridge> ovsdbBridges = new HashSet<OvsdbBridge>();
1022 OvsdbTableStore tableStore = getTableStore(OvsdbConstant.DATABASENAME);
1023 if (tableStore == null) {
1024 return null;
1025 }
1026 OvsdbRowStore rowStore = tableStore.getRows(OvsdbConstant.BRIDGE);
1027 if (rowStore == null) {
1028 return null;
1029 }
1030 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1031 for (String uuid : rows.keySet()) {
1032 Row row = getRow(OvsdbConstant.DATABASENAME, OvsdbConstant.BRIDGE,
1033 uuid);
1034 OvsdbBridge ovsdbBridge = getOvsdbBridge(row);
1035 if (ovsdbBridge != null) {
1036 ovsdbBridges.add(ovsdbBridge);
1037 }
1038 }
1039 return ovsdbBridges;
1040 }
1041
1042 @Override
1043 public Set<OvsdbPort> getPorts() {
1044 Set<OvsdbPort> ovsdbPorts = new HashSet<OvsdbPort>();
1045 OvsdbTableStore tableStore = getTableStore(OvsdbConstant.DATABASENAME);
1046 if (tableStore == null) {
1047 return null;
1048 }
1049 OvsdbRowStore rowStore = tableStore.getRows(OvsdbConstant.INTERFACE);
1050 if (rowStore == null) {
1051 return null;
1052 }
1053 ConcurrentMap<String, Row> rows = rowStore.getRowStore();
1054 for (String uuid : rows.keySet()) {
1055 Row row = getRow(OvsdbConstant.DATABASENAME,
1056 OvsdbConstant.INTERFACE, uuid);
1057 OvsdbPort ovsdbPort = getOvsdbPort(row);
1058 if (ovsdbPort != null) {
1059 ovsdbPorts.add(ovsdbPort);
1060 }
1061 }
1062 return ovsdbPorts;
1063 }
1064
1065 @Override
1066 public DatabaseSchema getDatabaseSchema(String dbName) {
1067 return schema.get(dbName);
1068 }
1069
1070 //Gets ovsdb port.
1071 private OvsdbPort getOvsdbPort(Row row) {
1072 DatabaseSchema dbSchema = getDatabaseSchema(OvsdbConstant.DATABASENAME);
1073 Interface intf = (Interface) TableGenerator
1074 .getTable(dbSchema, row, OvsdbTable.INTERFACE);
1075 if (intf == null) {
1076 return null;
1077 }
1078 long ofPort = getOfPort(intf);
1079 String portName = intf.getName();
1080 if ((ofPort < 0) || (portName == null)) {
1081 return null;
1082 }
1083
1084 OvsdbPort ovsdbPort = new OvsdbPort(new OvsdbPortNumber(ofPort),
1085 new OvsdbPortName(portName));
1086 return ovsdbPort;
1087 }
1088
1089 ////Gets ovsdb bridge.
1090 private OvsdbBridge getOvsdbBridge(Row row) {
1091 DatabaseSchema dbSchema = getDatabaseSchema(OvsdbConstant.DATABASENAME);
1092 Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, row,
1093 OvsdbTable.BRIDGE);
1094 if (bridge == null) {
1095 return null;
1096 }
1097
1098 OvsdbSet datapathIdSet = (OvsdbSet) bridge.getDatapathIdColumn().data();
1099 @SuppressWarnings("unchecked")
1100 Set<String> datapathIds = datapathIdSet.set();
1101 if (datapathIds == null || datapathIds.size() == 0) {
1102 return null;
1103 }
1104 String datapathId = (String) datapathIds.toArray()[0];
1105 String bridgeName = bridge.getName();
1106 if ((datapathId == null) || (bridgeName == null)) {
1107 return null;
1108 }
1109
1110 OvsdbBridge ovsdbBridge = new OvsdbBridge(new OvsdbBridgeName(bridgeName),
1111 new OvsdbDatapathId(datapathId));
1112 return ovsdbBridge;
1113 }
1114
1115 //Gets ofPort in the interface.
1116 private long getOfPort(Interface intf) {
1117 OvsdbSet ofPortSet = (OvsdbSet) intf.getOpenFlowPortColumn().data();
1118 @SuppressWarnings("unchecked")
1119 Set<Integer> ofPorts = ofPortSet.set();
1120 while (ofPorts == null || ofPorts.size() <= 0) {
1121 log.debug("The ofport is null in {}", intf.getName());
1122 return -1;
1123 }
1124 // return (long) ofPorts.toArray()[0];
1125 Iterator<Integer> it = ofPorts.iterator();
1126 return Long.parseLong(it.next().toString());
1127 }
1128}