Merge "fixed sonar issue in GenericRequest.java"
[ccsdk/sli/adaptors.git] / resource-assignment / provider / src / main / java / org / onap / ccsdk / sli / adaptors / ra / ResourceAllocator.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                                                      reserved.
7  * Modifications Copyright (C) 2018 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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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=========================================================
21  */
22
23 package org.onap.ccsdk.sli.adaptors.ra;
24
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import org.onap.ccsdk.sli.adaptors.ra.comp.EndPointAllocator;
32 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceData;
33 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceEntity;
34 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceRequest;
35 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceResponse;
36 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceTarget;
37 import org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManager;
38 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
39 import org.onap.ccsdk.sli.adaptors.rm.data.ReleaseRequest;
40 import org.onap.ccsdk.sli.adaptors.util.speed.SpeedUtil;
41 import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
42 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
43 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
44 import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 public class ResourceAllocator implements SvcLogicResource {
49
50     private static final Logger log = LoggerFactory.getLogger(ResourceAllocator.class);
51
52     private static final String[] INPUT_PREFIX = {"ra-input.", "tmp.resource-allocator."};
53
54     private ResourceManager resourceManager;
55     private EndPointAllocator endPointAllocator;
56     private SpeedUtil speedUtil;
57
58     public ResourceAllocator() {
59         log.info("ResourceAllocator created.");
60     }
61
62     @Override
63     public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx)
64             throws SvcLogicException {
65         return QueryStatus.SUCCESS;
66     }
67
68     @Override
69     public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix,
70             SvcLogicContext ctx) throws SvcLogicException {
71
72         return QueryStatus.SUCCESS;
73     }
74
75     @Override
76     public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx)
77             throws SvcLogicException {
78         return QueryStatus.SUCCESS;
79     }
80
81     @Override
82     public QueryStatus delete(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
83         return QueryStatus.SUCCESS;
84     }
85
86     @Override
87     public QueryStatus save(String arg0, boolean arg1, boolean arg2, String arg3, Map<String, String> arg4, String arg5,
88             SvcLogicContext arg6) throws SvcLogicException {
89         return QueryStatus.SUCCESS;
90     }
91
92     @Override
93     public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx)
94             throws SvcLogicException {
95         return allocateResources(ctx, true, prefix);
96     }
97
98     @Override
99     public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix,
100             String orderBy, SvcLogicContext ctx) throws SvcLogicException {
101
102         String resourceEntityId = getParam(ctx,
103                 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, false, null);
104         String resourceEntityType =
105                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, false, null);
106         String resourceEntityVersion =
107                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
108
109         String resourceTargetId =
110                 getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
111         String resourceTargetType =
112                 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
113         String resourceName = getParam(ctx, "resource-name", false, null);
114         String resourceEntityTypeFilter = getParam(ctx, "resource-entity-type-filter", false, null);
115         String resourceEntityIdFilter = getParam(ctx, "resource-entity-id-filter", false, null);
116         String resourceShareGroupFilter = getParam(ctx, "resource-share-group-filter", false, null);
117         String resourceTargetTypeFilter = getParam(ctx, "resource-target-type-filter", false, null);
118         String resourceTargetIdFilter = getParam(ctx, "resource-target-id-filter", false, null);
119
120         if (resourceEntityId != null && resourceEntityType != null) {
121             List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(resourceEntityType, resourceEntityId,
122                     resourceEntityVersion);
123             setResourceDataInContext(ctx, prefix, rdlist);
124         } else if (resourceTargetId != null && resourceTargetType != null && resourceName != null) {
125             ResourceData rd = endPointAllocator.getResource(resourceTargetType, resourceTargetId, resourceName,
126                     resourceEntityTypeFilter, resourceEntityIdFilter, resourceShareGroupFilter);
127             setResourceDataInContext(ctx, prefix, Collections.singletonList(rd));
128         } else if ((resourceTargetTypeFilter != null || resourceTargetIdFilter != null) && resourceName != null) {
129             List<ResourceData> rdlist = endPointAllocator.getResourcesForTarget(resourceTargetTypeFilter,
130                     resourceTargetIdFilter, resourceName);
131             setResourceDataInContext(ctx, prefix, rdlist);
132         }
133
134         return QueryStatus.SUCCESS;
135     }
136
137     public AllocationStatus query(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
138             List<ResourceResponse> rsList) throws Exception {
139
140         if (sd != null && sd.resourceEntityId != null && sd.resourceEntityType != null) {
141             List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(sd.resourceEntityType,
142                     sd.resourceEntityId, sd.resourceEntityVersion);
143             setResourceDataInResponse(rdlist, rsList);
144         } else if (rt != null && rt.resourceTargetId != null && rt.resourceTargetType != null && rr != null
145                 && rr.resourceName != null) {
146             ResourceData rd = endPointAllocator.getResource(rt.resourceTargetType, rt.resourceTargetId, rr.resourceName,
147                     rr.resourceEntityTypeFilter, rr.resourceEntityIdFilter, rr.resourceShareGroupFilter);
148             setResourceDataInResponse(Collections.singletonList(rd), rsList);
149         } else if (rr != null && (rr.resourceTargetTypeFilter != null || rr.resourceTargetIdFilter != null)
150                 && rr.resourceName != null) {
151             List<ResourceData> rdlist = endPointAllocator.getResourcesForTarget(rr.resourceTargetTypeFilter,
152                     rr.resourceTargetIdFilter, rr.resourceName);
153             setResourceDataInResponse(rdlist, rsList);
154         }
155
156         return AllocationStatus.Success;
157     }
158
159     private void setResourceDataInContext(SvcLogicContext ctx, String prefix, List<ResourceData> rdlist) {
160         prefix = prefix == null ? "" : prefix + '.';
161
162         setAttr(ctx, prefix + "resource-list_length", String.valueOf(rdlist.size()));
163
164         for (int i = 0; i < rdlist.size(); i++) {
165             ResourceData rd = rdlist.get(i);
166
167             String pp = prefix + "resource-list[" + i + "].";
168
169             setAttr(ctx, pp + "resource-name", rd.resourceName);
170             setAttr(ctx, pp + "endpoint-position", rd.endPointPosition);
171             setAttr(ctx, pp + "resource-target-type", rd.resourceTargetType);
172             setAttr(ctx, pp + "resource-target-id", rd.resourceTargetId);
173             // SDNGC-7687
174             setAttr(ctx, pp + "resource-target-value", rd.resourceTargetValue);
175             setAttr(ctx, pp + "status", rd.status);
176
177             if (rd.data != null && !rd.data.isEmpty()) {
178                 for (String kk : rd.data.keySet()) {
179                     String value = String.valueOf(rd.data.get(kk));
180                     setAttr(ctx, pp + kk, value);
181                 }
182             }
183         }
184     }
185
186     @Override
187     public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx)
188             throws SvcLogicException {
189         return allocateResources(ctx, false, prefix);
190     }
191
192     public AllocationStatus reserve(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
193             List<ResourceResponse> rsList) throws Exception {
194         return allocateResources(sd, rt, rr, rsList);
195     }
196
197     @Override
198     public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
199         String resourceEntityId = getParam(ctx,
200                 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, true, null);
201         String resourceEntityType =
202                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
203         String resourceEntityVersion =
204                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, null);
205         String resourceTargetId =
206                 getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
207         String resourceTargetType =
208                 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
209         String resourceName = getParam(ctx, new String[] {"resource-name"}, false, null);
210         String limitReleaseAmountStr = getParam(ctx, new String[] {"limit-release-amount"}, false, "-1");
211         int limitReleaseAmount = Integer.parseInt(limitReleaseAmountStr);
212         String rangeReleaseNumbers = getParam(ctx, new String[] {"range-release-numbers"}, false, null);
213
214
215         String endPointPosition = getParam(ctx, "endpoint-position", false, null);
216
217         ResourceEntity sd = new ResourceEntity();
218         sd.resourceEntityId = resourceEntityId;
219         sd.resourceEntityType = resourceEntityType;
220         sd.resourceEntityVersion = resourceEntityVersion;
221
222         ResourceRequest rr = new ResourceRequest();
223         rr.endPointPosition = endPointPosition;
224         rr.resourceName = resourceName;
225         rr.rangeReleaseNumbers = rangeReleaseNumbers;
226         rr.limitReleaseAmount = limitReleaseAmount;
227
228         ResourceTarget rt = new ResourceTarget();
229         rt.resourceTargetType = resourceTargetType;
230         rt.resourceTargetId = resourceTargetId;
231
232         try {
233             this.release(sd, rr, rt);
234         } catch (Exception e) {
235             throw new SvcLogicException(e.getMessage());
236         }
237         return QueryStatus.SUCCESS;
238     }
239
240     public AllocationStatus release(ResourceEntity sd) throws Exception {
241         return release(sd, null, null);
242     }
243
244     public AllocationStatus release(ResourceEntity sd, ResourceRequest rr) throws Exception {
245         return release(sd, rr, null);
246     }
247
248     public AllocationStatus release(ResourceEntity sd, ResourceRequest rr, ResourceTarget rt) throws Exception {
249
250         ReleaseRequest releaseRequest = new ReleaseRequest();
251
252         if (sd != null && sd.resourceEntityVersion != null) {
253             releaseRequest.resourceSetId = null;
254
255             if (rr != null && rr.endPointPosition != null && !rr.endPointPosition.isEmpty()) {
256                 releaseRequest.resourceSetId = sd.resourceEntityType + "::" + sd.resourceEntityId + "::"
257                         + rr.endPointPosition + "::" + sd.resourceEntityVersion;
258             } else {
259                 releaseRequest.resourceSetId =
260                         sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + sd.resourceEntityVersion;
261             }
262
263         } else if (sd != null && (sd.resourceEntityVersion == null || sd.resourceEntityVersion.isEmpty())) {
264             releaseRequest.resourceUnionId = null;
265
266             if (rr != null && rr.endPointPosition != null && !rr.endPointPosition.isEmpty()) {
267                 releaseRequest.resourceUnionId =
268                         sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + rr.endPointPosition;
269             } else {
270                 releaseRequest.resourceUnionId = sd.resourceEntityType + "::" + sd.resourceEntityId;
271             }
272         }
273
274         if (rt != null && rt.resourceTargetId != null && rt.resourceTargetType != null) {
275             releaseRequest.assetId = rt.resourceTargetType + "::" + rt.resourceTargetId;
276         }
277
278         if (rr != null) {
279             releaseRequest.resourceName = rr.resourceName;
280             releaseRequest.releaseNumbers =
281                     StrUtil.listInt(rr.rangeReleaseNumbers, "Invalid value for range-release-numbers");
282             releaseRequest.releaseAmount = rr.limitReleaseAmount;
283         }
284
285         log.info("Releasing resources:");
286         StrUtil.info(log, releaseRequest);
287
288         resourceManager.releaseResources(releaseRequest);
289
290         return AllocationStatus.Success;
291     }
292
293     private QueryStatus allocateResources(SvcLogicContext ctx, boolean checkOnly, String prefix)
294             throws SvcLogicException {
295         String serviceModel = getParam(ctx, "service-model", true, null);
296         String requestType = getParam(ctx, "request-type", false, "New");
297
298         ResourceEntity sd = getResourceEntityData(ctx);
299         ResourceTarget rt = getResourceTargetData(ctx);
300         ResourceRequest rr = getResourceRequest(ctx);
301
302         log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
303         StrUtil.info(log, sd);
304         StrUtil.info(log, rt);
305         StrUtil.info(log, rr);
306
307         boolean change = "change".equalsIgnoreCase(requestType);
308
309         List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, checkOnly, change);
310
311         if (rlist != null && !rlist.isEmpty()) {
312             setResourceDataInContext(ctx, prefix, rlist);
313
314             for (ResourceData rd : rlist) {
315                 if (!"Success".equals(rd.status)) {
316                     log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
317                     return QueryStatus.NOT_FOUND;
318                 }
319             }
320         }
321         return QueryStatus.SUCCESS;
322     }
323
324     private AllocationStatus allocateResources(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
325             List<ResourceResponse> rsList) throws Exception {
326
327         String serviceModel = rr.serviceModel;
328         String requestType = rr.requestType == null ? "New" : rr.requestType;
329
330         log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
331         StrUtil.info(log, sd);
332         StrUtil.info(log, rt);
333         StrUtil.info(log, rr);
334
335         boolean change = "change".equalsIgnoreCase(requestType);
336
337         List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, rr.checkOnly, change);
338
339         if (rlist != null && !rlist.isEmpty()) {
340             setResourceDataInResponse(rlist, rsList);
341
342             for (ResourceData rd : rlist) {
343                 if (!"Success".equals(rd.status)) {
344                     log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
345                     return AllocationStatus.ResourceNotFound;
346                 }
347             }
348         }
349
350         return AllocationStatus.Success;
351     }
352
353     private void setResourceDataInResponse(List<ResourceData> rlist, List<ResourceResponse> rsList) {
354         for (ResourceData rd : emptyIfNull(rlist)) {
355             ResourceResponse res = new ResourceResponse();
356             res.resourceName = rd.resourceName;
357             res.endPointPosition = rd.endPointPosition;
358             res.resourceTargetId = rd.resourceTargetId;
359             res.resourceTargetType = rd.resourceTargetType;
360             res.status = rd.status;
361             if (rd.data != null && !rd.data.isEmpty()) {
362                 for (String kk : rd.data.keySet()) {
363                     if ("allocated".equalsIgnoreCase(kk)) {
364                         res.resourceAllocated = String.valueOf(rd.data.get(kk));
365                     }
366
367                     if ("used".equalsIgnoreCase(kk)) {
368                         res.resourceUsed = String.valueOf(rd.data.get(kk));
369                     }
370
371                     if ("available".equalsIgnoreCase(kk)) {
372                         res.resourceAvailable = String.valueOf(rd.data.get(kk));
373                     }
374
375                     if ("limit".equalsIgnoreCase(kk)) {
376                         res.resourceLimit = String.valueOf(rd.data.get(kk));
377                     }
378
379                 }
380             }
381             rsList.add(res);
382         }
383
384     }
385
386     public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
387         return iterable == null ? Collections.<T>emptyList() : iterable;
388     }
389
390     private void setAttr(SvcLogicContext ctx, String name, String value) {
391         ctx.setAttribute(name, value);
392         log.info("Added context attr: " + name + ": " + value);
393     }
394
395     private ResourceEntity getResourceEntityData(SvcLogicContext ctx) throws SvcLogicException {
396         ResourceEntity sd = new ResourceEntity();
397         sd.resourceEntityId = getParam(ctx,
398                 new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, true, null);
399         sd.resourceEntityType =
400                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
401         sd.resourceEntityVersion =
402                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
403         sd.data = getDataParam(ctx, "reservation-entity-data", "resource-entity-data", "service-data");
404         return sd;
405     }
406
407     private ResourceTarget getResourceTargetData(SvcLogicContext ctx) throws SvcLogicException {
408         ResourceTarget sd = new ResourceTarget();
409         sd.resourceTargetId = getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, true, null);
410         sd.resourceTargetType =
411                 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, true, null);
412         sd.data = getDataParam(ctx, "reservation-target-data", "resource-target-data", "equipment-data");
413         return sd;
414     }
415
416     private ResourceRequest getResourceRequest(SvcLogicContext ctx) throws SvcLogicException {
417         ResourceRequest rr = new ResourceRequest();
418         rr.resourceName = getParam(ctx, "resource-name", false, null);
419         rr.resourceShareGroup = getParam(ctx, "resource-share-group", false, null);
420         rr.rangeRequestedNumbers = getParam(ctx, "range-requested-numbers", false, null);
421         rr.rangeExcludeNumbers = getParam(ctx, "range-exclude-numbers", false, null);
422         String rangeReverseOrderStr = getParam(ctx, "range-reverse-order", false, "false");
423         rr.rangeReverseOrder = Boolean.parseBoolean(rangeReverseOrderStr);
424         String rangeMinOverrideStr = getParam(ctx, "range-min-override", false, "-1");
425         rr.rangeMinOverride = Integer.parseInt(rangeMinOverrideStr);
426         String rangeMaxOverrideStr = getParam(ctx, "range-max-override", false, "-1");
427         rr.rangeMaxOverride = Integer.parseInt(rangeMaxOverrideStr);
428         String rangeForceNewNumbersStr = getParam(ctx, "range-force-new-numbers", false, "false");
429         rr.rangeForceNewNumbers = Boolean.parseBoolean(rangeForceNewNumbersStr);
430         String replaceStr = getParam(ctx, "replace", false, "true");
431         rr.replace = Boolean.parseBoolean(replaceStr);
432         rr.applicationId = getParam(ctx, "application-id", false, "SDNC");
433         rr.endPointPosition = getParam(ctx, "endpoint-position", false, null);
434         return rr;
435     }
436
437     private String getParam(SvcLogicContext ctx, String name, boolean required, String def) throws SvcLogicException {
438         String v = null;
439         for (String p : INPUT_PREFIX) {
440             v = ctx.getAttribute(p + name);
441             if (v != null && v.trim().length() > 0) {
442                 log.info("Param: " + name + ": " + v.trim());
443                 return v.trim();
444             }
445         }
446         if (required) {
447             throw new SvcLogicException("The following variable is required in DG context: " + name);
448         }
449
450         log.info("Param: " + name + " not supplied. Using default: " + def);
451         return def;
452     }
453
454     private String getParam(SvcLogicContext ctx, String[] names, boolean required, String def)
455             throws SvcLogicException {
456         String v = null;
457         for (String name : names) {
458             v = getParam(ctx, name, false, def);
459             if (v != null) {
460                 return v;
461             }
462         }
463         if (required) {
464             throw new SvcLogicException(
465                     "One of the following variable is required in DG context: " + Arrays.deepToString(names));
466         }
467
468         log.info("Param: " + Arrays.deepToString(names) + " not supplied. Using default: " + def);
469         return def;
470     }
471
472     private Map<String, String> getDataParam(SvcLogicContext ctx, String... names) {
473         Map<String, String> data = new HashMap<>();
474         Set<String> ctxNames = ctx.getAttributeKeySet();
475         for (String n : ctxNames) {
476             for (String p : INPUT_PREFIX) {
477                 for (String name : names) {
478                     String pp = p + name + '.';
479                     if (n.startsWith(pp)) {
480                         String nn = n.substring(pp.length());
481                         String vv = ctx.getAttribute(n);
482                         data.put(nn, vv);
483
484                         log.info("Data param: " + nn + ": " + vv);
485
486                         if (ctxNames.contains(n + "-unit")) {
487                             try {
488                                 long v = Long.parseLong(vv);
489                                 String unit = ctx.getAttribute(n + "-unit");
490                                 long kbps = speedUtil.convertToKbps(v, unit);
491                                 long mbps = speedUtil.convertToMbps(v, unit);
492                                 data.put(nn + "-kbps", String.valueOf(kbps));
493                                 data.put(nn + "-mbps", String.valueOf(mbps));
494
495                                 log.info("Data param: " + nn + "-kbps: " + kbps);
496                                 log.info("Data param: " + nn + "-mbps: " + mbps);
497
498                             } catch (Exception e) {
499                                 log.warn("Invalid number for " + n + ": " + vv);
500                             }
501                         }
502                     }
503                 }
504             }
505         }
506         return data;
507     }
508
509     public void setResourceManager(ResourceManager resourceManager) {
510         this.resourceManager = resourceManager;
511     }
512
513     public void setEndPointAllocator(EndPointAllocator endPointAllocator) {
514         this.endPointAllocator = endPointAllocator;
515     }
516
517     public void setSpeedUtil(SpeedUtil speedUtil) {
518         this.speedUtil = speedUtil;
519     }
520 }