Fix warnings in sample-bundles
[openflowplugin.git] / samples / sample-bundles / src / main / java / org / opendaylight / openflowplugin / samples / sample / bundles / SampleFlowCapableNodeListener.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.samples.sample.bundles;
9
10 import java.util.List;
11 import java.util.concurrent.CompletableFuture;
12 import java.util.concurrent.ExecutionException;
13 import java.util.concurrent.ExecutorService;
14 import java.util.concurrent.Executors;
15 import java.util.concurrent.Future;
16 import javax.annotation.PreDestroy;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.mdsal.binding.api.DataBroker;
20 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
21 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
22 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
23 import org.opendaylight.mdsal.binding.api.DataTreeModification;
24 import org.opendaylight.mdsal.binding.api.RpcService;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Group;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessages;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.AddBundleMessagesInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundle;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.ControlBundleInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.MessagesBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.Message;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.add.bundle.messages.input.messages.MessageBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddFlowCaseBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.BundleAddGroupCaseBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.bundle.add.flow._case.AddFlowCaseDataBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.bundle.inner.message.grouping.bundle.inner.message.bundle.add.group._case.AddGroupCaseDataBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleControlType;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleFlags;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.rev170124.BundleId;
74 import org.opendaylight.yangtools.concepts.Registration;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
76 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
77 import org.opendaylight.yangtools.yang.common.Uint16;
78 import org.opendaylight.yangtools.yang.common.Uint32;
79 import org.opendaylight.yangtools.yang.common.Uint64;
80 import org.opendaylight.yangtools.yang.common.Uint8;
81 import org.osgi.service.component.annotations.Activate;
82 import org.osgi.service.component.annotations.Component;
83 import org.osgi.service.component.annotations.Deactivate;
84 import org.osgi.service.component.annotations.Reference;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
87
88 /**
89  * Sample DataTreeChangeListener.
90  */
91 @Singleton
92 @Component(service = { })
93 public final class SampleFlowCapableNodeListener implements DataTreeChangeListener<FlowCapableNode>, AutoCloseable {
94     private static final Logger LOG = LoggerFactory.getLogger(SampleFlowCapableNodeListener.class);
95
96     private static final BundleId BUNDLE_ID = new BundleId(Uint32.ONE);
97     private static final BundleFlags BUNDLE_FLAGS = new BundleFlags(true, true);
98     private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
99
100     private final ControlBundle controlBundle;
101     private final AddBundleMessages addBundleMessages;
102     private final Registration listenerReg;
103
104     @Inject
105     @Activate
106     public SampleFlowCapableNodeListener(@Reference final DataBroker dataBroker,
107             @Reference final RpcService rpcService) {
108         controlBundle = rpcService.getRpc(ControlBundle.class);
109         addBundleMessages = rpcService.getRpc(AddBundleMessages.class);
110         LOG.debug("inSessionInitialized() passing");
111
112         final InstanceIdentifier<FlowCapableNode> path = InstanceIdentifier.create(Nodes.class).child(Node.class)
113                 .augmentation(FlowCapableNode.class);
114         final DataTreeIdentifier<FlowCapableNode> identifier =
115                 DataTreeIdentifier.of(LogicalDatastoreType.OPERATIONAL, path);
116
117         listenerReg = dataBroker.registerTreeChangeListener(identifier, SampleFlowCapableNodeListener.this);
118     }
119
120     @PreDestroy
121     @Deactivate
122     @Override
123     public void close() {
124         LOG.debug("close() passing");
125         listenerReg.close();
126     }
127
128     @Override
129     public void onDataTreeChanged(final List<DataTreeModification<FlowCapableNode>> modifications) {
130         for (var modification : modifications) {
131             if (modification.getRootNode().modificationType() == ModificationType.WRITE) {
132                 final var nodePath = modification.getRootPath().path().firstIdentifierOf(Node.class);
133                 LOG.info("Node connected:  {}", nodePath);
134
135                 final var nodeRef = new NodeRef(nodePath);
136
137                 final var openBundleInput = new ControlBundleInputBuilder()
138                         .setNode(nodeRef)
139                         .setBundleId(BUNDLE_ID)
140                         .setFlags(BUNDLE_FLAGS)
141                         .setType(BundleControlType.ONFBCTOPENREQUEST)
142                         .build();
143
144                 final var commitBundleInput = new ControlBundleInputBuilder()
145                         .setNode(nodeRef)
146                         .setBundleId(BUNDLE_ID)
147                         .setFlags(BUNDLE_FLAGS)
148                         .setType(BundleControlType.ONFBCTCOMMITREQUEST)
149                         .build();
150
151                 final var innerMessages = createMessages(nodeRef);
152                 final var messages = new MessagesBuilder().setMessage(innerMessages).build();
153                 final var addBundleMessagesInput = new AddBundleMessagesInputBuilder()
154                         .setNode(nodeRef)
155                         .setBundleId(BUNDLE_ID)
156                         .setFlags(BUNDLE_FLAGS)
157                         .setMessages(messages)
158                         .build();
159
160                 makeCompletableFuture(controlBundle.invoke(openBundleInput))
161                     .thenComposeAsync(voidRpcResult -> {
162                         LOG.debug("Open successful: {}, msg: {}", voidRpcResult.isSuccessful(),
163                                 voidRpcResult.getErrors());
164                         return makeCompletableFuture(addBundleMessages.invoke(addBundleMessagesInput));
165                     }).thenComposeAsync(voidRpcResult -> {
166                         LOG.debug("AddBundleMessages successful: {}, msg: {}", voidRpcResult.isSuccessful(),
167                                 voidRpcResult.getErrors());
168                         return makeCompletableFuture(controlBundle.invoke(commitBundleInput));
169                     }).thenAccept(voidRpcResult -> LOG.debug("Commit successful: {}, msg: {}",
170                         voidRpcResult.isSuccessful(), voidRpcResult.getErrors()));
171             }
172         }
173     }
174
175     private static <T> CompletableFuture<T> makeCompletableFuture(final Future<T> future) {
176         return CompletableFuture.supplyAsync(() -> {
177             try {
178                 return future.get();
179             } catch (InterruptedException | ExecutionException e) {
180                 throw new IllegalStateException(e);
181             }
182         }, EXECUTOR);
183     }
184
185     private static List<Message> createMessages(final NodeRef nodeRef) {
186         final var messages = List.of(
187             new MessageBuilder()
188                 .setNode(nodeRef)
189                 .setBundleInnerMessage(new BundleAddGroupCaseBuilder()
190                     .setAddGroupCaseData(new AddGroupCaseDataBuilder(createGroup(Uint32.ONE)).build()).build())
191                 .build(),
192             new MessageBuilder()
193                 .setNode(nodeRef)
194                 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
195                     .setAddFlowCaseData(
196                         new AddFlowCaseDataBuilder(createFlow("42", Uint32.ONE, Uint16.ONE, Uint8.ONE)).build())
197                     .build())
198                 .build(),
199             new MessageBuilder()
200                 .setNode(nodeRef)
201                 .setBundleInnerMessage(new BundleAddFlowCaseBuilder()
202                     .setAddFlowCaseData(
203                         new AddFlowCaseDataBuilder(createFlow("43", Uint32.ONE, Uint16.TWO, Uint8.TWO)).build())
204                     .build())
205                 .build());
206
207         LOG.debug("createMessages() passing {}", messages);
208
209         return messages;
210     }
211
212     private static Flow createFlow(final String flowId, final Uint32 groupId, final Uint16 priority,
213             final Uint8 tableId) {
214         return new FlowBuilder()
215             .setId(new FlowId(flowId))
216             .setTableId(tableId)
217             .setMatch(new MatchBuilder()
218                 .setEthernetMatch(new EthernetMatchBuilder()
219                     .setEthernetType(new EthernetTypeBuilder()
220                         .setType(new EtherType(Uint32.valueOf(2048)))
221                         .build())
222                     .build())
223                 .build())
224             .setInstructions(createGroupInstructions(groupId).build())
225             .setPriority(priority)
226             .setCookie(new FlowCookie(Uint64.valueOf(flowId + "" + priority)))
227             .setHardTimeout(Uint16.ZERO)
228             .setIdleTimeout(Uint16.ZERO)
229             .setStrict(false)
230             .setContainerName(null)
231             .setFlowName("FlowWithGroupInstruction")
232             .build();
233     }
234
235     private static Group createGroup(final Uint32 groupId) {
236         return new GroupBuilder()
237             .setGroupId(new GroupId(groupId))
238             .setBarrier(false)
239             .setGroupName("Foo")
240             .setContainerName(null)
241             .setGroupType(GroupTypes.GroupAll)
242             .setBuckets(createBuckets().build())
243             .build();
244     }
245
246     private static BucketsBuilder createBuckets() {
247         return new BucketsBuilder()
248             .setBucket(BindingMap.ordered(new BucketBuilder()
249                 .setBucketId(new BucketId(Uint32.valueOf(12)))
250                 .setAction(BindingMap.of(new ActionBuilder()
251                     .setOrder(0)
252                     .setAction(new PopVlanActionCaseBuilder()
253                         .setPopVlanAction(new PopVlanActionBuilder().build())
254                         .build())
255                     .build()))
256                 .build(), new BucketBuilder()
257                 .setBucketId(new BucketId(Uint32.valueOf(13)))
258                 .setAction(BindingMap.of(new ActionBuilder()
259                     .setAction(new SetFieldCaseBuilder()
260                         .setSetField(new SetFieldBuilder()
261                             .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix("10.0.1.0/32")).build())
262                             .build())
263                         .build())
264                     .setOrder(0)
265                     .build(), new ActionBuilder()
266                     .setOrder(0)
267                     .setAction(new SetFieldCaseBuilder()
268                         .setSetField(new SetFieldBuilder()
269                             .setLayer3Match(new Ipv4MatchBuilder()
270                                 .setIpv4Destination(new Ipv4Prefix("10.0.10.0/32"))
271                                 .build())
272                             .build())
273                         .build())
274                     .build()))
275                 .build()));
276     }
277
278     private static InstructionsBuilder createGroupInstructions(final Uint32 groupId) {
279         return new InstructionsBuilder()
280             .setInstruction(BindingMap.of(new InstructionBuilder()
281                 .setInstruction(new ApplyActionsCaseBuilder()
282                     .setApplyActions(new ApplyActionsBuilder()
283                         .setAction(BindingMap.of(new ActionBuilder()
284                             .setAction(new GroupActionCaseBuilder()
285                                 .setGroupAction(new GroupActionBuilder().setGroupId(groupId).build())
286                                 .build())
287                             .setOrder(1)
288                             .withKey(new ActionKey(0))
289                             .build()))
290                         .build())
291                     .build())
292                 .withKey(new InstructionKey(0))
293                 .build()));
294     }
295 }