Naoki Shiota
Committed by Gerrit Code Review

Made OpticalPathProvisioner to store connectivity data in distributed store. (ONOS-4518)

Change-Id: I7f9ef02cab4aa1848c8926d2e88478e035076c99
1 COMPILE_DEPS = [ 1 COMPILE_DEPS = [
2 '//lib:CORE_DEPS', 2 '//lib:CORE_DEPS',
3 + '//core/store/serializers:onos-core-serializers',
3 '//lib:org.apache.karaf.shell.console', 4 '//lib:org.apache.karaf.shell.console',
4 '//cli:onos-cli', 5 '//cli:onos-cli',
5 ] 6 ]
......
...@@ -89,6 +89,12 @@ ...@@ -89,6 +89,12 @@
89 </dependency> 89 </dependency>
90 90
91 <dependency> 91 <dependency>
92 + <groupId>org.onosproject</groupId>
93 + <artifactId>onos-core-serializers</artifactId>
94 + <version>${project.version}</version>
95 + </dependency>
96 +
97 + <dependency>
92 <groupId>com.google.guava</groupId> 98 <groupId>com.google.guava</groupId>
93 <artifactId>guava-testlib</artifactId> 99 <artifactId>guava-testlib</artifactId>
94 <scope>test</scope> 100 <scope>test</scope>
......
...@@ -22,14 +22,14 @@ import org.onlab.util.Bandwidth; ...@@ -22,14 +22,14 @@ import org.onlab.util.Bandwidth;
22 import org.onosproject.newoptical.api.OpticalConnectivityId; 22 import org.onosproject.newoptical.api.OpticalConnectivityId;
23 import org.onosproject.net.ConnectPoint; 23 import org.onosproject.net.ConnectPoint;
24 import org.onosproject.net.Link; 24 import org.onosproject.net.Link;
25 -import org.onosproject.net.Path;
26 25
27 import java.time.Duration; 26 import java.time.Duration;
28 -import java.util.HashSet;
29 import java.util.List; 27 import java.util.List;
28 +import java.util.Optional;
30 import java.util.Set; 29 import java.util.Set;
30 +import java.util.stream.Collectors;
31 31
32 -import static com.google.common.base.Preconditions.checkNotNull; 32 +import static com.google.common.base.Preconditions.checkState;
33 33
34 /** 34 /**
35 * Entity to store optical connectivity request and related information. 35 * Entity to store optical connectivity request and related information.
...@@ -42,48 +42,48 @@ public class OpticalConnectivity { ...@@ -42,48 +42,48 @@ public class OpticalConnectivity {
42 private final Bandwidth requestBandwidth; 42 private final Bandwidth requestBandwidth;
43 private final Duration requestLatency; 43 private final Duration requestLatency;
44 44
45 - // Bandwidth capacity of optical layer 45 + /**
46 - private Bandwidth opticalCapacity; 46 + * Set of packet link that is not yet established.
47 - 47 + * Packet links in this set are expected to be discovered after underlying (optical) path has been provisioned.
48 - private final Set<PacketLinkRealizedByOptical> realizingLinks = new HashSet<>(); 48 + */
49 - 49 + private final ImmutableSet<PacketLinkRealizedByOptical> unestablishedLinks;
50 - private State state = State.CREATED;
51 -
52 - public enum State {
53 - CREATED,
54 - INSTALLING,
55 - INSTALLED,
56 - WITHDRAWING,
57 - WITHDRAWN,
58 - FAILED
59 - }
60 50
61 - public OpticalConnectivity(OpticalConnectivityId id, Path path, Bandwidth requestBandwidth, 51 + /**
62 - Duration requestLatency) { 52 + * Set of packet link that is already established.
53 + */
54 + private final ImmutableSet<PacketLinkRealizedByOptical> establishedLinks;
55 +
56 + public OpticalConnectivity(OpticalConnectivityId id,
57 + List<Link> links,
58 + Bandwidth requestBandwidth,
59 + Duration requestLatency,
60 + Set<PacketLinkRealizedByOptical> unestablishedLinks,
61 + Set<PacketLinkRealizedByOptical> establishedLinks) {
63 this.id = id; 62 this.id = id;
64 - this.links = ImmutableList.copyOf(path.links()); 63 + this.links = ImmutableList.copyOf(links);
65 this.requestBandwidth = requestBandwidth; 64 this.requestBandwidth = requestBandwidth;
66 this.requestLatency = requestLatency; 65 this.requestLatency = requestLatency;
66 + this.unestablishedLinks = ImmutableSet.copyOf(unestablishedLinks);
67 + this.establishedLinks = ImmutableSet.copyOf(establishedLinks);
67 } 68 }
68 69
69 - public void setLinkEstablished(ConnectPoint src, ConnectPoint dst) { 70 + private OpticalConnectivity(OpticalConnectivity connectivity) {
70 - realizingLinks.stream().filter(l -> l.isBetween(src, dst)) 71 + this.id = connectivity.id;
71 - .findAny() 72 + this.links = ImmutableList.copyOf(connectivity.links);
72 - .ifPresent(l -> l.setEstablished(true)); 73 + this.requestBandwidth = connectivity.requestBandwidth;
73 - } 74 + this.requestLatency = connectivity.requestLatency;
74 - 75 + this.unestablishedLinks = ImmutableSet.copyOf(connectivity.unestablishedLinks);
75 - public void setLinkRemoved(ConnectPoint src, ConnectPoint dst) { 76 + this.establishedLinks = ImmutableSet.copyOf(connectivity.establishedLinks);
76 - realizingLinks.stream().filter(l -> l.isBetween(src, dst))
77 - .findAny()
78 - .ifPresent(l -> l.setEstablished(false));
79 } 77 }
80 78
81 public boolean isAllRealizingLinkEstablished() { 79 public boolean isAllRealizingLinkEstablished() {
82 - return realizingLinks.stream().allMatch(PacketLinkRealizedByOptical::isEstablished); 80 + // Check if all links are established
81 + return unestablishedLinks.isEmpty();
83 } 82 }
84 83
85 public boolean isAllRealizingLinkNotEstablished() { 84 public boolean isAllRealizingLinkNotEstablished() {
86 - return !realizingLinks.stream().anyMatch(PacketLinkRealizedByOptical::isEstablished); 85 + // Check if any link is not established
86 + return establishedLinks.isEmpty();
87 } 87 }
88 88
89 public OpticalConnectivityId id() { 89 public OpticalConnectivityId id() {
...@@ -102,59 +102,64 @@ public class OpticalConnectivity { ...@@ -102,59 +102,64 @@ public class OpticalConnectivity {
102 return requestLatency; 102 return requestLatency;
103 } 103 }
104 104
105 - public State state() { 105 + public Set<PacketLinkRealizedByOptical> getEstablishedLinks() {
106 - return state; 106 + return establishedLinks;
107 } 107 }
108 108
109 - public boolean state(State state) { 109 + public Set<PacketLinkRealizedByOptical> getUnestablishedLinks() {
110 - boolean valid = true; 110 + return unestablishedLinks;
111 - // reject invalid state transition
112 - switch (this.state) {
113 - case CREATED:
114 - valid = (state == State.INSTALLING || state == State.FAILED);
115 - break;
116 - case INSTALLING:
117 - valid = (state == State.INSTALLED || state == State.FAILED);
118 - break;
119 - case INSTALLED:
120 - valid = (state == State.WITHDRAWING || state == State.FAILED);
121 - break;
122 - case WITHDRAWING:
123 - valid = (state == State.WITHDRAWN || state == State.FAILED);
124 - break;
125 - case FAILED:
126 - valid = (state == State.INSTALLING || state == State.WITHDRAWING || state == State.FAILED);
127 - break;
128 - default:
129 - break;
130 } 111 }
131 112
132 - if (valid) { 113 + public OpticalConnectivity setLinkEstablished(ConnectPoint src,
133 - this.state = state; 114 + ConnectPoint dst,
134 - } 115 + boolean established) {
116 + Set<PacketLinkRealizedByOptical> newEstablishedLinks;
117 + Set<PacketLinkRealizedByOptical> newUnestablishedLinks;
135 118
136 - return valid; 119 + if (established) {
137 - } 120 + // move PacketLink from unestablished set to established set
121 + Optional<PacketLinkRealizedByOptical> link = this.unestablishedLinks.stream()
122 + .filter(l -> l.isBetween(src, dst)).findAny();
123 + checkState(link.isPresent());
138 124
139 - public Bandwidth getOpticalCapacity() { 125 + newUnestablishedLinks = this.unestablishedLinks.stream()
140 - return opticalCapacity; 126 + .filter(l -> !l.isBetween(src, dst))
141 - } 127 + .collect(Collectors.toSet());
128 + newEstablishedLinks = ImmutableSet.<PacketLinkRealizedByOptical>builder()
129 + .addAll(this.establishedLinks)
130 + .add(link.get())
131 + .build();
132 + } else {
133 + // move PacketLink from established set to unestablished set
134 + Optional<PacketLinkRealizedByOptical> link = this.establishedLinks.stream()
135 + .filter(l -> l.isBetween(src, dst)).findAny();
136 + checkState(link.isPresent());
142 137
143 - public void setOpticalCapacity(Bandwidth opticalCapacity) { 138 + newEstablishedLinks = this.establishedLinks.stream()
144 - this.opticalCapacity = opticalCapacity; 139 + .filter(l -> !l.isBetween(src, dst))
140 + .collect(Collectors.toSet());
141 + newUnestablishedLinks = ImmutableSet.<PacketLinkRealizedByOptical>builder()
142 + .addAll(this.unestablishedLinks)
143 + .add(link.get())
144 + .build();
145 } 145 }
146 146
147 - public void addRealizingLink(PacketLinkRealizedByOptical link) { 147 + return new OpticalConnectivity(this.id,
148 - checkNotNull(link); 148 + this.links,
149 - realizingLinks.add(link); 149 + this.requestBandwidth,
150 + this.requestLatency,
151 + newUnestablishedLinks,
152 + newEstablishedLinks);
150 } 153 }
151 154
152 - public void removeRealizingLink(PacketLinkRealizedByOptical link) { 155 + public Set<PacketLinkRealizedByOptical> getRealizingLinks() {
153 - checkNotNull(link); 156 + return ImmutableSet.<PacketLinkRealizedByOptical>builder()
154 - realizingLinks.remove(link); 157 + .addAll(unestablishedLinks)
158 + .addAll(establishedLinks)
159 + .build();
155 } 160 }
156 161
157 - public Set<PacketLinkRealizedByOptical> getRealizingLinks() { 162 + public static OpticalConnectivity copyOf(OpticalConnectivity connectivity) {
158 - return ImmutableSet.copyOf(realizingLinks); 163 + return new OpticalConnectivity(connectivity);
159 } 164 }
160 } 165 }
......
...@@ -17,7 +17,6 @@ package org.onosproject.newoptical; ...@@ -17,7 +17,6 @@ package org.onosproject.newoptical;
17 17
18 import com.google.common.annotations.Beta; 18 import com.google.common.annotations.Beta;
19 import com.google.common.collect.ImmutableList; 19 import com.google.common.collect.ImmutableList;
20 -import com.google.common.collect.Sets;
21 20
22 import org.apache.commons.lang3.tuple.Pair; 21 import org.apache.commons.lang3.tuple.Pair;
23 import org.apache.felix.scr.annotations.Activate; 22 import org.apache.felix.scr.annotations.Activate;
...@@ -27,8 +26,8 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -27,8 +26,8 @@ import org.apache.felix.scr.annotations.Reference;
27 import org.apache.felix.scr.annotations.ReferenceCardinality; 26 import org.apache.felix.scr.annotations.ReferenceCardinality;
28 import org.apache.felix.scr.annotations.Service; 27 import org.apache.felix.scr.annotations.Service;
29 import org.onlab.util.Bandwidth; 28 import org.onlab.util.Bandwidth;
29 +import org.onlab.util.KryoNamespace;
30 import org.onosproject.cluster.ClusterService; 30 import org.onosproject.cluster.ClusterService;
31 -import org.onosproject.cluster.NodeId;
32 import org.onosproject.core.ApplicationId; 31 import org.onosproject.core.ApplicationId;
33 import org.onosproject.core.CoreService; 32 import org.onosproject.core.CoreService;
34 import org.onosproject.event.ListenerTracker; 33 import org.onosproject.event.ListenerTracker;
...@@ -66,20 +65,29 @@ import org.onosproject.net.resource.Resources; ...@@ -66,20 +65,29 @@ import org.onosproject.net.resource.Resources;
66 import org.onosproject.net.topology.LinkWeight; 65 import org.onosproject.net.topology.LinkWeight;
67 import org.onosproject.net.topology.PathService; 66 import org.onosproject.net.topology.PathService;
68 import org.onosproject.net.topology.TopologyEdge; 67 import org.onosproject.net.topology.TopologyEdge;
68 +import org.onosproject.store.serializers.KryoNamespaces;
69 import org.onosproject.store.service.AtomicCounter; 69 import org.onosproject.store.service.AtomicCounter;
70 +import org.onosproject.store.service.ConsistentMap;
71 +import org.onosproject.store.service.DistributedSet;
72 +import org.onosproject.store.service.MapEvent;
73 +import org.onosproject.store.service.MapEventListener;
74 +import org.onosproject.store.service.Serializer;
70 import org.onosproject.store.service.StorageService; 75 import org.onosproject.store.service.StorageService;
76 +import org.onosproject.store.service.Versioned;
71 import org.slf4j.Logger; 77 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory; 78 import org.slf4j.LoggerFactory;
73 79
74 import java.time.Duration; 80 import java.time.Duration;
81 +import java.util.ArrayList;
75 import java.util.Collections; 82 import java.util.Collections;
83 +import java.util.HashMap;
84 +import java.util.HashSet;
76 import java.util.Iterator; 85 import java.util.Iterator;
77 import java.util.LinkedList; 86 import java.util.LinkedList;
78 import java.util.List; 87 import java.util.List;
79 import java.util.Map; 88 import java.util.Map;
80 import java.util.Optional; 89 import java.util.Optional;
81 import java.util.Set; 90 import java.util.Set;
82 -import java.util.concurrent.ConcurrentHashMap;
83 import java.util.stream.Collectors; 91 import java.util.stream.Collectors;
84 import java.util.stream.Stream; 92 import java.util.stream.Stream;
85 93
...@@ -99,6 +107,9 @@ public class OpticalPathProvisioner ...@@ -99,6 +107,9 @@ public class OpticalPathProvisioner
99 protected static final Logger log = LoggerFactory.getLogger(OpticalPathProvisioner.class); 107 protected static final Logger log = LoggerFactory.getLogger(OpticalPathProvisioner.class);
100 108
101 private static final String OPTICAL_CONNECTIVITY_ID_COUNTER = "optical-connectivity-id"; 109 private static final String OPTICAL_CONNECTIVITY_ID_COUNTER = "optical-connectivity-id";
110 + private static final String LINKPATH_MAP_NAME = "newoptical-linkpath";
111 + private static final String CONNECTIVITY_MAP_NAME = "newoptical-connectivity";
112 + private static final String CROSSCONNECTLINK_SET_NAME = "newoptical-crossconnectlink";
102 113
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected IntentService intentService; 115 protected IntentService intentService;
...@@ -137,14 +148,28 @@ public class OpticalPathProvisioner ...@@ -137,14 +148,28 @@ public class OpticalPathProvisioner
137 148
138 private ListenerTracker listeners; 149 private ListenerTracker listeners;
139 150
140 - private Map<PacketLinkRealizedByOptical, OpticalConnectivity> linkPathMap = new ConcurrentHashMap<>(); 151 + private InternalStoreListener storeListener = new InternalStoreListener();
141 152
142 - // TODO this should be stored to distributed store 153 + private ConsistentMap<PacketLinkRealizedByOptical, OpticalConnectivity> linkPathMap;
143 - private Map<OpticalConnectivityId, OpticalConnectivity> connectivities = new ConcurrentHashMap<>(); 154 +
155 + private ConsistentMap<OpticalConnectivityId, OpticalConnectivity> connectivityMap;
144 156
145 - // TODO this should be stored to distributed store
146 // Map of cross connect link and installed path which uses the link 157 // Map of cross connect link and installed path which uses the link
147 - private Set<Link> usedCrossConnectLinks = Sets.newConcurrentHashSet(); 158 + private DistributedSet<Link> usedCrossConnectLinkSet;
159 +
160 + private static final KryoNamespace.Builder LINKPATH_SERIALIZER = KryoNamespace.newBuilder()
161 + .register(KryoNamespaces.API)
162 + .register(PacketLinkRealizedByOptical.class)
163 + .register(OpticalConnectivityId.class)
164 + .register(OpticalConnectivity.class);
165 +
166 + private static final KryoNamespace.Builder CONNECTIVITY_SERIALIZER = KryoNamespace.newBuilder()
167 + .register(KryoNamespaces.API)
168 + .register(OpticalConnectivityId.class)
169 + .register(OpticalConnectivity.class);
170 +
171 + private static final KryoNamespace.Builder CROSSCONNECTLINKS_SERIALIZER = KryoNamespace.newBuilder()
172 + .register(KryoNamespaces.API);
148 173
149 @Activate 174 @Activate
150 protected void activate() { 175 protected void activate() {
...@@ -153,17 +178,39 @@ public class OpticalPathProvisioner ...@@ -153,17 +178,39 @@ public class OpticalPathProvisioner
153 178
154 idCounter = storageService.getAtomicCounter(OPTICAL_CONNECTIVITY_ID_COUNTER); 179 idCounter = storageService.getAtomicCounter(OPTICAL_CONNECTIVITY_ID_COUNTER);
155 180
181 + linkPathMap = storageService.<PacketLinkRealizedByOptical, OpticalConnectivity>consistentMapBuilder()
182 + .withSerializer(Serializer.using(LINKPATH_SERIALIZER.build()))
183 + .withName(LINKPATH_MAP_NAME)
184 + .withApplicationId(appId)
185 + .build();
186 +
187 + connectivityMap = storageService.<OpticalConnectivityId, OpticalConnectivity>consistentMapBuilder()
188 + .withSerializer(Serializer.using(CONNECTIVITY_SERIALIZER.build()))
189 + .withName(CONNECTIVITY_MAP_NAME)
190 + .withApplicationId(appId)
191 + .build();
192 +
193 + usedCrossConnectLinkSet = storageService.<Link>setBuilder()
194 + .withSerializer(Serializer.using(CROSSCONNECTLINKS_SERIALIZER.build()))
195 + .withName(CROSSCONNECTLINK_SET_NAME)
196 + .withApplicationId(appId)
197 + .build()
198 + .asDistributedSet();
199 +
156 eventDispatcher.addSink(OpticalPathEvent.class, listenerRegistry); 200 eventDispatcher.addSink(OpticalPathEvent.class, listenerRegistry);
157 201
158 listeners = new ListenerTracker(); 202 listeners = new ListenerTracker();
159 listeners.addListener(linkService, new InternalLinkListener()) 203 listeners.addListener(linkService, new InternalLinkListener())
160 .addListener(intentService, new InternalIntentListener()); 204 .addListener(intentService, new InternalIntentListener());
161 205
206 + linkPathMap.addListener(storeListener);
207 +
162 log.info("Started"); 208 log.info("Started");
163 } 209 }
164 210
165 @Deactivate 211 @Deactivate
166 protected void deactivate() { 212 protected void deactivate() {
213 + linkPathMap.removeListener(storeListener);
167 listeners.removeListeners(); 214 listeners.removeListeners();
168 eventDispatcher.removeSink(OpticalPathEvent.class); 215 eventDispatcher.removeSink(OpticalPathEvent.class);
169 216
...@@ -205,22 +252,67 @@ public class OpticalPathProvisioner ...@@ -205,22 +252,67 @@ public class OpticalPathProvisioner
205 checkNotNull(path); 252 checkNotNull(path);
206 log.info("setupPath({}, {}, {})", path, bandwidth, latency); 253 log.info("setupPath({}, {}, {})", path, bandwidth, latency);
207 254
208 - // validate optical path 255 + // map of cross connect points (optical port -> packet port)
209 - List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs = getCrossConnectPoints(path); 256 + Map<ConnectPoint, ConnectPoint> crossConnectPointMap = new HashMap<>();
210 - if (!checkXcPoints(xcPointPairs)) { 257 +
211 - // Can't setup path if cross connect points are mismatched 258 + // list of (src, dst) pair of optical ports between which optical path should be installed
212 - log.error("Failed to setup path because of mismatched cross connect points."); 259 + List<Pair<ConnectPoint, ConnectPoint>> crossConnectPoints = new ArrayList<>();
260 +
261 + // Scan path to find pairs of connect points between which optical intent is installed
262 + // opticalSrcPort works as a flag parameter to show scanning status
263 + ConnectPoint opticalSrcPort = null;
264 + for (Link link : path.links()) {
265 + if (!isCrossConnectLink(link)) {
266 + continue;
267 + }
268 +
269 + if (opticalSrcPort != null) {
270 + // opticalSrcPort!=null means src port was already found
271 + // in this case link.src() is optical layer, and link.dst() is packet layer
272 +
273 + // Check if types of src port and dst port matches
274 + Device srcDevice = checkNotNull(deviceService.getDevice(opticalSrcPort.deviceId()),
275 + "Unknown device ID");
276 + Device dstDevice = checkNotNull(deviceService.getDevice(link.src().deviceId()),
277 + "Unknown device ID");
278 + if (srcDevice.type() != dstDevice.type()) {
279 + log.error("Unsupported mix of cross connect points : {}, {}",
280 + srcDevice.type(), dstDevice.type());
213 return null; 281 return null;
214 } 282 }
215 283
216 - OpticalConnectivity connectivity = createConnectivity(path, bandwidth, latency); 284 + // Update cross connect points map
285 + crossConnectPointMap.put(link.src(), link.dst());
286 +
287 + // Add optical ports pair to list
288 + crossConnectPoints.add(Pair.of(opticalSrcPort, link.src()));
289 +
290 + // Reset flag parameter
291 + opticalSrcPort = null;
292 + } else {
293 + // opticalSrcPort==null means src port was not found yet
294 + // in this case link.src() is packet layer, and link.dst() is optical layer
295 +
296 + // Update cross connect points map
297 + crossConnectPointMap.put(link.dst(), link.src());
298 + // Set opticalSrcPort to src of link (optical port)
299 + opticalSrcPort = link.dst();
300 + }
301 + }
302 +
303 + // create intents from cross connect points
304 + List<Intent> intents = createIntents(crossConnectPoints);
305 +
306 + // create set of PacketLinkRealizedByOptical
307 + Set<PacketLinkRealizedByOptical> packetLinks = createPacketLinkSet(crossConnectPoints,
308 + intents, crossConnectPointMap);
217 309
218 - // create intents from cross connect points and set connectivity information 310 + // create OpticalConnectivity object and store information to distributed store
219 - List<Intent> intents = createIntents(xcPointPairs, connectivity); 311 + OpticalConnectivity connectivity = createConnectivity(path, bandwidth, latency, packetLinks);
220 312
221 // store cross connect port usage 313 // store cross connect port usage
222 path.links().stream().filter(this::isCrossConnectLink) 314 path.links().stream().filter(this::isCrossConnectLink)
223 - .forEach(usedCrossConnectLinks::add); 315 + .forEach(usedCrossConnectLinkSet::add);
224 316
225 // Submit the intents 317 // Submit the intents
226 for (Intent i : intents) { 318 for (Intent i : intents) {
...@@ -231,12 +323,16 @@ public class OpticalPathProvisioner ...@@ -231,12 +323,16 @@ public class OpticalPathProvisioner
231 return connectivity.id(); 323 return connectivity.id();
232 } 324 }
233 325
234 - private OpticalConnectivity createConnectivity(Path path, Bandwidth bandwidth, Duration latency) { 326 + private OpticalConnectivity createConnectivity(Path path, Bandwidth bandwidth, Duration latency,
327 + Set<PacketLinkRealizedByOptical> links) {
235 OpticalConnectivityId id = OpticalConnectivityId.of(idCounter.getAndIncrement()); 328 OpticalConnectivityId id = OpticalConnectivityId.of(idCounter.getAndIncrement());
236 - OpticalConnectivity connectivity = new OpticalConnectivity(id, path, bandwidth, latency); 329 + OpticalConnectivity connectivity = new OpticalConnectivity(id, path.links(), bandwidth, latency,
330 + links, Collections.emptySet());
331 +
332 + links.forEach(l -> linkPathMap.put(l, connectivity));
237 333
238 // store connectivity information 334 // store connectivity information
239 - connectivities.put(connectivity.id(), connectivity); 335 + connectivityMap.put(connectivity.id(), connectivity);
240 336
241 return connectivity; 337 return connectivity;
242 } 338 }
...@@ -244,7 +340,7 @@ public class OpticalPathProvisioner ...@@ -244,7 +340,7 @@ public class OpticalPathProvisioner
244 @Override 340 @Override
245 public boolean removeConnectivity(OpticalConnectivityId id) { 341 public boolean removeConnectivity(OpticalConnectivityId id) {
246 log.info("removeConnectivity({})", id); 342 log.info("removeConnectivity({})", id);
247 - OpticalConnectivity connectivity = connectivities.remove(id); 343 + Versioned<OpticalConnectivity> connectivity = connectivityMap.remove(id);
248 344
249 if (connectivity == null) { 345 if (connectivity == null) {
250 log.info("OpticalConnectivity with id {} not found.", id); 346 log.info("OpticalConnectivity with id {} not found.", id);
...@@ -252,7 +348,7 @@ public class OpticalPathProvisioner ...@@ -252,7 +348,7 @@ public class OpticalPathProvisioner
252 } 348 }
253 349
254 // TODO withdraw intent only if all of connectivities that use the optical path are withdrawn 350 // TODO withdraw intent only if all of connectivities that use the optical path are withdrawn
255 - connectivity.getRealizingLinks().forEach(l -> { 351 + connectivity.value().getRealizingLinks().forEach(l -> {
256 Intent intent = intentService.getIntent(l.realizingIntentKey()); 352 Intent intent = intentService.getIntent(l.realizingIntentKey());
257 intentService.withdraw(intent); 353 intentService.withdraw(intent);
258 }); 354 });
...@@ -262,98 +358,34 @@ public class OpticalPathProvisioner ...@@ -262,98 +358,34 @@ public class OpticalPathProvisioner
262 358
263 @Override 359 @Override
264 public Optional<List<Link>> getPath(OpticalConnectivityId id) { 360 public Optional<List<Link>> getPath(OpticalConnectivityId id) {
265 - OpticalConnectivity connectivity = connectivities.get(id); 361 + Versioned<OpticalConnectivity> connectivity = connectivityMap.get(id);
266 if (connectivity == null) { 362 if (connectivity == null) {
267 log.info("OpticalConnectivity with id {} not found.", id); 363 log.info("OpticalConnectivity with id {} not found.", id);
268 return Optional.empty(); 364 return Optional.empty();
269 } 365 }
270 366
271 - return Optional.of(ImmutableList.copyOf(connectivity.links())); 367 + return Optional.of(ImmutableList.copyOf(connectivity.value().links()));
272 - }
273 -
274 - /**
275 - * Returns list of (optical, packet) pairs of cross connection points of missing optical path sections.
276 - *
277 - * Scans the given multi-layer path and looks for sections that use cross connect links.
278 - * The ingress and egress points in the optical layer are combined to the packet layer ports, and
279 - * are returned in a list.
280 - *
281 - * @param path the multi-layer path
282 - * @return List of cross connect link's (packet port, optical port) pairs
283 - */
284 - private List<Pair<ConnectPoint, ConnectPoint>> getCrossConnectPoints(Path path) {
285 - List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs = new LinkedList<>();
286 - boolean scanning = false;
287 -
288 - for (Link link : path.links()) {
289 - if (!isCrossConnectLink(link)) {
290 - continue;
291 - }
292 -
293 - if (scanning) {
294 - // link.src() is packet, link.dst() is optical
295 - xcPointPairs.add(Pair.of(checkNotNull(link.src()), checkNotNull(link.dst())));
296 - scanning = false;
297 - } else {
298 - // link.src() is optical, link.dst() is packet
299 - xcPointPairs.add(Pair.of(checkNotNull(link.dst()), checkNotNull(link.src())));
300 - scanning = true;
301 - }
302 - }
303 -
304 - return xcPointPairs;
305 - }
306 -
307 - /**
308 - * Checks if optical cross connect points are of same type.
309 - *
310 - * @param xcPointPairs list of cross connection points
311 - * @return true if cross connect point pairs are of same type, false otherwise
312 - */
313 - private boolean checkXcPoints(List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs) {
314 - checkArgument(xcPointPairs.size() % 2 == 0);
315 -
316 - Iterator<Pair<ConnectPoint, ConnectPoint>> itr = xcPointPairs.iterator();
317 -
318 - while (itr.hasNext()) {
319 - // checkArgument at start ensures we'll always have pairs of connect points
320 - Pair<ConnectPoint, ConnectPoint> src = itr.next();
321 - Pair<ConnectPoint, ConnectPoint> dst = itr.next();
322 -
323 - Device.Type srcType = deviceService.getDevice(src.getKey().deviceId()).type();
324 - Device.Type dstType = deviceService.getDevice(dst.getKey().deviceId()).type();
325 -
326 - // Only support connections between identical port types
327 - if (srcType != dstType) {
328 - log.warn("Unsupported mix of cross connect points : {}, {}", srcType, dstType);
329 - return false;
330 - }
331 - }
332 -
333 - return true;
334 } 368 }
335 369
336 /** 370 /**
337 * Scans the list of cross connection points and returns a list of optical connectivity intents. 371 * Scans the list of cross connection points and returns a list of optical connectivity intents.
338 - * During the process, store intent ID and its realizing link information to given connectivity object. 372 + * During the process, save information about packet links to given set.
339 * 373 *
340 - * @param xcPointPairs list of cross connection points 374 + * @param crossConnectPoints list of (src, dst) pair between which optical path will be set up
341 * @return list of optical connectivity intents 375 * @return list of optical connectivity intents
342 */ 376 */
343 - private List<Intent> createIntents(List<Pair<ConnectPoint, ConnectPoint>> xcPointPairs, 377 + private List<Intent> createIntents(List<Pair<ConnectPoint, ConnectPoint>> crossConnectPoints) {
344 - OpticalConnectivity connectivity) {
345 - checkArgument(xcPointPairs.size() % 2 == 0);
346 -
347 List<Intent> intents = new LinkedList<>(); 378 List<Intent> intents = new LinkedList<>();
348 - Iterator<Pair<ConnectPoint, ConnectPoint>> itr = xcPointPairs.iterator(); 379 + Iterator<Pair<ConnectPoint, ConnectPoint>> itr = crossConnectPoints.iterator();
349 380
350 while (itr.hasNext()) { 381 while (itr.hasNext()) {
351 // checkArgument at start ensures we'll always have pairs of connect points 382 // checkArgument at start ensures we'll always have pairs of connect points
352 - Pair<ConnectPoint, ConnectPoint> src = itr.next(); 383 + Pair<ConnectPoint, ConnectPoint> next = itr.next();
353 - Pair<ConnectPoint, ConnectPoint> dst = itr.next(); 384 + ConnectPoint src = next.getLeft();
385 + ConnectPoint dst = next.getRight();
354 386
355 - Port srcPort = deviceService.getPort(src.getKey().deviceId(), src.getKey().port()); 387 + Port srcPort = deviceService.getPort(src.deviceId(), src.port());
356 - Port dstPort = deviceService.getPort(dst.getKey().deviceId(), dst.getKey().port()); 388 + Port dstPort = deviceService.getPort(dst.deviceId(), dst.port());
357 389
358 if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) { 390 if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) {
359 OduCltPort srcOCPort = (OduCltPort) srcPort; 391 OduCltPort srcOCPort = (OduCltPort) srcPort;
...@@ -365,16 +397,12 @@ public class OpticalPathProvisioner ...@@ -365,16 +397,12 @@ public class OpticalPathProvisioner
365 // Create OTN circuit 397 // Create OTN circuit
366 OpticalCircuitIntent circuitIntent = OpticalCircuitIntent.builder() 398 OpticalCircuitIntent circuitIntent = OpticalCircuitIntent.builder()
367 .appId(appId) 399 .appId(appId)
368 - .src(src.getKey()) 400 + .src(src)
369 - .dst(dst.getKey()) 401 + .dst(dst)
370 .signalType(srcOCPort.signalType()) 402 .signalType(srcOCPort.signalType())
371 .bidirectional(true) 403 .bidirectional(true)
372 .build(); 404 .build();
373 intents.add(circuitIntent); 405 intents.add(circuitIntent);
374 - PacketLinkRealizedByOptical pLink = PacketLinkRealizedByOptical.create(src.getValue(), dst.getValue(),
375 - circuitIntent);
376 - connectivity.addRealizingLink(pLink);
377 - linkPathMap.put(pLink, connectivity);
378 } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) { 406 } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) {
379 OchPort srcOchPort = (OchPort) srcPort; 407 OchPort srcOchPort = (OchPort) srcPort;
380 OchPort dstOchPort = (OchPort) dstPort; 408 OchPort dstOchPort = (OchPort) dstPort;
...@@ -385,16 +413,12 @@ public class OpticalPathProvisioner ...@@ -385,16 +413,12 @@ public class OpticalPathProvisioner
385 // Create lightpath 413 // Create lightpath
386 OpticalConnectivityIntent opticalIntent = OpticalConnectivityIntent.builder() 414 OpticalConnectivityIntent opticalIntent = OpticalConnectivityIntent.builder()
387 .appId(appId) 415 .appId(appId)
388 - .src(src.getKey()) 416 + .src(src)
389 - .dst(dst.getKey()) 417 + .dst(dst)
390 .signalType(srcOchPort.signalType()) 418 .signalType(srcOchPort.signalType())
391 .bidirectional(true) 419 .bidirectional(true)
392 .build(); 420 .build();
393 intents.add(opticalIntent); 421 intents.add(opticalIntent);
394 - PacketLinkRealizedByOptical pLink = PacketLinkRealizedByOptical.create(src.getValue(), dst.getValue(),
395 - opticalIntent);
396 - connectivity.addRealizingLink(pLink);
397 - linkPathMap.put(pLink, connectivity);
398 } else { 422 } else {
399 log.warn("Unsupported cross connect point types {} {}", srcPort.type(), dstPort.type()); 423 log.warn("Unsupported cross connect point types {} {}", srcPort.type(), dstPort.type());
400 return Collections.emptyList(); 424 return Collections.emptyList();
...@@ -404,6 +428,36 @@ public class OpticalPathProvisioner ...@@ -404,6 +428,36 @@ public class OpticalPathProvisioner
404 return intents; 428 return intents;
405 } 429 }
406 430
431 + private Set<PacketLinkRealizedByOptical> createPacketLinkSet(List<Pair<ConnectPoint, ConnectPoint>> connectPoints,
432 + List<Intent> intents,
433 + Map<ConnectPoint, ConnectPoint> crossConnectPoints) {
434 + checkArgument(connectPoints.size() == intents.size());
435 +
436 + Set<PacketLinkRealizedByOptical> pLinks = new HashSet<>();
437 +
438 + Iterator<Pair<ConnectPoint, ConnectPoint>> xcPointsItr = connectPoints.iterator();
439 + Iterator<Intent> intentItr = intents.iterator();
440 + while (xcPointsItr.hasNext()) {
441 + Pair<ConnectPoint, ConnectPoint> xcPoints = xcPointsItr.next();
442 + Intent intent = intentItr.next();
443 +
444 + ConnectPoint packetSrc = checkNotNull(crossConnectPoints.get(xcPoints.getLeft()));
445 + ConnectPoint packetDst = checkNotNull(crossConnectPoints.get(xcPoints.getRight()));
446 +
447 + if (intent instanceof OpticalConnectivityIntent) {
448 + pLinks.add(PacketLinkRealizedByOptical.create(packetSrc, packetDst,
449 + (OpticalConnectivityIntent) intent));
450 + } else if (intent instanceof OpticalCircuitIntent) {
451 + pLinks.add(PacketLinkRealizedByOptical.create(packetSrc, packetDst,
452 + (OpticalCircuitIntent) intent));
453 + } else {
454 + log.warn("Unexpected intent type: {}", intent.getClass());
455 + }
456 + }
457 +
458 + return pLinks;
459 + }
460 +
407 /** 461 /**
408 * Verifies if given device type is in packet layer, i.e., ROADM, OTN or ROADM_OTN device. 462 * Verifies if given device type is in packet layer, i.e., ROADM, OTN or ROADM_OTN device.
409 * 463 *
...@@ -444,18 +498,15 @@ public class OpticalPathProvisioner ...@@ -444,18 +498,15 @@ public class OpticalPathProvisioner
444 498
445 /** 499 /**
446 * Updates bandwidth resource of given connect point. 500 * Updates bandwidth resource of given connect point.
501 + *
447 * @param cp Connect point 502 * @param cp Connect point
448 * @param bandwidth New bandwidth 503 * @param bandwidth New bandwidth
449 */ 504 */
450 private void updatePortBandwidth(ConnectPoint cp, Bandwidth bandwidth) { 505 private void updatePortBandwidth(ConnectPoint cp, Bandwidth bandwidth) {
451 - NodeId localNode = clusterService.getLocalNode().id();
452 - NodeId sourceMaster = mastershipService.getMasterFor(cp.deviceId());
453 - if (localNode.equals(sourceMaster)) {
454 log.debug("update Port {} Bandwidth {}", cp, bandwidth); 506 log.debug("update Port {} Bandwidth {}", cp, bandwidth);
455 BandwidthCapacity bwCapacity = networkConfigService.addConfig(cp, BandwidthCapacity.class); 507 BandwidthCapacity bwCapacity = networkConfigService.addConfig(cp, BandwidthCapacity.class);
456 bwCapacity.capacity(bandwidth).apply(); 508 bwCapacity.capacity(bandwidth).apply();
457 } 509 }
458 - }
459 510
460 /** 511 /**
461 * Updates usage information of bandwidth based on connectivity which is established. 512 * Updates usage information of bandwidth based on connectivity which is established.
...@@ -487,6 +538,12 @@ public class OpticalPathProvisioner ...@@ -487,6 +538,12 @@ public class OpticalPathProvisioner
487 * @param connectivity Optical connectivity 538 * @param connectivity Optical connectivity
488 */ 539 */
489 private void releaseBandwidthUsage(OpticalConnectivity connectivity) { 540 private void releaseBandwidthUsage(OpticalConnectivity connectivity) {
541 + if (connectivity.links().isEmpty()) {
542 + return;
543 + }
544 +
545 + // release resource only if this node is the master for link head device
546 + if (mastershipService.isLocalMaster(connectivity.links().get(0).src().deviceId())) {
490 OpticalConnectivityId connectivityId = connectivity.id(); 547 OpticalConnectivityId connectivityId = connectivity.id();
491 548
492 log.debug("releasing bandwidth allocated to {}", connectivityId); 549 log.debug("releasing bandwidth allocated to {}", connectivityId);
...@@ -497,6 +554,7 @@ public class OpticalPathProvisioner ...@@ -497,6 +554,7 @@ public class OpticalPathProvisioner
497 } 554 }
498 log.debug("DONE releasing bandwidth for {}", connectivityId); 555 log.debug("DONE releasing bandwidth for {}", connectivityId);
499 } 556 }
557 + }
500 558
501 private class BandwidthLinkWeight implements LinkWeight { 559 private class BandwidthLinkWeight implements LinkWeight {
502 private Bandwidth bandwidth = null; 560 private Bandwidth bandwidth = null;
...@@ -515,7 +573,7 @@ public class OpticalPathProvisioner ...@@ -515,7 +573,7 @@ public class OpticalPathProvisioner
515 } 573 }
516 574
517 // Avoid cross connect links with used ports 575 // Avoid cross connect links with used ports
518 - if (isCrossConnectLink(l) && usedCrossConnectLinks.contains(l)) { 576 + if (isCrossConnectLink(l) && usedCrossConnectLinkSet.contains(l)) {
519 return -1.0; 577 return -1.0;
520 } 578 }
521 579
...@@ -592,18 +650,16 @@ public class OpticalPathProvisioner ...@@ -592,18 +650,16 @@ public class OpticalPathProvisioner
592 ConnectPoint packetSrc = e.getKey().src(); 650 ConnectPoint packetSrc = e.getKey().src();
593 ConnectPoint packetDst = e.getKey().dst(); 651 ConnectPoint packetDst = e.getKey().dst();
594 Bandwidth bw = e.getKey().bandwidth(); 652 Bandwidth bw = e.getKey().bandwidth();
653 +
654 + // reflect modification only if packetSrc is local_
655 + if (mastershipService.isLocalMaster(packetSrc.deviceId())) {
595 // Updates bandwidth of packet ports 656 // Updates bandwidth of packet ports
596 updatePortBandwidth(packetSrc, bw); 657 updatePortBandwidth(packetSrc, bw);
597 updatePortBandwidth(packetDst, bw); 658 updatePortBandwidth(packetDst, bw);
598 659
599 - OpticalConnectivity connectivity = e.getValue(); 660 + // Updates link status in distributed map
600 - connectivity.setLinkEstablished(packetSrc, packetDst); 661 + linkPathMap.computeIfPresent(e.getKey(), (link, connectivity) ->
601 - 662 + e.getValue().value().setLinkEstablished(packetSrc, packetDst, true));
602 - if (e.getValue().isAllRealizingLinkEstablished()) {
603 - updateBandwidthUsage(connectivity);
604 -
605 - // Notifies listeners if all links are established
606 - post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_INSTALLED, e.getValue().id()));
607 } 663 }
608 }); 664 });
609 } 665 }
...@@ -633,23 +689,23 @@ public class OpticalPathProvisioner ...@@ -633,23 +689,23 @@ public class OpticalPathProvisioner
633 .forEach(e -> { 689 .forEach(e -> {
634 ConnectPoint packetSrc = e.getKey().src(); 690 ConnectPoint packetSrc = e.getKey().src();
635 ConnectPoint packetDst = e.getKey().dst(); 691 ConnectPoint packetDst = e.getKey().dst();
692 +
693 + // reflect modification only if packetSrc is local_
694 + if (mastershipService.isLocalMaster(packetSrc.deviceId())) {
636 // Updates bandwidth of packet ports 695 // Updates bandwidth of packet ports
637 updatePortBandwidth(packetSrc, bw); 696 updatePortBandwidth(packetSrc, bw);
638 updatePortBandwidth(packetDst, bw); 697 updatePortBandwidth(packetDst, bw);
639 - OpticalConnectivity connectivity = e.getValue();
640 - connectivity.setLinkRemoved(packetSrc, packetDst);
641 698
642 - // Notifies listeners if all links are gone 699 + // Updates link status in distributed map
643 - if (e.getValue().isAllRealizingLinkNotEstablished()) { 700 + linkPathMap.computeIfPresent(e.getKey(), (link, connectivity) ->
644 - releaseBandwidthUsage(connectivity); 701 + e.getValue().value().setLinkEstablished(packetSrc, packetDst, false));
645 - post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, e.getValue().id()));
646 } 702 }
647 }); 703 });
648 } 704 }
649 705
650 private void removeXcLinkUsage(ConnectPoint cp) { 706 private void removeXcLinkUsage(ConnectPoint cp) {
651 Optional<Link> link = linkService.getLinks(cp).stream() 707 Optional<Link> link = linkService.getLinks(cp).stream()
652 - .filter(usedCrossConnectLinks::contains) 708 + .filter(usedCrossConnectLinkSet::contains)
653 .findAny(); 709 .findAny();
654 710
655 if (!link.isPresent()) { 711 if (!link.isPresent()) {
...@@ -657,7 +713,7 @@ public class OpticalPathProvisioner ...@@ -657,7 +713,7 @@ public class OpticalPathProvisioner
657 return; 713 return;
658 } 714 }
659 715
660 - usedCrossConnectLinks.remove(link.get()); 716 + usedCrossConnectLinkSet.remove(link.get());
661 } 717 }
662 } 718 }
663 719
...@@ -669,22 +725,60 @@ public class OpticalPathProvisioner ...@@ -669,22 +725,60 @@ public class OpticalPathProvisioner
669 switch (event.type()) { 725 switch (event.type()) {
670 case LINK_REMOVED: 726 case LINK_REMOVED:
671 Link link = event.subject(); 727 Link link = event.subject();
728 + // updates linkPathMap only if src device of link is local
729 + if (!mastershipService.isLocalMaster(link.src().deviceId())) {
730 + return;
731 + }
732 +
733 + // find all packet links that correspond to removed link
672 Set<PacketLinkRealizedByOptical> pLinks = linkPathMap.keySet().stream() 734 Set<PacketLinkRealizedByOptical> pLinks = linkPathMap.keySet().stream()
673 .filter(l -> l.isBetween(link.src(), link.dst()) || l.isBetween(link.dst(), link.src())) 735 .filter(l -> l.isBetween(link.src(), link.dst()) || l.isBetween(link.dst(), link.src()))
674 .collect(Collectors.toSet()); 736 .collect(Collectors.toSet());
675 737
676 pLinks.forEach(l -> { 738 pLinks.forEach(l -> {
677 - OpticalConnectivity c = linkPathMap.get(l); 739 + // remove found packet links from distributed store
678 - // Notifies listeners if all links are gone 740 + linkPathMap.computeIfPresent(l, (plink, conn) -> {
679 - if (c.isAllRealizingLinkNotEstablished()) { 741 + // Notifies listeners if all packet links are gone
680 - post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, c.id())); 742 + if (conn.isAllRealizingLinkNotEstablished()) {
743 + post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, conn.id()));
681 } 744 }
682 - linkPathMap.remove(l); 745 + return null;
746 + });
683 }); 747 });
684 default: 748 default:
685 break; 749 break;
686 } 750 }
687 } 751 }
688 } 752 }
753 +
754 + private class InternalStoreListener
755 + implements MapEventListener<PacketLinkRealizedByOptical, OpticalConnectivity> {
756 +
757 + @Override
758 + public void event(MapEvent<PacketLinkRealizedByOptical, OpticalConnectivity> event) {
759 + switch (event.type()) {
760 + case UPDATE:
761 + OpticalConnectivity oldConnectivity = event.oldValue().value();
762 + OpticalConnectivity newConnectivity = event.newValue().value();
763 +
764 + if (!oldConnectivity.isAllRealizingLinkEstablished() &&
765 + newConnectivity.isAllRealizingLinkEstablished()) {
766 + // Notifies listeners if all links are established
767 + updateBandwidthUsage(newConnectivity);
768 + post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_INSTALLED, newConnectivity.id()));
769 + } else if (!oldConnectivity.isAllRealizingLinkNotEstablished() &&
770 + newConnectivity.isAllRealizingLinkNotEstablished()) {
771 + // Notifies listeners if all links are gone
772 + releaseBandwidthUsage(newConnectivity);
773 + post(new OpticalPathEvent(OpticalPathEvent.Type.PATH_REMOVED, newConnectivity.id()));
774 + }
775 +
776 + break;
777 + default:
778 + break;
779 + }
780 + }
781 +
782 + }
689 } 783 }
690 784
......
...@@ -33,9 +33,6 @@ public class PacketLinkRealizedByOptical { ...@@ -33,9 +33,6 @@ public class PacketLinkRealizedByOptical {
33 private final Bandwidth bandwidth; 33 private final Bandwidth bandwidth;
34 // TODO should be list of Intent Key? 34 // TODO should be list of Intent Key?
35 private final Key realizingIntentKey; 35 private final Key realizingIntentKey;
36 - // established=false represents that this (packet) link is expected to be
37 - // discovered after underlying (optical) path has been provisioned.
38 - private boolean established;
39 36
40 /** 37 /**
41 * Creates instance with specified parameters. 38 * Creates instance with specified parameters.
...@@ -51,7 +48,6 @@ public class PacketLinkRealizedByOptical { ...@@ -51,7 +48,6 @@ public class PacketLinkRealizedByOptical {
51 this.dst = dst; 48 this.dst = dst;
52 this.realizingIntentKey = realizingIntentKey; 49 this.realizingIntentKey = realizingIntentKey;
53 this.bandwidth = bandwidth; 50 this.bandwidth = bandwidth;
54 - this.established = false;
55 } 51 }
56 52
57 /** 53 /**
...@@ -129,24 +125,6 @@ public class PacketLinkRealizedByOptical { ...@@ -129,24 +125,6 @@ public class PacketLinkRealizedByOptical {
129 } 125 }
130 126
131 /** 127 /**
132 - * Returns whether packet link is realized or not.
133 - *
134 - * @return true if packet link is realized. false if not.
135 - */
136 - public boolean isEstablished() {
137 - return established;
138 - }
139 -
140 - /**
141 - * Sets packet link to be established.
142 - *
143 - * @param established status of packet link
144 - */
145 - public void setEstablished(boolean established) {
146 - this.established = established;
147 - }
148 -
149 - /**
150 * Check if packet link is between specified two connect points. 128 * Check if packet link is between specified two connect points.
151 * 129 *
152 * @param src source connect point 130 * @param src source connect point
...@@ -157,4 +135,36 @@ public class PacketLinkRealizedByOptical { ...@@ -157,4 +135,36 @@ public class PacketLinkRealizedByOptical {
157 return (this.src.equals(src) && this.dst.equals(dst)); 135 return (this.src.equals(src) && this.dst.equals(dst));
158 } 136 }
159 137
138 + @Override
139 + public boolean equals(Object o) {
140 + if (this == o) {
141 + return true;
142 + }
143 + if (o == null || getClass() != o.getClass()) {
144 + return false;
145 + }
146 +
147 + PacketLinkRealizedByOptical that = (PacketLinkRealizedByOptical) o;
148 +
149 + if (!src.equals(that.src)) {
150 + return false;
151 + }
152 + if (!dst.equals(that.dst)) {
153 + return false;
154 + }
155 + if (!bandwidth.equals(that.bandwidth)) {
156 + return false;
157 + }
158 + return realizingIntentKey.equals(that.realizingIntentKey);
159 +
160 + }
161 +
162 + @Override
163 + public int hashCode() {
164 + int result = src.hashCode();
165 + result = 31 * result + dst.hashCode();
166 + result = 31 * result + bandwidth.hashCode();
167 + result = 31 * result + realizingIntentKey.hashCode();
168 + return result;
169 + }
160 } 170 }
......
...@@ -33,7 +33,7 @@ import java.util.Optional; ...@@ -33,7 +33,7 @@ import java.util.Optional;
33 public interface OpticalPathService extends ListenerService<OpticalPathEvent, OpticalPathListener> { 33 public interface OpticalPathService extends ListenerService<OpticalPathEvent, OpticalPathListener> {
34 34
35 /** 35 /**
36 - * Calculates optical path between connect points and sets up connectivity. 36 + * Calculates multi-layer path between connect points and sets up connectivity.
37 * 37 *
38 * @param ingress ingress port 38 * @param ingress ingress port
39 * @param egress egress port 39 * @param egress egress port
...@@ -45,9 +45,9 @@ public interface OpticalPathService extends ListenerService<OpticalPathEvent, Op ...@@ -45,9 +45,9 @@ public interface OpticalPathService extends ListenerService<OpticalPathEvent, Op
45 Bandwidth bandwidth, Duration latency); 45 Bandwidth bandwidth, Duration latency);
46 46
47 /** 47 /**
48 - * Sets up connectivity along given optical path. 48 + * Sets up connectivity along given multi-layer path including cross-connect links.
49 * 49 *
50 - * @param path path along which connectivity will be set up 50 + * @param path multi-layer path along which connectivity will be set up
51 * @param bandwidth required bandwidth. No bandwidth is assured if null. 51 * @param bandwidth required bandwidth. No bandwidth is assured if null.
52 * @param latency required latency. No latency is assured if null. 52 * @param latency required latency. No latency is assured if null.
53 * @return true if successful. false otherwise. 53 * @return true if successful. false otherwise.
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 16
17 package org.onosproject.newoptical; 17 package org.onosproject.newoptical;
18 18
19 +import com.google.common.collect.ImmutableSet;
19 import org.junit.After; 20 import org.junit.After;
20 import org.junit.Before; 21 import org.junit.Before;
21 import org.junit.Test; 22 import org.junit.Test;
...@@ -39,7 +40,9 @@ import org.onosproject.net.provider.ProviderId; ...@@ -39,7 +40,9 @@ import org.onosproject.net.provider.ProviderId;
39 import org.onosproject.newoptical.api.OpticalConnectivityId; 40 import org.onosproject.newoptical.api.OpticalConnectivityId;
40 41
41 import java.time.Duration; 42 import java.time.Duration;
43 +import java.util.Collections;
42 import java.util.List; 44 import java.util.List;
45 +import java.util.Set;
43 import java.util.stream.Collectors; 46 import java.util.stream.Collectors;
44 import java.util.stream.Stream; 47 import java.util.stream.Stream;
45 48
...@@ -94,10 +97,9 @@ public class OpticalConnectivityTest { ...@@ -94,10 +97,9 @@ public class OpticalConnectivityTest {
94 Link link2 = createLink(cp22, cp31); 97 Link link2 = createLink(cp22, cp31);
95 List<Link> links = Stream.of(link1, link2).collect(Collectors.toList()); 98 List<Link> links = Stream.of(link1, link2).collect(Collectors.toList());
96 99
97 - Path path = new MockPath(cp12, cp31, links);
98 -
99 OpticalConnectivityId cid = OpticalConnectivityId.of(1L); 100 OpticalConnectivityId cid = OpticalConnectivityId.of(1L);
100 - OpticalConnectivity oc = new OpticalConnectivity(cid, path, bandwidth, latency); 101 + OpticalConnectivity oc = new OpticalConnectivity(cid, links, bandwidth, latency,
102 + Collections.emptySet(), Collections.emptySet());
101 103
102 assertNotNull(oc); 104 assertNotNull(oc);
103 assertEquals(oc.id(), cid); 105 assertEquals(oc.id(), cid);
...@@ -133,8 +135,6 @@ public class OpticalConnectivityTest { ...@@ -133,8 +135,6 @@ public class OpticalConnectivityTest {
133 Link link6 = createLink(cp62, cp71); 135 Link link6 = createLink(cp62, cp71);
134 List<Link> links = Stream.of(link1, link2, link3, link4, link5, link6).collect(Collectors.toList()); 136 List<Link> links = Stream.of(link1, link2, link3, link4, link5, link6).collect(Collectors.toList());
135 137
136 - Path path = new MockPath(cp12, cp71, links);
137 -
138 // Mocks 2 intents to create OduCtl connectivity 138 // Mocks 2 intents to create OduCtl connectivity
139 OpticalConnectivityIntent connIntent1 = createConnectivityIntent(cp21, cp32); 139 OpticalConnectivityIntent connIntent1 = createConnectivityIntent(cp21, cp32);
140 PacketLinkRealizedByOptical oduLink1 = PacketLinkRealizedByOptical.create(cp12, cp41, 140 PacketLinkRealizedByOptical oduLink1 = PacketLinkRealizedByOptical.create(cp12, cp41,
...@@ -144,29 +144,29 @@ public class OpticalConnectivityTest { ...@@ -144,29 +144,29 @@ public class OpticalConnectivityTest {
144 PacketLinkRealizedByOptical oduLink2 = PacketLinkRealizedByOptical.create(cp42, cp71, 144 PacketLinkRealizedByOptical oduLink2 = PacketLinkRealizedByOptical.create(cp42, cp71,
145 connIntent2); 145 connIntent2);
146 146
147 + Set<PacketLinkRealizedByOptical> plinks = ImmutableSet.of(oduLink1, oduLink2);
148 +
147 Bandwidth bandwidth = Bandwidth.bps(100); 149 Bandwidth bandwidth = Bandwidth.bps(100);
148 Duration latency = Duration.ofMillis(10); 150 Duration latency = Duration.ofMillis(10);
149 151
150 OpticalConnectivityId cid = OpticalConnectivityId.of(1L); 152 OpticalConnectivityId cid = OpticalConnectivityId.of(1L);
151 - OpticalConnectivity oc = new OpticalConnectivity(cid, path, bandwidth, latency); 153 + OpticalConnectivity oc1 = new OpticalConnectivity(cid, links, bandwidth, latency,
152 - 154 + plinks, Collections.emptySet());
153 - oc.addRealizingLink(oduLink1);
154 - oc.addRealizingLink(oduLink2);
155 155
156 - assertTrue(oc.isAllRealizingLinkNotEstablished()); 156 + assertTrue(oc1.isAllRealizingLinkNotEstablished());
157 - assertFalse(oc.isAllRealizingLinkEstablished()); 157 + assertFalse(oc1.isAllRealizingLinkEstablished());
158 158
159 // Sets link realized by connIntent1 to be established 159 // Sets link realized by connIntent1 to be established
160 - oc.setLinkEstablished(cp12, cp41); 160 + OpticalConnectivity oc2 = oc1.setLinkEstablished(cp12, cp41, true);
161 161
162 - assertFalse(oc.isAllRealizingLinkNotEstablished()); 162 + assertFalse(oc2.isAllRealizingLinkNotEstablished());
163 - assertFalse(oc.isAllRealizingLinkEstablished()); 163 + assertFalse(oc2.isAllRealizingLinkEstablished());
164 164
165 // Sets link realized by connIntent2 to be established 165 // Sets link realized by connIntent2 to be established
166 - oc.setLinkEstablished(cp42, cp71); 166 + OpticalConnectivity oc3 = oc2.setLinkEstablished(cp42, cp71, true);
167 167
168 - assertFalse(oc.isAllRealizingLinkNotEstablished()); 168 + assertFalse(oc3.isAllRealizingLinkNotEstablished());
169 - assertTrue(oc.isAllRealizingLinkEstablished()); 169 + assertTrue(oc3.isAllRealizingLinkEstablished());
170 } 170 }
171 171
172 /** 172 /**
...@@ -196,8 +196,6 @@ public class OpticalConnectivityTest { ...@@ -196,8 +196,6 @@ public class OpticalConnectivityTest {
196 Link link6 = createLink(cp62, cp71); 196 Link link6 = createLink(cp62, cp71);
197 List<Link> links = Stream.of(link1, link2, link3, link4, link5, link6).collect(Collectors.toList()); 197 List<Link> links = Stream.of(link1, link2, link3, link4, link5, link6).collect(Collectors.toList());
198 198
199 - Path path = new MockPath(cp12, cp71, links);
200 -
201 // Mocks 2 intents to create Och connectivity 199 // Mocks 2 intents to create Och connectivity
202 OpticalCircuitIntent circuitIntent1 = createCircuitIntent(cp21, cp32); 200 OpticalCircuitIntent circuitIntent1 = createCircuitIntent(cp21, cp32);
203 PacketLinkRealizedByOptical ochLink1 = PacketLinkRealizedByOptical.create(cp12, cp41, 201 PacketLinkRealizedByOptical ochLink1 = PacketLinkRealizedByOptical.create(cp12, cp41,
...@@ -207,29 +205,29 @@ public class OpticalConnectivityTest { ...@@ -207,29 +205,29 @@ public class OpticalConnectivityTest {
207 PacketLinkRealizedByOptical ochLink2 = PacketLinkRealizedByOptical.create(cp42, cp71, 205 PacketLinkRealizedByOptical ochLink2 = PacketLinkRealizedByOptical.create(cp42, cp71,
208 circuitIntent2); 206 circuitIntent2);
209 207
208 + Set<PacketLinkRealizedByOptical> plinks = ImmutableSet.of(ochLink1, ochLink2);
209 +
210 Bandwidth bandwidth = Bandwidth.bps(100); 210 Bandwidth bandwidth = Bandwidth.bps(100);
211 Duration latency = Duration.ofMillis(10); 211 Duration latency = Duration.ofMillis(10);
212 212
213 OpticalConnectivityId cid = OpticalConnectivityId.of(1L); 213 OpticalConnectivityId cid = OpticalConnectivityId.of(1L);
214 - OpticalConnectivity oc = new OpticalConnectivity(cid, path, bandwidth, latency); 214 + OpticalConnectivity oc1 = new OpticalConnectivity(cid, links, bandwidth, latency,
215 - 215 + plinks, Collections.emptySet());
216 - oc.addRealizingLink(ochLink1);
217 - oc.addRealizingLink(ochLink2);
218 216
219 - assertTrue(oc.isAllRealizingLinkNotEstablished()); 217 + assertTrue(oc1.isAllRealizingLinkNotEstablished());
220 - assertFalse(oc.isAllRealizingLinkEstablished()); 218 + assertFalse(oc1.isAllRealizingLinkEstablished());
221 219
222 // Sets link realized by circuitIntent1 to be established 220 // Sets link realized by circuitIntent1 to be established
223 - oc.setLinkEstablished(cp12, cp41); 221 + OpticalConnectivity oc2 = oc1.setLinkEstablished(cp12, cp41, true);
224 222
225 - assertFalse(oc.isAllRealizingLinkNotEstablished()); 223 + assertFalse(oc2.isAllRealizingLinkNotEstablished());
226 - assertFalse(oc.isAllRealizingLinkEstablished()); 224 + assertFalse(oc2.isAllRealizingLinkEstablished());
227 225
228 // Sets link realized by circuitIntent2 to be established 226 // Sets link realized by circuitIntent2 to be established
229 - oc.setLinkEstablished(cp42, cp71); 227 + OpticalConnectivity oc3 = oc2.setLinkEstablished(cp42, cp71, true);
230 228
231 - assertFalse(oc.isAllRealizingLinkNotEstablished()); 229 + assertFalse(oc3.isAllRealizingLinkNotEstablished());
232 - assertTrue(oc.isAllRealizingLinkEstablished()); 230 + assertTrue(oc3.isAllRealizingLinkEstablished());
233 } 231 }
234 232
235 private ConnectPoint createConnectPoint(long devIdNum, long portIdNum) { 233 private ConnectPoint createConnectPoint(long devIdNum, long portIdNum) {
......
...@@ -21,9 +21,12 @@ import org.junit.After; ...@@ -21,9 +21,12 @@ import org.junit.After;
21 import org.junit.Before; 21 import org.junit.Before;
22 import org.junit.Test; 22 import org.junit.Test;
23 import org.onlab.packet.ChassisId; 23 import org.onlab.packet.ChassisId;
24 +import org.onlab.packet.IpAddress;
24 import org.onlab.util.Bandwidth; 25 import org.onlab.util.Bandwidth;
25 import org.onlab.util.Frequency; 26 import org.onlab.util.Frequency;
26 import org.onosproject.cluster.ClusterServiceAdapter; 27 import org.onosproject.cluster.ClusterServiceAdapter;
28 +import org.onosproject.cluster.ControllerNode;
29 +import org.onosproject.cluster.NodeId;
27 import org.onosproject.core.ApplicationId; 30 import org.onosproject.core.ApplicationId;
28 import org.onosproject.core.CoreServiceAdapter; 31 import org.onosproject.core.CoreServiceAdapter;
29 import org.onosproject.core.DefaultApplicationId; 32 import org.onosproject.core.DefaultApplicationId;
...@@ -44,12 +47,15 @@ import org.onosproject.net.Device; ...@@ -44,12 +47,15 @@ import org.onosproject.net.Device;
44 import org.onosproject.net.DeviceId; 47 import org.onosproject.net.DeviceId;
45 import org.onosproject.net.ElementId; 48 import org.onosproject.net.ElementId;
46 import org.onosproject.net.Link; 49 import org.onosproject.net.Link;
50 +import org.onosproject.net.MastershipRole;
47 import org.onosproject.net.OchSignal; 51 import org.onosproject.net.OchSignal;
48 import org.onosproject.net.OduSignalType; 52 import org.onosproject.net.OduSignalType;
49 import org.onosproject.net.Path; 53 import org.onosproject.net.Path;
50 import org.onosproject.net.Port; 54 import org.onosproject.net.Port;
51 import org.onosproject.net.PortNumber; 55 import org.onosproject.net.PortNumber;
56 +import org.onosproject.net.config.Config;
52 import org.onosproject.net.config.NetworkConfigServiceAdapter; 57 import org.onosproject.net.config.NetworkConfigServiceAdapter;
58 +import org.onosproject.net.config.basics.BandwidthCapacity;
53 import org.onosproject.net.device.DeviceServiceAdapter; 59 import org.onosproject.net.device.DeviceServiceAdapter;
54 import org.onosproject.net.intent.Intent; 60 import org.onosproject.net.intent.Intent;
55 import org.onosproject.net.intent.IntentEvent; 61 import org.onosproject.net.intent.IntentEvent;
...@@ -74,8 +80,20 @@ import org.onosproject.net.topology.PathServiceAdapter; ...@@ -74,8 +80,20 @@ import org.onosproject.net.topology.PathServiceAdapter;
74 import org.onosproject.newoptical.api.OpticalConnectivityId; 80 import org.onosproject.newoptical.api.OpticalConnectivityId;
75 import org.onosproject.newoptical.api.OpticalPathEvent; 81 import org.onosproject.newoptical.api.OpticalPathEvent;
76 import org.onosproject.newoptical.api.OpticalPathListener; 82 import org.onosproject.newoptical.api.OpticalPathListener;
83 +import org.onosproject.store.service.AsyncConsistentMap;
84 +import org.onosproject.store.service.AsyncDistributedSet;
77 import org.onosproject.store.service.AtomicCounter; 85 import org.onosproject.store.service.AtomicCounter;
86 +import org.onosproject.store.service.ConsistentMap;
87 +import org.onosproject.store.service.ConsistentMapAdapter;
88 +import org.onosproject.store.service.ConsistentMapBuilder;
89 +import org.onosproject.store.service.DistributedSet;
90 +import org.onosproject.store.service.DistributedSetAdapter;
91 +import org.onosproject.store.service.DistributedSetBuilder;
92 +import org.onosproject.store.service.MapEvent;
93 +import org.onosproject.store.service.MapEventListener;
94 +import org.onosproject.store.service.SetEventListener;
78 import org.onosproject.store.service.StorageServiceAdapter; 95 import org.onosproject.store.service.StorageServiceAdapter;
96 +import org.onosproject.store.service.Versioned;
79 97
80 import java.time.Duration; 98 import java.time.Duration;
81 import java.util.ArrayList; 99 import java.util.ArrayList;
...@@ -87,6 +105,8 @@ import java.util.List; ...@@ -87,6 +105,8 @@ import java.util.List;
87 import java.util.Map; 105 import java.util.Map;
88 import java.util.Optional; 106 import java.util.Optional;
89 import java.util.Set; 107 import java.util.Set;
108 +import java.util.concurrent.Executor;
109 +import java.util.function.BiFunction;
90 import java.util.stream.Collectors; 110 import java.util.stream.Collectors;
91 import java.util.stream.Stream; 111 import java.util.stream.Stream;
92 112
...@@ -155,6 +175,8 @@ public class OpticalPathProvisionerTest { ...@@ -155,6 +175,8 @@ public class OpticalPathProvisionerTest {
155 protected TestLinkService linkService; 175 protected TestLinkService linkService;
156 protected TestPathService pathService; 176 protected TestPathService pathService;
157 protected TestIntentService intentService; 177 protected TestIntentService intentService;
178 + protected TestMastershipService mastershipService;
179 + protected TestClusterService clusterService;
158 protected IdGenerator idGenerator; 180 protected IdGenerator idGenerator;
159 181
160 @Before 182 @Before
...@@ -188,14 +210,24 @@ public class OpticalPathProvisionerTest { ...@@ -188,14 +210,24 @@ public class OpticalPathProvisionerTest {
188 210
189 this.pathService = new TestPathService(); 211 this.pathService = new TestPathService();
190 this.intentService = new TestIntentService(); 212 this.intentService = new TestIntentService();
213 + this.mastershipService = new TestMastershipService();
214 + this.clusterService = new TestClusterService();
215 +
216 + mastershipService.setMastership(DEVICE1.id(), MastershipRole.MASTER);
217 + mastershipService.setMastership(DEVICE2.id(), MastershipRole.MASTER);
218 + mastershipService.setMastership(DEVICE3.id(), MastershipRole.MASTER);
219 + mastershipService.setMastership(DEVICE4.id(), MastershipRole.MASTER);
220 + mastershipService.setMastership(DEVICE5.id(), MastershipRole.MASTER);
221 + mastershipService.setMastership(DEVICE6.id(), MastershipRole.MASTER);
222 + mastershipService.setMastership(DEVICE7.id(), MastershipRole.MASTER);
191 223
192 this.target = new OpticalPathProvisioner(); 224 this.target = new OpticalPathProvisioner();
193 target.coreService = new TestCoreService(); 225 target.coreService = new TestCoreService();
194 target.intentService = this.intentService; 226 target.intentService = this.intentService;
195 target.pathService = this.pathService; 227 target.pathService = this.pathService;
196 target.linkService = this.linkService; 228 target.linkService = this.linkService;
197 - target.mastershipService = new TestMastershipService(); 229 + target.mastershipService = this.mastershipService;
198 - target.clusterService = new TestClusterService(); 230 + target.clusterService = this.clusterService;
199 target.storageService = new TestStorageService(); 231 target.storageService = new TestStorageService();
200 target.deviceService = this.deviceService; 232 target.deviceService = this.deviceService;
201 target.networkConfigService = new TestNetworkConfigService(); 233 target.networkConfigService = new TestNetworkConfigService();
...@@ -310,15 +342,16 @@ public class OpticalPathProvisionerTest { ...@@ -310,15 +342,16 @@ public class OpticalPathProvisionerTest {
310 } 342 }
311 343
312 /** 344 /**
313 - * Checks if PATH_INSTALLED event comes up after intent is installed. 345 + * Checks if PATH_INSTALLED event comes up after intent whose master is this node is installed.
314 */ 346 */
315 @Test 347 @Test
316 - public void testInstalledEvent() { 348 + public void testInstalledEventLocal() {
317 Bandwidth bandwidth = Bandwidth.bps(100); 349 Bandwidth bandwidth = Bandwidth.bps(100);
318 Duration latency = Duration.ofMillis(10); 350 Duration latency = Duration.ofMillis(10);
319 351
320 OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency); 352 OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency);
321 353
354 + // notify all intents are installed
322 intentService.notifyInstalled(); 355 intentService.notifyInstalled();
323 356
324 assertEquals(1, listener.events.size()); 357 assertEquals(1, listener.events.size());
...@@ -327,26 +360,77 @@ public class OpticalPathProvisionerTest { ...@@ -327,26 +360,77 @@ public class OpticalPathProvisionerTest {
327 } 360 }
328 361
329 /** 362 /**
363 + * Checks if PATH_INSTALLED event comes up after intent whose master is remote node is installed.
364 + */
365 + @Test
366 + public void testInstalledEventRemote() {
367 + // set the master for ingress device of intent to remote node
368 + mastershipService.setMastership(DEVICE2.id(), MastershipRole.NONE);
369 +
370 + Bandwidth bandwidth = Bandwidth.bps(100);
371 + Duration latency = Duration.ofMillis(10);
372 +
373 + OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency);
374 +
375 + // notify all intents are installed
376 + intentService.notifyInstalled();
377 +
378 + // remote nodes must not receive event before distributed map is updated
379 + assertEquals(0, listener.events.size());
380 + }
381 +
382 + /**
330 * Checks if PATH_REMOVED event comes up after packet link is removed. 383 * Checks if PATH_REMOVED event comes up after packet link is removed.
331 */ 384 */
332 @Test 385 @Test
333 - public void testRemovedEvent() { 386 + public void testRemovedEventLocal() {
334 Bandwidth bandwidth = Bandwidth.bps(100); 387 Bandwidth bandwidth = Bandwidth.bps(100);
335 Duration latency = Duration.ofMillis(10); 388 Duration latency = Duration.ofMillis(10);
336 389
337 OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency); 390 OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency);
338 391
392 + // notify all intents are installed
339 intentService.notifyInstalled(); 393 intentService.notifyInstalled();
340 394
341 target.removeConnectivity(cid); 395 target.removeConnectivity(cid);
342 396
397 + // notify all intents are withdrawn
343 intentService.notifyWithdrawn(); 398 intentService.notifyWithdrawn();
344 399
400 + // must have received "INSTALLED" and "REMOVED" events
345 assertEquals(2, listener.events.size()); 401 assertEquals(2, listener.events.size());
402 + assertEquals(OpticalPathEvent.Type.PATH_INSTALLED, listener.events.get(0).type());
403 + assertEquals(cid, listener.events.get(0).subject());
346 assertEquals(OpticalPathEvent.Type.PATH_REMOVED, listener.events.get(1).type()); 404 assertEquals(OpticalPathEvent.Type.PATH_REMOVED, listener.events.get(1).type());
347 assertEquals(cid, listener.events.get(1).subject()); 405 assertEquals(cid, listener.events.get(1).subject());
348 } 406 }
349 407
408 +
409 + /**
410 + * Checks if PATH_REMOVED event comes up after packet link is removed.
411 + */
412 + @Test
413 + public void testRemovedEventRemote() {
414 + // set the master for ingress device of intent to remote node
415 + mastershipService.setMastership(DEVICE2.id(), MastershipRole.NONE);
416 +
417 + Bandwidth bandwidth = Bandwidth.bps(100);
418 + Duration latency = Duration.ofMillis(10);
419 +
420 + OpticalConnectivityId cid = target.setupConnectivity(CP12, CP71, bandwidth, latency);
421 +
422 + // notify all intents are installed
423 + intentService.notifyInstalled();
424 +
425 + target.removeConnectivity(cid);
426 +
427 + // notify all intents are withdrawn
428 + intentService.notifyWithdrawn();
429 +
430 + // remote nodes must not receive event before distributed map is updated
431 + assertEquals(0, listener.events.size());
432 + }
433 +
350 private static ConnectPoint createConnectPoint(long devIdNum, long portIdNum) { 434 private static ConnectPoint createConnectPoint(long devIdNum, long portIdNum) {
351 return new ConnectPoint( 435 return new ConnectPoint(
352 deviceIdOf(devIdNum), 436 deviceIdOf(devIdNum),
...@@ -495,18 +579,192 @@ public class OpticalPathProvisionerTest { ...@@ -495,18 +579,192 @@ public class OpticalPathProvisionerTest {
495 } 579 }
496 580
497 private static class TestMastershipService extends MastershipServiceAdapter { 581 private static class TestMastershipService extends MastershipServiceAdapter {
582 + private Map<DeviceId, MastershipRole> mastershipMap = new HashMap<>();
583 +
584 + public void setMastership(DeviceId deviceId, MastershipRole role) {
585 + mastershipMap.put(deviceId, role);
586 + }
587 +
588 + public void clear() {
589 + mastershipMap.clear();
590 + }
591 +
592 + @Override
593 + public MastershipRole getLocalRole(DeviceId deviceId) {
594 + return mastershipMap.get(deviceId);
595 + }
498 596
499 } 597 }
500 598
501 private static class TestClusterService extends ClusterServiceAdapter { 599 private static class TestClusterService extends ClusterServiceAdapter {
600 + private NodeId nodeId;
601 +
602 + public void setLocalNode(String nodeIdStr) {
603 + nodeId = NodeId.nodeId(nodeIdStr);
604 + }
605 +
606 + @Override
607 + public ControllerNode getLocalNode() {
608 + return new ControllerNode() {
609 + @Override
610 + public NodeId id() {
611 + return nodeId;
612 + }
502 613
614 + @Override
615 + public IpAddress ip() {
616 + return null;
617 + }
618 +
619 + @Override
620 + public int tcpPort() {
621 + return 0;
622 + }
623 + };
624 + }
503 } 625 }
504 626
505 private static class TestStorageService extends StorageServiceAdapter { 627 private static class TestStorageService extends StorageServiceAdapter {
628 +
629 + @Override
630 + public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() {
631 + ConsistentMapBuilder<K, V> builder = new ConsistentMapBuilder<K, V>() {
632 + @Override
633 + public AsyncConsistentMap<K, V> buildAsyncMap() {
634 + return null;
635 + }
636 +
637 + @Override
638 + public ConsistentMap<K, V> build() {
639 + return new TestConsistentMap<K, V>();
640 + }
641 + };
642 +
643 + return builder;
644 + }
645 +
646 + @Override
647 + public <E> DistributedSetBuilder<E> setBuilder() {
648 + DistributedSetBuilder<E> builder = new DistributedSetBuilder<E>() {
649 + @Override
650 + public AsyncDistributedSet<E> build() {
651 + return new DistributedSetAdapter<E>() {
652 + @Override
653 + public DistributedSet<E> asDistributedSet() {
654 + return new TestDistributedSet<E>();
655 + }
656 + };
657 + }
658 + };
659 +
660 + return builder;
661 + }
662 +
506 @Override 663 @Override
507 public AtomicCounter getAtomicCounter(String name) { 664 public AtomicCounter getAtomicCounter(String name) {
508 return new MockAtomicCounter(); 665 return new MockAtomicCounter();
509 } 666 }
667 +
668 + // Mock ConsistentMap that behaves as a HashMap
669 + class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
670 + private Map<K, Versioned<V>> map = new HashMap<>();
671 + private Map<MapEventListener<K, V>, Executor> listeners = new HashMap<>();
672 +
673 + public void notifyListeners(MapEvent<K, V> event) {
674 + listeners.forEach((c, e) -> e.execute(() -> c.event(event)));
675 + }
676 +
677 + @Override
678 + public int size() {
679 + return map.size();
680 + }
681 +
682 + @Override
683 + public Versioned<V> put(K key, V value) {
684 + Versioned<V> oldValue = map.get(key);
685 + Versioned<V> newValue = new Versioned<>(value, oldValue == null ? 0 : oldValue.version() + 1);
686 + map.put(key, newValue);
687 + notifyListeners(new MapEvent<>(name(), key, newValue, oldValue));
688 + return newValue;
689 + }
690 +
691 + @Override
692 + public Versioned<V> get(K key) {
693 + return map.get(key);
694 + }
695 +
696 + @Override
697 + public Versioned<V> remove(K key) {
698 + Versioned<V> oldValue = map.remove(key);
699 + notifyListeners(new MapEvent<>(name(), key, oldValue, null));
700 + return oldValue;
701 + }
702 +
703 + @Override
704 + public Versioned<V> computeIfPresent(K key,
705 + BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
706 + Versioned<V> oldValue = map.get(key);
707 + Versioned<V> newValue = new Versioned<>(remappingFunction.apply(key, oldValue.value()),
708 + oldValue == null ? 0 : oldValue.version() + 1);
709 + map.put(key, newValue);
710 + notifyListeners(new MapEvent<>(name(), key, newValue, oldValue));
711 + return newValue;
712 + }
713 +
714 +
715 + @Override
716 + public Set<Map.Entry<K, Versioned<V>>> entrySet() {
717 + return map.entrySet();
718 + }
719 +
720 + @Override
721 + public Set<K> keySet() {
722 + return map.keySet();
723 + }
724 +
725 + @Override
726 + public Collection<Versioned<V>> values() {
727 + return map.values();
728 + }
729 +
730 + @Override
731 + public void clear() {
732 + map.clear();
733 + }
734 +
735 + @Override
736 + public void addListener(MapEventListener<K, V> listener, Executor executor) {
737 + listeners.put(listener, executor);
738 + }
739 +
740 + @Override
741 + public void removeListener(MapEventListener<K, V> listener) {
742 + listeners.remove(listener);
743 + }
744 + }
745 +
746 + // Mock DistributedSet that behaves as a HashSet
747 + class TestDistributedSet<E> extends HashSet<E> implements DistributedSet<E> {
748 +
749 + @Override
750 + public void addListener(SetEventListener<E> listener) {
751 + }
752 +
753 + @Override
754 + public void removeListener(SetEventListener<E> listener) {
755 + }
756 +
757 + @Override
758 + public String name() {
759 + return null;
760 + }
761 +
762 + @Override
763 + public Type primitiveType() {
764 + return null;
765 + }
766 + }
767 +
510 } 768 }
511 769
512 private static class TestDeviceService extends DeviceServiceAdapter { 770 private static class TestDeviceService extends DeviceServiceAdapter {
...@@ -525,6 +783,25 @@ public class OpticalPathProvisionerTest { ...@@ -525,6 +783,25 @@ public class OpticalPathProvisionerTest {
525 } 783 }
526 784
527 private static class TestNetworkConfigService extends NetworkConfigServiceAdapter { 785 private static class TestNetworkConfigService extends NetworkConfigServiceAdapter {
786 + @Override
787 + @SuppressWarnings("unchecked")
788 + public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
789 + if (BandwidthCapacity.class.equals(configClass)) {
790 + return (C) new BandwidthCapacity() {
791 + @Override
792 + public void apply() {
793 + // do nothing
794 + }
795 +
796 + @Override
797 + public BandwidthCapacity capacity(Bandwidth bandwidth) {
798 + // do nothing
799 + return this;
800 + }
801 + };
802 + }
803 + return null;
804 + }
528 805
529 } 806 }
530 807
......