2 * Copyright (c) 2017 Pantheon Technologies s.r.o. 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
8 package org.opendaylight.openflowplugin.impl.services.multilayer;
10 import com.google.common.annotations.VisibleForTesting;
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 com.google.common.util.concurrent.MoreExecutors;
15 import com.google.common.util.concurrent.SettableFuture;
16 import java.util.ArrayList;
17 import java.util.List;
18 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
19 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
20 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
21 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
22 import org.opendaylight.openflowplugin.extension.api.ConverterMessageToOFJava;
23 import org.opendaylight.openflowplugin.extension.api.ConvertorData;
24 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
25 import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
26 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
27 import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
28 import org.opendaylight.openflowplugin.extension.api.exception.ConverterNotFoundException;
29 import org.opendaylight.openflowplugin.extension.api.path.MessagePath;
30 import org.opendaylight.openflowplugin.impl.services.AbstractExperimenterMultipartService;
31 import org.opendaylight.openflowplugin.impl.services.util.RequestInputUtils;
32 import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItem;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.send.experimenter.mp.request.output.ExperimenterCoreMessageItemBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenter;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenterCaseBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.experimenter._case.MultipartRequestExperimenterBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
47 import org.opendaylight.yangtools.yang.common.ErrorType;
48 import org.opendaylight.yangtools.yang.common.RpcResult;
49 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
50 import org.slf4j.Logger;
52 public class MultiLayerExperimenterMultipartService extends AbstractExperimenterMultipartService<MultipartReply> {
54 private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(MultiLayerExperimenterMultipartService.class);
56 public MultiLayerExperimenterMultipartService(RequestContextStack requestContextStack, DeviceContext deviceContext,
57 ExtensionConverterProvider extensionConverterProvider) {
58 super(requestContextStack, deviceContext, extensionConverterProvider);
62 @SuppressWarnings("unchecked")
63 protected OfHeader buildRequest(Xid xid, SendExperimenterMpRequestInput input) throws ServiceException {
64 final TypeVersionKey key = new TypeVersionKey<>(
65 input.getExperimenterMessageOfChoice().implementedInterface(),
68 final ConverterMessageToOFJava<ExperimenterMessageOfChoice, ExperimenterDataOfChoice,
69 ConvertorData> messageConverter = getExtensionConverterProvider().getMessageConverter(key);
71 if (messageConverter == null) {
72 throw new ServiceException(new ConverterNotFoundException(key.toString()));
76 return RequestInputUtils
77 .createMultipartHeader(MultipartType.OFPMPEXPERIMENTER, xid.getValue(), getVersion())
78 .setMultipartRequestBody(new MultipartRequestExperimenterCaseBuilder()
79 .setMultipartRequestExperimenter(new MultipartRequestExperimenterBuilder()
80 .setExperimenter(messageConverter.getExperimenterId())
81 .setExpType(messageConverter.getType())
82 .setExperimenterDataOfChoice(messageConverter
83 .convert(input.getExperimenterMessageOfChoice(), null))
87 } catch (final ConversionException e) {
88 throw new ServiceException(e);
93 @SuppressWarnings("unchecked")
94 public ListenableFuture<RpcResult<SendExperimenterMpRequestOutput>> handleAndReply(
95 SendExperimenterMpRequestInput input) {
96 final ListenableFuture<RpcResult<List<MultipartReply>>> multipartFuture = handleServiceCall(input);
97 final SettableFuture<RpcResult<SendExperimenterMpRequestOutput>> finalFuture = SettableFuture.create();
99 class CallBackImpl implements FutureCallback<RpcResult<List<MultipartReply>>> {
101 public void onSuccess(final RpcResult<List<MultipartReply>> result) {
102 if (result.isSuccessful()) {
103 final List<MultipartReply> multipartReplies = result.getResult();
104 if (multipartReplies.isEmpty()) {
105 LOG.warn("Multipart reply to Experimenter-Mp request shouldn't be empty list.");
106 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed()
107 .withError(ErrorType.RPC, "Multipart reply list is empty.").build());
110 "OnSuccess, rpc result successful,"
111 + " multipart response for rpc sendExperimenterMpRequest with xid {} obtained.",
112 multipartReplies.get(0).getXid());
113 final SendExperimenterMpRequestOutputBuilder sendExpMpReqOutputBuilder =
114 new SendExperimenterMpRequestOutputBuilder();
115 final List<ExperimenterCoreMessageItem> expCoreMessageItem = new ArrayList<>();
116 for (MultipartReply multipartReply : multipartReplies) {
117 final MultipartReplyExperimenterCase caseBody =
118 (MultipartReplyExperimenterCase)multipartReply.getMultipartReplyBody();
119 final MultipartReplyExperimenter replyBody = caseBody.getMultipartReplyExperimenter();
120 final ExperimenterDataOfChoice vendorData = replyBody.getExperimenterDataOfChoice();
121 final MessageTypeKey<? extends ExperimenterDataOfChoice> key = new MessageTypeKey<>(
123 (Class<? extends ExperimenterDataOfChoice>) vendorData.implementedInterface());
124 final ConvertorMessageFromOFJava<ExperimenterDataOfChoice, MessagePath> messageConverter =
125 getExtensionConverterProvider().getMessageConverter(key);
126 if (messageConverter == null) {
127 LOG.warn("Custom converter for {}[OF:{}] not found",
128 vendorData.implementedInterface(),
130 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed()
131 .withError(ErrorType.RPC, "Custom converter not found.").build());
134 final ExperimenterMessageOfChoice messageOfChoice =
135 messageConverter.convert(vendorData, MessagePath.MPMESSAGE_RPC_OUTPUT);
136 final ExperimenterCoreMessageItemBuilder expCoreMessageItemBuilder =
137 new ExperimenterCoreMessageItemBuilder();
138 expCoreMessageItemBuilder.setExperimenterMessageOfChoice(messageOfChoice);
139 expCoreMessageItem.add(expCoreMessageItemBuilder.build());
141 sendExpMpReqOutputBuilder.setExperimenterCoreMessageItem(expCoreMessageItem);
142 finalFuture.set(RpcResultBuilder.success(sendExpMpReqOutputBuilder.build()).build());
145 LOG.warn("OnSuccess, rpc result unsuccessful,"
146 + " multipart response for rpc sendExperimenterMpRequest was unsuccessful.");
147 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed()
148 .withRpcErrors(result.getErrors()).build());
153 public void onFailure(final Throwable throwable) {
154 LOG.warn("Failure multipart response for Experimenter-Mp request", throwable);
155 finalFuture.set(RpcResultBuilder.<SendExperimenterMpRequestOutput>failed()
156 .withError(ErrorType.RPC, "Future error", throwable).build());
160 Futures.addCallback(multipartFuture, new CallBackImpl(), MoreExecutors.directExecutor());
166 OfHeader buildRequestTest(Xid xid, SendExperimenterMpRequestInput input) throws ServiceException {
167 return buildRequest(xid, input);