2 * Copyright (c) 2014 Cisco Systems, Inc. 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.ofoverlay;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
17 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
22 import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinitionKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubjectFeatureInstances;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
32 import org.opendaylight.yangtools.concepts.ListenerRegistration;
33 import org.opendaylight.yangtools.yang.binding.DataObject;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import java.util.concurrent.ScheduledExecutorService;
41 * Manage all things SFC
43 * This is a bit of a place-holder for functionality
44 * that we'll need to add for SFC integration. This
45 * will likely change a lot.
47 * One problem is that the ActionInstance can reference
48 * an ActionDefintion that doesn't yet exist. Since the
49 * life cycles of these two objects are independent, we'd
50 * need some way of doing this check if there's ever an
51 * update that creates the ActionDefinition with a "chain"
52 * action after the ActionInstance that references it
53 * (i.e the creation of the ActionDefinition event).
55 * There are some other questions that need resolving -- how are
56 * updates to SFC chains received and managed by GBP? We
57 * may need to either add an RPC that SFC calls for updates
58 * or implement a data change listener to manage SFC state
61 * TODO Move SfcManager out out ofoverlay renderer -- should be something
62 * that's shared by renderers, not specific to ofoverlay
66 public class SfcManager implements AutoCloseable, DataChangeListener {
67 private static final Logger LOG =
68 LoggerFactory.getLogger(SfcManager.class);
70 private final DataBroker dataBroker;
72 private final PolicyResolver policyResolver;
74 private final RpcProviderRegistry rpcRegistry;
75 private final ScheduledExecutorService executor;
76 private final InstanceIdentifier<ActionInstance> allActionInstancesIid;
77 private final ListenerRegistration<DataChangeListener> actionListener;
79 // place-holder - not sure what we'll call it
80 private final String SFC_CHAIN_ACTION = "CHAIN";
81 private final String SFC_CHAIN_NAME = "sfc-chain-name";
82 private final String SFC_RSP_NAME = "rsp-sfc-gbp";
84 public SfcManager(DataBroker dataBroker,
85 PolicyResolver policyResolver,
86 RpcProviderRegistry rpcRegistry,
87 ScheduledExecutorService executor) {
88 this.dataBroker = dataBroker;
89 this.policyResolver = policyResolver;
90 this.rpcRegistry = rpcRegistry;
91 this.executor = executor;
94 * For now, listen to all changes in rules
96 allActionInstancesIid =
97 InstanceIdentifier.builder(Tenants.class)
99 .child(SubjectFeatureInstances.class)
100 .child(ActionInstance.class)
102 actionListener = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
103 allActionInstancesIid, this, DataChangeScope.ONE);
104 LOG.debug("SfcManager: Started");
108 public void onDataChanged(
109 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
111 // For now, just go off new ActionInstance objects
112 for (DataObject dao : change.getCreatedData().values()) {
113 if (dao instanceof ActionInstance) {
114 ActionInstance ai = (ActionInstance)dao;
115 LOG.debug("New ActionInstance created");
116 executor.execute(new MatchActionDefTask(ai));
120 // We'll worry about udpates and deletes later
121 // for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
122 // DataObject old = change.getOriginalData().get(iid);
123 // if (old != null && old instanceof Rule) {
128 // for (DataObject dao : change.getUpdatedData().values()) {
134 * Private internal class that gets the action definition
135 * referenced by the instance. If the definition has an
136 * action of "chain" (or whatever we decide to use
137 * here), then we need to invoke the SFC API to go
138 * get the chain information, which we'll eventually
139 * use during policy resolution.
144 private class MatchActionDefTask implements Runnable,
145 FutureCallback<Optional<ActionDefinition>> {
146 private final ActionInstance actionInstance;
147 private final InstanceIdentifier<ActionDefinition> adIid;
148 private final ActionDefinitionId id;
150 public MatchActionDefTask(ActionInstance actionInstance) {
151 this.actionInstance = actionInstance;
152 this.id = actionInstance.getActionDefinitionId();
154 adIid = InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
155 .child(ActionDefinition.class,
156 new ActionDefinitionKey(this.id))
162 * Create read transaction with callback
166 ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
167 ListenableFuture<Optional<ActionDefinition>> dao =
168 rot.read(LogicalDatastoreType.CONFIGURATION, adIid);
169 Futures.addCallback(dao, this, executor);
174 public void onFailure(Throwable arg0) {
175 LOG.error("Failure reading ActionDefinition {}", id.getValue());
179 public void onSuccess(Optional<ActionDefinition> dao) {
180 LOG.debug("Found ActionDefinition {}", id.getValue());
181 if (dao instanceof ActionDefinition) {
182 ActionDefinition ad = (ActionDefinition)dao;
183 if (ad.getName().getValue().equals(SFC_CHAIN_ACTION)) {
185 * We have the state we need:
186 * 1) it's a "CHAIN" action
187 * 2) the name is defined in the ActionInstance
189 if (actionInstance.getParameterValue() != null) {
197 * Go get the RenderedServicePath from SFC
199 * TBD: what to do with this once we have it - who to
202 private void getSfcChain() {
203 for (ParameterValue pv: actionInstance.getParameterValue()) {
204 if (pv.getName().getValue().equals(SFC_CHAIN_NAME)) {
207 // RenderedServicePath rsp =
208 // createRenderedServicePathAndState(pv.getStringValue());
215 * Go get the RenderedServicePath from SFC
217 * TBD: what to do with this once we have it - who to
220 private void getSfcRsp() {
221 for (ParameterValue pv: actionInstance.getParameterValue()) {
222 if (pv.getName().getValue().equals(SFC_CHAIN_NAME)) {
225 /* Uncomment when new SFC artifacts are pushed
226 RenderedServicePathFirstHop renderedServicePathFirstHop =
227 SfcProviderRenderedPathAPI.readRenderedServicePathFirstHop(SFC_CHAIN_NAME);*/
237 public void close() throws Exception {
238 if (actionListener != null) actionListener.close();