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.idmanager.rev160406.IdManagerService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 public class FlowBasedServicesInterfaceStateListener extends AbstractClusteredSyncDataTreeChangeListener<Interface>
49 implements RecoverableListener {
51 private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesInterfaceStateListener.class);
53 private final ManagedNewTransactionRunner txRunner;
54 private final EntityOwnershipUtils entityOwnershipUtils;
55 private final JobCoordinator coordinator;
56 private final FlowBasedServicesStateRendererFactoryResolver flowBasedServicesStateRendererFactoryResolver;
59 public FlowBasedServicesInterfaceStateListener(@Reference final DataBroker dataBroker,
60 final EntityOwnershipUtils entityOwnershipUtils,
61 @Reference final JobCoordinator coordinator,
62 final FlowBasedServicesStateRendererFactoryResolver
63 flowBasedServicesStateRendererFactoryResolver,
64 final InterfaceServiceRecoveryHandler
65 interfaceServiceRecoveryHandler,
66 @Reference final ServiceRecoveryRegistry serviceRecoveryRegistry,
67 final IdManagerService idManagerService) {
68 super(dataBroker, LogicalDatastoreType.OPERATIONAL,
69 InstanceIdentifier.create(InterfacesState.class).child(Interface.class));
70 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
71 this.entityOwnershipUtils = entityOwnershipUtils;
72 this.coordinator = coordinator;
73 this.flowBasedServicesStateRendererFactoryResolver = flowBasedServicesStateRendererFactoryResolver;
75 serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(), this);
79 public void remove(@NonNull final InstanceIdentifier<Interface> instanceIdentifier,
80 @NonNull final Interface interfaceStateOld) {
85 public void update(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface interfaceStateOld,
86 @NonNull Interface interfaceStateNew) {
91 public void add(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface interfaceStateNew) {
92 if (Other.class.equals(interfaceStateNew.getType()) || !entityOwnershipUtils
93 .isEntityOwner(IfmConstants.INTERFACE_SERVICE_BINDING_ENTITY,
94 IfmConstants.INTERFACE_SERVICE_BINDING_ENTITY)) {
98 LOG.debug("Received interface state add event for {}", interfaceStateNew.getName());
99 FlowBasedServicesUtils.SERVICE_MODE_MAP.values().forEach(serviceMode -> coordinator
100 .enqueueJob(interfaceStateNew.getName(), new RendererStateInterfaceBindWorker(
101 flowBasedServicesStateRendererFactoryResolver
102 .getFlowBasedServicesStateRendererFactory(serviceMode)
103 .getFlowBasedServicesStateAddRenderer(), interfaceStateNew, serviceMode),
104 IfmConstants.JOB_MAX_RETRIES));
108 public void registerListener() {
113 public void deregisterListener() {
117 private class RendererStateInterfaceBindWorker implements Callable<List<? extends ListenableFuture<?>>> {
119 FlowBasedServicesStateAddable flowBasedServicesStateAddable;
120 Class<? extends ServiceModeBase> serviceMode;
122 RendererStateInterfaceBindWorker(FlowBasedServicesStateAddable flowBasedServicesStateAddable, Interface iface,
123 Class<? extends ServiceModeBase> serviceMode) {
124 this.flowBasedServicesStateAddable = flowBasedServicesStateAddable;
126 this.serviceMode = serviceMode;
130 public List<ListenableFuture<Void>> call() {
131 List<ListenableFuture<Void>> futures = new ArrayList<>();
132 futures.add(txRunner.applyWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
133 confTx -> FlowBasedServicesUtils.getServicesInfoForInterface(confTx, iface.getName(),
134 serviceMode)).transformAsync(servicesInfo -> {
135 if (servicesInfo == null) {
136 LOG.trace("service info is null for interface {}", iface.getName());
137 return Futures.immediateFuture(null);
140 List<BoundServices> allServices = new ArrayList<>(servicesInfo.getBoundServices().values());
141 if (allServices == null || allServices.isEmpty()) {
142 LOG.trace("bound services is empty for interface {}", iface.getName());
143 return Futures.immediateFuture(null);
145 return txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, operTx -> {
146 // Build the service-binding state if there are services bound on this interface
147 FlowBasedServicesUtils.addBoundServicesState(operTx, iface.getName(), FlowBasedServicesUtils
148 .buildBoundServicesState(iface, serviceMode));
149 flowBasedServicesStateAddable.bindServices(futures, iface, allServices, serviceMode);
151 }, MoreExecutors.directExecutor()));