Thomas Vachuska

Moved demo app back to main onos repo.

Change-Id: I3e445b28c1a19f9af9b582a05f3f6403af6d19c2
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<app name="org.onosproject.demo" origin="ON.Lab" version="1.2.0"
18 + features="onos-app-demo">
19 + <description>Flow throughput test application</description>
20 +</app>
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<project xmlns="http://maven.apache.org/POM/4.0.0"
18 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 + <modelVersion>4.0.0</modelVersion>
21 +
22 + <parent>
23 + <groupId>org.onosproject</groupId>
24 + <artifactId>onos-apps-test</artifactId>
25 + <version>1.2.0-SNAPSHOT</version>
26 + <relativePath>../pom.xml</relativePath>
27 + </parent>
28 +
29 + <artifactId>onos-app-demo</artifactId>
30 + <packaging>bundle</packaging>
31 +
32 + <description>ONOS demo app bundle</description>
33 +
34 + <properties>
35 + <web.context>/onos/demo</web.context>
36 + </properties>
37 +
38 + <dependencies>
39 + <dependency>
40 + <groupId>org.osgi</groupId>
41 + <artifactId>org.osgi.compendium</artifactId>
42 + </dependency>
43 + <dependency>
44 + <groupId>org.onosproject</groupId>
45 + <artifactId>onlab-rest</artifactId>
46 + <version>${project.version}</version>
47 + </dependency>
48 +
49 + <dependency>
50 + <groupId>org.onosproject</groupId>
51 + <artifactId>onos-rest</artifactId>
52 + <version>${project.version}</version>
53 + </dependency>
54 +
55 + <dependency>
56 + <groupId>com.sun.jersey</groupId>
57 + <artifactId>jersey-servlet</artifactId>
58 + </dependency>
59 + <dependency>
60 + <groupId>com.fasterxml.jackson.core</groupId>
61 + <artifactId>jackson-databind</artifactId>
62 + </dependency>
63 +
64 + <dependency>
65 + <groupId>com.fasterxml.jackson.core</groupId>
66 + <artifactId>jackson-annotations</artifactId>
67 + </dependency>
68 +
69 + <dependency>
70 + <groupId>org.osgi</groupId>
71 + <artifactId>org.osgi.core</artifactId>
72 + </dependency>
73 + </dependencies>
74 +
75 + <build>
76 + <plugins>
77 + <plugin>
78 + <groupId>org.apache.felix</groupId>
79 + <artifactId>maven-bundle-plugin</artifactId>
80 + <extensions>true</extensions>
81 + <configuration>
82 + <instructions>
83 + <_wab>src/main/webapp/</_wab>
84 + <Bundle-SymbolicName>
85 + ${project.groupId}.${project.artifactId}
86 + </Bundle-SymbolicName>
87 + <Import-Package>
88 + org.slf4j,
89 + org.osgi.framework,
90 + javax.ws.rs,javax.ws.rs.core,
91 + com.sun.jersey.api.core,
92 + com.sun.jersey.spi.container.servlet,
93 + com.sun.jersey.server.impl.container.servlet,
94 + com.fasterxml.jackson.databind,
95 + com.fasterxml.jackson.databind.node,
96 + org.apache.commons.lang.math.*,
97 + com.google.common.*,
98 + org.onlab.packet.*,
99 + org.onlab.rest.*,
100 + org.onosproject.*,
101 + org.onlab.util.*,
102 + org.jboss.netty.util.*
103 + </Import-Package>
104 + <Web-ContextPath>${web.context}</Web-ContextPath>
105 + </instructions>
106 + </configuration>
107 + </plugin>
108 + </plugins>
109 + </build>
110 +
111 +</project>
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.demo;
17 +
18 +import com.fasterxml.jackson.databind.JsonNode;
19 +
20 +import java.util.Optional;
21 +
22 +/**
23 + * Simple demo api interface.
24 + */
25 +public interface DemoAPI {
26 +
27 + enum InstallType { MESH, RANDOM };
28 +
29 + /**
30 + * Tests flow subsystem based on the parameters supplied.
31 + *
32 + * @param params the test parameters
33 + * @return JSON representation
34 + */
35 + JsonNode flowTest(Optional<JsonNode> params);
36 +
37 + /**
38 + * Installs intents based on the installation type.
39 + * @param type the installation type.
40 + * @param runParams run params
41 + */
42 + void setup(InstallType type, Optional<JsonNode> runParams);
43 +
44 + /**
45 + * Uninstalls all existing intents.
46 + */
47 + void tearDown();
48 +
49 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.demo;
17 +
18 +import com.fasterxml.jackson.databind.JsonNode;
19 +import com.fasterxml.jackson.databind.ObjectMapper;
20 +import com.fasterxml.jackson.databind.node.ObjectNode;
21 +import com.google.common.base.Predicate;
22 +import com.google.common.base.Stopwatch;
23 +import com.google.common.collect.FluentIterable;
24 +import com.google.common.collect.Lists;
25 +import com.google.common.collect.Sets;
26 +import com.google.common.util.concurrent.ThreadFactoryBuilder;
27 +import org.apache.commons.lang.math.RandomUtils;
28 +import org.apache.felix.scr.annotations.Activate;
29 +import org.apache.felix.scr.annotations.Component;
30 +import org.apache.felix.scr.annotations.Deactivate;
31 +import org.apache.felix.scr.annotations.Reference;
32 +import org.apache.felix.scr.annotations.ReferenceCardinality;
33 +import org.apache.felix.scr.annotations.Service;
34 +import org.onlab.packet.MacAddress;
35 +import org.onosproject.cluster.ClusterService;
36 +import org.onosproject.cluster.ControllerNode;
37 +import org.onosproject.cluster.NodeId;
38 +import org.onosproject.core.ApplicationId;
39 +import org.onosproject.core.CoreService;
40 +import org.onosproject.mastership.MastershipService;
41 +import org.onosproject.net.Device;
42 +import org.onosproject.net.Host;
43 +import org.onosproject.net.HostId;
44 +import org.onosproject.net.MastershipRole;
45 +import org.onosproject.net.PortNumber;
46 +import org.onosproject.net.device.DeviceService;
47 +import org.onosproject.net.flow.DefaultFlowRule;
48 +import org.onosproject.net.flow.DefaultTrafficSelector;
49 +import org.onosproject.net.flow.DefaultTrafficTreatment;
50 +import org.onosproject.net.flow.FlowRuleOperations;
51 +import org.onosproject.net.flow.FlowRuleOperationsContext;
52 +import org.onosproject.net.flow.FlowRuleService;
53 +import org.onosproject.net.flow.TrafficSelector;
54 +import org.onosproject.net.flow.TrafficTreatment;
55 +import org.onosproject.net.host.HostService;
56 +import org.onosproject.net.intent.Constraint;
57 +import org.onosproject.net.intent.HostToHostIntent;
58 +import org.onosproject.net.intent.Intent;
59 +import org.onosproject.net.intent.IntentService;
60 +import org.slf4j.Logger;
61 +
62 +import java.util.Collection;
63 +import java.util.Collections;
64 +import java.util.HashSet;
65 +import java.util.Iterator;
66 +import java.util.LinkedList;
67 +import java.util.List;
68 +import java.util.Objects;
69 +import java.util.Optional;
70 +import java.util.Random;
71 +import java.util.Set;
72 +import java.util.concurrent.Callable;
73 +import java.util.concurrent.CountDownLatch;
74 +import java.util.concurrent.ExecutionException;
75 +import java.util.concurrent.ExecutorService;
76 +import java.util.concurrent.Executors;
77 +import java.util.concurrent.Future;
78 +import java.util.concurrent.TimeUnit;
79 +import java.util.concurrent.TimeoutException;
80 +
81 +import static org.slf4j.LoggerFactory.getLogger;
82 +
83 +/**
84 + * Application to set up demos.
85 + */
86 +@Component(immediate = true)
87 +@Service
88 +public class DemoInstaller implements DemoAPI {
89 +
90 + private final Logger log = getLogger(getClass());
91 +
92 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 + protected CoreService coreService;
94 +
95 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 + protected IntentService intentService;
97 +
98 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 + protected HostService hostService;
100 +
101 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 + protected MastershipService mastershipService;
103 +
104 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 + protected ClusterService clusterService;
106 +
107 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 + protected DeviceService deviceService;
109 +
110 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 + protected FlowRuleService flowService;
112 +
113 + private ExecutorService worker;
114 +
115 + private ExecutorService installWorker;
116 +
117 + private ApplicationId appId;
118 +
119 + private final Set<Intent> existingIntents = new HashSet<>();
120 + private RandomInstaller randomInstaller;
121 +
122 + private ObjectMapper mapper = new ObjectMapper();
123 +
124 +
125 +
126 + @Activate
127 + public void activate() {
128 + String nodeId = clusterService.getLocalNode().ip().toString();
129 + appId = coreService.registerApplication("org.onosproject.demo.installer."
130 + + nodeId);
131 + worker = Executors.newFixedThreadPool(1,
132 + new ThreadFactoryBuilder()
133 + .setNameFormat("demo-app-worker")
134 + .build());
135 + log.info("Started with Application ID {}", appId.id());
136 + }
137 +
138 + @Deactivate
139 + public void deactivate() {
140 + shutdownAndAwaitTermination(worker);
141 + if (installWorker != null && !installWorker.isShutdown()) {
142 + shutdownAndAwaitTermination(installWorker);
143 + }
144 + log.info("Stopped");
145 + }
146 +
147 + @Override
148 + public JsonNode flowTest(Optional<JsonNode> params) {
149 + int flowsPerDevice = 1000;
150 + int neighbours = 0;
151 + boolean remove = true;
152 + if (params.isPresent()) {
153 + flowsPerDevice = params.get().get("flowsPerDevice").asInt();
154 + neighbours = params.get().get("neighbours").asInt();
155 + remove = params.get().get("remove").asBoolean();
156 + }
157 +
158 + Future<JsonNode> future = worker.submit(new FlowTest(flowsPerDevice, neighbours, remove));
159 +
160 + try {
161 + return future.get(10, TimeUnit.SECONDS);
162 + } catch (InterruptedException | ExecutionException | TimeoutException e) {
163 + ObjectNode node = mapper.createObjectNode();
164 + node.put("Error", e.getMessage());
165 + return node;
166 + }
167 + }
168 +
169 + @Override
170 + public void setup(InstallType type, Optional<JsonNode> runParams) {
171 + switch (type) {
172 + case MESH:
173 + log.debug("Installing mesh intents");
174 + worker.execute(new MeshInstaller());
175 + break;
176 + case RANDOM:
177 + //check that we do not have a random installer running
178 + if (installWorker == null || installWorker.isShutdown()) {
179 + installWorker = Executors.newFixedThreadPool(1,
180 + new ThreadFactoryBuilder()
181 + .setNameFormat("random-worker")
182 + .build());
183 + log.debug("Installing random sequence of intents");
184 + randomInstaller = new RandomInstaller(runParams);
185 + installWorker.execute(randomInstaller);
186 + } else {
187 + log.warn("Random installer is already running");
188 + }
189 + break;
190 + default:
191 + throw new IllegalArgumentException("What is it you want exactly?");
192 + }
193 + }
194 +
195 + @Override
196 + public void tearDown() {
197 + worker.submit(new UnInstaller());
198 + }
199 +
200 +
201 + /**
202 + * Simply installs a mesh of intents from all the hosts existing in the network.
203 + */
204 + private class MeshInstaller implements Runnable {
205 +
206 + @Override
207 + public void run() {
208 + TrafficSelector selector = DefaultTrafficSelector.emptySelector();
209 + TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
210 + List<Constraint> constraint = Lists.newArrayList();
211 + List<Host> hosts = Lists.newArrayList(hostService.getHosts());
212 + while (!hosts.isEmpty()) {
213 + Host src = hosts.remove(0);
214 + for (Host dst : hosts) {
215 + HostToHostIntent intent = HostToHostIntent.builder()
216 + .appId(appId)
217 + .one(src.id())
218 + .two(dst.id())
219 + .selector(selector)
220 + .treatment(treatment)
221 + .constraints(constraint)
222 + .build();
223 + existingIntents.add(intent);
224 + intentService.submit(intent);
225 + }
226 + }
227 + }
228 + }
229 +
230 + /**
231 + * Randomly installs and withdraws intents.
232 + */
233 + private class RandomInstaller implements Runnable {
234 +
235 + private final boolean isLocal;
236 + private final Set<Host> hosts;
237 +
238 + private final Random random = new Random(System.currentTimeMillis());
239 +
240 + private Set<HostPair> uninstalledOrWithdrawn;
241 + private Set<HostPair> installed;
242 +
243 + private CountDownLatch latch;
244 +
245 + //used to wait on a batch to be processed.
246 + private static final int ITERATIONMAX = 50000000;
247 +
248 +
249 + public RandomInstaller(Optional<JsonNode> runParams) {
250 + /*
251 + Check if we have params and honour them. Otherwise
252 + set defaults to processing only local stuff and
253 + all local hosts.
254 + */
255 + if (runParams.isPresent()) {
256 + JsonNode node = runParams.get();
257 + isLocal = node.get("local").asBoolean();
258 + hosts = node.get("hosts") == null ? Sets.newHashSet(hostService.getHosts()) :
259 + constructHostIds(node.get("hosts").elements());
260 + } else {
261 + isLocal = true;
262 + hosts = Sets.newHashSet(hostService.getHosts());
263 + }
264 +
265 + //construct list of intents.
266 + installed = Sets.newHashSet();
267 + if (isLocal) {
268 + uninstalledOrWithdrawn = buildPairs(pruneHostsByMasterShip());
269 + } else {
270 + uninstalledOrWithdrawn = buildPairs(hosts);
271 + }
272 +
273 + }
274 +
275 + private Set<Host> constructHostIds(Iterator<JsonNode> elements) {
276 + Set<Host> hostIds = Sets.newHashSet();
277 + JsonNode n;
278 + while (elements.hasNext()) {
279 + n = elements.next();
280 + hostIds.add(hostService.getHost(HostId.hostId(n.textValue())));
281 + }
282 + return hostIds;
283 + }
284 +
285 + @Override
286 + public void run() {
287 + if (!installWorker.isShutdown()) {
288 + randomize();
289 + latch = new CountDownLatch(1);
290 + try {
291 + trackIntents();
292 + } catch (InterruptedException e) {
293 + shutdown();
294 + }
295 + }
296 +
297 + }
298 +
299 +
300 + /**
301 + * Check whether the previously submitted batch is in progress
302 + * and if yes submit the next one. If things hang, wait for at
303 + * most 5 seconds and bail.
304 + * @throws InterruptedException if the thread go interupted
305 + */
306 + private void trackIntents() throws InterruptedException {
307 + //FIXME
308 + // TODO generate keys for each set of intents to allow manager to throttle
309 + // TODO may also look into the store to see how many operations are pending
310 +
311 + //if everything is good proceed.
312 + if (!installWorker.isShutdown()) {
313 + installWorker.execute(this);
314 + }
315 +
316 + }
317 +
318 + public void shutdown() {
319 + log.warn("Shutting down random installer!");
320 + cleanUp();
321 + }
322 +
323 +
324 + /**
325 + * Shuffle the uninstalled and installed list (separately) and select
326 + * a random number of them and install or uninstall them respectively.
327 + */
328 + private void randomize() {
329 + List<HostPair> hostList = new LinkedList<>(uninstalledOrWithdrawn);
330 + Collections.shuffle(hostList);
331 + List<HostPair> toInstall = hostList.subList(0,
332 + random.nextInt(hostList.size() - 1));
333 + List<HostPair> toRemove;
334 + if (!installed.isEmpty()) {
335 + hostList = new LinkedList<>(installed);
336 + Collections.shuffle(hostList);
337 + toRemove = hostList.subList(0,
338 + random.nextInt(hostList.size() - 1));
339 + uninstallIntents(toRemove);
340 + }
341 + installIntents(toInstall);
342 +
343 + }
344 +
345 + private void installIntents(List<HostPair> toInstall) {
346 + for (HostPair pair : toInstall) {
347 + installed.add(pair);
348 + uninstalledOrWithdrawn.remove(pair);
349 + intentService.submit(pair.h2hIntent());
350 + }
351 + }
352 +
353 + private void uninstallIntents(Collection<HostPair> toRemove) {
354 + for (HostPair pair : toRemove) {
355 + installed.remove(pair);
356 + uninstalledOrWithdrawn.add(pair);
357 + intentService.withdraw(pair.h2hIntent());
358 + }
359 + }
360 +
361 + /**
362 + * Take everything and remove it all.
363 + */
364 + private void cleanUp() {
365 + List<HostPair> allPairs = Lists.newArrayList(installed);
366 + allPairs.addAll(uninstalledOrWithdrawn);
367 + for (HostPair pair : allPairs) {
368 + intentService.withdraw(pair.h2hIntent());
369 + }
370 + }
371 +
372 +
373 + private Set<HostPair> buildPairs(Set<Host> hosts) {
374 + Set<HostPair> pairs = Sets.newHashSet();
375 + Iterator<Host> it = Sets.newHashSet(hosts).iterator();
376 + while (it.hasNext()) {
377 + Host src = it.next();
378 + it.remove();
379 + for (Host dst : hosts) {
380 + pairs.add(new HostPair(src, dst));
381 + }
382 + }
383 + return pairs;
384 + }
385 +
386 + private Set<Host> pruneHostsByMasterShip() {
387 + return FluentIterable.from(hosts)
388 + .filter(hasLocalMaster())
389 + .toSet();
390 +
391 + }
392 +
393 + private Predicate<? super Host> hasLocalMaster() {
394 + return new Predicate<Host>() {
395 + @Override
396 + public boolean apply(Host host) {
397 + return mastershipService.getLocalRole(
398 + host.location().deviceId()).equals(MastershipRole.MASTER);
399 + }
400 + };
401 + }
402 +
403 +
404 + /**
405 + * Simple class representing a pair of hosts and precomputes the associated
406 + * h2h intent.
407 + */
408 + private class HostPair {
409 +
410 + private final Host src;
411 + private final Host dst;
412 +
413 + private final TrafficSelector selector = DefaultTrafficSelector.emptySelector();
414 + private final TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
415 + private final List<Constraint> constraint = Lists.newArrayList();
416 + private final HostToHostIntent intent;
417 +
418 + public HostPair(Host src, Host dst) {
419 + this.src = src;
420 + this.dst = dst;
421 + this.intent = HostToHostIntent.builder()
422 + .appId(appId)
423 + .one(src.id())
424 + .two(dst.id())
425 + .selector(selector)
426 + .treatment(treatment)
427 + .constraints(constraint)
428 + .build();
429 + }
430 +
431 + public HostToHostIntent h2hIntent() {
432 + return intent;
433 + }
434 +
435 + @Override
436 + public boolean equals(Object o) {
437 + if (this == o) {
438 + return true;
439 + }
440 + if (o == null || getClass() != o.getClass()) {
441 + return false;
442 + }
443 +
444 + HostPair hostPair = (HostPair) o;
445 +
446 + return Objects.equals(src, hostPair.src) &&
447 + Objects.equals(dst, hostPair.dst);
448 +
449 + }
450 +
451 + @Override
452 + public int hashCode() {
453 + return Objects.hash(src, dst);
454 + }
455 +
456 +
457 + }
458 +
459 + }
460 +
461 + /**
462 + * Remove anything that is running and clear it all out.
463 + */
464 + private class UnInstaller implements Runnable {
465 + @Override
466 + public void run() {
467 + if (!existingIntents.isEmpty()) {
468 + clearExistingIntents();
469 + }
470 +
471 + if (installWorker != null && !installWorker.isShutdown()) {
472 + shutdownAndAwaitTermination(installWorker);
473 + randomInstaller.shutdown();
474 + }
475 + }
476 +
477 + private void clearExistingIntents() {
478 + for (Intent i : existingIntents) {
479 + intentService.withdraw(i);
480 + }
481 + existingIntents.clear();
482 + }
483 + }
484 +
485 + /**
486 + * Shutdown a pool cleanly if possible.
487 + *
488 + * @param pool an executorService
489 + */
490 + private void shutdownAndAwaitTermination(ExecutorService pool) {
491 + pool.shutdown(); // Disable new tasks from being submitted
492 + try {
493 + // Wait a while for existing tasks to terminate
494 + if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
495 + pool.shutdownNow(); // Cancel currently executing tasks
496 + // Wait a while for tasks to respond to being cancelled
497 + if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
498 + log.error("Pool did not terminate");
499 + }
500 + }
501 + } catch (Exception ie) {
502 + // (Re-)Cancel if current thread also interrupted
503 + pool.shutdownNow();
504 + // Preserve interrupt status
505 + Thread.currentThread().interrupt();
506 + }
507 + }
508 +
509 + private class FlowTest implements Callable<JsonNode> {
510 + private final int flowPerDevice;
511 + private final int neighbours;
512 + private final boolean remove;
513 + private FlowRuleOperations.Builder adds;
514 + private FlowRuleOperations.Builder removes;
515 +
516 + public FlowTest(int flowsPerDevice, int neighbours, boolean remove) {
517 + this.flowPerDevice = flowsPerDevice;
518 + this.neighbours = neighbours;
519 + this.remove = remove;
520 + prepareInstallation();
521 + }
522 +
523 + private void prepareInstallation() {
524 + Set<ControllerNode> instances = Sets.newHashSet(clusterService.getNodes());
525 + instances.remove(clusterService.getLocalNode());
526 + Set<NodeId> acceptableNodes = Sets.newHashSet();
527 + if (neighbours >= instances.size()) {
528 + instances.forEach(instance -> acceptableNodes.add(instance.id()));
529 + } else {
530 + Iterator<ControllerNode> nodes = instances.iterator();
531 + for (int i = neighbours; i > 0; i--) {
532 + acceptableNodes.add(nodes.next().id());
533 + }
534 + }
535 + acceptableNodes.add(clusterService.getLocalNode().id());
536 +
537 + Set<Device> devices = Sets.newHashSet();
538 + for (Device dev : deviceService.getDevices()) {
539 + if (acceptableNodes.contains(
540 + mastershipService.getMasterFor(dev.id()))) {
541 + devices.add(dev);
542 + }
543 + }
544 +
545 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
546 + .setOutput(PortNumber.portNumber(RandomUtils.nextInt())).build();
547 + TrafficSelector.Builder sbuilder;
548 + FlowRuleOperations.Builder rules = FlowRuleOperations.builder();
549 + FlowRuleOperations.Builder remove = FlowRuleOperations.builder();
550 +
551 + for (Device d : devices) {
552 + for (int i = 0; i < this.flowPerDevice; i++) {
553 + sbuilder = DefaultTrafficSelector.builder();
554 +
555 + sbuilder.matchEthSrc(MacAddress.valueOf(RandomUtils.nextInt() * i))
556 + .matchEthDst(MacAddress.valueOf((Integer.MAX_VALUE - i) * RandomUtils.nextInt()));
557 +
558 +
559 + int randomPriority = RandomUtils.nextInt();
560 + DefaultFlowRule f = new DefaultFlowRule(d.id(), sbuilder.build(), treatment,
561 + randomPriority, appId, 10, false);
562 + rules.add(f);
563 + remove.remove(f);
564 +
565 + }
566 + }
567 +
568 + this.adds = rules;
569 + this.removes = remove;
570 + }
571 +
572 + @Override
573 + public JsonNode call() throws Exception {
574 + ObjectNode node = mapper.createObjectNode();
575 + CountDownLatch latch = new CountDownLatch(1);
576 + flowService.apply(adds.build(new FlowRuleOperationsContext() {
577 +
578 + private final Stopwatch timer = Stopwatch.createStarted();
579 +
580 + @Override
581 + public void onSuccess(FlowRuleOperations ops) {
582 +
583 + long elapsed = timer.elapsed(TimeUnit.MILLISECONDS);
584 + node.put("elapsed", elapsed);
585 +
586 +
587 + latch.countDown();
588 + }
589 + }));
590 +
591 + latch.await(10, TimeUnit.SECONDS);
592 + if (this.remove) {
593 + flowService.apply(removes.build());
594 + }
595 + return node;
596 + }
597 + }
598 +}
599 +
600 +
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.demo;
17 +
18 +import com.fasterxml.jackson.databind.JsonNode;
19 +import com.fasterxml.jackson.databind.ObjectMapper;
20 +import org.onlab.rest.BaseResource;
21 +
22 +import javax.ws.rs.Consumes;
23 +import javax.ws.rs.GET;
24 +import javax.ws.rs.POST;
25 +import javax.ws.rs.Path;
26 +import javax.ws.rs.Produces;
27 +import javax.ws.rs.core.MediaType;
28 +import javax.ws.rs.core.Response;
29 +import java.io.IOException;
30 +import java.io.InputStream;
31 +import java.util.Optional;
32 +
33 +/**
34 + * Rest API for demos.
35 + */
36 +@Path("intents")
37 +public class DemoResource extends BaseResource {
38 +
39 +
40 +
41 + @POST
42 + @Path("flowTest")
43 + @Consumes(MediaType.APPLICATION_JSON)
44 + @Produces(MediaType.APPLICATION_JSON)
45 + public Response flowTest(InputStream input) throws IOException {
46 + ObjectMapper mapper = new ObjectMapper();
47 + JsonNode cfg = mapper.readTree(input);
48 + DemoAPI demo = get(DemoAPI.class);
49 + return Response.ok(demo.flowTest(Optional.ofNullable(cfg)).toString()).build();
50 + }
51 +
52 + @POST
53 + @Path("setup")
54 + @Consumes(MediaType.APPLICATION_JSON)
55 + @Produces(MediaType.APPLICATION_JSON)
56 + public Response setup(InputStream input) throws IOException {
57 + ObjectMapper mapper = new ObjectMapper();
58 + JsonNode cfg = mapper.readTree(input);
59 + if (!cfg.has("type")) {
60 + return Response.status(Response.Status.BAD_REQUEST)
61 + .entity("Expected type field containing either mesh or random.").build();
62 + }
63 +
64 +
65 + DemoAPI.InstallType type = DemoAPI.InstallType.valueOf(
66 + cfg.get("type").asText().toUpperCase());
67 + DemoAPI demo = get(DemoAPI.class);
68 + demo.setup(type, Optional.ofNullable(cfg.get("runParams")));
69 +
70 + return Response.ok(mapper.createObjectNode().toString()).build();
71 + }
72 +
73 + @GET
74 + @Path("teardown")
75 + @Produces(MediaType.APPLICATION_JSON)
76 + public Response tearDown() throws IOException {
77 + ObjectMapper mapper = new ObjectMapper();
78 + DemoAPI demo = get(DemoAPI.class);
79 + demo.tearDown();
80 + return Response.ok(mapper.createObjectNode().toString()).build();
81 + }
82 +
83 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/**
18 + * Demo applications live here.
19 + */
20 +package org.onosproject.demo;
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2014 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
18 + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
19 + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
20 + id="ONOS" version="2.5">
21 + <display-name>ONOS DEMO APP API v1.0</display-name>
22 +
23 + <servlet>
24 + <servlet-name>JAX-RS Service</servlet-name>
25 + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
26 + <init-param>
27 + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
28 + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
29 + </init-param>
30 + <init-param>
31 + <param-name>com.sun.jersey.config.property.classnames</param-name>
32 + <param-value>
33 + org.onosproject.demo.DemoResource
34 + </param-value>
35 + </init-param>
36 + <load-on-startup>1</load-on-startup>
37 + </servlet>
38 +
39 + <servlet-mapping>
40 + <servlet-name>JAX-RS Service</servlet-name>
41 + <url-pattern>/*</url-pattern>
42 + </servlet-mapping>
43 +
44 +</web-app>
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
34 <modules> 34 <modules>
35 <module>election</module> 35 <module>election</module>
36 <module>intent-perf</module> 36 <module>intent-perf</module>
37 + <module>demo</module>
37 </modules> 38 </modules>
38 39
39 </project> 40 </project>
......
...@@ -241,6 +241,13 @@ ...@@ -241,6 +241,13 @@
241 <bundle>mvn:org.onosproject/onos-app-election/@ONOS-VERSION</bundle> 241 <bundle>mvn:org.onosproject/onos-app-election/@ONOS-VERSION</bundle>
242 </feature> 242 </feature>
243 243
244 + <feature name="onos-app-demo" version="@FEATURE-VERSION"
245 + description="ONOS demo applications">
246 + <feature>onos-api</feature>
247 + <bundle>mvn:org.onosproject/onlab-misc/@ONOS-VERSION</bundle>
248 + <bundle>mvn:org.onosproject/onos-app-demo/@ONOS-VERSION</bundle>
249 + </feature>
250 +
244 251
245 <!-- ONOS sample app features: to be moved to a different repo --> 252 <!-- ONOS sample app features: to be moved to a different repo -->
246 253
...@@ -258,13 +265,6 @@ ...@@ -258,13 +265,6 @@
258 <bundle>mvn:org.onosproject/onos-app-ifwd/@ONOS-VERSION</bundle> 265 <bundle>mvn:org.onosproject/onos-app-ifwd/@ONOS-VERSION</bundle>
259 </feature> 266 </feature>
260 267
261 - <feature name="onos-app-demo" version="@FEATURE-VERSION"
262 - description="ONOS demo applications">
263 - <feature>onos-api</feature>
264 - <bundle>mvn:org.onosproject/onlab-misc/@ONOS-VERSION</bundle>
265 - <bundle>mvn:org.onosproject/onos-app-demo/@ONOS-VERSION</bundle>
266 - </feature>
267 -
268 <feature name="onos-app-database-perf" version="@FEATURE-VERSION" 268 <feature name="onos-app-database-perf" version="@FEATURE-VERSION"
269 description="ONOS partitioned database perf application"> 269 description="ONOS partitioned database perf application">
270 <feature>onos-api</feature> 270 <feature>onos-api</feature>
......