BUG-6650: ep-ip/sgt, propose sxp-generator
[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
13 import com.google.common.base.Preconditions;
14 import com.google.common.util.concurrent.Futures;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Optional;
22 import java.util.Set;
23 import javax.annotation.Nonnull;
24 import javax.annotation.Nullable;
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.groupbasedpolicy.renderer.ios_xe_provider.impl.writer.PolicyWriterUtil;
31 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPToSgtMapper;
32 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
33 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.ClassNameType;
34 import org.opendaylight.yang.gen.v1.urn.ios.rev160308.PolicyActionType;
35 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroup;
36 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroupBuilder;
37 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Destination;
38 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.DestinationBuilder;
39 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Source;
40 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.SourceBuilder;
41 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicy;
42 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.ServicePolicyBuilder;
43 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.TypeBuilder;
44 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction;
45 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder;
46 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
47 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapBuilder;
48 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
49 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
50 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapBuilder;
51 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
52 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
53 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.MatchBuilder;
54 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
55 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassBuilder;
56 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
57 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionList;
58 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListBuilder;
59 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListKey;
60 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.ForwardCaseBuilder;
61 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.ForwardBuilder;
62 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePath;
63 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathBuilder;
64 import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpoint;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.AddressEndpointWithLocationAug;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
87 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
88 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
89 import org.slf4j.Logger;
90 import org.slf4j.LoggerFactory;
91
92 public class PolicyManagerUtil {
93
94     private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerUtil.class);
95
96     private PolicyManagerUtil() {
97         throw new IllegalAccessError("instance of util class not supported");
98     }
99
100     /**
101      * Main method for policy creation which looks for all actions specified in rules between two endpoints. Whichever
102      * action has been found, it is resolved (only chain action is supported for now).
103      *
104      * @param sourceSgt      - security group tag of source endpoint
105      * @param destinationSgt - security group tag of destination endpoint
106      * @param context        - stores info about location of classifier/policy-map and status
107      * @param data           - new data, used to found appropriate rule group
108      * @param peerEndpoint   - contains info about rule groups between endpoint pairs
109      * @param dataBroker     - data provider for odl controller
110      */
111     public static void syncEndpointPairCreatePolicy(final Sgt sourceSgt, final Sgt destinationSgt,
112                                                     final PolicyConfigurationContext context, final Configuration data,
113                                                     final PeerEndpoint peerEndpoint, final DataBroker dataBroker) {
114         // Create appropriate policy map
115         if (!PolicyManagerUtil.constructEmptyPolicyMapWithInterface(context)) {
116             final String policyMapName = context.getPolicyMapLocation().getPolicyMapName();
117             final String interfaceName = context.getPolicyMapLocation().getInterfaceName();
118             final String info = String.format("Unable to create policy-map %s on interface %s", policyMapName, interfaceName);
119             context.appendUnconfiguredRendererEP(StatusUtil.assembleFullyNotConfigurableRendererEP(context, info));
120             LOG.warn(info);
121             return;
122         }
123
124         // Find actions from acquired data
125         final Map<ActionCase, ActionInDirection> actionMap = PolicyManagerUtil.getActionInDirection(data, peerEndpoint);
126         if (actionMap.isEmpty()) {
127             LOG.debug("No usable action found for EP-sgt[{}] | peerEP-sgt[{}]", sourceSgt, destinationSgt);
128             return;
129         }
130
131         // Chain action
132         if (actionMap.containsKey(ActionCase.CHAIN)) {
133             ServiceChainingUtil.newChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, context,
134                     dataBroker);
135         }
136     }
137
138     /**
139      * Method for policy removal which looks for all actions specified in rules between two endpoints. Whichever
140      * action has been found, it is resolved (only chain action is supported).
141      *
142      * @param sourceSgt      - security group tag of source endpoint
143      * @param destinationSgt - security group tag of destination endpoint
144      * @param context        - stores info about location of classifier/policy-map and status
145      * @param data           - data used to identify all elements marked to remove
146      * @param peerEndpoint   - contains info about rule groups between endpoint pairs
147      */
148     public static void syncEndpointPairRemovePolicy(final Sgt sourceSgt, final Sgt destinationSgt,
149                                                     final PolicyConfigurationContext context, final Configuration data,
150                                                     final PeerEndpoint peerEndpoint) {
151         // Find actions from acquired data
152         final Map<ActionCase, ActionInDirection> actionMap = PolicyManagerUtil.getActionInDirection(data, peerEndpoint);
153         if (actionMap.isEmpty()) {
154             LOG.debug("no usable action found for EP-sgt[{}] | peerEP-sgt[{}]",
155                     sourceSgt, destinationSgt);
156             return;
157         }
158
159         // Chain action
160         if (actionMap.containsKey(ActionCase.CHAIN)) {
161             ServiceChainingUtil.resolveRemovedChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap,
162                     context);
163         }
164
165         // Remove policy-map if empty
166         if (!deleteEmptyPolicyMapWithInterface(context.getPolicyMapLocation())) {
167             final PolicyManagerImpl.PolicyMapLocation location = context.getPolicyMapLocation();
168             final String info = String.format("Unable to remove policy-map %s and interface %s", location.getPolicyMapName(),
169                     location.getInterfaceName());
170             LOG.warn(info);
171         }
172     }
173
174     /**
175      * According to info from {@link RuleGroupWithRendererEndpointParticipation} (composite key) finds appropriate subject
176      *
177      * @param data                       - contains all rule groups
178      * @param ruleGroupWithParticipation - contains info about how to find right rule group
179      * @return rule group if found, null otherwise
180      */
181     @Nullable
182     private static RuleGroup findRuleGroup(final Configuration data,
183                                            final RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation) {
184         final TenantId tenantId = ruleGroupWithParticipation.getTenantId();
185         final ContractId contractId = ruleGroupWithParticipation.getContractId();
186         final SubjectName subjectName = ruleGroupWithParticipation.getSubjectName();
187         for (RuleGroup ruleGroup : data.getRuleGroups().getRuleGroup()) {
188             if (!ruleGroup.getTenantId().equals(tenantId)) {
189                 continue;
190             }
191             if (!ruleGroup.getContractId().equals(contractId)) {
192                 continue;
193             }
194             if (ruleGroup.getSubjectName().equals(subjectName)) {
195                 return ruleGroup;
196             }
197         }
198         return null;
199     }
200
201     @Nullable
202     public static Sgt findSgtTag(final EPToSgtMapper sxpEpProvider, final AddressEndpointKey endpointKey,
203                                  final List<AddressEndpointWithLocation> endpointsWithLocation) {
204         if (endpointKey == null || endpointsWithLocation == null) {
205             return null;
206         }
207         final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
208                 endpointsWithLocation);
209
210         //TODO: involve sxpEpProvider
211         final AddressEndpointWithLocationAug augmentation = endpointWithLocation.getAugmentation(AddressEndpointWithLocationAug.class);
212         if (augmentation == null) {
213             return null;
214         }
215
216         return augmentation.getSgt();
217     }
218
219     /**
220      * Creates empty policy-map if does not exist and bounds it to interface if it is not. If policy-map exists, method
221      * checks whether it is connected to correct interface and creates it if necessary. If policy-map does not exist,
222      * it is created with particular interface
223      *
224      * @param context - all data required to create/localize policy-map
225      * @return true if policy-map and interface is present/written on the device, false otherwise
226      */
227     private static boolean constructEmptyPolicyMapWithInterface(final PolicyConfigurationContext context) {
228         final PolicyManagerImpl.PolicyMapLocation policyMapLocation = context.getPolicyMapLocation();
229         final String policyMapName = policyMapLocation.getPolicyMapName();
230         final DataBroker mountpoint = policyMapLocation.getMountpoint();
231         final String interfaceName = policyMapLocation.getInterfaceName();
232         final NodeId nodeId = policyMapLocation.getNodeId();
233         final InstanceIdentifier<PolicyMap> policyMapIid = PolicyWriterUtil.policyMapInstanceIdentifier(policyMapName);
234         final Optional<PolicyMap> optionalPolicyMap =
235                 Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, policyMapIid));
236         if (optionalPolicyMap.isPresent()) {
237             LOG.trace("Policy map with name {} on interface {} already exists", policyMapName, interfaceName);
238             final InstanceIdentifier<ServicePolicy> servicePolicyIid = PolicyWriterUtil.interfaceInstanceIdentifier(interfaceName);
239             final Optional<ServicePolicy> optionalServicePolicy =
240                     Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, servicePolicyIid));
241             if (optionalServicePolicy.isPresent()) {
242                 LOG.trace("Policy map {} is bound to correct interface {} ", policyMapName, interfaceName);
243                 return true;
244             } else {
245                 boolean iResult = PolicyWriterUtil.writeInterface(context.getPolicyMapLocation());
246                 context.setFutureResult(Futures.immediateCheckedFuture(iResult));
247                 return iResult;
248             }
249         } else {
250             final PolicyMap emptyMap = createEmptyPolicyMap(policyMapName);
251             boolean pmResult = PolicyWriterUtil.writePolicyMap(emptyMap, context.getPolicyMapLocation());
252             context.setFutureResult(Futures.immediateCheckedFuture(pmResult));
253             if (pmResult) {
254                 LOG.info("Created policy-map {} on node {}", policyMapName, nodeId.getValue());
255                 LOG.trace("Adding policy-map {} to interface {}", policyMapName, interfaceName);
256                 boolean iResult = PolicyWriterUtil.writeInterface(context.getPolicyMapLocation());
257                 context.setFutureResult(Futures.immediateCheckedFuture(iResult));
258                 return iResult;
259             }
260             return false;
261         }
262     }
263
264     /**
265      * Removes empty policy-map and its interface
266      *
267      * @param policyMapLocation - location of policy-map
268      * @return true if policy-map is present and not empty or if it is successfully removed also with interface, false
269      * otherwise
270      */
271     private static boolean deleteEmptyPolicyMapWithInterface(PolicyManagerImpl.PolicyMapLocation policyMapLocation) {
272         final String policyMapName = policyMapLocation.getPolicyMapName();
273         final DataBroker mountpoint = policyMapLocation.getMountpoint();
274         final InstanceIdentifier<PolicyMap> policyMapIid = PolicyWriterUtil.policyMapInstanceIdentifier(policyMapName);
275         // Read policy map
276         final Optional<PolicyMap> optionalPolicyMap = Optional.ofNullable(PolicyWriterUtil.netconfRead(mountpoint, policyMapIid));
277         if (optionalPolicyMap.isPresent()) {
278             final PolicyMap policyMap = optionalPolicyMap.get();
279             if (policyMap.getXmlClass() == null || policyMap.getXmlClass().isEmpty()) {
280                 // No entries, remove
281                 if (PolicyWriterUtil.removePolicyMap(policyMapLocation)) {
282                     // Remove interface binding if exists
283                     LOG.info("Policy-map {} removed", policyMapName);
284                     return PolicyWriterUtil.removeInterface(policyMapLocation);
285                 }
286                 return false;
287             }
288             LOG.debug("Policy-map {} still contains entries, cannot be removed", policyMapLocation.getPolicyMapName());
289             return true;
290         }
291         return true;
292
293     }
294
295     public static ServicePolicy createServicePolicy(final String chainName, final Direction direction) {
296         // Service Chain
297         final ServiceChainBuilder serviceChainBuilder = new ServiceChainBuilder();
298         serviceChainBuilder.setName(chainName) // Same as the policy map name
299                 .setDirection(direction);
300         // Service policy
301         final TypeBuilder typeBuilder = new TypeBuilder();
302         typeBuilder.setServiceChain(serviceChainBuilder.build());
303         // Service Policy
304         ServicePolicyBuilder servicePolicyBuilder = new ServicePolicyBuilder();
305         servicePolicyBuilder.setType(typeBuilder.build());
306
307         return servicePolicyBuilder.build();
308     }
309
310     private static PolicyMap createEmptyPolicyMap(String policyMapName) {
311         // TODO maybe could be better to create also class-default entry with pass-through value than not to create any default entry at all
312         // Construct policy map
313         final PolicyMapBuilder policyMapBuilder = new PolicyMapBuilder();
314         policyMapBuilder.setName(policyMapName)
315                 .setKey(new PolicyMapKey(policyMapName))
316                 .setType(PolicyMap.Type.ServiceChain);
317         return policyMapBuilder.build();
318     }
319
320     static Class createPolicyMapEntry(final String policyClassName, final RenderedServicePath renderedPath,
321                                       final ActionCase actionCase) {
322         // Forward Case
323         final ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
324         if (actionCase.equals(CHAIN) && renderedPath != null) {
325             // Chain Action
326             final ForwardBuilder forwardBuilder = new ForwardBuilder();
327             final List<ServicePath> servicePaths = new ArrayList<>();
328             final ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
329             servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
330                     .setServicePathId(renderedPath.getPathId())
331                     .setServiceIndex(renderedPath.getStartingIndex());
332             servicePaths.add(servicePathBuilder.build());
333             forwardBuilder.setServicePath(servicePaths);
334             forwardCaseBuilder.setForward(forwardBuilder.build());
335         }
336         // Create Action List
337         final List<ActionList> actionList = new ArrayList<>();
338         final ActionListBuilder actionListBuilder = new ActionListBuilder();
339         actionListBuilder.setKey(new ActionListKey(PolicyActionType.Forward))
340                 .setActionType(PolicyActionType.Forward)
341                 .setActionParam(forwardCaseBuilder.build());
342         actionList.add(actionListBuilder.build());
343         // Build class entry
344         final ClassBuilder policyClassBuilder = new ClassBuilder();
345         policyClassBuilder.setName(new ClassNameType(policyClassName))
346                 .setKey(new ClassKey(new ClassNameType(policyClassName)))
347                 .setActionList(actionList);
348         return policyClassBuilder.build();
349     }
350
351     static Match createSecurityGroupMatch(final int sourceTag, final int destinationTag) {
352         final SecurityGroupBuilder sgBuilder = new SecurityGroupBuilder();
353         final Source source = new SourceBuilder().setTag(sourceTag).build();
354         final Destination destination = new DestinationBuilder().setTag(destinationTag).build();
355         sgBuilder.setDestination(destination)
356                 .setSource(source);
357         final SecurityGroup securityGroup = sgBuilder.build();
358         final MatchBuilder matchBuilder = new MatchBuilder();
359         matchBuilder.setSecurityGroup(securityGroup);
360         return matchBuilder.build();
361     }
362
363     @Nonnull
364     static ClassMap createClassMap(final String classMapName, final Match match) {
365         final ClassMapBuilder cmBuilder = new ClassMapBuilder();
366         cmBuilder.setName(classMapName)
367                 .setKey(new ClassMapKey(classMapName))
368                 .setPrematch(ClassMap.Prematch.MatchAll)
369                 .setMatch(match);
370         return cmBuilder.build();
371     }
372
373     /**
374      * Constructs {@link ActionInDirection} object with {@link ActionCase} as a key. ActionInDirection object contains
375      * info about action, participation and rule direction.
376      *
377      * @param data - used for finding rule's rule group
378      * @param peer - contains {@link RuleGroupWithRendererEndpointParticipation}
379      * @return map with actionCase/ActionInDirection entries, empty map if no rule is found
380      */
381     @Nonnull
382     private static Map<ActionCase, ActionInDirection> getActionInDirection(final Configuration data,
383                                                                            final PeerEndpoint peer) {
384         final Set<ResolvedRule> rulesInDirection = new HashSet<>();
385         EndpointPolicyParticipation participation = null;
386         HasDirection.Direction direction = null;
387         // Find all rules in desired direction
388         for (RuleGroupWithRendererEndpointParticipation ruleGroupKey :
389                 peer.getRuleGroupWithRendererEndpointParticipation()) {
390             participation = ruleGroupKey.getRendererEndpointParticipation();
391             final RuleGroup ruleGroup = findRuleGroup(data, ruleGroupKey);
392             if (ruleGroup == null || ruleGroup.getResolvedRule() == null) {
393                 continue;
394             }
395
396             for (ResolvedRule resolvedRule : ruleGroup.getResolvedRule()) {
397                 if (resolvedRule == null) {
398                     continue;
399                 }
400                 if (resolvedRule.getClassifier() == null || resolvedRule.getAction() == null) {
401                     continue;
402                 }
403                 // TODO only first Classifier used
404                 final Classifier classifier = resolvedRule.getClassifier().get(0);
405                 direction = classifier.getDirection();
406                 rulesInDirection.add(resolvedRule);
407             }
408         }
409         if (rulesInDirection.isEmpty()) {
410             return Collections.emptyMap();
411         }
412         // TODO use only first rule with ActionDefinitionID for now
413         final Map<ActionCase, ActionInDirection> result = new HashMap<>();
414         for (ResolvedRule resolvedRule : rulesInDirection) {
415             // TODO only first action used for now
416             final Action action = resolvedRule.getAction().get(0);
417             final RuleName name = resolvedRule.getName();
418             if (action.getActionDefinitionId() != null) {
419                 final ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
420                 // Currently only chain action is supported
421                 if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
422                     ActionInDirection actionInDirection = new ActionInDirection(name, action, participation, direction);
423                     result.put(ActionCase.CHAIN, actionInDirection);
424                     return result;
425                 }
426             }
427         }
428         return Collections.emptyMap();
429     }
430
431     public static InstanceIdentifier getMountpointIidFromAbsoluteLocation(final RendererEndpoint endpoint,
432                                                                           final List<AddressEndpointWithLocation> endpointsWithLocation) {
433         if (endpointsWithLocation.isEmpty()) {
434             return null;
435         }
436         AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
437                 endpointsWithLocation);
438         final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
439         final LocationType locationType = absoluteLocation.getLocationType();
440         ExternalLocationCase location = (ExternalLocationCase) locationType;
441         if (location == null) {
442             LOG.warn("Endpoint {} does not contain info about external location",
443                     endpointWithLocation.getKey().toString());
444             return null;
445         }
446         return location.getExternalNodeMountPoint();
447     }
448
449     public static String getInterfaceNameFromAbsoluteLocation(final RendererEndpoint endpoint,
450                                                               final List<AddressEndpointWithLocation> endpointsWithLocation) {
451         if (endpoint == null || endpointsWithLocation == null) {
452             return null;
453         }
454         final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
455                 endpointsWithLocation);
456         final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
457         final LocationType locationType = absoluteLocation.getLocationType();
458         final ExternalLocationCase location = (ExternalLocationCase) locationType;
459         if (location == null) {
460             LOG.warn("Endpoint {} does not contain info about external location",
461                     endpointWithLocation.getKey().toString());
462             return null;
463         }
464         return location.getExternalNodeConnector();
465     }
466
467     static TenantId getTenantId(final PeerEndpoint peer) {
468         for (RuleGroupWithRendererEndpointParticipation ruleGroup :
469                 peer.getRuleGroupWithRendererEndpointParticipation()) {
470             if (ruleGroup.getTenantId() != null) {
471                 return ruleGroup.getTenantId();
472             }
473         }
474         return null;
475     }
476
477     static String generateClassMapName(final int sourceTag, final int destinationTag) {
478         return "srcTag" + sourceTag + "_dstTag" + destinationTag;
479     }
480
481     /**
482      * Action in Direction - wrapper class
483      */
484     static class ActionInDirection {
485
486         private final RuleName ruleName;
487         private final Action action;
488         private final EndpointPolicyParticipation participation;
489         private final HasDirection.Direction direction;
490
491         ActionInDirection(final RuleName ruleName,
492                           final Action action,
493                           final EndpointPolicyParticipation participation,
494                           final HasDirection.Direction direction) {
495             this.ruleName = Preconditions.checkNotNull(ruleName);
496             this.action = Preconditions.checkNotNull(action);
497             this.participation = Preconditions.checkNotNull(participation);
498             this.direction = Preconditions.checkNotNull(direction);
499         }
500
501         RuleName getRuleName() {
502             return ruleName;
503         }
504
505         Action getAction() {
506             return action;
507         }
508
509         EndpointPolicyParticipation getParticipation() {
510             return participation;
511         }
512
513         HasDirection.Direction getDirection() {
514             return direction;
515         }
516     }
517 }