/* * Copyright (c) 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.controller.clustering.it.provider; import com.google.common.util.concurrent.Futures; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Future; import org.opendaylight.controller.clustering.it.provider.impl.FlappingSingletonService; import org.opendaylight.controller.clustering.it.provider.impl.GetConstantService; import org.opendaylight.controller.clustering.it.provider.impl.RoutedGetConstantService; import org.opendaylight.controller.clustering.it.provider.impl.SingletonGetConstantService; import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec; import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodecFactory; import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration; import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer; import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.AddShardReplicaInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.BecomeModuleLeaderInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.BecomePrefixLeaderInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.IsClientAbortedOutput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.OdlMdsalLowlevelControlService; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.ProduceTransactionsInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.PublishNotificationsInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterBoundConstantInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterConstantInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterDefaultConstantInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RegisterSingletonConstantInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.RemoveShardReplicaInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.SubscribeYnlInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterBoundConstantInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterFlappingSingletonOutput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnregisterFlappingSingletonOutputBuilder; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDdtlOutput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeDtclOutput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeYnlInput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.UnsubscribeYnlOutput; import org.opendaylight.yang.gen.v1.tag.opendaylight.org._2017.controller.yang.lowlevel.control.rev170215.WriteTransactionsInput; import org.opendaylight.yangtools.concepts.ListenerRegistration; 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.opendaylight.yangtools.yang.model.api.SchemaContextListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MdsalLowLevelTestProvider implements OdlMdsalLowlevelControlService { private static final Logger LOG = LoggerFactory.getLogger(MdsalLowLevelTestProvider.class); private final RpcProviderRegistry rpcRegistry; private final BindingAwareBroker.RpcRegistration registration; private final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer; private final SchemaService schemaService; private final ClusterSingletonServiceProvider singletonService; private final DOMRpcProviderService domRpcService; private Map, DOMRpcImplementationRegistration> routedRegistrations = new HashMap<>(); private DOMRpcImplementationRegistration globalGetConstantRegistration = null; private ClusterSingletonServiceRegistration getSingletonConstantRegistration; private FlappingSingletonService flappingSingletonService; public MdsalLowLevelTestProvider(final RpcProviderRegistry rpcRegistry, final DOMRpcProviderService domRpcService, final ClusterSingletonServiceProvider singletonService, final SchemaService schemaService, final BindingNormalizedNodeSerializer bindingNormalizedNodeSerializer) { this.rpcRegistry = rpcRegistry; this.domRpcService = domRpcService; this.singletonService = singletonService; this.schemaService = schemaService; this.bindingNormalizedNodeSerializer = bindingNormalizedNodeSerializer; registration = rpcRegistry.addRpcImplementation(OdlMdsalLowlevelControlService.class, this); } @Override public Future> unregisterSingletonConstant() { LOG.debug("unregister-singleton-constant"); if (getSingletonConstantRegistration == null) { LOG.debug("No get-singleton-constant registration present."); final RpcError rpcError = RpcResultBuilder .newError(ErrorType.APPLICATION, "missing-registration", "No get-singleton-constant rpc registration present."); final RpcResult result = RpcResultBuilder.failed().withRpcError(rpcError).build(); return Futures.immediateFuture(result); } try { getSingletonConstantRegistration.close(); getSingletonConstantRegistration = null; return Futures.immediateFuture(RpcResultBuilder.success().build()); } catch (final Exception e) { LOG.debug("There was a problem closing the singleton constant service", e); final RpcError rpcError = RpcResultBuilder .newError(ErrorType.APPLICATION, "error-closing", "There was a problem closing get-singleton-constant"); final RpcResult result = RpcResultBuilder.failed().withRpcError(rpcError).build(); return Futures.immediateFuture(result); } } @Override public Future> publishNotifications(PublishNotificationsInput input) { return null; } @Override public Future> subscribeDtcl() { return null; } @Override public Future> writeTransactions(WriteTransactionsInput input) { return null; } @Override public Future> isClientAborted() { return null; } @Override public Future> becomeModuleLeader(BecomeModuleLeaderInput input) { return null; } @Override public Future> removeShardReplica(RemoveShardReplicaInput input) { return null; } @Override public Future> subscribeYnl(SubscribeYnlInput input) { return null; } @Override public Future> becomePrefixLeader(BecomePrefixLeaderInput input) { return null; } @Override public Future> unregisterBoundConstant(final UnregisterBoundConstantInput input) { LOG.debug("unregister-bound-constant, {}", input); final DOMRpcImplementationRegistration registration = routedRegistrations.remove(input.getContext()); if (registration == null) { LOG.debug("No get-contexted-constant registration for context: {}", input.getContext()); final RpcError rpcError = RpcResultBuilder .newError(ErrorType.APPLICATION, "missing-registration", "No get-constant rpc registration present."); final RpcResult result = RpcResultBuilder.failed().withRpcError(rpcError).build(); return Futures.immediateFuture(result); } registration.close(); return Futures.immediateFuture(RpcResultBuilder.success().build()); } @Override public Future> registerSingletonConstant(final RegisterSingletonConstantInput input) { LOG.debug("Received register-singleton-constant rpc, input: {}", input); if (input.getConstant() == null) { final RpcError error = RpcResultBuilder.newError( ErrorType.RPC, "Invalid input.", "Constant value is null"); return Futures.immediateFuture(RpcResultBuilder.failed().withRpcError(error).build()); } getSingletonConstantRegistration = SingletonGetConstantService.registerNew(singletonService, domRpcService, input.getConstant()); return Futures.immediateFuture(RpcResultBuilder.success().build()); } @Override public Future> registerDefaultConstant(RegisterDefaultConstantInput input) { return null; } @Override public Future> unregisterConstant() { if (globalGetConstantRegistration == null) { final RpcError rpcError = RpcResultBuilder .newError(ErrorType.APPLICATION, "missing-registration", "No get-constant rpc registration present."); final RpcResult result = RpcResultBuilder.failed().withRpcError(rpcError).build(); return Futures.immediateFuture(result); } globalGetConstantRegistration.close(); globalGetConstantRegistration = null; return Futures.immediateFuture(RpcResultBuilder.success().build()); } @Override public Future> unregisterFlappingSingleton() { LOG.debug("unregister-flapping-singleton received."); if (flappingSingletonService == null) { final RpcError rpcError = RpcResultBuilder .newError(ErrorType.APPLICATION, "missing-registration", "No flapping-singleton registration present."); final RpcResult result = RpcResultBuilder.failed().withRpcError(rpcError).build(); return Futures.immediateFuture(result); } final long flapCount = flappingSingletonService.setInactive(); flappingSingletonService = null; final UnregisterFlappingSingletonOutput output = new UnregisterFlappingSingletonOutputBuilder().setFlapCount(flapCount).build(); return Futures.immediateFuture(RpcResultBuilder.success(output).build()); } @Override public Future> addShardReplica(AddShardReplicaInput input) { return null; } @Override public Future> subscribeDdtl() { return null; } @Override public Future> registerBoundConstant(final RegisterBoundConstantInput input) { LOG.debug("register-bound-constant: {}", input); if (input.getContext() == null) { final RpcError error = RpcResultBuilder.newError( ErrorType.RPC, "Invalid input.", "Context value is null"); return Futures.immediateFuture(RpcResultBuilder.failed().withRpcError(error).build()); } if (input.getConstant() == null) { final RpcError error = RpcResultBuilder.newError( ErrorType.RPC, "Invalid input.", "Constant value is null"); return Futures.immediateFuture(RpcResultBuilder.failed().withRpcError(error).build()); } if (routedRegistrations.containsKey(input.getContext())) { final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.", "There is already a rpc registered for context: " + input.getContext()); return Futures.immediateFuture(RpcResultBuilder.failed().withRpcError(error).build()); } final DOMRpcImplementationRegistration registration = RoutedGetConstantService.registerNew(bindingNormalizedNodeSerializer, domRpcService, input.getConstant(), input.getContext()); routedRegistrations.put(input.getContext(), registration); return Futures.immediateFuture(RpcResultBuilder.success().build()); } @Override public Future> registerFlappingSingleton() { LOG.debug("Received register-flapping-singleton."); if (flappingSingletonService != null) { final RpcError error = RpcResultBuilder.newError( ErrorType.RPC, "Registration present.", "flappin-singleton already registered"); return Futures.immediateFuture(RpcResultBuilder.failed().withRpcError(error).build()); } flappingSingletonService = new FlappingSingletonService(singletonService); return Futures.immediateFuture(RpcResultBuilder.success().build()); } @Override public Future> unsubscribeDtcl() { return null; } @Override public Future> deconfigureIdIntsShard() { return null; } @Override public Future> unsubscribeYnl(UnsubscribeYnlInput input) { return null; } @Override public Future> produceTransactions(ProduceTransactionsInput input) { return null; } @Override public Future> registerConstant(final RegisterConstantInput input) { LOG.debug("Received register-constant rpc, input: {}", input); if (input.getConstant() == null) { final RpcError error = RpcResultBuilder.newError( ErrorType.RPC, "Invalid input.", "Constant value is null"); return Futures.immediateFuture(RpcResultBuilder.failed().withRpcError(error).build()); } if (globalGetConstantRegistration != null) { final RpcError error = RpcResultBuilder.newError(ErrorType.RPC, "Registration present.", "There is already a get-constant rpc registered."); return Futures.immediateFuture(RpcResultBuilder.failed().withRpcError(error).build()); } globalGetConstantRegistration = GetConstantService.registerNew(domRpcService, input.getConstant()); return Futures.immediateFuture(RpcResultBuilder.success().build()); } @Override public Future> unregisterDefaultConstant() { return null; } @Override public Future> unsubscribeDdtl() { return null; } }