Thomas Vachuska
Committed by Gerrit Code Review

ONOS-1315 Adding configurability to intent performance test app.

Change-Id: I2782bdc0f78cc49aa60af1fa03eae91a2fd6bce0
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
42 <artifactId>onos-cli</artifactId> 42 <artifactId>onos-cli</artifactId>
43 <version>${project.version}</version> 43 <version>${project.version}</version>
44 </dependency> 44 </dependency>
45 + <dependency>
46 + <groupId>org.osgi</groupId>
47 + <artifactId>org.osgi.compendium</artifactId>
48 + </dependency>
45 </dependencies> 49 </dependencies>
46 50
47 <build> 51 <build>
......
...@@ -50,7 +50,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -50,7 +50,7 @@ import static org.slf4j.LoggerFactory.getLogger;
50 @Service(value = IntentPerfCollector.class) 50 @Service(value = IntentPerfCollector.class)
51 public class IntentPerfCollector { 51 public class IntentPerfCollector {
52 52
53 - private static final long SAMPLE_WINDOW = 5_000; 53 + private static final long SAMPLE_TIME_WINDOW_MS = 5_000;
54 private final Logger log = getLogger(getClass()); 54 private final Logger log = getLogger(getClass());
55 55
56 private static final int MAX_SAMPLES = 1_000; 56 private static final int MAX_SAMPLES = 1_000;
...@@ -82,9 +82,9 @@ public class IntentPerfCollector { ...@@ -82,9 +82,9 @@ public class IntentPerfCollector {
82 82
83 @Activate 83 @Activate
84 public void activate() { 84 public void activate() {
85 - this.nodeId = clusterService.getLocalNode().id(); 85 + nodeId = clusterService.getLocalNode().id();
86 - this.newestTime = 0;
87 86
87 + // TODO: replace with shared executor
88 messageHandlingExecutor = Executors.newSingleThreadExecutor( 88 messageHandlingExecutor = Executors.newSingleThreadExecutor(
89 groupedThreads("onos/perf", "message-handler")); 89 groupedThreads("onos/perf", "message-handler"));
90 90
...@@ -98,9 +98,8 @@ public class IntentPerfCollector { ...@@ -98,9 +98,8 @@ public class IntentPerfCollector {
98 for (int i = 0; i < nodes.length; i++) { 98 for (int i = 0; i < nodes.length; i++) {
99 nodeToIndex.put(nodes[i].id(), i); 99 nodeToIndex.put(nodes[i].id(), i);
100 } 100 }
101 - overall = new Sample(0, nodes.length);
102 - current = new Sample(0, nodes.length);
103 101
102 + clearSamples();
104 log.info("Started"); 103 log.info("Started");
105 } 104 }
106 105
...@@ -112,19 +111,26 @@ public class IntentPerfCollector { ...@@ -112,19 +111,26 @@ public class IntentPerfCollector {
112 } 111 }
113 112
114 /** 113 /**
114 + * Clears all previously accumulated data.
115 + */
116 + public void clearSamples() {
117 + newestTime = 0;
118 + overall = new Sample(0, nodes.length);
119 + current = new Sample(0, nodes.length);
120 + samples.clear();
121 + }
122 +
123 +
124 + /**
115 * Records a sample point of data about intent operation rate. 125 * Records a sample point of data about intent operation rate.
116 * 126 *
117 * @param overallRate overall rate 127 * @param overallRate overall rate
118 * @param currentRate current rate 128 * @param currentRate current rate
119 */ 129 */
120 public void recordSample(double overallRate, double currentRate) { 130 public void recordSample(double overallRate, double currentRate) {
121 - try { 131 + long now = System.currentTimeMillis();
122 - long now = System.currentTimeMillis(); 132 + addSample(now, nodeId, overallRate, currentRate);
123 - addSample(now, nodeId, overallRate, currentRate); 133 + broadcastSample(now, nodeId, overallRate, currentRate);
124 - broadcastSample(now, nodeId, overallRate, currentRate);
125 - } catch (Exception e) {
126 - log.error("Boom!", e);
127 - }
128 } 134 }
129 135
130 /** 136 /**
...@@ -173,7 +179,7 @@ public class IntentPerfCollector { ...@@ -173,7 +179,7 @@ public class IntentPerfCollector {
173 } 179 }
174 180
175 private Sample createCurrentSampleIfNeeded(long time) { 181 private Sample createCurrentSampleIfNeeded(long time) {
176 - Sample oldSample = time - newestTime > SAMPLE_WINDOW || current.isComplete() ? current : null; 182 + Sample oldSample = time - newestTime > SAMPLE_TIME_WINDOW_MS || current.isComplete() ? current : null;
177 if (oldSample != null) { 183 if (oldSample != null) {
178 newestTime = time; 184 newestTime = time;
179 current = new Sample(time, nodes.length); 185 current = new Sample(time, nodes.length);
...@@ -227,9 +233,9 @@ public class IntentPerfCollector { ...@@ -227,9 +233,9 @@ public class IntentPerfCollector {
227 @Override 233 @Override
228 public void handle(ClusterMessage message) { 234 public void handle(ClusterMessage message) {
229 String[] fields = new String(message.payload()).split("\\|"); 235 String[] fields = new String(message.payload()).split("\\|");
230 - log.info("Received sample from {}: {}", message.sender(), fields); 236 + log.debug("Received sample from {}: {}", message.sender(), fields);
231 addSample(Long.parseLong(fields[0]), message.sender(), 237 addSample(Long.parseLong(fields[0]), message.sender(),
232 - Double.parseDouble(fields[1]), Double.parseDouble(fields[1])); 238 + Double.parseDouble(fields[1]), Double.parseDouble(fields[2]));
233 } 239 }
234 } 240 }
235 } 241 }
......
...@@ -24,8 +24,11 @@ import org.apache.commons.lang.math.RandomUtils; ...@@ -24,8 +24,11 @@ import org.apache.commons.lang.math.RandomUtils;
24 import org.apache.felix.scr.annotations.Activate; 24 import org.apache.felix.scr.annotations.Activate;
25 import org.apache.felix.scr.annotations.Component; 25 import org.apache.felix.scr.annotations.Component;
26 import org.apache.felix.scr.annotations.Deactivate; 26 import org.apache.felix.scr.annotations.Deactivate;
27 +import org.apache.felix.scr.annotations.Modified;
27 import org.apache.felix.scr.annotations.Property; 28 import org.apache.felix.scr.annotations.Property;
28 import org.apache.felix.scr.annotations.Reference; 29 import org.apache.felix.scr.annotations.Reference;
30 +import org.apache.felix.scr.annotations.ReferenceCardinality;
31 +import org.apache.felix.scr.annotations.Service;
29 import org.onlab.packet.MacAddress; 32 import org.onlab.packet.MacAddress;
30 import org.onlab.util.Counter; 33 import org.onlab.util.Counter;
31 import org.onosproject.cfg.ComponentConfigService; 34 import org.onosproject.cfg.ComponentConfigService;
...@@ -50,10 +53,16 @@ import org.onosproject.net.intent.IntentService; ...@@ -50,10 +53,16 @@ import org.onosproject.net.intent.IntentService;
50 import org.onosproject.net.intent.Key; 53 import org.onosproject.net.intent.Key;
51 import org.onosproject.net.intent.PartitionService; 54 import org.onosproject.net.intent.PartitionService;
52 import org.onosproject.net.intent.PointToPointIntent; 55 import org.onosproject.net.intent.PointToPointIntent;
56 +import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
57 +import org.onosproject.store.cluster.messaging.ClusterMessage;
58 +import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
59 +import org.onosproject.store.cluster.messaging.MessageSubject;
60 +import org.osgi.service.component.ComponentContext;
53 import org.slf4j.Logger; 61 import org.slf4j.Logger;
54 62
55 import java.util.ArrayList; 63 import java.util.ArrayList;
56 import java.util.Collections; 64 import java.util.Collections;
65 +import java.util.Dictionary;
57 import java.util.List; 66 import java.util.List;
58 import java.util.Map; 67 import java.util.Map;
59 import java.util.Set; 68 import java.util.Set;
...@@ -65,11 +74,11 @@ import java.util.concurrent.TimeUnit; ...@@ -65,11 +74,11 @@ import java.util.concurrent.TimeUnit;
65 import java.util.stream.Collectors; 74 import java.util.stream.Collectors;
66 75
67 import static com.google.common.base.Preconditions.checkState; 76 import static com.google.common.base.Preconditions.checkState;
77 +import static com.google.common.base.Strings.isNullOrEmpty;
68 import static java.lang.String.format; 78 import static java.lang.String.format;
69 import static java.lang.System.currentTimeMillis; 79 import static java.lang.System.currentTimeMillis;
70 import static org.apache.felix.scr.annotations.ReferenceCardinality.MANDATORY_UNARY; 80 import static org.apache.felix.scr.annotations.ReferenceCardinality.MANDATORY_UNARY;
71 -import static org.onlab.util.Tools.delay; 81 +import static org.onlab.util.Tools.*;
72 -import static org.onlab.util.Tools.groupedThreads;
73 import static org.onosproject.net.intent.IntentEvent.Type.*; 82 import static org.onosproject.net.intent.IntentEvent.Type.*;
74 import static org.slf4j.LoggerFactory.getLogger; 83 import static org.slf4j.LoggerFactory.getLogger;
75 84
...@@ -77,20 +86,25 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -77,20 +86,25 @@ import static org.slf4j.LoggerFactory.getLogger;
77 * Application to test sustained intent throughput. 86 * Application to test sustained intent throughput.
78 */ 87 */
79 @Component(immediate = true) 88 @Component(immediate = true)
89 +@Service(value = IntentPerfInstaller.class)
80 public class IntentPerfInstaller { 90 public class IntentPerfInstaller {
81 91
82 private final Logger log = getLogger(getClass()); 92 private final Logger log = getLogger(getClass());
83 93
84 private static final int DEFAULT_NUM_WORKERS = 1; 94 private static final int DEFAULT_NUM_WORKERS = 1;
85 95
86 - private static final int DEFAULT_NUM_KEYS = 40_000; 96 + private static final int DEFAULT_NUM_KEYS = 40000;
87 - private static final int DEFAULT_GOAL_CYCLE_PERIOD = 1_000; //ms 97 + private static final int DEFAULT_GOAL_CYCLE_PERIOD = 1000; //ms
88 98
89 private static final int DEFAULT_NUM_NEIGHBORS = 0; 99 private static final int DEFAULT_NUM_NEIGHBORS = 0;
90 100
91 private static final int START_DELAY = 5_000; // ms 101 private static final int START_DELAY = 5_000; // ms
92 private static final int REPORT_PERIOD = 5_000; //ms 102 private static final int REPORT_PERIOD = 5_000; //ms
93 103
104 + private static final String START = "start";
105 + private static final String STOP = "stop";
106 + private static final MessageSubject CONTROL = new MessageSubject("intent-perf-ctl");
107 +
94 //FIXME add path length 108 //FIXME add path length
95 109
96 @Property(name = "numKeys", intValue = DEFAULT_NUM_KEYS, 110 @Property(name = "numKeys", intValue = DEFAULT_NUM_KEYS,
...@@ -134,6 +148,11 @@ public class IntentPerfInstaller { ...@@ -134,6 +148,11 @@ public class IntentPerfInstaller {
134 @Reference(cardinality = MANDATORY_UNARY) 148 @Reference(cardinality = MANDATORY_UNARY)
135 protected IntentPerfCollector sampleCollector; 149 protected IntentPerfCollector sampleCollector;
136 150
151 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
152 + protected ClusterCommunicationService communicationService;
153 +
154 + private ExecutorService messageHandlingExecutor;
155 +
137 private ExecutorService workers; 156 private ExecutorService workers;
138 private ApplicationId appId; 157 private ApplicationId appId;
139 private Listener listener; 158 private Listener listener;
...@@ -145,86 +164,138 @@ public class IntentPerfInstaller { ...@@ -145,86 +164,138 @@ public class IntentPerfInstaller {
145 private int lastKey = 0; 164 private int lastKey = 0;
146 165
147 private IntentPerfUi perfUi; 166 private IntentPerfUi perfUi;
167 + private NodeId nodeId;
168 + private TimerTask reporterTask;
148 169
149 @Activate 170 @Activate
150 - public void activate() { 171 + public void activate(ComponentContext context) {
151 -// configService.registerProperties(getClass()); 172 + configService.registerProperties(getClass());
152 173
153 - String nodeId = clusterService.getLocalNode().ip().toString(); 174 + nodeId = clusterService.getLocalNode().id();
154 - appId = coreService.registerApplication("org.onosproject.intentperf." + nodeId); 175 + appId = coreService.registerApplication("org.onosproject.intentperf." + nodeId.toString());
155 176
177 + // TODO: replace with shared timer
156 reportTimer = new Timer("onos-intent-perf-reporter"); 178 reportTimer = new Timer("onos-intent-perf-reporter");
157 workers = Executors.newFixedThreadPool(DEFAULT_NUM_WORKERS, groupedThreads("onos/intent-perf", "worker-%d")); 179 workers = Executors.newFixedThreadPool(DEFAULT_NUM_WORKERS, groupedThreads("onos/intent-perf", "worker-%d"));
158 180
159 -
160 // disable flow backups for testing 181 // disable flow backups for testing
161 log.info("flow props: {}", 182 log.info("flow props: {}",
162 configService.getProperties("org.onosproject.store.flow.impl.DistributedFlowRuleStore")); 183 configService.getProperties("org.onosproject.store.flow.impl.DistributedFlowRuleStore"));
163 configService.setProperty("org.onosproject.store.flow.impl.DistributedFlowRuleStore", 184 configService.setProperty("org.onosproject.store.flow.impl.DistributedFlowRuleStore",
164 "backupEnabled", "false"); 185 "backupEnabled", "false");
165 186
166 - // Schedule delayed start 187 + // TODO: replace with shared executor
167 - reportTimer.schedule(new TimerTask() { 188 + messageHandlingExecutor = Executors.newSingleThreadExecutor(
168 - @Override 189 + groupedThreads("onos/perf", "command-handler"));
169 - public void run() { 190 +
170 - start(); 191 + communicationService.addSubscriber(CONTROL, new InternalControl(),
171 - } 192 + messageHandlingExecutor);
172 - }, START_DELAY); 193 +
194 + listener = new Listener();
195 + intentService.addListener(listener);
196 +
197 + // TODO: investigate why this seems to be necessary for configs to get picked up on initial activation
198 + modify(context);
173 } 199 }
174 200
175 @Deactivate 201 @Deactivate
176 public void deactivate() { 202 public void deactivate() {
177 -// configService.unregisterProperties(getClass(), false); 203 + stopTestRun();
178 - stop(); 204 +
205 + configService.unregisterProperties(getClass(), false);
206 + messageHandlingExecutor.shutdown();
207 + communicationService.removeSubscriber(CONTROL);
208 +
209 + if (listener != null) {
210 + reportTimer.cancel();
211 + intentService.removeListener(listener);
212 + listener = null;
213 + reportTimer = null;
214 + }
179 } 215 }
180 216
181 - //FIXME add modified 217 + @Modified
218 + public void modify(ComponentContext context) {
219 + if (context == null) {
220 + logConfig("Reconfigured");
221 + return;
222 + }
223 +
224 + Dictionary<?, ?> properties = context.getProperties();
225 + int newNumKeys, newCyclePeriod, newNumNeighbors;
226 + try {
227 + String s = get(properties, "numKeys");
228 + newNumKeys = isNullOrEmpty(s) ? numKeys : Integer.parseInt(s.trim());
229 +
230 + s = get(properties, "cyclePeriod");
231 + newCyclePeriod = isNullOrEmpty(s) ? cyclePeriod : Integer.parseInt(s.trim());
232 +
233 + s = get(properties, "numNeighbors");
234 + newNumNeighbors = isNullOrEmpty(s) ? numNeighbors : Integer.parseInt(s.trim());
235 +
236 + } catch (NumberFormatException | ClassCastException e) {
237 + log.warn("Malformed configuration detected; using defaults", e);
238 + newNumKeys = DEFAULT_NUM_KEYS;
239 + newCyclePeriod = DEFAULT_GOAL_CYCLE_PERIOD;
240 + newNumNeighbors = DEFAULT_NUM_NEIGHBORS;
241 + }
242 +
243 + if (newNumKeys != numKeys || newCyclePeriod != cyclePeriod || newNumNeighbors != numNeighbors) {
244 + numKeys = newNumKeys;
245 + cyclePeriod = newCyclePeriod;
246 + numNeighbors = newNumNeighbors;
247 + logConfig("Reconfigured");
248 + }
249 + }
250 +
251 + public void start() {
252 + communicationService.broadcast(new ClusterMessage(nodeId, CONTROL, START.getBytes()));
253 + startTestRun();
254 + }
255 +
256 + public void stop() {
257 + communicationService.broadcast(new ClusterMessage(nodeId, CONTROL, STOP.getBytes()));
258 + stopTestRun();
259 + }
182 260
183 private void logConfig(String prefix) { 261 private void logConfig(String prefix) {
184 log.info("{} with appId {}; numKeys = {}; cyclePeriod = {} ms; numNeighbors={}", 262 log.info("{} with appId {}; numKeys = {}; cyclePeriod = {} ms; numNeighbors={}",
185 prefix, appId.id(), numKeys, cyclePeriod, numNeighbors); 263 prefix, appId.id(), numKeys, cyclePeriod, numNeighbors);
186 } 264 }
187 265
188 - public void start() { 266 + private void startTestRun() {
267 + sampleCollector.clearSamples();
268 +
189 // adjust numNeighbors and generate list of neighbors 269 // adjust numNeighbors and generate list of neighbors
190 numNeighbors = Math.min(clusterService.getNodes().size() - 1, numNeighbors); 270 numNeighbors = Math.min(clusterService.getNodes().size() - 1, numNeighbors);
191 271
192 - // perhaps we want to prime before listening...
193 - // we will need to discard the first few results for priming and warmup
194 - listener = new Listener();
195 - intentService.addListener(listener);
196 -
197 // Schedule reporter task on report period boundary 272 // Schedule reporter task on report period boundary
198 - reportTimer.scheduleAtFixedRate(new TimerTask() { 273 + reporterTask = new ReporterTask();
199 - @Override 274 + reportTimer.scheduleAtFixedRate(reporterTask,
200 - public void run() { 275 + REPORT_PERIOD - currentTimeMillis() % REPORT_PERIOD,
201 - //adjustRates(); // FIXME we currently adjust rates in the cycle thread 276 + REPORT_PERIOD);
202 - listener.report();
203 - }
204 - }, REPORT_PERIOD - currentTimeMillis() % REPORT_PERIOD, REPORT_PERIOD);
205 277
206 // Submit workers 278 // Submit workers
207 stopped = false; 279 stopped = false;
208 for (int i = 0; i < DEFAULT_NUM_WORKERS; i++) { 280 for (int i = 0; i < DEFAULT_NUM_WORKERS; i++) {
209 workers.submit(new Submitter(createIntents(numKeys, /*FIXME*/ 2, lastKey))); 281 workers.submit(new Submitter(createIntents(numKeys, /*FIXME*/ 2, lastKey)));
210 } 282 }
211 - logConfig("Started"); 283 + log.info("Started test run");
212 } 284 }
213 285
214 - public void stop() { 286 + private void stopTestRun() {
215 stopped = true; 287 stopped = true;
216 - if (listener != null) { 288 + if (reporterTask != null) {
217 - reportTimer.cancel(); 289 + reporterTask.cancel();
218 - intentService.removeListener(listener); 290 + reporterTask = null;
219 - listener = null;
220 - reportTimer = null;
221 } 291 }
292 +
222 try { 293 try {
223 - workers.awaitTermination(5, TimeUnit.SECONDS); 294 + workers.awaitTermination(5 * cyclePeriod, TimeUnit.MILLISECONDS);
224 } catch (InterruptedException e) { 295 } catch (InterruptedException e) {
225 log.warn("Failed to stop worker", e); 296 log.warn("Failed to stop worker", e);
226 } 297 }
227 - log.info("Stopped"); 298 + log.info("Stopped test run");
228 } 299 }
229 300
230 private List<NodeId> getNeighbors() { 301 private List<NodeId> getNeighbors() {
...@@ -491,4 +562,25 @@ public class IntentPerfInstaller { ...@@ -491,4 +562,25 @@ public class IntentPerfInstaller {
491 } 562 }
492 } 563 }
493 564
565 + private class InternalControl implements ClusterMessageHandler {
566 + @Override
567 + public void handle(ClusterMessage message) {
568 + String cmd = new String(message.payload());
569 + log.info("Received command {}", cmd);
570 + if (cmd.equals(START)) {
571 + startTestRun();
572 + } else {
573 + stopTestRun();
574 + }
575 + }
576 + }
577 +
578 + private class ReporterTask extends TimerTask {
579 + @Override
580 + public void run() {
581 + //adjustRates(); // FIXME we currently adjust rates in the cycle thread
582 + listener.report();
583 + }
584 + }
585 +
494 } 586 }
......
...@@ -29,7 +29,7 @@ import java.util.List; ...@@ -29,7 +29,7 @@ import java.util.List;
29 */ 29 */
30 @Command(scope = "onos", name = "intent-perf", 30 @Command(scope = "onos", name = "intent-perf",
31 description = "Displays accumulated performance metrics") 31 description = "Displays accumulated performance metrics")
32 -public class IntentPerfCommand extends AbstractShellCommand { 32 +public class IntentPerfListCommand extends AbstractShellCommand {
33 33
34 @Option(name = "-s", aliases = "--summary", description = "Output just summary", 34 @Option(name = "-s", aliases = "--summary", description = "Output just summary",
35 required = false, multiValued = false) 35 required = false, multiValued = false)
...@@ -49,11 +49,16 @@ public class IntentPerfCommand extends AbstractShellCommand { ...@@ -49,11 +49,16 @@ public class IntentPerfCommand extends AbstractShellCommand {
49 List<String> headers = collector.getSampleHeaders(); 49 List<String> headers = collector.getSampleHeaders();
50 Sample overall = collector.getOverall(); 50 Sample overall = collector.getOverall();
51 double total = 0; 51 double total = 0;
52 + print("%12s: %14s", "Node ID", "Overall Rate");
52 for (int i = 0; i < overall.data.length; i++) { 53 for (int i = 0; i < overall.data.length; i++) {
53 - print("%12s: %12.2f", headers.get(i), overall.data[i]); 54 + if (overall.data[i] >= 0) {
54 - total += overall.data[i]; 55 + print("%12s: %14.2f", headers.get(i), overall.data[i]);
56 + total += overall.data[i];
57 + } else {
58 + print("%12s: %14s", headers.get(i), " ");
59 + }
55 } 60 }
56 - print("%12s: %12.2f", "total", total); 61 + print("%12s: %14.2f", "total", total);
57 } 62 }
58 63
59 private void printSamples() { 64 private void printSamples() {
......
1 +/*
2 + * Copyright 2015 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.intentperf;
17 +
18 +import org.apache.karaf.shell.commands.Command;
19 +import org.onosproject.cli.AbstractShellCommand;
20 +
21 +/**
22 + * Starts intent performance test run.
23 + */
24 +@Command(scope = "onos", name = "intent-perf-start",
25 + description = "Starts intent performance test run")
26 +public class IntentPerfStartCommand extends AbstractShellCommand {
27 +
28 + @Override
29 + protected void execute() {
30 + get(IntentPerfInstaller.class).start();
31 + }
32 +
33 +}
1 +/*
2 + * Copyright 2015 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.intentperf;
17 +
18 +import org.apache.karaf.shell.commands.Command;
19 +import org.onosproject.cli.AbstractShellCommand;
20 +
21 +/**
22 + * Stops intent performance test run.
23 + */
24 +@Command(scope = "onos", name = "intent-perf-stop",
25 + description = "Stops intent performance test run")
26 +public class IntentPerfStopCommand extends AbstractShellCommand {
27 +
28 + @Override
29 + protected void execute() {
30 + get(IntentPerfInstaller.class).stop();
31 + }
32 +
33 +}
...@@ -16,7 +16,13 @@ ...@@ -16,7 +16,13 @@
16 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> 16 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
17 <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> 17 <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
18 <command> 18 <command>
19 - <action class="org.onosproject.intentperf.IntentPerfCommand"/> 19 + <action class="org.onosproject.intentperf.IntentPerfListCommand"/>
20 + </command>
21 + <command>
22 + <action class="org.onosproject.intentperf.IntentPerfStartCommand"/>
23 + </command>
24 + <command>
25 + <action class="org.onosproject.intentperf.IntentPerfStopCommand"/>
20 </command> 26 </command>
21 </command-bundle> 27 </command-bundle>
22 </blueprint> 28 </blueprint>
......