Brian O'Connor

Moving some apps to new repository

Repo URL: https://gerrit.onosproject.org/onos-app-samples

Apps moved
- calendar
- database-perf
- demo
- election
- ifwd
- intent-perf
- tvue

Apps removed
- foo

Change-Id: I90e8313554246aaeb92e46f9e9efcb93d951585b
Showing 74 changed files with 0 additions and 4179 deletions
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-calendar</artifactId>
<packaging>bundle</packaging>
<description>ONOS simple calendaring REST interface for intents</description>
<properties>
<web.context>/onos/calendar</web.context>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>1.18.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId>
<version>1.18.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-thirdparty</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-misc</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<_wab>src/main/webapp/</_wab>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.slf4j,
org.osgi.framework,
javax.ws.rs,javax.ws.rs.core,
com.sun.jersey.api.core,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Application providing integration between OSCARS and ONOS intent
* framework via REST API.
*/
package org.onosproject.calendar;
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="ONOS" version="2.5">
<display-name>ONOS GUI</display-name>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>org.onosproject.calendar.BandwidthCalendarResource</param-value>
</init-param>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-database-perf</artifactId>
<packaging>bundle</packaging>
<description>ONOS partitioned database perf test app bundle</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptor>src/assembly/bin.xml</descriptor>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<app name="org.onosproject.databaseperf" origin="ON.Lab" version="1.1.0"
features="onos-app-database-perf">
<description>Partitioned database performance measurement application</description>
</app>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<formats>
<format>zip</format>
</formats>
<id>onos</id>
<includeBaseDirectory>false</includeBaseDirectory>
<files>
<file>
<source>src/assembly/app.xml</source>
<destName>app.xml</destName>
</file>
<file>
<source>target/${project.artifactId}-${project.version}.jar</source>
<destName>m2/org/onosproject/${project.artifactId}/${project.version}/${project.artifactId}-${project.version}.jar</destName>
</file>
</files>
</assembly>
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.databaseperf;
import static org.apache.felix.scr.annotations.ReferenceCardinality.MANDATORY_UNARY;
import static org.onlab.util.Tools.delay;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.onlab.util.KryoNamespace;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.slf4j.Logger;
/**
* Application to measure partitioned database performance.
*/
@Component(immediate = true)
public class DatabasePerfInstaller {
private final Logger log = getLogger(getClass());
@Reference(cardinality = MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = MANDATORY_UNARY)
protected ClusterService clusterService;
@Reference(cardinality = MANDATORY_UNARY)
protected StorageService storageService;
private boolean stopped;
private ApplicationId appId;
private static final long REPORT_PERIOD = 5000L; //ms
private Timer reportTimer;
private AtomicInteger successCount = new AtomicInteger(0);
private AtomicInteger failureCount = new AtomicInteger(0);
private ConsistentMap<String, String> cmap;
private ControllerNode localNode;
private long reportStartTime = System.currentTimeMillis();
private static final int NUM_TASK_THREADS = 2;
private ExecutorService taskExecutor;
private static final Serializer SERIALIZER = new Serializer() {
KryoNamespace kryo = new KryoNamespace.Builder().build();
@Override
public <T> byte[] encode(T object) {
return kryo.serialize(object);
}
@Override
public <T> T decode(byte[] bytes) {
return kryo.deserialize(bytes);
}
};
@Activate
public void activate() {
localNode = clusterService.getLocalNode();
String nodeId = localNode.ip().toString();
appId = coreService.registerApplication("org.onosproject.nettyperf."
+ nodeId);
cmap = storageService.createConsistentMap("onos-app-database-perf-test-map", SERIALIZER);
taskExecutor = Executors.newFixedThreadPool(NUM_TASK_THREADS, groupedThreads("onos/database-perf", "worker"));
log.info("Started with Application ID {}", appId.id());
start();
}
@Deactivate
public void deactivate() {
stop();
log.info("Stopped");
}
public void start() {
long delay = System.currentTimeMillis() % REPORT_PERIOD;
reportTimer = new Timer("onos-netty-perf-reporter");
reportTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
report();
}
}, delay, REPORT_PERIOD);
stopped = false;
IntStream.range(0, NUM_TASK_THREADS).forEach(i -> {
taskExecutor.submit(() -> {
delay(2000); // take a breath to start
while (!stopped) {
performDBOperation();
delay(2); // take a breather
}
});
});
}
private void performDBOperation() {
String key = String.format("test%d", RandomUtils.nextInt(1000));
try {
if (RandomUtils.nextBoolean()) {
cmap.put(key, UUID.randomUUID().toString());
} else {
cmap.get(key);
}
successCount.incrementAndGet();
} catch (Exception e) {
failureCount.incrementAndGet();
}
}
private void report() {
long delta = System.currentTimeMillis() - reportStartTime;
if (delta > 0) {
int rate = (int) Math.round(((successCount.get() * 1000.0) / delta));
log.info("Passed: {}, Failed: {}, Rate: {}",
successCount.getAndSet(0), failureCount.getAndSet(0), rate);
reportStartTime = System.currentTimeMillis();
}
}
public void stop() {
reportTimer.cancel();
reportTimer = null;
stopped = true;
try {
taskExecutor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.warn("Failed to stop worker.");
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Performance test application that induces steady load on the partitioned database.
*/
package org.onosproject.databaseperf;
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-demo</artifactId>
<packaging>bundle</packaging>
<description>ONOS demo app bundle</description>
<properties>
<web.context>/onos/demo</web.context>
</properties>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>1.18.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId>
<version>1.18.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<_wab>src/main/webapp/</_wab>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.slf4j,
org.osgi.framework,
javax.ws.rs,javax.ws.rs.core,
com.sun.jersey.api.core,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
com.fasterxml.jackson.databind,
com.fasterxml.jackson.databind.node,
org.apache.commons.lang.math.*,
com.google.common.*,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*,
org.onlab.util.*,
org.jboss.netty.util.*
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.demo;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.Optional;
/**
* Simple demo api interface.
*/
public interface DemoAPI {
enum InstallType { MESH, RANDOM };
/**
* Tests flow subsystem based on the parameters supplied.
*
* @param params the test parameters
* @return JSON representation
*/
JsonNode flowTest(Optional<JsonNode> params);
/**
* Installs intents based on the installation type.
* @param type the installation type.
* @param runParams run params
*/
void setup(InstallType type, Optional<JsonNode> runParams);
/**
* Uninstalls all existing intents.
*/
void tearDown();
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.demo;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.onlab.rest.BaseResource;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
/**
* Rest API for demos.
*/
@Path("intents")
public class DemoResource extends BaseResource {
@POST
@Path("flowTest")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response flowTest(InputStream input) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode cfg = mapper.readTree(input);
DemoAPI demo = get(DemoAPI.class);
return Response.ok(demo.flowTest(Optional.ofNullable(cfg)).toString()).build();
}
@POST
@Path("setup")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response setup(InputStream input) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode cfg = mapper.readTree(input);
if (!cfg.has("type")) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Expected type field containing either mesh or random.").build();
}
DemoAPI.InstallType type = DemoAPI.InstallType.valueOf(
cfg.get("type").asText().toUpperCase());
DemoAPI demo = get(DemoAPI.class);
demo.setup(type, Optional.ofNullable(cfg.get("runParams")));
return Response.ok(mapper.createObjectNode().toString()).build();
}
@GET
@Path("teardown")
@Produces(MediaType.APPLICATION_JSON)
public Response tearDown() throws IOException {
ObjectMapper mapper = new ObjectMapper();
DemoAPI demo = get(DemoAPI.class);
demo.tearDown();
return Response.ok(mapper.createObjectNode().toString()).build();
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Demo applications live here.
*/
package org.onosproject.demo;
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="ONOS" version="2.5">
<display-name>ONOS DEMO APP API v1.0</display-name>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>
org.onosproject.demo.DemoResource
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-election</artifactId>
<packaging>bundle</packaging>
<description>ONOS app leadership election test</description>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<classifier>tests</classifier>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
</dependencies>
</project>
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.election;
import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.cluster.ClusterService;
import org.onosproject.core.CoreService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.LeadershipEvent;
import org.onosproject.cluster.LeadershipEventListener;
import org.onosproject.cluster.LeadershipService;
import org.onosproject.core.ApplicationId;
import org.slf4j.Logger;
/**
* Simple application to test leadership election.
*/
@Component(immediate = true)
public class ElectionTest {
private final Logger log = getLogger(getClass());
private static final String ELECTION_APP = "org.onosproject.election";
private ApplicationId appId;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LeadershipService leadershipService;
private LeadershipEventListener leadershipEventListener =
new InnerLeadershipEventListener();
private ControllerNode localControllerNode;
@Activate
protected void activate() {
log.info("Election-test app started");
appId = coreService.registerApplication(ELECTION_APP);
localControllerNode = clusterService.getLocalNode();
leadershipService.addListener(leadershipEventListener);
leadershipService.runForLeadership(appId.name());
}
@Deactivate
protected void deactivate() {
leadershipService.withdraw(appId.name());
leadershipService.removeListener(leadershipEventListener);
log.info("Election-test app Stopped");
}
/**
* A listener for Leadership Events.
*/
private class InnerLeadershipEventListener
implements LeadershipEventListener {
@Override
public void event(LeadershipEvent event) {
if (!event.subject().topic().equals(appId.name())) {
return; // Not our topic: ignore
}
//only log what pertains to us
log.debug("Leadership Event: time = {} type = {} event = {}",
event.time(), event.type(), event);
if (!event.subject().leader().equals(
localControllerNode.id())) {
return; // The event is not about this instance: ignore
}
switch (event.type()) {
case LEADER_ELECTED:
log.info("Election-test app leader elected");
break;
case LEADER_BOOTED:
log.info("Election-test app lost election");
break;
case LEADER_REELECTED:
log.debug("Election-test app was re-elected");
break;
default:
break;
}
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.election.cli;
import org.onosproject.cluster.NodeId;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cluster.LeadershipService;
/**
* CLI command to get the current leader for the Election test application.
*/
@Command(scope = "onos", name = "election-test-leader",
description = "Get the current leader for the Election test application")
public class ElectionTestLeaderCommand extends AbstractShellCommand {
private NodeId leader;
private static final String ELECTION_APP = "org.onosproject.election";
@Override
protected void execute() {
LeadershipService service = get(LeadershipService.class);
//print the current leader
leader = service.getLeader(ELECTION_APP);
printLeader(leader);
}
/**
* Prints the leader.
*
* @param leader the leader to print
*/
private void printLeader(NodeId leader) {
if (leader != null) {
print("The current leader for the Election app is %s.", leader);
} else {
print("There is currently no leader elected for the Election app");
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.election.cli;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cluster.LeadershipService;
/**
* CLI command to run for leadership of the Election test application.
*/
@Command(scope = "onos", name = "election-test-run",
description = "Run for leader of the Election test application")
public class ElectionTestRunCommand extends AbstractShellCommand {
private static final String ELECTION_APP = "org.onosproject.election";
@Override
protected void execute() {
LeadershipService service = get(LeadershipService.class);
service.runForLeadership(ELECTION_APP);
//print the current leader
print("Entering leadership elections for the Election app.");
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.election.cli;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cluster.LeadershipService;
/**
* CLI command to withdraw the local node from leadership election for
* the Election test application.
*/
@Command(scope = "onos", name = "election-test-withdraw",
description = "Withdraw node from leadership election for the Election test application")
public class ElectionTestWithdrawCommand extends AbstractShellCommand {
private static final String ELECTION_APP = "org.onosproject.election";
@Override
protected void execute() {
LeadershipService service = get(LeadershipService.class);
service.withdraw(ELECTION_APP);
//print the current leader
print("Withdrawing from leadership elections for the Election app.");
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Election test command-line handlers.
*/
package org.onosproject.election.cli;
\ No newline at end of file
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Sample application for use in various experiments.
*/
package org.onosproject.election;
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.election.cli.ElectionTestLeaderCommand"/>
</command>
<command>
<action class="org.onosproject.election.cli.ElectionTestRunCommand"/>
</command>
<command>
<action class="org.onosproject.election.cli.ElectionTestWithdrawCommand"/>
</command>
</command-bundle>
</blueprint>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-foo</artifactId>
<packaging>bundle</packaging>
<description>ONOS application for miscellaneous experiments</description>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-nio</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-netty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-misc</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
</dependencies>
</project>
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import static java.util.concurrent.Executors.newScheduledThreadPool;
import static org.onlab.util.Tools.namedThreads;
import static org.slf4j.LoggerFactory.getLogger;
import java.nio.ByteBuffer;
import java.util.concurrent.ScheduledExecutorService;
//import java.util.concurrent.TimeUnit;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ClusterEventListener;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.NodeId;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.store.service.DatabaseAdminService;
import org.onosproject.store.service.DatabaseException;
import org.onosproject.store.service.DatabaseService;
import org.onosproject.store.service.Lock;
import org.onosproject.store.service.LockService;
import org.onosproject.store.service.VersionedValue;
import org.slf4j.Logger;
/**
* Playground app component.
*/
@Component(immediate = true)
public class FooComponent {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MastershipService mastershipService;
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
protected DatabaseAdminService dbAdminService;
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
protected DatabaseService dbService;
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
protected LockService lockService;
private final ClusterEventListener clusterListener = new InnerClusterListener();
private final DeviceListener deviceListener = new InnerDeviceListener();
private final IntentListener intentListener = new InnerIntentListener();
private final MastershipListener mastershipListener = new InnerMastershipListener();
private ScheduledExecutorService executor;
@Activate
public void activate() {
executor = newScheduledThreadPool(4, namedThreads("foo-executor-%d"));
clusterService.addListener(clusterListener);
deviceService.addListener(deviceListener);
intentService.addListener(intentListener);
mastershipService.addListener(mastershipListener);
if (dbService == null || dbAdminService == null) {
log.info("Couldn't find DB service");
} else {
log.info("Found DB service");
//longIncrementor();
//lockUnlock();
//executor.scheduleAtFixedRate(new LongIncrementor(), 1, 10, TimeUnit.SECONDS);
//executor.scheduleAtFixedRate(new LongIncrementor(), 1, 10, TimeUnit.SECONDS);
}
log.info("Started");
}
@Deactivate
public void deactivate() {
executor.shutdown();
clusterService.removeListener(clusterListener);
deviceService.removeListener(deviceListener);
intentService.removeListener(intentListener);
mastershipService.removeListener(mastershipListener);
log.info("Stopped");
}
private class InnerClusterListener implements ClusterEventListener {
@Override
public void event(ClusterEvent event) {
log.info("WOOOOT! {}", event);
}
}
private class InnerDeviceListener implements DeviceListener {
@Override
public void event(DeviceEvent event) {
log.info("YEEEEHAAAAW! {}", event);
}
}
private class InnerIntentListener implements IntentListener {
@Override
public void event(IntentEvent event) {
String message;
if (event.type() == IntentEvent.Type.INSTALL_REQ) {
message = "WOW! It looks like someone has some intentions: {}";
} else if (event.type() == IntentEvent.Type.INSTALLED) {
message = "AWESOME! So far things are going great: {}";
} else if (event.type() == IntentEvent.Type.WITHDRAWN) {
message = "HMMM! Ambitions are fading apparently: {}";
} else {
message = "CRAP!!! Things are not turning out as intended: {}";
}
log.info(message, event.subject());
}
}
private class InnerMastershipListener implements MastershipListener {
@Override
public void event(MastershipEvent event) {
final NodeId myId = clusterService.getLocalNode().id();
if (myId.equals(event.roleInfo().master())) {
log.info("I have control/I wish you luck {}", event);
} else {
log.info("you have control {}", event);
}
}
}
private void lockUnlock() throws InterruptedException {
try {
final String locksTable = "onos-locks";
if (!dbAdminService.listTables().contains(locksTable)) {
dbAdminService.createTable(locksTable, 10000);
}
Lock lock = lockService.create("foo-bar");
log.info("Requesting lock");
lock.lock(10000);
//try {
//Thread.sleep(5000);
//} catch (InterruptedException e) {
//e.printStackTrace();
//}
log.info("Acquired Lock");
log.info("Do I have the lock: {} ", lock.isLocked());
//lock.unlock();
log.info("Do I have the lock: {} ", lock.isLocked());
} finally {
log.info("Done");
}
}
private void longIncrementor() {
try {
final String someTable = "admin";
final String someKey = "long";
if (!dbAdminService.listTables().contains(someTable)) {
dbAdminService.createTable(someTable);
}
VersionedValue vv = dbService.get(someTable, someKey);
if (vv == null) {
ByteBuffer zero = ByteBuffer.allocate(Long.BYTES).putLong(0);
if (dbService.putIfAbsent(someTable, someKey, zero.array())) {
log.info("Wrote initial value");
vv = dbService.get(someTable, someKey);
} else {
log.info("Concurrent write detected.");
// concurrent write detected, read and fall through
vv = dbService.get(someTable, someKey);
if (vv == null) {
log.error("Shouldn't reach here");
}
}
}
int retry = 1;
do {
if (vv == null) {
log.error("Shouldn't reach here - value is null");
break;
}
ByteBuffer prev = ByteBuffer.wrap(vv.value());
long next = prev.getLong() + 1;
byte[] newValue = ByteBuffer.allocate(Long.BYTES).putLong(next).array();
if (dbService.putIfVersionMatches(someTable, someKey, newValue, vv.version())) {
log.info("Write success. New value: {}", next);
break;
} else {
log.info("Write failed retrying.....{}", retry);
vv = dbService.get(someTable, someKey);
if (vv == null) {
log.error("Shouldn't reach here");
}
}
} while (retry++ < 5);
} catch (DatabaseException e) {
log.debug("DB Exception thrown {}", e.getMessage());
} catch (Exception e) {
log.error("Exception thrown", e);
}
}
private final class LongIncrementor implements Runnable {
@Override
public void run() {
longIncrementor();
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import com.google.common.collect.Lists;
import org.onlab.nio.AcceptorLoop;
import org.onlab.nio.IOLoop;
import org.onlab.nio.MessageStream;
import org.onlab.util.Counter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.channels.ByteChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static java.lang.String.format;
import static java.lang.System.nanoTime;
import static java.lang.System.out;
import static org.onlab.util.Tools.delay;
import static org.onlab.util.Tools.namedThreads;
/**
* Auxiliary test fixture to measure speed of NIO-based channels.
*/
public class IOLoopTestServer {
private static Logger log = LoggerFactory.getLogger(IOLoopTestServer.class);
private static final int PRUNE_FREQUENCY = 1000;
static final int PORT = 9876;
static final long TIMEOUT = 1000;
static final boolean SO_NO_DELAY = false;
static final int SO_SEND_BUFFER_SIZE = 128 * 1024;
static final int SO_RCV_BUFFER_SIZE = 128 * 1024;
static final DecimalFormat FORMAT = new DecimalFormat("#,##0");
private final AcceptorLoop aloop;
private final ExecutorService apool = Executors.newSingleThreadExecutor(namedThreads("accept"));
private final List<CustomIOLoop> iloops = new ArrayList<>();
private final ExecutorService ipool;
private final int workerCount;
private final int msgLength;
private int lastWorker = -1;
Counter messages;
Counter bytes;
/**
* Main entry point to launch the server.
*
* @param args command-line arguments
* @throws java.io.IOException if unable to crate IO loops
*/
public static void main(String[] args) throws IOException {
startStandalone(args);
System.exit(0);
}
/*
* Starts a standalone IO loop test server.
*
* @param args command-line arguments
*/
public static void startStandalone(String[] args) throws IOException {
InetAddress ip = InetAddress.getByName(args.length > 0 ? args[0] : "127.0.0.1");
int wc = args.length > 1 ? Integer.parseInt(args[1]) : 6;
int ml = args.length > 2 ? Integer.parseInt(args[2]) : 128;
log.info("Setting up the server with {} workers, {} byte messages on {}... ",
wc, ml, ip);
IOLoopTestServer server = new IOLoopTestServer(ip, wc, ml, PORT);
server.start();
// Start pruning clients and keep going until their number goes to 0.
int remaining = -1;
while (remaining == -1 || remaining > 0) {
delay(PRUNE_FREQUENCY);
int r = server.prune();
remaining = remaining == -1 && r == 0 ? remaining : r;
}
server.stop();
}
/**
* Creates a speed server.
*
* @param ip optional ip of the adapter where to bind
* @param wc worker count
* @param ml message length in bytes
* @param port listen port
* @throws java.io.IOException if unable to create IO loops
*/
public IOLoopTestServer(InetAddress ip, int wc, int ml, int port) throws IOException {
this.workerCount = wc;
this.msgLength = ml;
this.ipool = Executors.newFixedThreadPool(workerCount, namedThreads("io-loop"));
this.aloop = new CustomAcceptLoop(new InetSocketAddress(ip, port));
for (int i = 0; i < workerCount; i++) {
iloops.add(new CustomIOLoop());
}
}
/**
* Start the server IO loops and kicks off throughput tracking.
*/
public void start() {
messages = new Counter();
bytes = new Counter();
for (CustomIOLoop l : iloops) {
ipool.execute(l);
}
apool.execute(aloop);
for (CustomIOLoop l : iloops) {
l.awaitStart(TIMEOUT);
}
aloop.awaitStart(TIMEOUT);
}
/**
* Stop the server IO loops and freezes throughput tracking.
*/
public void stop() {
aloop.shutdown();
for (CustomIOLoop l : iloops) {
l.shutdown();
}
for (CustomIOLoop l : iloops) {
l.awaitStop(TIMEOUT);
}
aloop.awaitStop(TIMEOUT);
messages.freeze();
bytes.freeze();
}
/**
* Reports on the accumulated throughput and latency.
*/
public void report() {
DecimalFormat f = new DecimalFormat("#,##0");
out.println(format("Server: %s messages; %s bytes; %s mps; %s MBs",
f.format(messages.total()), f.format(bytes.total()),
f.format(messages.throughput()),
f.format(bytes.throughput() / (1024 * msgLength))));
}
/**
* Prunes the IO loops of stale message buffers.
*
* @return number of remaining IO loops among all workers.
*/
public int prune() {
int count = 0;
for (CustomIOLoop l : iloops) {
count += l.pruneStaleStreams();
}
return count;
}
// Get the next worker to which a client should be assigned
private synchronized CustomIOLoop nextWorker() {
lastWorker = (lastWorker + 1) % workerCount;
return iloops.get(lastWorker);
}
// Loop for transfer of fixed-length messages
private class CustomIOLoop extends IOLoop<TestMessage, TestMessageStream> {
public CustomIOLoop() throws IOException {
super(500);
}
@Override
protected TestMessageStream createStream(ByteChannel channel) {
return new TestMessageStream(msgLength, channel, this);
}
@Override
protected void removeStream(MessageStream<TestMessage> stream) {
super.removeStream(stream);
messages.add(stream.messagesIn().total());
bytes.add(stream.bytesIn().total());
}
@Override
protected void processMessages(List<TestMessage> messages,
MessageStream<TestMessage> stream) {
try {
stream.write(createResponses(messages));
} catch (IOException e) {
log.error("Unable to echo messages", e);
}
}
private List<TestMessage> createResponses(List<TestMessage> messages) {
List<TestMessage> responses = Lists.newArrayListWithCapacity(messages.size());
for (TestMessage message : messages) {
responses.add(new TestMessage(message.length(), message.requestorTime(),
nanoTime(), message.padding()));
}
return responses;
}
}
// Loop for accepting client connections
private class CustomAcceptLoop extends AcceptorLoop {
public CustomAcceptLoop(SocketAddress address) throws IOException {
super(500, address);
}
@Override
protected void acceptConnection(ServerSocketChannel channel) throws IOException {
SocketChannel sc = channel.accept();
sc.configureBlocking(false);
Socket so = sc.socket();
so.setTcpNoDelay(SO_NO_DELAY);
so.setReceiveBufferSize(SO_RCV_BUFFER_SIZE);
so.setSendBufferSize(SO_SEND_BUFFER_SIZE);
nextWorker().acceptStream(sc);
log.info("Connected client");
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import java.io.IOException;
import org.onlab.netty.Message;
import org.onlab.netty.MessageHandler;
/**
* Message handler that echos the message back to the sender.
*/
public class NettyEchoHandler implements MessageHandler {
@Override
public void handle(Message message) throws IOException {
message.respond(message.payload());
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import org.onlab.netty.Message;
import org.onlab.netty.MessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A MessageHandler that simply logs the information.
*/
public class NettyNothingHandler implements MessageHandler {
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
public void handle(Message message) {
// Do nothing
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import static java.lang.Thread.sleep;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.onlab.metrics.MetricsComponent;
import org.onlab.metrics.MetricsFeature;
import org.onlab.metrics.MetricsManager;
import org.onlab.netty.Endpoint;
import org.onlab.netty.NettyMessagingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.Timer;
/**
* The Simple netty client test.
*/
// FIXME: Should be move out to test or app
public final class SimpleNettyClient {
private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class);
static NettyMessagingService messaging;
static MetricsManager metrics;
private SimpleNettyClient() {
}
/**
* The entry point of application.
*
* @param args the input arguments
* @throws IOException the iO exception
* @throws InterruptedException the interrupted exception
* @throws ExecutionException the execution exception
* @throws TimeoutException the timeout exception
*/
public static void main(String[] args)
throws IOException, InterruptedException, ExecutionException,
TimeoutException {
try {
startStandalone(args);
} catch (Exception e) {
e.printStackTrace();
}
System.exit(0);
}
/**
* Start standalone.
*
* @param args the args
* @throws Exception the exception
*/
public static void startStandalone(String[] args) throws Exception {
String host = args.length > 0 ? args[0] : "localhost";
int port = args.length > 1 ? Integer.parseInt(args[1]) : 8081;
int warmup = args.length > 2 ? Integer.parseInt(args[2]) : 1000;
int iterations = args.length > 3 ? Integer.parseInt(args[3]) : 50 * 100000;
messaging = new TestNettyMessagingService(9081);
metrics = new MetricsManager();
Endpoint endpoint = new Endpoint(host, port);
messaging.activate();
MetricsFeature feature = new MetricsFeature("latency");
MetricsComponent component = metrics.registerComponent("NettyMessaging");
log.info("connecting " + host + ":" + port + " warmup:" + warmup + " iterations:" + iterations);
for (int i = 0; i < warmup; i++) {
messaging.sendAsync(endpoint, "simple", "Hello World".getBytes());
Future<byte[]> responseFuture = messaging
.sendAndReceive(endpoint, "echo",
"Hello World".getBytes());
responseFuture.get(100000, TimeUnit.MILLISECONDS);
}
log.info("measuring round-trip send & receive");
Timer sendAndReceiveTimer = metrics.createTimer(component, feature, "SendAndReceive");
int timeouts = 0;
for (int i = 0; i < iterations; i++) {
Future<byte[]> responseFuture;
Timer.Context context = sendAndReceiveTimer.time();
try {
responseFuture = messaging
.sendAndReceive(endpoint, "echo",
"Hello World".getBytes());
responseFuture.get(10000, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
timeouts++;
log.info("timeout:" + timeouts + " at iteration:" + i);
} finally {
context.stop();
}
// System.out.println("Got back:" + new String(response.get(2, TimeUnit.SECONDS)));
}
//sleep(1000);
log.info("measuring async sender");
Timer sendAsyncTimer = metrics.createTimer(component, feature, "AsyncSender");
for (int i = 0; i < iterations; i++) {
Timer.Context context = sendAsyncTimer.time();
messaging.sendAsync(endpoint, "simple", "Hello World".getBytes());
context.stop();
}
sleep(10000);
}
public static void stop() {
try {
messaging.deactivate();
} catch (Exception e) {
log.info("Unable to stop client %s", e);
}
}
/**
* The type Test netty messaging service.
*/
public static class TestNettyMessagingService extends NettyMessagingService {
/**
* Instantiates a new Test netty messaging service.
*
* @param port the port
* @throws Exception the exception
*/
public TestNettyMessagingService(int port) throws Exception {
super(port);
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import static org.onosproject.foo.SimpleNettyClient.startStandalone;
import static org.onosproject.foo.SimpleNettyClient.stop;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
/**
* Test Netty client performance.
*/
@Command(scope = "onos", name = "simple-netty-client",
description = "Starts simple Netty client")
public class SimpleNettyClientCommand extends AbstractShellCommand {
//FIXME: replace these arguments with proper ones needed for the test.
@Argument(index = 0, name = "hostname", description = "Server Hostname",
required = false, multiValued = false)
String hostname = "localhost";
@Argument(index = 1, name = "port", description = "Port",
required = false, multiValued = false)
String port = "8081";
@Argument(index = 2, name = "warmupCount", description = "Warm-up count",
required = false, multiValued = false)
String warmupCount = "1000";
@Argument(index = 3, name = "messageCount", description = "Message count",
required = false, multiValued = false)
String messageCount = "1000000";
@Override
protected void execute() {
try {
startStandalone(new String[]{hostname, port, warmupCount, messageCount});
} catch (Exception e) {
error("Unable to start client %s", e);
}
stop();
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import org.onlab.netty.NettyMessagingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Test to measure Messaging performance.
*/
public final class SimpleNettyServer {
private static Logger log = LoggerFactory.getLogger(SimpleNettyServer.class);
private SimpleNettyServer() {}
/**
* The entry point of application.
*
* @param args the input arguments
* @throws Exception the exception
*/
public static void main(String... args) throws Exception {
startStandalone(args);
System.exit(0);
}
/**
* Start standalone server.
*
* @param args the args
* @throws Exception the exception
*/
public static void startStandalone(String[] args) throws Exception {
int port = args.length > 0 ? Integer.parseInt(args[0]) : 8081;
NettyMessagingService server = new NettyMessagingService(port);
server.activate();
server.registerHandler("simple", new NettyNothingHandler());
server.registerHandler("echo", new NettyEchoHandler());
log.info("Netty Server server on port " + port);
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import static org.onosproject.foo.SimpleNettyServer.startStandalone;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
/**
* Starts the Simple Netty server.
*/
@Command(scope = "onos", name = "simple-netty-server",
description = "Starts simple Netty server")
public class SimpleNettyServerCommand extends AbstractShellCommand {
//FIXME: Replace these with parameters for
@Argument(index = 0, name = "port", description = "listen port",
required = false, multiValued = false)
String port = "8081";
@Override
protected void execute() {
try {
startStandalone(new String[]{port});
} catch (Exception e) {
error("Unable to start server %s", e);
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import static org.onosproject.foo.IOLoopTestClient.startStandalone;
/**
* Starts the test IO loop client.
*/
@Command(scope = "onos", name = "test-io-client",
description = "Starts the test IO loop client")
public class TestIOClientCommand extends AbstractShellCommand {
@Argument(index = 0, name = "serverIp", description = "Server IP address",
required = false, multiValued = false)
String serverIp = "127.0.0.1";
@Argument(index = 1, name = "workers", description = "IO workers",
required = false, multiValued = false)
String workers = "6";
@Argument(index = 2, name = "messageCount", description = "Message count",
required = false, multiValued = false)
String messageCount = "1000000";
@Argument(index = 3, name = "messageLength", description = "Message length (bytes)",
required = false, multiValued = false)
String messageLength = "128";
@Argument(index = 4, name = "timeoutSecs", description = "Test timeout (seconds)",
required = false, multiValued = false)
String timeoutSecs = "60";
@Override
protected void execute() {
try {
startStandalone(new String[]{serverIp, workers, messageCount, messageLength, timeoutSecs});
} catch (Exception e) {
error("Unable to start client %s", e);
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import static org.onosproject.foo.IOLoopTestServer.startStandalone;
/**
* Starts the test IO loop server.
*/
@Command(scope = "onos", name = "test-io-server",
description = "Starts the test IO loop server")
public class TestIOServerCommand extends AbstractShellCommand {
@Argument(index = 0, name = "serverIp", description = "Server IP address",
required = false, multiValued = false)
String serverIp = "127.0.0.1";
@Argument(index = 1, name = "workers", description = "IO workers",
required = false, multiValued = false)
String workers = "6";
@Argument(index = 2, name = "messageLength", description = "Message length (bytes)",
required = false, multiValued = false)
String messageLength = "128";
@Override
protected void execute() {
try {
startStandalone(new String[]{serverIp, workers, messageLength});
} catch (Exception e) {
error("Unable to start server %s", e);
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import org.onlab.nio.AbstractMessage;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Test message for measuring rate and round-trip latency.
*/
public class TestMessage extends AbstractMessage {
private final byte[] padding;
private final long requestorTime;
private final long responderTime;
/**
* Creates a new message with the specified data.
*
* @param length message length
* @param requestorTime requester time
* @param responderTime responder time
* @param padding message padding
*/
TestMessage(int length, long requestorTime, long responderTime, byte[] padding) {
this.length = length;
this.requestorTime = requestorTime;
this.responderTime = responderTime;
this.padding = checkNotNull(padding, "Padding cannot be null");
}
public long requestorTime() {
return requestorTime;
}
public long responderTime() {
return responderTime;
}
public byte[] padding() {
return padding;
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.foo;
import org.onlab.nio.IOLoop;
import org.onlab.nio.MessageStream;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
/**
* Fixed-length message transfer buffer.
*/
public class TestMessageStream extends MessageStream<TestMessage> {
private static final String E_WRONG_LEN = "Illegal message length: ";
private static final long START_TAG = 0xfeedcafedeaddeedL;
private static final long END_TAG = 0xbeadcafedeaddeedL;
private static final int META_LENGTH = 40;
private final int length;
private boolean isStrict = true;
public TestMessageStream(int length, ByteChannel ch, IOLoop<TestMessage, ?> loop) {
super(loop, ch, 64 * 1024, 500);
checkArgument(length >= META_LENGTH, "Length must be greater than header length of 40");
this.length = length;
}
void setNonStrict() {
isStrict = false;
}
@Override
protected TestMessage read(ByteBuffer rb) {
if (rb.remaining() < length) {
return null;
}
long startTag = rb.getLong();
if (isStrict) {
checkState(startTag == START_TAG, "Incorrect message start");
}
long size = rb.getLong();
long requestorTime = rb.getLong();
long responderTime = rb.getLong();
byte[] padding = padding();
rb.get(padding);
long endTag = rb.getLong();
if (isStrict) {
checkState(endTag == END_TAG, "Incorrect message end");
}
return new TestMessage((int) size, requestorTime, responderTime, padding);
}
@Override
protected void write(TestMessage message, ByteBuffer wb) {
if (message.length() != length) {
throw new IllegalArgumentException(E_WRONG_LEN + message.length());
}
wb.putLong(START_TAG);
wb.putLong(message.length());
wb.putLong(message.requestorTime());
wb.putLong(message.responderTime());
wb.put(message.padding(), 0, length - META_LENGTH);
wb.putLong(END_TAG);
}
public byte[] padding() {
return new byte[length - META_LENGTH];
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Sample application for use in various experiments.
*/
package org.onosproject.foo;
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.foo.TestIOClientCommand"/>
</command>
<command>
<action class="org.onosproject.foo.TestIOServerCommand"/>
</command>
<command>
<action class="org.onosproject.foo.SimpleNettyServerCommand"/>
</command>
<command>
<action class="org.onosproject.foo.SimpleNettyClientCommand"/>
</command>
</command-bundle>
</blueprint>
#
# Copyright 2014 Open Networking Laboratory
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
livetribe.slp.da.expired.services.purge.period=60
livetribe.slp.sa.client.connect.address=127.0.0.1
livetribe.slp.sa.client.factory=org.livetribe.slp.sa.StandardServiceAgentClient$Factory
livetribe.slp.sa.factory=org.livetribe.slp.sa.StandardServiceAgent$Factory
livetribe.slp.sa.service.renewal.enabled=true
livetribe.slp.sa.unicast.prefer.tcp=false
livetribe.slp.tcp.connector.factory=org.livetribe.slp.spi.net.SocketTCPConnector$Factory
livetribe.slp.tcp.connector.server.factory=org.livetribe.slp.spi.net.SocketTCPConnectorServer$Factory
livetribe.slp.tcp.message.max.length=4096
livetribe.slp.tcp.read.timeout=300000
livetribe.slp.ua.client.factory=org.livetribe.slp.ua.StandardUserAgentClient$Factory
livetribe.slp.ua.factory=org.livetribe.slp.ua.StandardUserAgent$Factory
livetribe.slp.ua.unicast.prefer.tcp=false
livetribe.slp.udp.connector.factory=org.livetribe.slp.spi.net.SocketUDPConnector$Factory
livetribe.slp.udp.connector.server.factory=org.livetribe.slp.spi.net.SocketUDPConnectorServer$Factory
net.slp.DAAddresses=
net.slp.DAAttributes=
net.slp.DAHeartBeat=10800
net.slp.MTU=1400
net.slp.SAAttributes=
net.slp.broadcastAddress=255.255.255.255
net.slp.datagramTimeouts=150,250,400
net.slp.interfaces=0.0.0.0
net.slp.isBroadcastOnly=false
net.slp.locale=en
net.slp.multicastAddress=239.255.255.253
net.slp.multicastMaximumWait=15000
net.slp.multicastTTL=255
net.slp.multicastTimeouts=150,250,400,600,1000
net.slp.notificationPort=1847
net.slp.port=427
net.slp.useScopes=default
org.onlab.cluster.name = TV-ONOS
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<app name="org.onosproject.app.ifwd" origin="ON.Lab" version="1.1.0"
features="onos-app-ifwd">
<description>ONOS Reactive forwarding application using intent subsystem (experimental)</description>
</app>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-ifwd</artifactId>
<packaging>bundle</packaging>
<description>ONOS simple reactive forwarding app that uses intent service</description>
</project>
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ifwd;
import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.topology.TopologyService;
import org.slf4j.Logger;
/**
* WORK-IN-PROGRESS: Sample reactive forwarding application using intent framework.
*/
@Component(immediate = true)
public class IntentReactiveForwarding {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowRuleService flowRuleService;
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
private ApplicationId appId;
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.ifwd");
packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
log.info("Started");
}
@Deactivate
public void deactivate() {
packetService.removeProcessor(processor);
processor = null;
log.info("Stopped");
}
/**
* Packet processor responsible for forwarding packets along their paths.
*/
private class ReactivePacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
// Stop processing if the packet has been handled, since we
// can't do any more to it.
if (context.isHandled()) {
return;
}
InboundPacket pkt = context.inPacket();
Ethernet ethPkt = pkt.parsed();
if (ethPkt == null) {
return;
}
HostId srcId = HostId.hostId(ethPkt.getSourceMAC());
HostId dstId = HostId.hostId(ethPkt.getDestinationMAC());
// Do we know who this is for? If not, flood and bail.
Host dst = hostService.getHost(dstId);
if (dst == null) {
flood(context);
return;
}
// Otherwise forward and be done with it.
setUpConnectivity(context, srcId, dstId);
forwardPacketToDst(context, dst);
}
}
// Floods the specified packet if permissible.
private void flood(PacketContext context) {
if (topologyService.isBroadcastPoint(topologyService.currentTopology(),
context.inPacket().receivedFrom())) {
packetOut(context, PortNumber.FLOOD);
} else {
context.block();
}
}
// Sends a packet out the specified port.
private void packetOut(PacketContext context, PortNumber portNumber) {
context.treatmentBuilder().setOutput(portNumber);
context.send();
}
private void forwardPacketToDst(PacketContext context, Host dst) {
TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(dst.location().port()).build();
OutboundPacket packet = new DefaultOutboundPacket(dst.location().deviceId(),
treatment, context.inPacket().unparsed());
packetService.emit(packet);
log.info("sending packet: {}", packet);
}
// Install a rule forwarding the packet to the specified port.
private void setUpConnectivity(PacketContext context, HostId srcId, HostId dstId) {
TrafficSelector selector = DefaultTrafficSelector.emptySelector();
TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
HostToHostIntent intent = new HostToHostIntent(appId, srcId, dstId,
selector, treatment);
intentService.submit(intent);
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Sample application that provides simple form of reactive forwarding
* using the intent service.
*/
package org.onosproject.ifwd;
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-intent-perf</artifactId>
<packaging>bundle</packaging>
<description>ONOS intent perf app bundle</description>
<dependencies>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<!-- Required for javadoc generation -->
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptor>src/assembly/bin.xml</descriptor>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<app name="org.onosproject.intentperf" origin="ON.Lab" version="1.1.0"
features="onos-app-intent-perf">
<description>Intent performance application</description>
</app>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<formats>
<format>zip</format>
</formats>
<id>onos</id>
<includeBaseDirectory>false</includeBaseDirectory>
<files>
<file>
<source>src/assembly/app.xml</source>
<destName>app.xml</destName>
</file>
<file>
<source>target/${project.artifactId}-${project.version}.jar</source>
<destName>m2/org/onosproject/${project.artifactId}/${project.version}/${project.artifactId}-${project.version}.jar</destName>
</file>
</files>
</assembly>
\ No newline at end of file
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.intentperf;
import com.google.common.collect.ImmutableList;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.cluster.messaging.ClusterMessage;
import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
import org.onosproject.store.cluster.messaging.MessageSubject;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Collects and distributes performance samples.
*/
@Component(immediate = true)
@Service(value = IntentPerfCollector.class)
public class IntentPerfCollector {
private static final long SAMPLE_TIME_WINDOW_MS = 5_000;
private final Logger log = getLogger(getClass());
private static final int MAX_SAMPLES = 1_000;
private final List<Sample> samples = new LinkedList<>();
private static final MessageSubject SAMPLE = new MessageSubject("intent-perf-sample");
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterCommunicationService communicationService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
protected IntentPerfUi ui;
// Auxiliary structures used to accrue data for normalized time interval
// across all nodes.
private long newestTime;
private Sample overall;
private Sample current;
private ControllerNode[] nodes;
private Map<NodeId, Integer> nodeToIndex;
private NodeId nodeId;
private ExecutorService messageHandlingExecutor;
@Activate
public void activate() {
nodeId = clusterService.getLocalNode().id();
// TODO: replace with shared executor
messageHandlingExecutor = Executors.newSingleThreadExecutor(
groupedThreads("onos/perf", "message-handler"));
communicationService.addSubscriber(SAMPLE, new InternalSampleCollector(),
messageHandlingExecutor);
nodes = clusterService.getNodes().toArray(new ControllerNode[]{});
Arrays.sort(nodes, (a, b) -> a.id().toString().compareTo(b.id().toString()));
nodeToIndex = new HashMap<>();
for (int i = 0; i < nodes.length; i++) {
nodeToIndex.put(nodes[i].id(), i);
}
clearSamples();
log.info("Started");
}
@Deactivate
public void deactivate() {
messageHandlingExecutor.shutdown();
communicationService.removeSubscriber(SAMPLE);
log.info("Stopped");
}
/**
* Clears all previously accumulated data.
*/
public void clearSamples() {
newestTime = 0;
overall = new Sample(0, nodes.length);
current = new Sample(0, nodes.length);
samples.clear();
}
/**
* Records a sample point of data about intent operation rate.
*
* @param overallRate overall rate
* @param currentRate current rate
*/
public void recordSample(double overallRate, double currentRate) {
long now = System.currentTimeMillis();
addSample(now, nodeId, overallRate, currentRate);
broadcastSample(now, nodeId, overallRate, currentRate);
}
/**
* Returns set of node ids as headers.
*
* @return node id headers
*/
public List<String> getSampleHeaders() {
List<String> headers = new ArrayList<>();
for (ControllerNode node : nodes) {
headers.add(node.id().toString());
}
return headers;
}
/**
* Returns set of all accumulated samples normalized to the local set of
* samples.
*
* @return accumulated samples
*/
public synchronized List<Sample> getSamples() {
return ImmutableList.copyOf(samples);
}
/**
* Returns overall throughput performance for each of the cluster nodes.
*
* @return overall intent throughput
*/
public synchronized Sample getOverall() {
return overall;
}
// Records a new sample to our collection of samples
private synchronized void addSample(long time, NodeId nodeId,
double overallRate, double currentRate) {
Sample fullSample = createCurrentSampleIfNeeded(time);
setSampleData(current, nodeId, currentRate);
setSampleData(overall, nodeId, overallRate);
pruneSamplesIfNeeded();
if (fullSample != null && ui != null) {
ui.reportSample(fullSample);
}
}
private Sample createCurrentSampleIfNeeded(long time) {
Sample oldSample = time - newestTime > SAMPLE_TIME_WINDOW_MS || current.isComplete() ? current : null;
if (oldSample != null) {
newestTime = time;
current = new Sample(time, nodes.length);
if (oldSample.time > 0) {
samples.add(oldSample);
}
}
return oldSample;
}
private void setSampleData(Sample sample, NodeId nodeId, double data) {
Integer index = nodeToIndex.get(nodeId);
if (index != null) {
sample.data[index] = data;
}
}
private void pruneSamplesIfNeeded() {
if (samples.size() > MAX_SAMPLES) {
samples.remove(0);
}
}
// Performance data sample.
static class Sample {
final long time;
final double[] data;
public Sample(long time, int nodeCount) {
this.time = time;
this.data = new double[nodeCount];
Arrays.fill(data, -1);
}
public boolean isComplete() {
for (int i = 0; i < data.length; i++) {
if (data[i] < 0) {
return false;
}
}
return true;
}
}
private void broadcastSample(long time, NodeId nodeId, double overallRate, double currentRate) {
String data = String.format("%d|%f|%f", time, overallRate, currentRate);
communicationService.broadcast(new ClusterMessage(nodeId, SAMPLE, data.getBytes()));
}
private class InternalSampleCollector implements ClusterMessageHandler {
@Override
public void handle(ClusterMessage message) {
String[] fields = new String(message.payload()).split("\\|");
log.debug("Received sample from {}: {}", message.sender(), fields);
addSample(Long.parseLong(fields[0]), message.sender(),
Double.parseDouble(fields[1]), Double.parseDouble(fields[2]));
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.intentperf;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.intentperf.IntentPerfCollector.Sample;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* Displays accumulated performance metrics.
*/
@Command(scope = "onos", name = "intent-perf",
description = "Displays accumulated performance metrics")
public class IntentPerfListCommand extends AbstractShellCommand {
@Option(name = "-s", aliases = "--summary", description = "Output just summary",
required = false, multiValued = false)
private boolean summary = false;
@Override
protected void execute() {
if (summary) {
printSummary();
} else {
printSamples();
}
}
private void printSummary() {
IntentPerfCollector collector = get(IntentPerfCollector.class);
List<String> headers = collector.getSampleHeaders();
Sample overall = collector.getOverall();
double total = 0;
print("%12s: %14s", "Node ID", "Overall Rate");
for (int i = 0; i < overall.data.length; i++) {
if (overall.data[i] >= 0) {
print("%12s: %14.2f", headers.get(i), overall.data[i]);
total += overall.data[i];
} else {
print("%12s: %14s", headers.get(i), " ");
}
}
print("%12s: %14.2f", "total", total);
}
private void printSamples() {
IntentPerfCollector collector = get(IntentPerfCollector.class);
List<String> headers = collector.getSampleHeaders();
List<Sample> samples = collector.getSamples();
System.out.print(String.format("%10s ", "Time"));
for (String header : headers) {
System.out.print(String.format("%12s ", header));
}
System.out.println(String.format("%12s", "Total"));
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
for (Sample sample : samples) {
double total = 0;
System.out.print(String.format("%10s ", sdf.format(new Date(sample.time))));
for (int i = 0; i < sample.data.length; i++) {
if (sample.data[i] >= 0) {
System.out.print(String.format("%12.2f ", sample.data[i]));
total += sample.data[i];
} else {
System.out.print(String.format("%12s ", " "));
}
}
System.out.println(String.format("%12.2f", total));
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.intentperf;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
/**
* Starts intent performance test run.
*/
@Command(scope = "onos", name = "intent-perf-start",
description = "Starts intent performance test run")
public class IntentPerfStartCommand extends AbstractShellCommand {
@Override
protected void execute() {
get(IntentPerfInstaller.class).start();
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.intentperf;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
/**
* Stops intent performance test run.
*/
@Command(scope = "onos", name = "intent-perf-stop",
description = "Stops intent performance test run")
public class IntentPerfStopCommand extends AbstractShellCommand {
@Override
protected void execute() {
get(IntentPerfInstaller.class).stop();
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.intentperf;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.intentperf.IntentPerfCollector.Sample;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiExtension;
import org.onosproject.ui.UiExtensionService;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.UiView;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static java.util.Collections.synchronizedSet;
/**
* Mechanism to stream data to the GUI.
*/
@Component(immediate = true, enabled = false)
public class IntentPerfUi {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected UiExtensionService uiExtensionService;
private final Set<StreamingControl> handlers = synchronizedSet(new HashSet<>());
private List<UiView> views = ImmutableList.of(new UiView("intentPerf", "Intent Performance"));
private UiExtension uiExtension = new UiExtension(views, this::newHandlers,
getClass().getClassLoader());
@Activate
protected void activate() {
uiExtensionService.register(uiExtension);
}
@Deactivate
protected void deactivate() {
uiExtensionService.unregister(uiExtension);
}
/**
* Reports a single sample of performance data.
*
* @param sample performance sample
*/
public void reportSample(Sample sample) {
synchronized (handlers) {
handlers.forEach(h -> h.send(sample));
}
}
// Creates and returns session specific message handler.
private Collection<UiMessageHandler> newHandlers() {
return ImmutableList.of(new StreamingControl());
}
// UI Message handlers for turning on/off reporting to a session.
private class StreamingControl extends UiMessageHandler {
private boolean streamingEnabled = false;
protected StreamingControl() {
super(ImmutableSet.of("intentPerfStart", "intentPerfStop"));
}
@Override
public void process(ObjectNode message) {
streamingEnabled = message.path("event").asText("unknown").equals("initPerfStart");
}
@Override
public void init(UiConnection connection, ServiceDirectory directory) {
super.init(connection, directory);
handlers.add(this);
}
@Override
public void destroy() {
super.destroy();
handlers.remove(this);
}
private void send(Sample sample) {
// FIXME: finish this
ObjectNode sn = mapper.createObjectNode()
.put("time", sample.time);
connection().sendMessage("intentPerf", 0, sn);
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Performance test application that induces steady load on the intent subsystem.
*/
package org.onosproject.intentperf;
\ No newline at end of file
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.intentperf.IntentPerfListCommand"/>
</command>
<command>
<action class="org.onosproject.intentperf.IntentPerfStartCommand"/>
</command>
<command>
<action class="org.onosproject.intentperf.IntentPerfStopCommand"/>
</command>
</command-bundle>
</blueprint>
date,value,node
00:55:15,68.38,node1
00:55:15,55.61,node2
00:55:15,74.00,node3
00:55:30,74.20,node1
00:55:30,77.60,node2
00:55:30,74.80,node3
00:55:45,74.60,node1
00:55:45,72.80,node2
00:55:45,77.00,node3
00:56:00,73.60,node1
00:56:00,75.00,node2
00:56:00,76.98,node3
00:56:15,75.82,node1
00:56:15,75.40,node2
00:56:15,76.00,node3
00:56:30,75.60,node1
00:56:30,74.59,node2
00:56:30,74.01,node3
\ No newline at end of file
key,value,date
Group1,37,00:23:00
Group2,12,00:23:00
Group3,46,00:23:00
Group1,32,00:23:05
Group2,19,00:23:05
Group3,42,00:23:05
Group1,45,00:23:10
Group2,16,00:23:10
Group3,44,00:23:10
Group1,24,00:23:15
Group2,52,00:23:15
Group3,64,00:23:15
Group1,34,00:23:20
Group2,62,00:23:20
Group3,74,00:23:20
Group1,34,00:23:25
Group2,62,00:23:25
Group3,74,00:23:25
\ No newline at end of file
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
ONOS GUI -- Intent Perf View -- CSS file
*/
.light #ov-intentPerf {
color: navy;
}
.dark #ov-intentPerf {
color: #1e5e6f;
}
.dark a {
color: #88c;
}
#ov-intentPerf .msg {
color: darkorange;
}
.light #ov-intentPerf .msg {
color: darkorange;
}
.dark #ov-intentPerf .msg {
color: #904e00;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.browser text {
text-anchor: end;
}
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- Intent Performance partial HTML -->
<div id="ov-sample">
<h2> Intent Performance View </h2>
<span class="msg">{{ ctrl.message }}</span>
<div id="intent-perf-chart"></div>
</div>
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
ONOS GUI -- Intent Performance View Module
*/
(function () {
'use strict';
// injected refs
var $log, tbs, flash;
function start() {
//var format = d3.time.format("%m/%d/%y");
var format = d3.time.format("%H:%M:%S");
var samples = [];
var margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var z = d3.scale.category20c();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(d3.time.seconds);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var stack = d3.layout.stack()
.offset("zero")
.values(function(d) { return d.values; })
.x(function(d) { return d.date; })
.y(function(d) { return d.value; });
var nest = d3.nest()
.key(function(d) { return d.key; });
var area = d3.svg.area()
.interpolate("cardinal")
.x(function(d) { return x(d.date); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
function fetchData() {
d3.csv("app/view/intentPerf/data.csv", function (data) {
samples = data;
updateGraph();
});
}
function updateGraph() {
samples.forEach(function(d) {
d.date = format.parse(d.date);
d.value = +d.value;
});
var layers = stack(nest.entries(samples));
x.domain(d3.extent(samples, function(d) { return d.date; }));
y.domain([0, d3.max(samples, function(d) { return d.y0 + d.y; })]);
svg.selectAll(".layer")
.data(layers)
.enter().append("path")
.attr("class", "layer")
.attr("d", function(d) { return area(d.values); })
.style("fill", function(d, i) { return z(i); });
svg.select(".x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select(".y")
.call(yAxis);
console.log('tick');
}
}
start();
// define the controller
angular.module('ovIntentPerf', ['onosUtil'])
.controller('OvIntentPerfCtrl',
['$scope', '$log', 'ToolbarService', 'FlashService',
function ($scope, _$log_, _tbs_, _flash_) {
var self = this
$log = _$log_;
tbs = _tbs_;
flash = _flash_;
self.message = 'Hey there dudes!';
start();
// Clean up on destroyed scope
$scope.$on('$destroy', function () {
});
$log.log('OvIntentPerfCtrl has been created');
}]);
}());
<link rel="stylesheet" href="app/view/intentPerf/intentPerf.css">
<!DOCTYPE html>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<html>
<head>
<title>Dev View</title>
<script src="tp/d3.min.js"></script>
<script src="tp/jquery-2.1.1.min.js"></script>
<link rel="stylesheet" href="app/view/intentPerf/intentPerf.css">
</head>
<body>
<div id="intent-perf-chart" style="width: 1024px; height: 800px"></div>
<script src="app/view/intentPerf/intentPerf.js"></script>
</body>
</html>
\ No newline at end of file
<script src="app/view/intentPerf/intentPerf.js"></script>
......@@ -32,24 +32,17 @@
<description>ONOS sample applications</description>
<modules>
<module>tvue</module>
<module>fwd</module>
<module>ifwd</module>
<module>mobility</module>
<module>proxyarp</module>
<module>config</module>
<module>sdnip</module>
<module>calendar</module>
<module>optical</module>
<module>metrics</module>
<module>oecfg</module>
<module>demo</module>
<module>election</module>
<module>routing</module>
<module>routing-api</module>
<module>bgprouter</module>
<module>intent-perf</module>
<module>database-perf</module>
</modules>
<properties>
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<app name="org.onosproject.app.tvue" origin="ON.Lab" version="1.1.0"
features="onos-app-tvue">
<description>Early prototype GUI (deprecated)</description>
</app>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-tvue</artifactId>
<packaging>bundle</packaging>
<description>ONOS simple topology viewer</description>
<properties>
<web.context>/onos/tvue</web.context>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>1.18.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId>
<version>1.18.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<_wab>src/main/webapp/</_wab>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.osgi.framework,
javax.ws.rs,javax.ws.rs.core,
com.sun.jersey.api.core,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
com.fasterxml.jackson.databind,
com.fasterxml.jackson.databind.node,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.tvue;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.ElementId;
import org.onosproject.net.Host;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyGraph;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.net.topology.TopologyVertex;
import org.onlab.packet.IpAddress;
import org.onlab.rest.BaseResource;
import javax.ws.rs.GET;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.HostId.hostId;
import static org.onosproject.net.PortNumber.portNumber;
/**
* Topology viewer resource.
*/
@javax.ws.rs.Path("topology")
public class TopologyResource extends BaseResource {
@javax.ws.rs.Path("/graph")
@GET
@Produces("application/json")
public Response graph() {
ObjectMapper mapper = new ObjectMapper();
// Fetch the services we'll be using.
DeviceService deviceService = get(DeviceService.class);
HostService hostService = get(HostService.class);
TopologyService topologyService = get(TopologyService.class);
// Fetch the current topology and its graph that we'll use to render.
Topology topo = topologyService.currentTopology();
TopologyGraph graph = topologyService.getGraph(topo);
// Build all interior vertexes, i.e. no end-station hosts yet
ArrayNode vertexesNode = mapper.createArrayNode();
for (TopologyVertex vertex : graph.getVertexes()) {
vertexesNode.add(json(mapper, vertex.deviceId(), 2,
vertex.deviceId().uri().getSchemeSpecificPart(),
deviceService.isAvailable(vertex.deviceId())));
}
// Now scan all links and count number of them between the same devices
// using a normalized link key.
Map<String, AggLink> linkRecords = aggregateLinks();
// Now build all interior edges using the aggregated links.
ArrayNode edgesNode = mapper.createArrayNode();
for (AggLink lr : linkRecords.values()) {
edgesNode.add(json(mapper, lr.links.size(), lr.link.src(), lr.link.dst()));
}
// Merge the exterior and interior vertexes and inject host links as
// the exterior edges.
for (Host host : hostService.getHosts()) {
Set<IpAddress> ipAddresses = host.ipAddresses();
IpAddress ipAddress = ipAddresses.isEmpty() ? null : ipAddresses.iterator().next();
String label = ipAddress != null ? ipAddress.toString() : host.mac().toString();
vertexesNode.add(json(mapper, host.id(), 3, label, true));
edgesNode.add(json(mapper, 1, host.location(), new ConnectPoint(host.id(), portNumber(-1))));
}
// Now put the vertexes and edges into a root node and ship them off
ObjectNode rootNode = mapper.createObjectNode();
rootNode.set("vertexes", vertexesNode);
rootNode.set("edges", edgesNode);
return Response.ok(rootNode.toString()).build();
}
/**
* Returns a JSON array of all paths between the specified hosts.
*
* @param src source host id
* @param dst target host id
* @return JSON array of paths
*/
@javax.ws.rs.Path("/paths/{src}/{dst}")
@GET
@Produces("application/json")
public Response paths(@PathParam("src") String src, @PathParam("dst") String dst) {
ObjectMapper mapper = new ObjectMapper();
PathService pathService = get(PathService.class);
Set<Path> paths = pathService.getPaths(elementId(src), elementId(dst));
ArrayNode pathsNode = mapper.createArrayNode();
for (Path path : paths) {
pathsNode.add(json(mapper, path));
}
// Now put the vertexes and edges into a root node and ship them off
ObjectNode rootNode = mapper.createObjectNode();
rootNode.set("paths", pathsNode);
return Response.ok(rootNode.toString()).build();
}
// Creates either device ID or host ID as appropriate.
private ElementId elementId(String id) {
return id.startsWith("nic:") ? hostId(id) : deviceId(id);
}
// Scan all links and counts number of them between the same devices
// using a normalized link key.
private Map<String, AggLink> aggregateLinks() {
Map<String, AggLink> aggLinks = new HashMap<>();
LinkService linkService = get(LinkService.class);
for (Link link : linkService.getLinks()) {
String key = key(link);
AggLink lr = aggLinks.get(key);
if (lr == null) {
lr = new AggLink(key);
aggLinks.put(key, lr);
}
lr.addLink(link);
}
return aggLinks;
}
// Produces JSON for a graph vertex.
private ObjectNode json(ObjectMapper mapper, ElementId id, int group,
String label, boolean isOnline) {
return mapper.createObjectNode()
.put("name", id.toString())
.put("label", label)
.put("group", group)
.put("online", isOnline);
}
// Produces JSON for a graph edge.
private ObjectNode json(ObjectMapper mapper, int count,
ConnectPoint src, ConnectPoint dst) {
return json(mapper, count, id(src), id(dst));
}
// Produces JSON for a graph edge.
private ObjectNode json(ObjectMapper mapper, int count, String src, String dst) {
return mapper.createObjectNode()
.put("source", src).put("target", dst).put("value", count);
}
// Produces JSON representation of a network path.
private ArrayNode json(ObjectMapper mapper, Path path) {
ArrayNode pathNode = mapper.createArrayNode();
for (Link link : path.links()) {
ObjectNode linkNode = mapper.createObjectNode()
.put("src", id(link.src()))
.put("dst", id(link.dst()));
pathNode.add(linkNode);
}
return pathNode;
}
// Aggregate link of all links between the same devices regardless of
// their direction.
private class AggLink {
Link link; // representative links
final String key;
final Set<Link> links = new HashSet<>();
AggLink(String key) {
this.key = key;
}
void addLink(Link link) {
links.add(link);
if (this.link == null) {
this.link = link;
}
}
}
// Returns a canonical key for the specified link.
static String key(Link link) {
String s = id(link.src());
String d = id(link.dst());
return s.compareTo(d) > 0 ? d + s : s + d;
}
// Returns a formatted string for the element associated with the given
// connection point.
private static String id(ConnectPoint cp) {
return cp.elementId().toString();
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Sample topology viewer application.
*/
package org.onosproject.tvue;
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="ONOS" version="2.5">
<display-name>ONOS GUI</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
</init-param>
<init-param>
<!--param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.onosproject.tvue</param-value-->
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>org.onosproject.tvue.TopologyResource</param-value>
</init-param>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Service</servlet-name>
<url-pattern>/rs/*</url-pattern>
</servlet-mapping>
</web-app>
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.