6c26d9e6cbcd65fbbc54c1f5c57db8e431d7a9f9
[netvirt.git] / qosservice / impl / src / main / java / org / opendaylight / netvirt / qosservice / QosPolicyChangeListener.java
1 /*
2  * Copyright (c) 2017 Intel Corporation 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.netvirt.qosservice;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import javax.annotation.PreDestroy;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
22 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
23 import org.opendaylight.infrautils.utils.concurrent.Executors;
24 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
25 import org.opendaylight.mdsal.binding.api.DataBroker;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.netvirt.qosservice.recovery.QosServiceRecoveryHandler;
28 import org.opendaylight.serviceutils.srm.RecoverableListener;
29 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
30 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredAsyncDataTreeChangeListener;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosPolicies;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosRuleTypes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.QosRuleTypesBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.QosPolicy;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.BandwidthLimitRules;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.policies.qos.policy.DscpmarkingRules;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.rule.types.RuleTypes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.qos.rev160613.qos.attributes.qos.rule.types.RuleTypesBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 @Singleton
48 public class QosPolicyChangeListener extends AbstractClusteredAsyncDataTreeChangeListener<QosPolicy>
49         implements RecoverableListener {
50     private static final Logger LOG = LoggerFactory.getLogger(QosPolicyChangeListener.class);
51     private final DataBroker dataBroker;
52     private final ManagedNewTransactionRunner txRunner;
53     private final QosNeutronUtils qosNeutronUtils;
54     private final JobCoordinator jobCoordinator;
55
56     @Inject
57     public QosPolicyChangeListener(final DataBroker dataBroker,
58                                    final QosNeutronUtils qosNeutronUtils, final JobCoordinator jobCoordinator,
59                                    final ServiceRecoveryRegistry serviceRecoveryRegistry,
60                                    final QosServiceRecoveryHandler qosServiceRecoveryHandler) {
61         super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Neutron.class)
62                 .child(QosPolicies.class).child(QosPolicy.class),
63                 Executors.newListeningSingleThreadExecutor("QosPolicyChangeListener", LOG));
64         this.dataBroker = dataBroker;
65         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
66         this.qosNeutronUtils = qosNeutronUtils;
67         this.jobCoordinator = jobCoordinator;
68         serviceRecoveryRegistry.addRecoverableListener(qosServiceRecoveryHandler.buildServiceRegistryKey(),
69                 this);
70         LOG.trace("{} created",  getClass().getSimpleName());
71         init();
72     }
73
74     public void init() {
75         supportedQoSRuleTypes();
76         LOG.trace("{} init and registerListener done", getClass().getSimpleName());
77     }
78
79     @Override
80     @PreDestroy
81     public void close() {
82         super.close();
83         Executors.shutdownAndAwaitTermination(getExecutorService());
84     }
85
86     @Override
87     public void registerListener() {
88         super.register();
89     }
90
91     @Override
92     public void deregisterListener() {
93         super.close();
94     }
95 /*
96     @Override
97     public void onDataTreeChanged(Collection<DataTreeModification<QosPolicy>> changes) {
98         handleQosPolicyChanges(changes);
99         handleBandwidthLimitRulesChanges(changes);
100         handleDscpMarkingRulesChanges(changes);
101     }
102
103     private void handleQosPolicyChanges(Collection<DataTreeModification<QosPolicy>> changes) {
104         Map<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyOriginalMap =
105                 ChangeUtils.extractOriginal(changes, QosPolicy.class);
106
107         for (Entry<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyMapEntry :
108                 ChangeUtils.extractCreated(changes, QosPolicy.class).entrySet()) {
109             add(qosPolicyMapEntry.getKey(), qosPolicyMapEntry.getValue());
110         }
111         for (Entry<InstanceIdentifier<QosPolicy>, QosPolicy> qosPolicyMapEntry :
112                 ChangeUtils.extractUpdated(changes, QosPolicy.class).entrySet()) {
113             update(qosPolicyMapEntry.getKey(), qosPolicyOriginalMap.get(qosPolicyMapEntry.getKey()),
114                     qosPolicyMapEntry.getValue());
115         }
116         for (InstanceIdentifier<QosPolicy> qosPolicyIid : ChangeUtils.extractRemoved(changes, QosPolicy.class)) {
117             remove(qosPolicyIid, qosPolicyOriginalMap.get(qosPolicyIid));
118         }
119     }
120
121     private void handleBandwidthLimitRulesChanges(Collection<DataTreeModification<QosPolicy>> changes) {
122         Map<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitOriginalMap =
123                 ChangeUtils.extractOriginal(changes, BandwidthLimitRules.class);
124
125         for (Entry<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitMapEntry :
126                 ChangeUtils.extractCreated(changes, BandwidthLimitRules.class).entrySet()) {
127             add(bwLimitMapEntry.getKey(), bwLimitMapEntry.getValue());
128         }
129         for (Entry<InstanceIdentifier<BandwidthLimitRules>, BandwidthLimitRules> bwLimitMapEntry :
130                 ChangeUtils.extractUpdated(changes, BandwidthLimitRules.class).entrySet()) {
131             update(bwLimitMapEntry.getKey(), bwLimitOriginalMap.get(bwLimitMapEntry.getKey()),
132                     bwLimitMapEntry.getValue());
133         }
134         for (InstanceIdentifier<BandwidthLimitRules> bwLimitIid :
135                 ChangeUtils.extractRemoved(changes, BandwidthLimitRules.class)) {
136             remove(bwLimitIid, bwLimitOriginalMap.get(bwLimitIid));
137         }
138     }
139
140     private void handleDscpMarkingRulesChanges(Collection<DataTreeModification<QosPolicy>> changes) {
141         Map<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkOriginalMap =
142                 ChangeUtils.extractOriginal(changes, DscpmarkingRules.class);
143
144         for (Entry<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkMapEntry :
145                 ChangeUtils.extractCreated(changes, DscpmarkingRules.class).entrySet()) {
146             add(dscpMarkMapEntry.getKey(), dscpMarkMapEntry.getValue());
147         }
148         for (Entry<InstanceIdentifier<DscpmarkingRules>, DscpmarkingRules> dscpMarkMapEntry :
149                 ChangeUtils.extractUpdated(changes, DscpmarkingRules.class).entrySet()) {
150             update(dscpMarkMapEntry.getKey(), dscpMarkOriginalMap.get(dscpMarkMapEntry.getKey()),
151                     dscpMarkMapEntry.getValue());
152         }
153         for (InstanceIdentifier<DscpmarkingRules> dscpMarkIid :
154                 ChangeUtils.extractRemoved(changes, DscpmarkingRules.class)) {
155             remove(dscpMarkIid, dscpMarkOriginalMap.get(dscpMarkIid));
156         }
157     }*/
158
159     @Override
160     public void add(InstanceIdentifier<QosPolicy> identifier, QosPolicy input) {
161         LOG.debug("Adding  QosPolicy : key: {}, value={}",
162                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(),input);
163         qosNeutronUtils.addToQosPolicyCache(input);
164     }
165
166     protected void add(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules input) {
167         LOG.debug("Adding BandwidthlimitRules : key: {}, value={}",
168                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
169
170         Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
171         for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
172             qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
173         }
174
175         for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
176             jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
177                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
178                         tx -> qosNeutronUtils.setPortBandwidthLimits(port, input, tx))));
179         }
180     }
181
182 /*    private void add(InstanceIdentifier<DscpmarkingRules> identifier, DscpmarkingRules input) {
183         LOG.debug("Adding DscpMarkingRules : key: {}, value={}",
184                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
185
186         Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
187
188         for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
189             qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
190         }
191
192         for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
193             jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
194                 qosNeutronUtils.setPortDscpMarking(port, input);
195                 return Collections.emptyList();
196             });
197         }
198     }*/
199
200     @Override
201     public void remove(InstanceIdentifier<QosPolicy> identifier, QosPolicy input) {
202         LOG.debug("Removing QosPolicy : key: {}, value={}",
203                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
204         qosNeutronUtils.removeFromQosPolicyCache(input);
205     }
206
207 /*    private void remove(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules input) {
208         LOG.debug("Removing BandwidthLimitRules : key: {}, value={}",
209                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
210
211         Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
212         BandwidthLimitRulesBuilder bwLimitBuilder = new BandwidthLimitRulesBuilder();
213         BandwidthLimitRules zeroBwLimitRule =
214                 bwLimitBuilder.setMaxBurstKbps(Uint64.ZERO).setMaxKbps(Uint64.ZERO).build();
215
216         for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
217             qosNeutronUtils.handleNeutronNetworkQosBwRuleRemove(network, zeroBwLimitRule);
218         }
219
220         for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
221             jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
222                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
223                         tx -> qosNeutronUtils.setPortBandwidthLimits(port, zeroBwLimitRule, tx))));
224         }
225     }*/
226
227 /*    private void remove(InstanceIdentifier<DscpmarkingRules> identifier,DscpmarkingRules input) {
228         LOG.debug("Removing DscpMarkingRules : key: {}, value={}",
229                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), input);
230
231         Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
232
233         for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
234             qosNeutronUtils.handleNeutronNetworkQosDscpRuleRemove(network);
235         }
236
237         for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
238             jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
239                 qosNeutronUtils.unsetPortDscpMark(port);
240                 return Collections.emptyList();
241             });
242         }
243     }*/
244
245     public void reapplyPolicy(String entityid) {
246         Uuid policyUuid = Uuid.getDefaultInstance(entityid);
247         if (qosNeutronUtils.getQosPolicyMap().get(policyUuid) == null) {
248             LOG.debug("Policy with Uuid: {} does not exist", entityid);
249             return;
250         }
251
252         @NonNull List<BandwidthLimitRules> nonnullBandwidthLimitRules =
253             new ArrayList<BandwidthLimitRules>(qosNeutronUtils.getQosPolicyMap().get(policyUuid)
254                     .nonnullBandwidthLimitRules().values());
255         if (!nonnullBandwidthLimitRules.isEmpty()) {
256             BandwidthLimitRules bandwidthLimitRules = nonnullBandwidthLimitRules.get(0);
257             update(policyUuid, bandwidthLimitRules);
258         }
259
260         @NonNull List<DscpmarkingRules> nonnullDscpmarkingRules =
261             new ArrayList<DscpmarkingRules>(qosNeutronUtils.getQosPolicyMap().get(policyUuid)
262                     .nonnullDscpmarkingRules().values());
263         if (!nonnullDscpmarkingRules.isEmpty()) {
264             DscpmarkingRules dscpmarkingRules = nonnullDscpmarkingRules.get(0);
265             update(policyUuid, dscpmarkingRules);
266         }
267     }
268
269     @Override
270     public void update(InstanceIdentifier<QosPolicy> identifier, QosPolicy original, QosPolicy update) {
271         LOG.debug("Updating QosPolicy : key: {}, original value={}, update value={}",
272                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original, update);
273         qosNeutronUtils.addToQosPolicyCache(update);
274     }
275
276 /*    private void update(InstanceIdentifier<BandwidthLimitRules> identifier, BandwidthLimitRules original,
277                         BandwidthLimitRules update) {
278         LOG.debug("Updating BandwidthLimitRules : key: {}, original value={}, update value={}",
279                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original,
280                 update);
281         Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
282         update(qosUuid, update);
283     }*/
284
285     private void update(Uuid qosUuid, BandwidthLimitRules update) {
286         for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
287             qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
288         }
289
290         for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
291             jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> Collections.singletonList(
292                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
293                         tx -> qosNeutronUtils.setPortBandwidthLimits(port, update, tx))));
294         }
295     }
296
297 /*    private void update(InstanceIdentifier<DscpmarkingRules> identifier, DscpmarkingRules original,
298                         DscpmarkingRules update) {
299         LOG.debug("Updating DscpMarkingRules : key: {}, original value={}, update value={}",
300                 identifier.firstKeyOf(QosPolicy.class).getUuid().getValue(), original, update);
301         Uuid qosUuid = identifier.firstKeyOf(QosPolicy.class).getUuid();
302         update(qosUuid, update);
303     }*/
304
305     private void update(Uuid qosUuid, DscpmarkingRules update) {
306         for (Network network : qosNeutronUtils.getQosNetworks(qosUuid)) {
307             qosNeutronUtils.handleNeutronNetworkQosUpdate(network, qosUuid);
308         }
309
310         for (Port port : qosNeutronUtils.getQosPorts(qosUuid)) {
311             jobCoordinator.enqueueJob("QosPort-" + port.getUuid().getValue(), () -> {
312                 qosNeutronUtils.setPortDscpMarking(port, update);
313                 return Collections.emptyList();
314             });
315         }
316     }
317
318     private void supportedQoSRuleTypes() {
319         QosRuleTypesBuilder qrtBuilder = new QosRuleTypesBuilder();
320         List<RuleTypes> value = new ArrayList<>();
321
322         value.add(getRuleTypes("bandwidth_limit_rules"));
323         value.add(getRuleTypes("dscp_marking_rules"));
324
325         qrtBuilder.setRuleTypes(value);
326
327         ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
328             InstanceIdentifier instanceIdentifier = InstanceIdentifier.create(Neutron.class).child(QosRuleTypes.class);
329             tx.merge(instanceIdentifier, qrtBuilder.build());
330         }), LOG, "Error setting up supported QoS rule types");
331     }
332
333     private RuleTypes getRuleTypes(String ruleType) {
334         RuleTypesBuilder rtBuilder = new RuleTypesBuilder();
335         rtBuilder.setRuleType(ruleType);
336         return rtBuilder.build();
337     }
338 }