Committed by
Gerrit Code Review
Separate resource search from resource allocation
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: Id254fe103803daf60ef2576fb5d717e9faa68c03
Showing
1 changed file
with
70 additions
and
47 deletions
... | @@ -97,7 +97,7 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical | ... | @@ -97,7 +97,7 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical |
97 | @Override | 97 | @Override |
98 | public List<Intent> compile(OpticalConnectivityIntent intent, | 98 | public List<Intent> compile(OpticalConnectivityIntent intent, |
99 | List<Intent> installable, | 99 | List<Intent> installable, |
100 | - Set<LinkResourceAllocations> resources) { | 100 | + Set<LinkResourceAllocations> linkResources) { |
101 | // Check if source and destination are optical OCh ports | 101 | // Check if source and destination are optical OCh ports |
102 | ConnectPoint src = intent.getSrc(); | 102 | ConnectPoint src = intent.getSrc(); |
103 | ConnectPoint dst = intent.getDst(); | 103 | ConnectPoint dst = intent.getDst(); |
... | @@ -113,94 +113,117 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical | ... | @@ -113,94 +113,117 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical |
113 | // TODO: try to release intent resources in IntentManager. | 113 | // TODO: try to release intent resources in IntentManager. |
114 | resourceService.release(intent.id()); | 114 | resourceService.release(intent.id()); |
115 | 115 | ||
116 | - // Reserve OCh ports | 116 | + // Check OCh port availability |
117 | Resource srcPortResource = Resources.discrete(src.deviceId(), src.port()).resource(); | 117 | Resource srcPortResource = Resources.discrete(src.deviceId(), src.port()).resource(); |
118 | Resource dstPortResource = Resources.discrete(dst.deviceId(), dst.port()).resource(); | 118 | Resource dstPortResource = Resources.discrete(dst.deviceId(), dst.port()).resource(); |
119 | - List<ResourceAllocation> allocation = resourceService.allocate(intent.id(), srcPortResource, dstPortResource); | 119 | + // If ports are not available, compilation fails |
120 | - if (allocation.isEmpty()) { | 120 | + if (!Stream.of(srcPortResource, dstPortResource).allMatch(resourceService::isAvailable)) { |
121 | - throw new IntentCompilationException("Unable to reserve ports for intent " + intent); | 121 | + throw new IntentCompilationException("Ports for the intent are not available. Intent: " + intent); |
122 | } | 122 | } |
123 | 123 | ||
124 | + List<Resource> resources = new ArrayList<>(); | ||
125 | + resources.add(srcPortResource); | ||
126 | + resources.add(dstPortResource); | ||
127 | + | ||
124 | // Calculate available light paths | 128 | // Calculate available light paths |
125 | Set<Path> paths = getOpticalPaths(intent); | 129 | Set<Path> paths = getOpticalPaths(intent); |
126 | 130 | ||
131 | + if (paths.isEmpty()) { | ||
132 | + throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent); | ||
133 | + } | ||
134 | + | ||
127 | // Static or dynamic lambda allocation | 135 | // Static or dynamic lambda allocation |
128 | String staticLambda = srcPort.annotations().value(AnnotationKeys.STATIC_LAMBDA); | 136 | String staticLambda = srcPort.annotations().value(AnnotationKeys.STATIC_LAMBDA); |
129 | OchPort srcOchPort = (OchPort) srcPort; | 137 | OchPort srcOchPort = (OchPort) srcPort; |
130 | OchPort dstOchPort = (OchPort) dstPort; | 138 | OchPort dstOchPort = (OchPort) dstPort; |
131 | - OchSignal ochSignal; | ||
132 | - | ||
133 | - // Use first path that can be successfully reserved | ||
134 | - for (Path path : paths) { | ||
135 | 139 | ||
140 | + Path firstPath = paths.iterator().next(); | ||
136 | // FIXME: need to actually reserve the lambda for static lambda's | 141 | // FIXME: need to actually reserve the lambda for static lambda's |
142 | + // static lambda case: early return | ||
137 | if (staticLambda != null) { | 143 | if (staticLambda != null) { |
138 | - ochSignal = new OchSignal(Frequency.ofHz(Long.parseLong(staticLambda)), | 144 | + allocateResources(intent, resources); |
145 | + | ||
146 | + OchSignal lambda = new OchSignal(Frequency.ofHz(Long.parseLong(staticLambda)), | ||
139 | srcOchPort.lambda().channelSpacing(), | 147 | srcOchPort.lambda().channelSpacing(), |
140 | srcOchPort.lambda().slotGranularity()); | 148 | srcOchPort.lambda().slotGranularity()); |
141 | - } else if (!srcOchPort.isTunable() || !dstOchPort.isTunable()) { | 149 | + return ImmutableList.of(createIntent(intent, firstPath, lambda)); |
150 | + } | ||
151 | + | ||
142 | // FIXME: also check destination OCh port | 152 | // FIXME: also check destination OCh port |
143 | - ochSignal = srcOchPort.lambda(); | 153 | + // non-tunable case: early return |
144 | - } else { | 154 | + if (!srcOchPort.isTunable() || !dstOchPort.isTunable()) { |
145 | - // Request and reserve lambda on path | 155 | + allocateResources(intent, resources); |
146 | - List<OchSignal> lambdas = assignWavelength(intent, path); | 156 | + |
147 | - if (lambdas.isEmpty()) { | 157 | + OchSignal lambda = srcOchPort.lambda(); |
158 | + return ImmutableList.of(createIntent(intent, firstPath, lambda)); | ||
159 | + } | ||
160 | + | ||
161 | + // Use first path that can be successfully reserved | ||
162 | + for (Path path : paths) { | ||
163 | + // find common lambda on path | ||
164 | + // a list of OchSignal indicates consecutive OchSignals | ||
165 | + List<OchSignal> lambda = findFirstAvailableOch(path); | ||
166 | + if (lambda.isEmpty()) { | ||
167 | + continue; | ||
168 | + } | ||
169 | + List<Resource> lambdaResources = convertToResources(path.links(), lambda); | ||
170 | + if (!lambdaResources.stream().allMatch(resourceService::isAvailable)) { | ||
148 | continue; | 171 | continue; |
149 | } | 172 | } |
150 | - ochSignal = OchSignal.toFixedGrid(lambdas, ChannelSpacing.CHL_50GHZ); | 173 | + resources.addAll(lambdaResources); |
174 | + | ||
175 | + allocateResources(intent, resources); | ||
176 | + | ||
177 | + OchSignal ochSignal = OchSignal.toFixedGrid(lambda, ChannelSpacing.CHL_50GHZ); | ||
178 | + return ImmutableList.of(createIntent(intent, path, ochSignal)); | ||
179 | + } | ||
180 | + | ||
181 | + throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent); | ||
151 | } | 182 | } |
152 | 183 | ||
184 | + private Intent createIntent(OpticalConnectivityIntent parentIntent, Path path, OchSignal lambda) { | ||
153 | // Create installable optical path intent | 185 | // Create installable optical path intent |
154 | // Only support fixed grid for now | 186 | // Only support fixed grid for now |
155 | OchSignalType signalType = OchSignalType.FIXED_GRID; | 187 | OchSignalType signalType = OchSignalType.FIXED_GRID; |
156 | 188 | ||
157 | - Intent newIntent = OpticalPathIntent.builder() | 189 | + return OpticalPathIntent.builder() |
158 | - .appId(intent.appId()) | 190 | + .appId(parentIntent.appId()) |
159 | - .src(intent.getSrc()) | 191 | + .src(parentIntent.getSrc()) |
160 | - .dst(intent.getDst()) | 192 | + .dst(parentIntent.getDst()) |
193 | + // calling paths.iterator().next() is safe because of non-empty set | ||
161 | .path(path) | 194 | .path(path) |
162 | - .lambda(ochSignal) | 195 | + .lambda(lambda) |
163 | .signalType(signalType) | 196 | .signalType(signalType) |
164 | - .bidirectional(intent.isBidirectional()) | 197 | + .bidirectional(parentIntent.isBidirectional()) |
165 | .build(); | 198 | .build(); |
166 | - | ||
167 | - return ImmutableList.of(newIntent); | ||
168 | } | 199 | } |
169 | 200 | ||
170 | - // Release port allocations if unsuccessful | 201 | + private void allocateResources(Intent intent, List<Resource> resources) { |
171 | - resourceService.release(intent.id()); | 202 | + // reserve all of required resources |
172 | - | 203 | + List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), resources); |
173 | - throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent); | 204 | + if (allocations.isEmpty()) { |
205 | + log.info("Resource allocation for {} failed (resource request: {})", intent, resources); | ||
206 | + throw new IntentCompilationException("Unable to allocate resources: " + resources); | ||
207 | + } | ||
174 | } | 208 | } |
175 | 209 | ||
176 | - /** | 210 | + private List<OchSignal> findFirstAvailableOch(Path path) { |
177 | - * Request and reserve first available wavelength across path. | ||
178 | - * | ||
179 | - * @param path path in WDM topology | ||
180 | - * @return first available lambda allocated | ||
181 | - */ | ||
182 | - private List<OchSignal> assignWavelength(Intent intent, Path path) { | ||
183 | Set<OchSignal> lambdas = findCommonLambdasOverLinks(path.links()); | 211 | Set<OchSignal> lambdas = findCommonLambdasOverLinks(path.links()); |
184 | if (lambdas.isEmpty()) { | 212 | if (lambdas.isEmpty()) { |
185 | return Collections.emptyList(); | 213 | return Collections.emptyList(); |
186 | } | 214 | } |
187 | 215 | ||
188 | - List<OchSignal> minLambda = findFirstLambda(lambdas, slotCount()); | 216 | + return findFirstLambda(lambdas, slotCount()); |
189 | - List<Resource> lambdaResources = path.links().stream() | 217 | + } |
218 | + | ||
219 | + private List<Resource> convertToResources(List<Link> links, List<OchSignal> lambda) { | ||
220 | + return links.stream() | ||
190 | .flatMap(x -> Stream.of( | 221 | .flatMap(x -> Stream.of( |
191 | Resources.discrete(x.src().deviceId(), x.src().port()).resource(), | 222 | Resources.discrete(x.src().deviceId(), x.src().port()).resource(), |
192 | Resources.discrete(x.dst().deviceId(), x.dst().port()).resource() | 223 | Resources.discrete(x.dst().deviceId(), x.dst().port()).resource() |
193 | )) | 224 | )) |
194 | - .flatMap(x -> minLambda.stream().map(l -> x.child(l))) | 225 | + .flatMap(x -> lambda.stream().map(x::child)) |
195 | .collect(Collectors.toList()); | 226 | .collect(Collectors.toList()); |
196 | - | ||
197 | - List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources); | ||
198 | - if (allocations.isEmpty()) { | ||
199 | - log.info("Resource allocation for {} failed (resource request: {})", intent, lambdaResources); | ||
200 | - return Collections.emptyList(); | ||
201 | - } | ||
202 | - | ||
203 | - return minLambda; | ||
204 | } | 227 | } |
205 | 228 | ||
206 | /** | 229 | /** | ... | ... |
-
Please register or login to post a comment