d2d98710f7612619e869763e19f38de5686f2e02
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / servicebindings / flowbased / listeners / FlowBasedServicesInterfaceStateListener.java
1 /*
2  * Copyright (c) 2016, 2018 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.genius.interfacemanager.servicebindings.flowbased.listeners;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
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;
45
46 @Singleton
47 public class FlowBasedServicesInterfaceStateListener extends AbstractClusteredSyncDataTreeChangeListener<Interface>
48         implements RecoverableListener {
49
50     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesInterfaceStateListener.class);
51
52     private final ManagedNewTransactionRunner txRunner;
53     private final EntityOwnershipUtils entityOwnershipUtils;
54     private final JobCoordinator coordinator;
55     private final FlowBasedServicesStateRendererFactoryResolver flowBasedServicesStateRendererFactoryResolver;
56
57     @Inject
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;
72         registerListener();
73         serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(), this);
74     }
75
76     @Override
77     public void remove(@NonNull final InstanceIdentifier<Interface> instanceIdentifier,
78                        @NonNull final Interface interfaceStateOld) {
79         //Do Nothing
80     }
81
82     @Override
83     public void update(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface interfaceStateOld,
84                        @NonNull Interface interfaceStateNew) {
85         // Do nothing
86     }
87
88     @Override
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)) {
93             return;
94         }
95
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));
103     }
104
105     @Override
106     public void registerListener() {
107         super.register();
108     }
109
110     @Override
111     public void deregisterListener() {
112         close();
113     }
114
115     private class RendererStateInterfaceBindWorker implements Callable<List<? extends ListenableFuture<?>>> {
116         Interface iface;
117         FlowBasedServicesStateAddable flowBasedServicesStateAddable;
118         Class<? extends ServiceModeBase> serviceMode;
119
120         RendererStateInterfaceBindWorker(FlowBasedServicesStateAddable flowBasedServicesStateAddable, Interface iface,
121                                          Class<? extends ServiceModeBase> serviceMode) {
122             this.flowBasedServicesStateAddable = flowBasedServicesStateAddable;
123             this.iface = iface;
124             this.serviceMode = serviceMode;
125         }
126
127         @Override
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);
136                         }
137
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);
142                         }
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);
148                         });
149                     }, MoreExecutors.directExecutor()));
150             return futures;
151         }
152     }
153 }