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