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
9 * http://www.apache.org/licenses/LICENSE-2.0
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=================================================
19 package org.onap.optf.cmso.optimizer.clients.optimizer;
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;
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;
41 * The Class ElementAvailability.
43 public class ElementAvailability extends ElementWindowMapping {
45 private List<TimeLimitAndVerticalTopology> policies;
46 private ActiveTicketsResponse ticketResponse;
48 private OptimizerParameters parameters = null;
50 private List<List<ChangeWindow>> globalRelativeAvailability = new ArrayList<>();
52 private Map<String, List<TicketData>> nodeUnAvailability = new TreeMap<>();
55 * Instantiates a new element availability.
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
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;
73 * @param parameters the parameters
74 * @throws ParseException the parse exception
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));
83 List<ChangeWindow> wholeWindow = new ArrayList<>();
84 wholeWindow.add(changeWindow);
85 globalRelativeAvailability.add(wholeWindow);
88 for (String id : nodeInfo.keySet()) {
89 calculateNodeAvailability(nodeInfo.get(id));
92 parameters.setMaxTime(new Long(parameters.getNoConflict().get(0).size()));
93 parameters.setNumElements(new Long(parameters.getNoConflict().size()));
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);
102 parameters.getLoaderCapacity().add(capacity);
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();
111 for (Long slot = 0L ; slot < parameters.getMaxTime() ; slot++) {
114 parameters.setElementSlotCapacity(capacity);
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();
125 for (String elementId : nodeInfo.keySet()) {
127 TopologyElementInfo info = nodeInfo.get(elementId);
128 // Library for lat/lon to timzezone is MIT license.
130 String timeZone = "GMT";
131 if (info.getElementLocation() != null && info.getElementLocation().getTimezone() != null
132 && !info.getElementLocation().getTimezone().equals("")) {
133 timeZone = info.getElementLocation().getTimezone();
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())) {
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))) {
153 parameters.getNoConflict().add(element);
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;
164 private boolean slotIsAvailable(ChangeWindow slot, String timeZone, List<TicketData> tickets) {
165 if (isGloballyAvailable(slot, timeZone) && isNotRestricted(slot, tickets)) {
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)) {
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
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
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)) {
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());
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);
227 private void updateNodeAvailability(String elementId, TicketData data) {
228 List<TicketData> list = nodeUnAvailability.get(elementId);
230 list = new ArrayList<>();
231 nodeUnAvailability.put(elementId, list);