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