Thomas Vachuska
Committed by Gerrit Code Review

Prototyping GUI & CLI for the intent performance test fixture.

Change-Id: I1f33872e62b55d168ccd8f2904472e41ecba4cc8
...@@ -31,6 +31,19 @@ ...@@ -31,6 +31,19 @@
31 31
32 <description>ONOS intent perf app bundle</description> 32 <description>ONOS intent perf app bundle</description>
33 33
34 + <dependencies>
35 + <dependency>
36 + <groupId>org.apache.karaf.shell</groupId>
37 + <artifactId>org.apache.karaf.shell.console</artifactId>
38 + </dependency>
39 +
40 + <dependency>
41 + <groupId>org.onosproject</groupId>
42 + <artifactId>onos-cli</artifactId>
43 + <version>${project.version}</version>
44 + </dependency>
45 + </dependencies>
46 +
34 <build> 47 <build>
35 <plugins> 48 <plugins>
36 <plugin> 49 <plugin>
......
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 com.google.common.collect.ImmutableList;
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Reference;
23 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 +import org.apache.felix.scr.annotations.Service;
25 +import org.onosproject.cluster.ClusterService;
26 +import org.onosproject.cluster.ControllerNode;
27 +import org.onosproject.cluster.NodeId;
28 +import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
29 +import org.onosproject.store.cluster.messaging.ClusterMessage;
30 +import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
31 +import org.onosproject.store.cluster.messaging.MessageSubject;
32 +import org.slf4j.Logger;
33 +
34 +import java.util.ArrayList;
35 +import java.util.Arrays;
36 +import java.util.HashMap;
37 +import java.util.LinkedList;
38 +import java.util.List;
39 +import java.util.Map;
40 +import java.util.concurrent.ExecutorService;
41 +import java.util.concurrent.Executors;
42 +
43 +import static org.onlab.util.Tools.groupedThreads;
44 +import static org.slf4j.LoggerFactory.getLogger;
45 +
46 +/**
47 + * Collects and distributes performance samples.
48 + */
49 +@Component(immediate = true)
50 +@Service(value = IntentPerfCollector.class)
51 +public class IntentPerfCollector {
52 +
53 + private static final long SAMPLE_WINDOW = 5_000;
54 + private final Logger log = getLogger(getClass());
55 +
56 + private static final int MAX_SAMPLES = 1_000;
57 +
58 + private final List<Sample> samples = new LinkedList<>();
59 +
60 + private static final MessageSubject SAMPLE = new MessageSubject("intent-perf-sample");
61 +
62 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 + protected ClusterCommunicationService communicationService;
64 +
65 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 + protected ClusterService clusterService;
67 +
68 + @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
69 + protected IntentPerfUi ui;
70 +
71 + // Auxiliary structures used to accrue data for normalized time interval
72 + // across all nodes.
73 + private long newestTime;
74 + private Sample overall;
75 + private Sample current;
76 +
77 + private ControllerNode[] nodes;
78 + private Map<NodeId, Integer> nodeToIndex;
79 +
80 + private NodeId nodeId;
81 + private ExecutorService messageHandlingExecutor;
82 +
83 + @Activate
84 + public void activate() {
85 + this.nodeId = clusterService.getLocalNode().id();
86 + this.newestTime = 0;
87 +
88 + messageHandlingExecutor = Executors.newSingleThreadExecutor(
89 + groupedThreads("onos/perf", "message-handler"));
90 +
91 + communicationService.addSubscriber(SAMPLE, new InternalSampleCollector(),
92 + messageHandlingExecutor);
93 +
94 + nodes = clusterService.getNodes().toArray(new ControllerNode[]{});
95 + Arrays.sort(nodes, (a, b) -> a.id().toString().compareTo(b.id().toString()));
96 +
97 + nodeToIndex = new HashMap<>();
98 + for (int i = 0; i < nodes.length; i++) {
99 + nodeToIndex.put(nodes[i].id(), i);
100 + }
101 + overall = new Sample(0, nodes.length);
102 + current = new Sample(0, nodes.length);
103 +
104 + log.info("Started");
105 + }
106 +
107 + @Deactivate
108 + public void deactivate() {
109 + messageHandlingExecutor.shutdown();
110 + communicationService.removeSubscriber(SAMPLE);
111 + log.info("Stopped");
112 + }
113 +
114 + /**
115 + * Records a sample point of data about intent operation rate.
116 + *
117 + * @param overallRate overall rate
118 + * @param currentRate current rate
119 + */
120 + public void recordSample(double overallRate, double currentRate) {
121 + try {
122 + long now = System.currentTimeMillis();
123 + addSample(now, nodeId, overallRate, currentRate);
124 + broadcastSample(now, nodeId, overallRate, currentRate);
125 + } catch (Exception e) {
126 + log.error("Boom!", e);
127 + }
128 + }
129 +
130 + /**
131 + * Returns set of node ids as headers.
132 + *
133 + * @return node id headers
134 + */
135 + public List<String> getSampleHeaders() {
136 + List<String> headers = new ArrayList<>();
137 + for (ControllerNode node : nodes) {
138 + headers.add(node.id().toString());
139 + }
140 + return headers;
141 + }
142 +
143 + /**
144 + * Returns set of all accumulated samples normalized to the local set of
145 + * samples.
146 + *
147 + * @return accumulated samples
148 + */
149 + public synchronized List<Sample> getSamples() {
150 + return ImmutableList.copyOf(samples);
151 + }
152 +
153 + /**
154 + * Returns overall throughput performance for each of the cluster nodes.
155 + *
156 + * @return overall intent throughput
157 + */
158 + public synchronized Sample getOverall() {
159 + return overall;
160 + }
161 +
162 + // Records a new sample to our collection of samples
163 + private synchronized void addSample(long time, NodeId nodeId,
164 + double overallRate, double currentRate) {
165 + Sample fullSample = createCurrentSampleIfNeeded(time);
166 + setSampleData(current, nodeId, currentRate);
167 + setSampleData(overall, nodeId, overallRate);
168 + pruneSamplesIfNeeded();
169 +
170 + if (fullSample != null && ui != null) {
171 + ui.reportSample(fullSample);
172 + }
173 + }
174 +
175 + private Sample createCurrentSampleIfNeeded(long time) {
176 + Sample oldSample = time - newestTime > SAMPLE_WINDOW || current.isComplete() ? current : null;
177 + if (oldSample != null) {
178 + newestTime = time;
179 + current = new Sample(time, nodes.length);
180 + if (oldSample.time > 0) {
181 + samples.add(oldSample);
182 + }
183 + }
184 + return oldSample;
185 + }
186 +
187 + private void setSampleData(Sample sample, NodeId nodeId, double data) {
188 + Integer index = nodeToIndex.get(nodeId);
189 + if (index != null) {
190 + sample.data[index] = data;
191 + }
192 + }
193 +
194 + private void pruneSamplesIfNeeded() {
195 + if (samples.size() > MAX_SAMPLES) {
196 + samples.remove(0);
197 + }
198 + }
199 +
200 + // Performance data sample.
201 + static class Sample {
202 + final long time;
203 + final double[] data;
204 +
205 + public Sample(long time, int nodeCount) {
206 + this.time = time;
207 + this.data = new double[nodeCount];
208 + Arrays.fill(data, -1);
209 + }
210 +
211 + public boolean isComplete() {
212 + for (int i = 0; i < data.length; i++) {
213 + if (data[i] < 0) {
214 + return false;
215 + }
216 + }
217 + return true;
218 + }
219 + }
220 +
221 + private void broadcastSample(long time, NodeId nodeId, double overallRate, double currentRate) {
222 + String data = String.format("%d|%f|%f", time, overallRate, currentRate);
223 + communicationService.broadcast(new ClusterMessage(nodeId, SAMPLE, data.getBytes()));
224 + }
225 +
226 + private class InternalSampleCollector implements ClusterMessageHandler {
227 + @Override
228 + public void handle(ClusterMessage message) {
229 + String[] fields = new String(message.payload()).split("\\|");
230 + log.info("Received sample from {}: {}", message.sender(), fields);
231 + addSample(Long.parseLong(fields[0]), message.sender(),
232 + Double.parseDouble(fields[1]), Double.parseDouble(fields[1]));
233 + }
234 + }
235 +}
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.apache.karaf.shell.commands.Option;
20 +import org.onosproject.cli.AbstractShellCommand;
21 +import org.onosproject.intentperf.IntentPerfCollector.Sample;
22 +
23 +import java.text.SimpleDateFormat;
24 +import java.util.Date;
25 +import java.util.List;
26 +
27 +/**
28 + * Displays accumulated performance metrics.
29 + */
30 +@Command(scope = "onos", name = "intent-perf",
31 + description = "Displays accumulated performance metrics")
32 +public class IntentPerfCommand extends AbstractShellCommand {
33 +
34 + @Option(name = "-s", aliases = "--summary", description = "Output just summary",
35 + required = false, multiValued = false)
36 + private boolean summary = false;
37 +
38 + @Override
39 + protected void execute() {
40 + if (summary) {
41 + printSummary();
42 + } else {
43 + printSamples();
44 + }
45 + }
46 +
47 + private void printSummary() {
48 + IntentPerfCollector collector = get(IntentPerfCollector.class);
49 + List<String> headers = collector.getSampleHeaders();
50 + Sample overall = collector.getOverall();
51 + double total = 0;
52 + for (int i = 0; i < overall.data.length; i++) {
53 + print("%12s: %12.2f", headers.get(i), overall.data[i]);
54 + total += overall.data[i];
55 + }
56 + print("%12s: %12.2f", "total", total);
57 + }
58 +
59 + private void printSamples() {
60 + IntentPerfCollector collector = get(IntentPerfCollector.class);
61 + List<String> headers = collector.getSampleHeaders();
62 + List<Sample> samples = collector.getSamples();
63 +
64 + System.out.print(String.format("%10s ", "Time"));
65 + for (String header : headers) {
66 + System.out.print(String.format("%12s ", header));
67 + }
68 + System.out.println(String.format("%12s", "Total"));
69 +
70 + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
71 + for (Sample sample : samples) {
72 + double total = 0;
73 + System.out.print(String.format("%10s ", sdf.format(new Date(sample.time))));
74 + for (int i = 0; i < sample.data.length; i++) {
75 + if (sample.data[i] >= 0) {
76 + System.out.print(String.format("%12.2f ", sample.data[i]));
77 + total += sample.data[i];
78 + } else {
79 + System.out.print(String.format("%12s ", " "));
80 + }
81 + }
82 + System.out.println(String.format("%12.2f", total));
83 + }
84 + }
85 +
86 +}
...@@ -131,6 +131,9 @@ public class IntentPerfInstaller { ...@@ -131,6 +131,9 @@ public class IntentPerfInstaller {
131 @Reference(cardinality = MANDATORY_UNARY) 131 @Reference(cardinality = MANDATORY_UNARY)
132 protected ComponentConfigService configService; 132 protected ComponentConfigService configService;
133 133
134 + @Reference(cardinality = MANDATORY_UNARY)
135 + protected IntentPerfCollector sampleCollector;
136 +
134 private ExecutorService workers; 137 private ExecutorService workers;
135 private ApplicationId appId; 138 private ApplicationId appId;
136 private Listener listener; 139 private Listener listener;
...@@ -141,9 +144,11 @@ public class IntentPerfInstaller { ...@@ -141,9 +144,11 @@ public class IntentPerfInstaller {
141 // FIXME this variable isn't shared properly between multiple worker threads 144 // FIXME this variable isn't shared properly between multiple worker threads
142 private int lastKey = 0; 145 private int lastKey = 0;
143 146
147 + private IntentPerfUi perfUi;
148 +
144 @Activate 149 @Activate
145 public void activate() { 150 public void activate() {
146 - configService.registerProperties(getClass()); 151 +// configService.registerProperties(getClass());
147 152
148 String nodeId = clusterService.getLocalNode().ip().toString(); 153 String nodeId = clusterService.getLocalNode().ip().toString();
149 appId = coreService.registerApplication("org.onosproject.intentperf." + nodeId); 154 appId = coreService.registerApplication("org.onosproject.intentperf." + nodeId);
...@@ -169,7 +174,7 @@ public class IntentPerfInstaller { ...@@ -169,7 +174,7 @@ public class IntentPerfInstaller {
169 174
170 @Deactivate 175 @Deactivate
171 public void deactivate() { 176 public void deactivate() {
172 - configService.unregisterProperties(getClass(), false); 177 +// configService.unregisterProperties(getClass(), false);
173 stop(); 178 stop();
174 } 179 }
175 180
...@@ -266,20 +271,16 @@ public class IntentPerfInstaller { ...@@ -266,20 +271,16 @@ public class IntentPerfInstaller {
266 * @return set of intents 271 * @return set of intents
267 */ 272 */
268 private Set<Intent> createIntents(int numberOfKeys, int pathLength, int firstKey) { 273 private Set<Intent> createIntents(int numberOfKeys, int pathLength, int firstKey) {
269 - //Set<Intent> result = new HashSet<>();
270 -
271 List<NodeId> neighbors = getNeighbors(); 274 List<NodeId> neighbors = getNeighbors();
272 275
273 Multimap<NodeId, Device> devices = ArrayListMultimap.create(); 276 Multimap<NodeId, Device> devices = ArrayListMultimap.create();
274 - deviceService.getAvailableDevices().forEach(device -> 277 + deviceService.getAvailableDevices()
275 - devices.put(mastershipService.getMasterFor(device.id()), device)); 278 + .forEach(device -> devices.put(mastershipService.getMasterFor(device.id()), device));
276 279
277 // ensure that we have at least one device per neighbor 280 // ensure that we have at least one device per neighbor
278 - neighbors.forEach(node -> 281 + neighbors.forEach(node -> checkState(devices.get(node).size() > 0,
279 - checkState(devices.get(node).size() > 0,
280 "There are no devices for {}", node)); 282 "There are no devices for {}", node));
281 283
282 -
283 // TODO pull this outside so that createIntent can use it 284 // TODO pull this outside so that createIntent can use it
284 // prefix based on node id for keys generated on this instance 285 // prefix based on node id for keys generated on this instance
285 long keyPrefix = ((long) clusterService.getLocalNode().ip().getIp4Address().toInt()) << 32; 286 long keyPrefix = ((long) clusterService.getLocalNode().ip().getIp4Address().toInt()) << 32;
...@@ -401,6 +402,7 @@ public class IntentPerfInstaller { ...@@ -401,6 +402,7 @@ public class IntentPerfInstaller {
401 } 402 }
402 403
403 int cycleCount = 0; 404 int cycleCount = 0;
405 +
404 private void adjustRates() { 406 private void adjustRates() {
405 407
406 int addDelta = Math.max(1000 - cycleCount, 10); 408 int addDelta = Math.max(1000 - cycleCount, 10);
...@@ -483,6 +485,10 @@ public class IntentPerfInstaller { ...@@ -483,6 +485,10 @@ public class IntentPerfInstaller {
483 format("%.2f", runningTotal.throughput()), 485 format("%.2f", runningTotal.throughput()),
484 format("%.2f", processedThroughput), 486 format("%.2f", processedThroughput),
485 stringBuilder); 487 stringBuilder);
488 +
489 + sampleCollector.recordSample(runningTotal.throughput(),
490 + processedThroughput);
486 } 491 }
487 } 492 }
493 +
488 } 494 }
......
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 com.fasterxml.jackson.databind.node.ObjectNode;
19 +import com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.ImmutableSet;
21 +import org.apache.felix.scr.annotations.Activate;
22 +import org.apache.felix.scr.annotations.Component;
23 +import org.apache.felix.scr.annotations.Deactivate;
24 +import org.apache.felix.scr.annotations.Reference;
25 +import org.apache.felix.scr.annotations.ReferenceCardinality;
26 +import org.onlab.osgi.ServiceDirectory;
27 +import org.onosproject.intentperf.IntentPerfCollector.Sample;
28 +import org.onosproject.ui.UiConnection;
29 +import org.onosproject.ui.UiExtension;
30 +import org.onosproject.ui.UiExtensionService;
31 +import org.onosproject.ui.UiMessageHandler;
32 +import org.onosproject.ui.UiView;
33 +
34 +import java.util.Collection;
35 +import java.util.HashSet;
36 +import java.util.List;
37 +import java.util.Set;
38 +
39 +import static java.util.Collections.synchronizedSet;
40 +
41 +/**
42 + * Mechanism to stream data to the GUI.
43 + */
44 +@Component(immediate = true, enabled = false)
45 +public class IntentPerfUi {
46 +
47 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
48 + protected UiExtensionService uiExtensionService;
49 +
50 + private final Set<StreamingControl> handlers = synchronizedSet(new HashSet<>());
51 +
52 + private List<UiView> views = ImmutableList.of(new UiView("intentPerf", "Intent Performance"));
53 + private UiExtension uiExtension = new UiExtension(views, this::newHandlers,
54 + getClass().getClassLoader());
55 +
56 + @Activate
57 + protected void activate() {
58 + uiExtensionService.register(uiExtension);
59 + }
60 +
61 + @Deactivate
62 + protected void deactivate() {
63 + uiExtensionService.unregister(uiExtension);
64 + }
65 +
66 + /**
67 + * Reports a single sample of performance data.
68 + *
69 + * @param sample performance sample
70 + */
71 + public void reportSample(Sample sample) {
72 + synchronized (handlers) {
73 + handlers.forEach(h -> h.send(sample));
74 + }
75 + }
76 +
77 + // Creates and returns session specific message handler.
78 + private Collection<UiMessageHandler> newHandlers() {
79 + return ImmutableList.of(new StreamingControl());
80 + }
81 +
82 + // UI Message handlers for turning on/off reporting to a session.
83 + private class StreamingControl extends UiMessageHandler {
84 +
85 + private boolean streamingEnabled = false;
86 +
87 + protected StreamingControl() {
88 + super(ImmutableSet.of("intentPerfStart", "intentPerfStop"));
89 + }
90 +
91 + @Override
92 + public void process(ObjectNode message) {
93 + streamingEnabled = message.path("event").asText("unknown").equals("initPerfStart");
94 + }
95 +
96 + @Override
97 + public void init(UiConnection connection, ServiceDirectory directory) {
98 + super.init(connection, directory);
99 + handlers.add(this);
100 + }
101 +
102 + @Override
103 + public void destroy() {
104 + super.destroy();
105 + handlers.remove(this);
106 + }
107 +
108 + private void send(Sample sample) {
109 + // FIXME: finish this
110 + ObjectNode sn = mapper.createObjectNode()
111 + .put("time", sample.time);
112 + connection().sendMessage("intentPerf", 0, sn);
113 + }
114 + }
115 +
116 +}
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 +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
17 + <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
18 + <command>
19 + <action class="org.onosproject.intentperf.IntentPerfCommand"/>
20 + </command>
21 + </command-bundle>
22 +</blueprint>
1 +date,value,node
2 +00:55:15,68.38,node1
3 +00:55:15,55.61,node2
4 +00:55:15,74.00,node3
5 +00:55:30,74.20,node1
6 +00:55:30,77.60,node2
7 +00:55:30,74.80,node3
8 +00:55:45,74.60,node1
9 +00:55:45,72.80,node2
10 +00:55:45,77.00,node3
11 +00:56:00,73.60,node1
12 +00:56:00,75.00,node2
13 +00:56:00,76.98,node3
14 +00:56:15,75.82,node1
15 +00:56:15,75.40,node2
16 +00:56:15,76.00,node3
17 +00:56:30,75.60,node1
18 +00:56:30,74.59,node2
19 +00:56:30,74.01,node3
...\ No newline at end of file ...\ No newline at end of file
1 +key,value,date
2 +Group1,37,00:23:00
3 +Group2,12,00:23:00
4 +Group3,46,00:23:00
5 +Group1,32,00:23:05
6 +Group2,19,00:23:05
7 +Group3,42,00:23:05
8 +Group1,45,00:23:10
9 +Group2,16,00:23:10
10 +Group3,44,00:23:10
11 +Group1,24,00:23:15
12 +Group2,52,00:23:15
13 +Group3,64,00:23:15
14 +Group1,34,00:23:20
15 +Group2,62,00:23:20
16 +Group3,74,00:23:20
17 +Group1,34,00:23:25
18 +Group2,62,00:23:25
19 +Group3,74,00:23:25
...\ No newline at end of file ...\ No newline at end of file
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 +
17 +/*
18 + ONOS GUI -- Intent Perf View -- CSS file
19 + */
20 +
21 +.light #ov-intentPerf {
22 + color: navy;
23 +}
24 +
25 +.dark #ov-intentPerf {
26 + color: #1e5e6f;
27 +}
28 +
29 +.dark a {
30 + color: #88c;
31 +}
32 +
33 +#ov-intentPerf .msg {
34 + color: darkorange;
35 +}
36 +
37 +.light #ov-intentPerf .msg {
38 + color: darkorange;
39 +}
40 +
41 +.dark #ov-intentPerf .msg {
42 + color: #904e00;
43 +}
44 +
45 +
46 +
47 +.axis path,
48 +.axis line {
49 + fill: none;
50 + stroke: #000;
51 + shape-rendering: crispEdges;
52 +}
53 +
54 +.browser text {
55 + text-anchor: end;
56 +}
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 +
17 +<!-- Intent Performance partial HTML -->
18 +<div id="ov-sample">
19 + <h2> Intent Performance View </h2>
20 +
21 + <span class="msg">{{ ctrl.message }}</span>
22 +
23 + <div id="intent-perf-chart"></div>
24 +</div>
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 +
17 +/*
18 + ONOS GUI -- Intent Performance View Module
19 + */
20 +(function () {
21 + 'use strict';
22 +
23 + // injected refs
24 + var $log, tbs, flash;
25 +
26 + function start() {
27 + //var format = d3.time.format("%m/%d/%y");
28 + var format = d3.time.format("%H:%M:%S");
29 + var samples = [];
30 +
31 + var margin = {top: 20, right: 30, bottom: 30, left: 40},
32 + width = 960 - margin.left - margin.right,
33 + height = 500 - margin.top - margin.bottom;
34 +
35 + var x = d3.time.scale()
36 + .range([0, width]);
37 +
38 + var y = d3.scale.linear()
39 + .range([height, 0]);
40 +
41 + var z = d3.scale.category20c();
42 +
43 + var xAxis = d3.svg.axis()
44 + .scale(x)
45 + .orient("bottom")
46 + .ticks(d3.time.seconds);
47 +
48 + var yAxis = d3.svg.axis()
49 + .scale(y)
50 + .orient("left");
51 +
52 + var stack = d3.layout.stack()
53 + .offset("zero")
54 + .values(function(d) { return d.values; })
55 + .x(function(d) { return d.date; })
56 + .y(function(d) { return d.value; });
57 +
58 + var nest = d3.nest()
59 + .key(function(d) { return d.key; });
60 +
61 + var area = d3.svg.area()
62 + .interpolate("cardinal")
63 + .x(function(d) { return x(d.date); })
64 + .y0(function(d) { return y(d.y0); })
65 + .y1(function(d) { return y(d.y0 + d.y); });
66 +
67 + var svg = d3.select("body").append("svg")
68 + .attr("width", width + margin.left + margin.right)
69 + .attr("height", height + margin.top + margin.bottom)
70 + .append("g")
71 + .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
72 +
73 + svg.append("g")
74 + .attr("class", "x axis")
75 + .attr("transform", "translate(0," + height + ")")
76 + .call(xAxis);
77 +
78 + svg.append("g")
79 + .attr("class", "y axis")
80 + .call(yAxis);
81 +
82 + function fetchData() {
83 + d3.csv("app/view/intentPerf/data.csv", function (data) {
84 + samples = data;
85 + updateGraph();
86 + });
87 + }
88 +
89 + function updateGraph() {
90 + samples.forEach(function(d) {
91 + d.date = format.parse(d.date);
92 + d.value = +d.value;
93 + });
94 +
95 + var layers = stack(nest.entries(samples));
96 +
97 + x.domain(d3.extent(samples, function(d) { return d.date; }));
98 + y.domain([0, d3.max(samples, function(d) { return d.y0 + d.y; })]);
99 +
100 + svg.selectAll(".layer")
101 + .data(layers)
102 + .enter().append("path")
103 + .attr("class", "layer")
104 + .attr("d", function(d) { return area(d.values); })
105 + .style("fill", function(d, i) { return z(i); });
106 +
107 + svg.select(".x")
108 + .attr("transform", "translate(0," + height + ")")
109 + .call(xAxis);
110 +
111 + svg.select(".y")
112 + .call(yAxis);
113 +
114 + console.log('tick');
115 + }
116 + }
117 +
118 + start();
119 +
120 + // define the controller
121 +
122 + angular.module('ovIntentPerf', ['onosUtil'])
123 + .controller('OvIntentPerfCtrl',
124 + ['$scope', '$log', 'ToolbarService', 'FlashService',
125 +
126 + function ($scope, _$log_, _tbs_, _flash_) {
127 + var self = this
128 +
129 + $log = _$log_;
130 + tbs = _tbs_;
131 + flash = _flash_;
132 +
133 + self.message = 'Hey there dudes!';
134 + start();
135 +
136 + // Clean up on destroyed scope
137 + $scope.$on('$destroy', function () {
138 + });
139 +
140 + $log.log('OvIntentPerfCtrl has been created');
141 + }]);
142 +}());
1 +<link rel="stylesheet" href="app/view/intentPerf/intentPerf.css">
1 +<!DOCTYPE html>
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 +<html>
18 +<head>
19 + <title>Dev View</title>
20 + <script src="tp/d3.min.js"></script>
21 + <script src="tp/jquery-2.1.1.min.js"></script>
22 +
23 + <link rel="stylesheet" href="app/view/intentPerf/intentPerf.css">
24 +</head>
25 +<body>
26 +<div id="intent-perf-chart" style="width: 1024px; height: 800px"></div>
27 +<script src="app/view/intentPerf/intentPerf.js"></script>
28 +</body>
29 +</html>
...\ No newline at end of file ...\ No newline at end of file
1 +<script src="app/view/intentPerf/intentPerf.js"></script>
...@@ -412,11 +412,6 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -412,11 +412,6 @@ public class EventuallyConsistentMapImpl<K, V>
412 peerUpdateFunction.apply(key, value)); 412 peerUpdateFunction.apply(key, value));
413 notifyListeners(new EventuallyConsistentMapEvent<>( 413 notifyListeners(new EventuallyConsistentMapEvent<>(
414 EventuallyConsistentMapEvent.Type.REMOVE, key, value)); 414 EventuallyConsistentMapEvent.Type.REMOVE, key, value));
415 - } else {
416 - // TODO remove this extra call when ONOS-1207 is resolved
417 - Timestamped<V> latest = (Timestamped) items.get(key);
418 - log.info("Remove of intent {} failed; request time {} vs. latest time {}",
419 - key, timestamp, latest.timestamp());
420 } 415 }
421 } 416 }
422 417
......
...@@ -26,6 +26,8 @@ import org.onosproject.cluster.ClusterStoreDelegate; ...@@ -26,6 +26,8 @@ import org.onosproject.cluster.ClusterStoreDelegate;
26 import org.onosproject.cluster.ControllerNode; 26 import org.onosproject.cluster.ControllerNode;
27 import org.onosproject.cluster.DefaultControllerNode; 27 import org.onosproject.cluster.DefaultControllerNode;
28 import org.onosproject.cluster.NodeId; 28 import org.onosproject.cluster.NodeId;
29 +import org.onosproject.net.intent.Key;
30 +import org.onosproject.net.intent.PartitionService;
29 import org.onosproject.store.AbstractStore; 31 import org.onosproject.store.AbstractStore;
30 import org.onlab.packet.IpAddress; 32 import org.onlab.packet.IpAddress;
31 import org.slf4j.Logger; 33 import org.slf4j.Logger;
...@@ -42,7 +44,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -42,7 +44,7 @@ import static org.slf4j.LoggerFactory.getLogger;
42 @Service 44 @Service
43 public class SimpleClusterStore 45 public class SimpleClusterStore
44 extends AbstractStore<ClusterEvent, ClusterStoreDelegate> 46 extends AbstractStore<ClusterEvent, ClusterStoreDelegate>
45 - implements ClusterStore { 47 + implements ClusterStore, PartitionService {
46 48
47 public static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1"); 49 public static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1");
48 50
...@@ -91,4 +93,13 @@ public class SimpleClusterStore ...@@ -91,4 +93,13 @@ public class SimpleClusterStore
91 public void removeNode(NodeId nodeId) { 93 public void removeNode(NodeId nodeId) {
92 } 94 }
93 95
96 + @Override
97 + public boolean isMine(Key intentKey) {
98 + return true;
99 + }
100 +
101 + @Override
102 + public NodeId getLeader(Key intentKey) {
103 + return instance.id();
104 + }
94 } 105 }
......
...@@ -4,7 +4,7 @@ export ONOS_NIC=192.168.56.* ...@@ -4,7 +4,7 @@ export ONOS_NIC=192.168.56.*
4 export OC1="192.168.56.11" 4 export OC1="192.168.56.11"
5 export OC2="192.168.56.12" 5 export OC2="192.168.56.12"
6 export OC3="192.168.56.13" 6 export OC3="192.168.56.13"
7 -export OCN="192.168.56.7" 7 +export OCN="192.168.56.14"
8 export OCI="${OC1}" 8 export OCI="${OC1}"
9 9
10 -export ONOS_FEATURES=webconsole,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-openflow,onos-app-fwd,onos-app-proxyarp,onos-app-mobility 10 +unset ONOS_FEATURES
......
...@@ -9,4 +9,5 @@ export OCN="10.128.11.4" ...@@ -9,4 +9,5 @@ export OCN="10.128.11.4"
9 export OCI="${OC1}" 9 export OCI="${OC1}"
10 export OCT="${OC1}" 10 export OCT="${OC1}"
11 11
12 -export ONOS_FEATURES="webconsole,onos-api,onos-core,onos-cli,onos-rest,onos-null" 12 +export ONOS_FEATURES="webconsole,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-openflow"
13 +export ONOS_FEATURES="webconsole,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-null"
......