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