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