Add INFO.yaml for GBP
[groupbasedpolicy.git] / renderers / faas / src / main / java / org / opendaylight / groupbasedpolicy / renderer / faas / FaasContractManagerListener.java
1 /*
2  * Copyright (c) 2015 Huawei Technologies and others. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.faas;
10
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.UlnDatastoreUtil;
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;
70
71 public class FaasContractManagerListener implements DataTreeChangeListener<Contract> {
72
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;
79     private final UlnDatastoreUtil ulnDatastoreUtil;
80
81     public FaasContractManagerListener(DataBroker dataProvider, TenantId gbpTenantId, Uuid faasTenantId,
82             Executor executor, UlnDatastoreUtil ulnDatastoreUtil) {
83         this.executor = executor;
84         this.gbpTenantId = gbpTenantId;
85         this.faasTenantId = faasTenantId;
86         this.dataProvider = dataProvider;
87         this.ulnDatastoreUtil = ulnDatastoreUtil;
88     }
89
90     @Override
91     public void onDataTreeChanged(Collection<DataTreeModification<Contract>> changes) {
92         executor.execute(() -> executeEvent(changes));
93     }
94
95     private void executeEvent(final Collection<DataTreeModification<Contract>> changes) {
96         for (DataTreeModification<Contract> change: changes) {
97             DataObjectModification<Contract> rootNode = change.getRootNode();
98             switch (rootNode.getModificationType()) {
99                 case SUBTREE_MODIFIED:
100                 case WRITE:
101                     Contract updatedContract = rootNode.getDataAfter();
102                     LOG.debug("Contract {} is Updated.", updatedContract.getId().getValue());
103                     ulnDatastoreUtil.submitSecurityGroupsToDs(initSecurityGroupBuilder(updatedContract).build());
104                     break;
105                 case DELETE:
106                     Contract deletedContract = rootNode.getDataBefore();
107                     LOG.debug("Contract {} is removed.", deletedContract.getId().getValue());
108                     ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
109                     Optional<MappedContract> op = DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
110                             FaasIidFactory.mappedContractIid(gbpTenantId, deletedContract.getId()), rwTx);
111                     if (op.isPresent()) {
112                         DataStoreHelper.submitToDs(rwTx);
113                     }
114                     Uuid val = mappedContracts.remove(deletedContract.getId());
115                     if (val != null) {
116                         ulnDatastoreUtil.removeSecurityGroupsFromDsIfExists(faasTenantId, val);
117                     }
118                     break;
119                 default:
120                     break;
121             }
122         }
123     }
124
125     public void loadAll(List<Contract> contracts, List<MappedContract> mpContracts) {
126         if (mpContracts != null) {
127             for (MappedContract mpContract : mpContracts) {
128                 mappedContracts.putIfAbsent(mpContract.getGbpContractId(), mpContract.getFaasSecurityRulesId());
129             }
130         }
131         if (contracts != null) {
132             for (Contract contract : contracts) {
133                 LOG.debug("Loading Contract {}", contract.getId().getValue());
134                 ulnDatastoreUtil.submitSecurityGroupsToDs(initSecurityGroupBuilder(contract).build());
135             }
136         }
137     }
138
139     protected SecurityRuleGroupsBuilder initSecurityGroupBuilder(Contract contract) {
140         LOG.trace("Start initSecurityGroupBuilder");
141         SecurityRuleGroupsBuilder builder = new SecurityRuleGroupsBuilder();
142         builder.setUuid(getFaasSecurityRulesId(contract.getId()));
143         builder.setName(new Text(contract.getId().getValue()));
144         if (contract.getDescription() != null) {
145             builder.setDescription(new Text("gbp-contract: " + contract.getDescription().getValue()));
146         } else {
147             builder.setDescription(new Text("gbp-contract"));
148         }
149         builder.setTenantId(faasTenantId);
150         builder.setSecurityRuleGroup(buildSecurityRuleGroup(contract));
151         LOG.trace("Contract {} is mapped to Faas Security Rules {} ", contract.getId().getValue(), builder.getUuid()
152             .getValue());
153         return builder;
154     }
155
156     private Uuid getFaasSecurityRulesId(ContractId contractId) {
157         Uuid val = mappedContracts.get(contractId);
158         if (val != null) {
159             return val;
160         }
161         Uuid faasContractId = null;
162         if (FaasPolicyManager.isUUid(contractId.getValue())) {
163             faasContractId = new Uuid(contractId.getValue());
164         } else {
165             faasContractId = new Uuid(UUID.randomUUID().toString());
166         }
167         mappedContracts.putIfAbsent(contractId, faasContractId);
168         val = mappedContracts.get(contractId);
169         MappedContractBuilder builder = new MappedContractBuilder();
170         builder.setFaasSecurityRulesId(val);
171         builder.setGbpContractId(contractId);
172         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
173         MappedContract result = builder.build();
174         wTx.put(LogicalDatastoreType.OPERATIONAL,
175                 FaasIidFactory.mappedContractIid(gbpTenantId, contractId), result);
176         if (DataStoreHelper.submitToDs(wTx)) {
177             LOG.debug("Cached in Datastore Mapped Contract {}", result);
178         } else {
179             LOG.error("Couldn't Cache in Datastore Mapped Contract {}", result);
180         }
181         return val;
182     }
183
184     @VisibleForTesting
185     List<SecurityRuleGroup> buildSecurityRuleGroup(Contract contract) {
186         LOG.trace("Start buildSecurityRuleGroup for contract {}", contract.getId().getValue());
187         List<SecurityRuleGroup> securityRuleGroups = new ArrayList<>();
188         if (contract.getClause() == null) {
189             LOG.debug("contract {} has no Clause", contract.getId().getValue());
190             return null;
191         }
192         for (Clause clause : contract.getClause()) {
193             if (clause.getSubjectRefs() == null) {
194                 LOG.debug("Clause {} in contract {} has no Subject Ref", clause.getName().getValue(), contract.getId()
195                     .getValue());
196                 continue;
197             }
198             if (contract.getSubject() == null) {
199                 LOG.warn("Couldn't find in Contract {} the expected subject references", contract.getId().getValue());
200                 continue;
201             }
202             for (SubjectName subjectRef : clause.getSubjectRefs()) {
203                 LOG.trace("Start Parsing Subject Ref {} in Contract {}", subjectRef, contract.getId().getValue());
204                 for (Subject sub : contract.getSubject()) {
205                     if (subjectRef.equals(sub.getName())) {
206                         SecurityRuleGroupBuilder securityRuleGroupBuilder = new SecurityRuleGroupBuilder();
207                         securityRuleGroupBuilder.setName(new Name(subjectRef.getValue()));
208                         List<Rule> subRules = sub.getRule();
209                         if (subRules == null) {
210                             LOG.warn("Subject {} in Contract {} doesn't have rules", subjectRef.getValue(),
211                                     contract.getId().getValue());
212                         } else {
213                             List<SecurityRule> securityRules = getSecurityRules(contract, subjectRef, subRules);
214                             LOG.debug("Subject {} in Contract {} has {} rules", subjectRef.getValue(), contract.getId()
215                                 .getValue(), securityRules.size());
216                             securityRuleGroupBuilder.setSecurityRule(securityRules);
217                         }
218                         LOG.debug("Added Rule {} to Subject {} in Contract {}", securityRuleGroupBuilder.getName()
219                             .getValue(), subjectRef.getValue(), contract.getId().getValue());
220                         securityRuleGroups.add(securityRuleGroupBuilder.build());
221                     }
222                 }
223             }
224         }
225         LOG.trace("Done with buildSecurityRuleGroup for contract {}", contract.getId().getValue());
226         return securityRuleGroups;
227     }
228
229     @VisibleForTesting
230     List<SecurityRule> getSecurityRules(Contract contract, SubjectName subjectRef, List<Rule> subRules) {
231         List<SecurityRule> securityRules = new ArrayList<>();
232         for (Rule rule : subRules) {
233             List<ClassifierRef> classifierRefs = rule.getClassifierRef();
234             List<RuleClassifier> pClassifiers = null;
235             if (classifierRefs == null || classifierRefs.isEmpty()) {
236                 LOG.warn("Rule {} in Subject {} in Contract {} doesn't have classifiers", rule.getName(), subjectRef,
237                         contract.getId());
238             } else {
239                 pClassifiers = getClassifiers(gbpTenantId, contract, classifierRefs, dataProvider);
240                 if (pClassifiers == null || pClassifiers.isEmpty()) {
241                     LOG.warn("Rule {} in Subject {} in Contract {} doesn't have classifiers -- Will ignore this rule",
242                             rule.getName(), subjectRef, contract.getId());
243                 }
244             }
245             List<ActionRef> actionRefs = rule.getActionRef();
246             List<RuleAction> pActions = null;
247             if (actionRefs == null || actionRefs.isEmpty()) {
248                 LOG.warn("Rule {} in Subject {} in Contract {} doesn't have actions", rule.getName(), subjectRef,
249                         contract.getId());
250             } else {
251                 pActions = getActions(contract, actionRefs);
252                 if (pActions == null || pActions.isEmpty()) {
253                     LOG.warn("Rule {} in Subject {} in Contract {} doesn't have actions", rule.getName(), subjectRef,
254                             contract.getId());
255                 }
256             }
257
258             securityRules.add(new SecurityRuleBuilder().setName(new Name(rule.getName().getValue()))
259                 .setOrder(rule.getOrder())
260                 .setRuleClassifier(pClassifiers)
261                 .setRuleAction(pActions)
262                 .build());
263         } // for rules
264         return securityRules;
265     }
266
267     private List<RuleAction> getActions(Contract contract, List<ActionRef> actionRefs) {
268         LOG.trace("Start Parsing Actions for actionRefs count {} in Contract {}", actionRefs.size(), contract.getId()
269             .getValue());
270         List<RuleAction> pActions = new ArrayList<>();
271         for (ActionRef actionRef : actionRefs) {
272             if (actionRef.getName() == null) {
273                 LOG.warn("Couldn't find an Action in Contract {} -- ignored Action", contract.getId().getValue());
274                 continue;
275             }
276             RuleActionBuilder ruleActionBuilder = new RuleActionBuilder();
277             ruleActionBuilder.setName(new Name(actionRef.getName().getValue()));
278             ruleActionBuilder.setOrder(actionRef.getOrder());
279             ActionInstance actionInstance = getActionInstance(actionRef.getName());
280             if (actionInstance == null) {
281                 LOG.warn("Action instance {} is not found -- will only use the Action ref info", actionRef.getName());
282             } else {
283                 if (actionInstance.getActionDefinitionId() != null) {
284                     ruleActionBuilder.setAdditionalInfo(new Text(actionInstance.getActionDefinitionId().getValue()));
285                 }
286                 List<ParameterValue> parms = null;
287                 if (actionInstance.getParameterValue() != null) {
288                     LOG.trace("Action Instance {} has {} parameters", actionInstance.getName().getValue(),
289                             actionInstance.getParameterValue().size());
290                     parms = new ArrayList<>();
291                     for (org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue instance : actionInstance.getParameterValue()) {
292                         ParameterValueBuilder pBuilder = new ParameterValueBuilder();
293                         pBuilder.setIntValue(instance.getIntValue());
294                         if (instance.getName() != null) {
295                             pBuilder.setName(new Name(instance.getName().getValue()));
296                         }
297                         pBuilder.setStringValue(instance.getStringValue());
298                         if (instance.getRangeValue() != null) {
299                             RangeValueBuilder rBuilder = new RangeValueBuilder().setMax(
300                                     instance.getRangeValue().getMax()).setMin(instance.getRangeValue().getMin());
301                             pBuilder.setRangeValue(rBuilder.build());
302                         }
303                         ParameterValue parm = pBuilder.build();
304                         LOG.trace("Added Parm {} from Action Instance {}", parm, actionInstance.getName().getValue());
305                         parms.add(parm);
306                     }
307                 } else {
308                     LOG.trace("Action Instance {} has no parameters", actionInstance.getName().getValue());
309                 }
310                 ruleActionBuilder.setParameterValue(parms);
311             }
312             pActions.add(ruleActionBuilder.build());
313         }
314
315         return pActions;
316     }
317
318     private ActionInstance getActionInstance(ActionName name) {
319         ReadOnlyTransaction trans = dataProvider.newReadOnlyTransaction();
320         InstanceIdentifier<ActionInstance> ciId = InstanceIdentifier.builder(Tenants.class)
321             .child(Tenant.class, new TenantKey(gbpTenantId))
322             .child(Policy.class)
323             .child(SubjectFeatureInstances.class)
324             .child(ActionInstance.class, new ActionInstanceKey(name))
325             .build();
326         try {
327             Optional<ActionInstance> data = trans.read(LogicalDatastoreType.CONFIGURATION, ciId).get();
328             if (data.isPresent()) {
329                 return data.get();
330             }
331         } catch (Exception e) {
332             LOG.error("Couldn't read Action instance from datastore. Exception: ", e);
333         }
334         return null;
335     }
336
337     private List<RuleClassifier> getClassifiers(TenantId tenantId, Contract contract,
338             List<ClassifierRef> classifierRefs, DataBroker dataProvider) {
339         List<RuleClassifier> fClassifiers = new ArrayList<>();
340         for (ClassifierRef classifierRef : classifierRefs) {
341             if (classifierRef.getName() == null) {
342                 LOG.warn("Found a Classifer without name in Contract {} ", contract.getId().getValue());
343                 continue;
344             }
345             RuleClassifierBuilder ruleClassifierBuilder = new RuleClassifierBuilder();
346             ruleClassifierBuilder.setName(new Name(classifierRef.getName().getValue()));
347             ClassifierInstance classifierInstance = getClassifierInstance(tenantId, classifierRef.getName(),
348                     dataProvider);
349             if (classifierInstance == null) {
350                 LOG.warn("Classifer instance {} is not found -- will only use the classifier Ref info",
351                         classifierRef.getName());
352             } else {
353                 if (classifierInstance.getClassifierDefinitionId() != null) {
354                     ruleClassifierBuilder.setAdditionalInfo(new Text(classifierInstance.getClassifierDefinitionId()
355                         .getValue()));
356                 }
357                 List<ParameterValue> parms = null;
358                 if (classifierInstance.getParameterValue() != null) {
359                     LOG.trace("Calssifier Instance {} has {} parameters", classifierInstance.getName().getValue(),
360                             classifierInstance.getParameterValue().size());
361                     parms = new ArrayList<>();
362                     for (org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue instance : classifierInstance.getParameterValue()) {
363                         ParameterValueBuilder pBuilder = new ParameterValueBuilder();
364                         pBuilder.setIntValue(instance.getIntValue());
365                         pBuilder.setName(new Name(instance.getName().getValue()));
366                         pBuilder.setStringValue(instance.getStringValue());
367                         if (instance.getRangeValue() != null) {
368                             RangeValueBuilder rBuilder = new RangeValueBuilder().setMax(
369                                     instance.getRangeValue().getMax()).setMin(instance.getRangeValue().getMin());
370                             pBuilder.setRangeValue(rBuilder.build());
371                         }
372                         ParameterValue parm = pBuilder.build();
373                         LOG.trace("Added parm {} from Classifier Instance {}", parm, classifierInstance.getName()
374                             .getValue());
375                         parms.add(parm);
376                     }
377                 } else {
378                     LOG.trace("Classifier Instance {} has no parameters", classifierInstance.getName().getValue());
379                 }
380                 ruleClassifierBuilder.setParameterValue(parms);
381             }
382             if (classifierRef.getDirection() != null) {
383                 ruleClassifierBuilder.setDirection(Direction.forValue(classifierRef.getDirection().getIntValue()));
384             } else {
385                 ruleClassifierBuilder.setDirection(Direction.Bidirectional);
386             }
387             fClassifiers.add(ruleClassifierBuilder.build());
388         }
389         return fClassifiers;
390     }
391
392     private ClassifierInstance getClassifierInstance(TenantId tenantId, ClassifierName name, DataBroker dataProvider) {
393         ReadOnlyTransaction trans = dataProvider.newReadOnlyTransaction();
394         InstanceIdentifier<ClassifierInstance> ciId = InstanceIdentifier.builder(Tenants.class)
395             .child(Tenant.class, new TenantKey(tenantId))
396             .child(Policy.class)
397             .child(SubjectFeatureInstances.class)
398             .child(ClassifierInstance.class, new ClassifierInstanceKey(name))
399             .build();
400         try {
401             Optional<ClassifierInstance> data = trans.read(LogicalDatastoreType.CONFIGURATION, ciId).get();
402             if (data.isPresent()) {
403                 return data.get();
404             }
405         } catch (Exception e) {
406             LOG.error("Couldn't read Classifier instance from datastore. Exception: ", e);
407         }
408         return null;
409     }
410 }