246a725485ed1c41724557a3a1f25282882624af
[optf/cmso.git] /
1 /*
2  *  ============LICENSE_START==============================================
3  *  Copyright (c) 2019 AT&T Intellectual Property.
4  *  =======================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
6  *  not use this file except in compliance with the License. You may obtain a
7  *  copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing
15  * permissions and limitations under the License.
16  * ============LICENSE_END=================================================
17  */
18
19 package org.onap.optf.cmso.optimizer.clients.optimizer;
20
21 import com.google.ical.compat.jodatime.DateTimeIterator;
22 import java.text.ParseException;
23 import java.util.Date;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.TreeMap;
27 import java.util.stream.Collectors;
28 import org.joda.time.DateTime;
29 import org.onap.optf.cmso.optimizer.availability.timewindows.RecurringWindows;
30 import org.onap.optf.cmso.optimizer.clients.optimizer.models.ElementSlot;
31 import org.onap.optf.cmso.optimizer.clients.optimizer.models.OptimizerSchedule;
32 import org.onap.optf.cmso.optimizer.clients.topology.models.TopologyElementInfo;
33 import org.onap.optf.cmso.optimizer.clients.topology.models.TopologyResponse;
34 import org.onap.optf.cmso.optimizer.service.rs.models.ChangeWindow;
35 import org.onap.optf.cmso.optimizer.service.rs.models.ElementInfo;
36 import org.onap.optf.cmso.optimizer.service.rs.models.OptimizerRequest;
37 import org.onap.optf.cmso.optimizer.service.rs.models.OptimizerScheduleInfo;
38 import org.onap.optf.cmso.optimizer.service.rs.models.ScheduledElement;
39 import org.onap.optf.cmso.optimizer.service.rs.models.ScheduledElement.ScheduleType;
40 import org.onap.optf.cmso.optimizer.service.rs.models.UnScheduledElement;
41 import org.onap.optf.cmso.optimizer.service.rs.models.UnScheduledElement.NotScheduledReason;
42
43 // This class ensures that the node indices nodes and the time slots are the
44 // same when processing the optimizer engine response as when initiating.
45 public class ElementWindowMapping {
46
47     protected OptimizerRequest optimizerRequest;
48     protected TopologyResponse topologyResponse;
49
50     protected Map<String, TopologyElementInfo> nodeInfo = new TreeMap<>();
51     private List<TopologyElementInfo> nodeArray = null;
52
53     public ElementWindowMapping(OptimizerRequest optimizerRequest, TopologyResponse topologyResponse)
54                     throws ParseException {
55         this.optimizerRequest = optimizerRequest;
56         this.topologyResponse = topologyResponse;
57         initialize();
58
59     }
60
61     private void initialize() throws ParseException {
62         List<TopologyElementInfo> elements = topologyResponse.getElements();
63         for (TopologyElementInfo info : elements) {
64             nodeInfo.put(info.getElementId(), info);
65         }
66     }
67
68     protected DateTimeIterator getRecurringIterator() throws ParseException {
69         // Only support 1 change window for now
70         ChangeWindow window = optimizerRequest.getChangeWindows().get(0);
71         Long duration = new Long(optimizerRequest.getNormalDuration());
72         if (optimizerRequest.getAdditionalDuration() != null) {
73             duration += optimizerRequest.getAdditionalDuration();
74         }
75         DateTimeIterator recur = RecurringWindows.getRecurringListForChangeWindow(window, duration);
76         return recur;
77     }
78
79     public void initializeForProcessResult() {
80        // we need nodeInfo to be an array to speed up the result processing.
81        // but we need it sorted by elementId as when we created it....
82        nodeArray = nodeInfo.values().stream().collect(Collectors.toList());
83        nodeInfo.clear();
84
85     }
86
87     public OptimizerScheduleInfo processResult(OptimizerSchedule result) throws ParseException {
88         // When considering the memory vs performance
89         // 5 minute duration for a month long change window is 8928 slots
90         // The assumption is that there were be fewer allocated slots
91         // than potential slots.
92         List<ElementSlot> elements = result.getElementSlotLoader();
93         Map<Integer, List<ElementSlot>> mapSlotToElement =
94                         elements.stream().collect(Collectors.groupingBy(ElementSlot::getSlot));
95         DateTimeIterator iter = getRecurringIterator();
96         // TODO - supporting only 1 change window at the moment.....
97         Long endWindow = optimizerRequest.getChangeWindows().get(0).getEndTime().getTime();
98         Integer slotIndex = 1;
99         while (iter.hasNext()) {
100             DateTime dateTime = iter.next();
101             if (dateTime.isAfter(endWindow))
102                 break;
103             List<ElementSlot> list = mapSlotToElement.get(slotIndex);
104             if (list != null) {
105                 list.stream().forEach(x -> x.setTime(dateTime.getMillis()));
106             }
107             slotIndex++;
108         }
109         //
110         // All assigned ElementSlots now have corresponding UTC time
111         //
112         OptimizerScheduleInfo info = new OptimizerScheduleInfo();
113         for (ElementSlot slot : elements) {
114             updateInfo(slot, info);
115         }
116         return info;
117     }
118
119     private void updateInfo(ElementSlot slot, OptimizerScheduleInfo info) {
120         TopologyElementInfo element = nodeArray.get(slot.getElementIndex()-1);
121         if (slot.getSlot() > 0) {
122             ScheduledElement scheduled = new ScheduledElement();
123             Integer durationInSeconds = optimizerRequest.getNormalDuration();
124             if (optimizerRequest.getAdditionalDuration() != null) {
125                 durationInSeconds += optimizerRequest.getAdditionalDuration();
126             }
127             scheduled.setDurationSeconds(durationInSeconds.longValue());
128             scheduled.setElementId(element.getElementId());
129             scheduled.setStartTime(new Date(slot.getTime()));
130             scheduled.setEndTime(new Date(slot.getTime() + (durationInSeconds*1000)));
131             scheduled.setScheduleType(ScheduleType.INDIVIDUAL);
132             scheduled.setGroupId(getGroupId(scheduled.getElementId()));
133             info.getScheduledElements().add(scheduled);
134         } else {
135             UnScheduledElement unscheduled = new UnScheduledElement();
136             unscheduled.setElementId(element.getElementId());
137             unscheduled.setGroupId("unknown");
138             unscheduled.getNotScheduledReaons().add(NotScheduledReason.Other);
139             unscheduled.getNotScheduledMessages().add("Unknown");
140             info.getUnScheduledElements().add(unscheduled);
141         }
142     }
143
144     private String getGroupId(String elementId) {
145         ElementInfo info = getElementInfo(elementId);
146         if (info != null) {
147             return info.getGroupId();
148         }
149         return "";
150     }
151
152     private ElementInfo getElementInfo(String elementId) {
153         List<ElementInfo> elements = optimizerRequest.getElements();
154         ElementInfo info = elements.stream().filter(x -> x.getElementId().equals(elementId)).findAny().orElse(null);
155         return info;
156     }
157
158 }