2 * Copyright (c) 2015 Huawei Technologies 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.renderer.faas;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Optional;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.List;
16 import java.util.UUID;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.Executor;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
23 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
24 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.faas.uln.datastore.api.UlnDatastoreApi;
28 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Name;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Text;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.common.rev151013.Uuid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.parameter.values.grouping.ParameterValue;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.parameter.values.grouping.ParameterValueBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.parameter.values.grouping.parameter.value.RangeValueBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.SecurityRuleGroupsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.SecurityRuleGroup;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.SecurityRuleGroupBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.SecurityRule;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.SecurityRuleBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleAction;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleActionBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleClassifier;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleClassifier.Direction;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.faas.logical.faas.security.rules.rev151013.security.rule.groups.attributes.security.rule.groups.container.security.rule.groups.security.rule.group.security.rule.RuleClassifierBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContract;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.faas.rev151009.mapped.tenants.entities.mapped.entity.MappedContractBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRef;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Policy;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.SubjectFeatureInstances;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Clause;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Subject;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.Rule;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstanceKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstanceKey;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
71 public class FaasContractManagerListener implements DataTreeChangeListener<Contract> {
73 private static final Logger LOG = LoggerFactory.getLogger(FaasContractManagerListener.class);
74 private final ConcurrentHashMap<ContractId, Uuid> mappedContracts = new ConcurrentHashMap<>();
75 private final Executor executor;
76 private final DataBroker dataProvider;
77 private final TenantId gbpTenantId;
78 private final Uuid faasTenantId;
80 public FaasContractManagerListener(DataBroker dataProvider, TenantId gbpTenantId, Uuid faasTenantId,
82 this.executor = executor;
83 this.gbpTenantId = gbpTenantId;
84 this.faasTenantId = faasTenantId;
85 this.dataProvider = dataProvider;
89 public void onDataTreeChanged(Collection<DataTreeModification<Contract>> changes) {
90 executor.execute(() -> executeEvent(changes));
93 private void executeEvent(final Collection<DataTreeModification<Contract>> changes) {
94 for (DataTreeModification<Contract> change: changes) {
95 DataObjectModification<Contract> rootNode = change.getRootNode();
96 switch (rootNode.getModificationType()) {
97 case SUBTREE_MODIFIED:
99 Contract updatedContract = rootNode.getDataAfter();
100 LOG.debug("Contract {} is Updated.", updatedContract.getId().getValue());
101 UlnDatastoreApi.submitSecurityGroupsToDs(initSecurityGroupBuilder(updatedContract).build());
104 Contract deletedContract = rootNode.getDataBefore();
105 LOG.debug("Contract {} is removed.", deletedContract.getId().getValue());
106 ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
107 Optional<MappedContract> op = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
108 FaasIidFactory.mappedContractIid(gbpTenantId, deletedContract.getId()), rwTx);
109 if (op.isPresent()) {
110 DataStoreHelper.submitToDs(rwTx);
112 Uuid val = mappedContracts.remove(deletedContract.getId());
114 UlnDatastoreApi.removeSecurityGroupsFromDsIfExists(faasTenantId, val);
123 public void loadAll(List<Contract> contracts, List<MappedContract> mpContracts) {
124 if (mpContracts != null) {
125 for (MappedContract mpContract : mpContracts) {
126 mappedContracts.putIfAbsent(mpContract.getGbpContractId(), mpContract.getFaasSecurityRulesId());
129 if (contracts != null) {
130 for (Contract contract : contracts) {
131 LOG.debug("Loading Contract {}", contract.getId().getValue());
132 UlnDatastoreApi.submitSecurityGroupsToDs(initSecurityGroupBuilder(contract).build());
137 protected SecurityRuleGroupsBuilder initSecurityGroupBuilder(Contract contract) {
138 LOG.trace("Start initSecurityGroupBuilder");
139 SecurityRuleGroupsBuilder builder = new SecurityRuleGroupsBuilder();
140 builder.setUuid(getFaasSecurityRulesId(contract.getId()));
141 builder.setName(new Text(contract.getId().getValue()));
142 if (contract.getDescription() != null) {
143 builder.setDescription(new Text("gbp-contract: " + contract.getDescription().getValue()));
145 builder.setDescription(new Text("gbp-contract"));
147 builder.setTenantId(faasTenantId);
148 builder.setSecurityRuleGroup(buildSecurityRuleGroup(contract));
149 LOG.trace("Contract {} is mapped to Faas Security Rules {} ", contract.getId().getValue(), builder.getUuid()
154 private Uuid getFaasSecurityRulesId(ContractId contractId) {
155 Uuid val = mappedContracts.get(contractId);
159 Uuid faasContractId = null;
160 if (FaasPolicyManager.isUUid(contractId.getValue())) {
161 faasContractId = new Uuid(contractId.getValue());
163 faasContractId = new Uuid(UUID.randomUUID().toString());
165 mappedContracts.putIfAbsent(contractId, faasContractId);
166 val = mappedContracts.get(contractId);
167 MappedContractBuilder builder = new MappedContractBuilder();
168 builder.setFaasSecurityRulesId(val);
169 builder.setGbpContractId(contractId);
170 WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
171 MappedContract result = builder.build();
172 wTx.put(LogicalDatastoreType.OPERATIONAL,
173 FaasIidFactory.mappedContractIid(gbpTenantId, contractId), result);
174 if (DataStoreHelper.submitToDs(wTx)) {
175 LOG.debug("Cached in Datastore Mapped Contract {}", result);
177 LOG.error("Couldn't Cache in Datastore Mapped Contract {}", result);
183 List<SecurityRuleGroup> buildSecurityRuleGroup(Contract contract) {
184 LOG.trace("Start buildSecurityRuleGroup for contract {}", contract.getId().getValue());
185 List<SecurityRuleGroup> securityRuleGroups = new ArrayList<>();
186 if (contract.getClause() == null) {
187 LOG.debug("contract {} has no Clause", contract.getId().getValue());
190 for (Clause clause : contract.getClause()) {
191 if (clause.getSubjectRefs() == null) {
192 LOG.debug("Clause {} in contract {} has no Subject Ref", clause.getName().getValue(), contract.getId()
196 if (contract.getSubject() == null) {
197 LOG.warn("Couldn't find in Contract {} the expected subject references", contract.getId().getValue());
200 for (SubjectName subjectRef : clause.getSubjectRefs()) {
201 LOG.trace("Start Parsing Subject Ref {} in Contract {}", subjectRef, contract.getId().getValue());
202 for (Subject sub : contract.getSubject()) {
203 if (subjectRef.equals(sub.getName())) {
204 SecurityRuleGroupBuilder securityRuleGroupBuilder = new SecurityRuleGroupBuilder();
205 securityRuleGroupBuilder.setName(new Name(subjectRef.getValue()));
206 List<Rule> subRules = sub.getRule();
207 if (subRules == null) {
208 LOG.warn("Subject {} in Contract {} doesn't have rules", subjectRef.getValue(),
209 contract.getId().getValue());
211 List<SecurityRule> securityRules = getSecurityRules(contract, subjectRef, subRules);
212 LOG.debug("Subject {} in Contract {} has {} rules", subjectRef.getValue(), contract.getId()
213 .getValue(), securityRules.size());
214 securityRuleGroupBuilder.setSecurityRule(securityRules);
216 LOG.debug("Added Rule {} to Subject {} in Contract {}", securityRuleGroupBuilder.getName()
217 .getValue(), subjectRef.getValue(), contract.getId().getValue());
218 securityRuleGroups.add(securityRuleGroupBuilder.build());
223 LOG.trace("Done with buildSecurityRuleGroup for contract {}", contract.getId().getValue());
224 return securityRuleGroups;
228 List<SecurityRule> getSecurityRules(Contract contract, SubjectName subjectRef, List<Rule> subRules) {
229 List<SecurityRule> securityRules = new ArrayList<>();
230 for (Rule rule : subRules) {
231 List<ClassifierRef> classifierRefs = rule.getClassifierRef();
232 List<RuleClassifier> pClassifiers = null;
233 if (classifierRefs == null || classifierRefs.isEmpty()) {
234 LOG.warn("Rule {} in Subject {} in Contract {} doesn't have classifiers", rule.getName(), subjectRef,
237 pClassifiers = getClassifiers(gbpTenantId, contract, classifierRefs, dataProvider);
238 if (pClassifiers == null || pClassifiers.isEmpty()) {
239 LOG.warn("Rule {} in Subject {} in Contract {} doesn't have classifiers -- Will ignore this rule",
240 rule.getName(), subjectRef, contract.getId());
243 List<ActionRef> actionRefs = rule.getActionRef();
244 List<RuleAction> pActions = null;
245 if (actionRefs == null || actionRefs.isEmpty()) {
246 LOG.warn("Rule {} in Subject {} in Contract {} doesn't have actions", rule.getName(), subjectRef,
249 pActions = getActions(contract, actionRefs);
250 if (pActions == null || pActions.isEmpty()) {
251 LOG.warn("Rule {} in Subject {} in Contract {} doesn't have actions", rule.getName(), subjectRef,
256 securityRules.add(new SecurityRuleBuilder().setName(new Name(rule.getName().getValue()))
257 .setOrder(rule.getOrder())
258 .setRuleClassifier(pClassifiers)
259 .setRuleAction(pActions)
262 return securityRules;
265 private List<RuleAction> getActions(Contract contract, List<ActionRef> actionRefs) {
266 LOG.trace("Start Parsing Actions for actionRefs count {} in Contract {}", actionRefs.size(), contract.getId()
268 List<RuleAction> pActions = new ArrayList<>();
269 for (ActionRef actionRef : actionRefs) {
270 if (actionRef.getName() == null) {
271 LOG.warn("Couldn't find an Action in Contract {} -- ignored Action", contract.getId().getValue());
274 RuleActionBuilder ruleActionBuilder = new RuleActionBuilder();
275 ruleActionBuilder.setName(new Name(actionRef.getName().getValue()));
276 ruleActionBuilder.setOrder(actionRef.getOrder());
277 ActionInstance actionInstance = getActionInstance(actionRef.getName());
278 if (actionInstance == null) {
279 LOG.warn("Action instance {} is not found -- will only use the Action ref info", actionRef.getName());
281 if (actionInstance.getActionDefinitionId() != null) {
282 ruleActionBuilder.setAdditionalInfo(new Text(actionInstance.getActionDefinitionId().getValue()));
284 List<ParameterValue> parms = null;
285 if (actionInstance.getParameterValue() != null) {
286 LOG.trace("Action Instance {} has {} parameters", actionInstance.getName().getValue(),
287 actionInstance.getParameterValue().size());
288 parms = new ArrayList<>();
289 for (org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue instance : actionInstance.getParameterValue()) {
290 ParameterValueBuilder pBuilder = new ParameterValueBuilder();
291 pBuilder.setIntValue(instance.getIntValue());
292 if (instance.getName() != null) {
293 pBuilder.setName(new Name(instance.getName().getValue()));
295 pBuilder.setStringValue(instance.getStringValue());
296 if (instance.getRangeValue() != null) {
297 RangeValueBuilder rBuilder = new RangeValueBuilder().setMax(
298 instance.getRangeValue().getMax()).setMin(instance.getRangeValue().getMin());
299 pBuilder.setRangeValue(rBuilder.build());
301 ParameterValue parm = pBuilder.build();
302 LOG.trace("Added Parm {} from Action Instance {}", parm, actionInstance.getName().getValue());
306 LOG.trace("Action Instance {} has no parameters", actionInstance.getName().getValue());
308 ruleActionBuilder.setParameterValue(parms);
310 pActions.add(ruleActionBuilder.build());
316 private ActionInstance getActionInstance(ActionName name) {
317 ReadOnlyTransaction trans = dataProvider.newReadOnlyTransaction();
318 InstanceIdentifier<ActionInstance> ciId = InstanceIdentifier.builder(Tenants.class)
319 .child(Tenant.class, new TenantKey(gbpTenantId))
321 .child(SubjectFeatureInstances.class)
322 .child(ActionInstance.class, new ActionInstanceKey(name))
325 Optional<ActionInstance> data = trans.read(LogicalDatastoreType.CONFIGURATION, ciId).get();
326 if (data.isPresent()) {
329 } catch (Exception e) {
330 LOG.error("Couldn't read Action instance from datastore. Exception: ", e);
335 private List<RuleClassifier> getClassifiers(TenantId tenantId, Contract contract,
336 List<ClassifierRef> classifierRefs, DataBroker dataProvider) {
337 List<RuleClassifier> fClassifiers = new ArrayList<>();
338 for (ClassifierRef classifierRef : classifierRefs) {
339 if (classifierRef.getName() == null) {
340 LOG.warn("Found a Classifer without name in Contract {} ", contract.getId().getValue());
343 RuleClassifierBuilder ruleClassifierBuilder = new RuleClassifierBuilder();
344 ruleClassifierBuilder.setName(new Name(classifierRef.getName().getValue()));
345 ClassifierInstance classifierInstance = getClassifierInstance(tenantId, classifierRef.getName(),
347 if (classifierInstance == null) {
348 LOG.warn("Classifer instance {} is not found -- will only use the classifier Ref info",
349 classifierRef.getName());
351 if (classifierInstance.getClassifierDefinitionId() != null) {
352 ruleClassifierBuilder.setAdditionalInfo(new Text(classifierInstance.getClassifierDefinitionId()
355 List<ParameterValue> parms = null;
356 if (classifierInstance.getParameterValue() != null) {
357 LOG.trace("Calssifier Instance {} has {} parameters", classifierInstance.getName().getValue(),
358 classifierInstance.getParameterValue().size());
359 parms = new ArrayList<>();
360 for (org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue instance : classifierInstance.getParameterValue()) {
361 ParameterValueBuilder pBuilder = new ParameterValueBuilder();
362 pBuilder.setIntValue(instance.getIntValue());
363 pBuilder.setName(new Name(instance.getName().getValue()));
364 pBuilder.setStringValue(instance.getStringValue());
365 if (instance.getRangeValue() != null) {
366 RangeValueBuilder rBuilder = new RangeValueBuilder().setMax(
367 instance.getRangeValue().getMax()).setMin(instance.getRangeValue().getMin());
368 pBuilder.setRangeValue(rBuilder.build());
370 ParameterValue parm = pBuilder.build();
371 LOG.trace("Added parm {} from Classifier Instance {}", parm, classifierInstance.getName()
376 LOG.trace("Classifier Instance {} has no parameters", classifierInstance.getName().getValue());
378 ruleClassifierBuilder.setParameterValue(parms);
380 if (classifierRef.getDirection() != null) {
381 ruleClassifierBuilder.setDirection(Direction.forValue(classifierRef.getDirection().getIntValue()));
383 ruleClassifierBuilder.setDirection(Direction.Bidirectional);
385 fClassifiers.add(ruleClassifierBuilder.build());
390 private ClassifierInstance getClassifierInstance(TenantId tenantId, ClassifierName name, DataBroker dataProvider) {
391 ReadOnlyTransaction trans = dataProvider.newReadOnlyTransaction();
392 InstanceIdentifier<ClassifierInstance> ciId = InstanceIdentifier.builder(Tenants.class)
393 .child(Tenant.class, new TenantKey(tenantId))
395 .child(SubjectFeatureInstances.class)
396 .child(ClassifierInstance.class, new ClassifierInstanceKey(name))
399 Optional<ClassifierInstance> data = trans.read(LogicalDatastoreType.CONFIGURATION, ciId).get();
400 if (data.isPresent()) {
403 } catch (Exception e) {
404 LOG.error("Couldn't read Classifier instance from datastore. Exception: ", e);