Create Optimized API - Done-1 93/83393/2
authorJerry Flood <jflood@att.com>
Tue, 26 Mar 2019 17:38:37 +0000 (13:38 -0400)
committerJerry Flood <jflood@att.com>
Tue, 26 Mar 2019 18:11:42 +0000 (14:11 -0400)
Not quite - one more file

Issue-ID: OPTFRA-458

Change-Id: Idecd64d65be8b6c5c3115915a53b36459b74b601
Signed-off-by: Jerry Flood <jflood@att.com>
cmso-service/src/main/java/org/onap/optf/cmso/filters/CmsoContainerFilters.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/service/rs/CmsoOptimizerCallbackImpl.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/service/rs/CmsoService.java [new file with mode: 0644]

diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/filters/CmsoContainerFilters.java b/cmso-service/src/main/java/org/onap/optf/cmso/filters/CmsoContainerFilters.java
new file mode 100644 (file)
index 0000000..4c44163
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright © 2017-2019 AT&T Intellectual Property.
+ * Modifications Copyright © 2018 IBM.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *         https://creativecommons.org/licenses/by/4.0/
+ * 
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.onap.optf.cmso.filters;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.ext.Provider;
+
+import org.onap.observations.Mdc;
+import org.onap.observations.Observation;
+import org.onap.optf.cmso.common.LogMessages;
+import org.onap.optf.cmso.filters.MessageHeaders.HeadersEnum;
+import org.springframework.stereotype.Component;
+
+@Priority(1)
+@Provider
+@Component
+public class CmsoContainerFilters implements ContainerRequestFilter, ContainerResponseFilter {
+
+
+       @Context
+       private HttpServletRequest servletRequest;
+
+    @Override
+    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
+            throws IOException {
+        try {
+                       Mdc.auditEnd(requestContext, responseContext);
+                       Observation.report(LogMessages.INCOMING_MESSAGE_RESPONSE, 
+                                       requestContext.getMethod(),
+                                       requestContext.getUriInfo().getPath().toString(),
+                                       responseContext.getStatusInfo().toString());
+            MultivaluedMap<String, String> reqHeaders = requestContext.getHeaders();
+            MultivaluedMap<String, Object> respHeaders = responseContext.getHeaders();
+            String minorVersion = (String) reqHeaders.getFirst(HeadersEnum.MinorVersion.toString());
+            respHeaders.add(HeadersEnum.MinorVersion.toString(), minorVersion);
+            respHeaders.add(HeadersEnum.LatestVersion.toString(), MessageHeaders.latestVersion);
+            respHeaders.add(HeadersEnum.PatchVersion.toString(), MessageHeaders.patchVersion);
+
+        } catch (Exception e) {
+            if (e instanceof WebApplicationException) {
+               Observation.report(LogMessages.EXPECTED_EXCEPTION, e.getMessage());
+            } else {
+               Observation.report(LogMessages.UNEXPECTED_EXCEPTION, e.getMessage());
+            }
+        }
+    }
+
+    @Override
+    public void filter(ContainerRequestContext requestContext) throws IOException {
+        try {
+            // On the way in
+                       Mdc.auditStart(requestContext, servletRequest);
+                       Observation.report(LogMessages.INCOMING_MESSAGE, 
+                                       requestContext.getMethod(),
+                                       requestContext.getUriInfo().getPath().toString());
+
+            String majorVersion = requestContext.getUriInfo().getPath();
+            if (majorVersion != null) {
+
+                if (majorVersion.startsWith("dispatch/"))
+                    return;
+                majorVersion = majorVersion.replaceAll("/.*$", "");
+            }
+            if (!MessageHeaders.validateMajorVersion(majorVersion)) {
+                ResponseBuilder builder = null;
+                String response = "Unsupported Major version";
+                builder = Response.status(Response.Status.NOT_FOUND).entity(response);
+                throw new WebApplicationException(builder.build());
+            }
+            MultivaluedMap<String, String> headers = requestContext.getHeaders();
+            String transactionId = (String) headers.getFirst(HeadersEnum.TransactionID.toString());
+            if (transactionId == null) {
+                transactionId = UUID.randomUUID().toString();
+                headers.add(HeadersEnum.TransactionID.toString(), transactionId);
+            }
+            String minorVersion = (String) headers.getFirst(HeadersEnum.MinorVersion.toString());
+            if (minorVersion == null) {
+                minorVersion = MessageHeaders.supportedMajorVersions.get(majorVersion);
+                headers.add(HeadersEnum.MinorVersion.toString(), minorVersion);
+            }
+            if (!MessageHeaders.validateMajorMinorVersion(majorVersion, minorVersion)) {
+                ResponseBuilder builder = null;
+                String response = "Unsupported API version";
+                builder = Response.status(Response.Status.NOT_FOUND).entity(response);
+                throw new WebApplicationException(builder.build());
+
+            }
+        } catch (Exception e) {
+            if (e instanceof WebApplicationException) {
+                Observation.report(LogMessages.EXPECTED_EXCEPTION, e.getMessage());
+                throw e;
+            } else {
+               Observation.report(LogMessages.UNEXPECTED_EXCEPTION, e.getMessage());
+            }
+        }
+
+    }
+
+}
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/service/rs/CmsoOptimizerCallbackImpl.java b/cmso-service/src/main/java/org/onap/optf/cmso/service/rs/CmsoOptimizerCallbackImpl.java
new file mode 100644 (file)
index 0000000..1596051
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright © 2017-2019 AT&T Intellectual Property.
+ * Modifications Copyright © 2018 IBM.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.onap.optf.cmso.service.rs;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.transaction.Transactional;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.ISODateTimeFormat;
+import org.onap.optf.cmso.common.CMSStatusEnum;
+import org.onap.optf.cmso.common.DomainsEnum;
+import org.onap.optf.cmso.common.LogMessages;
+import org.onap.optf.cmso.common.exceptions.CMSException;
+import org.onap.optf.cmso.common.exceptions.CMSNotFoundException;
+import org.onap.optf.cmso.model.ChangeManagementGroup;
+import org.onap.optf.cmso.model.ChangeManagementSchedule;
+import org.onap.optf.cmso.model.Schedule;
+import org.onap.optf.cmso.model.dao.ChangeManagementChangeWindowDAO;
+import org.onap.optf.cmso.model.dao.ChangeManagementDetailDAO;
+import org.onap.optf.cmso.model.dao.ChangeManagementGroupDAO;
+import org.onap.optf.cmso.model.dao.ChangeManagementScheduleDAO;
+import org.onap.optf.cmso.optimizer.bean.CMOptimizerResponse;
+import org.onap.optf.cmso.optimizer.bean.CMSchedule;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+/**
+ * The Class CmsoOptimizerCallbackImpl.
+ */
+@Controller
+public class CmsoOptimizerCallbackImpl extends BaseSchedulerServiceImpl implements CmsoOptimizerCallback {
+    private static EELFLogger log = EELFManager.getInstance().getLogger(CmsoOptimizerCallbackImpl.class);
+    private static EELFLogger metrics = EELFManager.getInstance().getMetricsLogger();
+    private static EELFLogger audit = EELFManager.getInstance().getAuditLogger();
+    private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();
+    private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();
+
+    @Context
+    UriInfo uri;
+
+    @Context
+    HttpServletRequest request;
+
+
+    @Autowired
+    ChangeManagementScheduleDAO cmScheduleDAO;
+
+    @Autowired
+    ChangeManagementGroupDAO cmGroupDAO;
+
+    @Autowired
+    ChangeManagementChangeWindowDAO cmChangeWindowDAO;
+
+    @Autowired
+    ChangeManagementDetailDAO cmDetailsDAO;
+
+    /**
+     * Sniro callback.
+     *
+     * @param apiVersion the api version
+     * @param sniroResponse the sniro response
+     * @return the response
+     */
+    @Override
+    @Transactional
+    public Response sniroCallback(String apiVersion, CMOptimizerResponse sniroResponse) {
+        Response response = null;
+        log.info(LogMessages.PROCESS_OPTIMIZER_CALLBACK, "Received", request.getRemoteAddr(), "");
+        log.info(LogMessages.OPTIMIZER_REQUEST, "Callback received", sniroResponse.getTransactionId(),
+                uri.getAbsolutePath().toString());
+        try {
+            // Note that transaction ID and schedule ID are currently the same value.
+
+            String transactionId = sniroResponse.getTransactionId();
+
+            // Synchronize this with transaction that scheduled the SNIRO optimization
+            // to ensure status updates are properly ordered.
+            // This is necessary only in the race condition where SNIRO callback comes
+            // before the SNIRO response is processed and the scheduling transaction is
+            // still in flight.
+            // Note that this may happen in loopback mode, but is not likely to happen with
+            // real SNIRO unless SNIRO changes to be synchronous and the callback comes before
+            // the response.
+            // If this lock times out, the schedule will remain in 'Optimization In
+            // Progress' and never complete.
+            Schedule schedule = scheduleDAO.lockOneByTransactionId(transactionId);
+
+            if (schedule == null) {
+                throw new CMSNotFoundException(DomainsEnum.ChangeManagement.toString(),
+                        "(OptimizerTransactionID=" + transactionId + ")");
+
+            }
+            CMSStatusEnum status = CMSStatusEnum.PendingApproval.fromString(schedule.getStatus());
+            debug.debug("Status at time of SNIRO callback is " + status.toString());
+            switch (status) {
+                // PendingSchedule may be a valid status in the cases where SNIRO async call
+                // returns before
+                // We have committed the OptimizationInProgress status
+                // The dispatch logic ensures that we only every dispatch once.
+                case OptimizationInProgress:
+                    processSniroResponse(sniroResponse, schedule);
+                    scheduleDAO.save(schedule);
+                    response = Response.ok().build();
+                    break;
+                default:
+                    throw new CMSException(Status.PRECONDITION_FAILED, LogMessages.OPTIMIZER_CALLBACK_STATE_ERROR,
+                            CMSStatusEnum.OptimizationInProgress.toString(), schedule.getStatus().toString());
+            }
+        } catch (CMSException e) {
+            errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+            response = Response.status(e.getStatus()).entity(e.getRequestError()).build();
+        } catch (Exception e) {
+            errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+            response = Response.serverError().entity(e.getMessage()).build();
+        } finally {
+        }
+        return response;
+    }
+
+    private void processSniroResponse(CMOptimizerResponse sniroResponse, Schedule schedule) {
+        try {
+            schedule.setOptimizerReturnDateTimeMillis(System.currentTimeMillis());
+            schedule.setOptimizerStatus(sniroResponse.getRequestState());
+            schedule.setOptimizerMessage(sniroResponse.getDescription());
+            String scheduleId = sniroResponse.getScheduleId();
+            ObjectMapper om = new ObjectMapper();
+            CMSchedule[] scheduleArray = sniroResponse.getSchedule();
+            if (scheduleArray != null && scheduleArray.length > 0) {
+                String scheduleString = om.writeValueAsString(scheduleArray);
+                schedule.setSchedule(scheduleString);
+                log.debug("scheduleId={0} schedule={1}", scheduleId, scheduleString);
+                for (CMSchedule sniroSchedule : sniroResponse.getSchedule()) {
+                    String groupId = sniroSchedule.getGroupId();
+                    DateTime finishTime = convertDate(sniroSchedule.getFinishTime(), "finishTime");
+                    DateTime startTime = convertDate(sniroSchedule.getStartTime(), "startTime");
+                    ChangeManagementGroup group = cmGroupDAO.findOneBySchedulesIDGroupID(schedule.getUuid(), groupId);
+                    if (group == null) {
+                        throw new CMSException(Status.PRECONDITION_FAILED,
+                                LogMessages.CHANGE_MANAGEMENT_GROUP_NOT_FOUND, schedule.getScheduleId(), groupId);
+                    }
+                    group.setStartTimeMillis(startTime.getMillis());
+                    group.setFinishTimeMillis(finishTime.getMillis());
+                    DateTime latestInstanceStartTime =
+                                    convertDate(sniroSchedule.getLatestInstanceStartTime(), "latestInstanceStartTime");
+                    group.setLastInstanceStartTimeMillis(latestInstanceStartTime.getMillis());
+                    cmGroupDAO.save(group);
+                    long totalDuration =
+                            (group.getAdditionalDurationInSecs() + group.getNormalDurationInSecs()) * 1000L;
+                    Map<String, Map<String, Long>> startAndFinishTimeMap = new HashMap<String, Map<String, Long>>();
+                    makeMap(startTime.getMillis(), latestInstanceStartTime.getMillis(), group.getConcurrencyLimit(),
+                            totalDuration, sniroSchedule.getNode(), startAndFinishTimeMap);
+                    for (String node : sniroSchedule.getNode()) {
+                        processNode(schedule, group, node, startAndFinishTimeMap);
+                    }
+                }
+                schedule.setStatus(CMSStatusEnum.PendingApproval.toString());
+            } else {
+                debug.debug("scheduleId={0} schedule=null status={1} ", scheduleId, schedule.getOptimizerStatus());
+                schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());
+            }
+        } catch (CMSException e) {
+            errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+            schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());
+            schedule.setOptimizerStatus(e.getStatus().toString());
+            schedule.setOptimizerMessage(e.getLocalizedMessage());
+        } catch (Exception e) {
+            errors.error(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+            schedule.setStatus(CMSStatusEnum.OptimizationFailed.toString());
+            schedule.setOptimizerStatus("Exception");
+            schedule.setOptimizerMessage(e.getLocalizedMessage());
+        }
+    }
+
+    /**
+     * Make map.
+     *
+     * @param startTime the start time
+     * @param latestInstanceStartTime the latest instance start time
+     * @param concurrencyLimit the concurrency limit
+     * @param totalDuration the total duration
+     * @param nodeList the node list
+     * @param startAndFinishTimeMap the start and finish time map
+     * @throws CMSException the CMS exception
+     */
+    public static void makeMap(Long startTime, Long latestInstanceStartTime, int concurrencyLimit, long totalDuration,
+            List<String> nodeList, Map<String, Map<String, Long>> startAndFinishTimeMap) throws CMSException {
+        Long nextStartTime = null;
+        Long nextFinishTime = null;
+        for (int nodeNumber = 0; nodeNumber < nodeList.size(); nodeNumber++) {
+            String node = nodeList.get(nodeNumber);
+            if (nodeNumber % concurrencyLimit == 0) {
+                if (nodeNumber == 0) {
+                    nextStartTime = startTime;
+                }
+                else {
+                    nextStartTime = nextStartTime + totalDuration;
+                }
+                if (nextStartTime > latestInstanceStartTime) {
+                    throw new CMSException(Status.BAD_REQUEST, LogMessages.UNABLE_TO_ALLOCATE_VNF_TIMESLOTS,
+                            startTime.toString(), latestInstanceStartTime.toString(), String.valueOf(totalDuration),
+                            String.valueOf(concurrencyLimit), String.valueOf(nodeList.size()));
+                }
+                nextFinishTime = nextStartTime + totalDuration;
+            }
+            Map<String, Long> map = new HashMap<String, Long>();
+            map.put("startTime", nextStartTime);
+            map.put("finishTime", nextFinishTime);
+            startAndFinishTimeMap.put(node, map);
+        }
+
+    }
+
+    private void processNode(Schedule schedule, ChangeManagementGroup group, String node,
+            Map<String, Map<String, Long>> startAndFinishTimeMap) throws CMSException {
+        Map<String, Long> map = startAndFinishTimeMap.get(node);
+        ChangeManagementSchedule detail = cmScheduleDAO.findOneByGroupUuidAndVnfName(group.getUuid(), node);
+        if (detail == null) {
+            throw new CMSException(Status.NOT_FOUND, LogMessages.UNABLE_TO_LOCATE_SCHEDULE_DETAIL,
+                    schedule.getScheduleId(), group.getGroupId(), node);
+        }
+        detail.setStartTimeMillis(map.get("startTime"));
+        detail.setFinishTimeMillis(map.get("finishTime"));
+        detail.setVnfId("");
+        detail.setStatus(CMSStatusEnum.PendingApproval.toString());
+        cmScheduleDAO.save(detail);
+    }
+
+    /**
+     * Convert date.
+     *
+     * @param utcDate the utc date
+     * @param attrName the attr name
+     * @return the date time
+     * @throws CMSException the CMS exception
+     */
+    public static DateTime convertDate(String utcDate, String attrName) throws CMSException {
+        try {
+            DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withZoneUTC().parseDateTime(utcDate);
+            if (dateTime != null) {
+                return dateTime;
+            }
+        } catch (Exception e) {
+            debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+        }
+        throw new CMSException(Status.BAD_REQUEST, LogMessages.INVALID_ATTRIBUTE, attrName, utcDate);
+    }
+
+    /**
+     * Convert ISO date.
+     *
+     * @param utcDate the utc date
+     * @param attrName the attr name
+     * @return the date time
+     * @throws CMSException the CMS exception
+     */
+    public static DateTime convertIsoDate(String utcDate, String attrName) throws CMSException {
+        try {
+            DateTime dateTime = ISODateTimeFormat.dateTimeParser().parseDateTime(utcDate);
+            if (dateTime != null) {
+                return dateTime;
+            }
+        } catch (Exception e) {
+            debug.debug(LogMessages.UNEXPECTED_EXCEPTION, e, e.getMessage());
+        }
+        throw new CMSException(Status.BAD_REQUEST, LogMessages.INVALID_ATTRIBUTE, attrName, utcDate);
+    }
+
+}
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/service/rs/CmsoService.java b/cmso-service/src/main/java/org/onap/optf/cmso/service/rs/CmsoService.java
new file mode 100644 (file)
index 0000000..d9b338e
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright © 2017-2018 AT&T Intellectual Property.
+ * Modifications Copyright © 2018 IBM.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.onap.optf.cmso.service.rs;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import org.onap.optf.cmso.common.CMSRequestError;
+import org.onap.optf.cmso.model.Schedule;
+import org.onap.optf.cmso.service.rs.models.ApprovalMessage;
+import org.onap.optf.cmso.service.rs.models.CmDetailsMessage;
+import org.onap.optf.cmso.service.rs.models.CmsoMessage;
+
+@Api("CMSO Schedule API")
+@Path("/{apiVersion}")
+@Produces({MediaType.APPLICATION_JSON})
+public interface CmsoService {
+    // ******************************************************************
+    @GET
+    @Path("/schedules")
+    @Produces({MediaType.APPLICATION_JSON})
+    @ApiOperation(value = "", notes = "Returns a list of Scheduler Requests based upon the filter criteria.",
+            response = Schedule.class, responseContainer = "List")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "OK"),
+            @ApiResponse(code = 404, message = "No records found", response = CMSRequestError.class),
+            @ApiResponse(code = 500, message = "Unexpected Runtime error", response = Exception.class)})
+    public Response searchScheduleRequests(
+            @ApiParam(value = "v1") @PathParam("apiVersion") @DefaultValue("v1") String apiVersion,
+            @DefaultValue(value = "false") @ApiParam(
+                    value = "Include details") @QueryParam("includeDetails") Boolean includeDetails,
+            @ApiParam(value = "Schedule identifier", allowMultiple = true) @QueryParam("scheduleId") String scheduleId,
+            @ApiParam(value = "Schedule name", allowMultiple = true) @QueryParam("scheduleName") String scheduleName,
+            @ApiParam(value = "SCheduler creator User id of ",
+                    allowMultiple = true) @QueryParam("userId") String userId,
+            @ApiParam(value = "Schedule status", allowMultiple = true) @QueryParam("status") String status,
+            @ApiParam(value = "Creation date and time (<low date>[,<hi date>])",
+                    allowMultiple = true) @QueryParam("createDateTime") String createDateTime,
+            @ApiParam(value = "Optimizer status",
+                    allowMultiple = true) @QueryParam("optimizerStatus") String optimizerStatus,
+            @ApiParam(value = "Workflow", allowMultiple = true) @QueryParam("WorkflowName") String workflowName,
+            @Context UriInfo uri, @Context HttpServletRequest request);
+
+    // ******************************************************************
+    @POST
+    @Path("/schedules/{scheduleId}")
+    @Produces({MediaType.APPLICATION_JSON})
+    @ApiOperation(value = "", notes = "Creates a schedule request for scheduleId")
+    @ApiResponses(
+            value = {@ApiResponse(code = 202, message = "Schedule request accepted for optimization."),
+                    @ApiResponse(code = 409, message = "Schedule request already exists for this schedule id.",
+                            response = CMSRequestError.class),
+                    @ApiResponse(code = 500, message = "Unexpected Runtime error")})
+    public Response createScheduleRequest(
+            @ApiParam(value = "v1") @PathParam("apiVersion") @DefaultValue("v1") String apiVersion,
+            @ApiParam(value = "Schedule id to uniquely identify the schedule request being created.")
+            @PathParam("scheduleId") String scheduleId,
+            @ApiParam(value = "Data for creating a schedule request for the given schedule id")
+                CmsoMessage scheduleMessage,
+            @Context HttpServletRequest request);
+
+    // ******************************************************************
+    @DELETE
+    @Path("/schedules/{scheduleId}")
+    @Produces({MediaType.APPLICATION_JSON})
+    @ApiOperation(value = "", notes = "Cancels the schedule request for scheduleId")
+    @ApiResponses(value = {@ApiResponse(code = 204, message = "Delete successful"),
+            @ApiResponse(code = 404, message = "No record found", response = CMSRequestError.class),
+            @ApiResponse(code = 500, message = "Unexpected Runtime error")})
+    public Response deleteScheduleRequest(
+            @ApiParam(value = "v1") @PathParam("apiVersion") @DefaultValue("v1") String apiVersion,
+            @ApiParam(value = "Schedule id to uniquely identify the schedule request being deleted.")
+            @PathParam("scheduleId") String scheduleId,
+            @Context HttpServletRequest request);
+
+    // ******************************************************************
+    @GET
+    @Path("/schedules/{scheduleId}")
+    @Produces({MediaType.APPLICATION_JSON})
+    @ApiOperation(value = "", notes = "Retrieve the schedule request for scheduleId", response = Schedule.class)
+    @ApiResponses(
+            value = {@ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 404, message = "No record found"),
+                    @ApiResponse(code = 500, message = "Unexpected Runtime error")})
+    public Response getScheduleRequestInfo(
+            @ApiParam(value = "v1") @PathParam("apiVersion") @DefaultValue("v1") String apiVersion,
+            @ApiParam(value = "Schedule id to uniquely identify the schedule info being retrieved.")
+            @PathParam("scheduleId") String scheduleId,
+            @Context HttpServletRequest request);
+
+    // ******************************************************************
+    @POST
+    @Path("/schedules/{scheduleId}/approvals")
+    @Produces({MediaType.APPLICATION_JSON})
+    @ApiOperation(value = "",
+            notes = "Adds an accept/reject approval status to the schedule request identified by scheduleId")
+    @ApiResponses(
+            value = {@ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 404, message = "No record found"),
+                    @ApiResponse(code = 500, message = "Unexpected Runtime error")})
+    public Response approveScheduleRequest(
+            @ApiParam(value = "v1") @PathParam("apiVersion") @DefaultValue("v1") String apiVersion,
+            @ApiParam(value = "Schedule id to uniquely identify the schedule request being accepted or rejected.")
+            @PathParam("scheduleId") String scheduleId,
+            @ApiParam(value = "Accept or reject approval message") ApprovalMessage approval,
+            @Context HttpServletRequest request);
+
+    // ******************************************************************
+    @GET
+    @Path("/schedules/scheduleDetails")
+    @Produces({MediaType.APPLICATION_JSON})
+    @ApiOperation(value = "", notes = "Returns a list of Schedule request details based upon the filter criteria.",
+            response = CmDetailsMessage.class, responseContainer = "List")
+    @ApiResponses(value = {@ApiResponse(code = 200, message = "OK"),
+            @ApiResponse(code = 404, message = "No records found", response = CMSRequestError.class),
+            @ApiResponse(code = 500, message = "Unexpected Runtime error", response = Exception.class)})
+    public Response searchScheduleRequestDetails(
+            @ApiParam(value = "v1") @PathParam("apiVersion") @DefaultValue("v1") String apiVersion,
+            @ApiParam(value = "Schedule identifier",
+                    allowMultiple = true) @QueryParam("request.scheduleId") String scheduleId,
+            @ApiParam(value = "Schedule name",
+                    allowMultiple = true) @QueryParam("request.scheduleName") String scheduleName,
+            @ApiParam(value = "Scheduler creator User id of ",
+                    allowMultiple = true) @QueryParam("request.userId") String userId,
+            @ApiParam(value = "Schedule status", allowMultiple = true) @QueryParam("request.status") String status,
+            @ApiParam(value = "Creation date and time (<low date>[,<hi date>])",
+                    allowMultiple = true) @QueryParam("request.createDateTime") String createDateTime,
+            @ApiParam(value = "Optimizer status",
+                    allowMultiple = true) @QueryParam("request.optimizerStatus") String optimizerStatus,
+            @ApiParam(value = "Request Approval user id",
+                    allowMultiple = true) @QueryParam("request.approvalUserId") String requestApprovalUserId,
+            @ApiParam(value = "Request Approval status",
+                    allowMultiple = true) @QueryParam("request.approvalStatus") String requestApprovalStatus,
+            @ApiParam(value = "Request Approval type",
+                    allowMultiple = true) @QueryParam("request.approvalType") String requestApprovalType,
+            @ApiParam(value = "Workflow", allowMultiple = true) @QueryParam("WorkflowName") String workflowName,
+            @ApiParam(value = "VNF Name", allowMultiple = true) @QueryParam("vnfName") String vnfName,
+            @ApiParam(value = "VNF Id", allowMultiple = true) @QueryParam("vnfId") String vnfId,
+            @ApiParam(value = "VNF Status", allowMultiple = true) @QueryParam("vnfStatus") String vnfStatus,
+            // @ApiParam(value="VNF Schedule Id", allowMultiple=true) @QueryParam("vnfScheduleId")
+            // String
+            // vnfScheduleId,
+            @ApiParam(value = "Start time <low>,<high>",
+                    allowMultiple = true) @QueryParam("startTime") String startTime,
+            @ApiParam(value = "Finish time <low>,<high>",
+                    allowMultiple = true) @QueryParam("finishTime") String finishTime,
+            @ApiParam(value = "Last instance start time <low>,<high>",
+                    allowMultiple = true) @QueryParam("lastInstanceTime") String lastInstanceTime,
+            @ApiParam(value = "TM Change Ticket Change Id",
+                    allowMultiple = true) @QueryParam("tmChangeId") String tmChangeId,
+            // @ApiParam(value="Approval user id", allowMultiple=true) @QueryParam("approvalUserId")
+            // String approvalUserId,
+            // @ApiParam(value="Approval status", allowMultiple=true) @QueryParam("approvalStatus")
+            // String
+            // approvalStatus,
+            // @ApiParam(value="Approval type", allowMultiple=true) @QueryParam("approvalType")
+            // String
+            // approvalType,
+            @ApiParam(value = "Maximum number of schedules to return") @QueryParam("maxSchedules") Integer maxSchedules,
+            @ApiParam(value = "Return schedules > lastScheduleId") @QueryParam("lastScheduleId") String lastScheduleId,
+            @ApiParam(
+                    value = "Return concurrencyLimit") @QueryParam("request.concurrencyLimit") Integer concurrencyLimit,
+            @Context UriInfo uri, @Context HttpServletRequest request);
+
+}