Fix for neutron issue - use karaf-parent
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / SfcManager.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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.ofoverlay;
10
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;
37
38 import java.util.concurrent.ScheduledExecutorService;
39
40 /**
41  * Manage all things SFC
42  *
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.
46  *
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).
54  *
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
59  * updates.
60  *
61  * TODO Move SfcManager out out ofoverlay renderer -- should be something
62  *       that's shared by renderers, not specific to ofoverlay
63  *
64  * @author tbachman
65  */
66 public class SfcManager implements AutoCloseable, DataChangeListener {
67     private static final Logger LOG =
68             LoggerFactory.getLogger(SfcManager.class);
69
70     private final DataBroker dataBroker;
71     // currently unused
72     private final PolicyResolver policyResolver;
73     // currently unused
74     private final RpcProviderRegistry rpcRegistry;
75     private final ScheduledExecutorService executor;
76     private final InstanceIdentifier<ActionInstance> allActionInstancesIid;
77     private final ListenerRegistration<DataChangeListener> actionListener;
78
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";
83
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;
92
93         /*
94          * For now, listen to all changes in rules
95          */
96         allActionInstancesIid =
97                 InstanceIdentifier.builder(Tenants.class)
98                     .child(Tenant.class)
99                     .child(SubjectFeatureInstances.class)
100                     .child(ActionInstance.class)
101                     .build();
102         actionListener = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, 
103                 allActionInstancesIid, this, DataChangeScope.ONE);
104         LOG.debug("SfcManager: Started");
105     }
106
107     @Override
108     public void onDataChanged(
109             AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
110
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));
117             }
118         }
119
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) {
124 //
125 //            }
126 //        }
127 //
128 //        for (DataObject dao : change.getUpdatedData().values()) {
129 //
130 //        }
131     }
132
133     /**
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.
140      *
141      * @author tbachman
142      *
143      */
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;
149
150         public MatchActionDefTask(ActionInstance actionInstance) {
151             this.actionInstance = actionInstance;
152             this.id = actionInstance.getActionDefinitionId();
153
154             adIid = InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
155                                       .child(ActionDefinition.class,
156                                              new ActionDefinitionKey(this.id))
157                                       .build();
158
159         }
160
161         /**
162          * Create read transaction with callback
163          */
164         @Override
165         public void run() {
166             ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
167             ListenableFuture<Optional<ActionDefinition>> dao =
168                     rot.read(LogicalDatastoreType.CONFIGURATION, adIid);
169             Futures.addCallback(dao, this, executor);
170
171         }
172
173         @Override
174         public void onFailure(Throwable arg0) {
175             LOG.error("Failure reading ActionDefinition {}", id.getValue());
176         }
177
178         @Override
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)) {
184                     /*
185                      * We have the state we need:
186                      *  1) it's a "CHAIN" action
187                      *  2) the name is defined in the ActionInstance
188                      */
189                     if (actionInstance.getParameterValue() != null) {
190                         getSfcRsp();
191                     }
192                 }
193             }
194         }
195
196         /**
197          * Go get the RenderedServicePath from SFC
198          *
199          * TBD: what to do with this once we have it - who to
200          * give it to
201          */
202         private void getSfcChain() {
203             for (ParameterValue pv: actionInstance.getParameterValue()) {
204                 if (pv.getName().getValue().equals(SFC_CHAIN_NAME)) {
205
206                     // Go get the RSP
207 //                    RenderedServicePath rsp =
208 //                            createRenderedServicePathAndState(pv.getStringValue());
209
210                 }
211             }
212         }
213
214         /**
215          * Go get the RenderedServicePath from SFC
216          *
217          * TBD: what to do with this once we have it - who to
218          * give it to
219          */
220         private void getSfcRsp() {
221             for (ParameterValue pv: actionInstance.getParameterValue()) {
222                 if (pv.getName().getValue().equals(SFC_CHAIN_NAME)) {
223
224
225 /*                  Uncomment when new SFC artifacts are pushed
226                     RenderedServicePathFirstHop renderedServicePathFirstHop =
227                             SfcProviderRenderedPathAPI.readRenderedServicePathFirstHop(SFC_CHAIN_NAME);*/
228
229                 }
230             }
231         }
232
233
234     }
235
236     @Override
237     public void close() throws Exception {
238         if (actionListener != null) actionListener.close();
239
240     }
241 }