/*
* Copyright (c) 2015, 2017 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
/**
* Class for handling SFC OVS RPCs
* <p>
*
* @author Andrej Kincel (andrej.kincel@gmail.com)
* @version 0.1
* @since 2015-03-31
*/
package org.opendaylight.sfc.ovs.provider;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.Futures;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.opendaylight.sfc.ovs.api.SfcOvsDataStoreAPI;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.CreateOvsBridgeInput;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.CreateOvsBridgeOutput;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.CreateOvsBridgeOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.ServiceFunctionForwarderOvsService;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.create.ovs.bridge.input.OvsNode;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SfcOvsRpc implements ServiceFunctionForwarderOvsService {
private static final Logger LOG = LoggerFactory.getLogger(SfcOvsRpc.class);
private static final String OVSDB_NODE_PREFIX = "ovsdb://";
protected static ExecutorService executor = Executors.newFixedThreadPool(5);
/**
* This method writes a new OVS Bridge into OVSDB Config DataStore. This write event triggers
* creation of the OVS Bridge in running OpenVSwitch instance identified by OVS Node ip:port
* locator.
*
* <p>
* @param input RPC input including a OVS Bridge name and parent OVS Node ip:port locator
* @return RPC output: true if write to OVSDB Config DataStore was successful, otherwise false.
*/
@Override
public Future<RpcResult<CreateOvsBridgeOutput>> createOvsBridge(CreateOvsBridgeInput input) {
Preconditions.checkNotNull(input, "create-ovs-bridge RPC input must be not null!");
Preconditions.checkNotNull(input.getOvsNode(),
"create-ovs-bridge RPC input container ovs-node must be not null!");
RpcResultBuilder<CreateOvsBridgeOutput> rpcResultBuilder;
NodeId nodeId = null;
OvsNode ovsNode = input.getOvsNode();
//create parent OVS Node InstanceIdentifier (based on ip:port locator)
if (ovsNode.getPort() != null && ovsNode.getIp() != null) {
nodeId = new NodeId(OVSDB_NODE_PREFIX
+ ovsNode.getIp().getIpv4Address().getValue()
+ ":" + ovsNode.getPort().getValue());
//create parent OVS Node InstanceIdentifier (based on ip)
} else if (ovsNode.getIp() != null) {
IpAddress ipAddress = new IpAddress(ovsNode.getIp().getValue());
Node node = SfcOvsUtil.getManagerNodeByIp(ipAddress, executor);
if (node != null) {
nodeId = node.getNodeId();
}
}
if (nodeId != null) {
InstanceIdentifier<Node> nodeIID = SfcOvsUtil.buildOvsdbNodeIID(nodeId);
//build OVS Bridge
//TODO: separate into function as it will grow in future (including DP locators, etc.)
OvsdbBridgeAugmentationBuilder ovsdbBridgeBuilder = new OvsdbBridgeAugmentationBuilder();
ovsdbBridgeBuilder.setBridgeName(new OvsdbBridgeName(input.getName()));
ovsdbBridgeBuilder.setManagedBy(new OvsdbNodeRef(nodeIID));
Object[] methodParams = {ovsdbBridgeBuilder.build()};
SfcOvsDataStoreAPI sfcOvsDataStoreAPI =
new SfcOvsDataStoreAPI(SfcOvsDataStoreAPI.Method.PUT_OVSDB_BRIDGE, methodParams);
if ((boolean) SfcOvsUtil.submitCallable(sfcOvsDataStoreAPI, executor)) {
rpcResultBuilder = RpcResultBuilder.success(new CreateOvsBridgeOutputBuilder().setResult(true).build());
} else {
String message = "Error writing OVS Bridge: '" + input.getName()
+ "' into OVSDB Configuration DataStore.";
rpcResultBuilder = RpcResultBuilder.<CreateOvsBridgeOutput>failed()
.withError(RpcError.ErrorType.APPLICATION, message);
}
} else {
String message = "Error writing OVS Bridge: '" + input.getName()
+ "' into OVSDB Configuration DataStore (cannot determine parent NodeId).";
rpcResultBuilder = RpcResultBuilder.<CreateOvsBridgeOutput>failed()
.withError(RpcError.ErrorType.APPLICATION, message);
}
return Futures.immediateFuture(rpcResultBuilder.build());
}
}