Java tutorial
/* * Copyright (c) 2014, 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 */ package org.opendaylight.sfc.provider; import static org.opendaylight.sfc.provider.SfcProviderDebug.printTraceStart; import static org.opendaylight.sfc.provider.SfcProviderDebug.printTraceStop; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.util.concurrent.Futures; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.sal.common.util.Rpcs; import org.opendaylight.sfc.provider.api.SfcDataStoreAPI; import org.opendaylight.sfc.provider.api.SfcInstanceIdentifiers; import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI; import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI; import org.opendaylight.sfc.provider.api.SfcProviderServiceFunctionAPI; import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI; import org.opendaylight.sfc.provider.api.SfcServicePathId; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.AllocatePathIdInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.AllocatePathIdOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.DeletePathIdInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.DeletePathIdOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ReadPathIdInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ReadPathIdOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ReservePathIdRangeInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ReservePathIdRangeOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.ServicePathIdService; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.SetGenerationAlgorithmInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.SetGenerationAlgorithmOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.service.path.id.rev150804.SetGenerationAlgorithmOutputBuilder; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathOutputBuilder; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.DeleteRenderedPathInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.DeleteRenderedPathOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.DeleteRenderedPathOutputBuilder; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.ReadRenderedServicePathFirstHopInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.ReadRenderedServicePathFirstHopOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.ReadRenderedServicePathFirstHopOutputBuilder; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.ReadRspFirstHopBySftListInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.ReadRspFirstHopBySftListOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.ReadRspFirstHopBySftListOutputBuilder; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePathService; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.TraceRenderedServicePathInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.TraceRenderedServicePathOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.path.first.hop.info.RenderedServicePathFirstHop; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.DeleteServiceFunctionInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.PutServiceFunctionInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ReadServiceFunctionInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ReadServiceFunctionOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ReadServiceFunctionOutputBuilder; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionService; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocator; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionKey; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.InstantiateServiceFunctionChainInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.InstantiateServiceFunctionChainOutput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.PutServiceFunctionChainsInput; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainService; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChains; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainsBuilder; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainKey; import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class holds all RPCs methods for SFC Provider. * * <p> * @author Reinaldo Penno (rapenno@gmail.com) * @author Konstantin Blagov (blagov.sk@hotmail.com) * @version 0.1 * @since 2014-06-30 */ public class SfcProviderRpc implements ServiceFunctionService, ServiceFunctionChainService, RenderedServicePathService, ServicePathIdService { private static final Logger LOG = LoggerFactory.getLogger(SfcProviderRpc.class); private static DataBroker dataBroker = null; public static SfcProviderRpc getSfcProviderRpc() { return new SfcProviderRpc(); } // blueprint setter public void setDataProvider(DataBroker broker) { dataBroker = broker; } // aux setter just for test public static void setDataProviderAux(DataBroker broker) { dataBroker = broker; } @Override public Future<RpcResult<Void>> deleteAllServiceFunction() { return null; } @Override public Future<RpcResult<Void>> deleteServiceFunction(DeleteServiceFunctionInput input) { return null; } @Override public Future<RpcResult<Void>> putServiceFunction(PutServiceFunctionInput input) { printTraceStart(LOG); LOG.info("\n####### Input: " + input); if (dataBroker == null) { return Futures.immediateFuture( RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, "No data provider.").build()); } // Data PLane Locator List<SfDataPlaneLocator> sfDataPlaneLocatorList = input.getSfDataPlaneLocator(); ServiceFunctionBuilder sfbuilder = new ServiceFunctionBuilder(); ServiceFunctionKey sfkey = new ServiceFunctionKey(input.getName()); ServiceFunction sf = sfbuilder.setName(input.getName()).setType(input.getType()).setKey(sfkey) .setIpMgmtAddress(input.getIpMgmtAddress()).setSfDataPlaneLocator(sfDataPlaneLocatorList).build(); InstanceIdentifier<ServiceFunction> sfEntryIID = InstanceIdentifier.builder(ServiceFunctions.class) .child(ServiceFunction.class, sf.getKey()).build(); WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction(); writeTx.merge(LogicalDatastoreType.CONFIGURATION, sfEntryIID, sf, true); printTraceStop(LOG); return Futures.transform(writeTx.submit(), (Function<Void, RpcResult<Void>>) input1 -> RpcResultBuilder.<Void>success().build()); } @Override public Future<RpcResult<ReadServiceFunctionOutput>> readServiceFunction(ReadServiceFunctionInput input) { printTraceStart(LOG); LOG.info("Input: " + input); if (dataBroker != null) { ServiceFunctionKey sfkey = new ServiceFunctionKey(new SfName(input.getName())); InstanceIdentifier<ServiceFunction> sfIID; sfIID = InstanceIdentifier.builder(ServiceFunctions.class).child(ServiceFunction.class, sfkey).build(); ReadOnlyTransaction readTx = dataBroker.newReadOnlyTransaction(); Optional<ServiceFunction> dataObject = null; try { dataObject = readTx.read(LogicalDatastoreType.CONFIGURATION, sfIID).get(); } catch (InterruptedException | ExecutionException e) { LOG.debug("Failed to readServiceFunction : {}", e.getMessage()); } if (dataObject != null && dataObject.isPresent()) { ServiceFunction serviceFunction = dataObject.get(); LOG.debug("readServiceFunction Success: {}", serviceFunction.getName()); ReadServiceFunctionOutput readServiceFunctionOutput = null; ReadServiceFunctionOutputBuilder outputBuilder = new ReadServiceFunctionOutputBuilder(); outputBuilder.setName(serviceFunction.getName()).setType(serviceFunction.getType()) .setIpMgmtAddress(serviceFunction.getIpMgmtAddress()) .setSfDataPlaneLocator(serviceFunction.getSfDataPlaneLocator()); readServiceFunctionOutput = outputBuilder.build(); printTraceStop(LOG); return Futures.immediateFuture(Rpcs.<ReadServiceFunctionOutput>getRpcResult(true, readServiceFunctionOutput, Collections.<RpcError>emptySet())); } printTraceStop(LOG); return Futures.immediateFuture( Rpcs.<ReadServiceFunctionOutput>getRpcResult(true, null, Collections.<RpcError>emptySet())); } else { LOG.warn("\n####### Data Provider is NULL : {}", Thread.currentThread().getStackTrace()[1]); printTraceStop(LOG); return Futures.immediateFuture( Rpcs.<ReadServiceFunctionOutput>getRpcResult(true, null, Collections.<RpcError>emptySet())); } } @Override public Future<RpcResult<InstantiateServiceFunctionChainOutput>> instantiateServiceFunctionChain( InstantiateServiceFunctionChainInput input) { return null; } @Override public Future<RpcResult<Void>> putServiceFunctionChains(PutServiceFunctionChainsInput input) { printTraceStart(LOG); ServiceFunctionChainsBuilder serviceFunctionChainsBuilder = new ServiceFunctionChainsBuilder(); serviceFunctionChainsBuilder = serviceFunctionChainsBuilder .setServiceFunctionChain(input.getServiceFunctionChain()); ServiceFunctionChains sfcs = serviceFunctionChainsBuilder.build(); if (!SfcDataStoreAPI.writeMergeTransactionAPI(SfcInstanceIdentifiers.SFC_IID, sfcs, LogicalDatastoreType.CONFIGURATION)) { LOG.error("Failed to create service function chain: {}", input.getServiceFunctionChain().toString()); } return Futures.immediateFuture(Rpcs.<Void>getRpcResult(true, Collections.<RpcError>emptySet())); } @SuppressWarnings("unused") private ServiceFunctionChain findServiceFunctionChain(SfcName name) { ServiceFunctionChainKey key = new ServiceFunctionChainKey(name); InstanceIdentifier<ServiceFunctionChain> serviceFunctionChainInstanceIdentifier = InstanceIdentifier .builder(ServiceFunctionChains.class).child(ServiceFunctionChain.class, key).build(); ServiceFunctionChain serviceFunctionChain = SfcDataStoreAPI .readTransactionAPI(serviceFunctionChainInstanceIdentifier, LogicalDatastoreType.CONFIGURATION); if (serviceFunctionChain == null) { LOG.error("Failed to find Service Function Chain: {}", name); } return serviceFunctionChain; } @Override public Future<RpcResult<CreateRenderedPathOutput>> createRenderedPath( CreateRenderedPathInput createRenderedPathInput) { ServiceFunctionPath createdServiceFunctionPath; RenderedServicePath renderedServicePath; RenderedServicePath revRenderedServicePath; CreateRenderedPathOutputBuilder createRenderedPathOutputBuilder = new CreateRenderedPathOutputBuilder(); RpcResult<CreateRenderedPathOutput> rpcResult; RspName retRspName = null; createdServiceFunctionPath = SfcProviderServicePathAPI .readServiceFunctionPath(new SfpName(createRenderedPathInput.getParentServiceFunctionPath())); if (createdServiceFunctionPath != null) { renderedServicePath = SfcProviderRenderedPathAPI .createRenderedServicePathAndState(createdServiceFunctionPath, createRenderedPathInput); if (renderedServicePath != null) { retRspName = renderedServicePath.getName(); createRenderedPathOutputBuilder.setName(retRspName.getValue()); rpcResult = RpcResultBuilder.success(createRenderedPathOutputBuilder.build()).build(); if (SfcProviderRenderedPathAPI.isChainSymmetric(createdServiceFunctionPath, renderedServicePath)) { revRenderedServicePath = SfcProviderRenderedPathAPI .createSymmetricRenderedServicePathAndState(renderedServicePath); if (revRenderedServicePath == null) { LOG.error("Failed to create symmetric service path: {}"); } else { SfcProviderRenderedPathAPI.setSymmetricPathId(renderedServicePath, revRenderedServicePath.getPathId()); } } } else { rpcResult = RpcResultBuilder.<CreateRenderedPathOutput>failed() .withError(ErrorType.APPLICATION, "Failed to create RSP").build(); } } else { rpcResult = RpcResultBuilder.<CreateRenderedPathOutput>failed() .withError(ErrorType.APPLICATION, "Service Function Path does not exist").build(); } return Futures.immediateFuture(rpcResult); } /** * When a RSP is deleted, it has to be removed from: SFF, SF and RSP * operational state. * * <p> * @param rspName * RspName object with the Rendered Service Path * @return true if all path was deleted, false otherwise. */ private boolean deleteRenderedPathWithRspName(RspName rspName) { boolean ret = true; ret = SfcProviderServiceForwarderAPI.deletePathFromServiceForwarderState(rspName); ret = ret && SfcProviderServiceFunctionAPI.deleteRspFromServiceFunctionState(rspName); ret = ret && SfcProviderRenderedPathAPI.deleteRenderedServicePath(rspName); return ret; } /** * Remove RSP from all the operational state. * * <p> * @param input * schema path * <i>rendered-service-path/delete-rendered-path/input</i> * @return RPC output */ @Override public Future<RpcResult<DeleteRenderedPathOutput>> deleteRenderedPath(DeleteRenderedPathInput input) { boolean ret = true; RpcResultBuilder<DeleteRenderedPathOutput> rpcResultBuilder; RspName rspName = new RspName(input.getName()); RspName reverseRspName = SfcProviderRenderedPathAPI.getReversedRspName(rspName); if (reverseRspName != null) { // The RSP has a symmetric ("Reverse") Path ret = ret && this.deleteRenderedPathWithRspName(reverseRspName); } ret = ret && this.deleteRenderedPathWithRspName(rspName); DeleteRenderedPathOutputBuilder deleteRenderedPathOutputBuilder = new DeleteRenderedPathOutputBuilder(); deleteRenderedPathOutputBuilder.setResult(ret); if (ret) { rpcResultBuilder = RpcResultBuilder.success(deleteRenderedPathOutputBuilder.build()); } else { String message = "Error Deleting Rendered Service Path: " + input.getName(); rpcResultBuilder = RpcResultBuilder.<DeleteRenderedPathOutput>failed().withError(ErrorType.APPLICATION, message); } return Futures.immediateFuture(rpcResultBuilder.build()); } /** * This method gets all necessary information for a system to construct a * NSH header and associated overlay packet to target the first service hop * of a Rendered Service Path. * * <p> * @param input * RPC input including a Rendered Service Path name * @return RPC output including a renderedServicePathFirstHop. */ @Override public Future<RpcResult<ReadRenderedServicePathFirstHopOutput>> readRenderedServicePathFirstHop( ReadRenderedServicePathFirstHopInput input) { RenderedServicePathFirstHop renderedServicePathFirstHop = null; RpcResultBuilder<ReadRenderedServicePathFirstHopOutput> rpcResultBuilder; renderedServicePathFirstHop = SfcProviderRenderedPathAPI .readRenderedServicePathFirstHop(new RspName(input.getName())); ReadRenderedServicePathFirstHopOutput renderedServicePathFirstHopOutput = null; if (renderedServicePathFirstHop != null) { ReadRenderedServicePathFirstHopOutputBuilder renderedServicePathFirstHopOutputBuilder = new ReadRenderedServicePathFirstHopOutputBuilder(); renderedServicePathFirstHopOutputBuilder.setRenderedServicePathFirstHop(renderedServicePathFirstHop); renderedServicePathFirstHopOutput = renderedServicePathFirstHopOutputBuilder.build(); rpcResultBuilder = RpcResultBuilder.success(renderedServicePathFirstHopOutput); } else { String message = "Error Reading RSP First Hop from DataStore: " + input.getName(); rpcResultBuilder = RpcResultBuilder.<ReadRenderedServicePathFirstHopOutput>failed() .withError(ErrorType.APPLICATION, message); } return Futures.immediateFuture(rpcResultBuilder.build()); } /** * This method reads all the necessary information for the first hop of a * Rendered Service Path by ServiceFunctionTypeIdentity list. * * <p> * @param input * RPC input including a ServiceFunctionTypeIdentity list * @return RPC output including a renderedServicePathFirstHop. */ @Override public Future<RpcResult<ReadRspFirstHopBySftListOutput>> readRspFirstHopBySftList( ReadRspFirstHopBySftListInput input) { RenderedServicePathFirstHop renderedServicePathFirstHop = null; renderedServicePathFirstHop = SfcProviderRenderedPathAPI.readRspFirstHopBySftList(input.getSfst(), input.getSftList()); ReadRspFirstHopBySftListOutput readRspFirstHopBySftListOutput = null; if (renderedServicePathFirstHop != null) { ReadRspFirstHopBySftListOutputBuilder readRspFirstHopBySftListOutputBuilder = new ReadRspFirstHopBySftListOutputBuilder(); readRspFirstHopBySftListOutputBuilder.setRenderedServicePathFirstHop(renderedServicePathFirstHop); readRspFirstHopBySftListOutput = readRspFirstHopBySftListOutputBuilder.build(); } RpcResultBuilder<ReadRspFirstHopBySftListOutput> rpcResultBuilder = RpcResultBuilder .success(readRspFirstHopBySftListOutput); return Futures.immediateFuture(rpcResultBuilder.build()); } @Override public Future<RpcResult<TraceRenderedServicePathOutput>> traceRenderedServicePath( TraceRenderedServicePathInput input) { return null; } @Override public Future<RpcResult<ReservePathIdRangeOutput>> reservePathIdRange(ReservePathIdRangeInput input) { return null; } @Override public Future<RpcResult<ReadPathIdOutput>> readPathId(ReadPathIdInput input) { return null; } @Override public Future<RpcResult<AllocatePathIdOutput>> allocatePathId(AllocatePathIdInput input) { return null; } @Override public Future<RpcResult<DeletePathIdOutput>> deletePathId(DeletePathIdInput input) { return null; } @Override public Future<RpcResult<SetGenerationAlgorithmOutput>> setGenerationAlgorithm( SetGenerationAlgorithmInput input) { boolean result = SfcServicePathId.setGenerationAlgorithm(input.getGenerationAlgorithm()); SetGenerationAlgorithmOutputBuilder setGenerationAlgorithmOutputBuilder = new SetGenerationAlgorithmOutputBuilder(); setGenerationAlgorithmOutputBuilder.setResult(result); RpcResultBuilder<SetGenerationAlgorithmOutput> rpcResultBuilder = RpcResultBuilder .success(setGenerationAlgorithmOutputBuilder.build()); return Futures.immediateFuture(rpcResultBuilder.build()); } }