@Autowired\r
PropertiesManagement pm;\r
\r
- public boolean scheduleSniroOptimization(Integer id) {\r
+ public boolean scheduleOptimization(Integer id) {\r
Map<String, String> mdcSave = Mdc.save();\r
try {\r
- String snirourl = env.getProperty("cmso.optimizer.url");\r
- String snirocallbackurl = env.getProperty("cmso.optimizer.callbackurl");\r
+ String optimizerurl = env.getProperty("cmso.optimizer.url");\r
+ String optimizercallbackurl = env.getProperty("cmso.optimizer.callbackurl");\r
String username = env.getProperty("mechid.user");\r
- Integer maxAttempts = env.getProperty("cmso.sniro.maxAttempts", Integer.class, 20);\r
+ Integer maxAttempts = env.getProperty("cmso.optimizer.maxAttempts", Integer.class, 20);\r
\r
- // Ensure that only one cmso is requsting this call to SNIRO\r
+ // Ensure that only one cmso is requsting this call to optimizer\r
Schedule schedule = scheduleDAO.lockOne(id);\r
if (!schedule.getStatus().equals(CMSStatusEnum.PendingSchedule.toString()))\r
return false;\r
if (info == null) {\r
return true;\r
}\r
- buildRequest(cmReq, info, schedule, snirocallbackurl);\r
+ buildRequest(cmReq, info, schedule, optimizercallbackurl);\r
} catch (Exception e) {\r
Observation.report(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());\r
}\r
\r
// This service will call SNIO for each PendingOptimiztion\r
- // If the request is successfully scheduled in SNIRO, status will be\r
+ // If the request is successfully scheduled in optimizer, status will be\r
// updated to OptimizationInProgress.\r
Client client = ClientBuilder.newClient();\r
client.register(new BasicAuthenticatorFilter(username, password));\r
client.register(new CMSOClientFilters());\r
- WebTarget sniroTarget = client.target(snirourl);\r
- Invocation.Builder invocationBuilder = sniroTarget.request(MediaType.APPLICATION_JSON);\r
+ WebTarget optimizerTarget = client.target(optimizerurl);\r
+ Invocation.Builder invocationBuilder = optimizerTarget.request(MediaType.APPLICATION_JSON);\r
try {\r
//\r
// First, push OptimizationInProgress to the DB (flush()) assuming a 202 status,\r
- // in case the SNIRO callback is received prior to the\r
+ // in case the optimizer callback is received prior to the\r
// commit of this transaction.\r
- // SNIRO Callback will throw an error if it receives a response in the incorrect\r
+ // optimizer Callback will throw an error if it receives a response in the incorrect\r
// state.\r
//\r
schedule.setOptimizerTransactionId(cmReq.getRequestInfo().getTransactionId());\r
schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
schedule.setStatus(CMSStatusEnum.OptimizationInProgress.toString());\r
updateScheduleStatus(schedule);\r
- debug.debug("SNIRO url / user: " + snirourl + " / " + username);\r
- debug.debug("SNIRO Request: " + new ObjectMapper().writeValueAsString(cmReq));\r
- Observation.report(LogMessages.OPTIMIZER_REQUEST, "Begin", schedule.getScheduleId(), snirourl);\r
+ debug.debug("optimizer url / user: " + optimizerurl + " / " + username);\r
+ debug.debug("optimizer Request: " + new ObjectMapper().writeValueAsString(cmReq));\r
+ Observation.report(LogMessages.OPTIMIZER_REQUEST, "Begin", schedule.getScheduleId(), optimizerurl);\r
Response response = invocationBuilder.post(Entity.json(cmReq));\r
- Observation.report(LogMessages.OPTIMIZER_REQUEST, "End", schedule.getScheduleId(), snirourl);\r
+ Observation.report(LogMessages.OPTIMIZER_REQUEST, "End", schedule.getScheduleId(), optimizerurl);\r
switch (response.getStatus()) {\r
case 202:\r
debug.debug("Successfully scheduled optimization: " + schedule.getScheduleId());\r
- // Scheduled with SNIRO\r
+ // Scheduled with optimizer\r
break;\r
case 400: // Bad request\r
{\r
String message = response.readEntity(String.class);\r
schedule.setOptimizerMessage(message);\r
schedule.setStatus(CMSStatusEnum.ScheduleFailed.toString());\r
- // Need to understand the cause of this error. May be teh same as SNIRO\r
+ // Need to understand the cause of this error. May be teh same as optimizer\r
// down.\r
int tries = schedule.getOptimizerAttemptsToSchedule();\r
tries++;\r
return true;\r
} catch (ResponseProcessingException e) {\r
schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
- schedule.setOptimizerStatus("Failed to parse SNIRO response");\r
+ schedule.setOptimizerStatus("Failed to parse optimizer response");\r
schedule.setStatus(CMSStatusEnum.ScheduleFailed.toString());\r
- // Need to understand the cause of this error. May be teh same as SNIRO down.\r
+ // Need to understand the cause of this error. May be teh same as optimizer down.\r
int tries = schedule.getOptimizerAttemptsToSchedule();\r
tries++;\r
schedule.setOptimizerAttemptsToSchedule(tries);\r
updateScheduleStatus(schedule);\r
- // Getting invalid response from SNIRO.\r
+ // Getting invalid response from optimizer.\r
// May be data related.\r
Observation.report(LogMessages.OPTIMIZER_EXCEPTION, e, e.getMessage());\r
return false;\r
\r
} catch (ProcessingException e) {\r
- // Don't track number of retries on IO error (SNIRO is down)\r
+ // Don't track number of retries on IO error (optimizer is down)\r
schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
schedule.setStatus(CMSStatusEnum.PendingSchedule.toString());\r
updateScheduleStatus(schedule);\r
- /// Cannot connect to SNIRO\r
+ /// Cannot connect to optimizer\r
Observation.report(LogMessages.OPTIMIZER_EXCEPTION, e, e.getMessage());\r
// Wait until next cycle\r
return false;\r
return false;\r
}\r
\r
- private void buildRequest(CMOptimizerRequest cmReq, CMSInfo info, Schedule schedule, String snirocallbackurl) {\r
+ private void buildRequest(CMOptimizerRequest cmReq, CMSInfo info, Schedule schedule, String optimizercallbackurl) {\r
\r
- // TODO: Need to get SNIRO to accept ChangeManagementSchedulingInfo\r
- // This is to support 1707 SNIRO interface\r
+ // TODO: Need to get optimizer to accept ChangeManagementSchedulingInfo\r
+ // This is to support 1707 optimizer interface\r
CMRequestInfo reqInfo = cmReq.getRequestInfo();\r
CMSchedulingInfo schInfo = cmReq.getSchedulingInfo();\r
\r
UUID uuid = UUID.randomUUID();\r
- reqInfo.setCallbackUrl(snirocallbackurl);\r
+ reqInfo.setCallbackUrl(optimizercallbackurl);\r
reqInfo.setOptimizer(new String[] {"scheduling"});\r
reqInfo.setTransactionId(schedule.getOptimizerTransactionId());\r
reqInfo.setRequestId("CM-" + uuid.toString());\r
// Perhaps We create ChangeManagementSchedulingInfoV1, ...V2, etc.\r
// ANd try them one after another....\r
Observation.report(LogMessages.UNEXPECTED_EXCEPTION, e, "Unable to parse message. Format changed?");\r
- schedule.setOptimizerStatus("Failed to parse SNIRO request");\r
+ schedule.setOptimizerStatus("Failed to parse optimizer request");\r
schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());\r
scheduleDAO.save(schedule);\r
public HealthCheckComponent healthCheck() {\r
Map<String, String> mdcSave = Mdc.save();\r
HealthCheckComponent hcc = new HealthCheckComponent();\r
- hcc.setName("SNIRO Interface");\r
- String snirourl = env.getProperty("cmso.optimizer.url");\r
- String snirocallbackurl = env.getProperty("cmso.optimizer.callbackurl");\r
+ hcc.setName("OPtimizer Interface");\r
+ String optimizerurl = env.getProperty("cmso.optimizer.url");\r
+ String optimizercallbackurl = env.getProperty("cmso.optimizer.callbackurl");\r
String username = env.getProperty("mechid.user");\r
String password = pm.getProperty("mechid.pass", "");\r
- hcc.setUrl(snirourl);\r
+ hcc.setUrl(optimizerurl);\r
try {\r
UUID uuid = UUID.randomUUID();\r
// Build a bogus request should fail policy validation\r
client.register(new BasicAuthenticatorFilter(username, password));\r
client.register(new CMSOClientFilters());\r
\r
- WebTarget sniroTarget = client.target(snirourl);\r
- Invocation.Builder invocationBuilder = sniroTarget.request(MediaType.APPLICATION_JSON);\r
- debug.debug("SNIRO url / user: " + snirourl + " / " + username);\r
- Observation.report(LogMessages.OPTIMIZER_REQUEST, "Begin", "healthcheck", snirourl);\r
+ WebTarget optimizerTarget = client.target(optimizerurl);\r
+ Invocation.Builder invocationBuilder = optimizerTarget.request(MediaType.APPLICATION_JSON);\r
+ debug.debug("Optimizer url / user: " + optimizerurl + " / " + username);\r
+ Observation.report(LogMessages.OPTIMIZER_REQUEST, "Begin", "healthcheck", optimizerurl);\r
Response response = invocationBuilder.post(Entity.json(cmReq));\r
- Observation.report(LogMessages.OPTIMIZER_REQUEST, "End", "healthcheck", snirourl);\r
+ Observation.report(LogMessages.OPTIMIZER_REQUEST, "End", "healthcheck", optimizerurl);\r
String message = response.getStatus() + ":" + response.readEntity(String.class);\r
switch (response.getStatus()) {\r
case 202:\r
- debug.debug("Successful SNIRO healthcheck");\r
+ debug.debug("Successful optimizer healthcheck");\r
hcc.setHealthy(true);\r
break;\r
case 400:\r
// Expecting policy not found.\r
if (message.contains("Cannot fetch policy")) {\r
- debug.debug("Successful SNIRO healthcheck");\r
+ debug.debug("Successful optimizer healthcheck");\r
hcc.setHealthy(true);\r
hcc.setStatus("OK");\r
} else {\r
-/*\r
- * Copyright © 2017-2019 AT&T Intellectual Property.\r
- * Modifications Copyright © 2018 IBM.\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * \r
- * \r
- * Unless otherwise specified, all documentation contained herein is licensed\r
- * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
- * you may not use this documentation except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- * https://creativecommons.org/licenses/by/4.0/\r
- * \r
- * Unless required by applicable law or agreed to in writing, documentation\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
-*/\r
-\r
-package org.onap.optf.cmso.service.rs;\r
-\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import javax.servlet.http.HttpServletRequest;\r
-import javax.transaction.Transactional;\r
-import javax.ws.rs.core.Response;\r
-import javax.ws.rs.core.Response.Status;\r
-import javax.ws.rs.core.UriInfo;\r
-import org.joda.time.DateTime;\r
-import org.joda.time.format.DateTimeFormat;\r
-import org.joda.time.format.ISODateTimeFormat;\r
-import org.onap.observations.Mdc;\r
-import org.onap.optf.cmso.common.CMSStatusEnum;\r
-import org.onap.optf.cmso.common.DomainsEnum;\r
-import org.onap.optf.cmso.common.LogMessages;\r
-import org.onap.optf.cmso.common.exceptions.CMSException;\r
-import org.onap.optf.cmso.common.exceptions.CMSNotFoundException;\r
-import org.onap.optf.cmso.model.ChangeManagementGroup;\r
-import org.onap.optf.cmso.model.ChangeManagementSchedule;\r
-import org.onap.optf.cmso.model.Schedule;\r
-import org.onap.optf.cmso.model.dao.ChangeManagementChangeWindowDAO;\r
-import org.onap.optf.cmso.model.dao.ChangeManagementDetailDAO;\r
-import org.onap.optf.cmso.model.dao.ChangeManagementGroupDAO;\r
-import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;\r
-import org.onap.optf.cmso.optimizer.bean.CMOptimizerResponse;\r
-import org.onap.optf.cmso.optimizer.bean.CMSchedule;\r
-import org.springframework.beans.factory.annotation.Autowired;\r
-import org.springframework.stereotype.Controller;\r
-import com.att.eelf.configuration.EELFLogger;\r
-import com.att.eelf.configuration.EELFManager;\r
-import com.fasterxml.jackson.databind.ObjectMapper;\r
-\r
-@Controller\r
-public class CMSCallbackImpl extends BaseSchedulerServiceImpl implements CMSOptimizerCallback {\r
- private static EELFLogger log = EELFManager.getInstance().getLogger(CMSCallbackImpl.class);\r
- private static EELFLogger metrics = EELFManager.getInstance().getMetricsLogger();\r
- private static EELFLogger audit = EELFManager.getInstance().getAuditLogger();\r
- private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
- private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();\r
-\r
- @Autowired\r
- ChangeManagementScheduleDAO cmScheduleDAO;\r
-\r
- @Autowired\r
- ChangeManagementGroupDAO cmGroupDAO;\r
-\r
- @Autowired\r
- ChangeManagementChangeWindowDAO cmChangeWindowDAO;\r
-\r
- @Autowired\r
- ChangeManagementDetailDAO cmDetailsDAO;\r
-\r
- @Override\r
- @Transactional\r
- public Response sniroCallback(String apiVersion, CMOptimizerResponse sniroResponse, UriInfo uri,\r
- HttpServletRequest request) {\r
- Response response = null;\r
- log.info(LogMessages.PROCESS_OPTIMIZER_CALLBACK, "Received", request.getRemoteAddr(), "");\r
- log.info(LogMessages.OPTIMIZER_REQUEST, "Callback received", sniroResponse.getTransactionId(),\r
- uri.getAbsolutePath().toString());\r
- try {\r
- // Note that transaction ID and schedule ID are currently the same value.\r
-\r
- String transactionId = sniroResponse.getTransactionId();\r
-\r
- // Synchronize this with transaction that scheduled the SNIRO optimization\r
- // to ensure status updates are properly ordered.\r
- // This is necessary only in the race condition where SNIRO callback comes\r
- // before the SNIRO response is processed and the scheduling transaction is\r
- // still in flight.\r
- // Note that this may happen in loopback mode, but is not likely to happen with\r
- // real SNIRO unless SNIRO changes to be synchronous and the callback comes before\r
- // the response.\r
- // If this lock times out, the schedule will remain in 'Optimization In\r
- // Progress' and never complete.\r
- Schedule schedule = scheduleDAO.lockOneByTransactionId(transactionId);\r
-\r
- if (schedule == null) {\r
- throw new CMSNotFoundException(DomainsEnum.ChangeManagement.toString(),\r
- "(OptimizerTransactionID=" + transactionId + ")");\r
-\r
- }\r
- CMSStatusEnum status = CMSStatusEnum.PendingApproval.fromString(schedule.getStatus());\r
- debug.debug("Status at time of SNIRO callback is " + status.toString());\r
- switch (status) {\r
- // PendingSchedule may be a valid status in the cases where SNIRO async call\r
- // returns before\r
- // We have committed the OptimizationInProgress status\r
- // The dispatch logic ensures that we only every dispatch once.\r
- case OptimizationInProgress:\r
- processSniroResponse(sniroResponse, schedule);\r
- scheduleDAO.save(schedule);\r
- response = Response.ok().build();\r
- break;\r
- default:\r
- throw new CMSException(Status.PRECONDITION_FAILED, LogMessages.OPTIMIZER_CALLBACK_STATE_ERROR,\r
- CMSStatusEnum.OptimizationInProgress.toString(), schedule.getStatus().toString());\r
- }\r
- } catch (CMSException e) {\r
- errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
- response = Response.status(e.getStatus()).entity(e.getRequestError()).build();\r
- } catch (Exception e) {\r
- errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
- response = Response.serverError().entity(e.getMessage()).build();\r
- } finally {\r
- }\r
- return response;\r
- }\r
-\r
- private void processSniroResponse(CMOptimizerResponse sniroResponse, Schedule schedule) {\r
- try {\r
- schedule.setOptimizerReturnDateTimeMillis(System.currentTimeMillis());\r
- schedule.setOptimizerStatus(sniroResponse.getRequestState());\r
- schedule.setOptimizerMessage(sniroResponse.getDescription());\r
- String scheduleId = sniroResponse.getScheduleId();\r
- ObjectMapper om = new ObjectMapper();\r
- CMSchedule[] scheduleArray = sniroResponse.getSchedule();\r
- if (scheduleArray != null && scheduleArray.length > 0) {\r
- String scheduleString = om.writeValueAsString(scheduleArray);\r
- schedule.setSchedule(scheduleString);\r
- log.debug("scheduleId={0} schedule={1}", scheduleId, scheduleString);\r
- for (CMSchedule sniroSchedule : sniroResponse.getSchedule()) {\r
- String groupId = sniroSchedule.getGroupId();\r
- DateTime finishTime = convertDate(sniroSchedule.getFinishTime(), "finishTime");\r
- DateTime latestInstanceStartTime =\r
- convertDate(sniroSchedule.getLatestInstanceStartTime(), "latestInstanceStartTime");\r
- DateTime startTime = convertDate(sniroSchedule.getStartTime(), "startTime");\r
- ChangeManagementGroup group = cmGroupDAO.findOneBySchedulesIDGroupID(schedule.getId(), groupId);\r
- if (group == null) {\r
- throw new CMSException(Status.PRECONDITION_FAILED,\r
- LogMessages.CHANGE_MANAGEMENT_GROUP_NOT_FOUND, schedule.getScheduleId(), groupId);\r
- }\r
- group.setStartTimeMillis(startTime.getMillis());\r
- group.setFinishTimeMillis(finishTime.getMillis());\r
- group.setLastInstanceStartTimeMillis(latestInstanceStartTime.getMillis());\r
- cmGroupDAO.save(group);\r
- long totalDuration =\r
- (group.getAdditionalDurationInSecs() + group.getNormalDurationInSecs()) * 1000l;\r
- Map<String, Map<String, Long>> startAndFinishTimeMap = new HashMap<String, Map<String, Long>>();\r
- makeMap(startTime.getMillis(), latestInstanceStartTime.getMillis(), group.getConcurrencyLimit(),\r
- totalDuration, sniroSchedule.getNode(), startAndFinishTimeMap);\r
- for (String node : sniroSchedule.getNode()) {\r
- processNode(schedule, group, node, startAndFinishTimeMap);\r
- }\r
- }\r
- schedule.setStatus(CMSStatusEnum.PendingApproval.toString());\r
- } else {\r
- debug.debug("scheduleId={0} schedule=null status={1} ", scheduleId, schedule.getOptimizerStatus());\r
- schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());\r
- }\r
- } catch (CMSException e) {\r
- errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
- schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());\r
- schedule.setOptimizerStatus(e.getStatus().toString());\r
- schedule.setOptimizerMessage(e.getLocalizedMessage());\r
- } catch (Exception e) {\r
- errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
- schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());\r
- schedule.setOptimizerStatus("Exception");\r
- schedule.setOptimizerMessage(e.getLocalizedMessage());\r
- }\r
- }\r
-\r
- public static void makeMap(Long startTime, Long latestInstanceStartTime, int concurrencyLimit, long totalDuration,\r
- List<String> nodes, Map<String, Map<String, Long>> startAndFinishTimeMap) throws CMSException {\r
- Long nextStartTime = null;\r
- Long nextFinishTime = null;\r
- for (int nodeNumber = 0; nodeNumber < nodes.size(); nodeNumber++) {\r
- String node = nodes.get(nodeNumber);\r
- if (nodeNumber % concurrencyLimit == 0) {\r
- if (nodeNumber == 0)\r
- nextStartTime = startTime;\r
- else\r
- nextStartTime = nextStartTime + totalDuration;\r
- if (nextStartTime > latestInstanceStartTime) {\r
- throw new CMSException(Status.BAD_REQUEST, LogMessages.UNABLE_TO_ALLOCATE_VNF_TIMESLOTS,\r
- startTime.toString(), latestInstanceStartTime.toString(), String.valueOf(totalDuration),\r
- String.valueOf(concurrencyLimit), String.valueOf(nodes.size()));\r
- }\r
- nextFinishTime = nextStartTime + totalDuration;\r
- }\r
- Map<String, Long> map = new HashMap<String, Long>();\r
- map.put("startTime", nextStartTime);\r
- map.put("finishTime", nextFinishTime);\r
- startAndFinishTimeMap.put(node, map);\r
- }\r
-\r
- }\r
-\r
- private void processNode(Schedule schedule, ChangeManagementGroup group, String node,\r
- Map<String, Map<String, Long>> startAndFinishTimeMap) throws CMSException {\r
- Map<String, Long> map = startAndFinishTimeMap.get(node);\r
- ChangeManagementSchedule detail = cmScheduleDAO.findOneByGroupIDAndVnfName(group.getId(), node);\r
- if (detail == null) {\r
- throw new CMSException(Status.NOT_FOUND, LogMessages.UNABLE_TO_LOCATE_SCHEDULE_DETAIL,\r
- schedule.getScheduleId(), group.getGroupId(), node);\r
- }\r
- detail.setStartTimeMillis(map.get("startTime"));\r
- detail.setFinishTimeMillis(map.get("finishTime"));\r
- detail.setVnfId("");\r
- detail.setStatus(CMSStatusEnum.PendingApproval.toString());\r
- cmScheduleDAO.save(detail);\r
- }\r
-\r
- public static DateTime convertDate(String utcDate, String attrName) throws CMSException {\r
- try {\r
- DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withZoneUTC().parseDateTime(utcDate);\r
- if (dateTime != null)\r
- return dateTime;\r
- } catch (Exception e) {\r
- debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
- }\r
- throw new CMSException(Status.BAD_REQUEST, LogMessages.INVALID_ATTRIBUTE, attrName, utcDate);\r
- }\r
-\r
- public static DateTime convertISODate(String utcDate, String attrName) throws CMSException {\r
- try {\r
- DateTime dateTime = ISODateTimeFormat.dateTimeParser().parseDateTime(utcDate);\r
- if (dateTime != null)\r
- return dateTime;\r
- } catch (Exception e) {\r
- debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
- }\r
- throw new CMSException(Status.BAD_REQUEST, LogMessages.INVALID_ATTRIBUTE, attrName, utcDate);\r
- }\r
-\r
-}\r
+/*
+ * Copyright © 2017-2019 AT&T Intellectual Property.
+ * Modifications Copyright © 2018 IBM.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.onap.optf.cmso.service.rs;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.transaction.Transactional;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.ISODateTimeFormat;
+import org.onap.optf.cmso.common.CMSStatusEnum;
+import org.onap.optf.cmso.common.DomainsEnum;
+import org.onap.optf.cmso.common.LogMessages;
+import org.onap.optf.cmso.common.exceptions.CMSException;
+import org.onap.optf.cmso.common.exceptions.CMSNotFoundException;
+import org.onap.optf.cmso.model.ChangeManagementGroup;
+import org.onap.optf.cmso.model.ChangeManagementSchedule;
+import org.onap.optf.cmso.model.Schedule;
+import org.onap.optf.cmso.model.dao.ChangeManagementChangeWindowDAO;
+import org.onap.optf.cmso.model.dao.ChangeManagementDetailDAO;
+import org.onap.optf.cmso.model.dao.ChangeManagementGroupDAO;
+import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;
+import org.onap.optf.cmso.optimizer.bean.CMOptimizerResponse;
+import org.onap.optf.cmso.optimizer.bean.CMSchedule;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Controller
+public class CMSOOptimizerCallbackImpl extends BaseSchedulerServiceImpl implements CMSOptimizerCallback {
+ private static EELFLogger log = EELFManager.getInstance().getLogger(CMSOOptimizerCallbackImpl.class);
+ private static EELFLogger metrics = EELFManager.getInstance().getMetricsLogger();
+ private static EELFLogger audit = EELFManager.getInstance().getAuditLogger();
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();
+ private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();
+
+ @Context
+ UriInfo uri;
+
+ @Context
+ HttpServletRequest request;
+
+
+ @Autowired
+ ChangeManagementScheduleDAO cmScheduleDAO;
+
+ @Autowired
+ ChangeManagementGroupDAO cmGroupDAO;
+
+ @Autowired
+ ChangeManagementChangeWindowDAO cmChangeWindowDAO;
+
+ @Autowired
+ ChangeManagementDetailDAO cmDetailsDAO;
+
+ @Override
+ @Transactional
+ public Response sniroCallback(String apiVersion, CMOptimizerResponse sniroResponse) {
+ Response response = null;
+ log.info(LogMessages.PROCESS_OPTIMIZER_CALLBACK, "Received", request.getRemoteAddr(), "");
+ log.info(LogMessages.OPTIMIZER_REQUEST, "Callback received", sniroResponse.getTransactionId(),
+ uri.getAbsolutePath().toString());
+ try {
+ // Note that transaction ID and schedule ID are currently the same value.
+
+ String transactionId = sniroResponse.getTransactionId();
+
+ // Synchronize this with transaction that scheduled the SNIRO optimization
+ // to ensure status updates are properly ordered.
+ // This is necessary only in the race condition where SNIRO callback comes
+ // before the SNIRO response is processed and the scheduling transaction is
+ // still in flight.
+ // Note that this may happen in loopback mode, but is not likely to happen with
+ // real SNIRO unless SNIRO changes to be synchronous and the callback comes before
+ // the response.
+ // If this lock times out, the schedule will remain in 'Optimization In
+ // Progress' and never complete.
+ Schedule schedule = scheduleDAO.lockOneByTransactionId(transactionId);
+
+ if (schedule == null) {
+ throw new CMSNotFoundException(DomainsEnum.ChangeManagement.toString(),
+ "(OptimizerTransactionID=" + transactionId + ")");
+
+ }
+ CMSStatusEnum status = CMSStatusEnum.PendingApproval.fromString(schedule.getStatus());
+ debug.debug("Status at time of SNIRO callback is " + status.toString());
+ switch (status) {
+ // PendingSchedule may be a valid status in the cases where SNIRO async call
+ // returns before
+ // We have committed the OptimizationInProgress status
+ // The dispatch logic ensures that we only every dispatch once.
+ case OptimizationInProgress:
+ processSniroResponse(sniroResponse, schedule);
+ scheduleDAO.save(schedule);
+ response = Response.ok().build();
+ break;
+ default:
+ throw new CMSException(Status.PRECONDITION_FAILED, LogMessages.OPTIMIZER_CALLBACK_STATE_ERROR,
+ CMSStatusEnum.OptimizationInProgress.toString(), schedule.getStatus().toString());
+ }
+ } catch (CMSException e) {
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+ response = Response.status(e.getStatus()).entity(e.getRequestError()).build();
+ } catch (Exception e) {
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+ response = Response.serverError().entity(e.getMessage()).build();
+ } finally {
+ }
+ return response;
+ }
+
+ private void processSniroResponse(CMOptimizerResponse sniroResponse, Schedule schedule) {
+ try {
+ schedule.setOptimizerReturnDateTimeMillis(System.currentTimeMillis());
+ schedule.setOptimizerStatus(sniroResponse.getRequestState());
+ schedule.setOptimizerMessage(sniroResponse.getDescription());
+ String scheduleId = sniroResponse.getScheduleId();
+ ObjectMapper om = new ObjectMapper();
+ CMSchedule[] scheduleArray = sniroResponse.getSchedule();
+ if (scheduleArray != null && scheduleArray.length > 0) {
+ String scheduleString = om.writeValueAsString(scheduleArray);
+ schedule.setSchedule(scheduleString);
+ log.debug("scheduleId={0} schedule={1}", scheduleId, scheduleString);
+ for (CMSchedule sniroSchedule : sniroResponse.getSchedule()) {
+ String groupId = sniroSchedule.getGroupId();
+ DateTime finishTime = convertDate(sniroSchedule.getFinishTime(), "finishTime");
+ DateTime latestInstanceStartTime =
+ convertDate(sniroSchedule.getLatestInstanceStartTime(), "latestInstanceStartTime");
+ DateTime startTime = convertDate(sniroSchedule.getStartTime(), "startTime");
+ ChangeManagementGroup group = cmGroupDAO.findOneBySchedulesIDGroupID(schedule.getId(), groupId);
+ if (group == null) {
+ throw new CMSException(Status.PRECONDITION_FAILED,
+ LogMessages.CHANGE_MANAGEMENT_GROUP_NOT_FOUND, schedule.getScheduleId(), groupId);
+ }
+ group.setStartTimeMillis(startTime.getMillis());
+ group.setFinishTimeMillis(finishTime.getMillis());
+ group.setLastInstanceStartTimeMillis(latestInstanceStartTime.getMillis());
+ cmGroupDAO.save(group);
+ long totalDuration =
+ (group.getAdditionalDurationInSecs() + group.getNormalDurationInSecs()) * 1000l;
+ Map<String, Map<String, Long>> startAndFinishTimeMap = new HashMap<String, Map<String, Long>>();
+ makeMap(startTime.getMillis(), latestInstanceStartTime.getMillis(), group.getConcurrencyLimit(),
+ totalDuration, sniroSchedule.getNode(), startAndFinishTimeMap);
+ for (String node : sniroSchedule.getNode()) {
+ processNode(schedule, group, node, startAndFinishTimeMap);
+ }
+ }
+ schedule.setStatus(CMSStatusEnum.PendingApproval.toString());
+ } else {
+ debug.debug("scheduleId={0} schedule=null status={1} ", scheduleId, schedule.getOptimizerStatus());
+ schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());
+ }
+ } catch (CMSException e) {
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+ schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());
+ schedule.setOptimizerStatus(e.getStatus().toString());
+ schedule.setOptimizerMessage(e.getLocalizedMessage());
+ } catch (Exception e) {
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+ schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());
+ schedule.setOptimizerStatus("Exception");
+ schedule.setOptimizerMessage(e.getLocalizedMessage());
+ }
+ }
+
+ public static void makeMap(Long startTime, Long latestInstanceStartTime, int concurrencyLimit, long totalDuration,
+ List<String> nodes, Map<String, Map<String, Long>> startAndFinishTimeMap) throws CMSException {
+ Long nextStartTime = null;
+ Long nextFinishTime = null;
+ for (int nodeNumber = 0; nodeNumber < nodes.size(); nodeNumber++) {
+ String node = nodes.get(nodeNumber);
+ if (nodeNumber % concurrencyLimit == 0) {
+ if (nodeNumber == 0)
+ nextStartTime = startTime;
+ else
+ nextStartTime = nextStartTime + totalDuration;
+ if (nextStartTime > latestInstanceStartTime) {
+ throw new CMSException(Status.BAD_REQUEST, LogMessages.UNABLE_TO_ALLOCATE_VNF_TIMESLOTS,
+ startTime.toString(), latestInstanceStartTime.toString(), String.valueOf(totalDuration),
+ String.valueOf(concurrencyLimit), String.valueOf(nodes.size()));
+ }
+ nextFinishTime = nextStartTime + totalDuration;
+ }
+ Map<String, Long> map = new HashMap<String, Long>();
+ map.put("startTime", nextStartTime);
+ map.put("finishTime", nextFinishTime);
+ startAndFinishTimeMap.put(node, map);
+ }
+
+ }
+
+ private void processNode(Schedule schedule, ChangeManagementGroup group, String node,
+ Map<String, Map<String, Long>> startAndFinishTimeMap) throws CMSException {
+ Map<String, Long> map = startAndFinishTimeMap.get(node);
+ ChangeManagementSchedule detail = cmScheduleDAO.findOneByGroupIDAndVnfName(group.getId(), node);
+ if (detail == null) {
+ throw new CMSException(Status.NOT_FOUND, LogMessages.UNABLE_TO_LOCATE_SCHEDULE_DETAIL,
+ schedule.getScheduleId(), group.getGroupId(), node);
+ }
+ detail.setStartTimeMillis(map.get("startTime"));
+ detail.setFinishTimeMillis(map.get("finishTime"));
+ detail.setVnfId("");
+ detail.setStatus(CMSStatusEnum.PendingApproval.toString());
+ cmScheduleDAO.save(detail);
+ }
+
+ public static DateTime convertDate(String utcDate, String attrName) throws CMSException {
+ try {
+ DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withZoneUTC().parseDateTime(utcDate);
+ if (dateTime != null)
+ return dateTime;
+ } catch (Exception e) {
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+ }
+ throw new CMSException(Status.BAD_REQUEST, LogMessages.INVALID_ATTRIBUTE, attrName, utcDate);
+ }
+
+ public static DateTime convertISODate(String utcDate, String attrName) throws CMSException {
+ try {
+ DateTime dateTime = ISODateTimeFormat.dateTimeParser().parseDateTime(utcDate);
+ if (dateTime != null)
+ return dateTime;
+ } catch (Exception e) {
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+ }
+ throw new CMSException(Status.BAD_REQUEST, LogMessages.INVALID_ATTRIBUTE, attrName, utcDate);
+ }
+
+}