ac5d2e7966c83ce9e370548cc9b1d7ea28ba9ec2
[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.ArrayList;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.TreeMap;
29 import org.joda.time.DateTime;
30 import org.onap.optf.cmso.optimizer.availability.policies.model.TimeLimitAndVerticalTopology;
31 import org.onap.optf.cmso.optimizer.availability.timewindows.RecurringWindows;
32 import org.onap.optf.cmso.optimizer.clients.optimizer.models.OptimizerParameters;
33 import org.onap.optf.cmso.optimizer.clients.ticketmgt.models.ActiveTicketsResponse;
34 import org.onap.optf.cmso.optimizer.clients.ticketmgt.models.TicketData;
35 import org.onap.optf.cmso.optimizer.clients.topology.models.TopologyElementInfo;
36 import org.onap.optf.cmso.optimizer.clients.topology.models.TopologyResponse;
37 import org.onap.optf.cmso.optimizer.service.rs.models.ChangeWindow;
38 import org.onap.optf.cmso.optimizer.service.rs.models.OptimizerRequest;
39
40 /**
41  * The Class ElementAvailability.
42  */
43 public class ElementAvailability extends ElementWindowMapping {
44
45     private List<TimeLimitAndVerticalTopology> policies;
46     private ActiveTicketsResponse ticketResponse;
47
48     private OptimizerParameters parameters = null;
49
50     private List<List<ChangeWindow>> globalRelativeAvailability = new ArrayList<>();
51
52     private Map<String, List<TicketData>> nodeUnAvailability = new TreeMap<>();
53
54     /**
55      * Instantiates a new element availability.
56      *
57      * @param policies the policies
58      * @param optimizerRequest the optimizer request
59      * @param topologyResponse the topology response
60      * @param ticketResponse the ticket response
61      * @throws ParseException the parse exception
62      */
63     public ElementAvailability(List<TimeLimitAndVerticalTopology> policies, OptimizerRequest optimizerRequest,
64                     TopologyResponse topologyResponse, ActiveTicketsResponse ticketResponse) throws ParseException {
65         super(optimizerRequest, topologyResponse);
66         this.policies         = policies;
67         this.ticketResponse   = ticketResponse;
68     }
69
70     /**
71      * Populate.
72      *
73      * @param parameters the parameters
74      * @throws ParseException the parse exception
75      */
76     public void populate(OptimizerParameters parameters) throws ParseException {
77         this.parameters = parameters;
78         for (ChangeWindow changeWindow : optimizerRequest.getChangeWindows()) {
79             if  (policies.size() > 0) {
80                 globalRelativeAvailability
81                                 .add(RecurringWindows.getAvailabilityWindowsForPolicies(policies, changeWindow));
82             } else {
83                 List<ChangeWindow> wholeWindow = new ArrayList<>();
84                 wholeWindow.add(changeWindow);
85                 globalRelativeAvailability.add(wholeWindow);
86             }
87         }
88         for (String id : nodeInfo.keySet()) {
89             calculateNodeAvailability(nodeInfo.get(id));
90         }
91         setNoConflicts();
92         parameters.setMaxTime(new Long(parameters.getNoConflict().get(0).size()));
93         parameters.setNumElements(new Long(parameters.getNoConflict().size()));
94
95         // for now we have 1 loader with unlimited capacity
96         parameters.setNumLoaders(1L);
97         Long loaderCapacity = parameters.getNumElements();
98         List<Long> capacity =  new ArrayList<>();
99         for (Long slot = 0L ; slot < parameters.getMaxTime() ; slot++) {
100             capacity.add(loaderCapacity);
101         }
102         parameters.getLoaderCapacity().add(capacity);
103
104         // For now every slot has the same concurrency limit
105         capacity =  new ArrayList<>();
106         Long limit = new Long(optimizerRequest.getConcurrencyLimit());
107         if (limit > parameters.getNumElements()) {
108             limit = parameters.getNumElements();
109         }
110
111         for (Long slot = 0L ; slot < parameters.getMaxTime() ; slot++) {
112             capacity.add(limit);
113         }
114         parameters.setElementSlotCapacity(capacity);
115
116     }
117
118     private void setNoConflicts() throws ParseException {
119         // Only support 1 change window for now
120         ChangeWindow window = optimizerRequest.getChangeWindows().get(0);
121         Long duration = new Long(optimizerRequest.getNormalDuration());
122         if (optimizerRequest.getAdditionalDuration() != null) {
123             duration += optimizerRequest.getAdditionalDuration();
124         }
125         for (String elementId : nodeInfo.keySet()) {
126
127             TopologyElementInfo info = nodeInfo.get(elementId);
128             // Library for lat/lon to timzezone is MIT license.
129             // We must provided
130             String timeZone = "GMT";
131             if (info.getElementLocation() != null && info.getElementLocation().getTimezone() != null
132                             && !info.getElementLocation().getTimezone().equals("")) {
133                 timeZone = info.getElementLocation().getTimezone();
134             }
135             DateTimeIterator recur = getRecurringIterator();
136             List<Boolean> element = new ArrayList<>();
137             // calculate number time slots
138             long numberOfTimeSlots = calculateNumberOfSlotsInWindow(window, duration);
139             while (recur.hasNext() && element.size() < numberOfTimeSlots) {
140                 DateTime next = recur.next();
141                 if (next.isAfter(window.getEndTime().getTime())) {
142                     break;
143                 }
144                 ChangeWindow slot = new ChangeWindow();
145                 slot.setStartTime(next.toDate());
146                 slot.setEndTime(next.plus(duration).toDate());
147                 if (slotIsAvailable(slot, timeZone, nodeUnAvailability.get(elementId))) {
148                     element.add(true);
149                 } else {
150                     element.add(false);
151                 }
152             }
153             parameters.getNoConflict().add(element);
154         }
155
156     }
157
158     private long calculateNumberOfSlotsInWindow(ChangeWindow window, Long duration) {
159         long windowSize = window.getEndTime().getTime() - window.getStartTime().getTime();
160         long numberOfSlots = windowSize / duration;
161         return numberOfSlots;
162     }
163
164     private boolean slotIsAvailable(ChangeWindow slot, String timeZone, List<TicketData> tickets) {
165         if (isGloballyAvailable(slot, timeZone) && isNotRestricted(slot, tickets)) {
166             return true;
167         }
168         return false;
169     }
170
171     private boolean isNotRestricted(ChangeWindow slot, List<TicketData> tickets) {
172         if (tickets != null) {
173             for (TicketData ticket : tickets) {
174                 ChangeWindow window = new ChangeWindow();
175                 window.setStartTime(ticket.getStartTime());
176                 window.setEndTime(ticket.getEndTime());
177                 if (slot.overlaps(window)) {
178                     return false;
179                 }
180             }
181         }
182         return true;
183     }
184
185     //
186     // Globally availability are generally maintenance window definitions
187     // which are UTC times that are treated as relative to the local time zone.
188     // The slot is an absolute UTCT time as well.
189     // When we test to see if the slot is 'globally' available we must adjust it
190     // to the local time of the element to see it it matches the relative
191     // Consider
192     // slot UTC time is 06:00-07:00
193     // global availability (maintenance window) 00:00-06:00
194     // the slot for an element in US/Eastern
195     // time would be converted to 01:00-02:00
196     // and would fit in the local maintenance window
197     //
198     private boolean isGloballyAvailable(ChangeWindow slot, String timeZone) {
199         boolean available = false;
200         for (ChangeWindow global : globalRelativeAvailability.get(0)) {
201             if (global.containsInTimeZone(slot, timeZone)) {
202                 available = true;
203             }
204         }
205         return available;
206     }
207
208     private void calculateNodeAvailability(TopologyElementInfo info) {
209         Set<String> requiredElements = new HashSet<>();
210         requiredElements.add(info.getElementId());
211         if (info.getRequiredElements() != null) {
212             requiredElements.addAll(info.getRequiredElements());
213         }
214         if (ticketResponse.getElements() != null) {
215             List<TicketData> tickets = ticketResponse.getElements();
216             for (TicketData data : tickets) {
217                 for (String id : data.getElementIds()) {
218                     if (requiredElements.contains(id)) {
219                         updateNodeAvailability(id, data);
220                         break;
221                     }
222                 }
223             }
224         }
225     }
226
227     private void updateNodeAvailability(String elementId, TicketData data) {
228         List<TicketData> list = nodeUnAvailability.get(elementId);
229         if (list == null) {
230             list = new ArrayList<>();
231             nodeUnAvailability.put(elementId, list);
232         }
233         list.add(data);
234     }
235
236 }