2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule;
11 import static com.google.common.base.Preconditions.checkNotNull;
13 import java.util.HashMap;
14 import java.util.List;
17 import java.util.stream.Collectors;
19 import javax.annotation.Nonnull;
21 import org.opendaylight.controller.config.yang.config.neutron_mapper.impl.NeutronMapperModule;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
27 import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
28 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
29 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronAware;
30 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSecurityGroupAware;
31 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
32 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
33 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SecurityGroupUtils;
34 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SecurityRuleUtils;
35 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
36 import org.opendaylight.groupbasedpolicy.util.IidFactory;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.ActionChoice;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.change.action.of.security.group.rules.input.action.action.choice.SfcActionCase;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroupBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroupBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelector;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelectorBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderNamedSelector;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderNamedSelectorBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstanceBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroupKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRuleKey;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
76 import com.google.common.annotations.VisibleForTesting;
77 import com.google.common.base.Optional;
78 import com.google.common.base.Preconditions;
79 import com.google.common.collect.HashMultiset;
80 import com.google.common.collect.ImmutableList;
81 import com.google.common.collect.Multiset;
82 import com.google.common.collect.Sets;
84 public class NeutronSecurityRuleAware implements NeutronAware<SecurityRule> {
86 private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleAware.class);
87 public static final InstanceIdentifier<SecurityRule> SECURITY_RULE_WILDCARD_IID =
88 InstanceIdentifier.builder(Neutron.class).child(SecurityRules.class).child(SecurityRule.class).build();
89 private static final String CONTRACT_PROVIDER = "Contract provider: ";
90 private final DataBroker dataProvider;
91 private final Multiset<InstanceIdentifier<ClassifierInstance>> createdClassifierInstances;
92 private final Multiset<InstanceIdentifier<ActionInstance>> createdActionInstances;
93 private final Map<SecurityRuleKey, SecurityRule> pendingCreatedRules;
94 private final Map<SecurityGroupKey, SecurityGroup> pendingDeletedGroups;
95 final static String PROVIDED_BY = "provided_by-";
96 final static String POSSIBLE_CONSUMER = "possible_consumer-";
97 private final EndpointRegistrator epRegistrator;
99 public NeutronSecurityRuleAware(DataBroker dataProvider, EndpointRegistrator epRegistrator) {
100 this(dataProvider, HashMultiset.<InstanceIdentifier<ClassifierInstance>>create(),
101 HashMultiset.<InstanceIdentifier<ActionInstance>>create(), epRegistrator);
105 NeutronSecurityRuleAware(DataBroker dataProvider,
106 Multiset<InstanceIdentifier<ClassifierInstance>> classifierInstanceNames,
107 Multiset<InstanceIdentifier<ActionInstance>> createdActionInstances, EndpointRegistrator epRegistrator) {
108 this.dataProvider = checkNotNull(dataProvider);
109 this.createdClassifierInstances = checkNotNull(classifierInstanceNames);
110 this.createdActionInstances = checkNotNull(createdActionInstances);
111 this.pendingCreatedRules = new HashMap<>();
112 this.pendingDeletedGroups = new HashMap<>();
113 this.epRegistrator = Preconditions.checkNotNull(epRegistrator);
117 public void onCreated(SecurityRule secRule, Neutron neutron) {
118 LOG.trace("created securityRule - {}", secRule);
119 if (neutron.getSecurityGroups() == null || neutron.getSecurityGroups().getSecurityGroup() == null
120 || !neutron.getSecurityGroups()
123 .filter(sg -> sg.getKey().getUuid().equals(secRule.getSecurityGroupId()))
126 pendingCreatedRules.put(secRule.getKey(), secRule);
127 LOG.warn("Security group of security rule {} does not exist yet. The rule will be processed"
128 + "when the missing security group is created.", secRule.getKey());
131 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
132 boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(secRule, neutron, rwTx);
133 if (isNeutronSecurityRuleAdded) {
134 DataStoreHelper.submitToDs(rwTx);
140 public void flushPendingSecurityRulesFor(@Nonnull SecurityGroupKey secGroupKey, Neutron neutron) {
141 List<SecurityRule> rules = pendingCreatedRules.values()
143 .filter(sr -> sr.getSecurityGroupId().equals(secGroupKey.getUuid()))
144 .collect(Collectors.toList());
145 rules.forEach(sr -> {
146 LOG.trace("Flushing pending security rule {}", sr);
147 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
148 boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(sr, neutron, rwTx);
149 if (isNeutronSecurityRuleAdded) {
150 DataStoreHelper.submitToDs(rwTx);
154 pendingCreatedRules.remove(sr.getKey());
158 public boolean addNeutronSecurityRule(SecurityRule secRule, Neutron neutron, ReadWriteTransaction rwTx) {
159 return addNeutronSecurityRuleWithAction(secRule, neutron, MappingUtils.ALLOW_ACTION_CHOICE, rwTx);
162 public boolean addNeutronSecurityRuleWithAction(SecurityRule secRule, Neutron neutron, ActionChoice action,
163 ReadWriteTransaction rwTx) {
164 TenantId tenantId = new TenantId(secRule.getTenantId().getValue());
165 Uuid providerSecGroupId = secRule.getSecurityGroupId();
166 EndpointGroupId providerEpgId = new EndpointGroupId(providerSecGroupId.getValue());
168 Description contractDescription = createContractDescription(secRule, neutron);
169 SingleRuleContract singleRuleContract = createSingleRuleContract(secRule, contractDescription, action, neutron);
170 Contract contract = singleRuleContract.getContract();
171 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.contractIid(tenantId, contract.getId()), contract, true);
172 SelectorName providerSelector = getSelectorNameWithConsumer(secRule, neutron);
173 writeProviderNamedSelectorToEpg(providerSelector, contract.getId(), new EpgKeyDto(providerEpgId, tenantId), rwTx);
175 if (secRule.getRemoteGroupId() != null) {
176 Uuid consumerSecGroupId = secRule.getRemoteGroupId();
177 designContractsBetweenProviderAndConsumer(tenantId, providerSecGroupId, consumerSecGroupId, neutron, rwTx);
178 designContractsBetweenProviderAndConsumer(tenantId, consumerSecGroupId, providerSecGroupId, neutron, rwTx);
180 for (Uuid consumerSecGroupId : SecurityRuleUtils.findSecurityGroupsHavingSecurityRules(neutron)) {
181 designContractsBetweenProviderAndConsumer(tenantId, providerSecGroupId, consumerSecGroupId, neutron, rwTx);
182 designContractsBetweenProviderAndConsumer(tenantId, consumerSecGroupId, providerSecGroupId, neutron, rwTx);
186 ClassifierInstance classifierInstance = singleRuleContract.getSingleClassifierRule().getClassifierInstance();
187 createClassifierInstanceIfNotExists(tenantId, classifierInstance, rwTx);
188 createAllowActionInstanceIfNotExists(tenantId, rwTx);
193 static Description createContractDescription(SecurityRule secRule, Neutron neutron) {
194 if (NeutronMapperModule.isDebugEnabled()) {
195 Optional<SecurityGroup> providerSecGroup =
196 SecurityGroupUtils.findSecurityGroup(secRule.getSecurityGroupId(), neutron.getSecurityGroups());
197 if (!providerSecGroup.isPresent()) {
198 LOG.error("Neutron Security Group with UUID {} does not exist but it is in {}", secRule.getSecurityGroupId().getValue(),
200 throw new IllegalStateException(
201 "Neutron Security Group with UUID " + secRule.getSecurityGroupId().getValue() + " does not exist.");
203 return new Description(CONTRACT_PROVIDER + SecurityGroupUtils.getNameOrUuid(providerSecGroup.get()));
206 return new Description(CONTRACT_PROVIDER + secRule.getSecurityGroupId());
210 SingleRuleContract createSingleRuleContract(SecurityRule secRule, Description contractDescription,
211 ActionChoice action, Neutron neutron) {
212 if (secRule.getRemoteIpPrefix() != null) {
213 if (neutron.getNetworks() != null && neutron.getNetworks().getNetwork() != null) {
214 java.util.Optional<Network> publicNet = neutron.getNetworks()
217 .filter(net -> NetworkUtils.isRouterExternal(net))
219 if (publicNet.isPresent()) {
220 WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
221 wTx.merge(LogicalDatastoreType.CONFIGURATION,
222 IidFactory.externalImplicitGroupIid(new TenantId(secRule.getTenantId().getValue()),
223 MappingUtils.EPG_EXTERNAL_ID),
224 new ExternalImplicitGroupBuilder().setId(MappingUtils.EPG_EXTERNAL_ID).build(), true);
225 wTx.merge(LogicalDatastoreType.CONFIGURATION,
226 IidFactory.endpointGroupIid(new TenantId(secRule.getTenantId().getValue()),
227 MappingUtils.EPG_EXTERNAL_ID),
228 new EndpointGroupBuilder().setId(MappingUtils.EPG_EXTERNAL_ID).build(), true);
229 DataStoreHelper.submitToDs(wTx);
230 AddressEndpointRegBuilder addrEpbuilder = new AddressEndpointRegBuilder()
231 .setAddress(String.valueOf(secRule.getRemoteIpPrefix().getValue()))
232 .setAddressType(IpPrefixType.class)
233 .setContextType(MappingUtils.L3_CONTEXT)
234 .setContextId(new ContextId(publicNet.get().getUuid().getValue()))
235 .setTenant(new TenantId(secRule.getTenantId().getValue()))
236 .setTimestamp(System.currentTimeMillis())
237 .setEndpointGroup(ImmutableList.<EndpointGroupId>of(MappingUtils.EPG_EXTERNAL_ID));
238 RegisterEndpointInput regEp = new RegisterEndpointInputBuilder()
239 .setAddressEndpointReg(ImmutableList.of(addrEpbuilder.build())).build();
240 boolean registered = epRegistrator.registerEndpoint(regEp);
242 LOG.info("Registering endpoint representing remote-ip-prefix {}", addrEpbuilder.getKey());
244 LOG.error("Failed to register endpoint {}", addrEpbuilder.getKey());
248 return new SingleRuleContract(secRule, 0, contractDescription, action);
250 return new SingleRuleContract(secRule, 400, contractDescription, action);
254 void designContractsBetweenProviderAndConsumer(TenantId tenantId, Uuid provSecGroupId, Uuid consSecGroupId,
255 Neutron neutron, ReadWriteTransaction rwTx) {
256 Set<SecurityRule> provSecRules = getProvidedSecRulesBetween(provSecGroupId, consSecGroupId, neutron);
257 Set<SecurityRule> consSecRules = getProvidedSecRulesBetween(consSecGroupId, provSecGroupId, neutron);
258 EndpointGroupId consEpgId = new EndpointGroupId(consSecGroupId.getValue());
259 for (SecurityRule provSecRule : provSecRules) {
260 if (isProviderSecRuleSuitableForConsumerSecRules(provSecRule, consSecRules)) {
261 SelectorName consumerSelector = getSelectorNameWithProvider(provSecRule, neutron);
262 ContractId contractId = SecRuleEntityDecoder.getContractId(provSecRule);
263 writeConsumerNamedSelectorToEpg(consumerSelector, contractId, new EpgKeyDto(consEpgId, tenantId), rwTx);
265 // TODO add case when port ranges overlap
270 Set<SecurityRule> getProvidedSecRulesBetween(Uuid provSecGroup, Uuid consSecGroup, Neutron neutron) {
271 return Sets.union(SecurityRuleUtils.findSecurityRulesBySecGroupAndRemoteSecGroup(provSecGroup, consSecGroup, neutron),
272 SecurityRuleUtils.findSecurityRulesBySecGroupAndRemoteSecGroup(provSecGroup, null, neutron));
276 static boolean isProviderSecRuleSuitableForConsumerSecRules(SecurityRule provSecRule,
277 Set<SecurityRule> consSecRules) {
278 Direction directionProvSecRule = SecRuleEntityDecoder.getDirection(provSecRule);
279 for (SecurityRule consSecRule : consSecRules) {
280 Direction directionConsSecRule = SecRuleEntityDecoder.getDirection(consSecRule);
281 if (isDirectionOpposite(directionProvSecRule, directionConsSecRule)
282 && isOneWithinTwo(provSecRule, consSecRule)) {
289 public boolean changeActionOfNeutronSecurityRule(SecurityRule secRule, ActionChoice action, Neutron neutron, ReadWriteTransaction rwTx) {
290 addSfcChainActionInstance(action, new TenantId(secRule.getTenantId().getValue()), rwTx);
291 LOG.trace("Changing to action {} for secuirity group rule {}", action, secRule);
292 return addNeutronSecurityRuleWithAction(secRule, neutron, action, rwTx);
295 private void addSfcChainActionInstance(ActionChoice action, TenantId tenantId, ReadWriteTransaction rwTx) {
296 if (action instanceof SfcActionCase) {
297 String sfcChainName = ((SfcActionCase) action).getSfcChainName();
298 ActionName actionName = new ActionName(sfcChainName);
299 ActionInstance sfcActionInstance = new ActionInstanceBuilder().setName(actionName)
300 .setActionDefinitionId(ChainActionDefinition.ID)
302 ImmutableList.of(new ParameterValueBuilder().setName(
303 new ParameterName(ChainActionDefinition.SFC_CHAIN_NAME))
304 .setStringValue(sfcChainName)
307 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.actionInstanceIid(tenantId, actionName),
308 sfcActionInstance, true);
312 private void writeProviderNamedSelectorToEpg(SelectorName providerSelector, ContractId contractId, EpgKeyDto epgKey,
313 WriteTransaction wTx) {
314 ProviderNamedSelector providerNamedSelector = new ProviderNamedSelectorBuilder().setName(providerSelector)
315 .setContract(ImmutableList.of(contractId))
317 wTx.put(LogicalDatastoreType.CONFIGURATION,
318 IidFactory.providerNamedSelectorIid(epgKey.getTenantId(), epgKey.getEpgId(),
319 providerNamedSelector.getName()), providerNamedSelector, true);
322 private void writeConsumerNamedSelectorToEpg(SelectorName consumerSelector, ContractId contractId, EpgKeyDto epgKey,
323 WriteTransaction wTx) {
324 ConsumerNamedSelector consumerNamedSelector = new ConsumerNamedSelectorBuilder().setName(consumerSelector)
325 .setContract(ImmutableList.of(contractId))
327 wTx.put(LogicalDatastoreType.CONFIGURATION,
328 IidFactory.consumerNamedSelectorIid(epgKey.getTenantId(), epgKey.getEpgId(),
329 consumerNamedSelector.getName()), consumerNamedSelector, true);
333 void createClassifierInstanceIfNotExists(TenantId tenantId, ClassifierInstance classifierInstance,
334 WriteTransaction wTx) {
335 InstanceIdentifier<ClassifierInstance> classifierInstanceIid = IidFactory.classifierInstanceIid(tenantId,
336 classifierInstance.getName());
337 if (!createdClassifierInstances.contains(classifierInstanceIid)) {
338 wTx.put(LogicalDatastoreType.CONFIGURATION, classifierInstanceIid, classifierInstance, true);
340 createdClassifierInstances.add(classifierInstanceIid);
344 void createAllowActionInstanceIfNotExists(TenantId tenantId, ReadWriteTransaction rwTx) {
345 InstanceIdentifier<ActionInstance> actionInstanceIid = IidFactory.actionInstanceIid(tenantId,
346 MappingUtils.ACTION_ALLOW.getName());
347 if (!createdActionInstances.contains(actionInstanceIid)) {
348 rwTx.put(LogicalDatastoreType.CONFIGURATION, actionInstanceIid, MappingUtils.ACTION_ALLOW, true);
350 createdActionInstances.add(actionInstanceIid);
354 public void onUpdated(SecurityRule oldSecRule, SecurityRule newSecRule, Neutron oldNeutron, Neutron newNeutron) {
355 LOG.warn("updated securityRule - Never should be called "
356 + "- neutron API does not allow UPDATE on neutron security group rule. \nSecurity group rule: {}",
360 public void addPendingDeletedSecGroup(SecurityGroup secGroup) {
361 LOG.trace("Caching pending deleted security group {}", secGroup.getKey());
362 pendingDeletedGroups.put(secGroup.getKey(), secGroup);
366 public void onDeleted(SecurityRule deletedSecRule, Neutron oldNeutron, Neutron newNeutron) {
367 LOG.trace("deleted securityRule - {}", deletedSecRule);
368 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
369 boolean isNeutronSecurityRuleDeleted = deleteNeutronSecurityRule(deletedSecRule, oldNeutron, rwTx);
370 if (isNeutronSecurityRuleDeleted) {
371 DataStoreHelper.submitToDs(rwTx);
372 if (newNeutron == null || newNeutron.getSecurityRules() == null
373 || newNeutron.getSecurityRules().getSecurityRule() == null
374 || !newNeutron.getSecurityRules()
377 .filter(rule -> rule.getSecurityGroupId().equals(deletedSecRule.getSecurityGroupId()))
380 SecurityGroupKey secGroupKey = new SecurityGroupKey(deletedSecRule.getSecurityGroupId());
381 SecurityGroup pendingSg = pendingDeletedGroups.get(secGroupKey);
382 if (pendingSg != null) {
383 LOG.trace("Processing pending deleted security group {}", secGroupKey);
384 NeutronSecurityGroupAware.deleteGbpEndpointGroup(dataProvider,
385 new TenantId(deletedSecRule.getTenantId().getValue()),
386 new EndpointGroupId(secGroupKey.getUuid().getValue()));
387 pendingDeletedGroups.remove(secGroupKey);
395 public boolean deleteNeutronSecurityRule(SecurityRule secRule, Neutron neutron, ReadWriteTransaction rwTx) {
396 TenantId tenantId = new TenantId(secRule.getTenantId().getValue());
397 Uuid providerSecGroupId = secRule.getSecurityGroupId();
398 EndpointGroupId providerEpgId = new EndpointGroupId(providerSecGroupId.getValue());
400 SelectorName providerSelector = getSelectorNameWithConsumer(secRule, neutron);
401 deleteProviderNamedSelectorFromEpg(providerSelector, new EpgKeyDto(providerEpgId, tenantId), rwTx);
403 if (secRule.getRemoteGroupId() != null) {
404 Uuid consumerSecGroupId = secRule.getRemoteGroupId();
405 undesignContractsBetweenProviderAndConsumer(tenantId, providerSecGroupId, consumerSecGroupId, secRule, neutron, rwTx);
406 undesignContractsBetweenProviderAndConsumer(tenantId, consumerSecGroupId, providerSecGroupId, secRule, neutron, rwTx);
408 for (Uuid consumerSecGroupId : SecurityRuleUtils.findSecurityGroupsHavingSecurityRules(neutron)) {
409 undesignContractsBetweenProviderAndConsumer(tenantId, providerSecGroupId, consumerSecGroupId, secRule, neutron, rwTx);
410 undesignContractsBetweenProviderAndConsumer(tenantId, consumerSecGroupId, providerSecGroupId, secRule, neutron, rwTx);
414 ContractId contractId = SecRuleEntityDecoder.getContractId(secRule);
415 rwTx.delete(LogicalDatastoreType.CONFIGURATION, IidFactory.contractIid(tenantId, contractId));
417 ClassifierInstance classifierInstance = SecRuleEntityDecoder.getClassifierInstance(secRule);
418 deleteClassifierInstanceIfNotUsed(tenantId, classifierInstance, rwTx);
423 void undesignContractsBetweenProviderAndConsumer(TenantId tenantId, Uuid provSecGroupId,
424 Uuid consSecGroupId, SecurityRule removedSecRule, Neutron neutron, ReadWriteTransaction rwTx) {
425 Set<SecurityRule> provSecRules = getProvidedSecRulesBetween(provSecGroupId, consSecGroupId, neutron);
426 Set<SecurityRule> consSecRules = getProvidedSecRulesBetween(consSecGroupId, provSecGroupId, neutron);
427 EndpointGroupId consEpgId = new EndpointGroupId(consSecGroupId.getValue());
428 for (SecurityRule provSecRule : provSecRules) {
429 if (isProvidersSecRuleSuitableForConsumersSecRulesAndGoodToRemove(provSecRule, consSecRules, removedSecRule)) {
430 SelectorName consumerSelector = getSelectorNameWithProvider(provSecRule, neutron);
431 deleteConsumerNamedSelector(consumerSelector, new EpgKeyDto(consEpgId, tenantId), rwTx);
433 // TODO add case when port ranges overlap
438 static boolean isProvidersSecRuleSuitableForConsumersSecRulesAndGoodToRemove(SecurityRule provSecRule,
439 Set<SecurityRule> consSecRules, SecurityRule removedSecRule) {
440 Direction directionProvSecRule = SecRuleEntityDecoder.getDirection(provSecRule);
441 for (SecurityRule consSecRule : consSecRules) {
442 if (isRuleIdEqual(removedSecRule, consSecRule) || isRuleIdEqual(removedSecRule, provSecRule)) {
443 Direction directionConsSecRule = SecRuleEntityDecoder.getDirection(consSecRule);
444 if (isDirectionOpposite(directionProvSecRule, directionConsSecRule)
445 && isOneWithinTwo(provSecRule, consSecRule)) {
454 static boolean isRuleIdEqual(SecurityRule one, SecurityRule two) {
457 return one.getSecurityGroupId().equals(two.getSecurityGroupId());
460 private void deleteProviderNamedSelectorFromEpg(SelectorName providerSelector, EpgKeyDto providerEpgKey,
461 ReadWriteTransaction rwTx) {
462 InstanceIdentifier<ProviderNamedSelector> providerSelectorIid = IidFactory.providerNamedSelectorIid(
463 providerEpgKey.getTenantId(), providerEpgKey.getEpgId(), providerSelector);
464 DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, providerSelectorIid, rwTx);
467 private void deleteConsumerNamedSelector(SelectorName consumerSelector, EpgKeyDto consumerEpgKey,
468 ReadWriteTransaction rwTx) {
469 InstanceIdentifier<ConsumerNamedSelector> consumerSelectorIid = IidFactory.consumerNamedSelectorIid(
470 consumerEpgKey.getTenantId(), consumerEpgKey.getEpgId(), consumerSelector);
471 DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, consumerSelectorIid, rwTx);
474 private void deleteClassifierInstanceIfNotUsed(TenantId tenantId, ClassifierInstance classifierInstance,
475 ReadWriteTransaction rwTx) {
476 InstanceIdentifier<ClassifierInstance> classifierInstanceIid = IidFactory.classifierInstanceIid(tenantId,
477 classifierInstance.getName());
478 createdClassifierInstances.remove(classifierInstanceIid);
479 if (!createdClassifierInstances.contains(classifierInstanceIid)) {
480 DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, classifierInstanceIid, rwTx);
485 void deleteAllowActionInstanceIfNotUsed(TenantId tenantId, ReadWriteTransaction rwTx) {
486 InstanceIdentifier<ActionInstance> actionInstanceIid = IidFactory.actionInstanceIid(tenantId,
487 MappingUtils.ACTION_ALLOW.getName());
488 createdActionInstances.remove(actionInstanceIid);
489 if (!createdActionInstances.contains(actionInstanceIid)) {
490 DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, actionInstanceIid, rwTx);
494 private SelectorName getSelectorNameWithConsumer(SecurityRule secRule, Neutron neutron) {
495 ClauseName clauseName = SecRuleNameDecoder.getClauseName(secRule);
496 StringBuilder selectorNameBuilder = new StringBuilder().append(clauseName.getValue());
497 Uuid consumerSecGroupId = secRule.getRemoteGroupId();
498 if (consumerSecGroupId == null) {
499 return new SelectorName(selectorNameBuilder.toString());
502 // we cannot use name of security group in selector, because name can be changed
503 // therefore name is used only in debug mode
504 if (NeutronMapperModule.isDebugEnabled()) {
505 Optional<SecurityGroup> potentialConsumerSecGroup =
506 SecurityGroupUtils.findSecurityGroup(secRule.getRemoteGroupId(), neutron.getSecurityGroups());
507 if (!potentialConsumerSecGroup.isPresent()) {
508 LOG.error("Neutron Security Group with UUID {} does not exist but it is in {}",
509 consumerSecGroupId.getValue(), secRule);
510 throw new IllegalStateException(
511 "Neutron Security Group with UUID " + consumerSecGroupId.getValue() + " does not exist.");
514 selectorNameBuilder.append(MappingUtils.NAME_DOUBLE_DELIMETER)
515 .append(POSSIBLE_CONSUMER)
516 .append(SecurityGroupUtils.getNameOrUuid(potentialConsumerSecGroup.get()));
517 return new SelectorName(selectorNameBuilder.toString());
520 selectorNameBuilder.append(MappingUtils.NAME_DOUBLE_DELIMETER)
521 .append(POSSIBLE_CONSUMER)
522 .append(consumerSecGroupId.getValue());
523 return new SelectorName(selectorNameBuilder.toString());
526 private SelectorName getSelectorNameWithProvider(SecurityRule secRule, Neutron neutron) {
527 ClauseName clauseName = SecRuleNameDecoder.getClauseName(secRule);
528 Uuid providerSecGroupId = secRule.getSecurityGroupId();
530 // we cannot use name of security group in selector, because name can be changed
531 // therefore name is used only in debug mode
532 if (NeutronMapperModule.isDebugEnabled()) {
533 Optional<SecurityGroup> potentialProviderSecGroup =
534 SecurityGroupUtils.findSecurityGroup(secRule.getSecurityGroupId(), neutron.getSecurityGroups());
535 if (!potentialProviderSecGroup.isPresent()) {
536 LOG.error("Neutron Security Group with UUID {} does not exist but it is in {}",
537 providerSecGroupId.getValue(), secRule);
538 throw new IllegalStateException(
539 "Neutron Security Group with UUID " + providerSecGroupId.getValue() + " does not exist.");
541 String selectorName = new StringBuilder().append(clauseName.getValue())
542 .append(MappingUtils.NAME_DOUBLE_DELIMETER)
544 .append(SecurityGroupUtils.getNameOrUuid(potentialProviderSecGroup.get()))
546 return new SelectorName(selectorName);
549 String selectorName = new StringBuilder().append(clauseName.getValue())
550 .append(MappingUtils.NAME_DOUBLE_DELIMETER)
552 .append(providerSecGroupId.getValue())
554 return new SelectorName(selectorName);
558 static boolean isDirectionOpposite(Direction one, Direction two) {
559 return (one == Direction.In && two == Direction.Out) || (one == Direction.Out && two == Direction.In);
563 static boolean isOneWithinTwo(SecurityRule one, SecurityRule two) {
564 if (!isOneGroupIdWithinTwoRemoteGroupId(one, two) || !isOneGroupIdWithinTwoRemoteGroupId(two, one))
566 if (!SecRuleEntityDecoder.isEtherTypeOfOneWithinTwo(one, two))
568 if (!SecRuleEntityDecoder.isProtocolOfOneWithinTwo(one, two))
570 if (!SecRuleEntityDecoder.isPortsOfOneWithinTwo(one, two))
572 if (two.getRemoteIpPrefix() != null
573 && one.getRemoteIpPrefix() == null)
579 static boolean isOneGroupIdWithinTwoRemoteGroupId(SecurityRule one, SecurityRule two) {
580 return (two.getRemoteGroupId() == null || two.getRemoteGroupId().equals(
581 one.getSecurityGroupId()));