Neutron-mapper uses only DTOs from neutron.yang
[groupbasedpolicy.git] / neutron-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / mapper / mapping / rule / NeutronSecurityRuleAware.java
1 /*
2  * Copyright (c) 2014 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.neutron.mapper.mapping.rule;
10
11 import static com.google.common.base.Preconditions.checkNotNull;
12
13 import java.util.Set;
14
15 import org.opendaylight.controller.config.yang.config.neutron_mapper.impl.NeutronMapperModule;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
21 import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
22 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronAware;
23 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
24 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SecurityGroupUtils;
25 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SecurityRuleUtils;
26 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
27 import org.opendaylight.groupbasedpolicy.util.IidFactory;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.ActionChoice;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.action.choice.SfcActionCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelector;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelectorBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderNamedSelector;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderNamedSelectorBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstanceBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 import com.google.common.annotations.VisibleForTesting;
58 import com.google.common.base.Optional;
59 import com.google.common.collect.HashMultiset;
60 import com.google.common.collect.ImmutableList;
61 import com.google.common.collect.Multiset;
62 import com.google.common.collect.Sets;
63
64 public class NeutronSecurityRuleAware implements NeutronAware<SecurityRule> {
65
66     private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleAware.class);
67     public static final InstanceIdentifier<SecurityRule> SECURITY_RULE_WILDCARD_IID =
68             InstanceIdentifier.builder(Neutron.class).child(SecurityRules.class).child(SecurityRule.class).build();
69     private static final String CONTRACT_PROVIDER = "Contract provider: ";
70     private final DataBroker dataProvider;
71     private final Multiset<InstanceIdentifier<ClassifierInstance>> createdClassifierInstances;
72     private final Multiset<InstanceIdentifier<ActionInstance>> createdActionInstances;
73     final static String PROVIDED_BY = "provided_by-";
74     final static String POSSIBLE_CONSUMER = "possible_consumer-";
75
76     public NeutronSecurityRuleAware(DataBroker dataProvider) {
77         this(dataProvider, HashMultiset.<InstanceIdentifier<ClassifierInstance>>create(),
78                 HashMultiset.<InstanceIdentifier<ActionInstance>>create());
79     }
80
81     @VisibleForTesting
82     NeutronSecurityRuleAware(DataBroker dataProvider,
83             Multiset<InstanceIdentifier<ClassifierInstance>> classifierInstanceNames,
84             Multiset<InstanceIdentifier<ActionInstance>> createdActionInstances) {
85         this.dataProvider = checkNotNull(dataProvider);
86         this.createdClassifierInstances = checkNotNull(classifierInstanceNames);
87         this.createdActionInstances = checkNotNull(createdActionInstances);
88     }
89
90     @Override
91     public void onCreated(SecurityRule secRule, Neutron neutron) {
92         LOG.trace("created securityRule - {}", secRule);
93         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
94         boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(secRule, neutron, rwTx);
95         if (isNeutronSecurityRuleAdded) {
96             DataStoreHelper.submitToDs(rwTx);
97         } else {
98             rwTx.cancel();
99         }
100     }
101
102     public boolean addNeutronSecurityRule(SecurityRule secRule, Neutron neutron, ReadWriteTransaction rwTx) {
103         return addNeutronSecurityRuleWithAction(secRule, neutron, MappingUtils.ALLOW_ACTION_CHOICE, rwTx);
104     }
105
106     public boolean addNeutronSecurityRuleWithAction(SecurityRule secRule, Neutron neutron, ActionChoice action,
107             ReadWriteTransaction rwTx) {
108         TenantId tenantId = new TenantId(secRule.getTenantId().getValue());
109         Uuid providerSecGroupId = secRule.getSecurityGroupId();
110         EndpointGroupId providerEpgId = new EndpointGroupId(providerSecGroupId.getValue());
111
112         Description contractDescription = createContractDescription(secRule, neutron);
113         SingleRuleContract singleRuleContract = createSingleRuleContract(secRule, contractDescription, action);
114         Contract contract = singleRuleContract.getContract();
115         rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.contractIid(tenantId, contract.getId()), contract, true);
116         SelectorName providerSelector = getSelectorNameWithConsumer(secRule, neutron);
117         writeProviderNamedSelectorToEpg(providerSelector, contract.getId(), new EpgKeyDto(providerEpgId, tenantId), rwTx);
118
119         if (secRule.getRemoteGroupId() != null) {
120             Uuid consumerSecGroupId = secRule.getRemoteGroupId();
121             designContractsBetweenProviderAndConsumer(tenantId, providerSecGroupId, consumerSecGroupId, neutron, rwTx);
122             designContractsBetweenProviderAndConsumer(tenantId, consumerSecGroupId, providerSecGroupId, neutron, rwTx);
123         } else {
124             for (Uuid consumerSecGroupId : SecurityRuleUtils.findSecurityGroupsHavingSecurityRules(neutron)) {
125                 designContractsBetweenProviderAndConsumer(tenantId, providerSecGroupId, consumerSecGroupId, neutron, rwTx);
126                 designContractsBetweenProviderAndConsumer(tenantId, consumerSecGroupId, providerSecGroupId, neutron, rwTx);
127             }
128         }
129
130         ClassifierInstance classifierInstance = singleRuleContract.getSingleClassifierRule().getClassifierInstance();
131         createClassifierInstanceIfNotExists(tenantId, classifierInstance, rwTx);
132         createAllowActionInstanceIfNotExists(tenantId, rwTx);
133         return true;
134     }
135
136     @VisibleForTesting
137     static Description createContractDescription(SecurityRule secRule, Neutron neutron) {
138         if (NeutronMapperModule.isDebugEnabled()) {
139             Optional<SecurityGroup> providerSecGroup =
140                     SecurityGroupUtils.findSecurityGroup(secRule.getSecurityGroupId(), neutron.getSecurityGroups());
141             if (!providerSecGroup.isPresent()) {
142                 LOG.error("Neutron Security Group with UUID {} does not exist but it is in {}", secRule.getSecurityGroupId().getValue(),
143                         secRule);
144                 throw new IllegalStateException(
145                         "Neutron Security Group with UUID " + secRule.getSecurityGroupId().getValue() + " does not exist.");
146             }
147             return new Description(CONTRACT_PROVIDER + SecurityGroupUtils.getNameOrUuid(providerSecGroup.get()));
148         }
149
150         return new Description(CONTRACT_PROVIDER + secRule.getSecurityGroupId());
151     }
152
153     @VisibleForTesting
154     static SingleRuleContract createSingleRuleContract(SecurityRule secRule, Description contractDescription, ActionChoice action) {
155         if (secRule.getRemoteIpPrefix() != null) {
156             return new SingleRuleContract(secRule, 0, contractDescription, action);
157         }
158         return new SingleRuleContract(secRule, 400, contractDescription, action);
159     }
160
161     @VisibleForTesting
162     void designContractsBetweenProviderAndConsumer(TenantId tenantId, Uuid provSecGroupId, Uuid consSecGroupId,
163             Neutron neutron, ReadWriteTransaction rwTx) {
164         Set<SecurityRule> provSecRules = getProvidedSecRulesBetween(provSecGroupId, consSecGroupId, neutron);
165         Set<SecurityRule> consSecRules = getProvidedSecRulesBetween(consSecGroupId, provSecGroupId, neutron);
166         EndpointGroupId consEpgId = new EndpointGroupId(consSecGroupId.getValue());
167         for (SecurityRule provSecRule : provSecRules) {
168             if (isProviderSecRuleSuitableForConsumerSecRules(provSecRule, consSecRules)) {
169                 SelectorName consumerSelector = getSelectorNameWithProvider(provSecRule, neutron);
170                 ContractId contractId = SecRuleEntityDecoder.getContractId(provSecRule);
171                 writeConsumerNamedSelectorToEpg(consumerSelector, contractId, new EpgKeyDto(consEpgId, tenantId), rwTx);
172             }
173             // TODO add case when port ranges overlap
174         }
175     }
176
177     @VisibleForTesting
178     Set<SecurityRule> getProvidedSecRulesBetween(Uuid provSecGroup, Uuid consSecGroup, Neutron neutron) {
179         return Sets.union(SecurityRuleUtils.findSecurityRulesBySecGroupAndRemoteSecGroup(provSecGroup, consSecGroup, neutron),
180                 SecurityRuleUtils.findSecurityRulesBySecGroupAndRemoteSecGroup(provSecGroup, null, neutron));
181     }
182
183     @VisibleForTesting
184     static boolean isProviderSecRuleSuitableForConsumerSecRules(SecurityRule provSecRule,
185             Set<SecurityRule> consSecRules) {
186         Direction directionProvSecRule = SecRuleEntityDecoder.getDirection(provSecRule);
187         for (SecurityRule consSecRule : consSecRules) {
188             Direction directionConsSecRule = SecRuleEntityDecoder.getDirection(consSecRule);
189             if (isDirectionOpposite(directionProvSecRule, directionConsSecRule)
190                     && isOneWithinTwo(provSecRule, consSecRule)) {
191                 return true;
192             }
193         }
194         return false;
195     }
196
197     public boolean changeActionOfNeutronSecurityRule(SecurityRule secRule, ActionChoice action, Neutron neutron, ReadWriteTransaction rwTx) {
198         addSfcChainActionInstance(action, new TenantId(secRule.getTenantId().getValue()), rwTx);
199         LOG.trace("Changing to action {} for secuirity group rule {}", action, secRule);
200         return addNeutronSecurityRuleWithAction(secRule, neutron, action, rwTx);
201     }
202
203     private void addSfcChainActionInstance(ActionChoice action, TenantId tenantId, ReadWriteTransaction rwTx) {
204         if (action instanceof SfcActionCase) {
205             String sfcChainName = ((SfcActionCase) action).getSfcChainName();
206             ActionName actionName = new ActionName(sfcChainName);
207             ActionInstance sfcActionInstance = new ActionInstanceBuilder().setName(actionName)
208                 .setActionDefinitionId(ChainActionDefinition.ID)
209                 .setParameterValue(
210                         ImmutableList.of(new ParameterValueBuilder().setName(
211                                 new ParameterName(ChainActionDefinition.SFC_CHAIN_NAME))
212                             .setStringValue(sfcChainName)
213                             .build()))
214                 .build();
215             rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.actionInstanceIid(tenantId, actionName),
216                     sfcActionInstance, true);
217         }
218     }
219
220     private void writeProviderNamedSelectorToEpg(SelectorName providerSelector, ContractId contractId, EpgKeyDto epgKey,
221             WriteTransaction wTx) {
222         ProviderNamedSelector providerNamedSelector = new ProviderNamedSelectorBuilder().setName(providerSelector)
223             .setContract(ImmutableList.of(contractId))
224             .build();
225         wTx.put(LogicalDatastoreType.CONFIGURATION,
226                 IidFactory.providerNamedSelectorIid(epgKey.getTenantId(), epgKey.getEpgId(),
227                         providerNamedSelector.getName()), providerNamedSelector, true);
228     }
229
230     private void writeConsumerNamedSelectorToEpg(SelectorName consumerSelector, ContractId contractId, EpgKeyDto epgKey,
231             WriteTransaction wTx) {
232         ConsumerNamedSelector consumerNamedSelector = new ConsumerNamedSelectorBuilder().setName(consumerSelector)
233             .setContract(ImmutableList.of(contractId))
234             .build();
235         wTx.put(LogicalDatastoreType.CONFIGURATION,
236                 IidFactory.consumerNamedSelectorIid(epgKey.getTenantId(), epgKey.getEpgId(),
237                         consumerNamedSelector.getName()), consumerNamedSelector, true);
238     }
239
240     @VisibleForTesting
241     void createClassifierInstanceIfNotExists(TenantId tenantId, ClassifierInstance classifierInstance,
242             WriteTransaction wTx) {
243         InstanceIdentifier<ClassifierInstance> classifierInstanceIid = IidFactory.classifierInstanceIid(tenantId,
244                 classifierInstance.getName());
245         if (!createdClassifierInstances.contains(classifierInstanceIid)) {
246             wTx.put(LogicalDatastoreType.CONFIGURATION, classifierInstanceIid, classifierInstance, true);
247         }
248         createdClassifierInstances.add(classifierInstanceIid);
249     }
250
251     @VisibleForTesting
252     void createAllowActionInstanceIfNotExists(TenantId tenantId, ReadWriteTransaction rwTx) {
253         InstanceIdentifier<ActionInstance> actionInstanceIid = IidFactory.actionInstanceIid(tenantId,
254                 MappingUtils.ACTION_ALLOW.getName());
255         if (!createdActionInstances.contains(actionInstanceIid)) {
256             rwTx.put(LogicalDatastoreType.CONFIGURATION, actionInstanceIid, MappingUtils.ACTION_ALLOW, true);
257         }
258         createdActionInstances.add(actionInstanceIid);
259     }
260
261     @Override
262     public void onUpdated(SecurityRule oldSecRule, SecurityRule newSecRule, Neutron oldNeutron, Neutron newNeutron) {
263         LOG.warn("updated securityRule - Never should be called "
264                 + "- neutron API does not allow UPDATE on neutron security group rule. \nSecurity group rule: {}",
265                 newSecRule);
266     }
267
268     @Override
269     public void onDeleted(SecurityRule deletedSecRule, Neutron oldNeutron, Neutron newNeutron) {
270         LOG.trace("deleted securityRule - {}", deletedSecRule);
271         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
272         boolean isNeutronSecurityRuleDeleted = deleteNeutronSecurityRule(deletedSecRule, oldNeutron, rwTx);
273         if (isNeutronSecurityRuleDeleted) {
274             DataStoreHelper.submitToDs(rwTx);
275         } else {
276             rwTx.cancel();
277         }
278     }
279
280     public boolean deleteNeutronSecurityRule(SecurityRule secRule, Neutron neutron, ReadWriteTransaction rwTx) {
281         TenantId tenantId = new TenantId(secRule.getTenantId().getValue());
282         Uuid providerSecGroupId = secRule.getSecurityGroupId();
283         EndpointGroupId providerEpgId = new EndpointGroupId(providerSecGroupId.getValue());
284
285         SelectorName providerSelector = getSelectorNameWithConsumer(secRule, neutron);
286         deleteProviderNamedSelectorFromEpg(providerSelector, new EpgKeyDto(providerEpgId, tenantId), rwTx);
287
288         if (secRule.getRemoteGroupId() != null) {
289             Uuid consumerSecGroupId = secRule.getRemoteGroupId();
290             undesignContractsBetweenProviderAndConsumer(tenantId, providerSecGroupId, consumerSecGroupId, secRule, neutron, rwTx);
291             undesignContractsBetweenProviderAndConsumer(tenantId, consumerSecGroupId, providerSecGroupId, secRule, neutron, rwTx);
292         } else {
293             for (Uuid consumerSecGroupId : SecurityRuleUtils.findSecurityGroupsHavingSecurityRules(neutron)) {
294                 undesignContractsBetweenProviderAndConsumer(tenantId, providerSecGroupId, consumerSecGroupId, secRule, neutron, rwTx);
295                 undesignContractsBetweenProviderAndConsumer(tenantId, consumerSecGroupId, providerSecGroupId, secRule, neutron, rwTx);
296             }
297         }
298
299         ContractId contractId = SecRuleEntityDecoder.getContractId(secRule);
300         rwTx.delete(LogicalDatastoreType.CONFIGURATION, IidFactory.contractIid(tenantId, contractId));
301
302         ClassifierInstance classifierInstance = SecRuleEntityDecoder.getClassifierInstance(secRule);
303         deleteClassifierInstanceIfNotUsed(tenantId, classifierInstance, rwTx);
304         return true;
305     }
306
307     @VisibleForTesting
308     void undesignContractsBetweenProviderAndConsumer(TenantId tenantId, Uuid provSecGroupId,
309             Uuid consSecGroupId, SecurityRule removedSecRule, Neutron neutron, ReadWriteTransaction rwTx) {
310         Set<SecurityRule> provSecRules = getProvidedSecRulesBetween(provSecGroupId, consSecGroupId, neutron);
311         Set<SecurityRule> consSecRules = getProvidedSecRulesBetween(consSecGroupId, provSecGroupId, neutron);
312         EndpointGroupId consEpgId = new EndpointGroupId(consSecGroupId.getValue());
313         for (SecurityRule provSecRule : provSecRules) {
314             if (isProvidersSecRuleSuitableForConsumersSecRulesAndGoodToRemove(provSecRule, consSecRules, removedSecRule)) {
315                 SelectorName consumerSelector = getSelectorNameWithProvider(provSecRule, neutron);
316                 deleteConsumerNamedSelector(consumerSelector, new EpgKeyDto(consEpgId, tenantId), rwTx);
317             }
318             // TODO add case when port ranges overlap
319         }
320     }
321
322     @VisibleForTesting
323     static boolean isProvidersSecRuleSuitableForConsumersSecRulesAndGoodToRemove(SecurityRule provSecRule,
324             Set<SecurityRule> consSecRules, SecurityRule removedSecRule) {
325         Direction directionProvSecRule = SecRuleEntityDecoder.getDirection(provSecRule);
326         for (SecurityRule consSecRule : consSecRules) {
327             if (isRuleIdEqual(removedSecRule, consSecRule) || isRuleIdEqual(removedSecRule, provSecRule)) {
328                 Direction directionConsSecRule = SecRuleEntityDecoder.getDirection(consSecRule);
329                 if (isDirectionOpposite(directionProvSecRule, directionConsSecRule)
330                         && isOneWithinTwo(provSecRule, consSecRule)) {
331                     return true;
332                 }
333             }
334         }
335         return false;
336     }
337
338     @VisibleForTesting
339     static boolean isRuleIdEqual(SecurityRule one, SecurityRule two) {
340         checkNotNull(one);
341         checkNotNull(two);
342         return one.getSecurityGroupId().equals(two.getSecurityGroupId());
343     }
344
345     private void deleteProviderNamedSelectorFromEpg(SelectorName providerSelector, EpgKeyDto providerEpgKey,
346             ReadWriteTransaction rwTx) {
347         InstanceIdentifier<ProviderNamedSelector> providerSelectorIid = IidFactory.providerNamedSelectorIid(
348                 providerEpgKey.getTenantId(), providerEpgKey.getEpgId(), providerSelector);
349         DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, providerSelectorIid, rwTx);
350     }
351
352     private void deleteConsumerNamedSelector(SelectorName consumerSelector, EpgKeyDto consumerEpgKey,
353             ReadWriteTransaction rwTx) {
354         InstanceIdentifier<ConsumerNamedSelector> consumerSelectorIid = IidFactory.consumerNamedSelectorIid(
355                 consumerEpgKey.getTenantId(), consumerEpgKey.getEpgId(), consumerSelector);
356         DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, consumerSelectorIid, rwTx);
357     }
358
359     private void deleteClassifierInstanceIfNotUsed(TenantId tenantId, ClassifierInstance classifierInstance,
360             ReadWriteTransaction rwTx) {
361         InstanceIdentifier<ClassifierInstance> classifierInstanceIid = IidFactory.classifierInstanceIid(tenantId,
362                 classifierInstance.getName());
363         createdClassifierInstances.remove(classifierInstanceIid);
364         if (!createdClassifierInstances.contains(classifierInstanceIid)) {
365             DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, classifierInstanceIid, rwTx);
366         }
367     }
368
369     @VisibleForTesting
370     void deleteAllowActionInstanceIfNotUsed(TenantId tenantId, ReadWriteTransaction rwTx) {
371         InstanceIdentifier<ActionInstance> actionInstanceIid = IidFactory.actionInstanceIid(tenantId,
372                 MappingUtils.ACTION_ALLOW.getName());
373         createdActionInstances.remove(actionInstanceIid);
374         if (!createdActionInstances.contains(actionInstanceIid)) {
375             DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, actionInstanceIid, rwTx);
376         }
377     }
378
379     private SelectorName getSelectorNameWithConsumer(SecurityRule secRule, Neutron neutron) {
380         ClauseName clauseName = SecRuleNameDecoder.getClauseName(secRule);
381         StringBuilder selectorNameBuilder = new StringBuilder().append(clauseName.getValue());
382         Uuid consumerSecGroupId = secRule.getRemoteGroupId();
383         if (consumerSecGroupId == null) {
384             return new SelectorName(selectorNameBuilder.toString());
385         }
386
387         // we cannot use name of security group in selector, because name can be changed
388         // therefore name is used only in debug mode
389         if (NeutronMapperModule.isDebugEnabled()) {
390             Optional<SecurityGroup> potentialConsumerSecGroup =
391                     SecurityGroupUtils.findSecurityGroup(secRule.getRemoteGroupId(), neutron.getSecurityGroups());
392             if (!potentialConsumerSecGroup.isPresent()) {
393                 LOG.error("Neutron Security Group with UUID {} does not exist but it is in {}",
394                         consumerSecGroupId.getValue(), secRule);
395                 throw new IllegalStateException(
396                         "Neutron Security Group with UUID " + consumerSecGroupId.getValue() + " does not exist.");
397             }
398
399             selectorNameBuilder.append(MappingUtils.NAME_DOUBLE_DELIMETER)
400                 .append(POSSIBLE_CONSUMER)
401                 .append(SecurityGroupUtils.getNameOrUuid(potentialConsumerSecGroup.get()));
402             return new SelectorName(selectorNameBuilder.toString());
403         }
404
405         selectorNameBuilder.append(MappingUtils.NAME_DOUBLE_DELIMETER)
406             .append(POSSIBLE_CONSUMER)
407             .append(consumerSecGroupId.getValue());
408         return new SelectorName(selectorNameBuilder.toString());
409     }
410
411     private SelectorName getSelectorNameWithProvider(SecurityRule secRule, Neutron neutron) {
412         ClauseName clauseName = SecRuleNameDecoder.getClauseName(secRule);
413         Uuid providerSecGroupId = secRule.getSecurityGroupId();
414
415         // we cannot use name of security group in selector, because name can be changed
416         // therefore name is used only in debug mode
417         if (NeutronMapperModule.isDebugEnabled()) {
418             Optional<SecurityGroup> potentialProviderSecGroup =
419                     SecurityGroupUtils.findSecurityGroup(secRule.getSecurityGroupId(), neutron.getSecurityGroups());
420             if (!potentialProviderSecGroup.isPresent()) {
421                 LOG.error("Neutron Security Group with UUID {} does not exist but it is in {}",
422                         providerSecGroupId.getValue(), secRule);
423                 throw new IllegalStateException(
424                         "Neutron Security Group with UUID " + providerSecGroupId.getValue() + " does not exist.");
425             }
426             String selectorName = new StringBuilder().append(clauseName.getValue())
427                 .append(MappingUtils.NAME_DOUBLE_DELIMETER)
428                 .append(PROVIDED_BY)
429                 .append(SecurityGroupUtils.getNameOrUuid(potentialProviderSecGroup.get()))
430                 .toString();
431             return new SelectorName(selectorName);
432         }
433
434         String selectorName = new StringBuilder().append(clauseName.getValue())
435             .append(MappingUtils.NAME_DOUBLE_DELIMETER)
436             .append(PROVIDED_BY)
437             .append(providerSecGroupId.getValue())
438             .toString();
439         return new SelectorName(selectorName);
440     }
441
442     @VisibleForTesting
443     static boolean isDirectionOpposite(Direction one, Direction two) {
444         return (one == Direction.In && two == Direction.Out) || (one == Direction.Out && two == Direction.In);
445     }
446
447     @VisibleForTesting
448     static boolean isOneWithinTwo(SecurityRule one, SecurityRule two) {
449         if (!isOneGroupIdWithinTwoRemoteGroupId(one, two) || !isOneGroupIdWithinTwoRemoteGroupId(two, one))
450             return false;
451         if (!SecRuleEntityDecoder.isEtherTypeOfOneWithinTwo(one, two))
452             return false;
453         if (!SecRuleEntityDecoder.isProtocolOfOneWithinTwo(one, two))
454             return false;
455         if (!SecRuleEntityDecoder.isPortsOfOneWithinTwo(one, two))
456             return false;
457         if (two.getRemoteIpPrefix() != null
458                 && one.getRemoteIpPrefix() == null)
459             return false;
460         return true;
461     }
462
463     @VisibleForTesting
464     static boolean isOneGroupIdWithinTwoRemoteGroupId(SecurityRule one, SecurityRule two) {
465         return (two.getRemoteGroupId() == null || two.getRemoteGroupId().equals(
466                 one.getSecurityGroupId()));
467     }
468
469 }