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.MappingUtils;
13 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NeutronMapperIidFactory;
14 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
15 import org.opendaylight.groupbasedpolicy.util.IidFactory;
16 import org.opendaylight.neutron.spi.INeutronSecurityRuleAware;
17 import org.opendaylight.neutron.spi.NeutronSecurityRule;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMapping;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMappingBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 import com.google.common.base.Optional;
48 import com.google.common.collect.ImmutableList;
50 public class NeutronSecurityRuleAware implements INeutronSecurityRuleAware {
52 private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleAware.class);
53 private final DataBroker dataProvider;
55 public NeutronSecurityRuleAware(DataBroker dataProvider) {
56 this.dataProvider = checkNotNull(dataProvider);
60 public int canCreateNeutronSecurityRule(NeutronSecurityRule securityRule) {
61 LOG.trace("canCreateNeutronSecurityRule - {}", securityRule);
62 // nothing to consider
67 public void neutronSecurityRuleCreated(NeutronSecurityRule securityRule) {
68 LOG.trace("neutronSecurityRuleCreated - {}", securityRule);
69 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
70 boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(securityRule, rwTx);
71 if (isNeutronSecurityRuleAdded) {
72 DataStoreHelper.submitToDs(rwTx);
79 * <b>ASSUMPTION</b>: Endpoint group with id
80 * {@link NeutronSecurityRule#getSecurityRuleGroupID()} and
81 * endpoint group with id {@link NeutronSecurityRule#getSecurityRemoteGroupID()} already exist
84 * @param secRule neutron security rule from which GBP entities are created
85 * @param rwTx GBP entities are stored to this transaction. This method NEVER submits or cancel
87 * @return {@code true} if operation was successful; {@code false} if an illegal state occurs -
88 * the transaction may contain just partial result
90 public static boolean addNeutronSecurityRule(NeutronSecurityRule secRule, ReadWriteTransaction rwTx) {
91 TransformSecRule transform = new TransformSecRule(secRule);
92 TenantId tenantId = transform.getTenantId();
93 EndpointGroupId providerEpgId = transform.getProviderEpgId();
94 EndpointGroupId consumerEpgId = transform.getConsumerEpgId();
95 SubjectName subjectName = transform.getSubjectName();
97 Optional<ContractId> potentialContractId = readContractIdFromEpgPairToContractMapping(providerEpgId,
99 ContractId contractId = null;
100 if (potentialContractId.isPresent()) {
101 contractId = potentialContractId.get();
102 Optional<Subject> potentialSubject = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
103 IidFactory.subjectIid(tenantId, contractId, subjectName), rwTx);
104 if (!potentialSubject.isPresent()) {
105 // it also means that clause for this subject does not exist
106 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subjectIid(tenantId, contractId, subjectName),
107 transform.createSubject());
108 rwTx.put(LogicalDatastoreType.CONFIGURATION,
109 IidFactory.clauseIid(tenantId, contractId, transform.getClauseName()), transform.createClause());
112 // check assumption that provider EPG exists
113 Optional<EndpointGroup> potentialProviderEpg = DataStoreHelper.readFromDs(
114 LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId), rwTx);
115 if (!potentialProviderEpg.isPresent()) {
116 LOG.warn("Illegal state - Endpoint group {} does not exist.", providerEpgId.getValue());
120 if (providerEpgId.equals(consumerEpgId)) {
121 EndpointGroup providerConsumerEpg = potentialProviderEpg.get();
122 if (providerConsumerEpg.getIntraGroupPolicy() == null
123 || !providerConsumerEpg.getIntraGroupPolicy().equals(IntraGroupPolicy.RequireContract)) {
124 EndpointGroup newProviderConsumerEpg = new EndpointGroupBuilder(providerConsumerEpg).setIntraGroupPolicy(
125 IntraGroupPolicy.RequireContract)
127 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId),
128 newProviderConsumerEpg);
131 Optional<EndpointGroup> potentialConsumerEpg = DataStoreHelper.readFromDs(
132 LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, consumerEpgId), rwTx);
133 if (!potentialConsumerEpg.isPresent()) {
134 if (MappingUtils.EPG_ANY_ID.equals(consumerEpgId)) {
135 EndpointGroup epgAny = createEpgAny();
136 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ANY_ID),
139 LOG.warn("Illegal state - Endpoint group {} does not exist.", consumerEpgId.getValue());
144 // creates and stores contract with clause and subject
145 Subject subject = transform.createSubject();
146 Clause clause = transform.createClause();
147 Contract contract = createContract(clause, subject);
148 contractId = contract.getId();
149 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.contractIid(tenantId, contractId), contract);
150 putEpgPairToContractMapping(providerEpgId, consumerEpgId, contractId, rwTx);
152 // adds provider and consumer named selectors
153 ProviderNamedSelector providerSelector = createProviderNamedSelector(contractId);
154 rwTx.put(LogicalDatastoreType.CONFIGURATION,
155 IidFactory.providerNamedSelectorIid(tenantId, providerEpgId, providerSelector.getName()),
157 ConsumerNamedSelector consumerSelector = createConsumerNamedSelector(contractId);
158 rwTx.put(LogicalDatastoreType.CONFIGURATION,
159 IidFactory.consumerNamedSelectorIid(tenantId, consumerEpgId, consumerSelector.getName()),
163 // create classifier-instance
164 ClassifierName classifierName = transform.getClassifierName();
165 ClassifierInstance classifier = transform.createClassifier();
166 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.classifierInstanceIid(tenantId, classifierName),
168 // create action-instance if it does not exist yet
169 Optional<ActionInstance> potentialAction = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
170 IidFactory.actionInstanceIid(tenantId, MappingUtils.ACTION_ALLOW.getName()), rwTx);
171 if (!potentialAction.isPresent()) {
172 rwTx.put(LogicalDatastoreType.CONFIGURATION,
173 IidFactory.actionInstanceIid(tenantId, MappingUtils.ACTION_ALLOW.getName()),
174 MappingUtils.ACTION_ALLOW, true);
178 Rule rule = transform.createRule(0);
179 rwTx.put(LogicalDatastoreType.CONFIGURATION,
180 IidFactory.ruleIid(tenantId, contractId, subjectName, rule.getName()), rule);
184 private static EndpointGroup createEpgAny() {
185 return new EndpointGroupBuilder().setId(MappingUtils.EPG_ANY_ID)
186 .setDescription(new Description(MappingUtils.NEUTRON_RULE__ + "epg_any"))
187 .setIntraGroupPolicy(IntraGroupPolicy.RequireContract)
192 public int canUpdateNeutronSecurityRule(NeutronSecurityRule delta, NeutronSecurityRule original) {
193 LOG.warn("canUpdateNeutronSecurityRule - Never should be called "
194 + "- neutron API does not allow UPDATE on neutron security group rule. \nDelta: {} \nOriginal: {}",
196 return StatusCode.BAD_REQUEST;
200 public void neutronSecurityRuleUpdated(NeutronSecurityRule securityRule) {
201 LOG.warn("neutronSecurityRuleUpdated - Never should be called "
202 + "- neutron API does not allow UPDATE on neutron security group rule. \nSecurity group rule: {}",
207 public int canDeleteNeutronSecurityRule(NeutronSecurityRule securityRule) {
208 LOG.trace("canDeleteNeutronSecurityRule - {}", securityRule);
209 // nothing to consider
210 return StatusCode.OK;
214 public void neutronSecurityRuleDeleted(NeutronSecurityRule secRule) {
215 LOG.trace("neutronSecurityRuleCreated - {}", secRule);
216 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
217 boolean isNeutronSecurityRuleDelete = deleteNeutronSecurityRule(secRule, rwTx);
218 if (isNeutronSecurityRuleDelete) {
219 DataStoreHelper.submitToDs(rwTx);
221 DataStoreHelper.submitToDs(rwTx);
226 * @param secRule neutron security rule from which GBP entities are deleted
227 * @param rwTx GBP entities are stored to this transaction. This method NEVER submits or cancel
229 * @return {@code true} if operation was successful; {@code false} if an illegal state occurs -
230 * the transaction may contain just partial result
232 public static boolean deleteNeutronSecurityRule(NeutronSecurityRule secRule, ReadWriteTransaction rwTx) {
233 TransformSecRule transform = new TransformSecRule(secRule);
234 TenantId tenantId = transform.getTenantId();
235 EndpointGroupId providerEpgId = transform.getProviderEpgId();
236 EndpointGroupId consumerEpgId = transform.getConsumerEpgId();
238 Optional<ContractId> potentialContractId = readContractIdFromEpgPairToContractMapping(providerEpgId,
239 consumerEpgId, rwTx);
240 if (!potentialContractId.isPresent()) {
241 LOG.warn("Illegal state - mapping EPG pair (provider EPG {} consumer EPG {}) does not exist.",
242 providerEpgId.getValue(), consumerEpgId.getValue());
246 ContractId contractId = potentialContractId.get();
247 ClassifierName classifierName = transform.getClassifierName();
248 InstanceIdentifier<ClassifierInstance> classifierIid = IidFactory.classifierInstanceIid(tenantId,
250 Optional<ClassifierInstance> potentialClassifier = DataStoreHelper.removeIfExists(
251 LogicalDatastoreType.CONFIGURATION, classifierIid, rwTx);
252 if (!potentialClassifier.isPresent()) {
253 LOG.warn("Illegal state - classifier-instance {} does not exist. {}", classifierName.getValue(),
258 RuleName ruleName = transform.getRuleName();
259 SubjectName subjectName = transform.getSubjectName();
260 InstanceIdentifier<Rule> ruleIid = IidFactory.ruleIid(tenantId, contractId, subjectName, ruleName);
261 Optional<Rule> potentionalRule = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, ruleIid,
263 if (!potentionalRule.isPresent()) {
264 LOG.warn("Illegal state - rule {} does not exist. {}", ruleName.getValue(), ruleIid);
268 InstanceIdentifier<Subject> subjectIid = IidFactory.subjectIid(tenantId, contractId, subjectName);
269 Optional<Subject> potentionalSubject = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
271 if (!potentionalSubject.isPresent()) {
272 LOG.warn("Illegal state - subject {} does not exist. {}", subjectName.getValue(), subjectName);
276 ClauseName clauseName = transform.getClauseName();
277 InstanceIdentifier<Clause> clauseIid = IidFactory.clauseIid(tenantId, contractId, clauseName);
278 Optional<Clause> potentialClause = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, clauseIid,
280 if (!potentialClause.isPresent()) {
281 LOG.warn("Illegal state - clause {} does not exist. {}", clauseName.getValue(), clauseIid);
285 Subject subject = potentionalSubject.get();
286 if (subject.getRule() == null || subject.getRule().isEmpty()) {
287 rwTx.delete(LogicalDatastoreType.CONFIGURATION, clauseIid);
288 rwTx.delete(LogicalDatastoreType.CONFIGURATION, subjectIid);
291 InstanceIdentifier<Contract> contractIid = IidFactory.contractIid(tenantId, contractId);
292 Optional<Contract> potentialContract = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
294 if (!potentialContract.isPresent()) {
295 LOG.warn("Illegal state - contract {} does not exist. {}", contractId.getValue(), contractIid);
299 Contract contract = potentialContract.get();
300 if (contract.getSubject() == null || contract.getSubject().isEmpty()) {
301 // remove contract and named selectors from EPGs
302 rwTx.delete(LogicalDatastoreType.CONFIGURATION, contractIid);
303 SelectorName providerSelectorName = createNameOfNamedSelector(contractId);
304 InstanceIdentifier<ProviderNamedSelector> providerSelectorIid = IidFactory.providerNamedSelectorIid(
305 tenantId, providerEpgId, providerSelectorName);
306 Optional<ProviderNamedSelector> potentialProviderSelector = DataStoreHelper.removeIfExists(
307 LogicalDatastoreType.CONFIGURATION, providerSelectorIid, rwTx);
308 if (!potentialProviderSelector.isPresent()) {
309 LOG.warn("Illegal state - provider-name-selector {} does not exist. {}",
310 providerSelectorName.getValue(), providerSelectorIid);
313 SelectorName consumerSelectorName = createNameOfNamedSelector(contractId);
314 InstanceIdentifier<ConsumerNamedSelector> consumerSelectorIid = IidFactory.consumerNamedSelectorIid(
315 tenantId, consumerEpgId, consumerSelectorName);
316 Optional<ConsumerNamedSelector> potentialConsuemrSelector = DataStoreHelper.removeIfExists(
317 LogicalDatastoreType.CONFIGURATION, consumerSelectorIid, rwTx);
318 if (!potentialConsuemrSelector.isPresent()) {
319 LOG.warn("Illegal state - consumer-name-selector {} does not exist. {}",
320 consumerSelectorName.getValue(), consumerSelectorIid);
327 public static Optional<ContractId> readContractIdFromEpgPairToContractMapping(EndpointGroupId providerEpgId,
328 EndpointGroupId consumerEpgId, ReadTransaction rTx) {
329 Optional<EndpointGroupPairToContractMapping> potentialMapping = DataStoreHelper.readFromDs(
330 LogicalDatastoreType.OPERATIONAL,
331 NeutronMapperIidFactory.endpointGroupPairToContractMappingIid(providerEpgId, consumerEpgId), rTx);
332 if (potentialMapping.isPresent()) {
333 return Optional.of(potentialMapping.get().getContractId());
335 return Optional.absent();
338 private static void putEpgPairToContractMapping(EndpointGroupId providerEpgId, EndpointGroupId consumerEpgId,
339 ContractId contractId, WriteTransaction wTx) {
340 EndpointGroupPairToContractMapping epgPairToContractMapping = new EndpointGroupPairToContractMappingBuilder().setProviderEpgId(
342 .setConsumerEpgId(consumerEpgId)
343 .setContractId(contractId)
345 wTx.put(LogicalDatastoreType.OPERATIONAL, NeutronMapperIidFactory.endpointGroupPairToContractMappingIid(
346 epgPairToContractMapping.getProviderEpgId(), epgPairToContractMapping.getConsumerEpgId()),
347 epgPairToContractMapping, true);
350 private static Contract createContract(Clause clause, Subject subject) {
351 ContractId contractId = new ContractId(UUID.randomUUID().toString());
352 return new ContractBuilder().setId(contractId)
353 .setClause(ImmutableList.of(clause))
354 .setSubject(ImmutableList.of(subject))
358 private static ProviderNamedSelector createProviderNamedSelector(ContractId contractId) {
359 return new ProviderNamedSelectorBuilder().setName(createNameOfNamedSelector(contractId))
360 .setContract(ImmutableList.of(contractId))
364 private static ConsumerNamedSelector createConsumerNamedSelector(ContractId contractId) {
365 return new ConsumerNamedSelectorBuilder().setName(createNameOfNamedSelector(contractId))
366 .setContract(ImmutableList.of(contractId))
370 private static SelectorName createNameOfNamedSelector(ContractId contractId) {
371 return new SelectorName(MappingUtils.NEUTRON_RULE__ + contractId.getValue());