| /* |
| * Copyright 2015 Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.ovsdb.controller.driver; |
| |
| import io.netty.channel.Channel; |
| |
| import java.net.InetSocketAddress; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.ConcurrentMap; |
| import java.util.concurrent.ExecutionException; |
| |
| import org.onlab.packet.IpAddress; |
| import org.onosproject.ovsdb.controller.OvsdbBridge; |
| import org.onosproject.ovsdb.controller.OvsdbClientService; |
| import org.onosproject.ovsdb.controller.OvsdbConstant; |
| import org.onosproject.ovsdb.controller.OvsdbNodeId; |
| import org.onosproject.ovsdb.controller.OvsdbPort; |
| import org.onosproject.ovsdb.controller.OvsdbRowStore; |
| import org.onosproject.ovsdb.controller.OvsdbStore; |
| import org.onosproject.ovsdb.controller.OvsdbTableStore; |
| import org.onosproject.ovsdb.controller.OvsdbTunnel; |
| import org.onosproject.ovsdb.rfc.jsonrpc.Callback; |
| import org.onosproject.ovsdb.rfc.message.OperationResult; |
| import org.onosproject.ovsdb.rfc.message.TableUpdates; |
| import org.onosproject.ovsdb.rfc.notation.Condition; |
| import org.onosproject.ovsdb.rfc.notation.Mutation; |
| import org.onosproject.ovsdb.rfc.notation.OvsdbSet; |
| import org.onosproject.ovsdb.rfc.notation.Row; |
| import org.onosproject.ovsdb.rfc.notation.UUID; |
| import org.onosproject.ovsdb.rfc.operations.Delete; |
| import org.onosproject.ovsdb.rfc.operations.Insert; |
| import org.onosproject.ovsdb.rfc.operations.Mutate; |
| import org.onosproject.ovsdb.rfc.operations.Operation; |
| import org.onosproject.ovsdb.rfc.operations.Update; |
| import org.onosproject.ovsdb.rfc.schema.ColumnSchema; |
| import org.onosproject.ovsdb.rfc.schema.DatabaseSchema; |
| import org.onosproject.ovsdb.rfc.schema.TableSchema; |
| import org.onosproject.ovsdb.rfc.table.Bridge; |
| import org.onosproject.ovsdb.rfc.table.Controller; |
| import org.onosproject.ovsdb.rfc.table.Interface; |
| import org.onosproject.ovsdb.rfc.table.OvsdbTable; |
| import org.onosproject.ovsdb.rfc.table.Port; |
| import org.onosproject.ovsdb.rfc.table.TableGenerator; |
| import org.onosproject.ovsdb.rfc.utils.ConditionUtil; |
| import org.onosproject.ovsdb.rfc.utils.FromJsonUtil; |
| import org.onosproject.ovsdb.rfc.utils.JsonRpcWriterUtil; |
| import org.onosproject.ovsdb.rfc.utils.MutationUtil; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.fasterxml.jackson.databind.JsonNode; |
| import com.google.common.base.Function; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Maps; |
| import com.google.common.util.concurrent.Futures; |
| import com.google.common.util.concurrent.ListenableFuture; |
| import com.google.common.util.concurrent.SettableFuture; |
| |
| /** |
| * An representation of an ovsdb client. |
| */ |
| public class DefaultOvsdbClient |
| implements OvsdbProviderService, OvsdbClientService { |
| |
| private final Logger log = LoggerFactory |
| .getLogger(DefaultOvsdbClient.class); |
| |
| private Channel channel; |
| |
| private OvsdbAgent agent; |
| private boolean connected; |
| private OvsdbNodeId nodeId; |
| private Callback monitorCallBack; |
| |
| private OvsdbStore ovsdbStore = new OvsdbStore(); |
| |
| private final Map<String, String> requestMethod = Maps.newHashMap(); |
| private final Map<String, SettableFuture<? extends Object>> requestResult = Maps |
| .newHashMap(); |
| |
| private final Map<String, DatabaseSchema> schema = Maps.newHashMap(); |
| private final Set<OvsdbPort> ovsdbPorts = new HashSet<OvsdbPort>(); |
| private final Set<OvsdbTunnel> ovsdbTunnels = new HashSet<OvsdbTunnel>(); |
| private final Set<OvsdbBridge> ovsdbBridges = new HashSet<OvsdbBridge>(); |
| |
| /** |
| * Creates an OvsdbClient. |
| * |
| * @param nodeId ovsdb node id |
| */ |
| public DefaultOvsdbClient(OvsdbNodeId nodeId) { |
| this.nodeId = nodeId; |
| } |
| |
| @Override |
| public OvsdbNodeId nodeId() { |
| return nodeId; |
| } |
| |
| @Override |
| public void setAgent(OvsdbAgent agent) { |
| if (this.agent == null) { |
| this.agent = agent; |
| } |
| } |
| |
| @Override |
| public void setChannel(Channel channel) { |
| this.channel = channel; |
| } |
| |
| @Override |
| public void setConnection(boolean connected) { |
| this.connected = connected; |
| } |
| |
| @Override |
| public boolean isConnected() { |
| return this.connected; |
| } |
| |
| @Override |
| public void nodeAdded() { |
| this.agent.addConnectedNode(nodeId, this); |
| } |
| |
| @Override |
| public void nodeRemoved() { |
| this.agent.removeConnectedNode(nodeId); |
| channel.disconnect(); |
| } |
| |
| /** |
| * Gets the ovsdb table store. |
| * |
| * @param dbName the ovsdb database name |
| * @return ovsTableStore, empty if table store is find |
| */ |
| private OvsdbTableStore getTableStore(String dbName) { |
| if (ovsdbStore == null) { |
| return null; |
| } |
| return ovsdbStore.getOvsdbTableStore(dbName); |
| } |
| |
| /** |
| * Gets the ovsdb row store. |
| * |
| * @param dbName the ovsdb database name |
| * @param tableName the ovsdb table name |
| * |
| * @return ovsRowStore, empty if row store is find |
| */ |
| private OvsdbRowStore getRowStore(String dbName, String tableName) { |
| OvsdbTableStore tableStore = getTableStore(dbName); |
| if (tableStore == null) { |
| return null; |
| } |
| return tableStore.getRows(tableName); |
| } |
| |
| /** |
| * Gets the ovsdb row. |
| * |
| * @param dbName the ovsdb database name |
| * @param tableName the ovsdb table name |
| * @param uuid the key of the row |
| * @return row, empty if row is find |
| */ |
| @Override |
| public Row getRow(String dbName, String tableName, String uuid) { |
| OvsdbTableStore tableStore = getTableStore(dbName); |
| if (tableStore == null) { |
| return null; |
| } |
| OvsdbRowStore rowStore = tableStore.getRows(tableName); |
| if (rowStore == null) { |
| return null; |
| } |
| return rowStore.getRow(uuid); |
| } |
| |
| @Override |
| public void removeRow(String dbName, String tableName, String uuid) { |
| OvsdbTableStore tableStore = getTableStore(dbName); |
| if (tableStore == null) { |
| return; |
| } |
| OvsdbRowStore rowStore = tableStore.getRows(tableName); |
| if (rowStore == null) { |
| return; |
| } |
| rowStore.deleteRow(uuid); |
| } |
| |
| @Override |
| public void updateOvsdbStore(String dbName, String tableName, String uuid, |
| Row row) { |
| OvsdbTableStore tableStore = ovsdbStore.getOvsdbTableStore(dbName); |
| if (tableStore == null) { |
| tableStore = new OvsdbTableStore(); |
| } |
| OvsdbRowStore rowStore = tableStore.getRows(tableName); |
| if (rowStore == null) { |
| rowStore = new OvsdbRowStore(); |
| } |
| rowStore.insertRow(uuid, row); |
| tableStore.createOrUpdateTable(tableName, rowStore); |
| ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore); |
| } |
| |
| @Override |
| public String getPortUuid(String portName, String bridgeUuid) { |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| |
| Row bridgeRow = getRow(OvsdbConstant.DATABASENAME, |
| OvsdbConstant.BRIDGE, bridgeUuid); |
| |
| Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow, |
| OvsdbTable.BRIDGE); |
| if (bridge != null) { |
| OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data(); |
| @SuppressWarnings("unchecked") |
| Set<UUID> ports = setPorts.set(); |
| if (ports == null || ports.size() == 0) { |
| log.warn("The port uuid is null"); |
| return null; |
| } |
| |
| for (UUID uuid : ports) { |
| Row portRow = getRow(OvsdbConstant.DATABASENAME, |
| OvsdbConstant.PORT, uuid.value()); |
| if (portRow == null) { |
| continue; |
| } |
| Port port = (Port) TableGenerator.getTable(dbSchema, portRow, |
| OvsdbTable.PORT); |
| if (port != null && portName.equalsIgnoreCase(port.getName())) { |
| return uuid.value(); |
| } |
| } |
| |
| } |
| return null; |
| } |
| |
| @Override |
| public String getInterfaceUuid(String portUuid, String portName) { |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| |
| Row portRow = getRow(OvsdbConstant.DATABASENAME, OvsdbConstant.PORT, |
| portUuid); |
| Port port = (Port) TableGenerator.getTable(dbSchema, portRow, |
| OvsdbTable.PORT); |
| |
| if (port != null) { |
| OvsdbSet setInterfaces = (OvsdbSet) port.getInterfacesColumn().data(); |
| @SuppressWarnings("unchecked") |
| Set<UUID> interfaces = setInterfaces.set(); |
| |
| if (interfaces == null || interfaces.size() == 0) { |
| log.warn("The interface uuid is null"); |
| return null; |
| } |
| |
| for (UUID uuid : interfaces) { |
| Row intfRow = getRow(OvsdbConstant.DATABASENAME, |
| OvsdbConstant.INTERFACE, uuid.value()); |
| if (intfRow == null) { |
| continue; |
| } |
| Interface intf = (Interface) TableGenerator |
| .getTable(dbSchema, intfRow, OvsdbTable.INTERFACE); |
| if (intf != null && portName.equalsIgnoreCase(intf.getName())) { |
| return uuid.value(); |
| } |
| } |
| |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public String getBridgeUuid(String bridgeName) { |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| |
| OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME, |
| OvsdbConstant.BRIDGE); |
| if (rowStore == null) { |
| log.debug("The bridge uuid is null"); |
| return null; |
| } |
| |
| ConcurrentMap<String, Row> bridgeTableRows = rowStore.getRowStore(); |
| if (bridgeTableRows == null) { |
| log.debug("The bridge uuid is null"); |
| return null; |
| } |
| |
| for (String uuid : bridgeTableRows.keySet()) { |
| Bridge bridge = (Bridge) TableGenerator |
| .getTable(dbSchema, bridgeTableRows.get(uuid), |
| OvsdbTable.BRIDGE); |
| |
| if (bridge.getName().equals(bridgeName)) { |
| return uuid; |
| } |
| |
| } |
| return null; |
| } |
| |
| @Override |
| public String getControllerUuid(String controllerName, |
| String controllerTarget) { |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME, |
| OvsdbConstant.CONTROLLER); |
| if (rowStore == null) { |
| log.debug("The controller uuid is null"); |
| return null; |
| } |
| |
| ConcurrentMap<String, Row> controllerTableRows = rowStore.getRowStore(); |
| if (controllerTableRows != null) { |
| for (String uuid : controllerTableRows.keySet()) { |
| |
| Controller controller = (Controller) TableGenerator |
| .getTable(dbSchema, controllerTableRows.get(uuid), |
| OvsdbTable.CONTROLLER); |
| String target = (String) controller.getTargetColumn().data(); |
| if (target.equalsIgnoreCase(controllerTarget)) { |
| return uuid; |
| } |
| |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public String getOvsUuid(String dbName) { |
| OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME, |
| OvsdbConstant.DATABASENAME); |
| if (rowStore == null) { |
| log.debug("The bridge uuid is null"); |
| return null; |
| } |
| ConcurrentMap<String, Row> ovsTableRows = rowStore.getRowStore(); |
| if (ovsTableRows != null) { |
| for (String uuid : ovsTableRows.keySet()) { |
| Row row = ovsTableRows.get(uuid); |
| String tableName = row.tableName(); |
| if (tableName.equals(dbName)) { |
| return uuid; |
| } |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public void createPort(String bridgeName, String portName) { |
| String bridgeUuid = getBridgeUuid(bridgeName); |
| if (bridgeUuid == null) { |
| log.error("Can't find bridge {} in {}", bridgeName, |
| nodeId.getIpAddress()); |
| return; |
| } |
| |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| String portUuid = getPortUuid(portName, bridgeUuid); |
| |
| Port port = (Port) TableGenerator |
| .createTable(dbSchema, OvsdbTable.PORT); |
| |
| port.setName(portName); |
| if (portUuid == null) { |
| insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE, |
| "ports", bridgeUuid, port.getRow()); |
| } else { |
| updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow()); |
| } |
| |
| return; |
| } |
| |
| @Override |
| public void dropPort(String bridgeName, String portName) { |
| String bridgeUuid = getBridgeUuid(bridgeName); |
| if (bridgeUuid == null) { |
| log.error("Could not find Bridge {} in {}", bridgeName, nodeId); |
| return; |
| } |
| |
| String portUuid = getPortUuid(portName, bridgeUuid); |
| if (portUuid != null) { |
| log.info("Port {} delete", portName); |
| deleteConfig(OvsdbConstant.PORT, "_uuid", portUuid, |
| OvsdbConstant.BRIDGE, "ports"); |
| } |
| } |
| |
| @Override |
| public void createBridge(String bridgeName) { |
| log.debug("create bridge {}", bridgeName); |
| |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| if (dbSchema == null) { |
| log.warn("The schema is null"); |
| return; |
| } |
| |
| Bridge bridge = (Bridge) TableGenerator.createTable(dbSchema, |
| OvsdbTable.BRIDGE); |
| if (bridge == null) { |
| log.debug("Can not create bridge"); |
| return; |
| } |
| |
| Set<String> failModes = new HashSet<>(); |
| failModes.add("secure"); |
| bridge.setFailMode(failModes); |
| |
| Set<String> protocols = new HashSet<>(); |
| protocols.add(OvsdbConstant.OPENFLOW13); |
| bridge.setProtocols(protocols); |
| |
| String ovsUuid = getOvsUuid(OvsdbConstant.DATABASENAME); |
| if (ovsUuid == null) { |
| log.warn("The Open_vSwitch is null"); |
| return; |
| } |
| |
| String bridgeUuid = getBridgeUuid(bridgeName); |
| if (bridgeUuid == null) { |
| log.debug("Create a new bridge"); |
| |
| bridge.setName(bridgeName); |
| bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid", |
| OvsdbConstant.DATABASENAME, "bridges", |
| ovsUuid, bridge.getRow()); |
| |
| if (bridgeUuid != null) { |
| Port port = (Port) TableGenerator.createTable(dbSchema, |
| OvsdbTable.PORT); |
| if (port != null) { |
| log.debug("the port is not null"); |
| port.setName(bridgeName); |
| |
| insertConfig(OvsdbConstant.PORT, "_uuid", "Bridge", "ports", bridgeUuid, |
| port.getRow()); |
| } |
| } |
| |
| } else { |
| log.info("Update a bridge"); |
| updateConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUuid, bridge.getRow()); |
| } |
| |
| setController(bridgeUuid); |
| log.info("Create bridge success"); |
| } |
| |
| /** |
| * Sets the Controller. |
| * |
| * @param bridgeUuid bridge uuid |
| */ |
| private void setController(String bridgeUuid) { |
| String controllerUuid = null; |
| String iPAddress = IpAddress.valueOf(((InetSocketAddress) channel |
| .localAddress()) |
| .getAddress() |
| .getHostAddress()) |
| .toString(); |
| |
| String target = "tcp:" + iPAddress + ":" + OvsdbConstant.OFPORT; |
| log.debug("controller IP {}: port {}", iPAddress, OvsdbConstant.OFPORT); |
| |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| Controller controller = (Controller) TableGenerator |
| .createTable(dbSchema, OvsdbTable.CONTROLLER); |
| |
| if (controller != null) { |
| controller.setTarget(target); |
| controllerUuid = getControllerUuid(OvsdbConstant.CONTROLLER, target); |
| if (controllerUuid == null) { |
| |
| insertConfig(OvsdbConstant.CONTROLLER, "_uuid", |
| OvsdbConstant.BRIDGE, "controller", bridgeUuid, |
| controller.getRow()); |
| |
| } else { |
| |
| Bridge bridge = (Bridge) TableGenerator |
| .createTable(dbSchema, OvsdbTable.BRIDGE); |
| Set<UUID> controllerUuids = new HashSet<>(); |
| controllerUuids.add(UUID.uuid(controllerUuid)); |
| bridge.setController(controllerUuids); |
| updateConfig(OvsdbConstant.CONTROLLER, "_uuid", bridgeUuid, bridge.getRow()); |
| |
| } |
| } |
| |
| } |
| |
| @Override |
| public void dropBridge(String bridgeName) { |
| String bridgeUUID = getBridgeUuid(bridgeName); |
| if (bridgeUUID == null) { |
| log.warn("Could not find bridge in node", nodeId.getIpAddress()); |
| return; |
| } |
| deleteConfig(OvsdbConstant.BRIDGE, "_uuid", bridgeUUID, |
| OvsdbConstant.DATABASENAME, "bridges"); |
| } |
| |
| @Override |
| public void createTunnel(IpAddress srcIp, IpAddress dstIp) { |
| String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE); |
| if (bridgeUuid == null) { |
| log.warn("Could not find bridge {} and Could not create tunnel. ", |
| OvsdbConstant.INTEGRATION_BRIDGE); |
| return; |
| } |
| |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp); |
| String portUuid = getPortUuid(portName, bridgeUuid); |
| |
| Port port = (Port) TableGenerator |
| .createTable(dbSchema, OvsdbTable.PORT); |
| if (port != null) { |
| port.setName(portName); |
| } |
| |
| if (portUuid == null) { |
| portUuid = insertConfig(OvsdbConstant.PORT, "_uuid", OvsdbConstant.BRIDGE, |
| "ports", bridgeUuid, port.getRow()); |
| } else { |
| updateConfig(OvsdbConstant.PORT, "_uuid", portUuid, port.getRow()); |
| } |
| |
| // When a tunnel is created, A row is inserted into port table and |
| // interface table of the ovsdb node. |
| // and the following step is to get the interface uuid from local store |
| // in controller node. |
| // but it need spend some time synchronising data between node and |
| // controller. |
| // so loop to judge if interfaceUUid is null is necessary. |
| String interfaceUuid = null; |
| for (int i = 0; i < 10; i++) { |
| interfaceUuid = getInterfaceUuid(portUuid, portName); |
| if (interfaceUuid == null) { |
| try { |
| Thread.sleep(500); |
| } catch (InterruptedException e) { |
| log.warn("Interrupted while waiting to get interfaceUuid"); |
| Thread.currentThread().interrupt(); |
| } |
| } else { |
| break; |
| } |
| } |
| |
| if (interfaceUuid != null) { |
| OvsdbRowStore rowStore = getRowStore(OvsdbConstant.DATABASENAME, |
| OvsdbConstant.INTERFACE); |
| if (rowStore == null) { |
| log.debug("The bridge uuid is null"); |
| return; |
| } |
| |
| ConcurrentMap<String, Row> intfTableRows = rowStore.getRowStore(); |
| if (intfTableRows == null) { |
| log.debug("The bridge uuid is null"); |
| return; |
| } |
| |
| Interface tunInterface = (Interface) TableGenerator |
| .getTable(dbSchema, intfTableRows.get(interfaceUuid), |
| OvsdbTable.INTERFACE); |
| if (tunInterface != null) { |
| |
| tunInterface.setType(OvsdbConstant.TYPEVXLAN); |
| Map<String, String> options = Maps.newHashMap(); |
| options.put("key", "flow"); |
| options.put("local_ip", srcIp.toString()); |
| options.put("remote_ip", dstIp.toString()); |
| tunInterface.setOptions(options); |
| updateConfig(OvsdbConstant.INTERFACE, "_uuid", interfaceUuid, |
| tunInterface.getRow()); |
| log.info("Tunnel added success", tunInterface); |
| |
| } |
| } |
| |
| return; |
| } |
| |
| @Override |
| public void dropTunnel(IpAddress srcIp, IpAddress dstIp) { |
| String bridgeName = OvsdbConstant.INTEGRATION_BRIDGE; |
| String portName = getTunnelName(OvsdbConstant.TYPEVXLAN, dstIp); |
| String bridgeUuid = getBridgeUuid(OvsdbConstant.INTEGRATION_BRIDGE); |
| if (bridgeUuid == null) { |
| log.warn("Could not find bridge {} in {}", bridgeName, |
| nodeId.getIpAddress()); |
| return; |
| } |
| |
| String portUUID = getPortUuid(portName, bridgeUuid); |
| if (portUUID != null) { |
| log.info("Delete tunnel"); |
| deleteConfig(OvsdbConstant.PORT, "_uuid", portUUID, |
| OvsdbConstant.BRIDGE, "ports"); |
| } |
| |
| return; |
| } |
| |
| /** |
| * Delete transact config. |
| * |
| * @param childTableName child table name |
| * @param childColumnName child column name |
| * @param childUuid child row uuid |
| * @param parentTableName parent table name |
| * @param parentColumnName parent column |
| * |
| */ |
| private void deleteConfig(String childTableName, String childColumnName, |
| String childUuid, String parentTableName, |
| String parentColumnName) { |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| TableSchema childTableSchema = dbSchema.getTableSchema(childTableName); |
| |
| ArrayList<Operation> operations = Lists.newArrayList(); |
| if (parentTableName != null && parentColumnName != null) { |
| TableSchema parentTableSchema = dbSchema |
| .getTableSchema(parentTableName); |
| ColumnSchema parentColumnSchema = parentTableSchema |
| .getColumnSchema(parentColumnName); |
| List<Mutation> mutations = Lists.newArrayList(); |
| Mutation mutation = MutationUtil.delete(parentColumnSchema.name(), |
| UUID.uuid(childUuid)); |
| mutations.add(mutation); |
| List<Condition> conditions = Lists.newArrayList(); |
| Condition condition = ConditionUtil.includes(parentColumnName, |
| UUID.uuid(childUuid)); |
| conditions.add(condition); |
| Mutate op = new Mutate(parentTableSchema, conditions, mutations); |
| operations.add(op); |
| } |
| |
| List<Condition> conditions = Lists.newArrayList(); |
| Condition condition = ConditionUtil.equals(childColumnName, UUID.uuid(childUuid)); |
| conditions.add(condition); |
| Delete del = new Delete(childTableSchema, conditions); |
| operations.add(del); |
| transactConfig(OvsdbConstant.DATABASENAME, operations); |
| |
| return; |
| } |
| |
| /** |
| * Update transact config. |
| * |
| * @param tableName table name |
| * @param columnName column name |
| * @param uuid uuid |
| * @param row the config data |
| * |
| */ |
| private void updateConfig(String tableName, String columnName, String uuid, |
| Row row) { |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| TableSchema tableSchema = dbSchema.getTableSchema(tableName); |
| |
| List<Condition> conditions = Lists.newArrayList(); |
| Condition condition = ConditionUtil.equals(columnName, UUID.uuid(uuid)); |
| conditions.add(condition); |
| |
| Update update = new Update(tableSchema, row, conditions); |
| |
| ArrayList<Operation> operations = Lists.newArrayList(); |
| operations.add(update); |
| |
| transactConfig(OvsdbConstant.DATABASENAME, operations); |
| } |
| |
| /** |
| * Insert transact config. |
| * |
| * @param childTableName child table name |
| * @param childColumnName child column name |
| * @param parentTableName parent table name |
| * @param parentColumnName parent column |
| * @param parentUuid parent uuid |
| * @param row the config data |
| * |
| * @return uuid, empty if no uuid is find |
| */ |
| private String insertConfig(String childTableName, String childColumnName, |
| String parentTableName, String parentColumnName, |
| String parentUuid, Row row) { |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| TableSchema tableSchema = dbSchema.getTableSchema(childTableName); |
| |
| String namedUuid = childTableName; |
| Insert insert = new Insert(tableSchema, namedUuid, row); |
| |
| ArrayList<Operation> operations = Lists.newArrayList(); |
| operations.add(insert); |
| |
| if (parentTableName != null && parentColumnName != null) { |
| TableSchema parentTableSchema = dbSchema |
| .getTableSchema(parentTableName); |
| ColumnSchema parentColumnSchema = parentTableSchema |
| .getColumnSchema(parentColumnName); |
| |
| List<Mutation> mutations = Lists.newArrayList(); |
| Mutation mutation = MutationUtil.insert(parentColumnSchema.name(), |
| UUID.uuid(namedUuid)); |
| mutations.add(mutation); |
| |
| List<Condition> conditions = Lists.newArrayList(); |
| Condition condition = ConditionUtil.equals("_uuid", |
| UUID.uuid(parentUuid)); |
| conditions.add(condition); |
| |
| Mutate op = new Mutate(parentTableSchema, conditions, mutations); |
| operations.add(op); |
| } |
| if (childTableName.equalsIgnoreCase(OvsdbConstant.PORT)) { |
| log.info("Handle port insert"); |
| Insert intfInsert = handlePortInsertTable(OvsdbConstant.INTERFACE, |
| row); |
| |
| if (intfInsert != null) { |
| operations.add(intfInsert); |
| } |
| |
| Insert ins = (Insert) operations.get(0); |
| ins.getRow().put("interfaces", |
| UUID.uuid(OvsdbConstant.INTERFACE)); |
| } |
| |
| List<OperationResult> results; |
| try { |
| results = transactConfig(OvsdbConstant.DATABASENAME, operations) |
| .get(); |
| |
| return results.get(0).getUuid().value(); |
| } catch (InterruptedException e) { |
| log.warn("Interrupted while waiting to get result"); |
| Thread.currentThread().interrupt(); |
| } catch (ExecutionException e) { |
| log.error("Exception thrown while to get result"); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Handles port insert. |
| * |
| * @param tableName ovsdb table interface |
| * @param portRow row of port |
| * |
| * @return insert, empty if null |
| */ |
| private Insert handlePortInsertTable(String tableName, Row portRow) { |
| DatabaseSchema dbSchema = schema.get(OvsdbConstant.DATABASENAME); |
| |
| TableSchema portTableSchema = dbSchema |
| .getTableSchema(OvsdbConstant.PORT); |
| ColumnSchema portColumnSchema = portTableSchema.getColumnSchema("name"); |
| |
| String portName = (String) portRow.getColumn(portColumnSchema.name()).data(); |
| |
| Interface inf = (Interface) TableGenerator |
| .createTable(dbSchema, OvsdbTable.INTERFACE); |
| |
| inf.setName(portName); |
| |
| TableSchema intfTableSchema = dbSchema |
| .getTableSchema(OvsdbConstant.INTERFACE); |
| Insert insert = new Insert(intfTableSchema, OvsdbConstant.INTERFACE, |
| inf.getRow()); |
| return insert; |
| } |
| |
| /** |
| * Gets tunnel name. |
| * |
| * @param tunnelType |
| * @param dstIp the remote ip address |
| * |
| * @return tunnel name |
| */ |
| private String getTunnelName(String tunnelType, IpAddress dstIp) { |
| return tunnelType + "-" + dstIp.toString(); |
| } |
| |
| @Override |
| public ListenableFuture<DatabaseSchema> getOvsdbSchema(String dbName) { |
| if (dbName == null) { |
| return null; |
| } |
| DatabaseSchema databaseSchema = schema.get(dbName); |
| if (databaseSchema == null) { |
| List<String> dbNames = new ArrayList<String>(); |
| dbNames.add(dbName); |
| Function<JsonNode, DatabaseSchema> rowFunction = new Function<JsonNode, DatabaseSchema>() { |
| @Override |
| public DatabaseSchema apply(JsonNode input) { |
| log.info("Get ovsdb database schema", dbName); |
| DatabaseSchema dbSchema = FromJsonUtil |
| .jsonNodeToDbSchema(dbName, input); |
| if (dbSchema == null) { |
| log.debug("Get ovsdb database schema error"); |
| return null; |
| } |
| schema.put(dbName, dbSchema); |
| |
| return dbSchema; |
| } |
| }; |
| |
| ListenableFuture<JsonNode> input = getSchema(dbNames); |
| if (input != null) { |
| try { |
| log.info("input message: {}", input.get().toString()); |
| } catch (InterruptedException e) { |
| log.warn("Interrupted while waiting to get message"); |
| Thread.currentThread().interrupt(); |
| } catch (ExecutionException e) { |
| log.error("Exception thrown while to get message"); |
| } |
| } |
| return Futures.transform(input, rowFunction); |
| } else { |
| return Futures.immediateFuture(databaseSchema); |
| } |
| } |
| |
| @Override |
| public ListenableFuture<TableUpdates> monitorTables(String dbName, String id) { |
| if (dbName == null) { |
| return null; |
| } |
| DatabaseSchema dbSchema = schema.get(dbName); |
| if (dbSchema != null) { |
| Function<JsonNode, TableUpdates> rowFunction = new Function<JsonNode, TableUpdates>() { |
| @Override |
| public TableUpdates apply(JsonNode input) { |
| log.info("Get table updates"); |
| TableUpdates updates = FromJsonUtil |
| .jsonNodeToTableUpdates(input, dbSchema); |
| if (updates == null) { |
| log.debug("Get table updates error"); |
| return null; |
| } |
| return updates; |
| } |
| }; |
| return Futures.transform(monitor(dbSchema, id), rowFunction); |
| } |
| return null; |
| } |
| |
| @Override |
| public ListenableFuture<List<OperationResult>> transactConfig(String dbName, |
| List<Operation> operations) { |
| if (dbName == null) { |
| return null; |
| } |
| DatabaseSchema dbSchema = schema.get(dbName); |
| if (dbSchema != null) { |
| Function<List<JsonNode>, List<OperationResult>> rowFunction = |
| new Function<List<JsonNode>, List<OperationResult>>() { |
| @Override |
| public List<OperationResult> apply(List<JsonNode> input) { |
| log.info("Get ovsdb operation result"); |
| List<OperationResult> result = FromJsonUtil |
| .jsonNodeToOperationResult(input, operations); |
| |
| if (result == null) { |
| log.debug("The operation result is null"); |
| return null; |
| } |
| return result; |
| } |
| }; |
| return Futures.transform(transact(dbSchema, operations), |
| rowFunction); |
| } |
| return null; |
| } |
| |
| @Override |
| public ListenableFuture<JsonNode> getSchema(List<String> dbnames) { |
| String id = java.util.UUID.randomUUID().toString(); |
| String getSchemaString = JsonRpcWriterUtil.getSchemaStr(id, dbnames); |
| |
| SettableFuture<JsonNode> sf = SettableFuture.create(); |
| requestResult.put(id, sf); |
| requestMethod.put(id, "getSchema"); |
| |
| channel.writeAndFlush(getSchemaString); |
| return sf; |
| |
| } |
| |
| @Override |
| public ListenableFuture<List<String>> echo() { |
| String id = java.util.UUID.randomUUID().toString(); |
| String echoString = JsonRpcWriterUtil.echoStr(id); |
| |
| SettableFuture<List<String>> sf = SettableFuture.create(); |
| requestResult.put(id, sf); |
| requestMethod.put(id, "echo"); |
| |
| channel.writeAndFlush(echoString); |
| return sf; |
| |
| } |
| |
| @Override |
| public ListenableFuture<JsonNode> monitor(DatabaseSchema dbSchema, |
| String monitorId) { |
| String id = java.util.UUID.randomUUID().toString(); |
| String monitorString = JsonRpcWriterUtil.monitorStr(id, monitorId, |
| dbSchema); |
| |
| SettableFuture<JsonNode> sf = SettableFuture.create(); |
| requestResult.put(id, sf); |
| requestMethod.put(id, "monitor"); |
| |
| channel.writeAndFlush(monitorString); |
| return sf; |
| |
| } |
| |
| @Override |
| public ListenableFuture<List<String>> listDbs() { |
| String id = java.util.UUID.randomUUID().toString(); |
| String listDbsString = JsonRpcWriterUtil.listDbsStr(id); |
| |
| SettableFuture<List<String>> sf = SettableFuture.create(); |
| requestResult.put(id, sf); |
| requestMethod.put(id, "listDbs"); |
| |
| channel.writeAndFlush(listDbsString); |
| return sf; |
| |
| } |
| |
| @Override |
| public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema, |
| List<Operation> operations) { |
| String id = java.util.UUID.randomUUID().toString(); |
| String transactString = JsonRpcWriterUtil.transactStr(id, dbSchema, |
| operations); |
| |
| SettableFuture<List<JsonNode>> sf = SettableFuture.create(); |
| requestResult.put(id, sf); |
| requestMethod.put(id, "transact"); |
| |
| channel.writeAndFlush(transactString); |
| return sf; |
| |
| } |
| |
| @SuppressWarnings({ "rawtypes", "unchecked" }) |
| @Override |
| public void processResult(JsonNode response) { |
| log.debug("Handle result"); |
| String requestId = response.get("id").asText(); |
| SettableFuture sf = requestResult.get(requestId); |
| if (sf == null) { |
| log.debug("No such future to process"); |
| return; |
| } |
| String methodName = requestMethod.get(requestId); |
| |
| Object result; |
| result = FromJsonUtil.jsonResultParser(response, methodName); |
| |
| sf.set(result); |
| return; |
| } |
| |
| @Override |
| public void processRequest(JsonNode requestJson) { |
| log.debug("Handle request"); |
| if (requestJson.get("method").asText().equalsIgnoreCase("echo")) { |
| log.debug("handle echo request"); |
| |
| String replyString = FromJsonUtil.getEchoRequestStr(requestJson); |
| channel.writeAndFlush(replyString); |
| |
| return; |
| } else { |
| FromJsonUtil |
| .jsonCallbackRequestParser(requestJson, monitorCallBack); |
| return; |
| } |
| } |
| |
| @Override |
| public void setCallback(Callback monitorCallback) { |
| this.monitorCallBack = monitorCallback; |
| } |
| |
| @Override |
| public Set<OvsdbTunnel> getTunnels() { |
| return ovsdbTunnels; |
| } |
| |
| @Override |
| public Set<OvsdbBridge> getBridges() { |
| return ovsdbBridges; |
| } |
| |
| @Override |
| public Set<OvsdbPort> getPorts() { |
| return ovsdbPorts; |
| } |
| |
| @Override |
| public DatabaseSchema getDatabaseSchema(String dbName) { |
| return schema.get(dbName); |
| } |
| |
| } |