2 * Copyright (c) 2016, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.genius.interfacemanager.servicebindings.flowbased.listeners;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.concurrent.Callable;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.apache.aries.blueprint.annotation.service.Reference;
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
24 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
25 import org.opendaylight.genius.interfacemanager.IfmConstants;
26 import org.opendaylight.genius.interfacemanager.recovery.impl.InterfaceServiceRecoveryHandler;
27 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.state.factory.FlowBasedServicesStateAddable;
28 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.state.factory.FlowBasedServicesStateRendererFactoryResolver;
29 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
30 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
31 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
32 import org.opendaylight.mdsal.binding.api.DataBroker;
33 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
34 import org.opendaylight.serviceutils.srm.RecoverableListener;
35 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
36 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredSyncDataTreeChangeListener;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Other;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
47 public class FlowBasedServicesInterfaceStateListener extends AbstractClusteredSyncDataTreeChangeListener<Interface>
48 implements RecoverableListener {
50 private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesInterfaceStateListener.class);
52 private final ManagedNewTransactionRunner txRunner;
53 private final EntityOwnershipUtils entityOwnershipUtils;
54 private final JobCoordinator coordinator;
55 private final FlowBasedServicesStateRendererFactoryResolver flowBasedServicesStateRendererFactoryResolver;
58 public FlowBasedServicesInterfaceStateListener(@Reference final DataBroker dataBroker,
59 final EntityOwnershipUtils entityOwnershipUtils,
60 @Reference final JobCoordinator coordinator,
61 final FlowBasedServicesStateRendererFactoryResolver
62 flowBasedServicesStateRendererFactoryResolver,
63 final InterfaceServiceRecoveryHandler
64 interfaceServiceRecoveryHandler,
65 @Reference final ServiceRecoveryRegistry serviceRecoveryRegistry) {
66 super(dataBroker, LogicalDatastoreType.OPERATIONAL,
67 InstanceIdentifier.create(InterfacesState.class).child(Interface.class));
68 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
69 this.entityOwnershipUtils = entityOwnershipUtils;
70 this.coordinator = coordinator;
71 this.flowBasedServicesStateRendererFactoryResolver = flowBasedServicesStateRendererFactoryResolver;
73 serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(), this);
77 public void remove(@NonNull final InstanceIdentifier<Interface> instanceIdentifier,
78 @NonNull final Interface interfaceStateOld) {
83 public void update(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface interfaceStateOld,
84 @NonNull Interface interfaceStateNew) {
89 public void add(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface interfaceStateNew) {
90 if (Other.class.equals(interfaceStateNew.getType()) || !entityOwnershipUtils
91 .isEntityOwner(IfmConstants.INTERFACE_SERVICE_BINDING_ENTITY,
92 IfmConstants.INTERFACE_SERVICE_BINDING_ENTITY)) {
96 LOG.debug("Received interface state add event for {}", interfaceStateNew.getName());
97 FlowBasedServicesUtils.SERVICE_MODE_MAP.values().forEach(serviceMode -> coordinator
98 .enqueueJob(interfaceStateNew.getName(), new RendererStateInterfaceBindWorker(
99 flowBasedServicesStateRendererFactoryResolver
100 .getFlowBasedServicesStateRendererFactory(serviceMode)
101 .getFlowBasedServicesStateAddRenderer(), interfaceStateNew, serviceMode),
102 IfmConstants.JOB_MAX_RETRIES));
106 public void registerListener() {
111 public void deregisterListener() {
115 private class RendererStateInterfaceBindWorker implements Callable<List<? extends ListenableFuture<?>>> {
117 FlowBasedServicesStateAddable flowBasedServicesStateAddable;
118 Class<? extends ServiceModeBase> serviceMode;
120 RendererStateInterfaceBindWorker(FlowBasedServicesStateAddable flowBasedServicesStateAddable, Interface iface,
121 Class<? extends ServiceModeBase> serviceMode) {
122 this.flowBasedServicesStateAddable = flowBasedServicesStateAddable;
124 this.serviceMode = serviceMode;
128 public List<ListenableFuture<Void>> call() {
129 List<ListenableFuture<Void>> futures = new ArrayList<>();
130 futures.add(txRunner.applyWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
131 confTx -> FlowBasedServicesUtils.getServicesInfoForInterface(confTx, iface.getName(),
132 serviceMode)).transformAsync(servicesInfo -> {
133 if (servicesInfo == null) {
134 LOG.trace("service info is null for interface {}", iface.getName());
135 return Futures.immediateFuture(null);
138 List<BoundServices> allServices = new ArrayList<>(servicesInfo.getBoundServices());
139 if (allServices == null || allServices.isEmpty()) {
140 LOG.trace("bound services is empty for interface {}", iface.getName());
141 return Futures.immediateFuture(null);
143 return txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
144 // Build the service-binding state if there are services bound on this interface
145 FlowBasedServicesUtils.addBoundServicesState(operTx, iface.getName(), FlowBasedServicesUtils
146 .buildBoundServicesState(iface, serviceMode));
147 flowBasedServicesStateAddable.bindServices(futures, iface, allServices, serviceMode);
149 }, MoreExecutors.directExecutor()));