1 package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
3 import static com.google.common.base.Preconditions.checkNotNull;
7 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
8 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
9 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
10 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
11 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
12 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.DataStoreHelper;
13 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.IidFactory;
14 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
15 import org.opendaylight.neutron.spi.INeutronSecurityRuleAware;
16 import org.opendaylight.neutron.spi.NeutronSecurityRule;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMapping;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMappingBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 import com.google.common.base.Optional;
47 import com.google.common.collect.ImmutableList;
49 public class NeutronSecurityRuleAware implements INeutronSecurityRuleAware {
51 private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleAware.class);
52 private final DataBroker dataProvider;
54 public NeutronSecurityRuleAware(DataBroker dataProvider) {
55 this.dataProvider = checkNotNull(dataProvider);
59 public int canCreateNeutronSecurityRule(NeutronSecurityRule securityRule) {
60 LOG.trace("canCreateNeutronSecurityRule - {}", securityRule);
61 // nothing to consider
66 public void neutronSecurityRuleCreated(NeutronSecurityRule securityRule) {
67 LOG.trace("neutronSecurityRuleCreated - {}", securityRule);
68 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
69 boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(securityRule, rwTx);
70 if (isNeutronSecurityRuleAdded) {
71 DataStoreHelper.submitToDs(rwTx);
78 * <b>ASSUMPTION</b>: Endpoint group with id
79 * {@link NeutronSecurityRule#getSecurityRuleGroupID()} and
80 * endpoint group with id {@link NeutronSecurityRule#getSecurityRemoteGroupID()} already exist
83 * @param secRule neutron security rule from which GBP entities are created
84 * @param rwTx GBP entities are stored to this transaction. This method NEVER submits or cancel
86 * @return {@code true} if operation was successful; {@code false} if an illegal state occurs -
87 * the transaction may contain just partial result
89 public static boolean addNeutronSecurityRule(NeutronSecurityRule secRule, ReadWriteTransaction rwTx) {
90 TransformSecRule transform = new TransformSecRule(secRule);
91 TenantId tenantId = transform.getTenantId();
92 EndpointGroupId providerEpgId = transform.getProviderEpgId();
93 EndpointGroupId consumerEpgId = transform.getConsumerEpgId();
94 SubjectName subjectName = transform.getSubjectName();
96 Optional<ContractId> potentialContractId = readContractIdFromEpgPairToContractMapping(providerEpgId,
98 ContractId contractId = null;
99 if (potentialContractId.isPresent()) {
100 contractId = potentialContractId.get();
101 Optional<Subject> potentialSubject = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
102 IidFactory.subjectIid(tenantId, contractId, subjectName), rwTx);
103 if (!potentialSubject.isPresent()) {
104 // it also means that clause for this subject does not exist
105 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subjectIid(tenantId, contractId, subjectName),
106 transform.createSubject());
107 rwTx.put(LogicalDatastoreType.CONFIGURATION,
108 IidFactory.clauseIid(tenantId, contractId, transform.getClauseName()), transform.createClause());
111 // check assumption that provider EPG exists
112 Optional<EndpointGroup> potentialProviderEpg = DataStoreHelper.readFromDs(
113 LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId), rwTx);
114 if (!potentialProviderEpg.isPresent()) {
115 LOG.warn("Illegal state - Endpoint group {} does not exist.", providerEpgId.getValue());
119 if (providerEpgId.equals(consumerEpgId)) {
120 EndpointGroup providerConsumerEpg = potentialProviderEpg.get();
121 if (providerConsumerEpg.getIntraGroupPolicy() == null
122 || !providerConsumerEpg.getIntraGroupPolicy().equals(IntraGroupPolicy.RequireContract)) {
123 EndpointGroup newProviderConsumerEpg = new EndpointGroupBuilder(providerConsumerEpg).setIntraGroupPolicy(
124 IntraGroupPolicy.RequireContract)
126 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId),
127 newProviderConsumerEpg);
130 Optional<EndpointGroup> potentialConsumerEpg = DataStoreHelper.readFromDs(
131 LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, consumerEpgId), rwTx);
132 if (!potentialConsumerEpg.isPresent()) {
133 if (MappingUtils.EPG_ANY_ID.equals(consumerEpgId)) {
134 EndpointGroup epgAny = createEpgAny();
135 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ANY_ID),
138 LOG.warn("Illegal state - Endpoint group {} does not exist.", consumerEpgId.getValue());
143 // creates and stores contract with clause and subject
144 Subject subject = transform.createSubject();
145 Clause clause = transform.createClause();
146 Contract contract = createContract(clause, subject);
147 contractId = contract.getId();
148 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.contractIid(tenantId, contractId), contract);
149 putEpgPairToContractMapping(providerEpgId, consumerEpgId, contractId, rwTx);
151 // adds provider and consumer named selectors
152 ProviderNamedSelector providerSelector = createProviderNamedSelector(contractId);
153 rwTx.put(LogicalDatastoreType.CONFIGURATION,
154 IidFactory.providerNamedSelectorIid(tenantId, providerEpgId, providerSelector.getName()),
156 ConsumerNamedSelector consumerSelector = createConsumerNamedSelector(contractId);
157 rwTx.put(LogicalDatastoreType.CONFIGURATION,
158 IidFactory.consumerNamedSelectorIid(tenantId, consumerEpgId, consumerSelector.getName()),
162 // create classifier-instance
163 ClassifierName classifierName = transform.getClassifierName();
164 ClassifierInstance classifier = transform.createClassifier();
165 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.classifierInstanceIid(tenantId, classifierName),
167 // create action-instance if it does not exist yet
168 Optional<ActionInstance> potentialAction = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
169 IidFactory.actionInstanceIid(tenantId, MappingUtils.ACTION_ALLOW.getName()), rwTx);
170 if (!potentialAction.isPresent()) {
171 rwTx.put(LogicalDatastoreType.CONFIGURATION,
172 IidFactory.actionInstanceIid(tenantId, MappingUtils.ACTION_ALLOW.getName()),
173 MappingUtils.ACTION_ALLOW, true);
177 Rule rule = transform.createRule(0);
178 rwTx.put(LogicalDatastoreType.CONFIGURATION,
179 IidFactory.ruleIid(tenantId, contractId, subjectName, rule.getName()), rule);
183 private static EndpointGroup createEpgAny() {
184 return new EndpointGroupBuilder().setId(MappingUtils.EPG_ANY_ID)
185 .setDescription(new Description(MappingUtils.NEUTRON_RULE__ + "epg_any"))
186 .setIntraGroupPolicy(IntraGroupPolicy.RequireContract)
191 public int canUpdateNeutronSecurityRule(NeutronSecurityRule delta, NeutronSecurityRule original) {
192 LOG.warn("canUpdateNeutronSecurityRule - Never should be called "
193 + "- neutron API does not allow UPDATE on neutron security group rule. \nDelta: {} \nOriginal: {}",
195 return StatusCode.BAD_REQUEST;
199 public void neutronSecurityRuleUpdated(NeutronSecurityRule securityRule) {
200 LOG.warn("neutronSecurityRuleUpdated - Never should be called "
201 + "- neutron API does not allow UPDATE on neutron security group rule. \nSecurity group rule: {}",
206 public int canDeleteNeutronSecurityRule(NeutronSecurityRule securityRule) {
207 LOG.trace("canDeleteNeutronSecurityRule - {}", securityRule);
208 // nothing to consider
209 return StatusCode.OK;
213 public void neutronSecurityRuleDeleted(NeutronSecurityRule secRule) {
214 LOG.trace("neutronSecurityRuleCreated - {}", secRule);
215 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
216 boolean isNeutronSecurityRuleDelete = deleteNeutronSecurityRule(secRule, rwTx);
217 if (isNeutronSecurityRuleDelete) {
218 DataStoreHelper.submitToDs(rwTx);
220 DataStoreHelper.submitToDs(rwTx);
225 * @param secRule neutron security rule from which GBP entities are deleted
226 * @param rwTx GBP entities are stored to this transaction. This method NEVER submits or cancel
228 * @return {@code true} if operation was successful; {@code false} if an illegal state occurs -
229 * the transaction may contain just partial result
231 public static boolean deleteNeutronSecurityRule(NeutronSecurityRule secRule, ReadWriteTransaction rwTx) {
232 TransformSecRule transform = new TransformSecRule(secRule);
233 TenantId tenantId = transform.getTenantId();
234 EndpointGroupId providerEpgId = transform.getProviderEpgId();
235 EndpointGroupId consumerEpgId = transform.getConsumerEpgId();
237 Optional<ContractId> potentialContractId = readContractIdFromEpgPairToContractMapping(providerEpgId,
238 consumerEpgId, rwTx);
239 if (!potentialContractId.isPresent()) {
240 LOG.warn("Illegal state - mapping EPG pair (provider EPG {} consumer EPG {}) does not exist.",
241 providerEpgId.getValue(), consumerEpgId.getValue());
245 ContractId contractId = potentialContractId.get();
246 ClassifierName classifierName = transform.getClassifierName();
247 InstanceIdentifier<ClassifierInstance> classifierIid = IidFactory.classifierInstanceIid(tenantId,
249 Optional<ClassifierInstance> potentialClassifier = DataStoreHelper.removeIfExists(
250 LogicalDatastoreType.CONFIGURATION, classifierIid, rwTx);
251 if (!potentialClassifier.isPresent()) {
252 LOG.warn("Illegal state - classifier-instance {} does not exist. {}", classifierName.getValue(),
257 RuleName ruleName = transform.getRuleName();
258 SubjectName subjectName = transform.getSubjectName();
259 InstanceIdentifier<Rule> ruleIid = IidFactory.ruleIid(tenantId, contractId, subjectName, ruleName);
260 Optional<Rule> potentionalRule = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, ruleIid,
262 if (!potentionalRule.isPresent()) {
263 LOG.warn("Illegal state - rule {} does not exist. {}", ruleName.getValue(), ruleIid);
267 InstanceIdentifier<Subject> subjectIid = IidFactory.subjectIid(tenantId, contractId, subjectName);
268 Optional<Subject> potentionalSubject = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
270 if (!potentionalSubject.isPresent()) {
271 LOG.warn("Illegal state - subject {} does not exist. {}", subjectName.getValue(), subjectName);
275 ClauseName clauseName = transform.getClauseName();
276 InstanceIdentifier<Clause> clauseIid = IidFactory.clauseIid(tenantId, contractId, clauseName);
277 Optional<Clause> potentialClause = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, clauseIid,
279 if (!potentialClause.isPresent()) {
280 LOG.warn("Illegal state - clause {} does not exist. {}", clauseName.getValue(), clauseIid);
284 Subject subject = potentionalSubject.get();
285 if (subject.getRule() == null || subject.getRule().isEmpty()) {
286 rwTx.delete(LogicalDatastoreType.CONFIGURATION, clauseIid);
287 rwTx.delete(LogicalDatastoreType.CONFIGURATION, subjectIid);
290 InstanceIdentifier<Contract> contractIid = IidFactory.contractIid(tenantId, contractId);
291 Optional<Contract> potentialContract = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
293 if (!potentialContract.isPresent()) {
294 LOG.warn("Illegal state - contract {} does not exist. {}", contractId.getValue(), contractIid);
298 Contract contract = potentialContract.get();
299 if (contract.getSubject() == null || contract.getSubject().isEmpty()) {
300 // remove contract and named selectors from EPGs
301 rwTx.delete(LogicalDatastoreType.CONFIGURATION, contractIid);
302 SelectorName providerSelectorName = createNameOfNamedSelector(contractId);
303 InstanceIdentifier<ProviderNamedSelector> providerSelectorIid = IidFactory.providerNamedSelectorIid(
304 tenantId, providerEpgId, providerSelectorName);
305 Optional<ProviderNamedSelector> potentialProviderSelector = DataStoreHelper.removeIfExists(
306 LogicalDatastoreType.CONFIGURATION, providerSelectorIid, rwTx);
307 if (!potentialProviderSelector.isPresent()) {
308 LOG.warn("Illegal state - provider-name-selector {} does not exist. {}",
309 providerSelectorName.getValue(), providerSelectorIid);
312 SelectorName consumerSelectorName = createNameOfNamedSelector(contractId);
313 InstanceIdentifier<ConsumerNamedSelector> consumerSelectorIid = IidFactory.consumerNamedSelectorIid(
314 tenantId, consumerEpgId, consumerSelectorName);
315 Optional<ConsumerNamedSelector> potentialConsuemrSelector = DataStoreHelper.removeIfExists(
316 LogicalDatastoreType.CONFIGURATION, consumerSelectorIid, rwTx);
317 if (!potentialConsuemrSelector.isPresent()) {
318 LOG.warn("Illegal state - consumer-name-selector {} does not exist. {}",
319 consumerSelectorName.getValue(), consumerSelectorIid);
326 public static Optional<ContractId> readContractIdFromEpgPairToContractMapping(EndpointGroupId providerEpgId,
327 EndpointGroupId consumerEpgId, ReadTransaction rTx) {
328 Optional<EndpointGroupPairToContractMapping> potentialMapping = DataStoreHelper.readFromDs(
329 LogicalDatastoreType.OPERATIONAL,
330 IidFactory.endpointGroupPairToContractMappingIid(providerEpgId, consumerEpgId), rTx);
331 if (potentialMapping.isPresent()) {
332 return Optional.of(potentialMapping.get().getContractId());
334 return Optional.absent();
337 private static void putEpgPairToContractMapping(EndpointGroupId providerEpgId, EndpointGroupId consumerEpgId,
338 ContractId contractId, WriteTransaction wTx) {
339 EndpointGroupPairToContractMapping epgPairToContractMapping = new EndpointGroupPairToContractMappingBuilder().setProviderEpgId(
341 .setConsumerEpgId(consumerEpgId)
342 .setContractId(contractId)
344 wTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointGroupPairToContractMappingIid(
345 epgPairToContractMapping.getProviderEpgId(), epgPairToContractMapping.getConsumerEpgId()),
346 epgPairToContractMapping, true);
349 private static Contract createContract(Clause clause, Subject subject) {
350 ContractId contractId = new ContractId(UUID.randomUUID().toString());
351 return new ContractBuilder().setId(contractId)
352 .setClause(ImmutableList.of(clause))
353 .setSubject(ImmutableList.of(subject))
357 private static ProviderNamedSelector createProviderNamedSelector(ContractId contractId) {
358 return new ProviderNamedSelectorBuilder().setName(createNameOfNamedSelector(contractId))
359 .setContract(ImmutableList.of(contractId))
363 private static ConsumerNamedSelector createConsumerNamedSelector(ContractId contractId) {
364 return new ConsumerNamedSelectorBuilder().setName(createNameOfNamedSelector(contractId))
365 .setContract(ImmutableList.of(contractId))
369 private static SelectorName createNameOfNamedSelector(ContractId contractId) {
370 return new SelectorName(MappingUtils.NEUTRON_RULE__ + contractId.getValue());