2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights
7 * Modifications Copyright (C) 2019 IBM.
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.ccsdk.sli.adaptors.ra;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.List;
32 import org.onap.ccsdk.sli.adaptors.ra.comp.AllocationData;
33 import org.onap.ccsdk.sli.adaptors.ra.comp.EndPointAllocator;
34 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceData;
35 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceEntity;
36 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceRequest;
37 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceResponse;
38 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceTarget;
39 import org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManager;
40 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
41 import org.onap.ccsdk.sli.adaptors.rm.data.ReleaseRequest;
42 import org.onap.ccsdk.sli.adaptors.util.speed.SpeedUtil;
43 import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
44 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
45 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
46 import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 public class ResourceAllocator implements SvcLogicResource {
52 private static final Logger log = LoggerFactory.getLogger(ResourceAllocator.class);
54 private static final String[] INPUT_PREFIX = {"ra-input.", "tmp.resource-allocator."};
56 private ResourceManager resourceManager;
57 private EndPointAllocator endPointAllocator;
58 private SpeedUtil speedUtil;
60 public ResourceAllocator() {
61 log.info("ResourceAllocator created.");
65 public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx)
66 throws SvcLogicException {
67 return QueryStatus.SUCCESS;
71 public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix,
72 SvcLogicContext ctx) throws SvcLogicException {
74 return QueryStatus.SUCCESS;
78 public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx)
79 throws SvcLogicException {
80 return QueryStatus.SUCCESS;
84 public QueryStatus delete(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
85 return QueryStatus.SUCCESS;
89 public QueryStatus save(String arg0, boolean arg1, boolean arg2, String arg3, Map<String, String> arg4, String arg5,
90 SvcLogicContext arg6) throws SvcLogicException {
91 return QueryStatus.SUCCESS;
95 public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx)
96 throws SvcLogicException {
97 return allocateResources(ctx, true, prefix);
101 public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix,
102 String orderBy, SvcLogicContext ctx) throws SvcLogicException {
104 String resourceEntityId = getParam(ctx,
105 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, false, null);
106 String resourceEntityType =
107 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, false, null);
108 String resourceEntityVersion =
109 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
111 String resourceTargetId =
112 getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
113 String resourceTargetType =
114 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
115 String resourceName = getParam(ctx, "resource-name", false, null);
116 String resourceEntityTypeFilter = getParam(ctx, "resource-entity-type-filter", false, null);
117 String resourceEntityIdFilter = getParam(ctx, "resource-entity-id-filter", false, null);
118 String resourceShareGroupFilter = getParam(ctx, "resource-share-group-filter", false, null);
119 String resourceTargetTypeFilter = getParam(ctx, "resource-target-type-filter", false, null);
120 String resourceTargetIdFilter = getParam(ctx, "resource-target-id-filter", false, null);
122 if (resourceEntityId != null && resourceEntityType != null) {
123 List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(resourceEntityType, resourceEntityId,
124 resourceEntityVersion);
125 setResourceDataInContext(ctx, prefix, rdlist);
126 } else if (resourceTargetId != null && resourceTargetType != null && resourceName != null) {
127 ResourceData rd = endPointAllocator.getResource(resourceTargetType, resourceTargetId, resourceName,
128 resourceEntityTypeFilter, resourceEntityIdFilter, resourceShareGroupFilter);
130 setResourceDataInContext(ctx, prefix, Collections.singletonList(rd));
132 } else if ((resourceTargetTypeFilter != null || resourceTargetIdFilter != null) && resourceName != null) {
133 List<ResourceData> rdlist = endPointAllocator.getResourcesForTarget(resourceTargetTypeFilter,
134 resourceTargetIdFilter, resourceName);
135 setResourceDataInContext(ctx, prefix, rdlist);
138 return QueryStatus.SUCCESS;
141 public AllocationStatus query(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
142 List<ResourceResponse> rsList) throws Exception {
144 if (sd != null && sd.resourceEntityId != null && sd.resourceEntityType != null) {
145 List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(sd.resourceEntityType,
146 sd.resourceEntityId, sd.resourceEntityVersion);
147 setResourceDataInResponse(rdlist, rsList);
148 } else if (rt != null && rt.resourceTargetId != null && rt.resourceTargetType != null && rr != null
149 && rr.resourceName != null) {
150 ResourceData rd = endPointAllocator.getResource(rt.resourceTargetType, rt.resourceTargetId, rr.resourceName,
151 rr.resourceEntityTypeFilter, rr.resourceEntityIdFilter, rr.resourceShareGroupFilter);
152 setResourceDataInResponse(Collections.singletonList(rd), rsList);
153 } else if (rr != null && (rr.resourceTargetTypeFilter != null || rr.resourceTargetIdFilter != null)
154 && rr.resourceName != null) {
155 List<ResourceData> rdlist = endPointAllocator.getResourcesForTarget(rr.resourceTargetTypeFilter,
156 rr.resourceTargetIdFilter, rr.resourceName);
157 setResourceDataInResponse(rdlist, rsList);
160 return AllocationStatus.Success;
163 private void setResourceDataInContext(SvcLogicContext ctx, String prefix, List<ResourceData> rdlist) {
164 if (rdlist == null || rdlist.isEmpty()) {
168 prefix = prefix == null ? "" : prefix + '.';
170 setAttr(ctx, prefix + "resource-list_length", String.valueOf(rdlist.size()));
172 for (int i = 0; i < rdlist.size(); i++) {
173 ResourceData rd = rdlist.get(i);
175 String pp = prefix + "resource-list[" + i + "].";
177 setAttr(ctx, pp + "resource-name", rd.resourceName);
178 setAttr(ctx, pp + "endpoint-position", rd.endPointPosition);
179 setAttr(ctx, pp + "resource-target-type", rd.resourceTargetType);
180 setAttr(ctx, pp + "resource-target-id", rd.resourceTargetId);
181 setAttr(ctx, pp + "resource-target-value", rd.resourceTargetValue);
182 setAttr(ctx, pp + "status", rd.status);
184 Map<String, String> dataProp = dataToProperties(rd.data);
185 for (String kk : dataProp.keySet()) {
186 String value = String.valueOf(dataProp.get(kk));
187 setAttr(ctx, pp + kk, value);
190 if (rd.allocationDataList != null && !rd.allocationDataList.isEmpty()) {
192 setAttr(ctx, pp + "allocation-data-list_length", String.valueOf(rd.allocationDataList.size()));
194 for (int j = 0; j < rd.allocationDataList.size(); j++) {
195 AllocationData ad = rd.allocationDataList.get(j);
197 String ppp = pp + "allocation-data-list[" + j + "].";
199 setAttr(ctx, ppp + "resource-entity-type", ad.resourceEntityType);
200 setAttr(ctx, ppp + "resource-entity-id", ad.resourceEntityId);
201 setAttr(ctx, ppp + "resource-entity-version", ad.resourceEntityVersion);
203 if (ad.data != null && !ad.data.isEmpty()) {
204 for (String kk : ad.data.keySet()) {
205 String value = String.valueOf(ad.data.get(kk));
206 setAttr(ctx, ppp + kk, value);
215 public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx)
216 throws SvcLogicException {
217 return allocateResources(ctx, false, prefix);
220 public AllocationStatus reserve(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
221 List<ResourceResponse> rsList) throws Exception {
222 return allocateResources(sd, rt, rr, rsList);
226 public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
227 String resourceEntityId = getParam(ctx,
228 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, true, null);
229 String resourceEntityType =
230 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
231 String resourceEntityVersion =
232 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, null);
233 String resourceTargetId =
234 getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
235 String resourceTargetType =
236 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
237 String resourceName = getParam(ctx, new String[] {"resource-name"}, false, null);
238 String limitReleaseAmountStr = getParam(ctx, new String[] {"limit-release-amount"}, false, "-1");
239 int limitReleaseAmount = Integer.parseInt(limitReleaseAmountStr);
240 String rangeReleaseNumbers = getParam(ctx, new String[] {"range-release-numbers"}, false, null);
243 String endPointPosition = getParam(ctx, "endpoint-position", false, null);
245 ResourceEntity sd = new ResourceEntity();
246 sd.resourceEntityId = resourceEntityId;
247 sd.resourceEntityType = resourceEntityType;
248 sd.resourceEntityVersion = resourceEntityVersion;
250 ResourceRequest rr = new ResourceRequest();
251 rr.endPointPosition = endPointPosition;
252 rr.resourceName = resourceName;
253 rr.rangeReleaseNumbers = rangeReleaseNumbers;
254 rr.limitReleaseAmount = limitReleaseAmount;
256 ResourceTarget rt = new ResourceTarget();
257 rt.resourceTargetType = resourceTargetType;
258 rt.resourceTargetId = resourceTargetId;
261 this.release(sd, rr, rt);
262 } catch (Exception e) {
263 throw new SvcLogicException(e.getMessage());
265 return QueryStatus.SUCCESS;
268 public AllocationStatus release(ResourceEntity sd) throws Exception {
269 return release(sd, null, null);
272 public AllocationStatus release(ResourceEntity sd, ResourceRequest rr) throws Exception {
273 return release(sd, rr, null);
276 public AllocationStatus release(ResourceEntity sd, ResourceRequest rr, ResourceTarget rt) {
278 ReleaseRequest releaseRequest = new ReleaseRequest();
280 if (sd != null && sd.resourceEntityVersion != null) {
281 releaseRequest.resourceSetId = null;
283 if (rr != null && rr.endPointPosition != null && !rr.endPointPosition.isEmpty()) {
284 releaseRequest.resourceSetId = sd.resourceEntityType + "::" + sd.resourceEntityId + "::"
285 + rr.endPointPosition + "::" + sd.resourceEntityVersion;
287 releaseRequest.resourceSetId =
288 sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + sd.resourceEntityVersion;
291 } else if (sd != null && (sd.resourceEntityVersion == null || sd.resourceEntityVersion.isEmpty())) {
292 releaseRequest.resourceUnionId = null;
294 if (rr != null && rr.endPointPosition != null && !rr.endPointPosition.isEmpty()) {
295 releaseRequest.resourceUnionId =
296 sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + rr.endPointPosition;
298 releaseRequest.resourceUnionId = sd.resourceEntityType + "::" + sd.resourceEntityId;
302 if (rt != null && rt.resourceTargetId != null && rt.resourceTargetType != null) {
303 releaseRequest.assetId = rt.resourceTargetType + "::" + rt.resourceTargetId;
307 releaseRequest.resourceName = rr.resourceName;
308 releaseRequest.releaseNumbers =
309 StrUtil.listInt(rr.rangeReleaseNumbers, "Invalid value for range-release-numbers");
310 releaseRequest.releaseAmount = rr.limitReleaseAmount;
313 log.info("Releasing resources:");
314 StrUtil.info(log, releaseRequest);
316 resourceManager.releaseResources(releaseRequest);
318 return AllocationStatus.Success;
321 private QueryStatus allocateResources(SvcLogicContext ctx, boolean checkOnly, String prefix)
322 throws SvcLogicException {
323 String serviceModel = getParam(ctx, "service-model", true, null);
324 String requestType = getParam(ctx, "request-type", false, "New");
326 ResourceEntity sd = getResourceEntityData(ctx);
327 ResourceTarget rt = getResourceTargetData(ctx);
328 ResourceRequest rr = getResourceRequest(ctx);
330 log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
331 StrUtil.info(log, sd);
332 StrUtil.info(log, rt);
333 StrUtil.info(log, rr);
335 boolean change = "change".equalsIgnoreCase(requestType);
337 List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, checkOnly, change);
339 if (rlist != null && !rlist.isEmpty()) {
340 setResourceDataInContext(ctx, prefix, rlist);
342 for (ResourceData rd : rlist) {
343 if (!"Success".equals(rd.status)) {
344 log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
345 return QueryStatus.NOT_FOUND;
349 return QueryStatus.SUCCESS;
352 private AllocationStatus allocateResources(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
353 List<ResourceResponse> rsList) throws Exception {
355 String serviceModel = rr.serviceModel;
356 String requestType = rr.requestType == null ? "New" : rr.requestType;
358 log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
359 StrUtil.info(log, sd);
360 StrUtil.info(log, rt);
361 StrUtil.info(log, rr);
363 boolean change = "change".equalsIgnoreCase(requestType);
365 List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, rr.checkOnly, change);
367 if (rlist != null && !rlist.isEmpty()) {
368 setResourceDataInResponse(rlist, rsList);
370 for (ResourceData rd : rlist) {
371 if (!"Success".equals(rd.status)) {
372 log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
373 return AllocationStatus.ResourceNotFound;
378 return AllocationStatus.Success;
381 private void setResourceDataInResponse(List<ResourceData> rlist, List<ResourceResponse> rsList) {
382 for (ResourceData rd : emptyIfNull(rlist)) {
383 ResourceResponse res = new ResourceResponse();
384 res.resourceName = rd.resourceName;
385 res.endPointPosition = rd.endPointPosition;
386 res.resourceTargetId = rd.resourceTargetId;
387 res.resourceTargetType = rd.resourceTargetType;
388 res.status = rd.status;
389 if (rd.data != null && !rd.data.isEmpty()) {
390 for (String kk : rd.data.keySet()) {
391 if ("allocated".equalsIgnoreCase(kk)) {
392 res.resourceAllocated = String.valueOf(rd.data.get(kk));
395 if ("used".equalsIgnoreCase(kk)) {
396 res.resourceUsed = String.valueOf(rd.data.get(kk));
399 if ("available".equalsIgnoreCase(kk)) {
400 res.resourceAvailable = String.valueOf(rd.data.get(kk));
403 if ("limit".equalsIgnoreCase(kk)) {
404 res.resourceLimit = String.valueOf(rd.data.get(kk));
414 public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
415 return iterable == null ? Collections.<T>emptyList() : iterable;
418 private void setAttr(SvcLogicContext ctx, String name, String value) {
419 ctx.setAttribute(name, value);
420 log.info("Added context attr: " + name + ": " + value);
423 private ResourceEntity getResourceEntityData(SvcLogicContext ctx) throws SvcLogicException {
424 ResourceEntity sd = new ResourceEntity();
425 sd.resourceEntityId = getParam(ctx,
426 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, true, null);
427 sd.resourceEntityType =
428 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
429 sd.resourceEntityVersion =
430 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
431 sd.data = getDataParam(ctx, "reservation-entity-data", "resource-entity-data", "service-data");
435 private ResourceTarget getResourceTargetData(SvcLogicContext ctx) throws SvcLogicException {
436 ResourceTarget sd = new ResourceTarget();
437 sd.resourceTargetId = getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, true, null);
438 sd.resourceTargetType =
439 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, true, null);
440 sd.data = getDataParam(ctx, "reservation-target-data", "resource-target-data", "equipment-data");
444 private ResourceRequest getResourceRequest(SvcLogicContext ctx) throws SvcLogicException {
445 ResourceRequest rr = new ResourceRequest();
446 rr.resourceName = getParam(ctx, "resource-name", false, null);
447 rr.resourceShareGroup = getParam(ctx, "resource-share-group", false, null);
448 rr.rangeRequestedNumbers = getParam(ctx, "range-requested-numbers", false, null);
449 rr.rangeExcludeNumbers = getParam(ctx, "range-exclude-numbers", false, null);
450 String rangeReverseOrderStr = getParam(ctx, "range-reverse-order", false, "false");
451 rr.rangeReverseOrder = Boolean.parseBoolean(rangeReverseOrderStr);
452 String rangeMinOverrideStr = getParam(ctx, "range-min-override", false, "-1");
453 rr.rangeMinOverride = Integer.parseInt(rangeMinOverrideStr);
454 String rangeMaxOverrideStr = getParam(ctx, "range-max-override", false, "-1");
455 rr.rangeMaxOverride = Integer.parseInt(rangeMaxOverrideStr);
456 String rangeForceNewNumbersStr = getParam(ctx, "range-force-new-numbers", false, "false");
457 rr.rangeForceNewNumbers = Boolean.parseBoolean(rangeForceNewNumbersStr);
458 String rangeNextInSequenceStr = getParam(ctx, "range-next-in-sequence", false, "false");
459 rr.rangeNextInSequence = Boolean.parseBoolean(rangeNextInSequenceStr);
460 String replaceStr = getParam(ctx, "replace", false, "true");
461 rr.replace = Boolean.parseBoolean(replaceStr);
462 rr.applicationId = getParam(ctx, "application-id", false, "SDNC");
463 rr.endPointPosition = getParam(ctx, "endpoint-position", false, null);
467 private String getParam(SvcLogicContext ctx, String name, boolean required, String def) throws SvcLogicException {
469 for (String p : INPUT_PREFIX) {
470 v = ctx.getAttribute(p + name);
471 if (v != null && v.trim().length() > 0) {
472 log.info("Param: " + name + ": " + v.trim());
477 throw new SvcLogicException("The following variable is required in DG context: " + name);
480 log.info("Param: " + name + " not supplied. Using default: " + def);
484 private String getParam(SvcLogicContext ctx, String[] names, boolean required, String def)
485 throws SvcLogicException {
487 for (String name : names) {
488 v = getParam(ctx, name, false, def);
494 throw new SvcLogicException(
495 "One of the following variable is required in DG context: " + Arrays.deepToString(names));
498 log.info("Param: " + Arrays.deepToString(names) + " not supplied. Using default: " + def);
502 private Map<String, String> getDataParam(SvcLogicContext ctx, String... names) {
503 Map<String, String> data = new HashMap<>();
504 Set<String> ctxNames = ctx.getAttributeKeySet();
505 for (String n : ctxNames) {
506 for (String p : INPUT_PREFIX) {
507 for (String name : names) {
508 String pp = p + name + '.';
509 if (n.startsWith(pp)) {
510 String nn = n.substring(pp.length());
511 String vv = ctx.getAttribute(n);
514 log.info("Data param: " + nn + ": " + vv);
516 if (ctxNames.contains(n + "-unit")) {
518 long v = Long.parseLong(vv);
519 String unit = ctx.getAttribute(n + "-unit");
520 long kbps = speedUtil.convertToKbps(v, unit);
521 long mbps = speedUtil.convertToMbps(v, unit);
522 data.put(nn + "-kbps", String.valueOf(kbps));
523 data.put(nn + "-mbps", String.valueOf(mbps));
525 log.info("Data param: " + nn + "-kbps: " + kbps);
526 log.info("Data param: " + nn + "-mbps: " + mbps);
528 } catch (Exception e) {
529 log.warn("Invalid number for " + n + ": " + vv);
539 @SuppressWarnings("unchecked")
540 public static Map<String, String> dataToProperties(Map<String, Object> data) {
541 if (data == null || data.isEmpty()) {
542 return Collections.emptyMap();
545 Map<String, String> prop = new HashMap<>();
546 Map<String, Object> data1 = new HashMap<>(data);
548 while (!data1.isEmpty()) {
549 for (String key : new ArrayList<>(data1.keySet())) {
550 Object o = data1.get(key);
553 if (o instanceof Boolean || o instanceof Number || o instanceof String) {
554 prop.put(key, o.toString());
555 } else if (o instanceof Map) {
556 Map<String, Object> mm = (Map<String, Object>) o;
557 for (String key1 : mm.keySet()) {
558 data1.put(key + "." + key1, mm.get(key1));
560 } else if (o instanceof List) {
561 List<Object> ll = (List<Object>) o;
562 prop.put(key + "_length", String.valueOf(ll.size()));
563 for (int i = 0; i < ll.size(); i++) {
564 data1.put(key + '[' + i + ']', ll.get(i));
572 public void setResourceManager(ResourceManager resourceManager) {
573 this.resourceManager = resourceManager;
576 public void setEndPointAllocator(EndPointAllocator endPointAllocator) {
577 this.endPointAllocator = endPointAllocator;
580 public void setSpeedUtil(SpeedUtil speedUtil) {
581 this.speedUtil = speedUtil;