0e4b9252d385557a106cf4cfa8e052f0405efaa9
[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  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.ccsdk.sli.adaptors.ra;
23
24 import java.util.Arrays;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import org.onap.ccsdk.sli.adaptors.ra.comp.EndPointAllocator;
31 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceData;
32 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceEntity;
33 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceRequest;
34 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceResponse;
35 import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceTarget;
36 import org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManager;
37 import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
38 import org.onap.ccsdk.sli.adaptors.util.speed.SpeedUtil;
39 import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
40 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
41 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
42 import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 public class ResourceAllocator implements SvcLogicResource {
47
48     private static final Logger log = LoggerFactory.getLogger(ResourceAllocator.class);
49
50     private static final String[] INPUT_PREFIX = {"ra-input.", "tmp.resource-allocator."};
51
52     private ResourceManager resourceManager;
53     private EndPointAllocator endPointAllocator;
54     private SpeedUtil speedUtil;
55
56     public ResourceAllocator() {
57         log.info("ResourceAllocator created.");
58     }
59
60     @Override
61     public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx)
62             throws SvcLogicException {
63         return QueryStatus.SUCCESS;
64     }
65
66     @Override
67     public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix,
68             SvcLogicContext ctx) throws SvcLogicException {
69
70         return QueryStatus.SUCCESS;
71     }
72
73     @Override
74     public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx)
75             throws SvcLogicException {
76         return QueryStatus.SUCCESS;
77     }
78
79     @Override
80     public QueryStatus delete(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
81         return QueryStatus.SUCCESS;
82     }
83
84     @Override
85     public QueryStatus save(String arg0, boolean arg1, boolean arg2, String arg3, Map<String, String> arg4, String arg5,
86             SvcLogicContext arg6) throws SvcLogicException {
87         return QueryStatus.SUCCESS;
88     }
89
90     @Override
91     public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx)
92             throws SvcLogicException {
93         return allocateResources(ctx, true, prefix);
94     }
95
96     @Override
97     public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix,
98             String orderBy, SvcLogicContext ctx) throws SvcLogicException {
99
100         String resourceEntityId = getParam(ctx,
101                 new String[] {"service-instance-id", "reservation-entity-id", "resource-entity-id"}, false, null);
102         String resourceEntityType =
103                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, false, null);
104         String resourceEntityVersion =
105                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
106
107         String resourceTargetId =
108                 getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
109         String resourceTargetType =
110                 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
111         String resourceName = getParam(ctx, "resource-name", false, null);
112
113         if (resourceEntityId != null && resourceEntityType != null) {
114             List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(resourceEntityType, resourceEntityId,
115                     resourceEntityVersion);
116             setResourceDataInContext(ctx, prefix, rdlist);
117         } else if (resourceTargetId != null && resourceTargetType != null && resourceName != null) {
118             ResourceData rd = endPointAllocator.getResource(resourceTargetType, resourceTargetId, resourceName);
119             setResourceDataInContext(ctx, prefix, Collections.singletonList(rd));
120         }
121
122         return QueryStatus.SUCCESS;
123     }
124
125     public AllocationStatus query(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
126             List<ResourceResponse> rsList) throws Exception {
127
128         if (sd.resourceEntityId != null && sd.resourceEntityType != null) {
129             List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(sd.resourceEntityType,
130                     sd.resourceEntityId, sd.resourceEntityVersion);
131             setResourceDataInResponse(rdlist, rsList);
132         } else if (rt.resourceTargetId != null && rt.resourceTargetType != null && rr.resourceName != null) {
133             ResourceData rd =
134                     endPointAllocator.getResource(rt.resourceTargetType, rt.resourceTargetId, rr.resourceName);
135             setResourceDataInResponse(Collections.singletonList(rd), rsList);
136         }
137
138         return AllocationStatus.Success;
139     }
140
141     private void setResourceDataInContext(SvcLogicContext ctx, String prefix, List<ResourceData> rdlist) {
142         prefix = prefix == null ? "" : prefix + '.';
143
144         setAttr(ctx, prefix + "resource-list_length", String.valueOf(rdlist.size()));
145
146         for (int i = 0; i < rdlist.size(); i++) {
147             ResourceData rd = rdlist.get(i);
148
149             String pp = prefix + "resource-list[" + i + "].";
150
151             setAttr(ctx, pp + "resource-name", rd.resourceName);
152             setAttr(ctx, pp + "endpoint-position", rd.endPointPosition);
153             setAttr(ctx, pp + "resource-target-type", rd.resourceTargetType);
154             setAttr(ctx, pp + "resource-target-id", rd.resourceTargetId);
155             // SDNGC-7687
156             setAttr(ctx, pp + "resource-target-value", rd.resourceTargetValue);
157             setAttr(ctx, pp + "status", rd.status);
158
159             if (rd.data != null && !rd.data.isEmpty()) {
160                 for (String kk : rd.data.keySet()) {
161                     String value = String.valueOf(rd.data.get(kk));
162                     setAttr(ctx, pp + kk, value);
163                 }
164             }
165         }
166     }
167
168     @Override
169     public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx)
170             throws SvcLogicException {
171         return allocateResources(ctx, false, prefix);
172     }
173
174     public AllocationStatus reserve(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
175             List<ResourceResponse> rsList) throws Exception {
176         return allocateResources(sd, rt, rr, rsList);
177     }
178
179     @Override
180     public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
181         String resourceEntityId = getParam(ctx,
182                 new String[] {"service-instance-id", "reservation-entity-id", "resource-entity-id"}, true, null);
183         String resourceEntityType =
184                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
185         String resourceEntityVersion =
186                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, null);
187
188         ResourceEntity sd = new ResourceEntity();
189         sd.resourceEntityId = resourceEntityId;
190         sd.resourceEntityType = resourceEntityType;
191         sd.resourceEntityVersion = resourceEntityVersion;
192
193         try {
194             this.release(sd);
195         } catch (Exception e) {
196             throw new SvcLogicException(e.getMessage());
197         }
198         return QueryStatus.SUCCESS;
199     }
200
201     public AllocationStatus release(ResourceEntity sd) throws Exception {
202
203         if (sd.resourceEntityVersion != null) {
204             String resourceSet = sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + sd.resourceEntityVersion;
205             log.info("Starting release for: " + resourceSet);
206
207             resourceManager.releaseResourceSet(resourceSet);
208         } else {
209             String resourceUnion = sd.resourceEntityType + "::" + sd.resourceEntityId;
210             log.info("Starting release for: " + resourceUnion);
211
212             resourceManager.releaseResourceUnion(resourceUnion);
213         }
214
215         return AllocationStatus.Success;
216
217     }
218
219     private QueryStatus allocateResources(SvcLogicContext ctx, boolean checkOnly, String prefix)
220             throws SvcLogicException {
221         String serviceModel = getParam(ctx, "service-model", true, null);
222         String requestType = getParam(ctx, "request-type", false, "New");
223
224         ResourceEntity sd = getResourceEntityData(ctx);
225         ResourceTarget rt = getResourceTargetData(ctx);
226         ResourceRequest rr = getResourceRequest(ctx);
227
228         log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
229         StrUtil.info(log, sd);
230         StrUtil.info(log, rt);
231         StrUtil.info(log, rr);
232
233         boolean change = requestType.equalsIgnoreCase("change");
234
235         List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, checkOnly, change);
236
237         if (rlist != null && !rlist.isEmpty()) {
238             setResourceDataInContext(ctx, prefix, rlist);
239
240             for (ResourceData rd : rlist) {
241                 if (!rd.status.equals("Success")) {
242                     log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
243                     return QueryStatus.NOT_FOUND;
244                 }
245             }
246         }
247         return QueryStatus.SUCCESS;
248     }
249
250     private AllocationStatus allocateResources(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
251             List<ResourceResponse> rsList) throws Exception {
252
253         String serviceModel = rr.serviceModel;
254         String requestType = rr.requestType == null ? "New" : rr.requestType;
255
256         log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
257         StrUtil.info(log, sd);
258         StrUtil.info(log, rt);
259         StrUtil.info(log, rr);
260
261         boolean change = requestType.equalsIgnoreCase("change");
262
263         List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, rr.checkOnly, change);
264
265         if (rlist != null && !rlist.isEmpty()) {
266             setResourceDataInResponse(rlist, rsList);
267
268             for (ResourceData rd : rlist) {
269                 if (!rd.status.equals("Success")) {
270                     log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
271                     return AllocationStatus.ResourceNotFound;
272                 }
273             }
274         }
275
276         return AllocationStatus.Success;
277     }
278
279     private void setResourceDataInResponse(List<ResourceData> rlist, List<ResourceResponse> rsList) {
280         for (ResourceData rd : emptyIfNull(rlist)) {
281             ResourceResponse res = new ResourceResponse();
282             res.resourceName = rd.resourceName;
283             res.endPointPosition = rd.endPointPosition;
284             res.resourceTargetId = rd.resourceTargetId;
285             res.resourceTargetType = rd.resourceTargetType;
286             res.status = rd.status;
287             if (rd.data != null && !rd.data.isEmpty()) {
288                 for (String kk : rd.data.keySet()) {
289                     if (kk.equalsIgnoreCase("allocated")) {
290                         res.resourceAllocated = String.valueOf(rd.data.get(kk));
291                     }
292
293                     if (kk.equalsIgnoreCase("used")) {
294                         res.resourceUsed = String.valueOf(rd.data.get(kk));
295                     }
296
297                     if (kk.equalsIgnoreCase("available")) {
298                         res.resourceAvailable = String.valueOf(rd.data.get(kk));
299                     }
300
301                     if (kk.equalsIgnoreCase("limit")) {
302                         res.resourceLimit = String.valueOf(rd.data.get(kk));
303                     }
304
305                 }
306             }
307             rsList.add(res);
308         }
309
310     }
311
312     public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
313         return iterable == null ? Collections.<T>emptyList() : iterable;
314     }
315
316     private void setAttr(SvcLogicContext ctx, String name, String value) {
317         ctx.setAttribute(name, value);
318         log.info("Added context attr: " + name + ": " + value);
319     }
320
321     private ResourceEntity getResourceEntityData(SvcLogicContext ctx) throws SvcLogicException {
322         ResourceEntity sd = new ResourceEntity();
323         sd.resourceEntityId = getParam(ctx,
324                 new String[] {"service-instance-id", "reservation-entity-id", "resource-entity-id"}, true, null);
325         sd.resourceEntityType =
326                 getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
327         sd.resourceEntityVersion =
328                 getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
329         sd.data = getDataParam(ctx, "reservation-entity-data", "resource-entity-data", "service-data");
330         return sd;
331     }
332
333     private ResourceTarget getResourceTargetData(SvcLogicContext ctx) throws SvcLogicException {
334         ResourceTarget sd = new ResourceTarget();
335         sd.resourceTargetId = getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, true, null);
336         sd.resourceTargetType =
337                 getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, true, null);
338         sd.data = getDataParam(ctx, "reservation-target-data", "resource-target-data", "equipment-data");
339         return sd;
340     }
341
342     private ResourceRequest getResourceRequest(SvcLogicContext ctx) throws SvcLogicException {
343         ResourceRequest rr = new ResourceRequest();
344         rr.resourceName = getParam(ctx, "resource-name", false, null);
345         rr.resourceShareGroup = getParam(ctx, "resource-share-group", false, null);
346         rr.rangeRequestedNumbers = getParam(ctx, "range-requested-numbers", false, null);
347         rr.rangeExcludeNumbers = getParam(ctx, "range-exclude-numbers", false, null);
348         String rangeReverseOrderStr = getParam(ctx, "range-reverse-order", false, "false");
349         rr.rangeReverseOrder = Boolean.parseBoolean(rangeReverseOrderStr);
350         String rangeMinOverrideStr = getParam(ctx, "range-min-override", false, "-1");
351         rr.rangeMinOverride = Integer.parseInt(rangeMinOverrideStr);
352         String rangeMaxOverrideStr = getParam(ctx, "range-max-override", false, "-1");
353         rr.rangeMaxOverride = Integer.parseInt(rangeMaxOverrideStr);
354         String rangeForceNewNumbersStr = getParam(ctx, "range-force-new-numbers", false, "false");
355         rr.rangeForceNewNumbers = Boolean.parseBoolean(rangeForceNewNumbersStr);
356         String replaceStr = getParam(ctx, "replace", false, "true");
357         rr.replace = Boolean.parseBoolean(replaceStr);
358         rr.applicationId = getParam(ctx, "application-id", false, "SDNC");
359         rr.endPointPosition = getParam(ctx, "endpoint-position", false, null);
360         return rr;
361     }
362
363     private String getParam(SvcLogicContext ctx, String name, boolean required, String def) throws SvcLogicException {
364         String v = null;
365         for (String p : INPUT_PREFIX) {
366             v = ctx.getAttribute(p + name);
367             if (v != null && v.trim().length() > 0) {
368                 log.info("Param: " + name + ": " + v.trim());
369                 return v.trim();
370             }
371         }
372         if (required) {
373             throw new SvcLogicException("The following variable is required in DG context: " + name);
374         }
375
376         log.info("Param: " + name + " not supplied. Using default: " + def);
377         return def;
378     }
379
380     private String getParam(SvcLogicContext ctx, String[] names, boolean required, String def)
381             throws SvcLogicException {
382         String v = null;
383         for (String name : names) {
384             v = getParam(ctx, name, false, def);
385             if (v != null) {
386                 return v;
387             }
388         }
389         if (required) {
390             throw new SvcLogicException(
391                     "One of the following variable is required in DG context: " + Arrays.deepToString(names));
392         }
393
394         log.info("Param: " + names + " not supplied. Using default: " + def);
395         return def;
396     }
397
398     private Map<String, String> getDataParam(SvcLogicContext ctx, String... names) {
399         Map<String, String> data = new HashMap<>();
400         Set<String> ctxNames = ctx.getAttributeKeySet();
401         for (String n : ctxNames) {
402             for (String p : INPUT_PREFIX) {
403                 for (String name : names) {
404                     String pp = p + name + '.';
405                     if (n.startsWith(pp)) {
406                         String nn = n.substring(pp.length());
407                         String vv = ctx.getAttribute(n);
408                         data.put(nn, vv);
409
410                         log.info("Data param: " + nn + ": " + vv);
411
412                         if (ctxNames.contains(n + "-unit")) {
413                             try {
414                                 long v = Long.parseLong(vv);
415                                 String unit = ctx.getAttribute(n + "-unit");
416                                 long kbps = speedUtil.convertToKbps(v, unit);
417                                 long mbps = speedUtil.convertToMbps(v, unit);
418                                 data.put(nn + "-kbps", String.valueOf(kbps));
419                                 data.put(nn + "-mbps", String.valueOf(mbps));
420
421                                 log.info("Data param: " + nn + "-kbps: " + kbps);
422                                 log.info("Data param: " + nn + "-mbps: " + mbps);
423
424                             } catch (Exception e) {
425                                 log.warn("Invalid number for " + n + ": " + vv);
426                             }
427                         }
428                     }
429                 }
430             }
431         }
432         return data;
433     }
434
435     public void setResourceManager(ResourceManager resourceManager) {
436         this.resourceManager = resourceManager;
437     }
438
439     public void setEndPointAllocator(EndPointAllocator endPointAllocator) {
440         this.endPointAllocator = endPointAllocator;
441     }
442
443     public void setSpeedUtil(SpeedUtil speedUtil) {
444         this.speedUtil = speedUtil;
445     }
446 }