888d4795c3be1218599a72027abd4114e108414b
[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.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;
46
47 @Singleton
48 public class FlowBasedServicesInterfaceStateListener extends AbstractClusteredSyncDataTreeChangeListener<Interface>
49         implements RecoverableListener {
50
51     private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesInterfaceStateListener.class);
52
53     private final ManagedNewTransactionRunner txRunner;
54     private final EntityOwnershipUtils entityOwnershipUtils;
55     private final JobCoordinator coordinator;
56     private final FlowBasedServicesStateRendererFactoryResolver flowBasedServicesStateRendererFactoryResolver;
57
58     @Inject
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;
74         registerListener();
75         serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(), this);
76     }
77
78     @Override
79     public void remove(@NonNull final InstanceIdentifier<Interface> instanceIdentifier,
80                        @NonNull final Interface interfaceStateOld) {
81         //Do Nothing
82     }
83
84     @Override
85     public void update(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface interfaceStateOld,
86                        @NonNull Interface interfaceStateNew) {
87         // Do nothing
88     }
89
90     @Override
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)) {
95             return;
96         }
97
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));
105     }
106
107     @Override
108     public void registerListener() {
109         super.register();
110     }
111
112     @Override
113     public void deregisterListener() {
114         close();
115     }
116
117     private class RendererStateInterfaceBindWorker implements Callable<List<? extends ListenableFuture<?>>> {
118         Interface iface;
119         FlowBasedServicesStateAddable flowBasedServicesStateAddable;
120         Class<? extends ServiceModeBase> serviceMode;
121
122         RendererStateInterfaceBindWorker(FlowBasedServicesStateAddable flowBasedServicesStateAddable, Interface iface,
123                                          Class<? extends ServiceModeBase> serviceMode) {
124             this.flowBasedServicesStateAddable = flowBasedServicesStateAddable;
125             this.iface = iface;
126             this.serviceMode = serviceMode;
127         }
128
129         @Override
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);
138                         }
139
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);
144                         }
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);
150                         });
151                     }, MoreExecutors.directExecutor()));
152             return futures;
153         }
154     }
155 }