Madan Jampani

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Showing 117 changed files with 1603 additions and 351 deletions
...@@ -8,5 +8,6 @@ ...@@ -8,5 +8,6 @@
8 .checkstyle 8 .checkstyle
9 target 9 target
10 *.iml 10 *.iml
11 +*.pyc
11 dependency-reduced-pom.xml 12 dependency-reduced-pom.xml
12 .idea 13 .idea
......
...@@ -16,14 +16,24 @@ ...@@ -16,14 +16,24 @@
16 package org.onlab.onos.calendar; 16 package org.onlab.onos.calendar;
17 17
18 import java.net.URI; 18 import java.net.URI;
19 +import java.util.concurrent.CountDownLatch;
20 +import java.util.concurrent.TimeUnit;
21 +
19 import org.onlab.onos.net.ConnectPoint; 22 import org.onlab.onos.net.ConnectPoint;
20 import org.onlab.onos.net.DeviceId; 23 import org.onlab.onos.net.DeviceId;
24 +import org.onlab.onos.net.intent.Intent;
25 +import org.onlab.onos.net.intent.IntentEvent;
26 +import org.onlab.onos.net.intent.IntentId;
27 +import org.onlab.onos.net.intent.IntentListener;
21 import org.onlab.onos.net.intent.IntentService; 28 import org.onlab.onos.net.intent.IntentService;
29 +import org.onlab.onos.net.intent.IntentState;
22 import org.onlab.rest.BaseResource; 30 import org.onlab.rest.BaseResource;
31 +
23 import javax.ws.rs.POST; 32 import javax.ws.rs.POST;
24 import javax.ws.rs.DELETE; 33 import javax.ws.rs.DELETE;
25 import javax.ws.rs.PathParam; 34 import javax.ws.rs.PathParam;
26 import javax.ws.rs.core.Response; 35 import javax.ws.rs.core.Response;
36 +
27 import org.onlab.onos.core.ApplicationId; 37 import org.onlab.onos.core.ApplicationId;
28 import org.onlab.onos.core.CoreService; 38 import org.onlab.onos.core.CoreService;
29 import org.onlab.onos.net.flow.DefaultTrafficSelector; 39 import org.onlab.onos.net.flow.DefaultTrafficSelector;
...@@ -31,10 +41,15 @@ import org.onlab.onos.net.flow.TrafficSelector; ...@@ -31,10 +41,15 @@ import org.onlab.onos.net.flow.TrafficSelector;
31 import org.onlab.onos.net.flow.TrafficTreatment; 41 import org.onlab.onos.net.flow.TrafficTreatment;
32 import org.onlab.onos.net.intent.PointToPointIntent; 42 import org.onlab.onos.net.intent.PointToPointIntent;
33 import org.onlab.packet.Ethernet; 43 import org.onlab.packet.Ethernet;
44 +
34 import static org.onlab.onos.net.PortNumber.portNumber; 45 import static org.onlab.onos.net.PortNumber.portNumber;
35 import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; 46 import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
36 47
48 +import static org.onlab.onos.net.intent.IntentState.FAILED;
49 +import static org.onlab.onos.net.intent.IntentState.INSTALLED;
50 +import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
37 import static org.slf4j.LoggerFactory.getLogger; 51 import static org.slf4j.LoggerFactory.getLogger;
52 +
38 import org.slf4j.Logger; 53 import org.slf4j.Logger;
39 54
40 /** 55 /**
...@@ -44,6 +59,7 @@ import org.slf4j.Logger; ...@@ -44,6 +59,7 @@ import org.slf4j.Logger;
44 public class BandwidthCalendarResource extends BaseResource { 59 public class BandwidthCalendarResource extends BaseResource {
45 60
46 private static final Logger log = getLogger(BandwidthCalendarResource.class); 61 private static final Logger log = getLogger(BandwidthCalendarResource.class);
62 + private static final long TIMEOUT = 5; // seconds
47 63
48 @javax.ws.rs.Path("/{src}/{dst}/{srcPort}/{dstPort}/{bandwidth}") 64 @javax.ws.rs.Path("/{src}/{dst}/{srcPort}/{dstPort}/{bandwidth}")
49 @POST 65 @POST
...@@ -55,7 +71,7 @@ public class BandwidthCalendarResource extends BaseResource { ...@@ -55,7 +71,7 @@ public class BandwidthCalendarResource extends BaseResource {
55 71
56 log.info("Receiving Create Intent request..."); 72 log.info("Receiving Create Intent request...");
57 log.info("Path Constraints: Src = {} SrcPort = {} Dest = {} DestPort = {} BW = {}", 73 log.info("Path Constraints: Src = {} SrcPort = {} Dest = {} DestPort = {} BW = {}",
58 - src, srcPort, dst, dstPort, bandwidth); 74 + src, srcPort, dst, dstPort, bandwidth);
59 75
60 IntentService service = get(IntentService.class); 76 IntentService service = get(IntentService.class);
61 77
...@@ -66,36 +82,50 @@ public class BandwidthCalendarResource extends BaseResource { ...@@ -66,36 +82,50 @@ public class BandwidthCalendarResource extends BaseResource {
66 TrafficTreatment treatment = builder().build(); 82 TrafficTreatment treatment = builder().build();
67 83
68 PointToPointIntent intentP2P = 84 PointToPointIntent intentP2P =
69 - new PointToPointIntent(appId(), selector, treatment, 85 + new PointToPointIntent(appId(), selector, treatment,
70 - srcPoint, dstPoint); 86 + srcPoint, dstPoint);
71 - service.submit(intentP2P);
72 - log.info("Submitted Calendar App intent: src = " + src + "dest = " + dst
73 - + "srcPort = " + srcPort + "destPort" + dstPort + "intentID = " + intentP2P.id().toString());
74 - String reply = intentP2P.id().toString() + "\n";
75 87
76 - return Response.ok(reply).build(); 88 + CountDownLatch latch = new CountDownLatch(1);
89 + InternalIntentListener listener = new InternalIntentListener(intentP2P, service, latch);
90 + service.addListener(listener);
91 + service.submit(intentP2P);
92 + try {
93 + if (latch.await(TIMEOUT, TimeUnit.SECONDS)) {
94 + log.info("Submitted Calendar App intent: src = {}; dst = {}; " +
95 + "srcPort = {}; dstPort = {}; intentID = {}",
96 + src, dst, srcPort, dstPort, intentP2P.id());
97 + String reply = intentP2P.id() + " " + listener.getState() + "\n";
98 + return Response.ok(reply).build();
99 + }
100 + } catch (InterruptedException e) {
101 + log.warn("Interrupted while waiting for intent {} status", intentP2P.id());
102 + }
103 + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
77 } 104 }
78 105
79 @javax.ws.rs.Path("/cancellation/{intentId}") 106 @javax.ws.rs.Path("/cancellation/{intentId}")
80 @DELETE 107 @DELETE
81 public Response withdrawIntent(@PathParam("intentId") String intentId) { 108 public Response withdrawIntent(@PathParam("intentId") String intentId) {
82 - 109 + log.info("Receiving Teardown request for {}", intentId);
83 - log.info("Receiving Teardown request..."); 110 + IntentService service = get(IntentService.class);
84 - log.info("Withdraw intentId = {} ", intentId); 111 + Intent intent = service.getIntent(IntentId.valueOf(Long.parseLong(intentId)));
85 - 112 + if (intent != null) {
86 - String reply = "ok\n"; 113 + service.withdraw(intent);
87 - return Response.ok(reply).build(); 114 + String reply = "ok\n";
115 + return Response.ok(reply).build();
116 + }
117 + return Response.status(Response.Status.NOT_FOUND).build();
88 } 118 }
89 119
90 @javax.ws.rs.Path("/modification/{intentId}/{bandwidth}") 120 @javax.ws.rs.Path("/modification/{intentId}/{bandwidth}")
91 @POST 121 @POST
92 public Response modifyBandwidth(@PathParam("intentId") String intentId, 122 public Response modifyBandwidth(@PathParam("intentId") String intentId,
93 - @PathParam("bandwidth") String bandwidth) { 123 + @PathParam("bandwidth") String bandwidth) {
94 124
95 log.info("Receiving Modify request..."); 125 log.info("Receiving Modify request...");
96 log.info("Modify bw for intentId = {} with new bandwidth = {}", intentId, bandwidth); 126 log.info("Modify bw for intentId = {} with new bandwidth = {}", intentId, bandwidth);
97 127
98 - String reply = "ok\n"; 128 + String reply = "ok\n";
99 return Response.ok(reply).build(); 129 return Response.ok(reply).build();
100 } 130 }
101 131
...@@ -115,4 +145,34 @@ public class BandwidthCalendarResource extends BaseResource { ...@@ -115,4 +145,34 @@ public class BandwidthCalendarResource extends BaseResource {
115 protected ApplicationId appId() { 145 protected ApplicationId appId() {
116 return get(CoreService.class).registerApplication("org.onlab.onos.calendar"); 146 return get(CoreService.class).registerApplication("org.onlab.onos.calendar");
117 } 147 }
148 +
149 + // Auxiliary listener to wait until the given intent reaches the installed or failed states.
150 + private final class InternalIntentListener implements IntentListener {
151 + private final Intent intent;
152 + private final IntentService service;
153 + private final CountDownLatch latch;
154 + private IntentState state;
155 +
156 + private InternalIntentListener(Intent intent, IntentService service,
157 + CountDownLatch latch) {
158 + this.intent = intent;
159 + this.service = service;
160 + this.latch = latch;
161 + }
162 +
163 + @Override
164 + public void event(IntentEvent event) {
165 + if (event.subject().equals(intent)) {
166 + state = service.getIntentState(intent.id());
167 + if (state == INSTALLED || state == FAILED || state == WITHDRAWN) {
168 + latch.countDown();
169 + }
170 + service.removeListener(this);
171 + }
172 + }
173 +
174 + public IntentState getState() {
175 + return state;
176 + }
177 + }
118 } 178 }
......
...@@ -50,7 +50,10 @@ public class NetworkConfigReader { ...@@ -50,7 +50,10 @@ public class NetworkConfigReader {
50 50
51 private final Logger log = getLogger(getClass()); 51 private final Logger log = getLogger(getClass());
52 52
53 - private static final String DEFAULT_CONFIG_FILE = "config/addresses.json"; 53 + // Current working dir seems to be /opt/onos/apache-karaf-3.0.2
54 + // TODO: Set the path to /opt/onos/config
55 + private static final String CONFIG_DIR = "../config";
56 + private static final String DEFAULT_CONFIG_FILE = "addresses.json";
54 private String configFileName = DEFAULT_CONFIG_FILE; 57 private String configFileName = DEFAULT_CONFIG_FILE;
55 58
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -60,52 +63,9 @@ public class NetworkConfigReader { ...@@ -60,52 +63,9 @@ public class NetworkConfigReader {
60 protected void activate() { 63 protected void activate() {
61 log.info("Started network config reader"); 64 log.info("Started network config reader");
62 65
63 - log.info("Config file set to {}", configFileName);
64 -
65 AddressConfiguration config = readNetworkConfig(); 66 AddressConfiguration config = readNetworkConfig();
66 -
67 if (config != null) { 67 if (config != null) {
68 - for (AddressEntry entry : config.getAddresses()) { 68 + applyNetworkConfig(config);
69 -
70 - ConnectPoint cp = new ConnectPoint(
71 - DeviceId.deviceId(dpidToUri(entry.getDpid())),
72 - PortNumber.portNumber(entry.getPortNumber()));
73 -
74 - Set<InterfaceIpAddress> interfaceIpAddresses = new HashSet<>();
75 -
76 - for (String strIp : entry.getIpAddresses()) {
77 - // Get the IP address and the subnet mask length
78 - try {
79 - String[] splits = strIp.split("/");
80 - if (splits.length != 2) {
81 - throw new IllegalArgumentException("Invalid IP address and prefix length format");
82 - }
83 - // NOTE: IpPrefix will mask-out the bits after the prefix length.
84 - IpPrefix subnet = IpPrefix.valueOf(strIp);
85 - IpAddress addr = IpAddress.valueOf(splits[0]);
86 - InterfaceIpAddress ia =
87 - new InterfaceIpAddress(addr, subnet);
88 - interfaceIpAddresses.add(ia);
89 - } catch (IllegalArgumentException e) {
90 - log.warn("Bad format for IP address in config: {}", strIp);
91 - }
92 - }
93 -
94 - MacAddress macAddress = null;
95 - if (entry.getMacAddress() != null) {
96 - try {
97 - macAddress = MacAddress.valueOf(entry.getMacAddress());
98 - } catch (IllegalArgumentException e) {
99 - log.warn("Bad format for MAC address in config: {}",
100 - entry.getMacAddress());
101 - }
102 - }
103 -
104 - PortAddresses addresses = new PortAddresses(cp,
105 - interfaceIpAddresses, macAddress);
106 -
107 - hostAdminService.bindAddressesToPort(addresses);
108 - }
109 } 69 }
110 } 70 }
111 71
...@@ -114,12 +74,17 @@ public class NetworkConfigReader { ...@@ -114,12 +74,17 @@ public class NetworkConfigReader {
114 log.info("Stopped"); 74 log.info("Stopped");
115 } 75 }
116 76
77 + /**
78 + * Reads the network configuration.
79 + *
80 + * @return the network configuration on success, otherwise null
81 + */
117 private AddressConfiguration readNetworkConfig() { 82 private AddressConfiguration readNetworkConfig() {
118 - File configFile = new File(configFileName); 83 + File configFile = new File(CONFIG_DIR, configFileName);
119 -
120 ObjectMapper mapper = new ObjectMapper(); 84 ObjectMapper mapper = new ObjectMapper();
121 85
122 try { 86 try {
87 + log.info("Loading config: {}", configFile.getAbsolutePath());
123 AddressConfiguration config = 88 AddressConfiguration config =
124 mapper.readValue(configFile, AddressConfiguration.class); 89 mapper.readValue(configFile, AddressConfiguration.class);
125 90
...@@ -127,12 +92,58 @@ public class NetworkConfigReader { ...@@ -127,12 +92,58 @@ public class NetworkConfigReader {
127 } catch (FileNotFoundException e) { 92 } catch (FileNotFoundException e) {
128 log.warn("Configuration file not found: {}", configFileName); 93 log.warn("Configuration file not found: {}", configFileName);
129 } catch (IOException e) { 94 } catch (IOException e) {
130 - log.error("Unable to read config from file:", e); 95 + log.error("Error loading configuration", e);
131 } 96 }
132 97
133 return null; 98 return null;
134 } 99 }
135 100
101 + /**
102 + * Applies the network configuration.
103 + *
104 + * @param config the network configuration to apply
105 + */
106 + private void applyNetworkConfig(AddressConfiguration config) {
107 + for (AddressEntry entry : config.getAddresses()) {
108 + ConnectPoint cp = new ConnectPoint(
109 + DeviceId.deviceId(dpidToUri(entry.getDpid())),
110 + PortNumber.portNumber(entry.getPortNumber()));
111 +
112 + Set<InterfaceIpAddress> interfaceIpAddresses = new HashSet<>();
113 + for (String strIp : entry.getIpAddresses()) {
114 + // Get the IP address and the subnet mask length
115 + try {
116 + String[] splits = strIp.split("/");
117 + if (splits.length != 2) {
118 + throw new IllegalArgumentException("Invalid IP address and prefix length format");
119 + }
120 + // NOTE: IpPrefix will mask-out the bits after the prefix length.
121 + IpPrefix subnet = IpPrefix.valueOf(strIp);
122 + IpAddress addr = IpAddress.valueOf(splits[0]);
123 + InterfaceIpAddress ia =
124 + new InterfaceIpAddress(addr, subnet);
125 + interfaceIpAddresses.add(ia);
126 + } catch (IllegalArgumentException e) {
127 + log.warn("Bad format for IP address in config: {}", strIp);
128 + }
129 + }
130 +
131 + MacAddress macAddress = null;
132 + if (entry.getMacAddress() != null) {
133 + try {
134 + macAddress = MacAddress.valueOf(entry.getMacAddress());
135 + } catch (IllegalArgumentException e) {
136 + log.warn("Bad format for MAC address in config: {}",
137 + entry.getMacAddress());
138 + }
139 + }
140 +
141 + PortAddresses addresses = new PortAddresses(cp,
142 + interfaceIpAddresses, macAddress);
143 + hostAdminService.bindAddressesToPort(addresses);
144 + }
145 + }
146 +
136 private static String dpidToUri(String dpid) { 147 private static String dpidToUri(String dpid) {
137 return "of:" + dpid.replace(":", ""); 148 return "of:" + dpid.replace(":", "");
138 } 149 }
......
1 -{
2 - "interfaces" : [
3 - {
4 - "dpid" : "00:00:00:00:00:00:01",
5 - "port" : "1",
6 - "ips" : ["192.168.10.101/24"],
7 - "mac" : "00:00:00:11:22:33"
8 - },
9 - {
10 - "dpid" : "00:00:00:00:00:00:02",
11 - "port" : "1",
12 - "ips" : ["192.168.20.101/24", "192.168.30.101/24"]
13 - },
14 - {
15 - "dpid" : "00:00:00:00:00:00:03",
16 - "port" : "1",
17 - "ips" : ["10.1.0.1/16"],
18 - "mac" : "00:00:00:00:00:01"
19 - }
20 - ]
21 -}
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2014 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<project xmlns="http://maven.apache.org/POM/4.0.0"
18 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 + <modelVersion>4.0.0</modelVersion>
21 +
22 + <parent>
23 + <groupId>org.onlab.onos</groupId>
24 + <artifactId>onos-apps</artifactId>
25 + <version>1.0.0-SNAPSHOT</version>
26 + <relativePath>../pom.xml</relativePath>
27 + </parent>
28 +
29 + <artifactId>onos-app-demo</artifactId>
30 + <packaging>bundle</packaging>
31 +
32 + <description>ONOS demo app bundle</description>
33 +
34 + <properties>
35 + <web.context>/onos/demo</web.context>
36 + </properties>
37 +
38 + <dependencies>
39 + <dependency>
40 + <groupId>org.osgi</groupId>
41 + <artifactId>org.osgi.compendium</artifactId>
42 + </dependency>
43 + <dependency>
44 + <groupId>org.onlab.onos</groupId>
45 + <artifactId>onlab-rest</artifactId>
46 + <version>${project.version}</version>
47 + </dependency>
48 +
49 + <dependency>
50 + <groupId>org.onlab.onos</groupId>
51 + <artifactId>onos-rest</artifactId>
52 + <version>${project.version}</version>
53 + </dependency>
54 +
55 + <dependency>
56 + <groupId>com.sun.jersey</groupId>
57 + <artifactId>jersey-servlet</artifactId>
58 + </dependency>
59 + <dependency>
60 + <groupId>com.sun.jersey.jersey-test-framework</groupId>
61 + <artifactId>jersey-test-framework-core</artifactId>
62 + <version>1.18.1</version>
63 + <scope>test</scope>
64 + </dependency>
65 + <dependency>
66 + <groupId>com.sun.jersey.jersey-test-framework</groupId>
67 + <artifactId>jersey-test-framework-grizzly2</artifactId>
68 + <version>1.18.1</version>
69 + <scope>test</scope>
70 + </dependency>
71 +
72 + <dependency>
73 + <groupId>com.fasterxml.jackson.core</groupId>
74 + <artifactId>jackson-databind</artifactId>
75 + </dependency>
76 +
77 + <dependency>
78 + <groupId>com.fasterxml.jackson.core</groupId>
79 + <artifactId>jackson-annotations</artifactId>
80 + </dependency>
81 +
82 + <dependency>
83 + <groupId>org.osgi</groupId>
84 + <artifactId>org.osgi.core</artifactId>
85 + </dependency>
86 + </dependencies>
87 +
88 + <build>
89 + <plugins>
90 + <plugin>
91 + <groupId>org.apache.felix</groupId>
92 + <artifactId>maven-bundle-plugin</artifactId>
93 + <extensions>true</extensions>
94 + <configuration>
95 + <instructions>
96 + <_wab>src/main/webapp/</_wab>
97 + <Bundle-SymbolicName>
98 + ${project.groupId}.${project.artifactId}
99 + </Bundle-SymbolicName>
100 + <Import-Package>
101 + org.slf4j,
102 + org.osgi.framework,
103 + javax.ws.rs,javax.ws.rs.core,
104 + com.sun.jersey.api.core,
105 + com.sun.jersey.spi.container.servlet,
106 + com.sun.jersey.server.impl.container.servlet,
107 + com.fasterxml.jackson.databind,
108 + com.fasterxml.jackson.databind.node,
109 + com.google.common.*,
110 + org.onlab.packet.*,
111 + org.onlab.rest.*,
112 + org.onlab.onos.*
113 + </Import-Package>
114 + <Web-ContextPath>${web.context}</Web-ContextPath>
115 + </instructions>
116 + </configuration>
117 + </plugin>
118 + </plugins>
119 + </build>
120 +
121 +</project>
1 +package org.onlab.onos.demo;
2 +
3 +/**
4 + * Simple demo api interface.
5 + */
6 +public interface DemoAPI {
7 +
8 + enum InstallType { MESH, RANDOM };
9 +
10 + /**
11 + * Installs intents based on the installation type.
12 + * @param type the installation type.
13 + */
14 + void setup(InstallType type);
15 +
16 + /**
17 + * Uninstalls all existing intents.
18 + */
19 + void tearDown();
20 +
21 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onlab.onos.demo;
17 +
18 +import com.google.common.collect.Lists;
19 +import com.google.common.util.concurrent.ThreadFactoryBuilder;
20 +import org.apache.felix.scr.annotations.Activate;
21 +import org.apache.felix.scr.annotations.Component;
22 +import org.apache.felix.scr.annotations.Deactivate;
23 +import org.apache.felix.scr.annotations.Reference;
24 +import org.apache.felix.scr.annotations.ReferenceCardinality;
25 +import org.apache.felix.scr.annotations.Service;
26 +import org.onlab.onos.core.ApplicationId;
27 +import org.onlab.onos.core.CoreService;
28 +import org.onlab.onos.net.Host;
29 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
30 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
31 +import org.onlab.onos.net.flow.TrafficSelector;
32 +import org.onlab.onos.net.flow.TrafficTreatment;
33 +import org.onlab.onos.net.host.HostService;
34 +import org.onlab.onos.net.intent.HostToHostIntent;
35 +import org.onlab.onos.net.intent.Intent;
36 +import org.onlab.onos.net.intent.IntentService;
37 +import org.slf4j.Logger;
38 +
39 +
40 +import java.util.HashSet;
41 +import java.util.List;
42 +import java.util.Set;
43 +import java.util.concurrent.ExecutorService;
44 +import java.util.concurrent.Executors;
45 +
46 +import static org.slf4j.LoggerFactory.getLogger;
47 +
48 +/**
49 + * Application to set up demos.
50 + */
51 +@Component(immediate = true)
52 +@Service
53 +public class DemoInstaller implements DemoAPI {
54 +
55 + private final Logger log = getLogger(getClass());
56 +
57 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 + protected CoreService coreService;
59 +
60 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 + protected IntentService intentService;
62 +
63 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 + protected HostService hostService;
65 +
66 + private ExecutorService worker;
67 +
68 + private ApplicationId appId;
69 +
70 + private final Set<Intent> existingIntents = new HashSet<>();
71 +
72 +
73 +
74 + @Activate
75 + public void activate() {
76 + appId = coreService.registerApplication("org.onlab.onos.demo.installer");
77 + worker = Executors.newFixedThreadPool(1,
78 + new ThreadFactoryBuilder()
79 + .setNameFormat("demo-app-worker")
80 + .build());
81 + log.info("Started with Application ID {}", appId.id());
82 + }
83 +
84 + @Deactivate
85 + public void deactivate() {
86 + worker.shutdownNow();
87 + log.info("Stopped");
88 + }
89 +
90 + @Override
91 + public void setup(InstallType type) {
92 + switch (type) {
93 + case MESH:
94 + log.debug("Installing mesh intents");
95 + worker.execute(new MeshInstaller());
96 + break;
97 + case RANDOM:
98 + throw new IllegalArgumentException("Not yet implemented.");
99 + default:
100 + throw new IllegalArgumentException("What is it you want exactly?");
101 + }
102 + }
103 +
104 + @Override
105 + public void tearDown() {
106 + worker.submit(new UnInstaller());
107 + }
108 +
109 +
110 + private class MeshInstaller implements Runnable {
111 +
112 + @Override
113 + public void run() {
114 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
115 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
116 +
117 + List<Host> hosts = Lists.newArrayList(hostService.getHosts());
118 + while (!hosts.isEmpty()) {
119 + Host src = hosts.remove(0);
120 + for (Host dst : hosts) {
121 + HostToHostIntent intent = new HostToHostIntent(appId, src.id(), dst.id(),
122 + selector, treatment,
123 + null);
124 + existingIntents.add(intent);
125 + intentService.submit(intent);
126 + }
127 + }
128 + }
129 + }
130 +
131 +
132 + private class UnInstaller implements Runnable {
133 + @Override
134 + public void run() {
135 + for (Intent i : existingIntents) {
136 + intentService.withdraw(i);
137 + }
138 + }
139 + }
140 +}
141 +
142 +
1 +package org.onlab.onos.demo;
2 +
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import org.onlab.rest.BaseResource;
6 +
7 +import javax.ws.rs.Consumes;
8 +import javax.ws.rs.GET;
9 +import javax.ws.rs.POST;
10 +import javax.ws.rs.Path;
11 +import javax.ws.rs.Produces;
12 +import javax.ws.rs.core.MediaType;
13 +import javax.ws.rs.core.Response;
14 +import java.io.IOException;
15 +import java.io.InputStream;
16 +
17 +/**
18 + * Rest API for demos.
19 + */
20 +@Path("intents")
21 +public class DemoResource extends BaseResource {
22 +
23 +
24 + @POST
25 + @Path("setup")
26 + @Consumes(MediaType.APPLICATION_JSON)
27 + @Produces(MediaType.APPLICATION_JSON)
28 + public Response setup(InputStream input) throws IOException {
29 + ObjectMapper mapper = new ObjectMapper();
30 + JsonNode cfg = mapper.readTree(input);
31 + if (!cfg.has("type")) {
32 + return Response.status(Response.Status.BAD_REQUEST)
33 + .entity("Expected type field containing either mesh or random.").build();
34 + }
35 +
36 + DemoAPI.InstallType type = DemoAPI.InstallType.valueOf(
37 + cfg.get("type").asText().toUpperCase());
38 + DemoAPI demo = get(DemoAPI.class);
39 + demo.setup(type);
40 +
41 + return Response.ok(mapper.createObjectNode().toString()).build();
42 + }
43 +
44 + @GET
45 + @Path("teardown")
46 + @Produces(MediaType.APPLICATION_JSON)
47 + public Response tearDown() throws IOException {
48 + ObjectMapper mapper = new ObjectMapper();
49 + DemoAPI demo = get(DemoAPI.class);
50 + demo.tearDown();
51 + return Response.ok(mapper.createObjectNode().toString()).build();
52 + }
53 +
54 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/**
18 + * Demo applications live here.
19 + */
20 +package org.onlab.onos.demo;
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2014 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
18 + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
19 + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
20 + id="ONOS" version="2.5">
21 + <display-name>ONOS DEMO APP API v1.0</display-name>
22 +
23 + <servlet>
24 + <servlet-name>JAX-RS Service</servlet-name>
25 + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
26 + <init-param>
27 + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
28 + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
29 + </init-param>
30 + <init-param>
31 + <param-name>com.sun.jersey.config.property.classnames</param-name>
32 + <param-value>
33 + org.onlab.onos.demo.DemoResource
34 + </param-value>
35 + </init-param>
36 + <load-on-startup>1</load-on-startup>
37 + </servlet>
38 +
39 + <servlet-mapping>
40 + <servlet-name>JAX-RS Service</servlet-name>
41 + <url-pattern>/*</url-pattern>
42 + </servlet-mapping>
43 +
44 +</web-app>
...\ No newline at end of file ...\ No newline at end of file
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
44 <module>optical</module> 44 <module>optical</module>
45 <module>metrics</module> 45 <module>metrics</module>
46 <module>oecfg</module> 46 <module>oecfg</module>
47 + <module>demo</module>
47 </modules> 48 </modules>
48 49
49 <properties> 50 <properties>
......
...@@ -37,24 +37,31 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -37,24 +37,31 @@ import com.fasterxml.jackson.databind.ObjectMapper;
37 */ 37 */
38 public class SdnIpConfigReader implements SdnIpConfigService { 38 public class SdnIpConfigReader implements SdnIpConfigService {
39 39
40 - private static final Logger log = LoggerFactory.getLogger(SdnIpConfigReader.class); 40 + private final Logger log = LoggerFactory.getLogger(getClass());
41 41
42 - private static final String DEFAULT_CONFIG_FILE = "config/sdnip.json"; 42 + // Current working dir seems to be /opt/onos/apache-karaf-3.0.2
43 + // TODO: Set the path to /opt/onos/config
44 + private static final String CONFIG_DIR = "../config";
45 + private static final String DEFAULT_CONFIG_FILE = "sdnip.json";
43 private String configFileName = DEFAULT_CONFIG_FILE; 46 private String configFileName = DEFAULT_CONFIG_FILE;
47 +
44 private Map<String, BgpSpeaker> bgpSpeakers = new ConcurrentHashMap<>(); 48 private Map<String, BgpSpeaker> bgpSpeakers = new ConcurrentHashMap<>();
45 private Map<IpAddress, BgpPeer> bgpPeers = new ConcurrentHashMap<>(); 49 private Map<IpAddress, BgpPeer> bgpPeers = new ConcurrentHashMap<>();
46 50
47 /** 51 /**
48 - * Reads the info contained in the configuration file. 52 + * Reads SDN-IP related information contained in the configuration file.
49 * 53 *
50 - * @param configFilename The name of configuration file for SDN-IP application. 54 + * @param configFilename the name of the configuration file for the SDN-IP
55 + * application
51 */ 56 */
52 private void readConfiguration(String configFilename) { 57 private void readConfiguration(String configFilename) {
53 - File gatewaysFile = new File(configFilename); 58 + File configFile = new File(CONFIG_DIR, configFilename);
54 ObjectMapper mapper = new ObjectMapper(); 59 ObjectMapper mapper = new ObjectMapper();
55 60
56 try { 61 try {
57 - Configuration config = mapper.readValue(gatewaysFile, Configuration.class); 62 + log.info("Loading config: {}", configFile.getAbsolutePath());
63 + Configuration config = mapper.readValue(configFile,
64 + Configuration.class);
58 for (BgpSpeaker speaker : config.getBgpSpeakers()) { 65 for (BgpSpeaker speaker : config.getBgpSpeakers()) {
59 bgpSpeakers.put(speaker.name(), speaker); 66 bgpSpeakers.put(speaker.name(), speaker);
60 } 67 }
...@@ -64,13 +71,11 @@ public class SdnIpConfigReader implements SdnIpConfigService { ...@@ -64,13 +71,11 @@ public class SdnIpConfigReader implements SdnIpConfigService {
64 } catch (FileNotFoundException e) { 71 } catch (FileNotFoundException e) {
65 log.warn("Configuration file not found: {}", configFileName); 72 log.warn("Configuration file not found: {}", configFileName);
66 } catch (IOException e) { 73 } catch (IOException e) {
67 - log.error("Error reading JSON file", e); 74 + log.error("Error loading configuration", e);
68 } 75 }
69 } 76 }
70 77
71 public void init() { 78 public void init() {
72 - log.debug("Config file set to {}", configFileName);
73 -
74 readConfiguration(configFileName); 79 readConfiguration(configFileName);
75 } 80 }
76 81
......
1 -ONOS looks for these config files by default in $KARAF_LOG/config/
...\ No newline at end of file ...\ No newline at end of file
1 +The SDN-IP configuration files should be copied to directory
2 + $ONOS_HOME/tools/package/config
3 +
4 +After deployment and starting up the ONOS cluster, ONOS looks for these
5 +configuration files in /opt/onos/config on each cluster member.
......
...@@ -27,6 +27,7 @@ import org.onlab.onos.net.intent.constraint.BandwidthConstraint; ...@@ -27,6 +27,7 @@ import org.onlab.onos.net.intent.constraint.BandwidthConstraint;
27 import org.onlab.onos.net.intent.constraint.LambdaConstraint; 27 import org.onlab.onos.net.intent.constraint.LambdaConstraint;
28 import org.onlab.onos.net.resource.Bandwidth; 28 import org.onlab.onos.net.resource.Bandwidth;
29 import org.onlab.packet.Ethernet; 29 import org.onlab.packet.Ethernet;
30 +import org.onlab.packet.IpPrefix;
30 import org.onlab.packet.MacAddress; 31 import org.onlab.packet.MacAddress;
31 32
32 import static com.google.common.base.Strings.isNullOrEmpty; 33 import static com.google.common.base.Strings.isNullOrEmpty;
...@@ -48,6 +49,26 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { ...@@ -48,6 +49,26 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
48 required = false, multiValued = false) 49 required = false, multiValued = false)
49 private String ethTypeString = ""; 50 private String ethTypeString = "";
50 51
52 + @Option(name = "--ipProto", description = "IP Protocol",
53 + required = false, multiValued = false)
54 + private String ipProtoString = null;
55 +
56 + @Option(name = "--ipSrc", description = "Source IP Address",
57 + required = false, multiValued = false)
58 + private String srcIpString = null;
59 +
60 + @Option(name = "--ipDst", description = "Destination IP Address",
61 + required = false, multiValued = false)
62 + private String dstIpString = null;
63 +
64 + @Option(name = "--tcpSrc", description = "Source TCP Port",
65 + required = false, multiValued = false)
66 + private String srcTcpString = null;
67 +
68 + @Option(name = "--tcpDst", description = "Destination TCP Port",
69 + required = false, multiValued = false)
70 + private String dstTcpString = null;
71 +
51 @Option(name = "-b", aliases = "--bandwidth", description = "Bandwidth", 72 @Option(name = "-b", aliases = "--bandwidth", description = "Bandwidth",
52 required = false, multiValued = false) 73 required = false, multiValued = false)
53 private String bandwidthString = ""; 74 private String bandwidthString = "";
...@@ -79,6 +100,26 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { ...@@ -79,6 +100,26 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
79 selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString)); 100 selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString));
80 } 101 }
81 102
103 + if (!isNullOrEmpty(ipProtoString)) {
104 + selectorBuilder.matchIPProtocol((byte) Short.parseShort(ipProtoString));
105 + }
106 +
107 + if (!isNullOrEmpty(srcIpString)) {
108 + selectorBuilder.matchIPSrc(IpPrefix.valueOf(srcIpString));
109 + }
110 +
111 + if (!isNullOrEmpty(dstIpString)) {
112 + selectorBuilder.matchIPDst(IpPrefix.valueOf(dstIpString));
113 + }
114 +
115 + if (!isNullOrEmpty(srcTcpString)) {
116 + selectorBuilder.matchTcpSrc((short) Integer.parseInt(srcTcpString));
117 + }
118 +
119 + if (!isNullOrEmpty(dstTcpString)) {
120 + selectorBuilder.matchTcpSrc((short) Integer.parseInt(dstTcpString));
121 + }
122 +
82 return selectorBuilder.build(); 123 return selectorBuilder.build();
83 } 124 }
84 125
......
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onlab.onos.net;
17 +
18 +/**
19 + * Collection of keys for annotation.
20 + * Definitions of annotation keys needs to be here to avoid scattering.
21 + */
22 +public final class AnnotationKeys {
23 +
24 + // Prohibit instantiation
25 + private AnnotationKeys() {}
26 +
27 + /**
28 + * Annotation key for latency.
29 + */
30 + public static final String LATENCY = "latency";
31 +
32 + /**
33 + * Returns the value annotated object for the specified annotation key.
34 + * The annotated value is expected to be String that can be parsed as double.
35 + * If parsing fails, the returned value will be 1.0.
36 + *
37 + * @param annotated annotated object whose annotated value is obtained
38 + * @param key key of annotation
39 + * @return double value of annotated object for the specified key
40 + */
41 + public static double getAnnotatedValue(Annotated annotated, String key) {
42 + double value;
43 + try {
44 + value = Double.parseDouble(annotated.annotations().value(key));
45 + } catch (NumberFormatException e) {
46 + value = 1.0;
47 + }
48 + return value;
49 + }
50 +}
...@@ -80,6 +80,7 @@ public class DefaultFlowEntry extends DefaultFlowRule ...@@ -80,6 +80,7 @@ public class DefaultFlowEntry extends DefaultFlowRule
80 this.state = FlowEntryState.FAILED; 80 this.state = FlowEntryState.FAILED;
81 this.errType = errType; 81 this.errType = errType;
82 this.errCode = errCode; 82 this.errCode = errCode;
83 + this.lastSeen = System.currentTimeMillis();
83 } 84 }
84 85
85 @Override 86 @Override
......
...@@ -58,7 +58,7 @@ public class DefaultFlowRule implements FlowRule { ...@@ -58,7 +58,7 @@ public class DefaultFlowRule implements FlowRule {
58 } 58 }
59 59
60 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, 60 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
61 - TrafficTreatment treatement, int priority, ApplicationId appId, 61 + TrafficTreatment treatment, int priority, ApplicationId appId,
62 int timeout, boolean permanent) { 62 int timeout, boolean permanent) {
63 63
64 if (priority < FlowRule.MIN_PRIORITY) { 64 if (priority < FlowRule.MIN_PRIORITY) {
...@@ -68,7 +68,7 @@ public class DefaultFlowRule implements FlowRule { ...@@ -68,7 +68,7 @@ public class DefaultFlowRule implements FlowRule {
68 this.deviceId = deviceId; 68 this.deviceId = deviceId;
69 this.priority = priority; 69 this.priority = priority;
70 this.selector = selector; 70 this.selector = selector;
71 - this.treatment = treatement; 71 + this.treatment = treatment;
72 this.appId = appId.id(); 72 this.appId = appId.id();
73 this.timeout = timeout; 73 this.timeout = timeout;
74 this.permanent = permanent; 74 this.permanent = permanent;
......
...@@ -63,7 +63,7 @@ public final class DefaultTrafficSelector implements TrafficSelector { ...@@ -63,7 +63,7 @@ public final class DefaultTrafficSelector implements TrafficSelector {
63 63
64 @Override 64 @Override
65 public int hashCode() { 65 public int hashCode() {
66 - return Objects.hash(criteria); 66 + return criteria.hashCode();
67 } 67 }
68 68
69 @Override 69 @Override
......
...@@ -18,7 +18,7 @@ package org.onlab.onos.net.flow; ...@@ -18,7 +18,7 @@ package org.onlab.onos.net.flow;
18 import org.onlab.onos.core.ApplicationId; 18 import org.onlab.onos.core.ApplicationId;
19 import org.onlab.onos.net.provider.Provider; 19 import org.onlab.onos.net.provider.Provider;
20 20
21 -import com.google.common.util.concurrent.ListenableFuture; 21 +import java.util.concurrent.Future;
22 22
23 /** 23 /**
24 * Abstraction of a flow rule provider. 24 * Abstraction of a flow rule provider.
...@@ -58,6 +58,6 @@ public interface FlowRuleProvider extends Provider { ...@@ -58,6 +58,6 @@ public interface FlowRuleProvider extends Provider {
58 * @param batch a batch of flow rules 58 * @param batch a batch of flow rules
59 * @return a future indicating the status of this execution 59 * @return a future indicating the status of this execution
60 */ 60 */
61 - ListenableFuture<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch); 61 + Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch);
62 62
63 } 63 }
......
...@@ -196,7 +196,7 @@ public final class Criteria { ...@@ -196,7 +196,7 @@ public final class Criteria {
196 196
197 @Override 197 @Override
198 public int hashCode() { 198 public int hashCode() {
199 - return Objects.hash(port, type()); 199 + return Objects.hash(type(), port);
200 } 200 }
201 201
202 @Override 202 @Override
...@@ -242,7 +242,7 @@ public final class Criteria { ...@@ -242,7 +242,7 @@ public final class Criteria {
242 242
243 @Override 243 @Override
244 public int hashCode() { 244 public int hashCode() {
245 - return Objects.hash(mac, type); 245 + return Objects.hash(type, mac);
246 } 246 }
247 247
248 @Override 248 @Override
...@@ -288,7 +288,7 @@ public final class Criteria { ...@@ -288,7 +288,7 @@ public final class Criteria {
288 288
289 @Override 289 @Override
290 public int hashCode() { 290 public int hashCode() {
291 - return Objects.hash(ethType, type()); 291 + return Objects.hash(type(), ethType);
292 } 292 }
293 293
294 @Override 294 @Override
...@@ -336,7 +336,7 @@ public final class Criteria { ...@@ -336,7 +336,7 @@ public final class Criteria {
336 336
337 @Override 337 @Override
338 public int hashCode() { 338 public int hashCode() {
339 - return Objects.hash(ip, type); 339 + return Objects.hash(type, ip);
340 } 340 }
341 341
342 @Override 342 @Override
...@@ -382,7 +382,7 @@ public final class Criteria { ...@@ -382,7 +382,7 @@ public final class Criteria {
382 382
383 @Override 383 @Override
384 public int hashCode() { 384 public int hashCode() {
385 - return Objects.hash(proto, type()); 385 + return Objects.hash(type(), proto);
386 } 386 }
387 387
388 @Override 388 @Override
...@@ -427,7 +427,7 @@ public final class Criteria { ...@@ -427,7 +427,7 @@ public final class Criteria {
427 427
428 @Override 428 @Override
429 public int hashCode() { 429 public int hashCode() {
430 - return Objects.hash(vlanPcp); 430 + return Objects.hash(type(), vlanPcp);
431 } 431 }
432 432
433 @Override 433 @Override
...@@ -474,7 +474,7 @@ public final class Criteria { ...@@ -474,7 +474,7 @@ public final class Criteria {
474 474
475 @Override 475 @Override
476 public int hashCode() { 476 public int hashCode() {
477 - return Objects.hash(vlanId, type()); 477 + return Objects.hash(type(), vlanId);
478 } 478 }
479 479
480 @Override 480 @Override
...@@ -522,7 +522,7 @@ public final class Criteria { ...@@ -522,7 +522,7 @@ public final class Criteria {
522 522
523 @Override 523 @Override
524 public int hashCode() { 524 public int hashCode() {
525 - return Objects.hash(tcpPort, type); 525 + return Objects.hash(type, tcpPort);
526 } 526 }
527 527
528 @Override 528 @Override
...@@ -568,7 +568,7 @@ public final class Criteria { ...@@ -568,7 +568,7 @@ public final class Criteria {
568 568
569 @Override 569 @Override
570 public int hashCode() { 570 public int hashCode() {
571 - return Objects.hash(lambda, type); 571 + return Objects.hash(type, lambda);
572 } 572 }
573 573
574 @Override 574 @Override
...@@ -612,7 +612,7 @@ public final class Criteria { ...@@ -612,7 +612,7 @@ public final class Criteria {
612 612
613 @Override 613 @Override
614 public int hashCode() { 614 public int hashCode() {
615 - return Objects.hash(signalType, type); 615 + return Objects.hash(type, signalType);
616 } 616 }
617 617
618 @Override 618 @Override
......
...@@ -190,7 +190,7 @@ public final class Instructions { ...@@ -190,7 +190,7 @@ public final class Instructions {
190 190
191 @Override 191 @Override
192 public int hashCode() { 192 public int hashCode() {
193 - return Objects.hash(port, type()); 193 + return Objects.hash(type(), port);
194 } 194 }
195 195
196 @Override 196 @Override
......
...@@ -70,7 +70,7 @@ public abstract class L0ModificationInstruction implements Instruction { ...@@ -70,7 +70,7 @@ public abstract class L0ModificationInstruction implements Instruction {
70 70
71 @Override 71 @Override
72 public int hashCode() { 72 public int hashCode() {
73 - return Objects.hash(lambda, type(), subtype); 73 + return Objects.hash(type(), subtype, lambda);
74 } 74 }
75 75
76 @Override 76 @Override
......
...@@ -93,7 +93,7 @@ public abstract class L2ModificationInstruction implements Instruction { ...@@ -93,7 +93,7 @@ public abstract class L2ModificationInstruction implements Instruction {
93 93
94 @Override 94 @Override
95 public int hashCode() { 95 public int hashCode() {
96 - return Objects.hash(mac, type(), subtype); 96 + return Objects.hash(type(), subtype, mac);
97 } 97 }
98 98
99 @Override 99 @Override
...@@ -142,7 +142,7 @@ public abstract class L2ModificationInstruction implements Instruction { ...@@ -142,7 +142,7 @@ public abstract class L2ModificationInstruction implements Instruction {
142 142
143 @Override 143 @Override
144 public int hashCode() { 144 public int hashCode() {
145 - return Objects.hash(vlanId, type(), subtype()); 145 + return Objects.hash(type(), subtype(), vlanId);
146 } 146 }
147 147
148 @Override 148 @Override
...@@ -191,7 +191,7 @@ public abstract class L2ModificationInstruction implements Instruction { ...@@ -191,7 +191,7 @@ public abstract class L2ModificationInstruction implements Instruction {
191 191
192 @Override 192 @Override
193 public int hashCode() { 193 public int hashCode() {
194 - return Objects.hash(vlanPcp, type(), subtype()); 194 + return Objects.hash(type(), subtype(), vlanPcp);
195 } 195 }
196 196
197 @Override 197 @Override
......
...@@ -85,7 +85,7 @@ public abstract class L3ModificationInstruction implements Instruction { ...@@ -85,7 +85,7 @@ public abstract class L3ModificationInstruction implements Instruction {
85 85
86 @Override 86 @Override
87 public int hashCode() { 87 public int hashCode() {
88 - return Objects.hash(ip, type(), subtype()); 88 + return Objects.hash(type(), subtype(), ip);
89 } 89 }
90 90
91 @Override 91 @Override
......
...@@ -23,6 +23,7 @@ import org.onlab.onos.net.flow.TrafficSelector; ...@@ -23,6 +23,7 @@ import org.onlab.onos.net.flow.TrafficSelector;
23 import org.onlab.onos.net.flow.TrafficTreatment; 23 import org.onlab.onos.net.flow.TrafficTreatment;
24 24
25 import java.util.Collection; 25 import java.util.Collection;
26 +import java.util.Collections;
26 import java.util.List; 27 import java.util.List;
27 28
28 import static com.google.common.base.Preconditions.checkNotNull; 29 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -61,7 +62,7 @@ public abstract class ConnectivityIntent extends Intent { ...@@ -61,7 +62,7 @@ public abstract class ConnectivityIntent extends Intent {
61 Collection<NetworkResource> resources, 62 Collection<NetworkResource> resources,
62 TrafficSelector selector, 63 TrafficSelector selector,
63 TrafficTreatment treatment) { 64 TrafficTreatment treatment) {
64 - this(id, appId, resources, selector, treatment, null); 65 + this(id, appId, resources, selector, treatment, Collections.emptyList());
65 } 66 }
66 67
67 /** 68 /**
...@@ -87,7 +88,7 @@ public abstract class ConnectivityIntent extends Intent { ...@@ -87,7 +88,7 @@ public abstract class ConnectivityIntent extends Intent {
87 super(id, appId, resources); 88 super(id, appId, resources);
88 this.selector = checkNotNull(selector); 89 this.selector = checkNotNull(selector);
89 this.treatment = checkNotNull(treatment); 90 this.treatment = checkNotNull(treatment);
90 - this.constraints = constraints; 91 + this.constraints = checkNotNull(constraints);
91 } 92 }
92 93
93 /** 94 /**
...@@ -97,7 +98,7 @@ public abstract class ConnectivityIntent extends Intent { ...@@ -97,7 +98,7 @@ public abstract class ConnectivityIntent extends Intent {
97 super(); 98 super();
98 this.selector = null; 99 this.selector = null;
99 this.treatment = null; 100 this.treatment = null;
100 - this.constraints = null; 101 + this.constraints = Collections.emptyList();
101 } 102 }
102 103
103 /** 104 /**
......
...@@ -21,6 +21,7 @@ import org.onlab.onos.net.HostId; ...@@ -21,6 +21,7 @@ import org.onlab.onos.net.HostId;
21 import org.onlab.onos.net.flow.TrafficSelector; 21 import org.onlab.onos.net.flow.TrafficSelector;
22 import org.onlab.onos.net.flow.TrafficTreatment; 22 import org.onlab.onos.net.flow.TrafficTreatment;
23 23
24 +import java.util.Collections;
24 import java.util.List; 25 import java.util.List;
25 26
26 import static com.google.common.base.Preconditions.checkNotNull; 27 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -46,7 +47,7 @@ public final class HostToHostIntent extends ConnectivityIntent { ...@@ -46,7 +47,7 @@ public final class HostToHostIntent extends ConnectivityIntent {
46 public HostToHostIntent(ApplicationId appId, HostId one, HostId two, 47 public HostToHostIntent(ApplicationId appId, HostId one, HostId two,
47 TrafficSelector selector, 48 TrafficSelector selector,
48 TrafficTreatment treatment) { 49 TrafficTreatment treatment) {
49 - this(appId, one, two, selector, treatment, null); 50 + this(appId, one, two, selector, treatment, Collections.emptyList());
50 } 51 }
51 52
52 /** 53 /**
......
...@@ -22,6 +22,7 @@ import org.onlab.onos.net.Link; ...@@ -22,6 +22,7 @@ import org.onlab.onos.net.Link;
22 import org.onlab.onos.net.flow.TrafficSelector; 22 import org.onlab.onos.net.flow.TrafficSelector;
23 import org.onlab.onos.net.flow.TrafficTreatment; 23 import org.onlab.onos.net.flow.TrafficTreatment;
24 24
25 +import java.util.Collections;
25 import java.util.List; 26 import java.util.List;
26 import java.util.Set; 27 import java.util.Set;
27 28
...@@ -51,7 +52,7 @@ public final class LinkCollectionIntent extends ConnectivityIntent { ...@@ -51,7 +52,7 @@ public final class LinkCollectionIntent extends ConnectivityIntent {
51 TrafficTreatment treatment, 52 TrafficTreatment treatment,
52 Set<Link> links, 53 Set<Link> links,
53 ConnectPoint egressPoint) { 54 ConnectPoint egressPoint) {
54 - this(appId, selector , treatment, links, egressPoint, null); 55 + this(appId, selector , treatment, links, egressPoint, Collections.emptyList());
55 } 56 }
56 57
57 /** 58 /**
......
...@@ -22,6 +22,7 @@ import org.onlab.onos.net.ConnectPoint; ...@@ -22,6 +22,7 @@ import org.onlab.onos.net.ConnectPoint;
22 import org.onlab.onos.net.flow.TrafficSelector; 22 import org.onlab.onos.net.flow.TrafficSelector;
23 import org.onlab.onos.net.flow.TrafficTreatment; 23 import org.onlab.onos.net.flow.TrafficTreatment;
24 24
25 +import java.util.Collections;
25 import java.util.List; 26 import java.util.List;
26 import java.util.Set; 27 import java.util.Set;
27 28
...@@ -55,14 +56,7 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent { ...@@ -55,14 +56,7 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent {
55 TrafficTreatment treatment, 56 TrafficTreatment treatment,
56 Set<ConnectPoint> ingressPoints, 57 Set<ConnectPoint> ingressPoints,
57 ConnectPoint egressPoint) { 58 ConnectPoint egressPoint) {
58 - super(id(MultiPointToSinglePointIntent.class, selector, treatment, 59 + this(appId, selector, treatment, ingressPoints, egressPoint, Collections.emptyList());
59 - ingressPoints, egressPoint), appId, null, selector, treatment);
60 -
61 - checkNotNull(ingressPoints);
62 - checkArgument(!ingressPoints.isEmpty(), "Ingress point set cannot be empty");
63 -
64 - this.ingressPoints = Sets.newHashSet(ingressPoints);
65 - this.egressPoint = checkNotNull(egressPoint);
66 } 60 }
67 61
68 /** 62 /**
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onlab.onos.net.intent; 16 package org.onlab.onos.net.intent;
17 17
18 +import java.util.Collections;
18 import java.util.List; 19 import java.util.List;
19 20
20 import com.google.common.base.MoreObjects; 21 import com.google.common.base.MoreObjects;
...@@ -42,9 +43,7 @@ public class PathIntent extends ConnectivityIntent { ...@@ -42,9 +43,7 @@ public class PathIntent extends ConnectivityIntent {
42 */ 43 */
43 public PathIntent(ApplicationId appId, TrafficSelector selector, 44 public PathIntent(ApplicationId appId, TrafficSelector selector,
44 TrafficTreatment treatment, Path path) { 45 TrafficTreatment treatment, Path path) {
45 - super(id(PathIntent.class, selector, treatment, path), appId, 46 + this(appId, selector, treatment, path, Collections.emptyList());
46 - resources(path.links()), selector, treatment);
47 - this.path = path;
48 } 47 }
49 48
50 /** 49 /**
......
...@@ -21,6 +21,8 @@ import org.onlab.onos.net.resource.LinkResourceService; ...@@ -21,6 +21,8 @@ import org.onlab.onos.net.resource.LinkResourceService;
21 21
22 import java.util.Objects; 22 import java.util.Objects;
23 23
24 +import static org.onlab.onos.net.AnnotationKeys.getAnnotatedValue;
25 +
24 /** 26 /**
25 * Constraint that evaluates an arbitrary link annotated value is under the specified threshold. 27 * Constraint that evaluates an arbitrary link annotated value is under the specified threshold.
26 */ 28 */
...@@ -41,6 +43,12 @@ public class AnnotationConstraint extends BooleanConstraint { ...@@ -41,6 +43,12 @@ public class AnnotationConstraint extends BooleanConstraint {
41 this.threshold = threshold; 43 this.threshold = threshold;
42 } 44 }
43 45
46 + // Constructor for serialization
47 + private AnnotationConstraint() {
48 + this.key = "";
49 + this.threshold = 0;
50 + }
51 +
44 /** 52 /**
45 * Returns the key of link annotation this constraint designates. 53 * Returns the key of link annotation this constraint designates.
46 * @return key of link annotation 54 * @return key of link annotation
...@@ -65,25 +73,6 @@ public class AnnotationConstraint extends BooleanConstraint { ...@@ -65,25 +73,6 @@ public class AnnotationConstraint extends BooleanConstraint {
65 return value <= threshold; 73 return value <= threshold;
66 } 74 }
67 75
68 - /**
69 - * Returns the annotated value of the specified link. The annotated value
70 - * is expected to be String that can be parsed as double. If parsing fails,
71 - * the returned value will be 1.0.
72 - *
73 - * @param link link whose annotated value is obtained
74 - * @param key key of link annotation
75 - * @return double value of link annotation for the specified key
76 - */
77 - private double getAnnotatedValue(Link link, String key) {
78 - double value;
79 - try {
80 - value = Double.parseDouble(link.annotations().value(key));
81 - } catch (NumberFormatException e) {
82 - value = 1.0;
83 - }
84 - return value;
85 - }
86 -
87 @Override 76 @Override
88 public double cost(Link link, LinkResourceService resourceService) { 77 public double cost(Link link, LinkResourceService resourceService) {
89 if (isValid(link, resourceService)) { 78 if (isValid(link, resourceService)) {
......
...@@ -25,14 +25,14 @@ import java.time.Duration; ...@@ -25,14 +25,14 @@ import java.time.Duration;
25 import java.time.temporal.ChronoUnit; 25 import java.time.temporal.ChronoUnit;
26 import java.util.Objects; 26 import java.util.Objects;
27 27
28 +import static org.onlab.onos.net.AnnotationKeys.LATENCY;
29 +import static org.onlab.onos.net.AnnotationKeys.getAnnotatedValue;
30 +
28 /** 31 /**
29 * Constraint that evaluates the latency through a path. 32 * Constraint that evaluates the latency through a path.
30 */ 33 */
31 public class LatencyConstraint implements Constraint { 34 public class LatencyConstraint implements Constraint {
32 35
33 - // TODO: formalize the key for latency all over the codes.
34 - private static final String LATENCY_KEY = "latency";
35 -
36 private final Duration latency; 36 private final Duration latency;
37 37
38 /** 38 /**
...@@ -43,22 +43,18 @@ public class LatencyConstraint implements Constraint { ...@@ -43,22 +43,18 @@ public class LatencyConstraint implements Constraint {
43 this.latency = latency; 43 this.latency = latency;
44 } 44 }
45 45
46 + // Constructor for serialization
47 + private LatencyConstraint() {
48 + this.latency = Duration.ZERO;
49 + }
50 +
46 public Duration latency() { 51 public Duration latency() {
47 return latency; 52 return latency;
48 } 53 }
49 54
50 @Override 55 @Override
51 public double cost(Link link, LinkResourceService resourceService) { 56 public double cost(Link link, LinkResourceService resourceService) {
52 - String value = link.annotations().value(LATENCY_KEY); 57 + return getAnnotatedValue(link, LATENCY);
53 -
54 - double latencyInMicroSec;
55 - try {
56 - latencyInMicroSec = Double.parseDouble(value);
57 - } catch (NumberFormatException e) {
58 - latencyInMicroSec = 1.0;
59 - }
60 -
61 - return latencyInMicroSec;
62 } 58 }
63 59
64 @Override 60 @Override
......
...@@ -21,6 +21,7 @@ import org.onlab.onos.net.DeviceId; ...@@ -21,6 +21,7 @@ import org.onlab.onos.net.DeviceId;
21 import org.onlab.onos.net.Link; 21 import org.onlab.onos.net.Link;
22 import org.onlab.onos.net.resource.LinkResourceService; 22 import org.onlab.onos.net.resource.LinkResourceService;
23 23
24 +import java.util.Collections;
24 import java.util.Objects; 25 import java.util.Objects;
25 import java.util.Set; 26 import java.util.Set;
26 27
...@@ -39,6 +40,11 @@ public class ObstacleConstraint extends BooleanConstraint { ...@@ -39,6 +40,11 @@ public class ObstacleConstraint extends BooleanConstraint {
39 this.obstacles = ImmutableSet.copyOf(obstacles); 40 this.obstacles = ImmutableSet.copyOf(obstacles);
40 } 41 }
41 42
43 + // Constructor for serialization
44 + private ObstacleConstraint() {
45 + this.obstacles = Collections.emptySet();
46 + }
47 +
42 @Override 48 @Override
43 public boolean isValid(Link link, LinkResourceService resourceService) { 49 public boolean isValid(Link link, LinkResourceService resourceService) {
44 DeviceId src = link.src().deviceId(); 50 DeviceId src = link.src().deviceId();
......
...@@ -17,12 +17,13 @@ package org.onlab.onos.net.intent.constraint; ...@@ -17,12 +17,13 @@ package org.onlab.onos.net.intent.constraint;
17 17
18 import com.google.common.base.MoreObjects; 18 import com.google.common.base.MoreObjects;
19 import com.google.common.collect.ImmutableList; 19 import com.google.common.collect.ImmutableList;
20 -import org.onlab.onos.net.ElementId; 20 +import org.onlab.onos.net.DeviceId;
21 import org.onlab.onos.net.Link; 21 import org.onlab.onos.net.Link;
22 import org.onlab.onos.net.Path; 22 import org.onlab.onos.net.Path;
23 import org.onlab.onos.net.intent.Constraint; 23 import org.onlab.onos.net.intent.Constraint;
24 import org.onlab.onos.net.resource.LinkResourceService; 24 import org.onlab.onos.net.resource.LinkResourceService;
25 25
26 +import java.util.Collections;
26 import java.util.LinkedList; 27 import java.util.LinkedList;
27 import java.util.List; 28 import java.util.List;
28 import java.util.Objects; 29 import java.util.Objects;
...@@ -35,20 +36,25 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -35,20 +36,25 @@ import static com.google.common.base.Preconditions.checkNotNull;
35 */ 36 */
36 public class WaypointConstraint implements Constraint { 37 public class WaypointConstraint implements Constraint {
37 38
38 - private final List<ElementId> waypoints; 39 + private final List<DeviceId> waypoints;
39 40
40 /** 41 /**
41 * Creates a new waypoint constraint. 42 * Creates a new waypoint constraint.
42 * 43 *
43 * @param waypoints waypoints 44 * @param waypoints waypoints
44 */ 45 */
45 - public WaypointConstraint(ElementId... waypoints) { 46 + public WaypointConstraint(DeviceId... waypoints) {
46 checkNotNull(waypoints, "waypoints cannot be null"); 47 checkNotNull(waypoints, "waypoints cannot be null");
47 checkArgument(waypoints.length > 0, "length of waypoints should be more than 0"); 48 checkArgument(waypoints.length > 0, "length of waypoints should be more than 0");
48 this.waypoints = ImmutableList.copyOf(waypoints); 49 this.waypoints = ImmutableList.copyOf(waypoints);
49 } 50 }
50 51
51 - public List<ElementId> waypoints() { 52 + // Constructor for serialization
53 + private WaypointConstraint() {
54 + this.waypoints = Collections.emptyList();
55 + }
56 +
57 + public List<DeviceId> waypoints() {
52 return waypoints; 58 return waypoints;
53 } 59 }
54 60
...@@ -60,8 +66,8 @@ public class WaypointConstraint implements Constraint { ...@@ -60,8 +66,8 @@ public class WaypointConstraint implements Constraint {
60 66
61 @Override 67 @Override
62 public boolean validate(Path path, LinkResourceService resourceService) { 68 public boolean validate(Path path, LinkResourceService resourceService) {
63 - LinkedList<ElementId> waypoints = new LinkedList<>(this.waypoints); 69 + LinkedList<DeviceId> waypoints = new LinkedList<>(this.waypoints);
64 - ElementId current = waypoints.poll(); 70 + DeviceId current = waypoints.poll();
65 // This is safe because Path class ensures the number of links are more than 0 71 // This is safe because Path class ensures the number of links are more than 0
66 Link firstLink = path.links().get(0); 72 Link firstLink = path.links().get(0);
67 if (firstLink.src().elementId().equals(current)) { 73 if (firstLink.src().elementId().equals(current)) {
......
...@@ -37,6 +37,7 @@ import static org.easymock.EasyMock.createMock; ...@@ -37,6 +37,7 @@ import static org.easymock.EasyMock.createMock;
37 import static org.hamcrest.Matchers.closeTo; 37 import static org.hamcrest.Matchers.closeTo;
38 import static org.hamcrest.Matchers.is; 38 import static org.hamcrest.Matchers.is;
39 import static org.junit.Assert.assertThat; 39 import static org.junit.Assert.assertThat;
40 +import static org.onlab.onos.net.AnnotationKeys.LATENCY;
40 import static org.onlab.onos.net.DefaultLinkTest.cp; 41 import static org.onlab.onos.net.DefaultLinkTest.cp;
41 import static org.onlab.onos.net.DeviceId.deviceId; 42 import static org.onlab.onos.net.DeviceId.deviceId;
42 import static org.onlab.onos.net.Link.Type.DIRECT; 43 import static org.onlab.onos.net.Link.Type.DIRECT;
...@@ -51,7 +52,6 @@ public class LatencyConstraintTest { ...@@ -51,7 +52,6 @@ public class LatencyConstraintTest {
51 private static final PortNumber PN3 = PortNumber.portNumber(3); 52 private static final PortNumber PN3 = PortNumber.portNumber(3);
52 private static final PortNumber PN4 = PortNumber.portNumber(4); 53 private static final PortNumber PN4 = PortNumber.portNumber(4);
53 private static final ProviderId PROVIDER_ID = new ProviderId("of", "foo"); 54 private static final ProviderId PROVIDER_ID = new ProviderId("of", "foo");
54 - private static final String LATENCY_KEY = "latency";
55 private static final String LATENCY1 = "3.0"; 55 private static final String LATENCY1 = "3.0";
56 private static final String LATENCY2 = "4.0"; 56 private static final String LATENCY2 = "4.0";
57 57
...@@ -66,8 +66,8 @@ public class LatencyConstraintTest { ...@@ -66,8 +66,8 @@ public class LatencyConstraintTest {
66 public void setUp() { 66 public void setUp() {
67 linkResourceService = createMock(LinkResourceService.class); 67 linkResourceService = createMock(LinkResourceService.class);
68 68
69 - Annotations annotations1 = DefaultAnnotations.builder().set(LATENCY_KEY, LATENCY1).build(); 69 + Annotations annotations1 = DefaultAnnotations.builder().set(LATENCY, LATENCY1).build();
70 - Annotations annotations2 = DefaultAnnotations.builder().set(LATENCY_KEY, LATENCY2).build(); 70 + Annotations annotations2 = DefaultAnnotations.builder().set(LATENCY, LATENCY2).build();
71 71
72 link1 = new DefaultLink(PROVIDER_ID, cp(DID1, PN1), cp(DID2, PN2), DIRECT, annotations1); 72 link1 = new DefaultLink(PROVIDER_ID, cp(DID1, PN1), cp(DID2, PN2), DIRECT, annotations1);
73 link2 = new DefaultLink(PROVIDER_ID, cp(DID2, PN3), cp(DID3, PN4), DIRECT, annotations2); 73 link2 = new DefaultLink(PROVIDER_ID, cp(DID2, PN3), cp(DID3, PN4), DIRECT, annotations2);
......
...@@ -15,21 +15,12 @@ ...@@ -15,21 +15,12 @@
15 */ 15 */
16 package org.onlab.onos.net.flow.impl; 16 package org.onlab.onos.net.flow.impl;
17 17
18 -import static com.google.common.base.Preconditions.checkNotNull; 18 +import com.google.common.collect.ArrayListMultimap;
19 -import static org.slf4j.LoggerFactory.getLogger; 19 +import com.google.common.collect.Iterables;
20 -import static org.onlab.util.Tools.namedThreads; 20 +import com.google.common.collect.Lists;
21 - 21 +import com.google.common.collect.Maps;
22 -import java.util.List; 22 +import com.google.common.collect.Multimap;
23 -import java.util.Map; 23 +import com.google.common.collect.Sets;
24 -import java.util.Set;
25 -import java.util.concurrent.CancellationException;
26 -import java.util.concurrent.ExecutionException;
27 -import java.util.concurrent.ExecutorService;
28 -import java.util.concurrent.Executors;
29 -import java.util.concurrent.Future;
30 -import java.util.concurrent.TimeUnit;
31 -import java.util.concurrent.TimeoutException;
32 -import java.util.concurrent.atomic.AtomicReference;
33 24
34 import org.apache.felix.scr.annotations.Activate; 25 import org.apache.felix.scr.annotations.Activate;
35 import org.apache.felix.scr.annotations.Component; 26 import org.apache.felix.scr.annotations.Component;
...@@ -64,14 +55,22 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; ...@@ -64,14 +55,22 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry;
64 import org.onlab.onos.net.provider.AbstractProviderService; 55 import org.onlab.onos.net.provider.AbstractProviderService;
65 import org.slf4j.Logger; 56 import org.slf4j.Logger;
66 57
67 -import com.google.common.collect.ArrayListMultimap; 58 +import java.util.HashSet;
68 -import com.google.common.collect.Iterables; 59 +import java.util.List;
69 -import com.google.common.collect.Lists; 60 +import java.util.Map;
70 -import com.google.common.collect.Maps; 61 +import java.util.Set;
71 -import com.google.common.collect.Multimap; 62 +import java.util.concurrent.CancellationException;
72 -import com.google.common.collect.Sets; 63 +import java.util.concurrent.ExecutionException;
73 -import com.google.common.util.concurrent.Futures; 64 +import java.util.concurrent.ExecutorService;
74 -import com.google.common.util.concurrent.ListenableFuture; 65 +import java.util.concurrent.Executors;
66 +import java.util.concurrent.Future;
67 +import java.util.concurrent.TimeUnit;
68 +import java.util.concurrent.TimeoutException;
69 +import java.util.concurrent.atomic.AtomicReference;
70 +
71 +import static com.google.common.base.Preconditions.checkNotNull;
72 +import static org.onlab.util.Tools.namedThreads;
73 +import static org.slf4j.LoggerFactory.getLogger;
75 74
76 /** 75 /**
77 * Provides implementation of the flow NB &amp; SB APIs. 76 * Provides implementation of the flow NB &amp; SB APIs.
...@@ -92,8 +91,7 @@ public class FlowRuleManager ...@@ -92,8 +91,7 @@ public class FlowRuleManager
92 91
93 private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate(); 92 private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate();
94 93
95 - private final ExecutorService futureListeners = 94 + private ExecutorService futureService;
96 - Executors.newCachedThreadPool(namedThreads("provider-future-listeners"));
97 95
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected FlowRuleStore store; 97 protected FlowRuleStore store;
...@@ -106,6 +104,7 @@ public class FlowRuleManager ...@@ -106,6 +104,7 @@ public class FlowRuleManager
106 104
107 @Activate 105 @Activate
108 public void activate() { 106 public void activate() {
107 + futureService = Executors.newCachedThreadPool(namedThreads("provider-future-listeners"));
109 store.setDelegate(delegate); 108 store.setDelegate(delegate);
110 eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry); 109 eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry);
111 log.info("Started"); 110 log.info("Started");
...@@ -113,7 +112,7 @@ public class FlowRuleManager ...@@ -113,7 +112,7 @@ public class FlowRuleManager
113 112
114 @Deactivate 113 @Deactivate
115 public void deactivate() { 114 public void deactivate() {
116 - futureListeners.shutdownNow(); 115 + futureService.shutdownNow();
117 116
118 store.unsetDelegate(delegate); 117 store.unsetDelegate(delegate);
119 eventDispatcher.removeSink(FlowRuleEvent.class); 118 eventDispatcher.removeSink(FlowRuleEvent.class);
...@@ -364,6 +363,9 @@ public class FlowRuleManager ...@@ -364,6 +363,9 @@ public class FlowRuleManager
364 363
365 // Store delegate to re-post events emitted from the store. 364 // Store delegate to re-post events emitted from the store.
366 private class InternalStoreDelegate implements FlowRuleStoreDelegate { 365 private class InternalStoreDelegate implements FlowRuleStoreDelegate {
366 +
367 + private static final int TIMEOUT = 5000; // ms
368 +
367 // TODO: Right now we only dispatch events at individual flowEntry level. 369 // TODO: Right now we only dispatch events at individual flowEntry level.
368 // It may be more efficient for also dispatch events as a batch. 370 // It may be more efficient for also dispatch events as a batch.
369 @Override 371 @Override
...@@ -384,15 +386,28 @@ public class FlowRuleManager ...@@ -384,15 +386,28 @@ public class FlowRuleManager
384 386
385 FlowRuleProvider flowRuleProvider = 387 FlowRuleProvider flowRuleProvider =
386 getProvider(batchOperation.getOperations().get(0).getTarget().deviceId()); 388 getProvider(batchOperation.getOperations().get(0).getTarget().deviceId());
387 - final ListenableFuture<CompletedBatchOperation> result = 389 + final Future<CompletedBatchOperation> result =
388 flowRuleProvider.executeBatch(batchOperation); 390 flowRuleProvider.executeBatch(batchOperation);
389 - result.addListener(new Runnable() { 391 + futureService.submit(new Runnable() {
390 @Override 392 @Override
391 public void run() { 393 public void run() {
392 - store.batchOperationComplete(FlowRuleBatchEvent.completed(request, 394 + CompletedBatchOperation res;
393 - Futures.getUnchecked(result))); 395 + try {
396 + res = result.get(TIMEOUT, TimeUnit.MILLISECONDS);
397 + store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res));
398 + } catch (TimeoutException | InterruptedException | ExecutionException e) {
399 + log.warn("Something went wrong with the batch operation {}",
400 + request.batchId(), e);
401 +
402 + Set<FlowRule> failures = new HashSet<>(batchOperation.size());
403 + for (FlowRuleBatchEntry op : batchOperation.getOperations()) {
404 + failures.add(op.getTarget());
405 + }
406 + res = new CompletedBatchOperation(false, failures);
407 + store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res));
408 + }
394 } 409 }
395 - }, futureListeners); 410 + });
396 break; 411 break;
397 412
398 case BATCH_OPERATION_COMPLETED: 413 case BATCH_OPERATION_COMPLETED:
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onlab.onos.net.intent.impl; 16 package org.onlab.onos.net.intent.impl;
17 17
18 +import com.google.common.base.Predicate;
19 +import com.google.common.collect.FluentIterable;
18 import com.google.common.collect.ImmutableList; 20 import com.google.common.collect.ImmutableList;
19 import org.apache.felix.scr.annotations.Component; 21 import org.apache.felix.scr.annotations.Component;
20 import org.apache.felix.scr.annotations.Reference; 22 import org.apache.felix.scr.annotations.Reference;
...@@ -94,11 +96,19 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent> ...@@ -94,11 +96,19 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent>
94 protected Path getPath(ConnectivityIntent intent, 96 protected Path getPath(ConnectivityIntent intent,
95 ElementId one, ElementId two) { 97 ElementId one, ElementId two) {
96 Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints())); 98 Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints()));
97 - if (paths.isEmpty()) { 99 + final List<Constraint> constraints = intent.constraints();
98 - throw new PathNotFoundException("No packet path from " + one + " to " + two); 100 + ImmutableList<Path> filtered = FluentIterable.from(paths)
101 + .filter(new Predicate<Path>() {
102 + @Override
103 + public boolean apply(Path path) {
104 + return checkPath(path, constraints);
105 + }
106 + }).toList();
107 + if (filtered.isEmpty()) {
108 + throw new PathNotFoundException("No packet path form " + one + " to " + two);
99 } 109 }
100 // TODO: let's be more intelligent about this eventually 110 // TODO: let's be more intelligent about this eventually
101 - return paths.iterator().next(); 111 + return filtered.iterator().next();
102 } 112 }
103 113
104 /** 114 /**
......
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onlab.onos.net.flow;
17 +
18 +import java.util.concurrent.TimeUnit;
19 +
20 +import org.junit.Test;
21 +import org.onlab.onos.net.intent.IntentTestsMocks;
22 +
23 +import com.google.common.testing.EqualsTester;
24 +
25 +import static org.hamcrest.MatcherAssert.assertThat;
26 +import static org.hamcrest.Matchers.greaterThan;
27 +import static org.hamcrest.Matchers.is;
28 +import static org.onlab.onos.net.NetTestTools.did;
29 +
30 +/**
31 + * Unit tests for the DefaultFlowEntry class.
32 + */
33 +public class DefaultFlowEntryTest {
34 + private static final IntentTestsMocks.MockSelector SELECTOR =
35 + new IntentTestsMocks.MockSelector();
36 + private static final IntentTestsMocks.MockTreatment TREATMENT =
37 + new IntentTestsMocks.MockTreatment();
38 +
39 + private static DefaultFlowEntry makeFlowEntry(int uniqueValue) {
40 + return new DefaultFlowEntry(did("id" + Integer.toString(uniqueValue)),
41 + SELECTOR,
42 + TREATMENT,
43 + uniqueValue,
44 + FlowEntry.FlowEntryState.ADDED,
45 + uniqueValue,
46 + uniqueValue,
47 + uniqueValue,
48 + uniqueValue,
49 + uniqueValue);
50 + }
51 +
52 + final DefaultFlowEntry defaultFlowEntry1 = makeFlowEntry(1);
53 + final DefaultFlowEntry sameAsDefaultFlowEntry1 = makeFlowEntry(1);
54 + final DefaultFlowEntry defaultFlowEntry2 = makeFlowEntry(2);
55 +
56 + /**
57 + * Tests the equals, hashCode and toString methods using Guava EqualsTester.
58 + */
59 + @Test
60 + public void testEquals() {
61 + new EqualsTester()
62 + .addEqualityGroup(defaultFlowEntry1, sameAsDefaultFlowEntry1)
63 + .addEqualityGroup(defaultFlowEntry2)
64 + .testEquals();
65 + }
66 +
67 + /**
68 + * Tests the construction of a default flow entry from a device id.
69 + */
70 + @Test
71 + public void testDeviceBasedObject() {
72 + assertThat(defaultFlowEntry1.deviceId(), is(did("id1")));
73 + assertThat(defaultFlowEntry1.selector(), is(SELECTOR));
74 + assertThat(defaultFlowEntry1.treatment(), is(TREATMENT));
75 + assertThat(defaultFlowEntry1.timeout(), is(1));
76 + assertThat(defaultFlowEntry1.life(), is(1L));
77 + assertThat(defaultFlowEntry1.packets(), is(1L));
78 + assertThat(defaultFlowEntry1.bytes(), is(1L));
79 + assertThat(defaultFlowEntry1.state(), is(FlowEntry.FlowEntryState.ADDED));
80 + assertThat(defaultFlowEntry1.lastSeen(),
81 + greaterThan(System.currentTimeMillis() -
82 + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
83 + }
84 +
85 + /**
86 + * Tests the setters on a default flow entry object.
87 + */
88 + @Test
89 + public void testSetters() {
90 + final DefaultFlowEntry entry = makeFlowEntry(1);
91 +
92 + entry.setLastSeen();
93 + entry.setState(FlowEntry.FlowEntryState.PENDING_REMOVE);
94 + entry.setPackets(11);
95 + entry.setBytes(22);
96 + entry.setLife(33);
97 +
98 + assertThat(entry.deviceId(), is(did("id1")));
99 + assertThat(entry.selector(), is(SELECTOR));
100 + assertThat(entry.treatment(), is(TREATMENT));
101 + assertThat(entry.timeout(), is(1));
102 + assertThat(entry.life(), is(33L));
103 + assertThat(entry.packets(), is(11L));
104 + assertThat(entry.bytes(), is(22L));
105 + assertThat(entry.state(), is(FlowEntry.FlowEntryState.PENDING_REMOVE));
106 + assertThat(entry.lastSeen(),
107 + greaterThan(System.currentTimeMillis() -
108 + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
109 + }
110 +
111 + /**
112 + * Tests a default flow rule built for an error.
113 + */
114 + @Test
115 + public void testErrorObject() {
116 + final DefaultFlowEntry errorEntry =
117 + new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(1),
118 + 111,
119 + 222);
120 + assertThat(errorEntry.errType(), is(111));
121 + assertThat(errorEntry.errCode(), is(222));
122 + assertThat(errorEntry.state(), is(FlowEntry.FlowEntryState.FAILED));
123 + assertThat(errorEntry.lastSeen(),
124 + greaterThan(System.currentTimeMillis() -
125 + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
126 + }
127 +
128 + /**
129 + * Tests a default flow entry constructed from a flow rule.
130 + */
131 + @Test
132 + public void testFlowBasedObject() {
133 + final DefaultFlowEntry entry =
134 + new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(1));
135 + assertThat(entry.priority(), is(1));
136 + assertThat(entry.appId(), is((short) 0));
137 + assertThat(entry.lastSeen(),
138 + greaterThan(System.currentTimeMillis() -
139 + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
140 + }
141 +
142 + /**
143 + * Tests a default flow entry constructed from a flow rule plus extra
144 + * parameters.
145 + */
146 + @Test
147 + public void testFlowBasedObjectWithParameters() {
148 + final DefaultFlowEntry entry =
149 + new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(33),
150 + FlowEntry.FlowEntryState.REMOVED,
151 + 101, 102, 103);
152 + assertThat(entry.state(), is(FlowEntry.FlowEntryState.REMOVED));
153 + assertThat(entry.life(), is(101L));
154 + assertThat(entry.packets(), is(102L));
155 + assertThat(entry.bytes(), is(103L));
156 + assertThat(entry.lastSeen(),
157 + greaterThan(System.currentTimeMillis() -
158 + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
159 + }
160 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onlab.onos.net.flow;
18 +
19 +import org.junit.Test;
20 +import org.onlab.onos.net.intent.IntentTestsMocks;
21 +
22 +import com.google.common.testing.EqualsTester;
23 +
24 +import static org.hamcrest.MatcherAssert.assertThat;
25 +import static org.hamcrest.Matchers.is;
26 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutableBaseClass;
27 +import static org.onlab.onos.net.NetTestTools.APP_ID;
28 +import static org.onlab.onos.net.NetTestTools.did;
29 +
30 +/**
31 + * Unit tests for the default flow rule class.
32 + */
33 +public class DefaultFlowRuleTest {
34 + private static final IntentTestsMocks.MockSelector SELECTOR =
35 + new IntentTestsMocks.MockSelector();
36 + private static final IntentTestsMocks.MockTreatment TREATMENT =
37 + new IntentTestsMocks.MockTreatment();
38 +
39 + final FlowRule flowRule1 = new IntentTestsMocks.MockFlowRule(1);
40 + final FlowRule sameAsFlowRule1 = new IntentTestsMocks.MockFlowRule(1);
41 + final FlowRule flowRule2 = new IntentTestsMocks.MockFlowRule(2);
42 + final DefaultFlowRule defaultFlowRule1 = new DefaultFlowRule(flowRule1);
43 + final DefaultFlowRule sameAsDefaultFlowRule1 = new DefaultFlowRule(sameAsFlowRule1);
44 + final DefaultFlowRule defaultFlowRule2 = new DefaultFlowRule(flowRule2);
45 +
46 + /**
47 + * Checks that the DefaultFlowRule class is immutable but can be inherited
48 + * from.
49 + */
50 + @Test
51 + public void testImmutability() {
52 + assertThatClassIsImmutableBaseClass(DefaultFlowRule.class);
53 + }
54 +
55 + /**
56 + * Tests the equals, hashCode and toString methods using Guava EqualsTester.
57 + */
58 + @Test
59 + public void testEquals() {
60 + new EqualsTester()
61 + .addEqualityGroup(defaultFlowRule1, sameAsDefaultFlowRule1)
62 + .addEqualityGroup(defaultFlowRule2)
63 + .testEquals();
64 + }
65 +
66 + /**
67 + * Tests creation of a DefaultFlowRule using a FlowRule constructor.
68 + */
69 + @Test
70 + public void testCreationFromFlowRule() {
71 + assertThat(defaultFlowRule1.deviceId(), is(flowRule1.deviceId()));
72 + assertThat(defaultFlowRule1.appId(), is(flowRule1.appId()));
73 + assertThat(defaultFlowRule1.id(), is(flowRule1.id()));
74 + assertThat(defaultFlowRule1.isPermanent(), is(flowRule1.isPermanent()));
75 + assertThat(defaultFlowRule1.priority(), is(flowRule1.priority()));
76 + assertThat(defaultFlowRule1.selector(), is(flowRule1.selector()));
77 + assertThat(defaultFlowRule1.treatment(), is(flowRule1.treatment()));
78 + assertThat(defaultFlowRule1.timeout(), is(flowRule1.timeout()));
79 + }
80 +
81 + /**
82 + * Tests creation of a DefaultFlowRule using a FlowId constructor.
83 + */
84 + @Test
85 + public void testCreationWithFlowId() {
86 + final DefaultFlowRule rule =
87 + new DefaultFlowRule(did("1"), SELECTOR,
88 + TREATMENT, 22, 33,
89 + 44, false);
90 + assertThat(rule.deviceId(), is(did("1")));
91 + assertThat(rule.id().value(), is(33L));
92 + assertThat(rule.isPermanent(), is(false));
93 + assertThat(rule.priority(), is(22));
94 + assertThat(rule.selector(), is(SELECTOR));
95 + assertThat(rule.treatment(), is(TREATMENT));
96 + assertThat(rule.timeout(), is(44));
97 + }
98 +
99 + /**
100 + * Tests the creation of a DefaultFlowRule using an AppId constructor.
101 + */
102 + @Test
103 + public void testCreationWithAppId() {
104 + final DefaultFlowRule rule =
105 + new DefaultFlowRule(did("1"), SELECTOR,
106 + TREATMENT, 22, APP_ID,
107 + 44, false);
108 + assertThat(rule.deviceId(), is(did("1")));
109 + assertThat(rule.isPermanent(), is(false));
110 + assertThat(rule.priority(), is(22));
111 + assertThat(rule.selector(), is(SELECTOR));
112 + assertThat(rule.treatment(), is(TREATMENT));
113 + assertThat(rule.timeout(), is(44));
114 + }
115 +}
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onlab.onos.net.intent; 16 package org.onlab.onos.net.intent;
17 17
18 import static org.onlab.onos.net.NetTestTools.createPath; 18 import static org.onlab.onos.net.NetTestTools.createPath;
19 +import static org.onlab.onos.net.NetTestTools.did;
19 import static org.onlab.onos.net.NetTestTools.link; 20 import static org.onlab.onos.net.NetTestTools.link;
20 21
21 import java.util.ArrayList; 22 import java.util.ArrayList;
...@@ -31,6 +32,8 @@ import org.onlab.onos.net.DeviceId; ...@@ -31,6 +32,8 @@ import org.onlab.onos.net.DeviceId;
31 import org.onlab.onos.net.ElementId; 32 import org.onlab.onos.net.ElementId;
32 import org.onlab.onos.net.Link; 33 import org.onlab.onos.net.Link;
33 import org.onlab.onos.net.Path; 34 import org.onlab.onos.net.Path;
35 +import org.onlab.onos.net.flow.FlowId;
36 +import org.onlab.onos.net.flow.FlowRule;
34 import org.onlab.onos.net.flow.TrafficSelector; 37 import org.onlab.onos.net.flow.TrafficSelector;
35 import org.onlab.onos.net.flow.TrafficTreatment; 38 import org.onlab.onos.net.flow.TrafficTreatment;
36 import org.onlab.onos.net.flow.criteria.Criterion; 39 import org.onlab.onos.net.flow.criteria.Criterion;
...@@ -271,4 +274,60 @@ public class IntentTestsMocks { ...@@ -271,4 +274,60 @@ public class IntentTestsMocks {
271 } 274 }
272 } 275 }
273 276
277 + private static final IntentTestsMocks.MockSelector SELECTOR =
278 + new IntentTestsMocks.MockSelector();
279 + private static final IntentTestsMocks.MockTreatment TREATMENT =
280 + new IntentTestsMocks.MockTreatment();
281 +
282 + public static class MockFlowRule implements FlowRule {
283 +
284 + int priority;
285 + public MockFlowRule(int priority) {
286 + this.priority = priority;
287 + }
288 +
289 + @Override
290 + public FlowId id() {
291 + return FlowId.valueOf(1);
292 + }
293 +
294 + @Override
295 + public short appId() {
296 + return 0;
297 + }
298 +
299 + @Override
300 + public int priority() {
301 + return priority;
302 + }
303 +
304 + @Override
305 + public DeviceId deviceId() {
306 + return did("1");
307 + }
308 +
309 + @Override
310 + public TrafficSelector selector() {
311 + return SELECTOR;
312 + }
313 +
314 + @Override
315 + public TrafficTreatment treatment() {
316 + return TREATMENT;
317 + }
318 +
319 + @Override
320 + public int timeout() {
321 + return 0;
322 + }
323 +
324 + @Override
325 + public boolean isPermanent() {
326 + return false;
327 + }
328 +
329 +
330 + }
331 +
332 +
274 } 333 }
......
...@@ -85,6 +85,8 @@ import com.google.common.cache.Cache; ...@@ -85,6 +85,8 @@ import com.google.common.cache.Cache;
85 import com.google.common.cache.CacheBuilder; 85 import com.google.common.cache.CacheBuilder;
86 import com.google.common.cache.CacheLoader; 86 import com.google.common.cache.CacheLoader;
87 import com.google.common.cache.LoadingCache; 87 import com.google.common.cache.LoadingCache;
88 +import com.google.common.cache.RemovalListener;
89 +import com.google.common.cache.RemovalNotification;
88 import com.google.common.collect.ArrayListMultimap; 90 import com.google.common.collect.ArrayListMultimap;
89 import com.google.common.collect.ImmutableList; 91 import com.google.common.collect.ImmutableList;
90 import com.google.common.collect.ImmutableSet; 92 import com.google.common.collect.ImmutableSet;
...@@ -132,8 +134,7 @@ public class DistributedFlowRuleStore ...@@ -132,8 +134,7 @@ public class DistributedFlowRuleStore
132 private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = 134 private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures =
133 CacheBuilder.newBuilder() 135 CacheBuilder.newBuilder()
134 .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) 136 .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES)
135 - // TODO Explicitly fail the future if expired? 137 + .removalListener(new TimeoutFuture())
136 - //.removalListener(listener)
137 .build(); 138 .build();
138 139
139 // Cache of SMaps used for backup data. each SMap contain device flow table 140 // Cache of SMaps used for backup data. each SMap contain device flow table
...@@ -541,6 +542,17 @@ public class DistributedFlowRuleStore ...@@ -541,6 +542,17 @@ public class DistributedFlowRuleStore
541 log.debug("removedFromPrimary {}", removed); 542 log.debug("removedFromPrimary {}", removed);
542 } 543 }
543 544
545 + private static final class TimeoutFuture
546 + implements RemovalListener<Integer, SettableFuture<CompletedBatchOperation>> {
547 + @Override
548 + public void onRemoval(RemovalNotification<Integer, SettableFuture<CompletedBatchOperation>> notification) {
549 + // wrapping in ExecutionException to support Future.get
550 + notification.getValue()
551 + .setException(new ExecutionException("Timed out",
552 + new TimeoutException()));
553 + }
554 + }
555 +
544 private final class OnStoreBatch implements ClusterMessageHandler { 556 private final class OnStoreBatch implements ClusterMessageHandler {
545 private final NodeId local; 557 private final NodeId local;
546 558
...@@ -580,7 +592,18 @@ public class DistributedFlowRuleStore ...@@ -580,7 +592,18 @@ public class DistributedFlowRuleStore
580 592
581 @Override 593 @Override
582 public void run() { 594 public void run() {
583 - CompletedBatchOperation result = Futures.getUnchecked(f); 595 + CompletedBatchOperation result;
596 + try {
597 + result = f.get();
598 + } catch (InterruptedException | ExecutionException e) {
599 + log.error("Batch operation failed", e);
600 + // create everything failed response
601 + Set<FlowRule> failures = new HashSet<>(operation.size());
602 + for (FlowRuleBatchEntry op : operation.getOperations()) {
603 + failures.add(op.getTarget());
604 + }
605 + result = new CompletedBatchOperation(false, failures);
606 + }
584 try { 607 try {
585 message.respond(SERIALIZER.encode(result)); 608 message.respond(SERIALIZER.encode(result));
586 } catch (IOException e) { 609 } catch (IOException e) {
......
...@@ -72,7 +72,7 @@ public class DatabaseManager implements DatabaseService, DatabaseAdminService { ...@@ -72,7 +72,7 @@ public class DatabaseManager implements DatabaseService, DatabaseAdminService {
72 public static final String LOG_FILE_PREFIX = "/tmp/onos-copy-cat-log_"; 72 public static final String LOG_FILE_PREFIX = "/tmp/onos-copy-cat-log_";
73 73
74 // Current working dir seems to be /opt/onos/apache-karaf-3.0.2 74 // Current working dir seems to be /opt/onos/apache-karaf-3.0.2
75 - // TODO: Get the path to /opt/onos/config 75 + // TODO: Set the path to /opt/onos/config
76 private static final String CONFIG_DIR = "../config"; 76 private static final String CONFIG_DIR = "../config";
77 77
78 private static final String DEFAULT_MEMBER_FILE = "tablets.json"; 78 private static final String DEFAULT_MEMBER_FILE = "tablets.json";
......
...@@ -75,10 +75,14 @@ import org.onlab.onos.net.intent.OpticalConnectivityIntent; ...@@ -75,10 +75,14 @@ import org.onlab.onos.net.intent.OpticalConnectivityIntent;
75 import org.onlab.onos.net.intent.OpticalPathIntent; 75 import org.onlab.onos.net.intent.OpticalPathIntent;
76 import org.onlab.onos.net.intent.PathIntent; 76 import org.onlab.onos.net.intent.PathIntent;
77 import org.onlab.onos.net.intent.PointToPointIntent; 77 import org.onlab.onos.net.intent.PointToPointIntent;
78 +import org.onlab.onos.net.intent.constraint.AnnotationConstraint;
78 import org.onlab.onos.net.intent.constraint.BandwidthConstraint; 79 import org.onlab.onos.net.intent.constraint.BandwidthConstraint;
79 import org.onlab.onos.net.intent.constraint.BooleanConstraint; 80 import org.onlab.onos.net.intent.constraint.BooleanConstraint;
80 import org.onlab.onos.net.intent.constraint.LambdaConstraint; 81 import org.onlab.onos.net.intent.constraint.LambdaConstraint;
82 +import org.onlab.onos.net.intent.constraint.LatencyConstraint;
81 import org.onlab.onos.net.intent.constraint.LinkTypeConstraint; 83 import org.onlab.onos.net.intent.constraint.LinkTypeConstraint;
84 +import org.onlab.onos.net.intent.constraint.ObstacleConstraint;
85 +import org.onlab.onos.net.intent.constraint.WaypointConstraint;
82 import org.onlab.onos.net.link.DefaultLinkDescription; 86 import org.onlab.onos.net.link.DefaultLinkDescription;
83 import org.onlab.onos.net.packet.DefaultOutboundPacket; 87 import org.onlab.onos.net.packet.DefaultOutboundPacket;
84 import org.onlab.onos.net.provider.ProviderId; 88 import org.onlab.onos.net.provider.ProviderId;
...@@ -208,9 +212,14 @@ public final class KryoNamespaces { ...@@ -208,9 +212,14 @@ public final class KryoNamespaces {
208 LinkResourceRequest.class, 212 LinkResourceRequest.class,
209 Lambda.class, 213 Lambda.class,
210 Bandwidth.class, 214 Bandwidth.class,
215 + // Constraints
211 LambdaConstraint.class, 216 LambdaConstraint.class,
212 BandwidthConstraint.class, 217 BandwidthConstraint.class,
213 LinkTypeConstraint.class, 218 LinkTypeConstraint.class,
219 + LatencyConstraint.class,
220 + WaypointConstraint.class,
221 + ObstacleConstraint.class,
222 + AnnotationConstraint.class,
214 BooleanConstraint.class 223 BooleanConstraint.class
215 ) 224 )
216 .register(DefaultApplicationId.class, new DefaultApplicationIdSerializer()) 225 .register(DefaultApplicationId.class, new DefaultApplicationIdSerializer())
......
...@@ -18,6 +18,8 @@ package org.onlab.onos.store.trivial.impl; ...@@ -18,6 +18,8 @@ package org.onlab.onos.store.trivial.impl;
18 import com.google.common.base.Function; 18 import com.google.common.base.Function;
19 import com.google.common.cache.Cache; 19 import com.google.common.cache.Cache;
20 import com.google.common.cache.CacheBuilder; 20 import com.google.common.cache.CacheBuilder;
21 +import com.google.common.cache.RemovalListener;
22 +import com.google.common.cache.RemovalNotification;
21 import com.google.common.collect.FluentIterable; 23 import com.google.common.collect.FluentIterable;
22 import com.google.common.util.concurrent.Futures; 24 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.SettableFuture; 25 import com.google.common.util.concurrent.SettableFuture;
...@@ -53,8 +55,10 @@ import java.util.List; ...@@ -53,8 +55,10 @@ import java.util.List;
53 import java.util.concurrent.ConcurrentHashMap; 55 import java.util.concurrent.ConcurrentHashMap;
54 import java.util.concurrent.ConcurrentMap; 56 import java.util.concurrent.ConcurrentMap;
55 import java.util.concurrent.CopyOnWriteArrayList; 57 import java.util.concurrent.CopyOnWriteArrayList;
58 +import java.util.concurrent.ExecutionException;
56 import java.util.concurrent.Future; 59 import java.util.concurrent.Future;
57 import java.util.concurrent.TimeUnit; 60 import java.util.concurrent.TimeUnit;
61 +import java.util.concurrent.TimeoutException;
58 import java.util.concurrent.atomic.AtomicInteger; 62 import java.util.concurrent.atomic.AtomicInteger;
59 63
60 import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; 64 import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
...@@ -86,8 +90,7 @@ public class SimpleFlowRuleStore ...@@ -86,8 +90,7 @@ public class SimpleFlowRuleStore
86 private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = 90 private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures =
87 CacheBuilder.newBuilder() 91 CacheBuilder.newBuilder()
88 .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) 92 .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES)
89 - // TODO Explicitly fail the future if expired? 93 + .removalListener(new TimeoutFuture())
90 - //.removalListener(listener)
91 .build(); 94 .build();
92 95
93 @Activate 96 @Activate
...@@ -303,4 +306,15 @@ public class SimpleFlowRuleStore ...@@ -303,4 +306,15 @@ public class SimpleFlowRuleStore
303 } 306 }
304 notifyDelegate(event); 307 notifyDelegate(event);
305 } 308 }
309 +
310 + private static final class TimeoutFuture
311 + implements RemovalListener<Integer, SettableFuture<CompletedBatchOperation>> {
312 + @Override
313 + public void onRemoval(RemovalNotification<Integer, SettableFuture<CompletedBatchOperation>> notification) {
314 + // wrapping in ExecutionException to support Future.get
315 + notification.getValue()
316 + .setException(new ExecutionException("Timed out",
317 + new TimeoutException()));
318 + }
319 + }
306 } 320 }
......
...@@ -197,6 +197,8 @@ ...@@ -197,6 +197,8 @@
197 <feature name="onos-app-sdnip" version="1.0.0" 197 <feature name="onos-app-sdnip" version="1.0.0"
198 description="SDN-IP peering application"> 198 description="SDN-IP peering application">
199 <feature>onos-api</feature> 199 <feature>onos-api</feature>
200 + <feature>onos-app-proxyarp</feature>
201 + <feature>onos-app-config</feature>
200 <bundle>mvn:org.onlab.onos/onos-app-sdnip/1.0.0-SNAPSHOT</bundle> 202 <bundle>mvn:org.onlab.onos/onos-app-sdnip/1.0.0-SNAPSHOT</bundle>
201 </feature> 203 </feature>
202 204
...@@ -225,4 +227,12 @@ ...@@ -225,4 +227,12 @@
225 <bundle>mvn:org.onlab.onos/onos-app-metrics-topology/1.0.0-SNAPSHOT</bundle> 227 <bundle>mvn:org.onlab.onos/onos-app-metrics-topology/1.0.0-SNAPSHOT</bundle>
226 </feature> 228 </feature>
227 229
230 + <feature name="onos-app-demo" version="1.0.0"
231 + description="ONOS demo applications">
232 + <feature>onos-api</feature>
233 + <bundle>mvn:org.onlab.onos/onos-app-demo/1.0.0-SNAPSHOT</bundle>
234 + </feature>
235 +
236 +
237 +
228 </features> 238 </features>
......
1 -onos-config command will copy files contained in this directory to ONOS instances according to cell definition 1 +The onos-config command will copy files contained in this directory to ONOS
2 - 2 +instances according to cell definition.
......
...@@ -10,4 +10,5 @@ ...@@ -10,4 +10,5 @@
10 [ "$1" = "-w" ] && shift && onos-wait-for-start $1 10 [ "$1" = "-w" ] && shift && onos-wait-for-start $1
11 11
12 [ -n "$1" ] && OCI=$(find_node $1) && shift 12 [ -n "$1" ] && OCI=$(find_node $1) && shift
13 +unset KARAF_HOME
13 client -h $OCI -u karaf "$@" 2>/dev/null 14 client -h $OCI -u karaf "$@" 2>/dev/null
......
...@@ -3,10 +3,7 @@ ...@@ -3,10 +3,7 @@
3 # Launches ONOS GUI on the specified node. 3 # Launches ONOS GUI on the specified node.
4 # ----------------------------------------------------------------------------- 4 # -----------------------------------------------------------------------------
5 5
6 -[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 -. $ONOS_ROOT/tools/build/envDefaults
8 -
9 host=${1:-$OCI} 6 host=${1:-$OCI}
10 host=${host:-localhost} 7 host=${host:-localhost}
11 8
12 -open http://$host:8181/onos/tvue 9 +open http://$host:8181/onos/ui
......
...@@ -40,6 +40,7 @@ fi ...@@ -40,6 +40,7 @@ fi
40 # Load the cell setup 40 # Load the cell setup
41 . $ONOS_ROOT/tools/test/cells/${cell} 41 . $ONOS_ROOT/tools/test/cells/${cell}
42 42
43 +echo "ONOS_CELL=${ONOS_CELL}"
43 echo "ONOS_NIC=${ONOS_NIC}" 44 echo "ONOS_NIC=${ONOS_NIC}"
44 for n in {0..9}; do 45 for n in {0..9}; do
45 ocn="OC${n}" 46 ocn="OC${n}"
......
...@@ -108,33 +108,26 @@ ...@@ -108,33 +108,26 @@
108 ], 108 ],
109 109
110 "links" : [ 110 "links" : [
111 - { "src": "of:0000ffffffffff01/10", "dst": "of:0000ffffffffff02/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 111 + { "src": "of:0000ffffffffff01/50", "dst": "of:0000ffffffffff02/30","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
112 - { "src": "of:0000ffffffffff02/10", "dst": "of:0000ffffffffff03/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 112 + { "src": "of:0000ffffffffff02/50", "dst": "of:0000ffffffffff03/30","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
113 - { "src": "of:0000ffffffffff03/30", "dst": "of:0000ffffffffff04/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 113 + { "src": "of:0000ffffffffff03/50", "dst": "of:0000ffffffffff04/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
114 - { "src": "of:0000ffffffffff02/20", "dst": "of:0000ffffffffff05/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 114 + { "src": "of:0000ffffffffff01/20", "dst": "of:0000ffffffffff05/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
115 - { "src": "of:0000ffffffffff03/20", "dst": "of:0000ffffffffff06/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 115 + { "src": "of:0000ffffffffff02/20", "dst": "of:0000ffffffffff05/20","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
116 - { "src": "of:0000ffffffffff05/30", "dst": "of:0000ffffffffff06/20", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 116 + { "src": "of:0000ffffffffff03/20", "dst": "of:0000ffffffffff06/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
117 - { "src": "of:0000ffffffffff05/20", "dst": "of:0000ffffffffff07/21", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 117 + { "src": "of:0000ffffffffff04/20", "dst": "of:0000ffffffffff06/20","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
118 - { "src": "of:0000ffffffffff06/30", "dst": "of:0000ffffffffff08/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 118 + { "src": "of:0000ffffffffff05/30", "dst": "of:0000ffffffffff06/40","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
119 - { "src": "of:0000ffffffffff07/30", "dst": "of:0000ffffffffff08/20", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 119 + { "src": "of:0000ffffffffff05/40", "dst": "of:0000ffffffffff07/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
120 - { "src": "of:0000ffffffffff07/20", "dst": "of:0000ffffffffff09/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 120 + { "src": "of:0000ffffffffff06/30", "dst": "of:0000ffffffffff08/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
121 - { "src": "of:0000ffffffffff08/30", "dst": "of:0000ffffffffff0A/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 121 + { "src": "of:0000ffffffffff07/20", "dst": "of:0000ffffffffff08/30", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
122 + { "src": "of:0000ffffffffff07/30", "dst": "of:0000ffffffffff09/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
123 + { "src": "of:0000ffffffffff08/20", "dst": "of:0000ffffffffff0A/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
122 { "src": "of:0000ffffffffff09/20", "dst": "of:0000ffffffffff0A/20", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, 124 { "src": "of:0000ffffffffff09/20", "dst": "of:0000ffffffffff0A/20", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } },
123 125
124 - { "src": "of:0000ffffffff0001/2", "dst": "of:0000ffffffffff01/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, 126 + { "src": "of:0000ffffffff0001/2", "dst": "of:0000ffffffffff01/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
125 - { "src": "of:0000ffffffff0003/2", "dst": "of:0000ffffffffff03/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, 127 + { "src": "of:0000ffffffff0002/2", "dst": "of:0000ffffffffff04/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
126 - { "src": "of:0000ffffffff0004/2", "dst": "of:0000ffffffffff04/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, 128 + { "src": "of:0000ffffffff0003/2", "dst": "of:0000ffffffffff06/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
127 - { "src": "of:0000ffffffff0007/2", "dst": "of:0000ffffffffff07/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, 129 + { "src": "of:0000ffffffff0004/2", "dst": "of:0000ffffffffff07/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
128 - { "src": "of:0000ffffffff0009/2", "dst": "of:0000ffffffffff09/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, 130 + { "src": "of:0000ffffffff0005/2", "dst": "of:0000ffffffffff09/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } },
129 - { "src": "of:0000ffffffff000A/2", "dst": "of:0000ffffffffff0A/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } } 131 + { "src": "of:0000ffffffff0006/2", "dst": "of:0000ffffffffff0A/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }
130 - ],
131 -
132 - "hosts" : [
133 - { "mac": "00:00:00:00:00:01", "vlan": -1, "location": "of:0000ffffffff0001/1", "ip": "10.0.0.1" },
134 - { "mac": "00:00:00:00:00:03", "vlan": -1, "location": "of:0000ffffffff0003/1", "ip": "10.0.0.3" },
135 - { "mac": "00:00:00:00:00:04", "vlan": -1, "location": "of:0000ffffffff0004/1", "ip": "10.0.0.4" },
136 - { "mac": "00:00:00:00:00:07", "vlan": -1, "location": "of:0000ffffffff0007/1", "ip": "10.0.0.7" },
137 - { "mac": "00:00:00:00:00:09", "vlan": -1, "location": "of:0000ffffffff0009/1", "ip": "10.0.0.9" },
138 - { "mac": "00:00:00:00:00:0A", "vlan": -1, "location": "of:0000ffffffff000A/1", "ip": "10.0.0.10" }
139 ] 132 ]
140 -}
...\ No newline at end of file ...\ No newline at end of file
133 +}
......
...@@ -43,9 +43,9 @@ public class ImmutableClassChecker { ...@@ -43,9 +43,9 @@ public class ImmutableClassChecker {
43 * @param clazz the class to check 43 * @param clazz the class to check
44 * @return true if the given class is a properly specified immutable class. 44 * @return true if the given class is a properly specified immutable class.
45 */ 45 */
46 - private boolean isImmutableClass(Class<?> clazz) { 46 + private boolean isImmutableClass(Class<?> clazz, boolean allowNonFinalClass) {
47 // class must be declared final 47 // class must be declared final
48 - if (!Modifier.isFinal(clazz.getModifiers())) { 48 + if (!allowNonFinalClass && !Modifier.isFinal(clazz.getModifiers())) {
49 failureReason = "a class that is not final"; 49 failureReason = "a class that is not final";
50 return false; 50 return false;
51 } 51 }
...@@ -113,16 +113,16 @@ public class ImmutableClassChecker { ...@@ -113,16 +113,16 @@ public class ImmutableClassChecker {
113 } 113 }
114 114
115 /** 115 /**
116 - * Assert that the given class adheres to the utility class rules. 116 + * Assert that the given class adheres to the immutable class rules.
117 * 117 *
118 * @param clazz the class to check 118 * @param clazz the class to check
119 * 119 *
120 - * @throws java.lang.AssertionError if the class is not a valid 120 + * @throws java.lang.AssertionError if the class is not an
121 - * utility class 121 + * immutable class
122 */ 122 */
123 public static void assertThatClassIsImmutable(Class<?> clazz) { 123 public static void assertThatClassIsImmutable(Class<?> clazz) {
124 final ImmutableClassChecker checker = new ImmutableClassChecker(); 124 final ImmutableClassChecker checker = new ImmutableClassChecker();
125 - if (!checker.isImmutableClass(clazz)) { 125 + if (!checker.isImmutableClass(clazz, false)) {
126 final Description toDescription = new StringDescription(); 126 final Description toDescription = new StringDescription();
127 final Description mismatchDescription = new StringDescription(); 127 final Description mismatchDescription = new StringDescription();
128 128
...@@ -136,4 +136,31 @@ public class ImmutableClassChecker { ...@@ -136,4 +136,31 @@ public class ImmutableClassChecker {
136 throw new AssertionError(reason); 136 throw new AssertionError(reason);
137 } 137 }
138 } 138 }
139 +
140 + /**
141 + * Assert that the given class adheres to the immutable class rules, but
142 + * is not declared final. Classes that need to be inherited from cannot be
143 + * declared final.
144 + *
145 + * @param clazz the class to check
146 + *
147 + * @throws java.lang.AssertionError if the class is not an
148 + * immutable class
149 + */
150 + public static void assertThatClassIsImmutableBaseClass(Class<?> clazz) {
151 + final ImmutableClassChecker checker = new ImmutableClassChecker();
152 + if (!checker.isImmutableClass(clazz, true)) {
153 + final Description toDescription = new StringDescription();
154 + final Description mismatchDescription = new StringDescription();
155 +
156 + checker.describeTo(toDescription);
157 + checker.describeMismatch(mismatchDescription);
158 + final String reason =
159 + "\n" +
160 + "Expected: is \"" + toDescription.toString() + "\"\n" +
161 + " but : was \"" + mismatchDescription.toString() + "\"";
162 +
163 + throw new AssertionError(reason);
164 + }
165 + }
139 } 166 }
......
...@@ -24,6 +24,7 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -24,6 +24,7 @@ import org.onlab.onos.cluster.ClusterService;
24 import org.onlab.onos.cluster.ControllerNode; 24 import org.onlab.onos.cluster.ControllerNode;
25 import org.onlab.onos.cluster.NodeId; 25 import org.onlab.onos.cluster.NodeId;
26 import org.onlab.onos.mastership.MastershipService; 26 import org.onlab.onos.mastership.MastershipService;
27 +import org.onlab.onos.net.Annotated;
27 import org.onlab.onos.net.Annotations; 28 import org.onlab.onos.net.Annotations;
28 import org.onlab.onos.net.ConnectPoint; 29 import org.onlab.onos.net.ConnectPoint;
29 import org.onlab.onos.net.DefaultEdgeLink; 30 import org.onlab.onos.net.DefaultEdgeLink;
...@@ -45,6 +46,8 @@ import org.onlab.onos.net.link.LinkService; ...@@ -45,6 +46,8 @@ import org.onlab.onos.net.link.LinkService;
45 import org.onlab.onos.net.provider.ProviderId; 46 import org.onlab.onos.net.provider.ProviderId;
46 import org.onlab.osgi.ServiceDirectory; 47 import org.onlab.osgi.ServiceDirectory;
47 import org.onlab.packet.IpAddress; 48 import org.onlab.packet.IpAddress;
49 +import org.slf4j.Logger;
50 +import org.slf4j.LoggerFactory;
48 51
49 import java.util.Iterator; 52 import java.util.Iterator;
50 import java.util.Map; 53 import java.util.Map;
...@@ -68,6 +71,8 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; ...@@ -68,6 +71,8 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
68 */ 71 */
69 public abstract class TopologyMessages { 72 public abstract class TopologyMessages {
70 73
74 + protected static final Logger log = LoggerFactory.getLogger(TopologyMessages.class);
75 +
71 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true); 76 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);
72 private static final String COMPACT = "%s/%s-%s/%s"; 77 private static final String COMPACT = "%s/%s-%s/%s";
73 78
...@@ -195,7 +200,7 @@ public abstract class TopologyMessages { ...@@ -195,7 +200,7 @@ public abstract class TopologyMessages {
195 .put("id", device.id().toString()) 200 .put("id", device.id().toString())
196 .put("type", device.type().toString().toLowerCase()) 201 .put("type", device.type().toString().toLowerCase())
197 .put("online", deviceService.isAvailable(device.id())) 202 .put("online", deviceService.isAvailable(device.id()))
198 - .put("master", mastershipService.getMasterFor(device.id()).toString()); 203 + .put("master", master(device.id()));
199 204
200 // Generate labels: id, chassis id, no-label, optional-name 205 // Generate labels: id, chassis id, no-label, optional-name
201 ArrayNode labels = mapper.createArrayNode(); 206 ArrayNode labels = mapper.createArrayNode();
...@@ -207,6 +212,7 @@ public abstract class TopologyMessages { ...@@ -207,6 +212,7 @@ public abstract class TopologyMessages {
207 // Add labels, props and stuff the payload into envelope. 212 // Add labels, props and stuff the payload into envelope.
208 payload.set("labels", labels); 213 payload.set("labels", labels);
209 payload.set("props", props(device.annotations())); 214 payload.set("props", props(device.annotations()));
215 + addGeoLocation(device, payload);
210 addMetaUi(device.id().toString(), payload); 216 addMetaUi(device.id().toString(), payload);
211 217
212 String type = (event.type() == DEVICE_ADDED) ? "addDevice" : 218 String type = (event.type() == DEVICE_ADDED) ? "addDevice" :
...@@ -220,6 +226,7 @@ public abstract class TopologyMessages { ...@@ -220,6 +226,7 @@ public abstract class TopologyMessages {
220 ObjectNode payload = mapper.createObjectNode() 226 ObjectNode payload = mapper.createObjectNode()
221 .put("id", compactLinkString(link)) 227 .put("id", compactLinkString(link))
222 .put("type", link.type().toString().toLowerCase()) 228 .put("type", link.type().toString().toLowerCase())
229 + .put("online", true) // TODO: add link state field
223 .put("linkWidth", 2) 230 .put("linkWidth", 2)
224 .put("src", link.src().deviceId().toString()) 231 .put("src", link.src().deviceId().toString())
225 .put("srcPort", link.src().port().toString()) 232 .put("srcPort", link.src().port().toString())
...@@ -237,10 +244,11 @@ public abstract class TopologyMessages { ...@@ -237,10 +244,11 @@ public abstract class TopologyMessages {
237 .put("id", host.id().toString()) 244 .put("id", host.id().toString())
238 .put("ingress", compactLinkString(edgeLink(host, true))) 245 .put("ingress", compactLinkString(edgeLink(host, true)))
239 .put("egress", compactLinkString(edgeLink(host, false))); 246 .put("egress", compactLinkString(edgeLink(host, false)));
240 - payload.set("cp", location(mapper, host.location())); 247 + payload.set("cp", hostConnect(mapper, host.location()));
241 payload.set("labels", labels(mapper, ip(host.ipAddresses()), 248 payload.set("labels", labels(mapper, ip(host.ipAddresses()),
242 host.mac().toString())); 249 host.mac().toString()));
243 payload.set("props", props(host.annotations())); 250 payload.set("props", props(host.annotations()));
251 + addGeoLocation(host, payload);
244 addMetaUi(host.id().toString(), payload); 252 addMetaUi(host.id().toString(), payload);
245 253
246 String type = (event.type() == HOST_ADDED) ? "addHost" : 254 String type = (event.type() == HOST_ADDED) ? "addHost" :
...@@ -249,7 +257,7 @@ public abstract class TopologyMessages { ...@@ -249,7 +257,7 @@ public abstract class TopologyMessages {
249 } 257 }
250 258
251 // Encodes the specified host location into a JSON object. 259 // Encodes the specified host location into a JSON object.
252 - private ObjectNode location(ObjectMapper mapper, HostLocation location) { 260 + private ObjectNode hostConnect(ObjectMapper mapper, HostLocation location) {
253 return mapper.createObjectNode() 261 return mapper.createObjectNode()
254 .put("device", location.deviceId().toString()) 262 .put("device", location.deviceId().toString())
255 .put("port", location.port().toLong()); 263 .put("port", location.port().toLong());
...@@ -264,6 +272,12 @@ public abstract class TopologyMessages { ...@@ -264,6 +272,12 @@ public abstract class TopologyMessages {
264 return json; 272 return json;
265 } 273 }
266 274
275 + // Returns the name of the master node for the specified device id.
276 + private String master(DeviceId deviceId) {
277 + NodeId master = mastershipService.getMasterFor(deviceId);
278 + return master != null ? master.toString() : "";
279 + }
280 +
267 // Generates an edge link from the specified host location. 281 // Generates an edge link from the specified host location.
268 private EdgeLink edgeLink(Host host, boolean ingress) { 282 private EdgeLink edgeLink(Host host, boolean ingress) {
269 return new DefaultEdgeLink(PID, new ConnectPoint(host.id(), portNumber(0)), 283 return new DefaultEdgeLink(PID, new ConnectPoint(host.id(), portNumber(0)),
...@@ -278,10 +292,28 @@ public abstract class TopologyMessages { ...@@ -278,10 +292,28 @@ public abstract class TopologyMessages {
278 } 292 }
279 } 293 }
280 294
295 + // Adds a geo location JSON to the specified payload object.
296 + private void addGeoLocation(Annotated annotated, ObjectNode payload) {
297 + Annotations annotations = annotated.annotations();
298 + String slat = annotations.value("latitude");
299 + String slng = annotations.value("longitude");
300 + try {
301 + if (slat != null && slng != null && !slat.isEmpty() && !slng.isEmpty()) {
302 + double lat = Double.parseDouble(slat);
303 + double lng = Double.parseDouble(slng);
304 + ObjectNode loc = mapper.createObjectNode()
305 + .put("type", "latlng").put("lat", lat).put("lng", lng);
306 + payload.set("location", loc);
307 + }
308 + } catch (NumberFormatException e) {
309 + log.warn("Invalid geo data latitude={}; longiture={}", slat, slng);
310 + }
311 + }
312 +
281 // Updates meta UI information for the specified object. 313 // Updates meta UI information for the specified object.
282 protected void updateMetaUi(ObjectNode event) { 314 protected void updateMetaUi(ObjectNode event) {
283 ObjectNode payload = payload(event); 315 ObjectNode payload = payload(event);
284 - metaUi.put(string(payload, "id"), payload); 316 + metaUi.put(string(payload, "id"), (ObjectNode) payload.path("memento"));
285 } 317 }
286 318
287 // Returns device details response. 319 // Returns device details response.
...@@ -289,7 +321,6 @@ public abstract class TopologyMessages { ...@@ -289,7 +321,6 @@ public abstract class TopologyMessages {
289 Device device = deviceService.getDevice(deviceId); 321 Device device = deviceService.getDevice(deviceId);
290 Annotations annot = device.annotations(); 322 Annotations annot = device.annotations();
291 int portCount = deviceService.getPorts(deviceId).size(); 323 int portCount = deviceService.getPorts(deviceId).size();
292 - NodeId master = mastershipService.getMasterFor(device.id());
293 return envelope("showDetails", sid, 324 return envelope("showDetails", sid,
294 json(deviceId.toString(), 325 json(deviceId.toString(),
295 device.type().toString().toLowerCase(), 326 device.type().toString().toLowerCase(),
...@@ -303,7 +334,7 @@ public abstract class TopologyMessages { ...@@ -303,7 +334,7 @@ public abstract class TopologyMessages {
303 new Prop("Longitude", annot.value("longitude")), 334 new Prop("Longitude", annot.value("longitude")),
304 new Prop("Ports", Integer.toString(portCount)), 335 new Prop("Ports", Integer.toString(portCount)),
305 new Separator(), 336 new Separator(),
306 - new Prop("Master", master.toString()))); 337 + new Prop("Master", master(deviceId))));
307 } 338 }
308 339
309 // Returns host details response. 340 // Returns host details response.
...@@ -319,16 +350,15 @@ public abstract class TopologyMessages { ...@@ -319,16 +350,15 @@ public abstract class TopologyMessages {
319 new Prop("Longitude", annot.value("longitude")))); 350 new Prop("Longitude", annot.value("longitude"))));
320 } 351 }
321 352
322 -
323 // Produces a path message to the client. 353 // Produces a path message to the client.
324 - protected ObjectNode pathMessage(Path path) { 354 + protected ObjectNode pathMessage(Path path, String type) {
325 ObjectNode payload = mapper.createObjectNode(); 355 ObjectNode payload = mapper.createObjectNode();
326 ArrayNode links = mapper.createArrayNode(); 356 ArrayNode links = mapper.createArrayNode();
327 for (Link link : path.links()) { 357 for (Link link : path.links()) {
328 links.add(compactLinkString(link)); 358 links.add(compactLinkString(link));
329 } 359 }
330 360
331 - payload.set("links", links); 361 + payload.put("type", type).set("links", links);
332 return payload; 362 return payload;
333 } 363 }
334 364
......
...@@ -110,8 +110,8 @@ public class TopologyWebSocket ...@@ -110,8 +110,8 @@ public class TopologyWebSocket
110 try { 110 try {
111 ObjectNode event = (ObjectNode) mapper.reader().readTree(data); 111 ObjectNode event = (ObjectNode) mapper.reader().readTree(data);
112 String type = string(event, "event", "unknown"); 112 String type = string(event, "event", "unknown");
113 - if (type.equals("showDetails")) { 113 + if (type.equals("requestDetails")) {
114 - showDetails(event); 114 + requestDetails(event);
115 } else if (type.equals("updateMeta")) { 115 } else if (type.equals("updateMeta")) {
116 updateMetaUi(event); 116 updateMetaUi(event);
117 } else if (type.equals("requestPath")) { 117 } else if (type.equals("requestPath")) {
...@@ -122,7 +122,7 @@ public class TopologyWebSocket ...@@ -122,7 +122,7 @@ public class TopologyWebSocket
122 cancelTraffic(event); 122 cancelTraffic(event);
123 } 123 }
124 } catch (Exception e) { 124 } catch (Exception e) {
125 - System.out.println("WTF?! " + data); 125 + log.warn("Unable to parse GUI request {} due to {}", data, e);
126 e.printStackTrace(); 126 e.printStackTrace();
127 } 127 }
128 } 128 }
...@@ -165,9 +165,9 @@ public class TopologyWebSocket ...@@ -165,9 +165,9 @@ public class TopologyWebSocket
165 } 165 }
166 166
167 // Sends back device or host details. 167 // Sends back device or host details.
168 - private void showDetails(ObjectNode event) { 168 + private void requestDetails(ObjectNode event) {
169 ObjectNode payload = payload(event); 169 ObjectNode payload = payload(event);
170 - String type = string(payload, "type", "unknown"); 170 + String type = string(payload, "class", "unknown");
171 if (type.equals("device")) { 171 if (type.equals("device")) {
172 sendMessage(deviceDetails(deviceId(string(payload, "id")), 172 sendMessage(deviceDetails(deviceId(string(payload, "id")),
173 number(event, "sid"))); 173 number(event, "sid")));
...@@ -282,7 +282,8 @@ public class TopologyWebSocket ...@@ -282,7 +282,8 @@ public class TopologyWebSocket
282 if (installable != null && !installable.isEmpty()) { 282 if (installable != null && !installable.isEmpty()) {
283 PathIntent pathIntent = (PathIntent) installable.iterator().next(); 283 PathIntent pathIntent = (PathIntent) installable.iterator().next();
284 Path path = pathIntent.path(); 284 Path path = pathIntent.path();
285 - ObjectNode payload = pathMessage(path).put("intentId", intent.id().toString()); 285 + ObjectNode payload = pathMessage(path, "host")
286 + .put("intentId", intent.id().toString());
286 sendMessage(envelope("showPath", sid, payload)); 287 sendMessage(envelope("showPath", sid, payload));
287 } 288 }
288 } 289 }
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
21 <display-name>ONOS GUI</display-name> 21 <display-name>ONOS GUI</display-name>
22 22
23 <welcome-file-list> 23 <welcome-file-list>
24 - <welcome-file>index.html</welcome-file> 24 + <welcome-file>index2.html</welcome-file>
25 </welcome-file-list> 25 </welcome-file-list>
26 26
27 <servlet> 27 <servlet>
......
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/*
18 + ONOS GUI -- Floating Panels -- CSS file
19 +
20 + @author Simon Hunt
21 + */
22 +
23 +.fpanel {
24 + position: absolute;
25 + z-index: 100;
26 + display: block;
27 + top: 10%;
28 + width: 280px;
29 + right: -300px;
30 + opacity: 0;
31 + background-color: rgba(255,255,255,0.8);
32 +
33 + padding: 10px;
34 + color: black;
35 + font-size: 10pt;
36 + box-shadow: 2px 2px 16px #777;
37 +}
38 +
39 +/* TODO: light/dark themes */
40 +.light .fpanel {
41 +
42 +}
43 +.dark .fpanel {
44 +
45 +}
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
40 <link rel="stylesheet" href="base.css"> 40 <link rel="stylesheet" href="base.css">
41 <link rel="stylesheet" href="onos2.css"> 41 <link rel="stylesheet" href="onos2.css">
42 <link rel="stylesheet" href="mast2.css"> 42 <link rel="stylesheet" href="mast2.css">
43 + <link rel="stylesheet" href="floatPanel.css">
43 44
44 <!-- This is where contributed stylesheets get INJECTED --> 45 <!-- This is where contributed stylesheets get INJECTED -->
45 <!-- TODO: replace with template marker and inject refs server-side --> 46 <!-- TODO: replace with template marker and inject refs server-side -->
...@@ -62,8 +63,9 @@ ...@@ -62,8 +63,9 @@
62 <div id="view"> 63 <div id="view">
63 <!-- NOTE: views injected here by onos.js --> 64 <!-- NOTE: views injected here by onos.js -->
64 </div> 65 </div>
65 - <div id="overlays"> 66 + <div id="floatPanels">
66 - <!-- NOTE: overlays injected here, as needed --> 67 + <!-- NOTE: floating panels injected here, as needed -->
68 + <!-- see onos.ui.addFloatingPanel -->
67 </div> 69 </div>
68 <div id="alerts"> 70 <div id="alerts">
69 <!-- NOTE: alert content injected here, as needed --> 71 <!-- NOTE: alert content injected here, as needed -->
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
10 "", 10 "",
11 null 11 null
12 ], 12 ],
13 - "props": {} 13 + "props": {
14 + "latitude": 123.5,
15 + "longitude": 67.8,
16 + "anotherProp": "foobar"
17 + }
14 } 18 }
15 } 19 }
......
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000000000000003",
5 + "type": "switch",
6 + "online": true,
7 + "labels": [
8 + "of:0000000000000003",
9 + "3",
10 + "",
11 + null
12 + ],
13 + "props": {
14 + "latitude": 123.5,
15 + "longitude": 67.8,
16 + "anotherProp": "foobar"
17 + },
18 + "metaUi": {
19 + "xpc": 57.3,
20 + "ypc": 24.86,
21 + "and": "other properties the UI wishes to remember..."
22 + }
23 + }
24 +}
1 +{
2 + "event": "showDetails",
3 + "sid": 9,
4 + "payload": {
5 + "id": "CA:4B:EE:A4:B0:33/-1",
6 + "type": "host",
7 + "propOrder": [
8 + "MAC",
9 + "IP",
10 + "-",
11 + "Latitude",
12 + "Longitude"
13 + ],
14 + "props": {
15 + "MAC": "CA:4B:EE:A4:B0:33",
16 + "IP": "[10.0.0.1]",
17 + "-": "",
18 + "Latitude": null,
19 + "Longitude": null
20 + }
21 + }
22 +}
1 +{
2 + "event": "showDetails",
3 + "sid": 37,
4 + "payload": {
5 + "id": "of:000000000000000a",
6 + "type": "switch",
7 + "propOrder": [
8 + "Name",
9 + "Vendor",
10 + "H/W Version",
11 + "S/W Version",
12 + "Serial Number",
13 + "-",
14 + "Latitude",
15 + "Longitude",
16 + "Ports",
17 + "-",
18 + "Master"
19 + ],
20 + "props": {
21 + "Name": null,
22 + "Vendor": "Nicira, Inc.",
23 + "H/W Version": "Open vSwitch",
24 + "S/W Version": "2.0.1",
25 + "Serial Number": "None",
26 + "-": "",
27 + "Latitude": null,
28 + "Longitude": null,
29 + "Ports": "5",
30 + "Master":"local"
31 + }
32 + }
33 +}
1 { 1 {
2 - "event": "noop", 2 + "event": "requestDetails",
3 + "sid": 15,
3 "payload": { 4 "payload": {
4 - "id": "xyyzy" 5 + "id": "of:0000000000000003",
6 + "class": "device"
5 } 7 }
6 } 8 }
9 +
......
1 +{
2 + "event": "requestDetails",
3 + "sid": 9,
4 + "payload": {
5 + "id": "CA:4B:EE:A4:B0:33/-1",
6 + "class": "host"
7 + }
8 +}
...@@ -4,7 +4,11 @@ ...@@ -4,7 +4,11 @@
4 "payload": { 4 "payload": {
5 "id": "62:4F:65:BF:FF:B3/-1", 5 "id": "62:4F:65:BF:FF:B3/-1",
6 "class": "host", 6 "class": "host",
7 - "x": 197, 7 + "memento": {
8 - "y": 177 8 + "xpc": 57.3,
9 + "ypc": 24.86,
10 + "and": "other properties the UI wishes to remember..."
11 + }
9 } 12 }
10 } 13 }
14 +
......
...@@ -5,5 +5,9 @@ ...@@ -5,5 +5,9 @@
5 "title": "Host Intent Scenario", 5 "title": "Host Intent Scenario",
6 "params": { 6 "params": {
7 "lastAuto": 0 7 "lastAuto": 0
8 - } 8 + },
9 + "description": [
10 + "Currently this is just a sketch of the event sequence,",
11 + " but is NOT YET a runnable scenario."
12 + ]
9 } 13 }
...\ No newline at end of file ...\ No newline at end of file
......
1 +{
2 + "event": "removeHost",
3 + "payload": {
4 + "id": "A6:96:E5:03:52:5F/-1",
5 + "ingress": "A6:96:E5:03:52:5F/-1/0-of:0000ffffffff0008/1",
6 + "egress": "of:0000ffffffff0008/1-A6:96:E5:03:52:5F/-1/0",
7 + "cp": {
8 + "device": "of:0000ffffffff0008",
9 + "port": 1
10 + },
11 + "labels": [
12 + "10.0.0.17",
13 + "A6:96:E5:03:52:5F"
14 + ],
15 + "props": {}
16 + }
17 +}
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
4 "id": "of:0000ffffffff0008", 4 "id": "of:0000ffffffff0008",
5 "type": "switch", 5 "type": "switch",
6 "online": false, 6 "online": false,
7 + "location": {
8 + "type": "latlng",
9 + "lat": 37.6,
10 + "lng": 122.3
11 + },
7 "labels": [ 12 "labels": [
8 "0000ffffffff0008", 13 "0000ffffffff0008",
9 "FF:FF:FF:FF:00:08", 14 "FF:FF:FF:FF:00:08",
......
...@@ -20,6 +20,6 @@ ...@@ -20,6 +20,6 @@
20 "10. update link (increase width, update props)", 20 "10. update link (increase width, update props)",
21 "11. update link (reduce width, update props)", 21 "11. update link (reduce width, update props)",
22 "12. remove link", 22 "12. remove link",
23 - "" 23 + "13. remove host (10.0.0.17)"
24 ] 24 ]
25 -}
...\ No newline at end of file ...\ No newline at end of file
25 +}
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffffff04", 4 "id": "of:0000ffffffffff04",
5 "type": "roadm", 5 "type": "roadm",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffffff04", 8 "0000ffffffffff04",
9 "FF:FF:FF:FF:FF:04", 9 "FF:FF:FF:FF:FF:04",
......
...@@ -3,15 +3,15 @@ ...@@ -3,15 +3,15 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffff000A", 4 "id": "of:0000ffffffff000A",
5 "type": "switch", 5 "type": "switch",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffff000A", 8 "0000ffffffff000A",
9 "FF:FF:FF:FF:00:0A", 9 "FF:FF:FF:FF:00:0A",
10 "?" 10 "?"
11 ], 11 ],
12 "metaUi": { 12 "metaUi": {
13 - "Zx": 832, 13 + "x": 832,
14 - "Zy": 223 14 + "y": 223
15 } 15 }
16 } 16 }
17 } 17 }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffff0001", 4 "id": "of:0000ffffffff0001",
5 "type": "switch", 5 "type": "switch",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffff0001", 8 "0000ffffffff0001",
9 "FF:FF:FF:FF:00:01", 9 "FF:FF:FF:FF:00:01",
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffffff01", 4 "id": "of:0000ffffffffff01",
5 "type": "roadm", 5 "type": "roadm",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffffff01", 8 "0000ffffffffff01",
9 "FF:FF:FF:FF:FF:01", 9 "FF:FF:FF:FF:FF:01",
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffff0004", 4 "id": "of:0000ffffffff0004",
5 "type": "switch", 5 "type": "switch",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffff0004", 8 "0000ffffffff0004",
9 "FF:FF:FF:FF:00:04", 9 "FF:FF:FF:FF:00:04",
......
...@@ -3,15 +3,15 @@ ...@@ -3,15 +3,15 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffffff0A", 4 "id": "of:0000ffffffffff0A",
5 "type": "roadm", 5 "type": "roadm",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffffff0A", 8 "0000ffffffffff0A",
9 "FF:FF:FF:FF:FF:0A", 9 "FF:FF:FF:FF:FF:0A",
10 "?" 10 "?"
11 ], 11 ],
12 "metaUi": { 12 "metaUi": {
13 - "Zx": 840, 13 + "x": 840,
14 - "Zy": 290 14 + "y": 290
15 } 15 }
16 } 16 }
17 } 17 }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffffff09", 4 "id": "of:0000ffffffffff09",
5 "type": "roadm", 5 "type": "roadm",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffffff09", 8 "0000ffffffffff09",
9 "FF:FF:FF:FF:FF:09", 9 "FF:FF:FF:FF:FF:09",
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff02/20-of:0000ffffffffff05/10",
5 + "type": "optical",
6 + "linkWidth": 4,
4 "src": "of:0000ffffffffff02", 7 "src": "of:0000ffffffffff02",
5 "srcPort": "20", 8 "srcPort": "20",
6 "dst": "of:0000ffffffffff05", 9 "dst": "of:0000ffffffffff05",
7 "dstPort": "10", 10 "dstPort": "10",
8 - "type": "optical",
9 - "linkWidth": 6,
10 "props" : { 11 "props" : {
11 "BW": "80 G" 12 "BW": "80 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffff000A/2-of:0000ffffffffff0A/1",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffff000A", 7 "src": "of:0000ffffffff000A",
5 "srcPort": "2", 8 "srcPort": "2",
6 "dst": "of:0000ffffffffff0A", 9 "dst": "of:0000ffffffffff0A",
7 "dstPort": "1", 10 "dstPort": "1",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "100 G" 12 "BW": "100 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff03/10-of:0000ffffffffff02/10",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffffff03", 7 "src": "of:0000ffffffffff03",
5 "srcPort": "10", 8 "srcPort": "10",
6 "dst": "of:0000ffffffffff02", 9 "dst": "of:0000ffffffffff02",
7 "dstPort": "10", 10 "dstPort": "10",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffffff08", 4 "id": "of:0000ffffffffff08",
5 "type": "roadm", 5 "type": "roadm",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffffff08", 8 "0000ffffffffff08",
9 "FF:FF:FF:FF:FF:08", 9 "FF:FF:FF:FF:FF:08",
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff07/21-of:0000ffffffffff05/20",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffffff07", 7 "src": "of:0000ffffffffff07",
5 "srcPort": "21", 8 "srcPort": "21",
6 "dst": "of:0000ffffffffff05", 9 "dst": "of:0000ffffffffff05",
7 "dstPort": "20", 10 "dstPort": "20",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffff0001/2-of:0000ffffffffff01/1",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffff0001", 7 "src": "of:0000ffffffff0001",
5 "srcPort": "2", 8 "srcPort": "2",
6 "dst": "of:0000ffffffffff01", 9 "dst": "of:0000ffffffffff01",
7 "dstPort": "1", 10 "dstPort": "1",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff09/20-of:0000ffffffffff0A/20",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffffff09", 7 "src": "of:0000ffffffffff09",
5 "srcPort": "20", 8 "srcPort": "20",
6 "dst": "of:0000ffffffffff0A", 9 "dst": "of:0000ffffffffff0A",
7 "dstPort": "20", 10 "dstPort": "20",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 - "src": "of:0000ffffffffff06", 4 + "id": "of:0000ffffffffff07/30-of:0000ffffffffff08/20",
5 - "srcPort": "20",
6 - "dst": "of:0000ffffffffff05",
7 - "dstPort": "30",
8 "type": "optical", 5 "type": "optical",
9 - "linkWidth": 6, 6 + "linkWidth": 4,
7 + "src": "of:0000ffffffffff07",
8 + "srcPort": "30",
9 + "dst": "of:0000ffffffffff08",
10 + "dstPort": "20",
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 - "src": "of:0000ffffffffff07", 4 + "id": "of:0000ffffffffff02/10-of:0000ffffffffff01/10",
5 - "srcPort": "30",
6 - "dst": "of:0000ffffffffff08",
7 - "dstPort": "20",
8 "type": "optical", 5 "type": "optical",
9 - "linkWidth": 6, 6 + "linkWidth": 2,
7 + "src": "of:0000ffffffffff02",
8 + "srcPort": "10",
9 + "dst": "of:0000ffffffffff01",
10 + "dstPort": "10",
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 - "src": "of:0000ffffffffff03", 4 + "id": "of:0000ffffffffff04/27-of:0000ffffffffff08/10",
5 - "srcPort": "20", 5 + "src": "of:0000ffffffffff04",
6 - "dst": "of:0000ffffffffff06", 6 + "srcPort": "27",
7 + "dst": "of:0000ffffffffff08",
7 "dstPort": "10", 8 "dstPort": "10",
8 "type": "optical", 9 "type": "optical",
9 "linkWidth": 2, 10 "linkWidth": 2,
10 "props" : { 11 "props" : {
11 - "BW": "70 G" 12 + "BW": "30 G"
12 } 13 }
13 } 14 }
14 } 15 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 - "src": "of:0000ffffffffff02", 4 + "id": "of:0000ffffffff0003/2-of:0000ffffffffff03/1",
5 - "srcPort": "10",
6 - "dst": "of:0000ffffffffff01",
7 - "dstPort": "10",
8 "type": "optical", 5 "type": "optical",
9 "linkWidth": 2, 6 "linkWidth": 2,
7 + "src": "of:0000ffffffff0003",
8 + "srcPort": "2",
9 + "dst": "of:0000ffffffffff03",
10 + "dstPort": "1",
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff09/1-of:0000ffffffff0009/2",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffffff09", 7 "src": "of:0000ffffffffff09",
5 "srcPort": "1", 8 "srcPort": "1",
6 "dst": "of:0000ffffffff0009", 9 "dst": "of:0000ffffffff0009",
7 "dstPort": "2", 10 "dstPort": "2",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff03/30-of:0000ffffffffff04/10",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffffff03", 7 "src": "of:0000ffffffffff03",
5 "srcPort": "30", 8 "srcPort": "30",
6 "dst": "of:0000ffffffffff04", 9 "dst": "of:0000ffffffffff04",
7 "dstPort": "10", 10 "dstPort": "10",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff07/20-of:0000ffffffffff09/10",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffffff07", 7 "src": "of:0000ffffffffff07",
5 "srcPort": "20", 8 "srcPort": "20",
6 "dst": "of:0000ffffffffff09", 9 "dst": "of:0000ffffffffff09",
7 "dstPort": "10", 10 "dstPort": "10",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 "payload": { 3 "payload": {
4 "id": "of:0000ffffffffff03", 4 "id": "of:0000ffffffffff03",
5 "type": "roadm", 5 "type": "roadm",
6 - "online": false, 6 + "online": true,
7 "labels": [ 7 "labels": [
8 "0000ffffffffff03", 8 "0000ffffffffff03",
9 "FF:FF:FF:FF:FF:03", 9 "FF:FF:FF:FF:FF:03",
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff0A/10-of:0000ffffffffff08/30",
5 + "type": "optical",
6 + "linkWidth": 4,
4 "src": "of:0000ffffffffff0A", 7 "src": "of:0000ffffffffff0A",
5 "srcPort": "10", 8 "srcPort": "10",
6 "dst": "of:0000ffffffffff08", 9 "dst": "of:0000ffffffffff08",
7 "dstPort": "30", 10 "dstPort": "30",
8 - "type": "optical",
9 - "linkWidth": 6,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffff0004/2-of:0000ffffffffff04/1",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffff0004", 7 "src": "of:0000ffffffff0004",
5 "srcPort": "2", 8 "srcPort": "2",
6 "dst": "of:0000ffffffffff04", 9 "dst": "of:0000ffffffffff04",
7 "dstPort": "1", 10 "dstPort": "1",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff07/1-of:0000ffffffff0007/2",
5 + "type": "optical",
6 + "linkWidth": 2,
4 "src": "of:0000ffffffffff07", 7 "src": "of:0000ffffffffff07",
5 "srcPort": "1", 8 "srcPort": "1",
6 "dst": "of:0000ffffffff0007", 9 "dst": "of:0000ffffffff0007",
7 "dstPort": "2", 10 "dstPort": "2",
8 - "type": "optical",
9 - "linkWidth": 2,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 - "event": "addLink", 2 + "event": "updateDevice",
3 "payload": { 3 "payload": {
4 - "src": "of:0000ffffffff0003", 4 + "id": "of:0000ffffffffff06",
5 - "srcPort": "2", 5 + "type": "roadm",
6 - "dst": "of:0000ffffffffff03", 6 + "online": true,
7 - "dstPort": "1", 7 + "labels": [
8 - "type": "optical", 8 + "0000ffffffffff06",
9 - "linkWidth": 2, 9 + "FF:FF:FF:FF:FF:06",
10 - "props" : { 10 + "?"
11 - "BW": "70 G" 11 + ],
12 + "metaUi": {
13 + "x": 336,
14 + "y": 254
12 } 15 }
13 } 16 }
14 } 17 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 + "id": "of:0000ffffffffff06/20-of:0000ffffffffff05/30",
4 "src": "of:0000ffffffffff06", 5 "src": "of:0000ffffffffff06",
5 - "srcPort": "30", 6 + "srcPort": "20",
6 - "dst": "of:0000ffffffffff08", 7 + "dst": "of:0000ffffffffff05",
7 - "dstPort": "10", 8 + "dstPort": "30",
8 "type": "optical", 9 "type": "optical",
9 - "linkWidth": 6, 10 + "linkWidth": 4,
10 "props" : { 11 "props" : {
11 "BW": "70 G" 12 "BW": "70 G"
12 } 13 }
......
1 { 1 {
2 "event": "addLink", 2 "event": "addLink",
3 "payload": { 3 "payload": {
4 - "src": "of:0000ffffffffff04", 4 + "id": "of:0000ffffffffff03/20-of:0000ffffffffff06/10",
5 - "srcPort": "27",
6 - "dst": "of:0000ffffffffff08",
7 - "dstPort": "10",
8 "type": "optical", 5 "type": "optical",
9 "linkWidth": 2, 6 "linkWidth": 2,
7 + "src": "of:0000ffffffffff03",
8 + "srcPort": "20",
9 + "dst": "of:0000ffffffffff06",
10 + "dstPort": "10",
10 "props" : { 11 "props" : {
11 - "BW": "30 G" 12 + "BW": "70 G"
12 } 13 }
13 } 14 }
14 } 15 }
......
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "id": "of:0000ffffffffff06/30-of:0000ffffffffff08/10",
5 + "type": "optical",
6 + "linkWidth": 4,
7 + "src": "of:0000ffffffffff06",
8 + "srcPort": "30",
9 + "dst": "of:0000ffffffffff08",
10 + "dstPort": "10",
11 + "props" : {
12 + "BW": "70 G"
13 + }
14 + }
15 +}
1 +{
2 + "event": "updateDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff08",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff08",
9 + "FF:FF:FF:FF:FF:08",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 539,
14 + "y": 186
15 + }
16 + }
17 +}
1 +{
2 + "event": "removeLink",
3 + "payload": {
4 + "id": "of:0000ffffffffff07/30-of:0000ffffffffff08/20",
5 + "type": "optical",
6 + "linkWidth": 4,
7 + "src": "of:0000ffffffffff07",
8 + "srcPort": "30",
9 + "dst": "of:0000ffffffffff08",
10 + "dstPort": "20",
11 + "props" : {
12 + "BW": "70 G"
13 + }
14 + }
15 +}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.