2d0ff18f756e2df4af96324985f3ecf3c9afaac5
[groupbasedpolicy.git] / renderers / ios-xe / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ios_xe_provider / impl / util / PolicyManagerUtil.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
10
11 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
12 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Create;
13 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Delete;
14
15 import javax.annotation.Nonnull;
16 import javax.annotation.Nullable;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 import com.google.common.base.Preconditions;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
27 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyConfigurationContext;
28 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
29 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase;
30 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
31 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
32 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.PolicyActionType;
33 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroup;
34 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroupBuilder;
35 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Destination;
36 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.DestinationBuilder;
37 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Source;
38 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.SourceBuilder;
39 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
40 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicyBuilder;
41 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.TypeBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
43 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder;
44 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
45 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapBuilder;
46 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
47 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
48 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapBuilder;
49 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
50 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
51 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.MatchBuilder;
52 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
53 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassBuilder;
54 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
55 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionList;
56 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListBuilder;
57 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListKey;
58 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.ForwardCaseBuilder;
59 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.ForwardBuilder;
60 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePath;
61 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathBuilder;
62 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpoint;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.AddressEndpointWithLocationAug;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
84 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
87
88 public class PolicyManagerUtil {
89
90     private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerUtil.class);
91
92     /**
93      * Main method which looks for all actions specified in rules between two endpoints. Whichever action has been found,
94      * it is resolved. Only chain action is supported for now.
95      *
96      * @param sourceSgt      - security group tag of source endpoint
97      * @param destinationSgt - security group tag of destination endpoint
98      * @param context        - stores policy writer and info about not configurable rules
99      * @param dataAfter      - new data, used to found appropriate rule group
100      * @param peerEndpoint   - contains info about rule groups between endpoint pairs
101      * @param dataBroker     - data provider for odl controller
102      * @param action         - required action crate/delete
103      */
104     public static void syncResolvedPolicy(final Sgt sourceSgt, final Sgt destinationSgt, final PolicyConfigurationContext context,
105                                           final Configuration dataAfter, final PeerEndpoint peerEndpoint,
106                                           final DataBroker dataBroker, final PolicyManagerImpl.DsAction action) {
107         // Find actions from acquired data
108         final Map<ActionCase, ActionInDirection> actionMap = PolicyManagerUtil.getActionInDirection(dataAfter, peerEndpoint);
109         if (actionMap.isEmpty()) {
110             LOG.debug("no usable action found for EP-sgt[{}] | peerEP-sgt[{}]",
111                     sourceSgt, destinationSgt);
112             return;
113         }
114
115         // Chain action
116         if (actionMap.containsKey(ActionCase.CHAIN) && action.equals(Create)) {
117             ServiceChainingUtil.resolveNewChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, context,
118                     dataBroker);
119         }
120         if (actionMap.containsKey(ActionCase.CHAIN) && action.equals(Delete)) {
121             ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap,
122                     context.getPolicyWriter());
123         }
124     }
125
126     /**
127      * According to info from {@link RuleGroupWithRendererEndpointParticipation} (composite key) finds appropriate subject
128      *
129      * @param data                       - contains all rule groups
130      * @param ruleGroupWithParticipation - contains info about how to find right rule group
131      * @return rule group if found, null otherwise
132      */
133     @Nullable
134     private static RuleGroup findRuleGroup(final Configuration data,
135                                            final RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation) {
136         final TenantId tenantId = ruleGroupWithParticipation.getTenantId();
137         final ContractId contractId = ruleGroupWithParticipation.getContractId();
138         final SubjectName subjectName = ruleGroupWithParticipation.getSubjectName();
139         for (RuleGroup ruleGroup : data.getRuleGroups().getRuleGroup()) {
140             if (!ruleGroup.getTenantId().equals(tenantId)) {
141                 continue;
142             }
143             if (!ruleGroup.getContractId().equals(contractId)) {
144                 continue;
145             }
146             if (ruleGroup.getSubjectName().equals(subjectName)) {
147                 return ruleGroup;
148             }
149         }
150         return null;
151     }
152
153     @Nullable
154     public static Sgt findSgtTag(final AddressEndpointKey endpointKey,
155                                  final List<AddressEndpointWithLocation> endpointsWithLocation) {
156         if (endpointKey == null || endpointsWithLocation == null) {
157             return null;
158         }
159         final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
160                 endpointsWithLocation);
161         final AddressEndpointWithLocationAug augmentation = endpointWithLocation.getAugmentation(AddressEndpointWithLocationAug.class);
162         if (augmentation == null) {
163             return null;
164         }
165
166         return augmentation.getSgt();
167     }
168
169     public static ServicePolicy createServicePolicy(final String chainName, final Direction direction) {
170         // Service Chain
171         final ServiceChainBuilder serviceChainBuilder = new ServiceChainBuilder();
172         serviceChainBuilder.setName(chainName) // Same as the policy map name
173                 .setDirection(direction);
174         // Service policy
175         final TypeBuilder typeBuilder = new TypeBuilder();
176         typeBuilder.setServiceChain(serviceChainBuilder.build());
177         // Service Policy
178         ServicePolicyBuilder servicePolicyBuilder = new ServicePolicyBuilder();
179         servicePolicyBuilder.setType(typeBuilder.build());
180
181         return servicePolicyBuilder.build();
182     }
183
184     public static PolicyMap createPolicyMap(final String policyMapName, final Set<Class> policyMapEntries) {
185         // TODO maybe could be better to create also class-default entry with pass-through value than not to create any default entry at all
186         // Construct policy map
187         final List<Class> policyMapEntriesList = new ArrayList<>(policyMapEntries);
188         final PolicyMapBuilder policyMapBuilder = new PolicyMapBuilder();
189         policyMapBuilder.setName(policyMapName)
190                 .setKey(new PolicyMapKey(policyMapName))
191                 .setType(PolicyMap.Type.ServiceChain)
192                 .setXmlClass(policyMapEntriesList);
193         return policyMapBuilder.build();
194     }
195
196     static Class createPolicyEntry(final String policyClassName, final RenderedServicePath renderedPath,
197                                    final ActionCase actionCase) {
198         // Forward Case
199         final ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
200         if (actionCase.equals(CHAIN) && renderedPath != null) {
201             // Chain Action
202             final ForwardBuilder forwardBuilder = new ForwardBuilder();
203             final List<ServicePath> servicePaths = new ArrayList<>();
204             final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
205             servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
206                     .setServicePathId(renderedPath.getPathId())
207                     .setServiceIndex(renderedPath.getStartingIndex());
208             servicePaths.add(servicePathBuilder.build());
209             forwardBuilder.setServicePath(servicePaths);
210             forwardCaseBuilder.setForward(forwardBuilder.build());
211         }
212         // Create Action List
213         final List<ActionList> actionList = new ArrayList<>();
214         final ActionListBuilder actionListBuilder = new ActionListBuilder();
215         actionListBuilder.setKey(new ActionListKey(PolicyActionType.Forward))
216                 .setActionType(PolicyActionType.Forward)
217                 .setActionParam(forwardCaseBuilder.build());
218         actionList.add(actionListBuilder.build());
219         // Build class entry
220         final ClassBuilder policyClassBuilder = new ClassBuilder();
221         policyClassBuilder.setName(new ClassNameType(policyClassName))
222                 .setKey(new ClassKey(new ClassNameType(policyClassName)))
223                 .setActionList(actionList);
224         return policyClassBuilder.build();
225     }
226
227     static Match createSecurityGroupMatch(final int sourceTag, final int destinationTag) {
228         final SecurityGroupBuilder sgBuilder = new SecurityGroupBuilder();
229         final Source source = new SourceBuilder().setTag(sourceTag).build();
230         final Destination destination = new DestinationBuilder().setTag(destinationTag).build();
231         sgBuilder.setDestination(destination)
232                 .setSource(source);
233         final SecurityGroup securityGroup = sgBuilder.build();
234         final MatchBuilder matchBuilder = new MatchBuilder();
235         matchBuilder.setSecurityGroup(securityGroup);
236         return matchBuilder.build();
237     }
238
239     static ClassMap createClassMap(final String classMapName, final Match match) {
240         final ClassMapBuilder cmBuilder = new ClassMapBuilder();
241         cmBuilder.setName(classMapName)
242                 .setKey(new ClassMapKey(classMapName))
243                 .setPrematch(ClassMap.Prematch.MatchAll)
244                 .setMatch(match);
245         return cmBuilder.build();
246     }
247
248     /**
249      * Constructs {@link ActionInDirection} object with {@link ActionCase} as a key. ActionInDirection object contains
250      * info about action, participation and rule direction.
251      *
252      * @param data - used for finding rule's rule group
253      * @param peer - contains {@link RuleGroupWithRendererEndpointParticipation}
254      * @return map with actionCase/ActionInDirection entries, empty map if no rule is found
255      */
256     @Nonnull
257     private static Map<ActionCase, ActionInDirection> getActionInDirection(final Configuration data,
258                                                                            final PeerEndpoint peer) {
259         final Set<ResolvedRule> rulesInDirection = new HashSet<>();
260         EndpointPolicyParticipation participation = null;
261         HasDirection.Direction direction = null;
262         // Find all rules in desired direction
263         for (RuleGroupWithRendererEndpointParticipation ruleGroupKey :
264                 peer.getRuleGroupWithRendererEndpointParticipation()) {
265             participation = ruleGroupKey.getRendererEndpointParticipation();
266             final RuleGroup ruleGroup = findRuleGroup(data, ruleGroupKey);
267             if (ruleGroup == null || ruleGroup.getResolvedRule() == null) {
268                 continue;
269             }
270
271             for (ResolvedRule resolvedRule : ruleGroup.getResolvedRule()) {
272                 if (resolvedRule == null) {
273                     continue;
274                 }
275                 if (resolvedRule.getClassifier() == null || resolvedRule.getAction() == null) {
276                     continue;
277                 }
278                 // TODO only first Classifier used
279                 final Classifier classifier = resolvedRule.getClassifier().get(0);
280                 direction = classifier.getDirection();
281                 rulesInDirection.add(resolvedRule);
282             }
283         }
284         if (rulesInDirection.isEmpty()) {
285             return Collections.emptyMap();
286         }
287         // TODO use only first rule with ActionDefinitionID for now
288         final Map<ActionCase, ActionInDirection> result = new HashMap<>();
289         for (ResolvedRule resolvedRule : rulesInDirection) {
290             // TODO only first action used for now
291             final Action action = resolvedRule.getAction().get(0);
292             if (action.getActionDefinitionId() != null) {
293                 final ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
294                 // Currently only chain action is supported
295                 if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
296                     ActionInDirection actionInDirection = new ActionInDirection(action, participation, direction);
297                     result.put(ActionCase.CHAIN, actionInDirection);
298                     return result;
299                 }
300             }
301         }
302         return Collections.emptyMap();
303     }
304
305     public static InstanceIdentifier getMountpointIidFromAbsoluteLocation(final RendererEndpoint endpoint,
306                                                                           final List<AddressEndpointWithLocation> endpointsWithLocation) {
307         if (endpointsWithLocation.isEmpty()) {
308             return null;
309         }
310         AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
311                 endpointsWithLocation);
312         final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
313         final LocationType locationType = absoluteLocation.getLocationType();
314         ExternalLocationCase location = (ExternalLocationCase) locationType;
315         if (location == null) {
316             LOG.warn("Endpoint {} does not contain info about external location",
317                     endpointWithLocation.getKey().toString());
318             return null;
319         }
320         return location.getExternalNodeMountPoint();
321     }
322
323     public static String getInterfaceNameFromAbsoluteLocation(final RendererEndpoint endpoint,
324                                                               final List<AddressEndpointWithLocation> endpointsWithLocation) {
325         if (endpoint == null || endpointsWithLocation == null) {
326             return null;
327         }
328         final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
329                 endpointsWithLocation);
330         final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
331         final LocationType locationType = absoluteLocation.getLocationType();
332         final ExternalLocationCase location = (ExternalLocationCase) locationType;
333         if (location == null) {
334             LOG.warn("Endpoint {} does not contain info about external location",
335                     endpointWithLocation.getKey().toString());
336             return null;
337         }
338         return location.getExternalNodeConnector();
339     }
340
341     static TenantId getTenantId(final PeerEndpoint peer) {
342         for (RuleGroupWithRendererEndpointParticipation ruleGroup :
343                 peer.getRuleGroupWithRendererEndpointParticipation()) {
344             if (ruleGroup.getTenantId() != null) {
345                 return ruleGroup.getTenantId();
346             }
347         }
348         return null;
349     }
350
351     static String generateClassMapName(final int sourceTag, final int destinationTag) {
352         return "srcTag" + sourceTag + "_dstTag" + destinationTag;
353     }
354
355     /**
356      * Action in Direction - wrapper class
357      */
358     static class ActionInDirection {
359
360         private final Action action;
361         private final EndpointPolicyParticipation participation;
362         private final HasDirection.Direction direction;
363
364         ActionInDirection(final Action action,
365                           final EndpointPolicyParticipation participation,
366                           final HasDirection.Direction direction) {
367             this.action = Preconditions.checkNotNull(action);
368             this.participation = Preconditions.checkNotNull(participation);
369             this.direction = Preconditions.checkNotNull(direction);
370         }
371
372         Action getAction() {
373             return action;
374         }
375
376         EndpointPolicyParticipation getParticipation() {
377             return participation;
378         }
379
380         HasDirection.Direction getDirection() {
381             return direction;
382         }
383     }
384 }