blob: c964f012035ccb40bdd89601d4a4b2ec2c9819b4 [file] [log] [blame]
/*-
* ============LICENSE_START=======================================================
* OSAM
* ================================================================================
* Copyright (C) 2018 AT&T
* ================================================================================
* 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.
* ============LICENSE_END=========================================================
*/
package org.onap.osam.job.impl;
import com.google.common.collect.ImmutableMap;
import org.onap.osam.job.dao.job.JobStatus;
import org.onap.osam.job.dao.job.OsamJob;
import org.onap.osam.job.AsyncJobService;
import org.onap.osam.job.JobType;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Service
public class AsyncJobServiceImpl implements AsyncJobService {
private final JobFactory jobFactory;
private final JobsDataAccessService jobsDataAccessService;
private Map<String, JobStatus> msoStateToJobStatusMap = ImmutableMap.<String, JobStatus>builder()
.put("inprogress", JobStatus.IN_PROGRESS)
.put("failed", JobStatus.FAILED)
.put("pause", JobStatus.PAUSE)
.put("paused", JobStatus.PAUSE)
.put("complete", JobStatus.COMPLETED)
.put("pending", JobStatus.IN_PROGRESS)
.put("pendingmanualtask", JobStatus.PAUSE)
.put("unlocked", JobStatus.IN_PROGRESS)
.build();
public AsyncJobServiceImpl(JobFactory jobFactory, JobsDataAccessService jobsDataAccessService) {
this.jobFactory = jobFactory;
this.jobsDataAccessService = jobsDataAccessService;
}
@Override
public JobStatus calcStatus(String asyncRequestStatus) {
JobStatus jobStatus = msoStateToJobStatusMap.get(asyncRequestStatus);
return (jobStatus != null ? jobStatus : JobStatus.IN_PROGRESS);
}
@Override
public List<UUID> pushBulkJob(String userId, boolean isSuccessful, boolean isOltDependant) {
List<UUID> uuids = new ArrayList<>();
Date createdBulkDate = Calendar.getInstance().getTime();
int bulkSize = 1;
for (int i = 0; i < bulkSize; i++) {
OsamJob job = jobFactory.createRootJob(JobType.ChassisCreation, new DummyAsyncRequest(), userId, i,
ImmutableMap.of("isSuccessful", isSuccessful, "isOltDependant", isOltDependant));
UUID jobId = jobsDataAccessService.add(job);
uuids.add(jobId);
}
return uuids;
}
/*
private final DataAccessService dataAccessService;
private final IJobFactory jobAdapter;
private final IJobsDataAccessService jobService;
private SessionFactory sessionFactory;
private AaiClientInterface aaiClient;
private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI;
private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class);
@Autowired
public AsyncInstantiationBusinessLogicImpl(DataAccessService dataAccessService,
IJobFactory jobAdapter,
IJobsDataAccessService jobService,
SessionFactory sessionFactory,
AaiClientInterface aaiClient) {
this.dataAccessService = dataAccessService;
this.jobAdapter = jobAdapter;
this.jobService = jobService;
this.sessionFactory = sessionFactory;
this.aaiClient = aaiClient;
}
@Override
public List<ServiceInfo> getAllServicesInfo() {
return dataAccessService.getList(ServiceInfo.class, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null);
}
private String filterByCreationDateAndNotDeleted() {
LocalDateTime minus3Months = LocalDateTime.now().minusMonths(3);
Timestamp filterDate = Timestamp.valueOf(minus3Months);
return " where" +
" hidden = false" +
" and deleted_at is null" + // don't fetch deleted
" and created >= '" + filterDate + "' ";
}
private String orderByCreatedDateAndStatus() {
return " createdBulkDate DESC ,\n" +
" (CASE jobStatus\n" +
" WHEN 'COMPLETED' THEN 0\n" +
" WHEN 'FAILED' THEN 0\n" +
" WHEN 'IN_PROGRESS' THEN 1\n" +
" WHEN 'PAUSE' THEN 2\n" +
" WHEN 'PENDING' THEN 3\n" +
" WHEN 'STOPPED' THEN 3 END),\n" +
" statusModifiedDate ";
}
@Override
public List<UUID> pushBulkJob(ServiceInstantiation request, String userId) {
List<UUID> uuids = new ArrayList<>();
Date createdBulkDate = Calendar.getInstance().getTime();
int bulkSize = request.getBulkSize();
UUID templateId = UUID.randomUUID();
for (int i = 0; i < bulkSize; i++) {
//Job job = jobAdapter.createJob(JobType.ServiceInstantiation, request, templateId, userId, i);
Job job = jobAdapter.createJob(JobType.NoOp, request, templateId, userId, i);//should be some instatiation, this was changed as part of code cleaning
UUID jobId = jobService.add(job);
auditVidStatus(jobId,getStatus());
uuids.add(jobId);
dataAccessService.saveDomainObject(createServiceInfo(userId, request, jobId, templateId, createdBulkDate), DaoUtils.getPropsMap());
}
return uuids;
}
private ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate) {
return new ServiceInfo(
userId, JobStatus.PENDING, serviceInstantiation.isPause(), jobId, templateId,
serviceInstantiation.getOwningEntityId(),
serviceInstantiation.getOwningEntityName(),
serviceInstantiation.getProjectName(),
serviceInstantiation.getAicZoneId(),
serviceInstantiation.getAicZoneName(),
serviceInstantiation.getTenantId(),
serviceInstantiation.getTenantName(),
serviceInstantiation.getLcpCloudRegionId(),
null,
serviceInstantiation.getSubscriptionServiceType(),
serviceInstantiation.getSubscriberName(),
null,
serviceInstantiation.getInstanceName(),
serviceInstantiation.getModelInfo().getModelInvariantId(),
serviceInstantiation.getModelInfo().getModelName(),
serviceInstantiation.getModelInfo().getModelVersion(),
createdBulkDate
);
}
*/
/*//*
/@Override
public RequestDetailsWrapper<ServiceInstantiationRequestDetails> generateServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String userId) {
ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity owningEntity = new ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity(payload.getOwningEntityId(), payload.getOwningEntityName());
SubscriberInfo subscriberInfo = new SubscriberInfo();
subscriberInfo.setGlobalSubscriberId(payload.getGlobalSubscriberId());
String serviceInstanceName = null;
if(payload.isUserProvidedNaming()) {
serviceInstanceName = getUniqueName(payload.getInstanceName(), ResourceType.SERVICE_INSTANCE);
String finalServiceInstanceName = serviceInstanceName;
updateServiceInfo(jobId, x -> x.setServiceInstanceName(finalServiceInstanceName));
}
ServiceInstantiationRequestDetails.RequestInfo requestInfo = new ServiceInstantiationRequestDetails.RequestInfo(
serviceInstanceName,
payload.getProductFamilyId(),
"VID",
payload.isRollbackOnFailure(),
userId);
List<ServiceInstantiationRequestDetails.ServiceInstantiationService> serviceInstantiationService = new LinkedList<>();
List<Map<String, String>> unFilteredInstanceParams = payload.getInstanceParams() != null ? payload.getInstanceParams() : new LinkedList<>();
List<Map<String, String>> filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams);
ServiceInstantiationRequestDetails.ServiceInstantiationService serviceInstantiationService1 = new ServiceInstantiationRequestDetails.ServiceInstantiationService(
payload.getModelInfo(),
serviceInstanceName,
filteredInstanceParams,
createServiceInstantiationVnfList(payload)
);
serviceInstantiationService.add(serviceInstantiationService1);
ServiceInstantiationRequestDetails.RequestParameters requestParameters = new ServiceInstantiationRequestDetails.RequestParameters(payload.getSubscriptionServiceType(), false, serviceInstantiationService);
ServiceInstantiationRequestDetails.Project project = payload.getProjectName() != null ? new ServiceInstantiationRequestDetails.Project(payload.getProjectName()) : null;
ServiceInstantiationRequestDetails requestDetails = new ServiceInstantiationRequestDetails(payload.getModelInfo(), owningEntity, subscriberInfo,
project, requestInfo, requestParameters);
RequestDetailsWrapper<ServiceInstantiationRequestDetails> requestDetailsWrapper = new RequestDetailsWrapper(requestDetails);
debugRequestDetails(requestDetailsWrapper, logger);
return requestDetailsWrapper;
}*//*
private List<Map<String, String>> removeUnNeededParams(List<Map<String, String>> instanceParams) {
List<String> keysToRemove = new ArrayList<>();
if (instanceParams != null && !instanceParams.isEmpty()) {
for (String key : instanceParams.get(0).keySet()) {
for (String paramToIgnore : PARAMS_TO_IGNORE)
if ((key.equalsIgnoreCase(paramToIgnore))) {
keysToRemove.add(key);
}
}
for (String key : keysToRemove) {
instanceParams.get(0).remove(key);
}
//TODO will be removed on once we stop using List<Map<String, String>>
if (instanceParams.get(0).isEmpty()) {
return Collections.emptyList();
}
}
return instanceParams;
}
private ServiceInstantiationRequestDetails.ServiceInstantiationVnfList createServiceInstantiationVnfList(ServiceInstantiation payload) {
CloudConfiguration cloudConfiguration = new CloudConfiguration();
cloudConfiguration.setTenantId(payload.getTenantId());
cloudConfiguration.setLcpCloudRegionId(payload.getLcpCloudRegionId());
Map<String, Vnf> vnfs = payload.getVnfs();
List<ServiceInstantiationRequestDetails.ServiceInstantiationVnf> vnfList = new ArrayList<>();
for (Vnf vnf : vnfs.values()) {
Map<String, Map<String, VfModule>> vfModules = vnf.getVfModules();
List<VfModule> convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules);
List<VfModule> filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules, vnf.isUserProvidedNaming());
ServiceInstantiationRequestDetails.ServiceInstantiationVnf serviceInstantiationVnf = new ServiceInstantiationRequestDetails.ServiceInstantiationVnf(
vnf.getModelInfo(),
cloudConfiguration,
vnf.getPlatformName(),
vnf.getLineOfBusiness(),
payload.getProductFamilyId(),
removeUnNeededParams(vnf.getInstanceParams()),
filteredVfModules,
vnf.isUserProvidedNaming() ? getUniqueName(vnf.getInstanceName(), ResourceType.GENERIC_VNF) : null
);
vnfList.add(serviceInstantiationVnf);
}
return new ServiceInstantiationRequestDetails.ServiceInstantiationVnfList(vnfList);
}
private List<VfModule> convertVfModuleMapToList(Map<String, Map<String, VfModule>> vfModules) {
return vfModules.values().stream().flatMap(vfModule -> vfModule.values().stream()).collect(Collectors.toList());
}
private List<VfModule> filterInstanceParamsFromVfModuleAndUniqueNames(List<VfModule> unFilteredVfModules, boolean isUserProvidedNaming) {
return unFilteredVfModules.stream().map(vfModule ->
new VfModule(
vfModule.getModelInfo(),
getUniqueNameIfNeeded(isUserProvidedNaming, vfModule.getInstanceName(), ResourceType.VF_MODULE),
getUniqueNameIfNeeded(isUserProvidedNaming, vfModule.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP),
removeUnNeededParams(vfModule.getInstanceParams())))
.collect(Collectors.toList());
}
private String getUniqueNameIfNeeded(boolean isUserProvidedNaming, String name, ResourceType resourceType) {
return isUserProvidedNaming && !StringUtils.isEmpty(name) ?
getUniqueName(name, resourceType) : null;
}
@Override
public String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest) {
//in case pause flag is true - use assign , else - use create.
return MsoBusinessLogicImpl.validateEndpointPath(
serviceInstantiationRequest.isPause() ?
"mso.restapi.serviceInstanceAssign" : "mso.restapi.serviceInstanceCreate"
);
}
@Override
public String getOrchestrationRequestsPath() {
return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ);
}
@Override
public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer<ServiceInfo> serviceUpdater) {
ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID);
serviceUpdater.accept(serviceInfo);
dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap());
return serviceInfo;
}
private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) {
serviceInfo.setJobStatus(jobStatus);
serviceInfo.setStatusModifiedDate(new Date());
}
public ServiceInfo getServiceInfoByJobId(UUID jobUUID) {
List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, String.format(" where jobId = '%s' ", jobUUID), null, null);
if (serviceInfoList.size() != 1) {
throw new GenericUncheckedException("Failed to retrieve job with uuid " + jobUUID + " from ServiceInfo table. Instances found: " + serviceInfoList.size());
}
return serviceInfoList.get(0);
}
public List<JobAuditStatus> getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) {
return dataAccessService.getList(
JobAuditStatus.class,
String.format(" where SOURCE = '%s' and JOB_ID = '%s'",source, jobUUID),
" CREATED_DATE ", null);
}
private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){
List<JobAuditStatus> list = getAuditStatuses(jobUUID,source);
return !list.isEmpty() ? list.get(list.size()-1) : null;
}
@Override
public void auditVidStatus(UUID jobUUID, JobStatus jobStatus){
JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID);
auditStatus(vidStatus);
}
@Override
public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){
auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage());
}
@Override
public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){
JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO,
requestId != null ? UUID.fromString(requestId) : null,
additionalInfo);
auditStatus(msoStatus);
}
private void auditStatus(JobAuditStatus jobAuditStatus){
JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(),jobAuditStatus.getSource());
if (latestStatus == null || !latestStatus.equals(jobAuditStatus))
dataAccessService.saveDomainObject(jobAuditStatus, DaoUtils.getPropsMap());
}
@Override
public void handleFailedInstantiation(UUID jobUUID) {
ServiceInfo serviceInfo = updateServiceInfoAndAuditStatus(jobUUID, JobStatus.FAILED);
List<ServiceInfo> serviceInfoList = dataAccessService.getList(
ServiceInfo.class,
String.format(" where templateId = '%s' and jobStatus = '%s'",
serviceInfo.getTemplateId(),
JobStatus.PENDING),
null, null);
serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED));
}
@Override
public void deleteJob(UUID jobId) {
jobService.delete(jobId);
Date now = new Date();
updateServiceInfo(jobId, x -> x.setDeletedAt(now));
}
@Override
public void hideServiceInfo(UUID jobUUID) {
ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID);
if (!serviceInfo.getJobStatus().isFinal()) {
String message = String.format( "jobId %s: Service status does not allow hide service, status = %s",
serviceInfo.getJobId(),
serviceInfo.getJobStatus());
logger.error(EELFLoggerDelegate.errorLogger, message);
throw new OperationNotAllowedException(message);
}
serviceInfo.setHidden(true);
dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap());
}
@Override
public int
getCounterForName(String name) {
String hqlSelectNC = "from NameCounter where name = :name";
String hqlUpdateCounter = "update NameCounter set counter = :newCounter " +
"where name= :name " +
"and counter= :prevCounter";
Integer counter = null;
GenericUncheckedException lastException = null;
for (int i = 0; i< MAX_RETRIES_GETTING_COUNTER && counter==null; i++) {
try {
counter = calcCounter(name, hqlSelectNC, hqlUpdateCounter);
}
catch (GenericUncheckedException exception) {
lastException = exception; //do nothing, we will try again in the loop
}
}
if (counter!=null) {
return counter;
}
throw lastException!=null ? new DbFailureUncheckedException(lastException) :
new DbFailureUncheckedException("Failed to get counter for "+name+" due to unknown error");
}
private Integer calcCounter(String name, String hqlSelectNC, String hqlUpdateCounter) {
Integer counter;
counter = DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> {
NameCounter nameCounter = (NameCounter) session.createQuery(hqlSelectNC)
.setText("name", name)
.uniqueResult();
if (nameCounter != null) {
int updatedRows = session.createQuery(hqlUpdateCounter)
.setText("name", nameCounter.getName())
.setInteger("prevCounter", nameCounter.getCounter())
.setInteger("newCounter", nameCounter.getCounter() + 1)
.executeUpdate();
if (updatedRows == 1) {
return nameCounter.getCounter() + 1;
}
} else {
Object nameAsId = session.save(new NameCounter(name));
//if save success
if (nameAsId != null) {
return 1;
}
}
//in case of failure return null, in order to continue the loop
return null;
});
return counter;
}
@Override
public int getMaxRetriesGettingFreeNameFromAai() {
return maxRetriesGettingFreeNameFromAai;
}
@Override
public void setMaxRetriesGettingFreeNameFromAai(int maxRetriesGettingFreeNameFromAai) {
this.maxRetriesGettingFreeNameFromAai = maxRetriesGettingFreeNameFromAai;
}
@Override
public String getUniqueName(String name, ResourceType resourceType) {
//check that name aai response well before increasing counter from DB
//Prevents unnecessary increasing of the counter while AAI doesn't response
isNameFreeInAai(NAME_FOR_CHECK_AAI_STATUS, resourceType);
for (int i=0; i<getMaxRetriesGettingFreeNameFromAai(); i++) {
int counter = getCounterForName(name);
String newName = formatNameAndCounter(name, counter);
if (isNameFreeInAai(newName, resourceType)) {
return newName;
}
}
throw new MaxRetriesException("find unused name for "+name, getMaxRetriesGettingFreeNameFromAai());
}
//the method is protected so we can call it in the UT
protected String formatNameAndCounter(String name, int counter) {
return name + "_" + String.format("%03d", counter);
}
private boolean isNameFreeInAai(String name, ResourceType resourceType) throws InvalidAAIResponseException {
AaiResponse<AaiNodeQueryResponse> aaiResponse = aaiClient.searchNodeTypeByName(name, resourceType);
if (aaiResponse.getHttpCode() > 399 || aaiResponse.getT() == null) {
throw new InvalidAAIResponseException(aaiResponse);
}
return CollectionUtils.isEmpty(aaiResponse.getT().resultData);
}
*/
}