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;
40 public class ElementAvailability extends ElementWindowMapping{
42 private List<TimeLimitAndVerticalTopology> policies;
43 private ActiveTicketsResponse ticketResponse;
45 private OptimizerParameters parameters = null;
47 private List<List<ChangeWindow>> globalRelativeAvailability = new ArrayList<>();
49 private Map<String, List<TicketData>> nodeUnAvailability = new TreeMap<>();
51 public ElementAvailability(List<TimeLimitAndVerticalTopology> policies, OptimizerRequest optimizerRequest,
52 TopologyResponse topologyResponse, ActiveTicketsResponse ticketResponse) throws ParseException {
53 super(optimizerRequest, topologyResponse);
54 this.policies = policies;
55 this.ticketResponse = ticketResponse;
58 public void populate(OptimizerParameters parameters) throws ParseException {
59 this.parameters = parameters;
60 for (ChangeWindow changeWindow : optimizerRequest.getChangeWindows()) {
61 if (policies.size() > 0) {
62 globalRelativeAvailability
63 .add(RecurringWindows.getAvailabilityWindowsForPolicies(policies, changeWindow));
65 List<ChangeWindow> wholeWindow = new ArrayList<>();
66 wholeWindow.add(changeWindow);
67 globalRelativeAvailability.add(wholeWindow);
70 for (String id : nodeInfo.keySet()) {
71 calculateNodeAvailability(nodeInfo.get(id));
74 parameters.setMaxTime(new Long(parameters.getNoConflict().get(0).size()));
75 parameters.setNumElements(new Long(parameters.getNoConflict().size()));
77 // for now we have 1 loader with unlimited capacity
78 parameters.setNumLoaders(1L);
79 Long loaderCapacity = parameters.getNumElements();
80 List<Long> capacity = new ArrayList<>();
81 for (Long slot =0L ; slot < parameters.getMaxTime() ; slot++) {
82 capacity.add(loaderCapacity);
84 parameters.getLoaderCapacity().add(capacity);
86 // For now every slot has the same concurrency limit
87 capacity = new ArrayList<>();
88 Long limit = new Long(optimizerRequest.getConcurrencyLimit());
89 if (limit > parameters.getNumElements()) {
90 limit = parameters.getNumElements();
93 for (Long slot =0L ; slot < parameters.getMaxTime() ; slot++) {
96 parameters.setElementSlotCapacity(capacity);
100 private void setNoConflicts() throws ParseException {
101 // Only support 1 change window for now
102 ChangeWindow window = optimizerRequest.getChangeWindows().get(0);
103 Long duration = new Long(optimizerRequest.getNormalDuration());
104 if (optimizerRequest.getAdditionalDuration() != null) {
105 duration += optimizerRequest.getAdditionalDuration();
107 for (String elementId : nodeInfo.keySet()) {
109 TopologyElementInfo info = nodeInfo.get(elementId);
110 // Library for lat/lon to timzezone is MIT license.
112 String timeZone = "GMT";
113 if (info.getElementLocation() != null && info.getElementLocation().getTimezone() != null
114 && !info.getElementLocation().getTimezone().equals("")) {
115 timeZone = info.getElementLocation().getTimezone();
117 DateTimeIterator recur = getRecurringIterator();
118 List<Boolean> element = new ArrayList<>();
119 // calculate number time slots
120 long numberOfTimeSlots = calculateNumberOfSlotsInWindow(window, duration);
121 while (recur.hasNext() && element.size() < numberOfTimeSlots) {
122 DateTime next = recur.next();
123 if (next.isAfter(window.getEndTime().getTime())) {
126 ChangeWindow slot = new ChangeWindow();
127 slot.setStartTime(next.toDate());
128 slot.setEndTime(next.plus(duration).toDate());
129 if (slotIsAvailable(slot, timeZone, nodeUnAvailability.get(elementId))) {
135 parameters.getNoConflict().add(element);
140 private long calculateNumberOfSlotsInWindow(ChangeWindow window, Long duration)
142 long windowSize = window.getEndTime().getTime() - window.getStartTime().getTime();
143 long numberOfSlots = windowSize /duration;
144 return numberOfSlots;
147 private boolean slotIsAvailable(ChangeWindow slot, String timeZone, List<TicketData> tickets) {
148 if (isGloballyAvailable(slot, timeZone) && isNotRestricted(slot, tickets)) {
154 private boolean isNotRestricted(ChangeWindow slot, List<TicketData> tickets) {
155 if (tickets != null) {
156 for (TicketData ticket : tickets) {
157 ChangeWindow window = new ChangeWindow();
158 window.setStartTime(ticket.getStartTime());
159 window.setEndTime(ticket.getEndTime());
160 if (slot.overlaps(window)) {
169 // Globally availability are generally maintenance window definitions
170 // which are UTC times that are treated as relative to the local time zone.
171 // The slot is an absolute UTCT time as well.
172 // When we test to see if the slot is 'globally' available we must adjust it
173 // to the local time of the element to see it it matches the relative
175 // slot UTC time is 06:00-07:00
176 // global availability (maintenance window) 00:00-06:00
177 // the slot for an element in US/Eastern
178 // time would be converted to 01:00-02:00
179 // and would fit in the local maintenance window
181 private boolean isGloballyAvailable(ChangeWindow slot, String timeZone) {
182 boolean available = false;
183 for (ChangeWindow global : globalRelativeAvailability.get(0)) {
184 if (global.containsInTimeZone(slot, timeZone)) {
191 private void calculateNodeAvailability(TopologyElementInfo info) {
192 Set<String> requiredElements = new HashSet<>();
193 requiredElements.add(info.getElementId());
194 if (info.getRequiredElements() != null) {
195 requiredElements.addAll(info.getRequiredElements());
197 if (ticketResponse.getElements() != null) {
198 List<TicketData> tickets = ticketResponse.getElements();
199 for (TicketData data : tickets) {
200 for (String id : data.getElementIds()) {
201 if (requiredElements.contains(id)) {
202 updateNodeAvailability(id, data);
210 private void updateNodeAvailability(String elementId, TicketData data) {
211 List<TicketData> list = nodeUnAvailability.get(elementId);
213 list = new ArrayList<>();
214 nodeUnAvailability.put(elementId, list);