Clean up lambdas and streams
[netvirt.git] / vpnservice / policyservice / impl / src / main / java / org / opendaylight / netvirt / policyservice / listeners / PolicyProfileChangeListener.java
1 /*
2  * Copyright (c) 2017 Hewlett Packard Enterprise, Co. 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
9 package org.opendaylight.netvirt.policyservice.listeners;
10
11 import com.google.common.base.Optional;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15
16 import javax.annotation.PostConstruct;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
23 import org.opendaylight.genius.mdsalutil.NwConstants;
24 import org.opendaylight.netvirt.policyservice.PolicyAceFlowProgrammer;
25 import org.opendaylight.netvirt.policyservice.PolicyIdManager;
26 import org.opendaylight.netvirt.policyservice.PolicyRouteFlowProgrammer;
27 import org.opendaylight.netvirt.policyservice.PolicyRouteGroupProgrammer;
28 import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.PolicyProfiles;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.PolicyProfile;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.PolicyAclRule;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.policy.acl.rule.AceRule;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Listen on {@link PolicyProfile} config changes and update the policy pipeline
40  * whenever the association between policy classifier and underlay networks
41  * changes.<br>
42  * This listener will update the following flows/groups:<br>
43  * * POLICY_CLASSIFER_TABLE policy ACL flows when policy classifier
44  * added/removed<br>
45  * * POLICY_ROUTING_TABLE flows when policy classifier added/removed<br>
46  * * Policy classifier groups for each remote DPN is updated when policy
47  * classifier added/removed or when the list of associated underlay networks is
48  * updated
49  */
50 @SuppressWarnings("deprecation")
51 @Singleton
52 public class PolicyProfileChangeListener
53         extends AsyncDataTreeChangeListenerBase<PolicyProfile, PolicyProfileChangeListener> {
54     private static final Logger LOG = LoggerFactory.getLogger(PolicyProfileChangeListener.class);
55
56     private final DataBroker dataBroker;
57     private final PolicyIdManager policyIdManager;
58     private final PolicyServiceUtil policyServiceUtil;
59     private final PolicyAceFlowProgrammer aceFlowProgrammer;
60     private final PolicyRouteFlowProgrammer routeFlowProgrammer;
61     private final PolicyRouteGroupProgrammer routeGroupProgramer;
62
63     @Inject
64     public PolicyProfileChangeListener(final DataBroker dataBroker, final PolicyIdManager policyIdManager,
65             final PolicyServiceUtil policyServiceUtil, final PolicyAceFlowProgrammer aceFlowProgrammer,
66             final PolicyRouteFlowProgrammer routeFlowProgrammer, final PolicyRouteGroupProgrammer routeGroupProgramer) {
67         this.dataBroker = dataBroker;
68         this.policyIdManager = policyIdManager;
69         this.policyServiceUtil = policyServiceUtil;
70         this.aceFlowProgrammer = aceFlowProgrammer;
71         this.routeFlowProgrammer = routeFlowProgrammer;
72         this.routeGroupProgramer = routeGroupProgramer;
73     }
74
75     @Override
76     @PostConstruct
77     public void init() {
78         LOG.info("init");
79         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
80     }
81
82     @Override
83     protected InstanceIdentifier<PolicyProfile> getWildCardPath() {
84         return InstanceIdentifier.create(PolicyProfiles.class).child(PolicyProfile.class);
85     }
86
87     @Override
88     protected PolicyProfileChangeListener getDataTreeChangeListener() {
89         return this;
90     }
91
92     @Override
93     protected void remove(InstanceIdentifier<PolicyProfile> key, PolicyProfile policyProfile) {
94         String policyClassifier = policyProfile.getPolicyClassifier();
95         LOG.info("Policy profile {} removed", policyClassifier);
96         List<String> underlayNetworks = PolicyServiceUtil
97                 .getUnderlayNetworksFromPolicyRoutes(policyProfile.getPolicyRoute());
98         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(underlayNetworks, policyClassifier, false);
99         List<BigInteger> dpnIds = policyServiceUtil.getUnderlayNetworksDpns(underlayNetworks);
100         List<BigInteger> remoteDpIds = policyServiceUtil.getUnderlayNetworksRemoteDpns(underlayNetworks);
101         routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpnIds, remoteDpIds, NwConstants.DEL_FLOW);
102         updatePolicyAclRules(policyClassifier, underlayNetworks, NwConstants.DEL_FLOW);
103         routeFlowProgrammer.programPolicyClassifierFlows(policyClassifier, dpnIds, remoteDpIds, NwConstants.DEL_FLOW);
104         policyIdManager.releasePolicyClassifierId(policyClassifier);
105         releasePolicyClassifierGroupIds(policyClassifier, dpnIds);
106     }
107
108     @Override
109     protected void update(InstanceIdentifier<PolicyProfile> key, PolicyProfile origPolicyProfile,
110             PolicyProfile updatedPolicyProfile) {
111         List<String> origUnderlayNetworks = PolicyServiceUtil
112                 .getUnderlayNetworksFromPolicyRoutes(origPolicyProfile.getPolicyRoute());
113         List<String> updatedUnderlayNetworks = PolicyServiceUtil
114                 .getUnderlayNetworksFromPolicyRoutes(updatedPolicyProfile.getPolicyRoute());
115         List<String> removedUnderlayNetworks = new ArrayList<>(origUnderlayNetworks);
116         removedUnderlayNetworks.removeAll(updatedUnderlayNetworks);
117         List<String> addedUnderlayNetworks = new ArrayList<>(updatedUnderlayNetworks);
118         addedUnderlayNetworks.removeAll(origUnderlayNetworks);
119
120         String policyClassifier = updatedPolicyProfile.getPolicyClassifier();
121         LOG.info("Policy profile {} updated", policyClassifier);
122         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(removedUnderlayNetworks, policyClassifier, false);
123         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(addedUnderlayNetworks, policyClassifier, true);
124
125         // rewrite all group buckets
126         routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, origUnderlayNetworks,
127                 NwConstants.DEL_FLOW);
128         routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, updatedUnderlayNetworks,
129                 NwConstants.ADD_FLOW);
130
131         updatedUnderlayNetworks.removeAll(origUnderlayNetworks);
132         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(updatedUnderlayNetworks,
133                 updatedPolicyProfile.getPolicyClassifier(), true);
134         updatePolicyAclRules(policyClassifier, updatedUnderlayNetworks, NwConstants.ADD_FLOW);
135     }
136
137     @Override
138     protected void add(InstanceIdentifier<PolicyProfile> key, PolicyProfile policyProfile) {
139         String policyClassifier = policyProfile.getPolicyClassifier();
140         LOG.info("Policy profile {} added", policyClassifier);
141         List<String> underlayNetworks = PolicyServiceUtil
142                 .getUnderlayNetworksFromPolicyRoutes(policyProfile.getPolicyRoute());
143         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(underlayNetworks, policyClassifier, true);
144         List<BigInteger> dpnIds = policyServiceUtil.getUnderlayNetworksDpns(underlayNetworks);
145         List<BigInteger> remoteDpIds = policyServiceUtil.getUnderlayNetworksRemoteDpns(underlayNetworks);
146         routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpnIds, remoteDpIds, NwConstants.ADD_FLOW);
147         routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, underlayNetworks,
148                 NwConstants.ADD_FLOW);
149         updatePolicyAclRules(policyClassifier, underlayNetworks, NwConstants.ADD_FLOW);
150         routeFlowProgrammer.programPolicyClassifierFlows(policyClassifier, dpnIds, remoteDpIds, NwConstants.ADD_FLOW);
151     }
152
153     private void updatePolicyAclRules(String policyClassifier, List<String> underlayNetworks, int addOrRemove) {
154         List<PolicyAclRule> aclRules = policyServiceUtil.getPolicyClassifierAclRules(policyClassifier);
155         if (aclRules == null || aclRules.isEmpty()) {
156             LOG.debug("No policy ACE rules found for policy classifier {}", policyClassifier);
157             return;
158         }
159
160         List<BigInteger> dpIds = policyServiceUtil.getUnderlayNetworksDpns(underlayNetworks);
161         if (dpIds == null || dpIds.isEmpty()) {
162             LOG.debug("No DPNs found for installation of underlay networks {}", underlayNetworks);
163             return;
164         }
165
166         aclRules.forEach(aclRule -> {
167             List<AceRule> aceRules = aclRule.getAceRule();
168             if (aceRules != null) {
169                 aceRules.forEach(aceRule -> {
170                     Optional<Ace> policyAceOpt =
171                             policyServiceUtil.getPolicyAce(aclRule.getAclName(), aceRule.getRuleName());
172                     if (policyAceOpt.isPresent()) {
173                         aceFlowProgrammer.programAceFlows(policyAceOpt.get(), policyClassifier, dpIds,
174                                 addOrRemove);
175                     }
176                 });
177             } else {
178                 LOG.debug("No ACE rules found for ACL {}", aclRule.getAclName());
179             }
180         });
181     }
182
183     private void releasePolicyClassifierGroupIds(String policyClassifier, List<BigInteger> dpnIds) {
184         dpnIds.forEach(dpnId -> policyIdManager.releasePolicyClassifierGroupId(policyClassifier, dpnId));
185     }
186 }