--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.dispatcher;\r
+\r
+import javax.ws.rs.ProcessingException;\r
+import javax.ws.rs.client.Client;\r
+import javax.ws.rs.client.ClientBuilder;\r
+import javax.ws.rs.client.Entity;\r
+import javax.ws.rs.client.Invocation;\r
+import javax.ws.rs.client.ResponseProcessingException;\r
+import javax.ws.rs.client.WebTarget;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import org.onap.optf.cmso.common.BasicAuthenticatorFilter;\r
+import org.onap.optf.cmso.common.CMSStatusEnum;\r
+import org.onap.optf.cmso.common.CmHelpers;\r
+import org.onap.optf.cmso.common.LogMessages;\r
+import org.onap.optf.cmso.common.PropertiesManagement;\r
+import org.onap.optf.cmso.filters.CMSOClientFilters;\r
+import org.onap.optf.cmso.model.ChangeManagementSchedule;\r
+import org.onap.optf.cmso.model.Schedule;\r
+import org.onap.optf.cmso.model.dao.ChangeManagementGroupDAO;\r
+import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;\r
+import org.onap.optf.cmso.model.dao.ScheduleDAO;\r
+import org.onap.optf.cmso.service.rs.models.CmDomainDataEnum;\r
+import org.onap.optf.cmso.ticketmgt.TmClient;\r
+import org.onap.optf.cmso.wf.bean.WfChangeManagementResponse;\r
+import org.onap.optf.cmso.wf.bean.WfVidCmResponse;\r
+import org.quartz.SchedulerException;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.core.env.Environment;\r
+import org.springframework.stereotype.Component;\r
+import org.springframework.transaction.annotation.Transactional;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+import com.fasterxml.jackson.databind.JsonNode;\r
+import com.fasterxml.jackson.databind.ObjectMapper;\r
+\r
+@Component\r
+public class CMSOClient {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(CMSOClient.class);\r
+ private static EELFLogger metrics = EELFManager.getInstance().getMetricsLogger();\r
+ private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();\r
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+\r
+ @Autowired\r
+ ChangeManagementScheduleDAO cmScheduleDAO;\r
+\r
+ @Autowired\r
+ ChangeManagementGroupDAO cmGroupDAO;\r
+\r
+ @Autowired\r
+ ScheduleDAO scheduleDAO;\r
+\r
+ @Autowired\r
+ Environment env;\r
+\r
+ @Autowired\r
+ PropertiesManagement pm;\r
+\r
+ @Autowired\r
+ TmClient tmClient;\r
+\r
+ public void dispatch(ChangeManagementSchedule cmSchedule, Schedule schedule) {\r
+ try {\r
+\r
+ String url = env.getProperty("so.url");\r
+ if (!url.endsWith("/"))\r
+ url += "/";\r
+ url = url + "schedule/" + cmSchedule.getVnfName();\r
+ String callbackData = CmHelpers.getDomainData(schedule, CmDomainDataEnum.CallbackData);\r
+ String user = env.getProperty("so.user", "");\r
+ String pass = pm.getProperty("so.pass", "");\r
+ Client client = ClientBuilder.newClient();\r
+ if (!user.equals(""))\r
+ client.register(new BasicAuthenticatorFilter(user, pass));\r
+ client.register(new CMSOClientFilters());\r
+ WebTarget target = client.target(url);\r
+ ObjectMapper om = new ObjectMapper();\r
+ JsonNode jsonEntity = om.readTree(callbackData);\r
+ Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);\r
+ try {\r
+ Response response = invocationBuilder.post(Entity.json(jsonEntity));\r
+ switch (response.getStatus()) {\r
+ case 201: {\r
+ debug.debug("Response status=" + response.getStatus());\r
+ // Push the state up to the schedule.\r
+ processScheduleResponse(cmSchedule, schedule, response);\r
+ break;\r
+ }\r
+ case 200: {\r
+ debug.debug("Response status=" + response.getStatus());\r
+ // Push the state up to the schedule.\r
+ processScheduleResponse200(cmSchedule, schedule, response);\r
+ break;\r
+ }\r
+ case 400: // Bad request\r
+ case 500:\r
+ default: {\r
+ errors.error(LogMessages.UNEXPECTED_RESPONSE.toString(), "VID", response.getStatus(),\r
+ response.toString());\r
+ cmSchedule.setStatus(CMSStatusEnum.SchedulingFailed.toString());\r
+ cmSchedule.setStatusMessage(response.toString());\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ // No sense in retrying. These are time sensitive actions\r
+ catch (ResponseProcessingException e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ cmSchedule.setStatus(CMSStatusEnum.SchedulingFailed.toString());\r
+ cmSchedule.setStatusMessage(e.toString());\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+\r
+ } catch (ProcessingException e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ cmSchedule.setStatus(CMSStatusEnum.SchedulingFailed.toString());\r
+ cmSchedule.setStatusMessage(e.toString());\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ }\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ cmSchedule.setStatus(CMSStatusEnum.SchedulingFailed.toString());\r
+ cmSchedule.setStatusMessage(e.toString());\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ }\r
+ }\r
+\r
+ private void processScheduleResponse(ChangeManagementSchedule cmSchedule, Schedule schedule, Response response)\r
+ throws SchedulerException {\r
+ WfChangeManagementResponse resp = response.readEntity(WfChangeManagementResponse.class);\r
+ for (WfVidCmResponse cmResponse : resp.getCmResponses()) {\r
+ if (cmResponse.getVnfName().equals(cmSchedule.getVnfName())) {\r
+ cmSchedule.setStatus(CMSStatusEnum.Triggered.toString());\r
+ cmSchedule.setDispatchTimeMillis(System.currentTimeMillis());\r
+ cmSchedule.setMsoRequestId(cmResponse.getOrchestratorRequestId());\r
+ // Push the state up to the schedule.\r
+ updateTicket(cmSchedule, schedule);\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ return;\r
+ }\r
+ }\r
+ cmSchedule.setStatus(CMSStatusEnum.SchedulingFailed.toString());\r
+ cmSchedule.setStatusMessage("Response did not contain vnfName=" + cmSchedule.getVnfName());\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ }\r
+\r
+ private void processScheduleResponse200(ChangeManagementSchedule cmSchedule, Schedule schedule, Response response)\r
+ throws SchedulerException {\r
+\r
+ JsonNode node = response.readEntity(JsonNode.class);\r
+ log.info("Message returned from VID callback: " + node.toString());\r
+ JsonNode status = node.get("status");\r
+ Integer msoStatus = status.asInt();\r
+ JsonNode entity = node.get("entity");\r
+ if (msoStatus == 202) {\r
+ JsonNode rr = entity.get("requestReferences");\r
+ if (rr != null) {\r
+ JsonNode requestId = rr.get("requestId");\r
+ if (requestId != null) {\r
+ cmSchedule.setStatus(CMSStatusEnum.Triggered.toString());\r
+ cmSchedule.setDispatchTimeMillis(System.currentTimeMillis());\r
+ cmSchedule.setMsoRequestId(requestId.asText());\r
+ // Push the state up to the schedule.\r
+ updateTicket(cmSchedule, schedule);\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ cmSchedule.setStatus(CMSStatusEnum.SchedulingFailed.toString());\r
+ cmSchedule.setStatusMessage(node.toString());\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ }\r
+\r
+ private void updateTicket(ChangeManagementSchedule cmSchedule, Schedule schedule) {\r
+ try {\r
+ String changeId = cmSchedule.getTmChangeId();\r
+ if (changeId != null && !changeId.equals(""))\r
+ tmClient.updateTicket(schedule, cmSchedule, changeId);\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ }\r
+ }\r
+\r
+ @Transactional\r
+ public void updateScheduleStatus(ChangeManagementSchedule cmSchedule, Schedule schedule) {\r
+ cmScheduleDAO.save(cmSchedule);\r
+ if (schedule != null)\r
+ scheduleDAO.save(schedule);\r
+\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.dispatcher;\r
+\r
+import java.util.Map;\r
+import javax.ws.rs.client.Client;\r
+import javax.ws.rs.client.ClientBuilder;\r
+import javax.ws.rs.client.Invocation;\r
+import javax.ws.rs.client.WebTarget;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import org.onap.optf.cmso.common.BasicAuthenticatorFilter;\r
+import org.onap.optf.cmso.common.LogMessages;\r
+import org.onap.optf.cmso.common.Mdc;\r
+import org.onap.optf.cmso.common.PropertiesManagement;\r
+import org.onap.optf.cmso.eventq.DispatchedEventList;\r
+import org.onap.optf.cmso.model.dao.ChangeManagementGroupDAO;\r
+import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;\r
+import org.onap.optf.cmso.model.dao.ScheduleDAO;\r
+import org.onap.optf.cmso.ticketmgt.TmClient;\r
+import org.quartz.DisallowConcurrentExecution;\r
+import org.quartz.Job;\r
+import org.quartz.JobExecutionContext;\r
+import org.quartz.JobExecutionException;\r
+import org.quartz.SchedulerException;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.core.env.Environment;\r
+import org.springframework.stereotype.Component;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+\r
+/**\r
+ * This is the Quartz Job that is run to send the workflow to VID for execution\r
+ * \r
+ *\r
+ */\r
+@Component\r
+@DisallowConcurrentExecution\r
+public class CmJob implements Job {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(CmJob.class);\r
+ private static EELFLogger metrics = EELFManager.getInstance().getMetricsLogger();\r
+ private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();\r
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+\r
+ @Autowired\r
+ CMSOClient vidClient;\r
+\r
+ @Autowired\r
+ ChangeManagementScheduleDAO cmScheduleDAO;\r
+\r
+ @Autowired\r
+ ChangeManagementGroupDAO cmGroupDAO;\r
+\r
+ @Autowired\r
+ ScheduleDAO scheduleDAO;\r
+\r
+ @Autowired\r
+ TmClient tmClient;\r
+\r
+ @Autowired\r
+ PropertiesManagement pm;\r
+\r
+ @Autowired\r
+ Environment env;\r
+\r
+ @Autowired\r
+ DispatchedEventList dispatchedEventList;\r
+\r
+ @Override\r
+ public void execute(JobExecutionContext context) throws JobExecutionException {\r
+ Mdc.quartzJobBegin(context);\r
+ debug.debug(LogMessages.CM_JOB, "Entered");\r
+ Integer id = context.getJobDetail().getJobDataMap().getInt("key");\r
+ try {\r
+ // Hand this off to a transactional service\r
+ loopback(id);\r
+ } catch (Exception e) {\r
+ log.warn("Unexpected exception", e);\r
+ } finally {\r
+ dispatchedEventList.remove(id);\r
+ }\r
+ debug.debug(LogMessages.CM_JOB, "Exited");\r
+ }\r
+\r
+ public void loopback(Integer id) {\r
+ Map<String, String> mdcSave = Mdc.save();\r
+ try {\r
+ String url = env.getProperty("cmso.dispatch.url", "http://localhost:8089");\r
+ String path = env.getProperty("cmso.dispatch.schedule.path", "/cmso/dispatch/schedule/");\r
+ url = url + path + id;\r
+ String user = env.getProperty("mechid.user", "");\r
+ String pass = pm.getProperty("mechid.pass", "");\r
+ Client client = ClientBuilder.newClient();\r
+ client.register(new BasicAuthenticatorFilter(user, pass));\r
+ WebTarget target = client.target(url);\r
+ Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);\r
+ Response response = null;\r
+ try {\r
+ Mdc.metricStart(id.toString(), url);\r
+ response = invocationBuilder.get();\r
+ Mdc.metricEnd(response);\r
+ metrics.info(LogMessages.CM_JOB, id.toString());\r
+ switch (response.getStatus()) {\r
+ case 200:\r
+ log.info("Returned from dispatch call");\r
+ break;\r
+ case 400: // Bad request\r
+ default: {\r
+\r
+ throw new SchedulerException(\r
+ "Invalid return from dispach service: " + url + " : " + response.toString());\r
+ }\r
+ }\r
+ } catch (Exception e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ }\r
+ } catch (Exception e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ } finally {\r
+ Mdc.restore(mdcSave);\r
+ }\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.dispatcher;\r
+\r
+import java.net.InetAddress;\r
+import java.util.Date;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+import org.onap.optf.cmso.common.CMSStatusEnum;\r
+import org.onap.optf.cmso.common.LogMessages;\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.ChangeManagementGroupDAO;\r
+import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;\r
+import org.onap.optf.cmso.model.dao.ScheduleDAO;\r
+import org.onap.optf.cmso.ticketmgt.TmClient;\r
+import org.onap.optf.cmso.ticketmgt.bean.TmApprovalStatusEnum;\r
+import org.onap.optf.cmso.ticketmgt.bean.TmChangeInfo;\r
+import org.onap.optf.cmso.ticketmgt.bean.TmStatusEnum;\r
+import org.quartz.JobExecutionException;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.core.env.Environment;\r
+import org.springframework.stereotype.Component;\r
+import org.springframework.transaction.annotation.Transactional;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+import com.att.eelf.i18n.EELFResourceManager;\r
+\r
+/**\r
+ * This is the service used to dispatch a job COuld not get QuartzJobBean to\r
+ * be @Transactional\r
+ *\r
+ */\r
+@Component\r
+public class DispatchJob {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(DispatchJob.class);\r
+ private static EELFLogger metrics = EELFManager.getInstance().getMetricsLogger();\r
+ private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();\r
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+\r
+ @Autowired\r
+ CMSOClient vidClient;\r
+\r
+ @Autowired\r
+ ChangeManagementScheduleDAO cmScheduleDAO;\r
+\r
+ @Autowired\r
+ ChangeManagementGroupDAO cmGroupDAO;\r
+\r
+ @Autowired\r
+ ScheduleDAO scheduleDAO;\r
+\r
+ @Autowired\r
+ TmClient tmClient;\r
+\r
+ @Autowired\r
+ Environment env;\r
+\r
+ public void execute(Integer id) throws JobExecutionException {\r
+ debug.debug(LogMessages.CM_JOB, "Entered");\r
+ try {\r
+ // No other instance can read this cmso until we are done.\r
+ ChangeManagementSchedule cmSchedule = cmScheduleDAO.lockOne(id);\r
+ cmSchedule.setDispatcherInstance(InetAddress.getLocalHost().getHostAddress());\r
+ ChangeManagementGroup group = cmGroupDAO.findById(cmSchedule.getChangeManagementGroupsId()).orElse(null);\r
+ if (group != null) {\r
+ Schedule schedule = scheduleDAO.findById(group.getSchedulesId()).orElse(null);\r
+ if (schedule != null) {\r
+ schedule.setStatus(CMSStatusEnum.NotificationsInitiated.toString());\r
+ if (safeToDispatch(cmSchedule, schedule))\r
+ vidClient.dispatch(cmSchedule, schedule);\r
+ }\r
+ }\r
+\r
+ } catch (Exception e) {\r
+ log.warn("Unexpected exception", e);\r
+ }\r
+ debug.debug(LogMessages.CM_JOB, "Exited");\r
+\r
+ }\r
+\r
+ private boolean safeToDispatch(ChangeManagementSchedule cmSchedule, Schedule schedule) {\r
+\r
+ Integer leadTime = env.getProperty("cmso.cm.dispatch.lead.time.ms", Integer.class, 1000);\r
+ Boolean scheduleImmediateEnabled = env.getProperty("cmso.cm.dispatch.immediate.enabled", Boolean.class, false);\r
+\r
+ // *******************************************************************\r
+ // SHould we read with a lock to avoid race condition?\r
+ // Not sure there is any real value to that at the moment.\r
+ //\r
+\r
+ // *******************************************************************\r
+ // Validate that the state is accurate.\r
+ // Another instance may have dispatched\r
+ Long startTime = cmSchedule.getStartTimeMillis();\r
+ if (!cmSchedule.getStatus().equals(CMSStatusEnum.Scheduled.toString())\r
+ && !cmSchedule.getStatus().equals(CMSStatusEnum.ScheduledImmediate.toString())) {\r
+ log.info("Attempt to dispatch an event that is in the incorrect state scheduleId={0}, vnf={1}, status={2}",\r
+ schedule.getScheduleId(), cmSchedule.getVnfName(), cmSchedule.getStatus());\r
+ return false;\r
+ }\r
+\r
+ // *******************************************************************\r
+ //\r
+ // Validate ticket is still active with tm\r
+ //\r
+ // TODO\r
+ if (cmSchedule.getTmChangeId() != null && !cmSchedule.getTmChangeId().equals("")) {\r
+ if (!isChangeApproved(schedule, cmSchedule, scheduleImmediateEnabled)) {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ // *******************************************************************\r
+ //\r
+ // If this is schedule immediate. Dispatch it!\r
+ //\r
+ if (cmSchedule.getFinishTimeMillis() == null) {\r
+ if (scheduleImmediateEnabled) {\r
+ debug.info("Dispatching an immediate request" + cmSchedule.getVnfName());\r
+ return true;\r
+ } else {\r
+ // THis should not happen. If schedule immediate is not enables, it will fail\r
+ // ticket approval check.\r
+ // ... If we see this, it is a bug...\r
+ String message = "Attempt to schedule immediate when immmediate scheduling is disabled: "\r
+ + cmSchedule.getVnfName();\r
+ log.info(message);\r
+ cmSchedule.setStatus(CMSStatusEnum.SchedulingFailed.toString());\r
+ cmSchedule.setStatusMessage(message);\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ return false;\r
+ }\r
+ }\r
+\r
+ // *******************************************************************\r
+ //\r
+ // Validate that event is not past due. Time sensitive. Do not dispatch\r
+ // Do not account for lead time. This should be inconsequential, maybe????\r
+ //\r
+ long now = System.currentTimeMillis();\r
+ long startMillis = startTime;\r
+ if (now > startMillis) {\r
+ String message = EELFResourceManager.format(LogMessages.SCHEDULE_PAST_DUE, schedule.getScheduleId(),\r
+ cmSchedule.getVnfName(), new Date(now).toString(), new Date(startMillis).toString());\r
+ log.info(message);\r
+\r
+ cmSchedule.setStatus(CMSStatusEnum.PastDue.toString());\r
+ cmSchedule.setStatusMessage(message);\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ return false;\r
+ }\r
+\r
+ // *******************************************************************\r
+ // (Sleep until actual dispatch time...)\r
+ // leadTime allows for preparing call to VID to the start of workflow.\r
+ long sleep = (startMillis - leadTime) - System.currentTimeMillis();\r
+ if (sleep > 0l) {\r
+ try {\r
+ Thread.sleep(sleep);\r
+ } catch (Exception e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ private boolean isChangeApproved(Schedule schedule, ChangeManagementSchedule cmSchedule,\r
+ Boolean scheduleImmediateEnabled) {\r
+ String message = "";\r
+ // ChangeManagementGroup group =\r
+ // cmGroupDAO.findById(cmSchedule.getChangeManagementGroupsId()).orElse(null);\r
+ // Long startDate = group.getStartTimeMillis();\r
+ Set<String> vnfNames = new HashSet<String>();\r
+ vnfNames.add(cmSchedule.getVnfName());\r
+ TmChangeInfo info = tmClient.getChangeTicket(cmSchedule.getTmChangeId());\r
+ String otherStatus = env.getProperty("vtm.status", "");\r
+ String otherApprovalStatus = env.getProperty("vtm.approvalStatus", "");\r
+ String statusConfig = env.getProperty("vtm.approvalStatus",\r
+ TmApprovalStatusEnum.Approved.toString() + "|" + TmStatusEnum.Scheduled.toString());\r
+ String[] statusList = statusConfig.split(",");\r
+ if (info != null) {\r
+ String approvalStatus = info.getApprovalStatus();\r
+ String status = info.getStatus();\r
+ debug.debug("Retrieved changeid=" + info.getChangeId() + " approvlStatus=" + approvalStatus + " status="\r
+ + status);\r
+ String actualStatus = approvalStatus + "|" + status;\r
+ for (String okStatus : statusList) {\r
+ if (actualStatus.equals(okStatus)) {\r
+ return true;\r
+ }\r
+ }\r
+ // Look for proper state for immediate VNFs\r
+ debug.debug("Retrieved changeid=" + info.getChangeId() + " otherApprovlStatus=" + otherApprovalStatus\r
+ + " status=" + otherStatus);\r
+ if (cmSchedule.getStartTime() == null && scheduleImmediateEnabled) {\r
+ debug.debug("Ignoring status on immediate schedule: " + cmSchedule.getTmChangeId());\r
+ return true;\r
+ }\r
+ message = EELFResourceManager.format(LogMessages.CM_TICKET_NOT_APPROVED, schedule.getScheduleId(),\r
+ cmSchedule.getVnfName(), cmSchedule.getTmChangeId(), status, approvalStatus);\r
+ log.warn(message);\r
+ } else {\r
+ message = EELFResourceManager.format(LogMessages.UNABLE_TO_LOCATE_CHANGE_RECORD, schedule.getScheduleId(),\r
+ cmSchedule.getVnfName(), cmSchedule.getTmChangeId());\r
+ errors.error(message);\r
+ }\r
+ cmSchedule.setStatus(CMSStatusEnum.SchedulingFailed.toString());\r
+ cmSchedule.setStatusMessage(message);\r
+ updateScheduleStatus(cmSchedule, schedule);\r
+ return false;\r
+ }\r
+\r
+ @Transactional\r
+ public void updateScheduleStatus(ChangeManagementSchedule cmSchedule, Schedule schedule) {\r
+ cmScheduleDAO.save(cmSchedule);\r
+ scheduleDAO.save(schedule);\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.dispatcher.rs;\r
+\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.ws.rs.GET;\r
+import javax.ws.rs.Path;\r
+import javax.ws.rs.PathParam;\r
+import javax.ws.rs.Produces;\r
+import javax.ws.rs.core.Context;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import javax.ws.rs.core.UriInfo;\r
+import io.swagger.annotations.Api;\r
+import io.swagger.annotations.ApiOperation;\r
+import io.swagger.annotations.ApiParam;\r
+import io.swagger.annotations.ApiResponse;\r
+import io.swagger.annotations.ApiResponses;\r
+\r
+@Api\r
+@Path("/dispatch")\r
+@Produces({MediaType.APPLICATION_JSON})\r
+public interface DispacherService {\r
+\r
+ // ******************************************************************\r
+ @GET\r
+ @Path("/schedule/{id}")\r
+ @Produces({MediaType.APPLICATION_JSON})\r
+ @ApiOperation(value = "", notes = "Does dispsatch of provided cm schedule id.", response = Integer.class)\r
+ @ApiResponses(\r
+ value = {@ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Request failed")})\r
+ public Response dispatchSchedule(@ApiParam(value = "Identifier", allowMultiple = false) @PathParam("id") Integer id,\r
+ @Context UriInfo uri, @Context HttpServletRequest request);\r
+\r
+ // ******************************************************************\r
+ @GET\r
+ @Path("/optimizer/{id}")\r
+ @Produces({MediaType.APPLICATION_JSON})\r
+ @ApiOperation(value = "", notes = "Does dispsatch of provided cm schedule id.", response = Integer.class)\r
+ @ApiResponses(\r
+ value = {@ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Request failed")})\r
+ public Response dispatchOptimizer(\r
+ @ApiParam(value = "Identifier", allowMultiple = false) @PathParam("id") Integer id, @Context UriInfo uri,\r
+ @Context HttpServletRequest request);\r
+\r
+ // ******************************************************************\r
+ @GET\r
+ @Path("/schedulestatus/{id}")\r
+ @Produces({MediaType.APPLICATION_JSON})\r
+ @ApiOperation(value = "", notes = "Does dispsatch of provided schedule id.", response = Integer.class)\r
+ @ApiResponses(\r
+ value = {@ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Request failed")})\r
+ public Response dispatchScheduleStatus(\r
+ @ApiParam(value = "Identifier", allowMultiple = false) @PathParam("id") Integer id, @Context UriInfo uri,\r
+ @Context HttpServletRequest request);\r
+\r
+ // ******************************************************************\r
+ @GET\r
+ @Path("/sostatus/{id}")\r
+ @Produces({MediaType.APPLICATION_JSON})\r
+ @ApiOperation(value = "", notes = "Does dispsatch of provided cm schedule id.", response = Integer.class)\r
+ @ApiResponses(\r
+ value = {@ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Request failed")})\r
+ public Response dispatchSoStatus(@ApiParam(value = "Identifier", allowMultiple = true) @PathParam("id") Integer id,\r
+ @Context UriInfo uri, @Context HttpServletRequest request);\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.dispatcher.rs;\r
+\r
+import java.util.UUID;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.ws.rs.core.Response;\r
+import javax.ws.rs.core.UriInfo;\r
+import org.onap.optf.cmso.common.LogMessages;\r
+import org.onap.optf.cmso.common.Mdc;\r
+import org.onap.optf.cmso.dispatcher.DispatchJob;\r
+import org.onap.optf.cmso.optimizer.CMSOptimizerClient;\r
+import org.onap.optf.cmso.sostatus.MsoStatusClient;\r
+import org.onap.optf.cmso.ticketmgt.TmStatusClient;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.stereotype.Controller;\r
+import org.springframework.transaction.annotation.Transactional;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+\r
+@Controller\r
+public class DispatcherServiceImpl implements DispacherService {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(DispatcherServiceImpl.class);\r
+ private static EELFLogger audit = EELFManager.getInstance().getAuditLogger();\r
+ private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();\r
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+\r
+ @Autowired\r
+ DispatchJob dispatchJob;\r
+\r
+ @Autowired\r
+ CMSOptimizerClient sniroClient;\r
+\r
+ @Autowired\r
+ TmStatusClient tmStatusClient;\r
+\r
+ @Autowired\r
+ MsoStatusClient msoStatusClient;\r
+\r
+ @Override\r
+ @Transactional\r
+ public Response dispatchSchedule(Integer id, UriInfo uri, HttpServletRequest request) {\r
+ Mdc.begin(request, UUID.randomUUID().toString());\r
+ log.info("dispatchVID entered {}", id);\r
+ try {\r
+ dispatchJob.execute(id);\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e.getMessage());\r
+ debug.error(e.getMessage(), e);\r
+ }\r
+ Response response = Response.ok().build();\r
+ Mdc.end(response);\r
+ audit.info("dispatchVID");\r
+ return response;\r
+ }\r
+\r
+ @Override\r
+ @Transactional\r
+ public Response dispatchOptimizer(Integer id, UriInfo uri, HttpServletRequest request) {\r
+ Mdc.begin(request, UUID.randomUUID().toString());\r
+ log.info("Dispatch.exec entered {}", id);\r
+ try {\r
+ sniroClient.scheduleSniroOptimization(id);\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e.getMessage());\r
+ debug.error(e.getMessage(), e);\r
+ }\r
+ Response response = Response.ok().build();\r
+ Mdc.end(response);\r
+ audit.info("dispatchSNIRO");\r
+ return response;\r
+ }\r
+\r
+ @Override\r
+ @Transactional\r
+ public Response dispatchScheduleStatus(Integer id, UriInfo uri, HttpServletRequest request) {\r
+ Mdc.begin(request, UUID.randomUUID().toString());\r
+ log.info("Dispatch.exec entered {}", id);\r
+ try {\r
+ tmStatusClient.checkStatus(id);\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e.getMessage());\r
+ debug.error(e.getMessage(), e);\r
+ }\r
+ Response response = Response.ok().build();\r
+ Mdc.end(response);\r
+ audit.info("dispatchScheduleStatus");\r
+ return response;\r
+ }\r
+\r
+ @Override\r
+ @Transactional\r
+ public Response dispatchSoStatus(Integer id, UriInfo uri, HttpServletRequest request) {\r
+ Mdc.begin(request, UUID.randomUUID().toString());\r
+ log.info("Dispatch.exec entered {}", id);\r
+ try {\r
+ msoStatusClient.execute(id);\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e.getMessage());\r
+ debug.error(e.getMessage(), e);\r
+ }\r
+ Response response = Response.ok().build();\r
+ Mdc.end(response);\r
+ audit.info("dispatchMsoStatus");\r
+ return response;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.eventq;\r
+\r
+import java.util.Date;\r
+import java.util.List;\r
+import org.onap.optf.cmso.common.CMSStatusEnum;\r
+import org.onap.optf.cmso.common.LogMessages;\r
+import org.onap.optf.cmso.dispatcher.CmJob;\r
+import org.onap.optf.cmso.model.ChangeManagementSchedule;\r
+import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;\r
+import org.quartz.JobBuilder;\r
+import org.quartz.JobDetail;\r
+import org.quartz.Trigger;\r
+import org.quartz.TriggerBuilder;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.core.env.Environment;\r
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;\r
+import org.springframework.stereotype.Component;\r
+import org.springframework.transaction.annotation.Transactional;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+\r
+/**\r
+ * This job will look for ChangeManagementSchedule approved jobs that are due\r
+ * within the next n intervals of this job and schedule them in as a Quartz\r
+ * CmJob to be dispatched. These ChangeManagementSchedule rows will be\r
+ * status=Queued The CmJob will confirm that the job is OK to be dispatched and\r
+ * set status=.... The next N intervals should be enough to ensure sluggish\r
+ * performance of this process does not miss events but does not exhaust\r
+ * memory....\r
+ */\r
+@Component\r
+public class CMSQueueJob {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(CMSQueueJob.class);\r
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+\r
+ @Autowired\r
+ ChangeManagementScheduleDAO cmScheduleDAO;\r
+\r
+ @Autowired\r
+ SchedulerFactoryBean qsScheduler;\r
+\r
+ @Autowired\r
+ Environment env;\r
+\r
+ @Autowired\r
+ DispatchedEventList dispatchedEventList;\r
+\r
+ public boolean queueImminentJobs() {\r
+ Integer interval = env.getProperty("cmso.cm.polling.job.interval.ms", Integer.class, 10000);\r
+ Integer lookahead = env.getProperty("cmso.cm.polling.job.lookahead.intervals", Integer.class, 5);\r
+ long now = System.currentTimeMillis();\r
+ Long endTime = now + (interval * lookahead);\r
+ List<ChangeManagementSchedule> schedules =\r
+ cmScheduleDAO.findByStatusAndEndTime(CMSStatusEnum.Scheduled.toString(), endTime);\r
+ if (schedules.size() == 0)\r
+ return false;\r
+ for (ChangeManagementSchedule schedule : schedules) {\r
+ try {\r
+ if (!dispatchedEventList.isAlreadyDispatched(schedule.getId())) {\r
+ scheduleCmJob(schedule);\r
+ dispatchedEventList.addToDispathcedEventList(schedule.getId());\r
+ }\r
+ } catch (org.quartz.SchedulerException e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ // WIll keep trying until it goes Past due\r
+ schedule.setStatus(CMSStatusEnum.Scheduled.toString());\r
+ schedule.setDispatcherInstance("");\r
+ updateScheduleStatus(schedule);\r
+ } catch (Exception e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ schedule.setStatus(CMSStatusEnum.Scheduled.toString());\r
+ schedule.setDispatcherInstance("");\r
+ updateScheduleStatus(schedule);\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public void scheduleCmJob(ChangeManagementSchedule schedule) throws org.quartz.SchedulerException {\r
+ //\r
+ Integer dispatherLeadTime = env.getProperty("cmso.cm.dispatcher.lead.time.ms", Integer.class, 5000);\r
+ long dispatchTime = 0;\r
+ Long startTime = schedule.getStartTimeMillis();\r
+\r
+ /// If startTIme is null, it is an immediate start\r
+ if (startTime != null)\r
+ dispatchTime = startTime - dispatherLeadTime;\r
+\r
+ JobDetail jobDetail = JobBuilder.newJob(CmJob.class).build();\r
+ jobDetail.getJobDataMap().put("key", schedule.getId());\r
+\r
+ TriggerBuilder<Trigger> tb = TriggerBuilder.newTrigger().forJob(jobDetail);\r
+\r
+ long now = System.currentTimeMillis();\r
+ if (now > dispatchTime)\r
+ tb.startNow();\r
+ else\r
+ tb.startAt(new Date(dispatchTime));\r
+ Trigger trigger = tb.build();\r
+ qsScheduler.getScheduler().scheduleJob(jobDetail, trigger);\r
+\r
+ }\r
+\r
+ @Transactional\r
+ public void updateScheduleStatus(ChangeManagementSchedule cmSchedule) {\r
+ cmScheduleDAO.save(cmSchedule);\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.eventq;\r
+\r
+import org.onap.optf.cmso.common.LogMessages;\r
+import org.onap.optf.cmso.common.Mdc;\r
+import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;\r
+import org.quartz.DisallowConcurrentExecution;\r
+import org.quartz.JobExecutionContext;\r
+import org.quartz.JobExecutionException;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.scheduling.quartz.QuartzJobBean;\r
+import org.springframework.stereotype.Component;\r
+import org.springframework.transaction.annotation.Transactional;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+\r
+/**\r
+ * This quartz job runs periodically to query the ChangeManagementSChedule table\r
+ * to create CmJobs to queue in quartx.\r
+ *\r
+ */\r
+@Component\r
+@DisallowConcurrentExecution\r
+public class CmQuartzJob extends QuartzJobBean {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(CmQuartzJob.class);\r
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+\r
+ @Autowired\r
+ CMSQueueJob qJob;\r
+\r
+ // This is not called directly. Using @Autowired to ensure that startup\r
+ // Runs before the fist invocation of executeInternal\r
+ @Autowired\r
+ CmQuartzJobStartup startup;\r
+\r
+ @Autowired\r
+ ChangeManagementScheduleDAO cmScheduleDAO;\r
+\r
+ @Override\r
+ @Transactional\r
+ protected void executeInternal(JobExecutionContext context) throws JobExecutionException {\r
+ Mdc.quartzJobBegin(context);\r
+ debug.debug(LogMessages.CM_QUARTZ_JOB, "Entered");\r
+\r
+ // This logic does not make sense in k8s since we cannot count on IP address\r
+ // as the dispatch.\r
+ // Need to understand how to requeue when instances go down while dispatching\r
+ // jobs\r
+ // between "Queued for Dispatch" and "Triggered"\r
+ // startup.startup(); // Runs once\r
+\r
+ // Turns out that this is not necessary, Quartz does what makes sense after all\r
+ // if (isStale(context))\r
+ // return;\r
+\r
+ try {\r
+\r
+ boolean moreToSchedule = true;\r
+ while (moreToSchedule) {\r
+ try {\r
+ moreToSchedule = qJob.queueImminentJobs();\r
+ } catch (Exception e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ moreToSchedule = false;\r
+ }\r
+ }\r
+\r
+ } catch (Exception e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ }\r
+ debug.debug(LogMessages.CM_QUARTZ_JOB, "Exited");\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.eventq;\r
+\r
+import java.net.InetAddress;\r
+import java.util.concurrent.atomic.AtomicBoolean;\r
+import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.stereotype.Component;\r
+import org.springframework.transaction.annotation.Transactional;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+\r
+/**\r
+ * This bean uses @AUtowired to ensure that it runs once at startup to reset all\r
+ * QueuedForDispatch rows that were in flight last time from this\r
+ * "dispatcherInstnace" shut down.\r
+ * \r
+ * Potentially, in a distributed environment, when a "dispatcherInstance"\r
+ * shutdown is detected by another instance, it can run this query to requeue\r
+ * these items. We are a long way from there.\r
+ * \r
+ * Chances are great that re-queued events will end up being Past Due events\r
+ * \r
+ */\r
+@Component\r
+public class CmQuartzJobStartup {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(CmQuartzJobStartup.class);\r
+\r
+ @Autowired\r
+ ChangeManagementScheduleDAO cmScheduleDAO;\r
+\r
+ private AtomicBoolean started = new AtomicBoolean(false);\r
+\r
+ public CmQuartzJobStartup() {\r
+\r
+ }\r
+\r
+ @Transactional\r
+ public void startup() {\r
+ try {\r
+ if (started.getAndSet(true))\r
+ return;\r
+ int rows = cmScheduleDAO.requeueQueuedForDispatch(InetAddress.getLocalHost().getHostAddress());\r
+ log.info("{0} QUeued For Dispatch rows have been requeued at startup", rows);\r
+ } catch (Exception e) {\r
+ log.error("Exception caught in requeueing Queued for DIspatch rows at startup", e);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.eventq;\r
+\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+import org.springframework.stereotype.Component;\r
+\r
+/**\r
+ * This class is used to avoid re-dispatching scheduled events until the status\r
+ * changes to either ???? or ???? Note that other instances of CM SCheduler may\r
+ * be dispatching this event, but only the first one to grab the lock will\r
+ * publish the event.\r
+ *\r
+ */\r
+@Component\r
+public class DispatchedEventList {\r
+\r
+ private Set<Integer> list = new HashSet<>();\r
+\r
+ public synchronized void addToDispathcedEventList(Integer id) {\r
+ list.add(id);\r
+ }\r
+\r
+ public synchronized void remove(Integer id) {\r
+ list.remove(id);\r
+ }\r
+\r
+ public synchronized boolean isAlreadyDispatched(Integer id) {\r
+ return list.contains(id);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.UUID;\r
+import javax.ws.rs.ProcessingException;\r
+import javax.ws.rs.client.Client;\r
+import javax.ws.rs.client.ClientBuilder;\r
+import javax.ws.rs.client.Entity;\r
+import javax.ws.rs.client.Invocation;\r
+import javax.ws.rs.client.ResponseProcessingException;\r
+import javax.ws.rs.client.WebTarget;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import org.onap.optf.cmso.common.BasicAuthenticatorFilter;\r
+import org.onap.optf.cmso.common.CMSStatusEnum;\r
+import org.onap.optf.cmso.common.LogMessages;\r
+import org.onap.optf.cmso.common.Mdc;\r
+import org.onap.optf.cmso.common.PropertiesManagement;\r
+import org.onap.optf.cmso.filters.CMSOClientFilters;\r
+import org.onap.optf.cmso.model.Schedule;\r
+import org.onap.optf.cmso.model.dao.ScheduleDAO;\r
+import org.onap.optf.cmso.optimizer.bean.CMOptimizerRequest;\r
+import org.onap.optf.cmso.optimizer.bean.CMRequestInfo;\r
+import org.onap.optf.cmso.optimizer.bean.CMSchedulingInfo;\r
+import org.onap.optf.cmso.optimizer.bean.CMVnfDetails;\r
+import org.onap.optf.cmso.service.rs.models.CMSInfo;\r
+import org.onap.optf.cmso.service.rs.models.ChangeWindowMessage;\r
+import org.onap.optf.cmso.service.rs.models.HealthCheckComponent;\r
+import org.onap.optf.cmso.service.rs.models.VnfDetailsMessage;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.core.env.Environment;\r
+import org.springframework.stereotype.Component;\r
+import org.springframework.transaction.annotation.Transactional;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+import com.fasterxml.jackson.databind.ObjectMapper;\r
+\r
+@Component\r
+public class CMSOptimizerClient {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(CMSOptimizerClient.class);\r
+ private static EELFLogger metrics = EELFManager.getInstance().getMetricsLogger();\r
+ private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();\r
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+\r
+ @Autowired\r
+ ScheduleDAO scheduleDAO;\r
+\r
+ @Autowired\r
+ Environment env;\r
+\r
+ @Autowired\r
+ PropertiesManagement pm;\r
+\r
+ public boolean scheduleSniroOptimization(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 username = env.getProperty("mechid.user");\r
+ Integer maxAttempts = env.getProperty("cmso.sniro.maxAttempts", Integer.class, 20);\r
+\r
+ // Ensure that only one cmso is requsting this call to SNIRO\r
+ Schedule schedule = scheduleDAO.lockOne(id);\r
+ if (!schedule.getStatus().equals(CMSStatusEnum.PendingSchedule.toString()))\r
+ return false;\r
+\r
+ String password = pm.getProperty("mechid.pass", "");\r
+ //\r
+ // Only 'successfully' process one schedule per invocation\r
+ // If a schedule attemp fails and it could be because of the data in the\r
+ // message, try the next one. We don't want bad data to\r
+ //\r
+ if (schedule.getOptimizerAttemptsToSchedule() >= maxAttempts) {\r
+ schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());\r
+ schedule.setOptimizerMessage("Maximum number of attempts exceeded " + maxAttempts);\r
+ updateScheduleStatus(schedule);\r
+ return true;\r
+ }\r
+ CMOptimizerRequest cmReq = new CMOptimizerRequest();\r
+ try {\r
+ CMSInfo info = reconstituteMessage(schedule);\r
+ if (info == null) {\r
+ return true;\r
+ }\r
+ buildRequest(cmReq, info, schedule, snirocallbackurl);\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());\r
+ schedule.setOptimizerMessage("Unexpected exception: " + e.getMessage());\r
+ updateScheduleStatus(schedule);\r
+ return true;\r
+ }\r
+\r
+ // This service will call SNIO for each PendingOptimiztion\r
+ // If the request is successfully scheduled in SNIRO, 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
+ 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
+ // commit of this transaction.\r
+ // SNIRO 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
+ log.info(LogMessages.OPTIMIZER_REQUEST, "Begin", schedule.getScheduleId(), snirourl);\r
+ Mdc.metricStart(schedule.getScheduleId(), snirourl);\r
+ Response response = invocationBuilder.post(Entity.json(cmReq));\r
+\r
+ Mdc.metricEnd(response);\r
+ metrics.info(LogMessages.OPTIMIZER_REQUEST, "End", schedule.getScheduleId(), snirourl);\r
+ log.info(LogMessages.OPTIMIZER_REQUEST, "End", schedule.getScheduleId(), snirourl);\r
+ switch (response.getStatus()) {\r
+ case 202:\r
+ debug.debug("Successfully scheduled optimization: " + schedule.getScheduleId());\r
+ // Scheduled with SNIRO\r
+ break;\r
+ case 400: // Bad request\r
+ {\r
+ schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
+ schedule.setOptimizerStatus("HTTP Status: " + response.getStatus());\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
+ // down.\r
+ int tries = schedule.getOptimizerAttemptsToSchedule();\r
+ tries++;\r
+ schedule.setOptimizerAttemptsToSchedule(tries);\r
+ updateScheduleStatus(schedule);\r
+ errors.error(LogMessages.OPTIMIZER_EXCEPTION, message);\r
+ return true;\r
+ }\r
+\r
+ case 500:\r
+ default: {\r
+ String message = response.readEntity(String.class);\r
+ // SHould probably track the number of retries.\r
+ schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
+ int tries = schedule.getOptimizerAttemptsToSchedule();\r
+ tries++;\r
+ schedule.setStatus(CMSStatusEnum.ScheduleFailed.toString());\r
+ schedule.setOptimizerAttemptsToSchedule(tries);\r
+ schedule.setOptimizerMessage(message);\r
+ updateScheduleStatus(schedule);\r
+ /// Got processing error response\r
+ // may be transient, wait for next cycle.\r
+ errors.error(LogMessages.OPTIMIZER_EXCEPTION, message);\r
+ // Wait until next cycle and try again.\r
+ return false;\r
+ }\r
+\r
+ }\r
+ //\r
+ return true;\r
+ } catch (ResponseProcessingException e) {\r
+ schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
+ schedule.setOptimizerStatus("Failed to parse SNIRO response");\r
+ schedule.setStatus(CMSStatusEnum.ScheduleFailed.toString());\r
+ // Need to understand the cause of this error. May be teh same as SNIRO down.\r
+ int tries = schedule.getOptimizerAttemptsToSchedule();\r
+ tries++;\r
+ schedule.setOptimizerAttemptsToSchedule(tries);\r
+ updateScheduleStatus(schedule);\r
+ // Getting invalid response from SNIRO.\r
+ // May be data related.\r
+ errors.error(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
+ schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
+ schedule.setStatus(CMSStatusEnum.PendingSchedule.toString());\r
+ updateScheduleStatus(schedule);\r
+ /// Cannot connect to SNIRO\r
+ errors.error(LogMessages.OPTIMIZER_EXCEPTION, e, e.getMessage());\r
+ // Wait until next cycle\r
+ return false;\r
+ }\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+\r
+ } finally {\r
+ Mdc.restore(mdcSave);\r
+ }\r
+ return false;\r
+ }\r
+\r
+ private void buildRequest(CMOptimizerRequest cmReq, CMSInfo info, Schedule schedule, String snirocallbackurl) {\r
+\r
+ // TODO: Need to get SNIRO to accept ChangeManagementSchedulingInfo\r
+ // This is to support 1707 SNIRO interface\r
+ CMRequestInfo reqInfo = cmReq.getRequestInfo();\r
+ CMSchedulingInfo schInfo = cmReq.getSchedulingInfo();\r
+\r
+ UUID uuid = UUID.randomUUID();\r
+ reqInfo.setCallbackUrl(snirocallbackurl);\r
+ reqInfo.setOptimizer(new String[] {"scheduling"});\r
+ reqInfo.setTransactionId(schedule.getOptimizerTransactionId());\r
+ reqInfo.setRequestId("CM-" + uuid.toString());\r
+ reqInfo.setSourceId("cmso");\r
+\r
+ String[] policyArray = new String[1];\r
+ policyArray[0] = info.getPolicyId();\r
+ schInfo.setPolicyId(policyArray);\r
+ schInfo.setAdditionalDurationInSecs(info.getAdditionalDurationInSeconds());\r
+ schInfo.setConcurrencyLimit(info.getConcurrencyLimit());\r
+ schInfo.setNormalDurationInSecs(info.getNormalDurationInSeconds());\r
+ schInfo.setScheduleId(schedule.getScheduleId());\r
+ List<CMVnfDetails> list = new ArrayList<CMVnfDetails>();\r
+ String startTime = "";\r
+ String endTime = "";\r
+\r
+ for (VnfDetailsMessage vnf : info.getVnfDetails()) {\r
+ String groupId = vnf.getGroupId();\r
+ for (String node : vnf.getNode()) {\r
+ CMVnfDetails d = new CMVnfDetails(vnf.getGroupId());\r
+ d.setNode(node);\r
+ list.add(d);\r
+ }\r
+ if (startTime.equals("")) {\r
+ // Only supporting 1 CW for 1710\r
+ ChangeWindowMessage cw = vnf.getChangeWindow().get(0);\r
+ startTime = cw.getStartTime();\r
+ endTime = cw.getEndTime();\r
+ }\r
+ }\r
+ schInfo.setStartTime(startTime);\r
+ schInfo.setEndTime(endTime);\r
+ schInfo.setVnfDetails(list.toArray(new CMVnfDetails[list.size()]));\r
+\r
+ }\r
+\r
+ private CMSInfo reconstituteMessage(Schedule schedule) {\r
+ String request = schedule.getScheduleInfo();\r
+ ObjectMapper om = new ObjectMapper();\r
+ try {\r
+ CMSInfo info = om.readValue(request, CMSInfo.class);\r
+ return info;\r
+ } catch (Exception e) {\r
+ // Parsing should work here because this was a toString on the original object.\r
+ // We may have an issue when upgrading....\r
+ // Perhaps We create ChangeManagementSchedulingInfoV1, ...V2, etc.\r
+ // ANd try them one after another....\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, "Unable to parse message. Format changed?");\r
+ schedule.setOptimizerStatus("Failed to parse SNIRO request");\r
+ schedule.setOptimizerDateTimeMillis(System.currentTimeMillis());\r
+ schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());\r
+ scheduleDAO.save(schedule);\r
+ }\r
+ return null;\r
+ }\r
+\r
+ @Transactional\r
+ public void updateScheduleStatus(Schedule schedule) {\r
+ scheduleDAO.save(schedule);\r
+\r
+ }\r
+\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
+ String username = env.getProperty("mechid.user");\r
+ String password = pm.getProperty("mechid.pass", "");\r
+ hcc.setUrl(snirourl);\r
+ try {\r
+ UUID uuid = UUID.randomUUID();\r
+ // Build a bogus request should fail policy validation\r
+ CMRequestInfo requestInfo = new CMRequestInfo();\r
+ CMSchedulingInfo schedulingInfo = new CMSchedulingInfo();\r
+ CMOptimizerRequest cmReq = new CMOptimizerRequest();\r
+ cmReq.setRequestInfo(requestInfo);\r
+ cmReq.setSchedulingInfo(schedulingInfo);\r
+ requestInfo.setCallbackUrl("http://callbackurl.onap.org:8080/healthcheck");\r
+ requestInfo.setOptimizer(new String[] {"scheduling"});\r
+ requestInfo.setTransactionId(uuid.toString());\r
+ requestInfo.setRequestId("CM-" + uuid.toString());\r
+ requestInfo.setSourceId("cmso");\r
+ schedulingInfo.setAdditionalDurationInSecs(10);\r
+ schedulingInfo.setConcurrencyLimit(10);\r
+ schedulingInfo.setNormalDurationInSecs(10);\r
+ schedulingInfo.setPolicyId(new String[] {"healthcheck"});\r
+ schedulingInfo.setScheduleId(uuid.toString());\r
+ CMVnfDetails details = new CMVnfDetails();\r
+ details.setGroupId("");\r
+ details.setNode("healtcheck");\r
+ schedulingInfo.setVnfDetails(new CMVnfDetails[] {details});\r
+ schedulingInfo.setStartTime("2017-12-11T15:23:24Z");\r
+ schedulingInfo.setEndTime("2017-12-11T22:23:24Z");\r
+\r
+ Client client = ClientBuilder.newClient();\r
+ client.register(new BasicAuthenticatorFilter(username, password));\r
+ WebTarget sniroTarget = client.target(snirourl);\r
+ Invocation.Builder invocationBuilder = sniroTarget.request(MediaType.APPLICATION_JSON);\r
+ debug.debug("SNIRO url / user: " + snirourl + " / " + username);\r
+ log.info(LogMessages.OPTIMIZER_REQUEST, "Begin", "healthcheck", snirourl);\r
+ Mdc.metricStart("healthcjeck", snirourl);\r
+ Response response = invocationBuilder.post(Entity.json(cmReq));\r
+ Mdc.metricEnd(response);\r
+ metrics.info(LogMessages.OPTIMIZER_REQUEST, "End", "healthcheck", snirourl);\r
+ log.info(LogMessages.OPTIMIZER_REQUEST, "End", "healthcheck", snirourl);\r
+ String message = response.getStatus() + ":" + response.readEntity(String.class);\r
+ switch (response.getStatus()) {\r
+ case 202:\r
+ debug.debug("Successful SNIRO 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
+ hcc.setHealthy(true);\r
+ hcc.setStatus("OK");\r
+ } else {\r
+ hcc.setStatus(message);\r
+ }\r
+ break;\r
+ default:\r
+ hcc.setStatus(message);\r
+ break;\r
+ }\r
+ } catch (Exception e) {\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e.toString());\r
+ hcc.setStatus(e.toString());\r
+ } finally {\r
+ Mdc.restore(mdcSave);\r
+ }\r
+ return hcc;\r
+\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer;\r
+\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+import org.springframework.stereotype.Component;\r
+\r
+/**\r
+ * This class is used to avoid re-dispatching scheduled events until the status\r
+ * changes to either ???? or ???? Note that other instances of CM SCheduler may\r
+ * be dispatching this event, but only the first one to grab the lock will\r
+ * publish the event.\r
+ *\r
+ */\r
+@Component\r
+public class DispatchedOptimizerList {\r
+\r
+ private Set<Integer> list = new HashSet<>();\r
+\r
+ public synchronized void addToDispathcedEventList(Integer id) {\r
+ list.add(id);\r
+ }\r
+\r
+ public synchronized void remove(Integer id) {\r
+ list.remove(id);\r
+ }\r
+\r
+ public synchronized boolean isAlreadyDispatched(Integer id) {\r
+ return list.contains(id);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+import javax.ws.rs.client.Client;\r
+import javax.ws.rs.client.ClientBuilder;\r
+import javax.ws.rs.client.Invocation;\r
+import javax.ws.rs.client.WebTarget;\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import org.onap.optf.cmso.common.BasicAuthenticatorFilter;\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.Mdc;\r
+import org.onap.optf.cmso.common.PropertiesManagement;\r
+import org.onap.optf.cmso.model.Schedule;\r
+import org.onap.optf.cmso.model.dao.ScheduleDAO;\r
+import org.quartz.DisallowConcurrentExecution;\r
+import org.quartz.JobExecutionContext;\r
+import org.quartz.JobExecutionException;\r
+import org.quartz.SchedulerException;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.core.env.Environment;\r
+import org.springframework.scheduling.quartz.QuartzJobBean;\r
+import org.springframework.stereotype.Component;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+\r
+@Component\r
+@DisallowConcurrentExecution\r
+public class OptimizerQuartzJob extends QuartzJobBean {\r
+ private static EELFLogger log = EELFManager.getInstance().getLogger(OptimizerQuartzJob.class);\r
+ private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+ private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();\r
+ private static EELFLogger metrics = EELFManager.getInstance().getMetricsLogger();\r
+\r
+ @Autowired\r
+ ScheduleDAO scheduleDAO;\r
+\r
+ @Autowired\r
+ PropertiesManagement pm;\r
+\r
+ @Autowired\r
+ Environment env;\r
+\r
+ @Override\r
+ protected void executeInternal(JobExecutionContext context) throws JobExecutionException {\r
+ Mdc.quartzJobBegin(context);\r
+ debug.debug(LogMessages.OPTIMIZER_QUARTZ_JOB, "Entered");\r
+\r
+ // Turns out that this is not necessary. Quartz behaves in a way that makes\r
+ // sense.\r
+ // if (isStale(context))\r
+ // return;\r
+\r
+ try {\r
+ // This job will look at the schedules waiting to go to SNIRO\r
+ // (PendingSchedule),\r
+ // schedule the request and update the status to PendingSchedule\r
+ // and update the state to OptimizationInProgress\r
+ List<Schedule> schedules = scheduleDAO.findByDomainStatus(DomainsEnum.ChangeManagement.toString(),\r
+ CMSStatusEnum.PendingSchedule.toString());\r
+ for (Schedule s : schedules) {\r
+ scheduleOptimization(s);\r
+ }\r
+\r
+ } catch (Exception e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ }\r
+ debug.debug(LogMessages.OPTIMIZER_QUARTZ_JOB, "Exited");\r
+\r
+ }\r
+\r
+ public void scheduleOptimization(Schedule s) {\r
+ Integer id = s.getId();\r
+ Map<String, String> mdcSave = Mdc.save();\r
+ try {\r
+ String url = env.getProperty("cmso.dispatch.url", "http://localhost:8089");\r
+ String path = env.getProperty("cmso.dispatch.optimizer .path", "/cmso/dispatch/optimizer/");\r
+ url = url + path + id;\r
+ String user = env.getProperty("mechid.user", "");\r
+ String pass = pm.getProperty("mechid.pass", "");\r
+ Client client = ClientBuilder.newClient();\r
+ client.register(new BasicAuthenticatorFilter(user, pass));\r
+ WebTarget target = client.target(url);\r
+ Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);\r
+ Response response = null;\r
+ Mdc.metricStart(id.toString(), url);\r
+ response = invocationBuilder.get();\r
+ Mdc.metricEnd(response);\r
+ metrics.info(LogMessages.OPTIMIZER_QUARTZ_JOB, id.toString());\r
+ switch (response.getStatus()) {\r
+ case 200:\r
+ log.info("Returned from dispatch call");\r
+ break;\r
+ case 400: // Bad request\r
+ default: {\r
+\r
+ throw new SchedulerException(\r
+ "Invalid return from dispach service: " + url + " : " + response.toString());\r
+ }\r
+ }\r
+ } catch (Exception e) {\r
+ debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());\r
+ } finally {\r
+ Mdc.restore(mdcSave);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * According to the documentation I read, Quartz would queue a job without\r
+ * waiting for the completion of the job with @DisallowConcurrentExecution to\r
+ * complete so that there would be a backlog of triggers to process\r
+ * \r
+ * This was designed to spin though these stale triggers. When this didn't work,\r
+ * I discovered that the behavior is that Quartz will wait for the appropriate\r
+ * interval after @DisallowConcurrentExecution jobs complete.\r
+ * \r
+ * I tested by adding a sleep for an interval > the trigger interval\r
+ * \r
+ * QUartz appears to do what makes sense. Leaving this here in case issues\r
+ * arise...\r
+ * \r
+ */\r
+ @SuppressWarnings("unused")\r
+ private boolean isStale(JobExecutionContext context) {\r
+ // DO not process stale requests.\r
+ long now = System.currentTimeMillis();\r
+ long next = context.getNextFireTime().getTime();\r
+ long sch = context.getScheduledFireTime().getTime();\r
+ log.info("now=" + now);\r
+ log.info("nxt=" + next);\r
+ log.info("sch=" + sch);\r
+ if (now > sch) {\r
+ log.info("Skipping stale SNIRO job");\r
+ // return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer.bean;\r
+\r
+public class CMOptimizerRequest {\r
+\r
+ /*\r
+ * \r
+ * { "schedulingInfo": { "scheduleId": "CM-<__SCHEDULE ID__>", "startTime":\r
+ * "2017-02-15T00:00:00+05:00", "endTime": "2017-02-18T23:59:00+05:00",\r
+ * "normalDurationInSecs": 60, "additionalDurationInSecs": 0, // for backout\r
+ * "concurrencyLimit": 10, "policyId": ["SNIRO.TimeLimitAndVerticalTopology"],\r
+ * "vnfDetails": [{ â\80\9cnodeâ\80?: "satmo415vbc", â\80\9cgroupIdâ\80?: â\80\9cgroup1â\80?//optional }, {\r
+ * â\80\9cnodeâ\80?: "satmo415vbc", â\80\9cgroupIdâ\80?: â\80\9cgroup1â\80?//optional }] }, "requestInfo": {\r
+ * â\80\9ctransactionIdâ\80?: â\80?__TRANSACTIONID__â\80?, //logging "requestId":\r
+ * "CM-<__SCHEDULE ID__>", "sourceId": "cm-portal", â\80\9coptimizerâ\80?: [â\80\9cschedulingâ\80?],\r
+ * "callbackUrl": "http://callbackurl.onap.org:8080/callback" } }\r
+ * \r
+ */\r
+\r
+ private CMSchedulingInfo schedulingInfo;\r
+ private CMRequestInfo requestInfo;\r
+\r
+ public CMOptimizerRequest() {\r
+ schedulingInfo = new CMSchedulingInfo();\r
+ requestInfo = new CMRequestInfo();\r
+ }\r
+\r
+ public CMSchedulingInfo getSchedulingInfo() {\r
+ return schedulingInfo;\r
+ }\r
+\r
+ public void setSchedulingInfo(CMSchedulingInfo schedulingInfo) {\r
+ this.schedulingInfo = schedulingInfo;\r
+ }\r
+\r
+ public CMRequestInfo getRequestInfo() {\r
+ return requestInfo;\r
+ }\r
+\r
+ public void setRequestInfo(CMRequestInfo requestInfo) {\r
+ this.requestInfo = requestInfo;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer.bean;\r
+\r
+import io.swagger.annotations.ApiModel;\r
+import io.swagger.annotations.ApiModelProperty;\r
+\r
+@ApiModel(value = "Response from schedule optimizer",\r
+ description = "Asynchronous response to schedule oprimizer request.")\r
+public class CMOptimizerResponse {\r
+\r
+ /*\r
+ * \r
+ * { "transactionId": "dummy-transaction-id",\r
+ * "scheduleId":"CM-<__SCHEDULE ID__>", "requestState": "complete", "status":\r
+ * "Optimal", // diagnostic code "description": "Optimal solution found", //\r
+ * diagnostic code "schedule": [ { "groupId": "grp06", "startTime":\r
+ * "2016-10-01T00:30:00+05:00", // starting time for this group (In 1707,\r
+ * seconds will always be zero but there is no reason to hardcode that decision)\r
+ * "finishTime": "2016-10-01T00:40:00+05:00", // endtime for this group\r
+ * (including failover) "latestInstanceStartTime": "2016-10-01T00:38:00Z", //\r
+ * latest time when an instance of this group can be started "node": [ "up01",\r
+ * "up03", "up09" ] // list of instances for this group. } ] }\r
+ * \r
+ */\r
+\r
+ @ApiModelProperty(value = "Unique id of optimization request.")\r
+ private String transactionId;\r
+\r
+ @ApiModelProperty(value = "Schedule id for which the optimization request was executed.")\r
+ private String scheduleId;\r
+\r
+ @ApiModelProperty(value = "State of the request as reported by the optimizer.")\r
+ private String requestState;\r
+\r
+ @ApiModelProperty(value = "Status of the request.")\r
+ private String status;\r
+\r
+ @ApiModelProperty(value = "Description of the request status.")\r
+ private String description;\r
+\r
+ @ApiModelProperty(value = "List of schedules returned, one per group. Only 1 group supported at this time.")\r
+ private CMSchedule[] schedule;\r
+\r
+ public CMOptimizerResponse() {}\r
+\r
+ public String getTransactionId() {\r
+ return transactionId;\r
+ }\r
+\r
+ public void setTransactionId(String transactionId) {\r
+ this.transactionId = transactionId;\r
+ }\r
+\r
+ public String getScheduleId() {\r
+ return scheduleId;\r
+ }\r
+\r
+ public void setScheduleId(String scheduleId) {\r
+ this.scheduleId = scheduleId;\r
+ }\r
+\r
+ public String getRequestState() {\r
+ return requestState;\r
+ }\r
+\r
+ public void setRequestState(String requestState) {\r
+ this.requestState = requestState;\r
+ }\r
+\r
+ public String getDescription() {\r
+ return description;\r
+ }\r
+\r
+ public void setDescription(String description) {\r
+ this.description = description;\r
+ }\r
+\r
+ public String getStatus() {\r
+ return status;\r
+ }\r
+\r
+ public void setStatus(String status) {\r
+ this.status = status;\r
+ }\r
+\r
+ public CMSchedule[] getSchedule() {\r
+ return schedule;\r
+ }\r
+\r
+ public void setSchedule(CMSchedule[] schedule) {\r
+ this.schedule = schedule;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer.bean;\r
+\r
+public class CMRequestInfo {\r
+ private String transactionId;\r
+ private String requestId;\r
+ private String sourceId;\r
+ private String[] optimizer;\r
+ private String callbackUrl;\r
+\r
+ public CMRequestInfo() {}\r
+\r
+ public String getTransactionId() {\r
+ return transactionId;\r
+ }\r
+\r
+ public void setTransactionId(String transactionId) {\r
+ this.transactionId = transactionId;\r
+ }\r
+\r
+ public String getRequestId() {\r
+ return requestId;\r
+ }\r
+\r
+ public void setRequestId(String requestId) {\r
+ this.requestId = requestId;\r
+ }\r
+\r
+ public String getSourceId() {\r
+ return sourceId;\r
+ }\r
+\r
+ public void setSourceId(String sourceId) {\r
+ this.sourceId = sourceId;\r
+ }\r
+\r
+ public String[] getOptimizer() {\r
+ return optimizer;\r
+ }\r
+\r
+ public void setOptimizer(String[] optimizer) {\r
+ this.optimizer = optimizer;\r
+ }\r
+\r
+ public String getCallbackUrl() {\r
+ return callbackUrl;\r
+ }\r
+\r
+ public void setCallbackUrl(String callbackUrl) {\r
+ this.callbackUrl = callbackUrl;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer.bean;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+public class CMSchedule {\r
+ private String groupId;\r
+ private String startTime;\r
+ private String finishTime;\r
+ private String latestInstanceStartTime;\r
+ private List<String> node;\r
+\r
+ public CMSchedule() {\r
+ node = new ArrayList<String>();\r
+ }\r
+\r
+ public String getGroupId() {\r
+ return groupId;\r
+ }\r
+\r
+ public void setGroupId(String groupId) {\r
+ this.groupId = groupId;\r
+ }\r
+\r
+ public String getStartTime() {\r
+ return startTime;\r
+ }\r
+\r
+ public void setStartTime(String startTime) {\r
+ this.startTime = startTime;\r
+ }\r
+\r
+ public String getFinishTime() {\r
+ return finishTime;\r
+ }\r
+\r
+ public void setFinishTime(String finishTime) {\r
+ this.finishTime = finishTime;\r
+ }\r
+\r
+ public String getLatestInstanceStartTime() {\r
+ return latestInstanceStartTime;\r
+ }\r
+\r
+ public void setLatestInstanceStartTime(String latestInstanceStartTime) {\r
+ this.latestInstanceStartTime = latestInstanceStartTime;\r
+ }\r
+\r
+ public List<String> getNode() {\r
+ return node;\r
+ }\r
+\r
+ public void setNode(List<String> node) {\r
+ this.node = node;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer.bean;\r
+\r
+public class CMSchedulingInfo {\r
+ private String scheduleId;\r
+ private String startTime;\r
+ private String endTime;\r
+ private int normalDurationInSecs;\r
+ private int additionalDurationInSecs;\r
+ private int concurrencyLimit;\r
+ private String[] policyId;\r
+ private CMVnfDetails[] vnfDetails;\r
+\r
+ public CMSchedulingInfo() {}\r
+\r
+ public String getScheduleId() {\r
+ return scheduleId;\r
+ }\r
+\r
+ public void setScheduleId(String scheduleId) {\r
+ this.scheduleId = scheduleId;\r
+ }\r
+\r
+ public String getStartTime() {\r
+ return startTime;\r
+ }\r
+\r
+ public void setStartTime(String startTime) {\r
+ this.startTime = startTime;\r
+ }\r
+\r
+ public String getEndTime() {\r
+ return endTime;\r
+ }\r
+\r
+ public void setEndTime(String endTime) {\r
+ this.endTime = endTime;\r
+ }\r
+\r
+ public int getNormalDurationInSecs() {\r
+ return normalDurationInSecs;\r
+ }\r
+\r
+ public void setNormalDurationInSecs(int normalDurationInSecs) {\r
+ this.normalDurationInSecs = normalDurationInSecs;\r
+ }\r
+\r
+ public int getAdditionalDurationInSecs() {\r
+ return additionalDurationInSecs;\r
+ }\r
+\r
+ public void setAdditionalDurationInSecs(int additionalDurationInSecs) {\r
+ this.additionalDurationInSecs = additionalDurationInSecs;\r
+ }\r
+\r
+ public int getConcurrencyLimit() {\r
+ return concurrencyLimit;\r
+ }\r
+\r
+ public void setConcurrencyLimit(int concurrencyLimit) {\r
+ this.concurrencyLimit = concurrencyLimit;\r
+ }\r
+\r
+ public String[] getPolicyId() {\r
+ return policyId;\r
+ }\r
+\r
+ public void setPolicyId(String[] policyId) {\r
+ this.policyId = policyId;\r
+ }\r
+\r
+ public CMVnfDetails[] getVnfDetails() {\r
+ return vnfDetails;\r
+ }\r
+\r
+ public void setVnfDetails(CMVnfDetails[] vnfDetails) {\r
+ this.vnfDetails = vnfDetails;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright © 2017-2018 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.optimizer.bean;\r
+\r
+public class CMVnfDetails {\r
+ private String node;\r
+ private String groupId;\r
+\r
+ public CMVnfDetails() {}\r
+\r
+ public CMVnfDetails(String groupId) {\r
+ this.groupId = groupId;\r
+ }\r
+\r
+ public String getNode() {\r
+ return node;\r
+ }\r
+\r
+ public void setNode(String node) {\r
+ this.node = node;\r
+ }\r
+\r
+ public String getGroupId() {\r
+ return groupId;\r
+ }\r
+\r
+ public void setGroupId(String groupId) {\r
+ this.groupId = groupId;\r
+ }\r
+\r
+}\r