e6a2c80ccfc7a27beaea242488f52caab669899d
[ccsdk/sli/adaptors.git] / resource-assignment / provider / src / main / java / org / openecomp / sdnc / ra / ResourceAllocator.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 ONAP 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.openecomp.sdnc.ra;
23
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30
31 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
32 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
33 import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
34 import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
35 import org.openecomp.sdnc.ra.comp.EndPointAllocator;
36 import org.openecomp.sdnc.ra.comp.EndPointData;
37 import org.openecomp.sdnc.ra.comp.ServiceData;
38 import org.openecomp.sdnc.ra.equip.dao.ServerDao;
39 import org.openecomp.sdnc.ra.equip.dao.VpePortDao;
40 import org.openecomp.sdnc.ra.equip.dao.VplspePortDao;
41 import org.openecomp.sdnc.ra.equip.data.EquipmentData;
42 import org.openecomp.sdnc.ra.equip.data.EquipmentLevel;
43 import org.openecomp.sdnc.ra.rule.comp.AllocationRequestBuilder;
44 import org.openecomp.sdnc.ra.rule.dao.MaxPortSpeedDao;
45 import org.openecomp.sdnc.ra.rule.dao.MaxServerSpeedDao;
46 import org.openecomp.sdnc.ra.rule.dao.ParameterDao;
47 import org.openecomp.sdnc.ra.rule.data.ThresholdStatus;
48 import org.openecomp.sdnc.ra.service.dao.ServiceResourceDao;
49 import org.openecomp.sdnc.ra.service.data.ServiceResource;
50 import org.openecomp.sdnc.ra.service.data.ServiceStatus;
51 import org.openecomp.sdnc.rm.comp.ResourceManager;
52 import org.openecomp.sdnc.rm.data.AllocationAction;
53 import org.openecomp.sdnc.rm.data.AllocationItem;
54 import org.openecomp.sdnc.rm.data.AllocationOutcome;
55 import org.openecomp.sdnc.rm.data.AllocationRequest;
56 import org.openecomp.sdnc.rm.data.AllocationStatus;
57 import org.openecomp.sdnc.rm.data.LimitAllocationOutcome;
58 import org.openecomp.sdnc.rm.data.LimitAllocationRequest;
59 import org.openecomp.sdnc.rm.data.LimitResource;
60 import org.openecomp.sdnc.rm.data.MultiResourceAllocationOutcome;
61 import org.openecomp.sdnc.rm.data.RangeAllocationItem;
62 import org.openecomp.sdnc.rm.data.RangeResource;
63 import org.openecomp.sdnc.rm.data.Resource;
64 import org.openecomp.sdnc.util.speed.SpeedUtil;
65 import org.openecomp.sdnc.util.str.StrUtil;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68
69 public class ResourceAllocator implements SvcLogicResource {
70
71     private static final Logger log = LoggerFactory.getLogger(ResourceAllocator.class);
72
73     public ResourceAllocator() {
74         log.info("ResourceAllocator created.");
75     }
76
77     private ServerDao serverDao;
78     private VpePortDao vpePortDao;
79     private VplspePortDao vplspePortDao;
80     private MaxPortSpeedDao maxPortSpeedDao;
81     private MaxServerSpeedDao maxServerSpeedDao;
82     private ServiceResourceDao serviceResourceDao;
83     private ParameterDao parameterDao;
84
85     private AllocationRequestBuilder allocationRequestBuilder;
86     private ResourceManager resourceManager;
87     private SpeedUtil speedUtil;
88
89     private EndPointAllocator endPointAllocator;
90
91     @Override
92     public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx)
93             throws SvcLogicException {
94         return (QueryStatus.SUCCESS);
95     }
96
97     @Override
98     public QueryStatus update(
99             String resource,
100             String key,
101             Map<String, String> parms,
102             String prefix,
103             SvcLogicContext ctx) throws SvcLogicException {
104
105         return QueryStatus.SUCCESS;
106     }
107
108     @Override
109     public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx)
110             throws SvcLogicException {
111         return QueryStatus.SUCCESS;
112     }
113
114     @Override
115     public QueryStatus delete(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
116         return QueryStatus.SUCCESS;
117     }
118
119     @Override
120     public QueryStatus save(
121             String arg0,
122             boolean arg1,
123             boolean arg2,
124             String arg3,
125             Map<String, String> arg4,
126             String arg5,
127             SvcLogicContext arg6) throws SvcLogicException {
128         return QueryStatus.SUCCESS;
129     }
130
131     @Override
132     public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx)
133             throws SvcLogicException {
134         String serviceModel = ctx.getAttribute("tmp.resource-allocator.service-model");
135         if (serviceModel != null && serviceModel.trim().length() > 0)
136             return allocateResources(serviceModel, ctx, true, prefix);
137         return allocateResourcesL3SDN(ctx, true, prefix);
138     }
139
140     @Override
141     public QueryStatus query(
142             String resource,
143             boolean localOnly,
144             String select,
145             String key,
146             String prefix,
147             String orderBy,
148             SvcLogicContext ctx) throws SvcLogicException {
149
150         prefix = prefix == null ? "" : prefix + '.';
151
152         if (!resource.equals("NetworkCapacity")) {
153             log.info("resource: " + resource);
154             log.info("key: " + key);
155
156             Resource r = resourceManager.getResource(resource, key);
157             if (r == null)
158                 return QueryStatus.NOT_FOUND;
159
160             if (r instanceof LimitResource) {
161                 ctx.setAttribute(prefix + "used", String.valueOf(((LimitResource) r).used));
162
163                 log.info("Added context attr: " + prefix + "used: " + String.valueOf(((LimitResource) r).used));
164             }
165
166             return QueryStatus.SUCCESS;
167         }
168
169         log.info("key: " + key);
170         log.info("prefix: " + prefix);
171
172         if (key == null)
173             return QueryStatus.SUCCESS;
174
175         if (key.startsWith("'") && key.endsWith("'"))
176             key = key.substring(1, key.length() - 1);
177
178         String endPointPosition = "VPE-Cust";
179
180         String resourceUnionId = key + '/' + endPointPosition;
181         List<Resource> rlist = resourceManager.getResourceUnion(resourceUnionId);
182
183         log.info("Resources found for " + resourceUnionId + ": " + rlist.size());
184
185         String assetId = null;
186         for (Resource r : rlist) {
187             log.info("Resource: " + r.resourceKey.resourceName);
188
189             if (r instanceof RangeResource) {
190                 RangeResource rr = (RangeResource) r;
191                 for (AllocationItem ai : r.allocationItems)
192                     if (ai.resourceUnionId.equals(resourceUnionId)) {
193                         RangeAllocationItem rai = (RangeAllocationItem) ai;
194                         ctx.setAttribute(prefix + r.resourceKey.resourceName, String.valueOf(rai.used.first()));
195
196                         log.info("Added context attr: " + prefix + r.resourceKey.resourceName + ": " +
197                                 String.valueOf(rr.used.first()));
198
199                         assetId = r.resourceKey.assetId;
200                         String vpeName = assetId;
201                         int i1 = assetId.indexOf('/');
202                         if (i1 > 0)
203                             vpeName = assetId.substring(0, i1);
204                         ctx.setAttribute(prefix + "vpe-name", vpeName);
205
206                         log.info("Added context attr: " + prefix + "vpe-name: " + vpeName);
207                     }
208             }
209         }
210
211         String affinityLink = "1";
212         if (assetId != null) {
213             for (Resource r : rlist) {
214                 if (r instanceof LimitResource) {
215                     LimitResource ll = (LimitResource) r;
216                     if (ll.resourceKey.assetId.startsWith(assetId + '-')) {
217                         int i1 = ll.resourceKey.assetId.lastIndexOf('-');
218                         affinityLink = ll.resourceKey.assetId.substring(i1 + 1);
219                         break;
220                     }
221                 }
222             }
223         }
224
225         ctx.setAttribute(prefix + "affinity-link", affinityLink);
226
227         log.info("Added context attr: " + prefix + "affinity-link: " + affinityLink);
228
229         return QueryStatus.SUCCESS;
230     }
231
232     @Override
233     public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx)
234             throws SvcLogicException {
235         String serviceModel = ctx.getAttribute("tmp.resource-allocator.service-model");
236         if (serviceModel != null && serviceModel.trim().length() > 0)
237             return allocateResources(serviceModel, ctx, false, prefix);
238         return allocateResourcesL3SDN(ctx, false, prefix);
239     }
240
241     @Override
242     public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
243         String serviceInstanceId = ctx.getAttribute("tmp.resource-allocator.service-instance-id");
244         if (serviceInstanceId == null)
245             throw new SvcLogicException("tmp.resource-allocator.service-instance-id is required in ResourceAllocator");
246
247         String requestTypeStr = ctx.getAttribute("tmp.resource-allocator.request-type");
248         if (requestTypeStr == null)
249             throw new SvcLogicException("tmp.resource-allocator.request-type is required in ResourceAllocator");
250
251         ReleaseRequestType requestType = null;
252         try {
253             requestType = ReleaseRequestType.convert(requestTypeStr);
254         } catch (IllegalArgumentException e) {
255             throw new SvcLogicException("Invalid tmp.resource-allocator.request-type: " + requestTypeStr +
256                     ". Supported values are Cancel, Activate, Disconnect.");
257         }
258
259         log.info("Starting release: " + requestType + " for: " + serviceInstanceId);
260
261         ServiceResource activeServiceResource =
262                 serviceResourceDao.getServiceResource(serviceInstanceId, ServiceStatus.Active);
263         ServiceResource pendingServiceResource =
264                 serviceResourceDao.getServiceResource(serviceInstanceId, ServiceStatus.Pending);
265
266         log.info("Active ServiceResource: ");
267         StrUtil.info(log, activeServiceResource);
268         log.info("Pending ServiceResource: ");
269         StrUtil.info(log, pendingServiceResource);
270
271         if (requestType == ReleaseRequestType.Cancel) {
272             if (pendingServiceResource != null) {
273                 log.info("Releasing pending resources: " + pendingServiceResource.resourceSetId);
274
275                 resourceManager.releaseResourceSet(pendingServiceResource.resourceSetId);
276                 serviceResourceDao.deleteServiceResource(serviceInstanceId, ServiceStatus.Pending);
277             } else {
278                 log.info("Pending record not found for service instance: " + serviceInstanceId + ". Nothing to do.");
279             }
280
281         } else if (requestType == ReleaseRequestType.Activate) {
282             if (pendingServiceResource != null) {
283                 if (activeServiceResource != null) {
284                     log.info("Releasing active resources: " + activeServiceResource.resourceSetId);
285
286                     resourceManager.releaseResourceSet(activeServiceResource.resourceSetId);
287                     serviceResourceDao.deleteServiceResource(serviceInstanceId, ServiceStatus.Active);
288                 }
289
290                 log.info("Updating the status of the pending record to active.");
291
292                 serviceResourceDao.updateServiceStatus(serviceInstanceId, ServiceStatus.Pending, ServiceStatus.Active);
293             } else {
294                 log.info("Pending record not found for service instance: " + serviceInstanceId + ". Nothing to do.");
295             }
296
297         } else if (requestType == ReleaseRequestType.Disconnect) {
298             if (pendingServiceResource != null) {
299                 log.info("Releasing pending resources: " + pendingServiceResource.resourceSetId);
300
301                 resourceManager.releaseResourceSet(pendingServiceResource.resourceSetId);
302                 serviceResourceDao.deleteServiceResource(serviceInstanceId, ServiceStatus.Pending);
303             }
304             if (activeServiceResource != null) {
305                 log.info("Releasing active resources: " + activeServiceResource.resourceSetId);
306
307                 resourceManager.releaseResourceSet(activeServiceResource.resourceSetId);
308                 serviceResourceDao.deleteServiceResource(serviceInstanceId, ServiceStatus.Active);
309             }
310         }
311
312         return QueryStatus.SUCCESS;
313     }
314
315     private QueryStatus allocateResourcesL3SDN(SvcLogicContext ctx, boolean checkOnly, String prefix)
316             throws SvcLogicException {
317         prefix = prefix == null ? "" : prefix + '.';
318
319         String aicSiteId = getAicSiteId(ctx);
320         Map<String, Object> service = getServiceData(ctx);
321
322         String requestTypeStr = ctx.getAttribute("tmp.resource-allocator.request-type");
323         if (requestTypeStr == null)
324             requestTypeStr = "New";
325
326         ReserveRequestType requestType = null;
327         try {
328             requestType = ReserveRequestType.convert(requestTypeStr);
329         } catch (IllegalArgumentException e) {
330             throw new SvcLogicException("Invalid tmp.resource-allocator.request-type: " + requestTypeStr +
331                     ". Supported values are New, Change.");
332         }
333
334         String serviceInstanceId = String.valueOf(service.get("service-instance-id"));
335
336         ServiceResource activeServiceResource =
337                 serviceResourceDao.getServiceResource(serviceInstanceId, ServiceStatus.Active);
338         ServiceResource pendingServiceResource =
339                 serviceResourceDao.getServiceResource(serviceInstanceId, ServiceStatus.Pending);
340
341         log.info("Active ServiceResource: ");
342         StrUtil.info(log, activeServiceResource);
343         log.info("Pending ServiceResource: ");
344         StrUtil.info(log, pendingServiceResource);
345
346         ServiceResource sr = new ServiceResource();
347         sr.serviceInstanceId = serviceInstanceId;
348         sr.serviceStatus = ServiceStatus.Pending;
349         sr.serviceChangeNumber = 1;
350         if (pendingServiceResource != null)
351             sr.serviceChangeNumber = pendingServiceResource.serviceChangeNumber + 1;
352         else if (activeServiceResource != null)
353             sr.serviceChangeNumber = activeServiceResource.serviceChangeNumber + 1;
354         sr.resourceSetId = serviceInstanceId + "/" + sr.serviceChangeNumber;
355         sr.resourceUnionId = serviceInstanceId;
356
357         log.info("New ServiceResource: ");
358         StrUtil.info(log, sr);
359
360         List<Map<String, Object>> vpePortData = vpePortDao.getVpePortData(aicSiteId);
361         List<Map<String, Object>> vplspePortData = vplspePortDao.getVplspePortData(aicSiteId);
362         List<Map<String, Object>> serverData = serverDao.getServerData(aicSiteId);
363
364         vpePortData = orderVpe(vpePortData);
365
366         long maxAvailableSpeedVpePort = 0;
367         boolean vpePortFound = false;
368
369         for (Map<String, Object> vpe : vpePortData) {
370             String vpeId = String.valueOf(vpe.get("vpe-id"));
371             String interfaceName = String.valueOf(vpe.get("physical-interface-name"));
372             String portId = vpeId + "/" + interfaceName;
373
374             log.info("Checking VPE port: " + portId);
375
376             String provStatus = String.valueOf(vpe.get("provisioning-status"));
377             if (!provStatus.equals("PROV")) {
378                 log.info("Skipping port " + portId + ": Provisioning status is not PROV.");
379                 continue;
380             }
381
382             String imageFile = String.valueOf(vpe.get("image-file-name"));
383             String endPointPosition = "VPE-Cust";
384             long maxPortSpeed = maxPortSpeedDao.getMaxPortSpeed(imageFile, endPointPosition, interfaceName);
385             vpe.put("max-port-speed", maxPortSpeed);
386
387             EquipmentData ed = new EquipmentData();
388             ed.data = vpe;
389             ed.equipmentId = portId;
390             ed.equipmentLevel = EquipmentLevel.Port;
391
392             ServiceData sd = new ServiceData();
393             sd.data = service;
394             sd.serviceModel = "L3SDN";
395             sd.endPointPosition = endPointPosition;
396             sd.resourceUnionId = sr.resourceUnionId;
397             sd.resourceSetId = sr.resourceSetId;
398
399             StrUtil.info(log, ed);
400             StrUtil.info(log, sd);
401
402             AllocationRequest ar = allocationRequestBuilder.buildAllocationRequest(sd, ed, checkOnly,
403                     requestType == ReserveRequestType.Change);
404             AllocationOutcome ao = resourceManager.allocateResources(ar);
405
406             if (ao.status == AllocationStatus.Success) {
407
408                 // Assign affinity link
409                 if (!checkOnly) {
410                     List<String> affinityLinkIdList = new ArrayList<>();
411                     affinityLinkIdList.add("0");
412                     affinityLinkIdList.add("1");
413                     affinityLinkIdList.add("2");
414                     affinityLinkIdList.add("3");
415
416                     String preferedAffinityLinkId = "0";
417                     long lowestAssignedBw = Long.MAX_VALUE;
418                     for (String affinityLinkId : affinityLinkIdList) {
419                         long used = 0;
420                         String assetId = ed.equipmentId + "-" + affinityLinkId;
421                         Resource r = resourceManager.getResource("Bandwidth", assetId);
422                         if (r != null) {
423                             LimitResource ll = (LimitResource) r;
424                             used = ll.used;
425                         }
426                         if (used < lowestAssignedBw) {
427                             lowestAssignedBw = used;
428                             preferedAffinityLinkId = affinityLinkId;
429                         }
430                         log.info("Assigned bandwidth on affinity link: " + assetId + ": " + used);
431                     }
432
433                     log.info("Prefered affinity link for " + ed.equipmentId + ": " + preferedAffinityLinkId);
434
435                     ctx.setAttribute(prefix + "affinity-link", preferedAffinityLinkId);
436
437                     LimitAllocationRequest ar1 = new LimitAllocationRequest();
438                     ar1.resourceSetId = sd.resourceSetId;
439                     ar1.resourceUnionId = sd.resourceUnionId;
440                     ar1.resourceShareGroupList = null;
441                     ar1.resourceName = "Bandwidth";
442                     ar1.assetId = ed.equipmentId + "-" + preferedAffinityLinkId;
443                     ar1.missingResourceAction = AllocationAction.Succeed_Allocate;
444                     ar1.expiredResourceAction = AllocationAction.Succeed_Allocate;
445                     ar1.replace = true;
446                     ar1.strict = false;
447                     ar1.checkLimit = Long.MAX_VALUE;
448                     ar1.checkCount = 0;
449                     ar1.allocateCount = (Long) sd.data.get("service-speed-kbps");
450
451                     resourceManager.allocateResources(ar1);
452                 }
453
454                 ctx.setAttribute(prefix + "vpe-name", vpeId);
455
456                 vpePortFound = true;
457                 break;
458             }
459
460             if (ao instanceof LimitAllocationOutcome) {
461                 LimitAllocationOutcome lao = (LimitAllocationOutcome) ao;
462                 long available = lao.limit - lao.used;
463                 if (available > maxAvailableSpeedVpePort)
464                     maxAvailableSpeedVpePort = available;
465             }
466         }
467
468         long maxAvailableSpeedVplspePort = 0;
469         boolean vplspePortFound = false;
470
471         for (Map<String, Object> vplspe : vplspePortData) {
472             String vplspeId = String.valueOf(vplspe.get("vplspe-id"));
473             String interfaceName = String.valueOf(vplspe.get("physical-interface-name"));
474             String portId = vplspeId + "/" + interfaceName;
475
476             log.info("Checking VPLSPE port: " + portId);
477
478             String provStatus = String.valueOf(vplspe.get("provisioning-status"));
479             if (!provStatus.equals("PROV")) {
480                 log.info("Skipping port " + portId + ": Provisioning status is not PROV.");
481                 continue;
482             }
483
484             long physicalSpeed = (Long) vplspe.get("physical-interface-speed");
485             String physicalSpeedUnit = String.valueOf(vplspe.get("physical-interface-speed-unit"));
486             long maxPortSpeed = speedUtil.convertToKbps(physicalSpeed, physicalSpeedUnit);
487             vplspe.put("max-port-speed", maxPortSpeed);
488
489             EquipmentData ed = new EquipmentData();
490             ed.data = vplspe;
491             ed.equipmentId = portId;
492             ed.equipmentLevel = EquipmentLevel.Port;
493
494             ServiceData sd = new ServiceData();
495             sd.data = service;
496             sd.serviceModel = "L3SDN";
497             sd.endPointPosition = "IPAG-TOA";
498             sd.resourceUnionId = sr.resourceUnionId;
499             sd.resourceSetId = sr.resourceSetId;
500
501             StrUtil.info(log, ed);
502             StrUtil.info(log, sd);
503
504             AllocationRequest ar = allocationRequestBuilder.buildAllocationRequest(sd, ed, checkOnly,
505                     requestType == ReserveRequestType.Change);
506             AllocationOutcome ao = resourceManager.allocateResources(ar);
507
508             if (ao.status == AllocationStatus.Success) {
509                 vplspePortFound = true;
510                 break;
511             }
512
513             if (ao instanceof LimitAllocationOutcome) {
514                 LimitAllocationOutcome lao = (LimitAllocationOutcome) ao;
515                 long available = lao.limit - lao.used;
516                 if (available > maxAvailableSpeedVplspePort)
517                     maxAvailableSpeedVplspePort = available;
518             }
519         }
520
521         long maxAvailableSpeedServer = 0;
522         boolean serverFound = false;
523
524         for (Map<String, Object> server : serverData) {
525             String serverId = String.valueOf(server.get("server-id"));
526             String serverModel = String.valueOf(server.get("server-model"));
527
528             log.info("Checking Server: " + serverId);
529
530             String endPointPosition = "VCE-Cust";
531
532             int serverCount = (Integer) server.get("server-count");
533             if (serverCount == 0)
534                 serverCount = 1;
535             String ratioString = parameterDao.getParameter("homing.pserver.sparing.ratio");
536             if (ratioString == null || ratioString.length() == 0)
537                 ratioString = "1:1";
538             int primaryServerCount = calculatePrimaryServerCount(serverCount, ratioString);
539             server.put("number-primary-servers", primaryServerCount);
540
541             int evcCount = getEvcCountOnServer(serverId);
542             int evcCountPerServer = (evcCount + primaryServerCount - 1) / primaryServerCount;
543             long maxServerSpeed = maxServerSpeedDao.getMaxServerSpeed(serverModel, evcCountPerServer);
544             server.put("max-server-speed", maxServerSpeed);
545             server.put("evc-count", evcCount);
546             server.put("evc-count-per-server", evcCountPerServer);
547
548             EquipmentData ed = new EquipmentData();
549             ed.data = server;
550             ed.equipmentId = serverId;
551             ed.equipmentLevel = EquipmentLevel.Server;
552
553             ServiceData sd = new ServiceData();
554             sd.data = service;
555             sd.serviceModel = "L3SDN";
556             sd.endPointPosition = endPointPosition;
557             sd.resourceUnionId = sr.resourceUnionId;
558             sd.resourceSetId = sr.resourceSetId;
559
560             StrUtil.info(log, ed);
561             StrUtil.info(log, sd);
562
563             AllocationRequest ar = allocationRequestBuilder.buildAllocationRequest(sd, ed, checkOnly,
564                     requestType == ReserveRequestType.Change);
565             AllocationOutcome ao = resourceManager.allocateResources(ar);
566
567             if (ao.status == AllocationStatus.Success) {
568                 serverFound = true;
569
570                 if (ao instanceof MultiResourceAllocationOutcome) {
571                     MultiResourceAllocationOutcome mrao = (MultiResourceAllocationOutcome) ao;
572                     for (AllocationOutcome ao1 : mrao.allocationOutcomeList) {
573                         if (ao1 instanceof LimitAllocationOutcome) {
574                             LimitAllocationOutcome lao = (LimitAllocationOutcome) ao1;
575                             if (lao.request.resourceName.equals("Bandwidth")) {
576                                 ThresholdStatus th = allocationRequestBuilder.getThresholdStatus(sd, ed, lao);
577                                 setThresholdData(ctx, th, sd, ed);
578                             }
579                         }
580                     }
581                 }
582
583                 break;
584             }
585
586             if (ao instanceof MultiResourceAllocationOutcome) {
587                 MultiResourceAllocationOutcome mrao = (MultiResourceAllocationOutcome) ao;
588                 for (AllocationOutcome ao1 : mrao.allocationOutcomeList) {
589                     if (ao1 instanceof LimitAllocationOutcome) {
590                         LimitAllocationOutcome lao = (LimitAllocationOutcome) ao1;
591                         if (lao.status == AllocationStatus.Failure && lao.request.resourceName.equals("Bandwidth")) {
592                             long available = lao.limit - lao.used;
593                             if (available > maxAvailableSpeedServer)
594                                 maxAvailableSpeedServer = available;
595                         }
596                         if (lao.status == AllocationStatus.Failure && lao.request.resourceName.equals("Connection")) {
597                             maxAvailableSpeedServer = 0;
598                             break;
599                         }
600
601                         ThresholdStatus th = allocationRequestBuilder.getThresholdStatus(sd, ed, lao);
602                         setThresholdData(ctx, th, sd, ed);
603                     }
604                 }
605             }
606         }
607
608         if (vpePortFound && vplspePortFound && serverFound) {
609             if (!checkOnly) {
610                 if (pendingServiceResource == null) {
611                     log.info("Adding the pending service resource record to DB.");
612                     serviceResourceDao.addServiceResource(sr);
613                 } else {
614                     log.info("Releasing previously allocated resources for resource set id: " +
615                             pendingServiceResource.resourceSetId);
616                     resourceManager.releaseResourceSet(pendingServiceResource.resourceSetId);
617
618                     log.info("Updating the pending service resource record in DB with service change number: " +
619                             sr.serviceChangeNumber);
620                     serviceResourceDao.updateServiceResource(sr);
621                 }
622             }
623
624             return QueryStatus.SUCCESS;
625         }
626
627         log.info("Releasing allocated resources (if any) for resource set id: " + sr.resourceSetId);
628         resourceManager.releaseResourceSet(sr.resourceSetId);
629
630         long maxAvailableSpeed = Long.MAX_VALUE;
631         if (!vpePortFound && maxAvailableSpeedVpePort < maxAvailableSpeed)
632             maxAvailableSpeed = maxAvailableSpeedVpePort;
633         if (!vplspePortFound && maxAvailableSpeedVplspePort < maxAvailableSpeed)
634             maxAvailableSpeed = maxAvailableSpeedVplspePort;
635         if (!serverFound && maxAvailableSpeedServer < maxAvailableSpeed)
636             maxAvailableSpeed = maxAvailableSpeedServer;
637
638         setOutputContext(ctx, maxAvailableSpeed, "kbps");
639         return QueryStatus.NOT_FOUND;
640     }
641
642     private List<Map<String, Object>> orderVpe(List<Map<String, Object>> vpePortData) {
643         for (Map<String, Object> vpe : vpePortData) {
644             String vpeId = String.valueOf(vpe.get("vpe-id"));
645             String interfaceName = String.valueOf(vpe.get("physical-interface-name"));
646             String portId = vpeId + "/" + interfaceName;
647             Resource r = resourceManager.getResource("Bandwidth", portId);
648             long used = 0;
649             if (r != null) {
650                 LimitResource ll = (LimitResource) r;
651                 used = ll.used;
652             }
653             vpe.put("used-bandwidth", used);
654
655             log.info("Used bandwidth on VPE: " + vpeId + ": " + used);
656         }
657
658         Collections.sort(vpePortData, new Comparator<Map<String, Object>>() {
659
660             @Override
661             public int compare(Map<String, Object> o1, Map<String, Object> o2) {
662                 long used1 = (Long) o1.get("used-bandwidth");
663                 long used2 = (Long) o2.get("used-bandwidth");
664                 if (used1 < used2)
665                     return -1;
666                 if (used1 > used2)
667                     return 1;
668                 return 0;
669             }
670         });
671
672         return vpePortData;
673     }
674
675     private void setThresholdData(SvcLogicContext ctx, ThresholdStatus th, ServiceData sd, EquipmentData ed) {
676         if (th == null)
677             return;
678
679         String pp = "tmp.resource-allocator-output.threshold-notification-list.threshold-hotification[0].";
680         ctx.setAttribute("tmp.resource-allocator-output.threshold-notification-list.threshold-hotification_length",
681                 "1");
682         ctx.setAttribute(pp + "message", th.resourceThreshold.message);
683         ctx.setAttribute(pp + "resource-rule.service-model", th.resourceRule.serviceModel);
684         ctx.setAttribute(pp + "resource-rule.endpoint-position", th.resourceRule.endPointPosition);
685         ctx.setAttribute(pp + "resource-rule.resource-name", th.resourceRule.resourceName);
686         ctx.setAttribute(pp + "resource-rule.equipment-level", th.resourceRule.equipmentLevel);
687         ctx.setAttribute(pp + "resource-rule.soft-limit-expression", th.resourceRule.softLimitExpression);
688         ctx.setAttribute(pp + "resource-rule.hard-limit-expression", th.resourceRule.hardLimitExpression);
689         ctx.setAttribute(pp + "resource-state.used", String.valueOf(th.used));
690         ctx.setAttribute(pp + "resource-state.limit-value", String.valueOf(th.limitValue));
691         ctx.setAttribute(pp + "resource-state.threshold-value", String.valueOf(th.thresholdValue));
692         ctx.setAttribute(pp + "resource-state.last-added", String.valueOf(th.lastAdded));
693         ctx.setAttribute(pp + "equipment-data.equipment-id", ed.equipmentId);
694         for (String edKey : ed.data.keySet())
695             ctx.setAttribute(pp + "equipment-data." + edKey, String.valueOf(ed.data.get(edKey)));
696     }
697
698     private QueryStatus allocateResources(String serviceModel, SvcLogicContext ctx, boolean checkOnly, String prefix)
699             throws SvcLogicException {
700         prefix = prefix == null ? "" : prefix + '.';
701
702         Map<String, Object> service = getServiceData(ctx);
703         Map<String, Object> ec = getEquipConstraints(ctx);
704
705         String requestTypeStr = ctx.getAttribute("tmp.resource-allocator.request-type");
706         if (requestTypeStr == null)
707             requestTypeStr = "New";
708
709         ReserveRequestType requestType = null;
710         try {
711             requestType = ReserveRequestType.convert(requestTypeStr);
712         } catch (IllegalArgumentException e) {
713             throw new SvcLogicException("Invalid tmp.resource-allocator.request-type: " + requestTypeStr +
714                     ". Supported values are New, Change.");
715         }
716
717         String serviceInstanceId = String.valueOf(service.get("service-instance-id"));
718
719         log.info("Starting reserve: " + requestType + ", service-instance-id: " + serviceInstanceId);
720
721         ServiceResource activeServiceResource =
722                 serviceResourceDao.getServiceResource(serviceInstanceId, ServiceStatus.Active);
723         ServiceResource pendingServiceResource =
724                 serviceResourceDao.getServiceResource(serviceInstanceId, ServiceStatus.Pending);
725
726         log.info("Active ServiceResource: ");
727         StrUtil.info(log, activeServiceResource);
728         log.info("Pending ServiceResource: ");
729         StrUtil.info(log, pendingServiceResource);
730
731         int changeNumber = 1;
732         if (pendingServiceResource != null)
733             changeNumber = pendingServiceResource.serviceChangeNumber + 1;
734         else if (activeServiceResource != null)
735             changeNumber = activeServiceResource.serviceChangeNumber + 1;
736
737         ServiceData sd = new ServiceData();
738         sd.data = service;
739         sd.serviceModel = serviceModel;
740         sd.endPointPosition = (String) service.get("end-point-position");
741         sd.resourceShareGroup = (String) service.get("resource-share-group");
742         sd.resourceName = (String) service.get("resource-name");
743         sd.serviceInstanceId = serviceInstanceId;
744
745         StrUtil.info(log, sd);
746
747         List<EndPointData> epList = endPointAllocator.allocateEndPoints(sd, ec, checkOnly,
748                 requestType == ReserveRequestType.Change, changeNumber);
749
750         if (epList != null && !epList.isEmpty()) {
751             if (!checkOnly) {
752                 EndPointData ep = epList.get(0);
753
754                 if (sd.resourceName == null) {
755                 ServiceResource sr = new ServiceResource();
756                 sr.serviceInstanceId = serviceInstanceId;
757                 sr.serviceStatus = ServiceStatus.Pending;
758                 sr.serviceChangeNumber = changeNumber;
759                 sr.resourceSetId = ep.resourceSetId;
760                 sr.resourceUnionId = ep.resourceUnionId;
761
762                 log.info("New ServiceResource: ");
763                 StrUtil.info(log, sr);
764
765                 if (pendingServiceResource == null) {
766                     log.info("Adding the pending service resource record to DB.");
767                     serviceResourceDao.addServiceResource(sr);
768                 } else {
769                     log.info("Releasing previously allocated resources for resource set id: " +
770                             pendingServiceResource.resourceSetId);
771                     resourceManager.releaseResourceSet(pendingServiceResource.resourceSetId);
772
773                     log.info("Updating the pending service resource record in DB with service change number: " +
774                             sr.serviceChangeNumber);
775                     serviceResourceDao.updateServiceResource(sr);
776                 }
777             }
778
779                 for (EndPointData ep1 : epList)
780                     if (ep1.data != null && !ep1.data.isEmpty())
781                         for (String key : ep1.data.keySet()) {
782                             String value = String.valueOf(ep1.data.get(key));
783                             ctx.setAttribute(prefix + key, value);
784
785                             log.info("Added context attr: " + prefix + key + ": " + value);
786                         }
787             }
788
789             return QueryStatus.SUCCESS;
790         }
791
792         log.info("Capacity not found for EVC: " + serviceInstanceId);
793
794         return QueryStatus.NOT_FOUND;
795     }
796
797     private int getEvcCountOnServer(String serverId) {
798         LimitResource l = (LimitResource) resourceManager.getResource("Connection", serverId);
799         if (l != null)
800             return (int) l.used;
801         return 0;
802     }
803
804     private String getAicSiteId(SvcLogicContext ctx) throws SvcLogicException {
805         String aicSiteId = ctx.getAttribute("tmp.resource-allocator.aic-site-id");
806         if (aicSiteId == null)
807             throw new SvcLogicException("tmp.resource-allocator.aic-site-id is required in ResourceAllocator");
808         return aicSiteId;
809     }
810
811     private Map<String, Object> getServiceData(SvcLogicContext ctx) throws SvcLogicException {
812         Map<String, Object> sd = new HashMap<String, Object>();
813
814         String endPointPosition = ctx.getAttribute("tmp.resource-allocator.end-point-position");
815         if (endPointPosition != null && endPointPosition.trim().length() > 0)
816             sd.put("end-point-position", endPointPosition.trim());
817
818         String resourceName = ctx.getAttribute("tmp.resource-allocator.resource-name");
819         if (resourceName != null && resourceName.trim().length() > 0)
820             sd.put("resource-name", resourceName.trim());
821
822         String resourceShareGroup = ctx.getAttribute("tmp.resource-allocator.resource-share-group");
823         if (resourceShareGroup != null && resourceShareGroup.trim().length() > 0)
824             sd.put("resource-share-group", resourceShareGroup.trim());
825
826         String serviceInstanceId = ctx.getAttribute("tmp.resource-allocator.service-instance-id");
827         if (serviceInstanceId == null)
828             serviceInstanceId = "checkServiceInstance";
829         sd.put("service-instance-id", serviceInstanceId);
830
831         String speedStr = ctx.getAttribute("tmp.resource-allocator.speed");
832         if (speedStr != null && speedStr.trim().length() > 0) {
833         long speed = 0;
834         try {
835             speed = Long.parseLong(speedStr);
836         } catch (NumberFormatException e) {
837             throw new SvcLogicException("Invalid tmp.resource-allocator.speed. Must be a number.");
838         }
839         String unit = ctx.getAttribute("tmp.resource-allocator.speed-unit");
840         if (unit == null || unit.trim().length() == 0)
841             throw new SvcLogicException("tmp.resource-allocator.speed-unit is required in ResourceAllocator");
842         long serviceSpeedKbps = speedUtil.convertToKbps(speed, unit);
843
844         sd.put("service-speed-kbps", serviceSpeedKbps);
845         }
846
847         String vpnId = ctx.getAttribute("tmp.resource-allocator.vpn-id");
848         if (vpnId != null && vpnId.trim().length() > 0)
849             sd.put("vpn-id", vpnId.trim());
850
851         String vpnIdList = ctx.getAttribute("tmp.resource-allocator.vpn-id-list");
852         if (vpnIdList != null && vpnIdList.trim().length() > 0)
853             sd.put("vpn-id-list", vpnIdList.trim());
854
855         String vrfName = ctx.getAttribute("tmp.resource-allocator.vrf-name");
856         if (vrfName != null && vrfName.trim().length() > 0)
857             sd.put("vrf-name", vrfName.trim());
858
859         String vrfNameList = ctx.getAttribute("tmp.resource-allocator.vrf-name-list");
860         if (vrfNameList != null && vrfNameList.trim().length() > 0)
861             sd.put("vrf-name-list", vrfNameList.trim());
862
863         String v4multicast = ctx.getAttribute("tmp.resource-allocator.v4-multicast");
864         if (v4multicast != null && v4multicast.trim().length() > 0)
865             sd.put("v4-multicast", v4multicast.trim());
866
867         String v6multicast = ctx.getAttribute("tmp.resource-allocator.v6-multicast");
868         if (v6multicast != null && v6multicast.trim().length() > 0)
869             sd.put("v6-multicast", v6multicast.trim());
870
871         String v4ServingSite = ctx.getAttribute("tmp.resource-allocator.v4-serving-site");
872         if (v4ServingSite != null && v4ServingSite.trim().length() > 0)
873             sd.put("v4-serving-site", v4ServingSite.trim());
874
875         String v6ServingSite = ctx.getAttribute("tmp.resource-allocator.v6-serving-site");
876         if (v6ServingSite != null && v6ServingSite.trim().length() > 0)
877             sd.put("v6-serving-site", v6ServingSite.trim());
878
879         return sd;
880     }
881
882     private Map<String, Object> getEquipConstraints(SvcLogicContext ctx) throws SvcLogicException {
883         Map<String, Object> mm = new HashMap<String, Object>();
884
885         String vrfRequired = ctx.getAttribute("tmp.resource-allocator.vrf-required");
886         if (vrfRequired != null && vrfRequired.trim().length() > 0)
887             mm.put("vrf-required", vrfRequired.trim());
888
889         String clli = ctx.getAttribute("tmp.resource-allocator.clli");
890         if (clli == null || clli.trim().length() == 0)
891             clli = ctx.getAttribute("tmp.resource-allocator.aic-site-id");
892         if (clli != null) {
893         mm.put("clli", clli.trim());
894             mm.put("aic-site-id", clli.trim());
895         }
896
897         String vpeName = ctx.getAttribute("tmp.resource-allocator.vpe-name");
898         if (vpeName != null && vpeName.trim().length() > 0)
899             mm.put("vpe-name", vpeName.trim());
900
901         String vnfName = ctx.getAttribute("tmp.resource-allocator.device-name");
902         if (vnfName != null && vnfName.trim().length() > 0)
903             mm.put("vnf-name", vnfName.trim());
904
905         String excludeVpeList = ctx.getAttribute("tmp.resource-allocator.exclude-vpe-list");
906         if (excludeVpeList != null && excludeVpeList.trim().length() > 0)
907             mm.put("exclude-vpe-list", excludeVpeList.trim());
908
909         String uplinkCircuitCountStr =
910                 ctx.getAttribute("tmp.resource-allocator.uplink-circuit-list.uplink-circuit_length");
911         if (uplinkCircuitCountStr != null) {
912             long uplinkCircuitCount = 0;
913             try {
914                 uplinkCircuitCount = Long.parseLong(uplinkCircuitCountStr);
915             } catch (NumberFormatException e) {
916                 throw new SvcLogicException(
917                         "Invalid tmp.resource-allocator.uplink-circuit-list.uplink-circuit_length. Must be a number.");
918             }
919             List<Map<String, Object>> uplinkCircuitList = new ArrayList<>();
920             for (int i = 0; i < uplinkCircuitCount; i++) {
921                 String uplinkCircuitId = ctx.getAttribute(
922                         "tmp.resource-allocator.uplink-circuit-list.uplink-circuit[" + i + "].uplink-circuit-id");
923                 String uplinkCircuitBandwidthStr =
924                         ctx.getAttribute("tmp.resource-allocator.uplink-circuit-list.uplink-circuit[" + i +
925                                 "].uplink-circuit-bandwidth");
926                 String uplinkCircuitBandwidthUnit =
927                         ctx.getAttribute("tmp.resource-allocator.uplink-circuit-list.uplink-circuit[" + i +
928                                 "].uplink-circuit-bandwidth-unit");
929
930                 long uplinkCircuitBandwidth = 0;
931                 try {
932                     uplinkCircuitBandwidth = Long.parseLong(uplinkCircuitBandwidthStr);
933                 } catch (NumberFormatException e) {
934                     throw new SvcLogicException("Invalid tmp.resource-allocator.uplink-circuit-list.uplink-circuit[" +
935                             i + "].uplink-circuit-id. Must be a number.");
936                 }
937
938                 long uplinkCircuitBandwidthKbps =
939                         speedUtil.convertToKbps(uplinkCircuitBandwidth, uplinkCircuitBandwidthUnit);
940
941                 Map<String, Object> uplinkCircuit = new HashMap<String, Object>();
942                 uplinkCircuit.put("uplink-circuit-id", uplinkCircuitId);
943                 uplinkCircuit.put("uplink-circuit-bandwidth", uplinkCircuitBandwidthKbps);
944                 uplinkCircuitList.add(uplinkCircuit);
945             }
946             mm.put("uplink-circuit-list", uplinkCircuitList);
947         }
948
949         return mm;
950     }
951
952     private void setOutputContext(SvcLogicContext ctx, long maxAvailableSpeed, String unit) {
953         ctx.setAttribute("tmp.resource-allocator-output.max-available-speed", String.valueOf(maxAvailableSpeed));
954         ctx.setAttribute("tmp.resource-allocator-output.speed-unit", unit);
955     }
956
957     private int calculatePrimaryServerCount(int serverCount, String ratioString) throws SvcLogicException {
958         String[] ss = ratioString.split(":");
959         if (ss.length != 2)
960             throw new SvcLogicException("Invalid value for homing.pserver.sparing.ratio: " + ratioString);
961
962         int n = 1, m = 1;
963         try {
964             n = Integer.parseInt(ss[0]);
965             m = Integer.parseInt(ss[1]);
966         } catch (Exception e) {
967             throw new SvcLogicException("Invalid value for homing.pserver.sparing.ratio: " + ratioString);
968         }
969
970         return (serverCount - 1) * n / (n + m) + 1;
971     }
972
973     public void setServerDao(ServerDao serverDao) {
974         this.serverDao = serverDao;
975     }
976
977     public void setVpePortDao(VpePortDao vpePortDao) {
978         this.vpePortDao = vpePortDao;
979     }
980
981     public void setVplspePortDao(VplspePortDao vplspePortDao) {
982         this.vplspePortDao = vplspePortDao;
983     }
984
985     public void setMaxPortSpeedDao(MaxPortSpeedDao maxPortSpeedDao) {
986         this.maxPortSpeedDao = maxPortSpeedDao;
987     }
988
989     public void setMaxServerSpeedDao(MaxServerSpeedDao maxServerSpeedDao) {
990         this.maxServerSpeedDao = maxServerSpeedDao;
991     }
992
993     public void setAllocationRequestBuilder(AllocationRequestBuilder allocationRequestBuilder) {
994         this.allocationRequestBuilder = allocationRequestBuilder;
995     }
996
997     public void setResourceManager(ResourceManager resourceManager) {
998         this.resourceManager = resourceManager;
999     }
1000
1001     public void setSpeedUtil(SpeedUtil speedUtil) {
1002         this.speedUtil = speedUtil;
1003     }
1004
1005     public void setServiceResourceDao(ServiceResourceDao serviceResourceDao) {
1006         this.serviceResourceDao = serviceResourceDao;
1007     }
1008
1009     public void setEndPointAllocator(EndPointAllocator endPointAllocator) {
1010         this.endPointAllocator = endPointAllocator;
1011     }
1012
1013     public void setParameterDao(ParameterDao parameterDao) {
1014         this.parameterDao = parameterDao;
1015     }
1016 }