Change Management Schedule Optimization 31/67931/1
authorRamaPrasad Amaranarayana (ra5425) <ra5425@att.com>
Wed, 19 Sep 2018 22:40:47 +0000 (18:40 -0400)
committerRamaPrasad Amaranarayana (ra5425) <ra5425@att.com>
Wed, 19 Sep 2018 22:40:47 +0000 (18:40 -0400)
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>
18 files changed:
cmso-service/src/main/java/org/onap/optf/cmso/dispatcher/CMSOClient.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/dispatcher/CmJob.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/dispatcher/DispatchJob.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/dispatcher/rs/DispacherService.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/dispatcher/rs/DispatcherServiceImpl.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/eventq/CMSQueueJob.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/eventq/CmQuartzJob.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/eventq/CmQuartzJobStartup.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/eventq/DispatchedEventList.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/CMSOptimizerClient.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/DispatchedOptimizerList.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/OptimizerQuartzJob.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/bean/CMOptimizerRequest.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/bean/CMOptimizerResponse.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/bean/CMRequestInfo.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/bean/CMSchedule.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/bean/CMSchedulingInfo.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/optimizer/bean/CMVnfDetails.java [new file with mode: 0644]

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