Implementation of services
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / services / CommonService.java
1 /**
2  * Copyright (c) 2015 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 package org.opendaylight.openflowplugin.impl.services;
9
10 import com.google.common.base.Function;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
15 import org.opendaylight.openflowplugin.api.OFConstants;
16 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
17 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
18 import org.opendaylight.openflowplugin.api.openflow.md.core.sal.NotificationComposer;
19 import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
20 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdatedBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionAware;
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;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
35 import org.opendaylight.yangtools.yang.binding.DataContainer;
36 import org.opendaylight.yangtools.yang.binding.Notification;
37 import org.opendaylight.yangtools.yang.common.RpcError;
38 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
39 import org.opendaylight.yangtools.yang.common.RpcResult;
40 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
41 import org.slf4j.Logger;
42 import java.math.BigInteger;
43 import java.util.ArrayList;
44 import java.util.List;
45 import java.util.concurrent.Future;
46
47 public class CommonService {
48     // protected OFRpcTaskContext rpcTaskContext;
49     protected short version;
50     protected BigInteger datapathId;
51     protected RpcContext rpcContext;
52     protected SwitchConnectionDistinguisher cookie;
53     // TODO should come from deviceContext
54     protected IMessageDispatchService messageService;
55     protected Xid xid;
56     protected Boolean isBarrier;
57
58     protected NotificationProviderService notificationProviderService;
59
60     protected final static Future<RpcResult<Void>> errorRpcResult = Futures.immediateFuture(RpcResultBuilder
61             .<Void>failed().withError(ErrorType.APPLICATION, "", "Request quota exceeded.").build());
62
63     private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(CommonService.class);
64
65     public CommonService() {
66
67     }
68
69     /**
70      * @param xid
71      */
72     public CommonService(final RpcContext rpcContext, final short version, final BigInteger datapathId,
73                          final IMessageDispatchService service, final Xid xid, final SwitchConnectionDistinguisher cookie) {
74         this.rpcContext = rpcContext;
75         this.version = version;
76         this.datapathId = datapathId;
77         this.messageService = service;
78         this.xid = xid;
79         this.cookie = cookie;
80     }
81
82     /**
83      * @param originalResult
84      * @param notificationProviderService
85      * @param notificationComposer        lazy notification composer
86      */
87     protected <R extends RpcResult<? extends TransactionAware>, N extends Notification, I extends DataContainer> void hookFutureNotification(
88             final ListenableFuture<R> originalResult, final NotificationProviderService notificationProviderService,
89             final NotificationComposer<N> notificationComposer) {
90
91         class FutureCallbackImpl implements FutureCallback<R> {
92             @Override
93             public void onSuccess(final R result) {
94                 if (null == notificationProviderService) {
95                     LOG.warn("onSuccess(): notificationServiceProvider is null, could not publish result {}", result);
96                 } else if (notificationComposer == null) {
97                     LOG.warn("onSuccess(): notificationComposer is null, could not publish result {}", result);
98                 } else if (result == null) {
99                     LOG.warn("onSuccess(): result is null, could not publish result {}", result);
100                 } else if (result.getResult() == null) {
101                     LOG.warn("onSuccess(): result.getResult() is null, could not publish result {}", result);
102                 } else if (result.getResult().getTransactionId() == null) {
103                     LOG.warn("onSuccess(): result.getResult().getTransactionId() is null, could not publish result {}",
104                             result);
105                 } else {
106                     notificationProviderService.publish(notificationComposer.compose(result.getResult()
107                             .getTransactionId()));
108                     // TODO: solve without task
109                     // task.getTaskContext().getMessageSpy().spyMessage(
110                     // task.getInput(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_SUBMITTED_SUCCESS);
111                 }
112             }
113
114             @Override
115             public void onFailure(final Throwable t) {
116                 // TODO: good place to notify MD-SAL about errors
117                 // TODO: solve without task
118                 // task.getTaskContext().getMessageSpy().spyMessage(
119                 // task.getInput(), MessageSpy.STATISTIC_GROUP.TO_SWITCH_SUBMITTED_FAILURE);
120             }
121         }
122
123         Futures.addCallback(originalResult, new FutureCallbackImpl());
124     }
125
126     /**
127      * @param input
128      * @return
129      */
130     protected NotificationComposer<FlowAdded> createFlowAddedNotification(final AddFlowInput input) {
131         return new NotificationComposer<FlowAdded>() {
132             @Override
133             public FlowAdded compose(final TransactionId tXid) {
134                 final FlowAddedBuilder newFlow = new FlowAddedBuilder((Flow) input);
135                 newFlow.setTransactionId(tXid);
136                 newFlow.setFlowRef(input.getFlowRef());
137                 return newFlow.build();
138             }
139         };
140     }
141
142     protected NotificationComposer<FlowUpdated> createFlowUpdatedNotification(final UpdateFlowInput input) {
143         return new NotificationComposer<FlowUpdated>() {
144             @Override
145             public FlowUpdated compose(final TransactionId tXid) {
146                 final FlowUpdatedBuilder updFlow = new FlowUpdatedBuilder(input.getUpdatedFlow());
147                 updFlow.setTransactionId(tXid);
148                 updFlow.setFlowRef(input.getFlowRef());
149                 return updFlow.build();
150             }
151         };
152     }
153
154     protected static NotificationComposer<FlowRemoved> createFlowRemovedNotification(final RemoveFlowInput input) {
155         return new NotificationComposer<FlowRemoved>() {
156             @Override
157             public FlowRemoved compose(final TransactionId tXid) {
158                 final FlowRemovedBuilder removedFlow = new FlowRemovedBuilder((Flow) input);
159                 removedFlow.setTransactionId(tXid);
160                 removedFlow.setFlowRef(input.getFlowRef());
161                 return removedFlow.build();
162             }
163         };
164     }
165
166     /**
167      * @param originalInput
168      * @return
169      */
170     protected static <T extends TransactionAware> Function<RpcResult<BarrierOutput>, RpcResult<T>> transformBarrierToTransactionAware(
171             final RpcResult<T> originalInput, final BarrierInput barrierInput) {
172
173         class FunctionImpl implements Function<RpcResult<BarrierOutput>, RpcResult<T>> {
174
175             @Override
176             public RpcResult<T> apply(final RpcResult<BarrierOutput> barrierResult) {
177                 RpcResultBuilder<T> rpcBuilder = null;
178                 if (barrierResult.isSuccessful()) {
179                     rpcBuilder = RpcResultBuilder.<T>success();
180                 } else {
181                     rpcBuilder = RpcResultBuilder.<T>failed();
182                     final RpcError rpcError = RpcResultBuilder
183                             .newWarning(
184                                     ErrorType.RPC,
185                                     OFConstants.ERROR_TAG_TIMEOUT,
186                                     "barrier sending failed",
187                                     OFConstants.APPLICATION_TAG,
188                                     "switch failed to respond on barrier request, barrier.xid = "
189                                             + barrierInput.getXid(), null);
190                     final List<RpcError> chainedErrors = new ArrayList<>();
191                     chainedErrors.add(rpcError);
192                     chainedErrors.addAll(barrierResult.getErrors());
193                     rpcBuilder.withRpcErrors(chainedErrors);
194                 }
195
196                 rpcBuilder.withResult(originalInput.getResult());
197
198                 return rpcBuilder.build();
199             }
200         }
201
202         return new FunctionImpl();
203     }
204
205 }