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.Name;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RuleName;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMapping;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.mapper.rev150223.mappings.endpoint.group.pair.to.contract.mappings.EndpointGroupPairToContractMappingBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstance;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 import com.google.common.base.Optional;
49 import com.google.common.collect.ImmutableList;
51 public class NeutronSecurityRuleAware implements INeutronSecurityRuleAware {
53 private static final Logger LOG = LoggerFactory.getLogger(NeutronSecurityRuleAware.class);
54 private final DataBroker dataProvider;
56 public NeutronSecurityRuleAware(DataBroker dataProvider) {
57 this.dataProvider = checkNotNull(dataProvider);
61 public int canCreateNeutronSecurityRule(NeutronSecurityRule securityRule) {
62 LOG.trace("canCreateNeutronSecurityRule - {}", securityRule);
63 // nothing to consider
68 public void neutronSecurityRuleCreated(NeutronSecurityRule securityRule) {
69 LOG.trace("neutronSecurityRuleCreated - {}", securityRule);
70 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
71 boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(securityRule, rwTx);
72 if (isNeutronSecurityRuleAdded) {
73 DataStoreHelper.submitToDs(rwTx);
80 * <b>ASSUMPTION</b>: Endpoint group with id
81 * {@link NeutronSecurityRule#getSecurityRuleGroupID()} and
82 * endpoint group with id {@link NeutronSecurityRule#getSecurityRemoteGroupID()} already exist
85 * @param secRule neutron security rule from which GBP entities are created
86 * @param rwTx GBP entities are stored to this transaction. This method NEVER submits or cancel
88 * @return {@code true} if operation was successful; {@code false} if an illegal state occurs -
89 * the transaction may contain just partial result
91 public static boolean addNeutronSecurityRule(NeutronSecurityRule secRule, ReadWriteTransaction rwTx) {
92 TransformSecRule transform = new TransformSecRule(secRule);
93 TenantId tenantId = transform.getTenantId();
94 EndpointGroupId providerEpgId = transform.getProviderEpgId();
95 EndpointGroupId consumerEpgId = transform.getConsumerEpgId();
96 SubjectName subjectName = transform.getSubjectName();
98 Optional<ContractId> potentialContractId = readContractIdFromEpgPairToContractMapping(providerEpgId,
100 ContractId contractId = null;
101 if (potentialContractId.isPresent()) {
102 contractId = potentialContractId.get();
103 Optional<Subject> potentialSubject = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
104 IidFactory.subjectIid(tenantId, contractId, subjectName), rwTx);
105 if (!potentialSubject.isPresent()) {
106 // it also means that clause for this subject does not exist
107 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.subjectIid(tenantId, contractId, subjectName),
108 transform.createSubject());
109 rwTx.put(LogicalDatastoreType.CONFIGURATION,
110 IidFactory.clauseIid(tenantId, contractId, transform.getClauseName()), transform.createClause());
113 // check assumption that provider EPG exists
114 Optional<EndpointGroup> potentialProviderEpg = DataStoreHelper.readFromDs(
115 LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId), rwTx);
116 if (!potentialProviderEpg.isPresent()) {
117 LOG.warn("Illegal state - Endpoint group {} does not exist.", providerEpgId.getValue());
121 if (providerEpgId.equals(consumerEpgId)) {
122 EndpointGroup providerConsumerEpg = potentialProviderEpg.get();
123 if (providerConsumerEpg.getIntraGroupPolicy() == null
124 || !providerConsumerEpg.getIntraGroupPolicy().equals(IntraGroupPolicy.RequireContract)) {
125 EndpointGroup newProviderConsumerEpg = new EndpointGroupBuilder(providerConsumerEpg).setIntraGroupPolicy(
126 IntraGroupPolicy.RequireContract)
128 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, providerEpgId),
129 newProviderConsumerEpg);
132 Optional<EndpointGroup> potentialConsumerEpg = DataStoreHelper.readFromDs(
133 LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, consumerEpgId), rwTx);
134 if (!potentialConsumerEpg.isPresent()) {
135 if (MappingUtils.EPG_ANY_ID.equals(consumerEpgId)) {
136 EndpointGroup epgAny = createEpgAny();
137 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.endpointGroupIid(tenantId, MappingUtils.EPG_ANY_ID),
140 LOG.warn("Illegal state - Endpoint group {} does not exist.", consumerEpgId.getValue());
145 // creates and stores contract with clause and subject
146 Subject subject = transform.createSubject();
147 Clause clause = transform.createClause();
148 Contract contract = createContract(clause, subject);
149 contractId = contract.getId();
150 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.contractIid(tenantId, contractId), contract);
151 putEpgPairToContractMapping(providerEpgId, consumerEpgId, contractId, rwTx);
153 // adds provider and consumer named selectors
154 ProviderNamedSelector providerSelector = createProviderNamedSelector(contractId);
155 rwTx.put(LogicalDatastoreType.CONFIGURATION,
156 IidFactory.providerNamedSelectorIid(tenantId, providerEpgId, providerSelector.getName()),
158 ConsumerNamedSelector consumerSelector = createConsumerNamedSelector(contractId);
159 rwTx.put(LogicalDatastoreType.CONFIGURATION,
160 IidFactory.consumerNamedSelectorIid(tenantId, consumerEpgId, consumerSelector.getName()),
164 // create classifier-instance
165 ClassifierName classifierName = transform.getClassifierName();
166 ClassifierInstance classifier = transform.createClassifier();
167 rwTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.classifierInstanceIid(tenantId, classifierName),
169 // create action-instance if it does not exist yet
170 Optional<ActionInstance> potentialAction = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
171 IidFactory.actionInstanceIid(tenantId, MappingUtils.ACTION_ALLOW.getName()), rwTx);
172 if (!potentialAction.isPresent()) {
173 rwTx.put(LogicalDatastoreType.CONFIGURATION,
174 IidFactory.actionInstanceIid(tenantId, MappingUtils.ACTION_ALLOW.getName()),
175 MappingUtils.ACTION_ALLOW, true);
179 Rule rule = transform.createRule(0);
180 rwTx.put(LogicalDatastoreType.CONFIGURATION,
181 IidFactory.ruleIid(tenantId, contractId, subjectName, rule.getName()), rule);
185 private static EndpointGroup createEpgAny() {
186 return new EndpointGroupBuilder()
187 .setId(MappingUtils.EPG_ANY_ID)
188 .setName(new Name("ANY_group"))
189 .setDescription(new Description(MappingUtils.NEUTRON_RULE__ + "epg_any"))
190 .setIntraGroupPolicy(IntraGroupPolicy.RequireContract)
195 public int canUpdateNeutronSecurityRule(NeutronSecurityRule delta, NeutronSecurityRule original) {
196 LOG.warn("canUpdateNeutronSecurityRule - Never should be called "
197 + "- neutron API does not allow UPDATE on neutron security group rule. \nDelta: {} \nOriginal: {}",
199 return StatusCode.BAD_REQUEST;
203 public void neutronSecurityRuleUpdated(NeutronSecurityRule securityRule) {
204 LOG.warn("neutronSecurityRuleUpdated - Never should be called "
205 + "- neutron API does not allow UPDATE on neutron security group rule. \nSecurity group rule: {}",
210 public int canDeleteNeutronSecurityRule(NeutronSecurityRule securityRule) {
211 LOG.trace("canDeleteNeutronSecurityRule - {}", securityRule);
212 // nothing to consider
213 return StatusCode.OK;
217 public void neutronSecurityRuleDeleted(NeutronSecurityRule secRule) {
218 LOG.trace("neutronSecurityRuleCreated - {}", secRule);
219 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
220 boolean isNeutronSecurityRuleDelete = deleteNeutronSecurityRule(secRule, rwTx);
221 if (isNeutronSecurityRuleDelete) {
222 DataStoreHelper.submitToDs(rwTx);
224 DataStoreHelper.submitToDs(rwTx);
229 * @param secRule neutron security rule from which GBP entities are deleted
230 * @param rwTx GBP entities are stored to this transaction. This method NEVER submits or cancel
232 * @return {@code true} if operation was successful; {@code false} if an illegal state occurs -
233 * the transaction may contain just partial result
235 public static boolean deleteNeutronSecurityRule(NeutronSecurityRule secRule, ReadWriteTransaction rwTx) {
236 TransformSecRule transform = new TransformSecRule(secRule);
237 TenantId tenantId = transform.getTenantId();
238 EndpointGroupId providerEpgId = transform.getProviderEpgId();
239 EndpointGroupId consumerEpgId = transform.getConsumerEpgId();
241 Optional<ContractId> potentialContractId = readContractIdFromEpgPairToContractMapping(providerEpgId,
242 consumerEpgId, rwTx);
243 if (!potentialContractId.isPresent()) {
244 LOG.warn("Illegal state - mapping EPG pair (provider EPG {} consumer EPG {}) does not exist.",
245 providerEpgId.getValue(), consumerEpgId.getValue());
249 ContractId contractId = potentialContractId.get();
250 ClassifierName classifierName = transform.getClassifierName();
251 InstanceIdentifier<ClassifierInstance> classifierIid = IidFactory.classifierInstanceIid(tenantId,
253 Optional<ClassifierInstance> potentialClassifier = DataStoreHelper.removeIfExists(
254 LogicalDatastoreType.CONFIGURATION, classifierIid, rwTx);
255 if (!potentialClassifier.isPresent()) {
256 LOG.warn("Illegal state - classifier-instance {} does not exist. {}", classifierName.getValue(),
261 RuleName ruleName = transform.getRuleName();
262 SubjectName subjectName = transform.getSubjectName();
263 InstanceIdentifier<Rule> ruleIid = IidFactory.ruleIid(tenantId, contractId, subjectName, ruleName);
264 Optional<Rule> potentionalRule = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, ruleIid,
266 if (!potentionalRule.isPresent()) {
267 LOG.warn("Illegal state - rule {} does not exist. {}", ruleName.getValue(), ruleIid);
271 InstanceIdentifier<Subject> subjectIid = IidFactory.subjectIid(tenantId, contractId, subjectName);
272 Optional<Subject> potentionalSubject = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
274 if (!potentionalSubject.isPresent()) {
275 LOG.warn("Illegal state - subject {} does not exist. {}", subjectName.getValue(), subjectName);
279 ClauseName clauseName = transform.getClauseName();
280 InstanceIdentifier<Clause> clauseIid = IidFactory.clauseIid(tenantId, contractId, clauseName);
281 Optional<Clause> potentialClause = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, clauseIid,
283 if (!potentialClause.isPresent()) {
284 LOG.warn("Illegal state - clause {} does not exist. {}", clauseName.getValue(), clauseIid);
288 Subject subject = potentionalSubject.get();
289 if (subject.getRule() == null || subject.getRule().isEmpty()) {
290 rwTx.delete(LogicalDatastoreType.CONFIGURATION, clauseIid);
291 rwTx.delete(LogicalDatastoreType.CONFIGURATION, subjectIid);
294 InstanceIdentifier<Contract> contractIid = IidFactory.contractIid(tenantId, contractId);
295 Optional<Contract> potentialContract = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
297 if (!potentialContract.isPresent()) {
298 LOG.warn("Illegal state - contract {} does not exist. {}", contractId.getValue(), contractIid);
302 Contract contract = potentialContract.get();
303 if (contract.getSubject() == null || contract.getSubject().isEmpty()) {
304 // remove contract and named selectors from EPGs
305 rwTx.delete(LogicalDatastoreType.CONFIGURATION, contractIid);
306 SelectorName providerSelectorName = createNameOfNamedSelector(contractId);
307 InstanceIdentifier<ProviderNamedSelector> providerSelectorIid = IidFactory.providerNamedSelectorIid(
308 tenantId, providerEpgId, providerSelectorName);
309 Optional<ProviderNamedSelector> potentialProviderSelector = DataStoreHelper.removeIfExists(
310 LogicalDatastoreType.CONFIGURATION, providerSelectorIid, rwTx);
311 if (!potentialProviderSelector.isPresent()) {
312 LOG.warn("Illegal state - provider-name-selector {} does not exist. {}",
313 providerSelectorName.getValue(), providerSelectorIid);
316 SelectorName consumerSelectorName = createNameOfNamedSelector(contractId);
317 InstanceIdentifier<ConsumerNamedSelector> consumerSelectorIid = IidFactory.consumerNamedSelectorIid(
318 tenantId, consumerEpgId, consumerSelectorName);
319 Optional<ConsumerNamedSelector> potentialConsuemrSelector = DataStoreHelper.removeIfExists(
320 LogicalDatastoreType.CONFIGURATION, consumerSelectorIid, rwTx);
321 if (!potentialConsuemrSelector.isPresent()) {
322 LOG.warn("Illegal state - consumer-name-selector {} does not exist. {}",
323 consumerSelectorName.getValue(), consumerSelectorIid);
330 public static Optional<ContractId> readContractIdFromEpgPairToContractMapping(EndpointGroupId providerEpgId,
331 EndpointGroupId consumerEpgId, ReadTransaction rTx) {
332 Optional<EndpointGroupPairToContractMapping> potentialMapping = DataStoreHelper.readFromDs(
333 LogicalDatastoreType.OPERATIONAL,
334 NeutronMapperIidFactory.endpointGroupPairToContractMappingIid(providerEpgId, consumerEpgId), rTx);
335 if (potentialMapping.isPresent()) {
336 return Optional.of(potentialMapping.get().getContractId());
338 return Optional.absent();
341 private static void putEpgPairToContractMapping(EndpointGroupId providerEpgId, EndpointGroupId consumerEpgId,
342 ContractId contractId, WriteTransaction wTx) {
343 EndpointGroupPairToContractMapping epgPairToContractMapping = new EndpointGroupPairToContractMappingBuilder().setProviderEpgId(
345 .setConsumerEpgId(consumerEpgId)
346 .setContractId(contractId)
348 wTx.put(LogicalDatastoreType.OPERATIONAL, NeutronMapperIidFactory.endpointGroupPairToContractMappingIid(
349 epgPairToContractMapping.getProviderEpgId(), epgPairToContractMapping.getConsumerEpgId()),
350 epgPairToContractMapping, true);
353 private static Contract createContract(Clause clause, Subject subject) {
354 ContractId contractId = new ContractId(UUID.randomUUID().toString());
355 return new ContractBuilder().setId(contractId)
356 .setClause(ImmutableList.of(clause))
357 .setSubject(ImmutableList.of(subject))
361 private static ProviderNamedSelector createProviderNamedSelector(ContractId contractId) {
362 return new ProviderNamedSelectorBuilder().setName(createNameOfNamedSelector(contractId))
363 .setContract(ImmutableList.of(contractId))
367 private static ConsumerNamedSelector createConsumerNamedSelector(ContractId contractId) {
368 return new ConsumerNamedSelectorBuilder().setName(createNameOfNamedSelector(contractId))
369 .setContract(ImmutableList.of(contractId))
373 private static SelectorName createNameOfNamedSelector(ContractId contractId) {
374 return new SelectorName(MappingUtils.NEUTRON_RULE__ + contractId.getValue());