Remove "response" from yang.
[packetcable.git] / packetcable-provider / src / main / java / org / opendaylight / controller / packetcable / provider / OpendaylightPacketcableProvider.java
1 package org.opendaylight.controller.packetcable.provider;
2
3 import com.google.common.base.Optional;
4 import com.google.common.collect.Lists;
5 import com.google.common.util.concurrent.CheckedFuture;
6 import com.google.common.util.concurrent.FutureCallback;
7 import com.google.common.util.concurrent.Futures;
8 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
9 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
10 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
11 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
12 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
13 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
14 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
15 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
16 import org.opendaylight.controller.packetcable.provider.processors.PCMMDataProcessor;
17 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
18 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
19 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
20 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.*;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.TrafficProfileBestEffortAttributes;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.TrafficProfileDocsisServiceClassNameAttributes;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.TrafficProfileFlowspecAttributes;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.BestEffortCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.DocsisServiceClassNameCase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.add.flow.input.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.FlowspecCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContextRef;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.node.cmts.broker.rev140909.*;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.node.cmts.rev140909.CmtsCapableNode;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.node.cmts.rev140909.nodes.node.CmtsNode;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.UdpMatchRangesRpcRemoveFlow;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.UdpMatchRangesRpcUpdateFlowOriginal;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.UdpMatchRangesRpcUpdateFlowUpdated;
45 import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
46 import org.opendaylight.yangtools.concepts.CompositeObjectRegistration.CompositeObjectRegistrationBuilder;
47 import org.opendaylight.yangtools.concepts.ListenerRegistration;
48 import org.opendaylight.yangtools.yang.binding.DataObject;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.opendaylight.yangtools.yang.common.RpcResult;
51 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
52 import org.pcmm.gates.IClassifier;
53 import org.pcmm.gates.ITrafficProfile;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 import java.util.Iterator;
58 import java.util.List;
59 import java.util.concurrent.ExecutionException;
60 import java.util.concurrent.ExecutorService;
61 import java.util.concurrent.Executors;
62 import java.util.concurrent.Future;
63 import java.util.concurrent.atomic.AtomicReference;
64
65 @SuppressWarnings("unused")
66 public class OpendaylightPacketcableProvider implements DataChangeListener,
67                 SalFlowService, OpenDaylightPacketCableProviderService,
68                 BindingAwareProvider, AutoCloseable {
69
70         private static final Logger logger = LoggerFactory.getLogger(OpendaylightPacketcableProvider.class);
71         private NotificationProviderService notificationProvider;
72         private DataBroker dataProvider;
73
74         private final ExecutorService executor;
75
76         // The following holds the Future for the current make toast task.
77         // This is used to cancel the current toast.
78         private final AtomicReference<Future<?>> currentConnectionsTasks = new AtomicReference<>();
79         private ProviderContext providerContext;
80         private NotificationProviderService notificationService;
81         private DataBroker dataBroker;
82         private ListenerRegistration<DataChangeListener> listenerRegistration;
83         private List<InstanceIdentifier<?>> cmtsInstances;
84         private PCMMDataProcessor pcmmDataProcessor;
85
86         public OpendaylightPacketcableProvider() {
87         logger.info("Instantiating");
88                 executor = Executors.newCachedThreadPool();
89                 cmtsInstances = Lists.newArrayList();
90                 pcmmDataProcessor = new PCMMDataProcessor();
91         }
92
93         public void setNotificationProvider(final NotificationProviderService salService) {
94                 this.notificationProvider = salService;
95         }
96
97         public void setDataProvider(final DataBroker salDataProvider) {
98                 this.dataProvider = salDataProvider;
99         }
100
101         /**
102          * Implemented from the AutoCloseable interface.
103          */
104         @Override
105         public void close() throws ExecutionException, InterruptedException {
106         logger.info("Closing");
107                 executor.shutdown();
108                 if (dataProvider != null) {
109                         for (Iterator<InstanceIdentifier<?>> iter = cmtsInstances.iterator(); iter.hasNext();) {
110                                 WriteTransaction tx = dataProvider.newWriteOnlyTransaction();
111                                 tx.delete(LogicalDatastoreType.OPERATIONAL, iter.next());
112                                 Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
113                                         @Override
114                                         public void onSuccess(final Void result) {
115                                                 logger.debug("Delete commit result: " + result);
116                                         }
117
118                                         @Override
119                                         public void onFailure(final Throwable t) {
120                                                 logger.error("Delete operation failed", t);
121                                         }
122                                 });
123                         }
124                 }
125         }
126
127         /**
128          * Implemented from the DataChangeListener interface.
129          */
130         @Override
131         public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
132                 DataObject dataObject = change.getUpdatedSubtree();
133                 logger.debug("OpendaylightPacketcableProvider.onDataChanged() :" + dataObject);
134         }
135
136         public void notifyConsumerOnCmtsAdd(CmtsNode input, TransactionId transactionId) {
137                 CmtsAdded cmtsRemoved = new CmtsAddedBuilder().setAddress(input.getAddress()).setPort(input.getPort()).setTransactionId(transactionId).build();
138                 notificationProvider.publish(cmtsRemoved);
139         }
140
141         public void notifyConsumerOnCmtsRemove(CmtsNode input, TransactionId transactionId) {
142                 CmtsRemoved cmtsRemoved = new CmtsRemovedBuilder().setAddress(input.getAddress()).setPort(input.getPort()).setTransactionId(transactionId).build();
143                 notificationProvider.publish(cmtsRemoved);
144         }
145
146         public void notifyConsumerOnCmtsUpdate(CmtsNode input, TransactionId transactionId) {
147                 CmtsUpdated cmtsRemoved = new CmtsUpdatedBuilder().setAddress(input.getAddress()).setPort(input.getPort()).setTransactionId(transactionId).build();
148                 notificationProvider.publish(cmtsRemoved);
149         }
150
151         @Override
152         public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
153                 Match match = input.getMatch();
154                 CmtsNode cmts = getCmtsNode(input);
155                 if (cmts != null)
156                         cmtsInstances.add(input.getNode().getValue());
157                 IClassifier classifier = buildClassifier(match);
158                 ITrafficProfile trafficProfie = null;
159                 for (Instruction i : input.getInstructions().getInstruction()) {
160                         if (i.getInstruction() instanceof ApplyActionsCase) {
161                                 ApplyActionsCase aac = (ApplyActionsCase) i.getInstruction();
162                                 for (Action a : aac.getApplyActions().getAction()) {
163                                         if (a.getAction() instanceof FlowspecCase) {
164                                                 // not implemented
165                                                 // trafficProfie = buildTrafficProfile(((FlowspecCase)
166                                                 // a.getAction()).getFlowspec());
167                                         } else if (a.getAction() instanceof BestEffortCase) {
168                                                 trafficProfie = buildTrafficProfile(((BestEffortCase) a.getAction()).getBestEffort());
169                                                 break;
170                                         } else if (a.getAction() instanceof DocsisServiceClassNameCase) {
171                                                 trafficProfie = buildTrafficProfile(((DocsisServiceClassNameCase) a.getAction()).getDocsisServiceClassName());
172                                                 break;
173                                         }
174                                 }
175                         }
176                 }
177                 TransactionId transactionId = null;
178                 notifyConsumerOnCmtsAdd(cmts, transactionId);
179                 return Futures.immediateFuture(RpcResultBuilder.success(new AddFlowOutputBuilder().setTransactionId(transactionId).build()).build());
180         }
181
182         @Override
183         public ITrafficProfile buildTrafficProfile(TrafficProfileDocsisServiceClassNameAttributes docsis) {
184                 return pcmmDataProcessor.process(docsis);
185         }
186
187         @Override
188         public ITrafficProfile buildTrafficProfile(TrafficProfileBestEffortAttributes bestEffort) {
189                 return pcmmDataProcessor.process(bestEffort);
190         }
191
192         @Override
193         public ITrafficProfile buildTrafficProfile(TrafficProfileFlowspecAttributes flowSpec) {
194                 return pcmmDataProcessor.process(flowSpec);
195         }
196
197         @Override
198         public IClassifier buildClassifier(Match match) {
199                 return pcmmDataProcessor.process(match);
200         }
201
202         @Override
203         public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
204                 UdpMatchRangesRpcRemoveFlow updRange = input.getMatch().getAugmentation(UdpMatchRangesRpcRemoveFlow.class);
205                 notifyConsumerOnCmtsRemove(getCmtsNode(input), null);
206                 return null;
207         }
208
209         @Override
210         public Future<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput input) {
211                 OriginalFlow foo = input.getOriginalFlow();
212                 UdpMatchRangesRpcUpdateFlowOriginal bar = foo.getMatch().getAugmentation(UdpMatchRangesRpcUpdateFlowOriginal.class);
213                 UpdatedFlow updated = input.getUpdatedFlow();
214                 UdpMatchRangesRpcUpdateFlowUpdated updatedRange = updated.getMatch().getAugmentation(UdpMatchRangesRpcUpdateFlowUpdated.class);
215                 notifyConsumerOnCmtsUpdate(getCmtsNode(input), null);
216                 return null;
217         }
218
219         @SuppressWarnings("unchecked")
220         protected CmtsNode getCmtsNode(NodeContextRef input) {
221                 NodeRef nodeRef = input.getNode();
222                 InstanceIdentifier<Node> instanceIdentifier = (InstanceIdentifier<Node>) nodeRef.getValue();
223                 ReadOnlyTransaction rtransaction = dataBroker.newReadOnlyTransaction();
224                 CheckedFuture<Optional<Node>, ReadFailedException> value = rtransaction.read(LogicalDatastoreType.CONFIGURATION, instanceIdentifier);
225                 rtransaction.close();
226                 Optional<Node> opt = null;
227                 try {
228                         opt = value.get();
229                 } catch (Exception e) {
230                         logger.error(e.getMessage());
231                         return null;
232                 }
233                 Node node = opt.get();
234                 CmtsCapableNode cmts = node.getAugmentation(CmtsCapableNode.class);
235                 CmtsNode cmtsNode = cmts.getCmtsNode();
236                 return cmtsNode;
237         }
238
239         @Override
240         public void onSessionInitiated(ProviderContext session) {
241         logger.info("Initiating session");
242                 providerContext = session;
243                 notificationService = session.getSALService(NotificationProviderService.class);
244                 dataBroker = session.getSALService(DataBroker.class);
245                 InstanceIdentifier<CmtsNode> listenTo = InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(CmtsCapableNode.class).child(CmtsNode.class);
246                 listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, listenTo, this, DataChangeScope.BASE);
247         }
248
249
250         public void onSessionAdded(/* Whatever you need per CmtsConnection */) {
251                 CompositeObjectRegistrationBuilder<OpendaylightPacketcableProvider> builder = CompositeObjectRegistration.<OpendaylightPacketcableProvider> builderFor(this);
252                 /*
253                  * You will need a routedRpc registration per Cmts... I'm not doing the
254                  * accounting of storing them here, but you will need to so you can
255                  * close them when your provider is closed
256                  */
257                 RoutedRpcRegistration<SalFlowService> registration = providerContext.addRoutedRpcImplementation(SalFlowService.class, this);
258                 /*
259                  * You will need to get your identifier somewhere... this is your
260                  * nodeId. I would recommend adoption a convention like
261                  * "cmts:<ipaddress>" for CmtsCapableNodes
262                  * registration.registerPath(NodeContext.class, getIdentifier());
263                  */
264         }
265
266 }