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