Sho SHIMIZU
Committed by Gerrit Code Review

Refactor: Reserve resources only in one place

This is a preparation task for the future Intent Framework major
enhancement that aims to consolidate resource allocation invocations
into the Framework side instead of the compiler side.

Declaring required resources and allocating the resources need to be
clearly separated. This patch tries to separate these phases.

Change-Id: I7b238f24996b3f1dc97afda6d188426001052127
...@@ -197,58 +197,116 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu ...@@ -197,58 +197,116 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
197 && isMultiplexingSupported(intent.getDst()); 197 && isMultiplexingSupported(intent.getDst());
198 198
199 // slots are used only for devices supporting multiplexing 199 // slots are used only for devices supporting multiplexing
200 - Set<TributarySlot> slots = Collections.emptySet(); 200 + List<Resource> ports = ImmutableList.of(srcPortResource, dstPortResource);
201 201
202 OpticalConnectivityIntent connIntent = findOpticalConnectivityIntent(intent.getSrc(), intent.getDst(), 202 OpticalConnectivityIntent connIntent = findOpticalConnectivityIntent(intent.getSrc(), intent.getDst(),
203 intent.getSignalType(), multiplexingSupported); 203 intent.getSignalType(), multiplexingSupported);
204 - if ((connIntent != null) && multiplexingSupported) { 204 +
205 - // Allocate TributarySlots on existing OCH ports 205 + if (connIntent != null && !multiplexingSupported) {
206 - slots = assignTributarySlots(intent, Pair.of(connIntent.getSrc(), connIntent.getDst())); 206 + return compile(intent, src, dst, Optional.of(connIntent), ports, false);
207 } 207 }
208 208
209 // Create optical connectivity intent if needed - no optical intent or not enough slots available 209 // Create optical connectivity intent if needed - no optical intent or not enough slots available
210 - if (connIntent == null || (multiplexingSupported && slots.isEmpty())) { 210 + if (connIntent == null) {
211 + return compile(intent, src, dst, Optional.empty(), ports, multiplexingSupported);
212 + }
213 +
214 + List<Resource> slots = availableSlotResources(connIntent.getSrc(), connIntent.getDst(),
215 + intent.getSignalType());
216 + if (slots.isEmpty()) {
217 + return compile(intent, src, dst, Optional.empty(), ports, true);
218 + }
219 +
220 + return compile(intent, src, dst, Optional.of(connIntent), ImmutableList.<Resource>builder()
221 + .addAll(ports).addAll(slots).build(), false);
222 +
223 + }
224 +
225 + private List<Intent> compile(OpticalCircuitIntent intent, ConnectPoint src, ConnectPoint dst,
226 + Optional<OpticalConnectivityIntent> existingConnectivity,
227 + List<Resource> resources, boolean supportsMultiplexing) {
228 + OpticalConnectivityIntent connectivityIntent;
229 + List<Resource> required;
230 + if (existingConnectivity.isPresent()) {
231 + connectivityIntent = existingConnectivity.get();
232 + required = resources;
233 + } else {
211 // Find OCh ports with available resources 234 // Find OCh ports with available resources
212 Pair<OchPort, OchPort> ochPorts = findPorts(intent.getSrc(), intent.getDst(), intent.getSignalType()); 235 Pair<OchPort, OchPort> ochPorts = findPorts(intent.getSrc(), intent.getDst(), intent.getSignalType());
213 236
214 if (ochPorts == null) { 237 if (ochPorts == null) {
215 - // Release port allocations if unsuccessful
216 - resourceService.release(intent.id());
217 throw new IntentCompilationException("Unable to find suitable OCH ports for intent " + intent); 238 throw new IntentCompilationException("Unable to find suitable OCH ports for intent " + intent);
218 } 239 }
219 240
220 ConnectPoint srcCP = new ConnectPoint(src.elementId(), ochPorts.getLeft().number()); 241 ConnectPoint srcCP = new ConnectPoint(src.elementId(), ochPorts.getLeft().number());
221 ConnectPoint dstCP = new ConnectPoint(dst.elementId(), ochPorts.getRight().number()); 242 ConnectPoint dstCP = new ConnectPoint(dst.elementId(), ochPorts.getRight().number());
222 243
223 - if (multiplexingSupported) {
224 - // Allocate TributarySlots on OCH ports
225 - slots = assignTributarySlots(intent, Pair.of(srcCP, dstCP));
226 - if (slots.isEmpty()) {
227 - // Release port allocations if unsuccessful
228 - resourceService.release(intent.id());
229 - throw new IntentCompilationException("Unable to find Tributary Slots for intent " + intent);
230 - }
231 - }
232 -
233 // Create optical connectivity intent 244 // Create optical connectivity intent
234 - OduSignalType signalType = ochPorts.getLeft().signalType(); 245 + connectivityIntent = OpticalConnectivityIntent.builder()
235 - connIntent = OpticalConnectivityIntent.builder()
236 .appId(appId) 246 .appId(appId)
237 .src(srcCP) 247 .src(srcCP)
238 .dst(dstCP) 248 .dst(dstCP)
239 - .signalType(signalType) 249 + .signalType(ochPorts.getLeft().signalType())
240 .bidirectional(intent.isBidirectional()) 250 .bidirectional(intent.isBidirectional())
241 .build(); 251 .build();
242 - intentService.submit(connIntent); 252 +
253 + if (!supportsMultiplexing) {
254 + required = resources;
255 + } else {
256 + List<Resource> slots = availableSlotResources(srcCP, dstCP, intent.getSignalType());
257 + if (slots.isEmpty()) {
258 + throw new IntentCompilationException("Unable to find Tributary Slots for intent " + intent);
259 + }
260 + required = ImmutableList.<Resource>builder().addAll(resources).addAll(slots).build();
261 + }
262 + }
263 +
264 + if (resourceService.allocate(intent.id(), required).isEmpty()) {
265 + throw new IntentCompilationException("Unable to allocate resources for intent " + intent
266 + + ": resources=" + required);
243 } 267 }
244 268
269 + intentService.submit(connectivityIntent);
270 +
245 // Save circuit to connectivity intent mapping 271 // Save circuit to connectivity intent mapping
246 - intentSetMultimap.allocateMapping(connIntent.id(), intent.id()); 272 + intentSetMultimap.allocateMapping(connectivityIntent.id(), intent.id());
247 273
248 - FlowRuleIntent circuitIntent = createFlowRule(intent, connIntent, slots); 274 + FlowRuleIntent circuitIntent = createFlowRule(intent, connectivityIntent, required.stream().
275 + flatMap(x -> Tools.stream(x.valueAs(TributarySlot.class)))
276 + .collect(Collectors.toSet()));
249 return ImmutableList.of(circuitIntent); 277 return ImmutableList.of(circuitIntent);
250 } 278 }
251 279
280 + private List<Resource> availableSlotResources(ConnectPoint src, ConnectPoint dst, CltSignalType signalType) {
281 + OduSignalType oduSignalType = mappingCltSignalTypeToOduSignalType(signalType);
282 + int requestedTsNum = oduSignalType.tributarySlots();
283 + Set<TributarySlot> commonTributarySlots = findCommonTributarySlotsOnCps(src, dst);
284 + if (commonTributarySlots.isEmpty()) {
285 + return Collections.emptyList();
286 + }
287 + if (commonTributarySlots.size() < requestedTsNum) {
288 + return Collections.emptyList();
289 + }
290 +
291 + Set<TributarySlot> tributarySlots = commonTributarySlots.stream()
292 + .limit(requestedTsNum)
293 + .collect(Collectors.toSet());
294 +
295 + final List<ConnectPoint> portsList = ImmutableList.of(src, dst);
296 + List<Resource> tributarySlotResources = portsList.stream()
297 + .flatMap(cp -> tributarySlots
298 + .stream()
299 + .map(ts-> Resources.discrete(cp.deviceId(), cp.port()).resource().child(ts)))
300 + .collect(Collectors.toList());
301 +
302 + if (!tributarySlotResources.stream().allMatch(resourceService::isAvailable)) {
303 + log.debug("Resource allocation for {} on {} and {} failed (resource request: {})",
304 + signalType, src, dst, tributarySlotResources);
305 + return Collections.emptyList();
306 + }
307 + return tributarySlotResources;
308 + }
309 +
252 private FlowRuleIntent createFlowRule(OpticalCircuitIntent higherIntent, 310 private FlowRuleIntent createFlowRule(OpticalCircuitIntent higherIntent,
253 OpticalConnectivityIntent lowerIntent, Set<TributarySlot> slots) { 311 OpticalConnectivityIntent lowerIntent, Set<TributarySlot> slots) {
254 // Create optical circuit intent 312 // Create optical circuit intent
...@@ -338,39 +396,6 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu ...@@ -338,39 +396,6 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
338 return true; 396 return true;
339 } 397 }
340 398
341 - private Set<TributarySlot> assignTributarySlots(OpticalCircuitIntent intent,
342 - Pair<ConnectPoint, ConnectPoint> ports) {
343 -
344 - OduSignalType oduSignalType = mappingCltSignalTypeToOduSignalType(intent.getSignalType());
345 - int requestedTsNum = oduSignalType.tributarySlots();
346 - Set<TributarySlot> commonTributarySlots = findCommonTributarySlotsOnCps(ports.getLeft(), ports.getRight());
347 - if (commonTributarySlots.isEmpty()) {
348 - return Collections.emptySet();
349 - }
350 - if (commonTributarySlots.size() < requestedTsNum) {
351 - return Collections.emptySet();
352 - }
353 -
354 - Set<TributarySlot> tributarySlots = commonTributarySlots.stream()
355 - .limit(requestedTsNum)
356 - .collect(Collectors.toSet());
357 -
358 - final List<ConnectPoint> portsList = ImmutableList.of(ports.getLeft(), ports.getRight());
359 - List<Resource> tributarySlotResources = portsList.stream()
360 - .flatMap(cp -> tributarySlots
361 - .stream()
362 - .map(ts-> Resources.discrete(cp.deviceId(), cp.port()).resource().child(ts)))
363 - .collect(Collectors.toList());
364 -
365 - List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), tributarySlotResources);
366 - if (allocations.isEmpty()) {
367 - log.debug("Resource allocation for {} failed (resource request: {})",
368 - intent, tributarySlotResources);
369 - return Collections.emptySet();
370 - }
371 - return tributarySlots;
372 - }
373 -
374 private ConnectPoint staticPort(ConnectPoint connectPoint) { 399 private ConnectPoint staticPort(ConnectPoint connectPoint) {
375 Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port()); 400 Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
376 401
......