From e601bbdc43bae9a08e2e10c5139a6f76b47860d7 Mon Sep 17 00:00:00 2001 From: Einat Vinouze Date: Tue, 16 Jul 2019 17:17:36 +0300 Subject: Implant vid-app-common org.onap.vid.job (main and test) Issue-ID: VID-378 Change-Id: I41b0bdc2c4e3635f3f3319b1cd63cefc61912dfc Signed-off-by: Einat Vinouze Signed-off-by: Ittay Stern --- .../src/main/java/org/onap/vid/job/Job.java | 13 +- .../src/main/java/org/onap/vid/job/JobAdapter.java | 8 +- .../src/main/java/org/onap/vid/job/JobCommand.java | 4 +- .../main/java/org/onap/vid/job/JobException.java | 4 +- .../src/main/java/org/onap/vid/job/JobType.java | 28 +- .../java/org/onap/vid/job/JobsBrokerService.java | 5 +- .../main/java/org/onap/vid/job/NextCommand.java | 4 +- .../onap/vid/job/command/ALaCarteServiceCommand.kt | 96 ++--- .../ALaCarteServiceInstantiationCommand.java | 41 -- .../vid/job/command/AggregateStateCommand.java | 4 +- .../job/command/BaseInProgressStatusCommand.java | 115 ------ .../vid/job/command/BaseInstantiationCommand.java | 38 -- .../org/onap/vid/job/command/BaseRootCommand.java | 61 --- .../onap/vid/job/command/BaseWatchingCommand.java | 90 ----- .../java/org/onap/vid/job/command/CommandBase.java | 4 +- .../onap/vid/job/command/CommandParentData.java | 37 +- .../org/onap/vid/job/command/CommandUtils.java | 4 +- .../org/onap/vid/job/command/ExpiryChecker.java | 4 +- .../org/onap/vid/job/command/HttpCallCommand.java | 4 +- .../vid/job/command/InProgressStatusService.java | 21 +- .../onap/vid/job/command/InstanceGroupCommand.kt | 34 +- .../command/InstanceGroupInstantiationCommand.java | 67 ---- .../vid/job/command/InstanceGroupMemberCommand.kt | 63 ++++ .../onap/vid/job/command/JobCommandFactory.java | 4 +- .../onap/vid/job/command/MacroServiceCommand.kt | 98 +++++ .../command/MacroServiceInstantiationCommand.java | 46 --- .../org/onap/vid/job/command/MsoRequestBuilder.kt | 411 +++++++++++++++++++++ .../vid/job/command/MsoResultHandlerService.kt | 27 +- .../org/onap/vid/job/command/NetworkCommand.kt | 65 ++++ .../job/command/NetworkInstantiationCommand.java | 61 --- .../java/org/onap/vid/job/command/NoOpCommand.java | 4 +- .../org/onap/vid/job/command/ResourceCommand.kt | 172 +++++++-- .../command/ResourceInProgressStatusCommand.java | 52 --- .../job/command/ResourceInstantiationCommand.java | 107 ------ .../ResourceWithChildrenInProgressCommand.java | 85 ----- .../org/onap/vid/job/command/RootServiceCommand.kt | 98 +++++ .../command/ServiceInProgressStatusCommand.java | 120 ------ .../job/command/ServiceInstantiationCommand.java | 126 ------- .../org/onap/vid/job/command/VfmoduleCommand.kt | 106 ++++++ .../job/command/VfmoduleInstantiationCommand.java | 64 ---- .../java/org/onap/vid/job/command/VnfCommand.kt | 140 +++++++ .../job/command/VnfInProgressStatusCommand.java | 107 ------ .../vid/job/command/VnfInstantiationCommand.java | 70 ---- .../org/onap/vid/job/command/VolumeGroupCommand.kt | 94 +++++ .../VolumeGroupInProgressStatusCommand.java | 85 ----- .../command/VolumeGroupInstantiationCommand.java | 103 ------ .../onap/vid/job/command/WatchChildrenJobsBL.kt | 6 +- .../org/onap/vid/job/command/WatchingCommand.java | 53 --- .../vid/job/command/WatchingCommandBaseModule.java | 113 ------ .../impl/DeleteOldJobsSchedulerInitializer.java | 96 +++++ .../org/onap/vid/job/impl/DeleteOldJobsWorker.java | 49 +++ .../java/org/onap/vid/job/impl/JobAdapterImpl.java | 25 +- .../java/org/onap/vid/job/impl/JobDaoImpl.java | 28 +- .../main/java/org/onap/vid/job/impl/JobData.java | 4 +- .../onap/vid/job/impl/JobSchedulerInitializer.java | 27 +- .../java/org/onap/vid/job/impl/JobSharedData.java | 18 +- .../main/java/org/onap/vid/job/impl/JobWorker.java | 31 +- .../job/impl/JobsBrokerServiceInDatabaseImpl.java | 144 +++++--- 58 files changed, 1693 insertions(+), 1895 deletions(-) delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceInstantiationCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/BaseInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/BaseInstantiationCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/BaseRootCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/BaseWatchingCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupMemberCommand.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/NetworkCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/NetworkInstantiationCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInstantiationCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ResourceWithChildrenInProgressCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VnfInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VnfInstantiationCommand.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupCommand.kt delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInProgressStatusCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInstantiationCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommand.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommandBaseModule.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java (limited to 'vid-app-common/src/main/java/org/onap/vid/job') diff --git a/vid-app-common/src/main/java/org/onap/vid/job/Job.java b/vid-app-common/src/main/java/org/onap/vid/job/Job.java index 3825c2cde..197e03b7b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/Job.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/Job.java @@ -7,9 +7,9 @@ * 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. @@ -23,8 +23,11 @@ package org.onap.vid.job; import com.fasterxml.jackson.annotation.JsonIgnore; import org.onap.vid.job.impl.JobSharedData; +import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; public interface Job { @@ -63,7 +66,9 @@ public interface Job { STOPPED(true, true), COMPLETED_WITH_ERRORS(true, true), COMPLETED_WITH_NO_ACTION(true, false), - CREATING(false); + CREATING(false), + PENDING_RESOURCE(false), + ; private final Boolean finalStatus; public Boolean isFinal(){return finalStatus;} @@ -83,5 +88,7 @@ public interface Job { this.failure = failure; } + public static final List FINAL_STATUS = Stream.of(JobStatus.values()).filter(JobStatus::isFinal).collect(Collectors.toList()); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobAdapter.java b/vid-app-common/src/main/java/org/onap/vid/job/JobAdapter.java index cd2ab8e4b..53b8a3028 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobAdapter.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobAdapter.java @@ -7,9 +7,9 @@ * 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. @@ -32,9 +32,9 @@ import java.util.UUID; public interface JobAdapter { JobModel toModel(Job job); - Job createServiceInstantiationJob(JobType jobType, AsyncJobRequest request, UUID templateId, String userId, String optimisticUniqueServiceInstanceName, Integer indexInBulk); + Job createServiceInstantiationJob(JobType jobType, AsyncJobRequest request, UUID templateId, String userId, String testApi, String optimisticUniqueServiceInstanceName, Integer indexInBulk); - Job createChildJob(JobType jobType, Job.JobStatus jobStatus, AsyncJobRequest request, JobSharedData parentSharedData, Map jobData); + Job createChildJob(JobType jobType, AsyncJobRequest request, JobSharedData parentSharedData, Map jobData, int indexInBulk); // Marks types that are an AsyncJob payload interface AsyncJobRequest { diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/JobCommand.java index 9d49df003..dfeacae66 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobException.java b/vid-app-common/src/main/java/org/onap/vid/job/JobException.java index 0ae0b1b98..eb2fecc8e 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobException.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobException.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobType.java b/vid-app-common/src/main/java/org/onap/vid/job/JobType.java index 7576c430f..b0cfa7a58 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobType.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobType.java @@ -7,9 +7,9 @@ * 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. @@ -32,26 +32,20 @@ public enum JobType { HttpCall(HttpCallCommand.class), AggregateState(AggregateStateCommand.class), - ServiceInstantiation(MacroServiceInstantiationCommand.class), - MacroServiceInstantiation(MacroServiceInstantiationCommand.class), - ALaCarteServiceInstantiation(ALaCarteServiceInstantiationCommand.class), + ServiceInstantiation(MacroServiceCommand.class), + MacroServiceInstantiation(MacroServiceCommand.class), + ALaCarteServiceInstantiation(ALaCarteServiceCommand.class), ALaCarteService(ALaCarteServiceCommand.class), - VnfInstantiation(VnfInstantiationCommand.class), - VfmoduleInstantiation(VfmoduleInstantiationCommand.class), - VolumeGroupInstantiation(VolumeGroupInstantiationCommand.class), - VolumeGroupInProgressStatus(VolumeGroupInProgressStatusCommand.class), - NetworkInstantiation(NetworkInstantiationCommand.class), - InstanceGroupInstantiation(InstanceGroupInstantiationCommand.class), + VnfInstantiation(VnfCommand.class), + VfmoduleInstantiation(VfmoduleCommand.class), + VolumeGroupInstantiation(VolumeGroupCommand.class), + NetworkInstantiation(NetworkCommand.class), InstanceGroup(InstanceGroupCommand.class), - InProgressStatus(ServiceInProgressStatusCommand.class), - ResourceInProgressStatus(ResourceInProgressStatusCommand.class), - VnfInProgressStatus(VnfInProgressStatusCommand.class), - Watching(WatchingCommand.class), - WatchingBaseModule(WatchingCommandBaseModule.class), + InstanceGroupMember(InstanceGroupMemberCommand.class), NoOp(NoOpCommand.class); private static final Map REVERSE_MAP = Stream.of(values()) - .filter(not(jobType -> jobType.equals(ServiceInstantiation))) + .filter(not(jobType -> (jobType == ServiceInstantiation) || (jobType == ALaCarteServiceInstantiation))) .collect(Collectors.toMap(t -> t.getCommandClass(), t -> t)); private final Class commandClass; diff --git a/vid-app-common/src/main/java/org/onap/vid/job/JobsBrokerService.java b/vid-app-common/src/main/java/org/onap/vid/job/JobsBrokerService.java index 5da3b309a..6c3eeb9a4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/JobsBrokerService.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/JobsBrokerService.java @@ -7,9 +7,9 @@ * 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. @@ -40,4 +40,5 @@ public interface JobsBrokerService { boolean mute(UUID jobId); + void deleteOldFinalJobs(long secondsAgo); } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/NextCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/NextCommand.java index 966158fb9..298a3f439 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/NextCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/NextCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceCommand.kt index 29897aceb..9bef3c11b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceCommand.kt @@ -7,9 +7,9 @@ * 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. @@ -21,14 +21,16 @@ package org.onap.vid.job.command import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate -import org.onap.vid.changeManagement.RequestDetailsWrapper -import org.onap.vid.job.* -import org.onap.vid.model.Action +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.serviceInstantiation.BaseResource import org.onap.vid.model.serviceInstantiation.ServiceInstantiation import org.onap.vid.mso.RestMsoImplementation -import org.onap.vid.mso.model.ServiceDeletionRequestDetails import org.onap.vid.properties.VidProperties import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.onap.vid.services.AuditService import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.context.annotation.Scope @@ -38,6 +40,8 @@ import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import java.util.* +const val UNIQUE_INSTANCE_NAME = "optimisticUniqueServiceInstanceName" + class ServiceExpiryChecker : ExpiryChecker { override fun isExpired(jobStartTime: ZonedDateTime?): Boolean { @@ -48,22 +52,20 @@ class ServiceExpiryChecker : ExpiryChecker { } } - @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) class ALaCarteServiceCommand @Autowired constructor( inProgressStatusService: InProgressStatusService, watchChildrenJobsBL: WatchChildrenJobsBL, private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, - private val jobsBrokerService: JobsBrokerService, + jobsBrokerService: JobsBrokerService, + private val msoRequestBuilder: MsoRequestBuilder, msoResultHandlerService: MsoResultHandlerService, - private val jobAdapter: JobAdapter, - restMso: RestMsoImplementation -) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, watchChildrenJobsBL), JobCommand { - - override fun getExpiryChecker(): ExpiryChecker { - return ServiceExpiryChecker(); - } + jobAdapter: JobAdapter, + restMso: RestMsoImplementation, + auditService: AuditService +) : RootServiceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter, asyncInstantiationBL, auditService, msoRequestBuilder), JobCommand { companion object { private val LOGGER = EELFLoggerDelegate.getLogger(ALaCarteServiceCommand::class.java) @@ -74,69 +76,27 @@ class ALaCarteServiceCommand @Autowired constructor( } override fun createChildren(): Job.JobStatus { - val dataForChild = buildDataForChild(getRequest())//.plus(ACTION_PHASE to actionPhase) - - val childJobType = when (actionPhase) { - Action.Create -> JobType.InstanceGroupInstantiation - Action.Delete -> JobType.InstanceGroup - else -> return Job.JobStatus.COMPLETED - } + val dataForChild = buildDataForChild(getRequest(), actionPhase) - childJobs = getRequest().vnfGroups - .map { jobAdapter.createChildJob(childJobType, Job.JobStatus.CREATING, it.value, sharedData, dataForChild) } - .map { jobsBrokerService.add(it) } - .map { it.toString() } + childJobs = pushChildrenJobsToBroker(getRequest().children, dataForChild) return Job.JobStatus.COMPLETED_WITH_NO_ACTION } - private fun buildDataForChild(request: ServiceInstantiation): Map { - val commandParentData = CommandParentData() - commandParentData.addInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID, request.instanceId) + override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + val instanceId = getActualInstanceId(request) + commandParentData.addInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID, instanceId) commandParentData.addModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO, request.modelInfo) - return commandParentData.parentData } - override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { - TODO("not implemented") - } - - override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { - val requestDetailsWrapper = generateServiceDeletionRequest() - val path = asyncInstantiationBL.getServiceDeletionPath(getRequest().instanceId) - return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.empty(), - "delete instance with id ${getRequest().instanceId}") - - } + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val instantiatePath = asyncInstantiationBL.getServiceInstantiationPath(request as ServiceInstantiation) - override fun handleInProgressStatus(jobStatus: Job.JobStatus): Job.JobStatus { - if (jobStatus==Job.JobStatus.FAILED) { - asyncInstantiationBL.handleFailedInstantiation(sharedData.jobUuid) - return jobStatus - } + val requestDetailsWrapper = msoRequestBuilder.generateALaCarteServiceInstantiationRequest( + request, optimisticUniqueServiceInstanceName, userId) - asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, jobStatus) - return if (jobStatus == Job.JobStatus.PAUSE) Job.JobStatus.IN_PROGRESS else jobStatus - } - - - private fun generateServiceDeletionRequest(): RequestDetailsWrapper { - return asyncInstantiationBL.generateALaCarteServiceDeletionRequest( - sharedData.jobUuid, getRequest(), sharedData.userId - ) - } - - override fun getExternalInProgressStatus() = Job.JobStatus.IN_PROGRESS - - override fun isServiceCommand(): Boolean = true - - override fun onFinal(jobStatus: Job.JobStatus) { - asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, jobStatus) - } + val actionDescription = "create service instance" - override fun onInitial(phase: Action) { - if (phase== Action.Delete) { - asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, Job.JobStatus.IN_PROGRESS) - } + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceInstantiationCommand.java deleted file mode 100644 index 38d5ede8a..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ALaCarteServiceInstantiationCommand.java +++ /dev/null @@ -1,41 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobCommand; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class ALaCarteServiceInstantiationCommand extends ServiceInstantiationCommand implements JobCommand { - - @Override - protected RequestDetailsWrapper generateServiceInstantiationRequest() { - return asyncInstantiationBL.generateALaCarteServiceInstantiationRequest( - getSharedData().getJobUuid(), getRequest(), optimisticUniqueServiceInstanceName, getSharedData().getUserId() - ); - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/AggregateStateCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/AggregateStateCommand.java index e64c304cb..34861d0ef 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/AggregateStateCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/AggregateStateCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInProgressStatusCommand.java deleted file mode 100644 index d21973dc2..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInProgressStatusCommand.java +++ /dev/null @@ -1,115 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import com.google.common.collect.ImmutableMap; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.job.*; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; -import org.onap.vid.mso.rest.AsyncRequestStatus; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.togglz.core.manager.FeatureManager; - -import javax.inject.Inject; -import java.util.Map; - -public abstract class BaseInProgressStatusCommand extends BaseInstantiationCommand implements JobCommand { - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(BaseInProgressStatusCommand.class); - - @Inject - protected AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - protected JobsBrokerService jobsBrokerService; - - @Inject - protected JobAdapter jobAdapter; - - @Inject - protected RestMsoImplementation restMso; - - @Inject - protected FeatureManager featureManager; - - @Inject - protected InProgressStatusService inProgressStatusService; - - - protected String requestId; - - protected String instanceId; - - - @Override - public NextCommand call() { - - try { - Job.JobStatus jobStatus = inProgressStatusService.call(getExpiryChecker(), getSharedData(), requestId); - return processJobStatus(jobStatus); - } catch (javax.ws.rs.ProcessingException e) { - // Retry when we can't connect MSO during getStatus - LOGGER.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, will retry: {}", requestId, e, e); - return new NextCommand(Job.JobStatus.IN_PROGRESS, this); - } catch (InProgressStatusService.BadResponseFromMso e) { - return handleFailedMsoResponse(e.getMsoResponse()); - } - catch (RuntimeException e) { - LOGGER.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, stopping: {}", requestId, e, e); - return new NextCommand(Job.JobStatus.STOPPED, this); - } - } - - protected abstract ExpiryChecker getExpiryChecker(); - - abstract NextCommand processJobStatus(Job.JobStatus jobStatus); - - private NextCommand handleFailedMsoResponse(RestObject msoResponse) { - inProgressStatusService.handleFailedMsoResponse(getSharedData().getJobUuid(), requestId, msoResponse); - return new NextCommand(Job.JobStatus.IN_PROGRESS, this); - } - - @Override - public BaseInProgressStatusCommand init(JobSharedData sharedData, Map commandData) { - return init(sharedData, (String) commandData.get("requestId"), (String) commandData.get("instanceId")); - } - - - protected BaseInProgressStatusCommand init(JobSharedData sharedData, - String requestId, - String instanceId) { - init(sharedData); - this.requestId = requestId; - this.instanceId = instanceId; - return this; - } - - @Override - public Map getData() { - return ImmutableMap.of( - "requestId", requestId, - "instanceId", instanceId - ); - } - - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInstantiationCommand.java deleted file mode 100644 index 20d71ab29..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseInstantiationCommand.java +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.impl.JobSharedData; - -import java.util.Map; - - -public abstract class BaseInstantiationCommand extends CommandBase{ - - - protected CommandParentData commandParentData = new CommandParentData(); - - protected BaseInstantiationCommand init(JobSharedData sharedData, Map commandData) { - super.init(sharedData); - commandParentData.initParentData(commandData); - return this; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseRootCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/BaseRootCommand.java deleted file mode 100644 index 4b81a9412..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseRootCommand.java +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.mso.RestObject; - -import javax.inject.Inject; - - -public abstract class BaseRootCommand extends CommandBase{ - - @Inject - private MsoResultHandlerService msoResultHandlerService; - - @Override - protected CommandBase init(JobSharedData sharedData) { - super.init(sharedData); - return this; - } - - protected ServiceInstantiation getRequest() { - return msoResultHandlerService.getRequest(getSharedData()); - } - - protected NextCommand handleRootResponse(RestObject msoResponse){ - MsoResult msoResult = msoResultHandlerService.handleRootResponse(getSharedData().getJobUuid(), msoResponse); - return new NextCommand(msoResult.getJobStatus(), - (msoResult.getMsoResourceIds()!=null) ? - new ServiceInProgressStatusCommand(getSharedData(), msoResult.getMsoResourceIds()) : - null - ); - - } - - protected NextCommand handleCommandFailed() { - return new NextCommand(msoResultHandlerService.handleRootCommandFailed(getSharedData().getJobUuid()).getJobStatus()); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseWatchingCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/BaseWatchingCommand.java deleted file mode 100644 index a0b7cd784..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/BaseWatchingCommand.java +++ /dev/null @@ -1,90 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.apache.commons.lang3.ObjectUtils; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobCommand; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public abstract class BaseWatchingCommand extends BaseInstantiationCommand implements JobCommand { - - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(BaseWatchingCommand.class); - - @Inject - protected AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - private WatchChildrenJobsBL watchChildrenJobsBL; - - private List childrenJobsIds; - - protected boolean isService; - - public BaseWatchingCommand() {} - - public BaseWatchingCommand(JobSharedData sharedData, List childrenJobsIds, boolean isService) { - init(sharedData, childrenJobsIds, isService); - } - - @Override - public NextCommand call() { - Job.JobStatus cumulativeJobsStatus = watchChildrenJobsBL.cumulateJobStatus( - watchChildrenJobsBL.retrieveChildrenJobsStatus(childrenJobsIds), - Job.JobStatus.COMPLETED); - return getNextCommand(cumulativeJobsStatus); - } - - protected abstract NextCommand getNextCommand(Job.JobStatus cumulativeJobsStatus); - - @Override - public BaseWatchingCommand init(JobSharedData sharedData, Map commandData) { - return init( - sharedData, - (List) commandData.get("childrenJobs"), - (boolean) commandData.get("isService") - ); - } - - protected BaseWatchingCommand init(JobSharedData sharedData, List childrenJobsIds, boolean isService) { - super.init(sharedData); - this.childrenJobsIds = ObjectUtils.defaultIfNull(childrenJobsIds, new ArrayList<>()); - this.isService = isService; - return this; - } - - @Override - public Map getData() { - Map data = new HashMap<>(); - data.put("childrenJobs", childrenJobsIds); - data.put("isService", isService); - return data; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandBase.java b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandBase.java index a13e4dc38..a9b524e01 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandBase.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandBase.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandParentData.java b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandParentData.java index 35f631183..744b2fe39 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandParentData.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandParentData.java @@ -7,9 +7,9 @@ * 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. @@ -21,12 +21,15 @@ package org.onap.vid.job.command; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.onap.vid.model.Action; import org.onap.vid.mso.model.ModelInfo; import java.util.HashMap; import java.util.Map; +import static java.util.Collections.emptyMap; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + public class CommandParentData { @@ -36,6 +39,7 @@ public class CommandParentData { VNF_INSTANCE_ID, VNF_MODEL_INFO, VG_INSTANCE_ID, + VNF_GROUP_INSTANCE_ID, ; } @@ -49,32 +53,30 @@ public class CommandParentData { new TypeReference> () {}; - private ObjectMapper objectMapper = new ObjectMapper(); - private Map getModelInfosByCommandData(Map commandData) { - Object object = commandData.get(RESOURCE_MODEL_INFOS); - if (object != null) { - return objectMapper.convertValue(object, mapCommandKeyToModelInfo); - } - return null; + Object object = commandData.getOrDefault(RESOURCE_MODEL_INFOS, emptyMap()); + return JACKSON_OBJECT_MAPPER.convertValue(object, mapCommandKeyToModelInfo); } private Map getInstanceIdsByCommandData(Map commandData) { - Object object = commandData.get(RESOURCE_INSTANCE_IDS); - if (object != null) { - return objectMapper.convertValue(object, mapCommandKeyToString); - } - return null; + Object object = commandData.getOrDefault(RESOURCE_INSTANCE_IDS, emptyMap()); + return JACKSON_OBJECT_MAPPER.convertValue(object, mapCommandKeyToString); } public Map getParentData() { Map data = new HashMap<>(); data.put(RESOURCE_INSTANCE_IDS, resourceInstancesIds); data.put(RESOURCE_MODEL_INFOS, resourceModelInfos); + + if (actionPhase != null) { + data.put(ResourceCommandKt.ACTION_PHASE, actionPhase); + } + return data; } private Map resourceInstancesIds = new HashMap<>(); private Map resourceModelInfos = new HashMap<>(); + private Action actionPhase = null; public void addModelInfo(CommandDataKey modelInfoKey, ModelInfo modelInfo) { resourceModelInfos.put(modelInfoKey, modelInfo); @@ -83,6 +85,11 @@ public class CommandParentData { public void addInstanceId(CommandDataKey instanceIdKey, String instanceId) { resourceInstancesIds.put(instanceIdKey, instanceId); } + + public void setActionPhase(Action actionPhase) { + this.actionPhase = actionPhase; + } + public ModelInfo getModelInfo(CommandDataKey modelInfoKey) { return resourceModelInfos.get(modelInfoKey); } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandUtils.java b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandUtils.java index e9936ed4c..0fe7255c4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/CommandUtils.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/CommandUtils.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ExpiryChecker.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ExpiryChecker.java index c41963d14..5d608255a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ExpiryChecker.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/ExpiryChecker.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/HttpCallCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/HttpCallCommand.java index 21c10ffac..9dc88dfea 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/HttpCallCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/HttpCallCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/InProgressStatusService.java b/vid-app-common/src/main/java/org/onap/vid/job/command/InProgressStatusService.java index 842a1bd17..3d1d78f8b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/InProgressStatusService.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/InProgressStatusService.java @@ -7,9 +7,9 @@ * 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. @@ -26,10 +26,12 @@ import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.mso.RestMsoImplementation; import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; +import org.onap.vid.properties.Features; import org.onap.vid.services.AsyncInstantiationBusinessLogic; import org.onap.vid.services.AuditService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.togglz.core.manager.FeatureManager; import java.time.ZonedDateTime; import java.time.format.DateTimeParseException; @@ -48,30 +50,37 @@ public class InProgressStatusService { private final AuditService auditService; + private final FeatureManager featureManager; + @Autowired - public InProgressStatusService(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso, AuditService auditService) { + public InProgressStatusService(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso, AuditService auditService, FeatureManager featureManager) { this.asyncInstantiationBL = asyncInstantiationBL; this.restMso = restMso; this.auditService = auditService; + this.featureManager = featureManager; } public Job.JobStatus call(ExpiryChecker expiryChecker, JobSharedData sharedData, String requestId) { RestObject asyncRequestStatus = getAsyncRequestStatus(requestId); - asyncInstantiationBL.auditMsoStatus(sharedData.getRootJobId(), asyncRequestStatus.get().request); + auditService.auditMsoStatus(sharedData.getRootJobId(), asyncRequestStatus.get().request); Job.JobStatus jobStatus = asyncInstantiationBL.calcStatus(asyncRequestStatus.get()); ZonedDateTime jobStartTime = getZonedDateTime(asyncRequestStatus, requestId); jobStatus = expiryChecker.isExpired(jobStartTime) ? Job.JobStatus.FAILED : jobStatus; + asyncInstantiationBL.updateResourceInfo(sharedData, jobStatus, asyncRequestStatus.get()); return jobStatus; } - private RestObject getAsyncRequestStatus(String requestId) { - String path = asyncInstantiationBL.getOrchestrationRequestsPath()+"/"+requestId; + RestObject getAsyncRequestStatus(String requestId) { + String path = asyncInstantiationBL.getOrchestrationRequestsPath() + "/" + requestId + + (featureManager.isActive(Features.FLAG_1908_RESUME_MACRO_SERVICE) ? "?format=detail" : ""); RestObject msoResponse = restMso.GetForObject(path, AsyncRequestStatus.class); + if (msoResponse.getStatusCode() >= 400 || msoResponse.get() == null) { throw new BadResponseFromMso(msoResponse); } + return msoResponse; } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupCommand.kt index e81fcd34e..26fb9aa09 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupCommand.kt @@ -7,9 +7,9 @@ * 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. @@ -24,6 +24,8 @@ import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate import org.onap.vid.job.Job import org.onap.vid.job.JobAdapter import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.serviceInstantiation.BaseResource import org.onap.vid.model.serviceInstantiation.InstanceGroup import org.onap.vid.mso.RestMsoImplementation import org.onap.vid.services.AsyncInstantiationBusinessLogic @@ -39,29 +41,42 @@ import java.util.* class InstanceGroupCommand @Autowired constructor( private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, msoResultHandlerService: MsoResultHandlerService, inProgressStatusService:InProgressStatusService, - watchChildrenJobsBL: WatchChildrenJobsBL -) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, watchChildrenJobsBL), JobCommand { + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter + ) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { companion object { private val LOGGER = EELFLoggerDelegate.getLogger(InstanceGroupCommand::class.java) } override fun createChildren(): Job.JobStatus { + val dataForChild = buildDataForChild(getRequest(), actionPhase) + + childJobs = pushChildrenJobsToBroker(getRequest().vnfGroupMembers.values, dataForChild); + return Job.JobStatus.COMPLETED_WITH_NO_ACTION } - override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + commandParentData.addInstanceId(CommandParentData.CommandDataKey.VNF_GROUP_INSTANCE_ID, request.instanceId) + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) val instantiatePath = asyncInstantiationBL.getInstanceGroupInstantiationPath() - val requestDetailsWrapper = asyncInstantiationBL.generateInstanceGroupInstantiationRequest( + val requestDetailsWrapper = msoRequestBuilder.generateInstanceGroupInstantiationRequest( request as InstanceGroup, serviceModelInfo, serviceInstanceId, - userId + userId, + testApi ) val actionDescription = "create instance group in $serviceInstanceId" @@ -76,4 +91,7 @@ class InstanceGroupCommand @Autowired constructor( } -} + override fun getRequest(): InstanceGroup { + return sharedData.request as InstanceGroup + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupInstantiationCommand.java deleted file mode 100644 index 6d9ddd499..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupInstantiationCommand.java +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command;//package org.onap.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.Action; -import org.onap.vid.model.serviceInstantiation.InstanceGroup; -import org.onap.vid.mso.model.InstanceGroupInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class InstanceGroupInstantiationCommand extends ResourceInstantiationCommand { - - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getInstanceGroupInstantiationPath(); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateInstanceGroupInstantiationRequest( - (InstanceGroup) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "INSTANCE_GROUP_REQUESTED"; - } - - @Override - protected boolean shouldInstantiateMyself() { - return Action.Create == ((InstanceGroup) getSharedData().getRequest()).getAction(); - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupMemberCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupMemberCommand.kt new file mode 100644 index 000000000..d8e9297a3 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/InstanceGroupMemberCommand.kt @@ -0,0 +1,63 @@ +package org.onap.vid.job.command + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.serviceInstantiation.InstanceGroupMember +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class InstanceGroupMemberCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(InstanceGroupMemberCommand::class.java) + } + + override fun createChildren(): Job.JobStatus { + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val instanceGroupId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_GROUP_INSTANCE_ID) + + val instantiatePath = asyncInstantiationBL.getInstanceGroupMemberInstantiationPath(instanceGroupId) + + val requestDetailsWrapper = msoRequestBuilder.generateInstanceGroupMemberRequest(getRequest().instanceId, userId) + + val actionDescription = "add instance group member ${getRequest().instanceId} to instance group $instanceGroupId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val instanceGroupId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_GROUP_INSTANCE_ID) + val path = asyncInstantiationBL.getInstanceGroupMemberDeletePath(instanceGroupId) + val requestDetailsWrapper = msoRequestBuilder.generateInstanceGroupMemberRequest(getRequest().instanceId, userId) + return MsoRestCallPlan(HttpMethod.POST, path, Optional.of(requestDetailsWrapper), Optional.of(userId), + "delete instance group member ${getRequest().instanceId} from instance group $instanceGroupId") + } + + override fun getRequest(): InstanceGroupMember { + return sharedData.request as InstanceGroupMember + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/JobCommandFactory.java b/vid-app-common/src/main/java/org/onap/vid/job/command/JobCommandFactory.java index 9f9a62201..32828ad5c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/JobCommandFactory.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/JobCommandFactory.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt new file mode 100644 index 000000000..8ce73d713 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceCommand.kt @@ -0,0 +1,98 @@ +package org.onap.vid.job.command + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.aai.ExceptionWithRequestInfo +import org.onap.vid.changeManagement.RequestDetailsWrapper +import org.onap.vid.exceptions.AbortingException +import org.onap.vid.exceptions.MaxRetriesException +import org.onap.vid.exceptions.TryAgainException +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.Action +import org.onap.vid.model.VidNotions.ModelCategory.* +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.onap.vid.services.AuditService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class MacroServiceCommand @Autowired constructor( + inProgressStatusService: InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + jobsBrokerService: JobsBrokerService, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + jobAdapter: JobAdapter, + restMso: RestMsoImplementation, + auditService: AuditService +) : RootServiceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter, asyncInstantiationBL, auditService, msoRequestBuilder), JobCommand { + + + companion object { + private val Logger = EELFLoggerDelegate.getLogger(MacroServiceCommand::class.java) + } + + override fun createChildren(): Job.JobStatus { + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + private val pre1806Models = setOf(Transport, INFRASTRUCTURE_VPN, SERVICE_WITH_COLLECTION_RESOURCE); + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + try { + val instantiatePath = asyncInstantiationBL.getServiceInstantiationPath(request as ServiceInstantiation) + + val requestDetailsWrapper = generateRequest(sharedData.jobUuid, request, optimisticUniqueServiceInstanceName, userId) + + val actionDescription = "create macro service instance" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + } + + //Aai return bad response while checking names uniqueness + catch (exception : ExceptionWithRequestInfo) { + Logger.error("Failed to check name uniqueness in AAI. VID will try again later", exception) + throw TryAgainException(exception); + } + + //Vid reached to max retries while trying to find unique name in AAI + catch (exception : MaxRetriesException) { + Logger.error("Failed to find unused name in AAI", exception) + throw AbortingException(exception); + } + } + + private fun generateRequest(jobUuid: UUID?, request: ServiceInstantiation, optimisticUniqueServiceInstanceName: String, userId: String): RequestDetailsWrapper { + // for transport or for infrastructure VPN - send the pre 1806 request + if (shouldUsePre1806Request(request)){ + return msoRequestBuilder.generateMacroServicePre1806InstantiationRequest(request, userId) + } + return msoRequestBuilder.generateMacroServiceInstantiationRequest(jobUuid, request, optimisticUniqueServiceInstanceName, userId) + } + + protected fun shouldUsePre1806Request(request: ServiceInstantiation): Boolean { + return (request.vidNotions != null && pre1806Models.contains(request.vidNotions.modelCategory)) + } + + + override fun handleInProgressStatus(jobStatus: Job.JobStatus): Job.JobStatus { + asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, jobStatus) + return if (jobStatus==Job.JobStatus.PAUSE) Job.JobStatus.IN_PROGRESS else jobStatus + } + + override fun isDescendantHasAction(phase: Action): Boolean { + return false + } + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceInstantiationCommand.java deleted file mode 100644 index 6687a2c2e..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/MacroServiceInstantiationCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobCommand; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class MacroServiceInstantiationCommand extends ServiceInstantiationCommand implements JobCommand { - - public MacroServiceInstantiationCommand() { - // empty constructor - } - - @Override - protected RequestDetailsWrapper generateServiceInstantiationRequest() { - return asyncInstantiationBL.generateMacroServiceInstantiationRequest( - getSharedData().getJobUuid(), getRequest(), optimisticUniqueServiceInstanceName, getSharedData().getUserId() - ); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt new file mode 100644 index 000000000..c8502b1e5 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoRequestBuilder.kt @@ -0,0 +1,411 @@ +package org.onap.vid.job.command + +import com.google.common.collect.ImmutableList +import org.apache.commons.lang3.ObjectUtils.defaultIfNull +import org.apache.commons.lang3.StringUtils +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.aai.AaiClientInterface +import org.onap.vid.aai.ExceptionWithRequestInfo +import org.onap.vid.aai.model.ResourceType +import org.onap.vid.changeManagement.RequestDetailsWrapper +import org.onap.vid.model.serviceInstantiation.* +import org.onap.vid.mso.model.* +import org.onap.vid.mso.model.BaseResourceInstantiationRequestDetails.* +import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.UserParamMap +import org.onap.vid.mso.rest.SubscriberInfo +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.onap.vid.services.CloudOwnerService +import org.onap.vid.utils.JACKSON_OBJECT_MAPPER +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service +import org.togglz.core.manager.FeatureManager +import java.util.* +import java.util.Collections.emptyList +import java.util.stream.Collectors + +@Service +class MsoRequestBuilder +@Autowired constructor(private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + private val cloudOwnerService: CloudOwnerService, + private val aaiClient: AaiClientInterface, + private val featureManager: FeatureManager) { + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(MsoRequestBuilder::class.java) + private const val VID_SOURCE = "VID" + } + + fun generateALaCarteServiceInstantiationRequest(payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String, userId: String): RequestDetailsWrapper { + val userParams = generateUserParamList() + + val requestParameters = ServiceInstantiationRequestDetails.RequestParameters(payload.subscriptionServiceType, true, userParams, payload.testApi) + + val requestDetails = generateServiceInstantiationRequestDetails(payload, requestParameters, optimisticUniqueServiceInstanceName, userId) + + return RequestDetailsWrapper(requestDetails) + } + + fun generateServiceDeletionRequest(payload: ServiceInstantiation, userId: String): RequestDetailsWrapper { + + val requestParameters = ServiceDeletionRequestDetails.RequestParameters(payload.isALaCarte, payload.testApi) + + val requestInfo = ServiceDeletionRequestDetails.RequestInfo( + VID_SOURCE, + userId) + + val requestDetails = ServiceDeletionRequestDetails(payload.modelInfo, requestInfo, requestParameters) + + return RequestDetailsWrapper(requestDetails) + } + + fun generateMacroServiceInstantiationRequest(jobId: UUID?, payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String, userId: String): RequestDetailsWrapper { + val serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName) + + val serviceInstantiationServiceList = generateServiceInstantiationServicesList(payload, serviceInstanceName, createServiceInstantiationVnfList(jobId, payload)) + + val requestParameters = ServiceInstantiationRequestDetails.RequestParameters(payload.subscriptionServiceType, false, serviceInstantiationServiceList) + + val requestDetails = generateServiceInstantiationRequestDetails(payload, requestParameters, serviceInstanceName, userId) + + return RequestDetailsWrapper(requestDetails) + } + + fun generateNetworkInstantiationRequest(networkDetails: Network, serviceModelInfo: ModelInfo, serviceInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(networkDetails.instanceName, ResourceType.L3_NETWORK, networkDetails.isRollbackOnFailure, networkDetails.productFamilyId, userId) + val cloudConfiguration = generateCloudConfiguration(networkDetails.lcpCloudRegionId, networkDetails.tenantId) + val platform = Platform(networkDetails.platformName) + val lineOfBusiness = LineOfBusiness.of(networkDetails.lineOfBusiness) + val requestParameters = BaseResourceInstantiationRequestDetails.RequestParameters(generateUserParamList(), testApi) + val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo)) + return RequestDetailsWrapper(NetworkInstantiationRequestDetails(networkDetails.modelInfo, cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)) + } + + fun generateVnfInstantiationRequest(vnfDetails: Vnf, serviceModelInfo: ModelInfo, serviceInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(vnfDetails.instanceName, ResourceType.GENERIC_VNF, vnfDetails.isRollbackOnFailure, vnfDetails.productFamilyId, userId) + val cloudConfiguration = generateCloudConfiguration(vnfDetails.lcpCloudRegionId, vnfDetails.tenantId) + val platform = Platform(vnfDetails.platformName) + val lineOfBusiness = LineOfBusiness.of(vnfDetails.lineOfBusiness) + val requestParameters = BaseResourceInstantiationRequestDetails.RequestParameters(generateUserParamList(), testApi) + val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo)) + return RequestDetailsWrapper(VnfInstantiationRequestDetails(vnfDetails.modelInfo, cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)) + } + + fun generateDeleteVnfRequest(vnfDetails: Vnf, userId: String): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(null, null, null, null, userId) + val cloudConfiguration = generateCloudConfiguration(vnfDetails.lcpCloudRegionId, vnfDetails.tenantId) + return RequestDetailsWrapper(VnfInstantiationRequestDetails(vnfDetails.modelInfo, cloudConfiguration, requestInfo, null, null, null, null)) + } + + fun generateVfModuleInstantiationRequest(vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, vgInstanceId: String?, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(vfModuleDetails.instanceName, ResourceType.VF_MODULE, vfModuleDetails.isRollbackOnFailure, null, userId) + + //cloud configuration + val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) + + //request parameters + val userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams) + val requestParameters = VfModuleInstantiationRequestDetails.RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload, testApi) + + //related instance list + val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo, vnfInstanceId to vnfModelInfo)) + if (StringUtils.isNotEmpty(vgInstanceId)) { + val volumeGroupModel = ModelInfo() + volumeGroupModel.modelType = "volumeGroup" + relatedInstanceList.add(RelatedInstance(volumeGroupModel, vgInstanceId, vfModuleDetails.volumeGroupInstanceName)) + } + return RequestDetailsWrapper(VfModuleInstantiationRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, relatedInstanceList, requestParameters)) + } + + fun generateVolumeGroupInstantiationRequest(vfModuleDetails: VfModule, serviceModelInfo: ModelInfo, serviceInstanceId: String, vnfModelInfo: ModelInfo, vnfInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(vfModuleDetails.volumeGroupInstanceName, ResourceType.VOLUME_GROUP, vfModuleDetails.isRollbackOnFailure, null, userId) + val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) + val userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.instanceParams), vfModuleDetails.supplementaryParams) + val requestParameters = VfModuleInstantiationRequestDetails.RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload, testApi) + val relatedInstances = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo, vnfInstanceId to vnfModelInfo)) + + vfModuleDetails.modelInfo.modelType = "volumeGroup" + return RequestDetailsWrapper(VolumeGroupRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, relatedInstances, requestParameters)) + } + + fun generateInstanceGroupInstantiationRequest(instanceGroupDetails: InstanceGroup, serviceModelInfo: ModelInfo, serviceInstanceId: String, userId: String, testApi: String?): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(instanceGroupDetails.instanceName, ResourceType.INSTANCE_GROUP, instanceGroupDetails.isRollbackOnFailure, null, userId) + val requestParameters = BaseResourceInstantiationRequestDetails.RequestParameters(generateUserParamList(), testApi) + val relatedInstanceList = generateRelatedInstances(mapOf(serviceInstanceId to serviceModelInfo)) + return RequestDetailsWrapper(InstanceGroupInstantiationRequestDetails(instanceGroupDetails.modelInfo, requestInfo, relatedInstanceList, requestParameters)) + } + + fun generateInstanceGroupMemberRequest(instanceGroupMemberId: String, userId: String): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(null, null, null, null, userId) + val modelInfo = ModelInfo() + modelInfo.modelType = "vnf" + val relatedInstanceList = generateRelatedInstances(mapOf(instanceGroupMemberId to modelInfo)) + return RequestDetailsWrapper(AddOrRemoveInstanceGroupMemberRequestDetails(requestInfo, relatedInstanceList)) + } + + fun generateDeleteNetworkRequest(networkDetails: Network, userId: String): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(null, null, null, null, userId) + val cloudConfiguration = generateCloudConfiguration(networkDetails.lcpCloudRegionId, networkDetails.tenantId) + return RequestDetailsWrapper(NetworkInstantiationRequestDetails(networkDetails.modelInfo, cloudConfiguration, requestInfo, null, null, null, null)) + } + + fun generateDeleteVfModuleRequest(vfModuleDetails: VfModule, userId: String): RequestDetailsWrapper { + val requestInfo = generateRequestInfo(null, null, null, null, userId) + val cloudConfiguration = generateCloudConfiguration(vfModuleDetails.lcpCloudRegionId, vfModuleDetails.tenantId) + return RequestDetailsWrapper(VfModuleInstantiationRequestDetails(vfModuleDetails.modelInfo, cloudConfiguration, requestInfo, null, null)) + } + + private fun generateServiceName(jobId: UUID?, payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String): String? { + var serviceInstanceName: String? = null + if (StringUtils.isNotEmpty(optimisticUniqueServiceInstanceName)) { + serviceInstanceName = peekServiceName(jobId, payload, optimisticUniqueServiceInstanceName) + } + return serviceInstanceName + } + + private fun peekServiceName(jobId: UUID?, payload: ServiceInstantiation, optimisticUniqueServiceInstanceName: String): String { + val serviceInstanceName: String + // unique name already exist in service info. If it's free in AAI we use it + if (isNameFreeInAai(optimisticUniqueServiceInstanceName, ResourceType.SERVICE_INSTANCE)) { + serviceInstanceName = optimisticUniqueServiceInstanceName + } else { + serviceInstanceName = asyncInstantiationBL.getUniqueName(payload.instanceName, ResourceType.SERVICE_INSTANCE) + }//otherwise we used the original service instance name (from payload) to get a new unique name from DB and AAI + + //update serviceInfo with new name if needed + try { + asyncInstantiationBL.updateServiceInfo(jobId) { x -> x.serviceInstanceName = serviceInstanceName } + } catch (e: Exception) { + LOGGER.error("Failed updating service name {} in serviceInfo", serviceInstanceName, e) + } + + return serviceInstanceName + } + + @Throws(ExceptionWithRequestInfo::class) + private fun isNameFreeInAai(name: String, resourceType: ResourceType): Boolean { + return !aaiClient.isNodeTypeExistsByName(name, resourceType) + } + + private fun generateServiceInstantiationServicesList(payload: ServiceInstantiation, serviceInstanceName: String?, vnfList: ServiceInstantiationRequestDetails.ServiceInstantiationVnfList): List { + val serviceInstantiationServiceList = LinkedList() + val unFilteredInstanceParams = defaultIfNull>>(payload.instanceParams, emptyList()) + val filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams) + val serviceInstantiationService = ServiceInstantiationRequestDetails.ServiceInstantiationService( + payload.modelInfo, + serviceInstanceName, + filteredInstanceParams, + vnfList + ) + serviceInstantiationServiceList.add(serviceInstantiationService) + return serviceInstantiationServiceList + } + + private fun removeUnNeededParams(instanceParams: List>?): List> { + val keysToRemove = mutableListOf() + if (instanceParams.isNullOrEmpty()) { + return emptyList() + } + + for (key in instanceParams[0].keys) { + for (paramToIgnore in AsyncInstantiationBusinessLogic.PARAMS_TO_IGNORE) + if (key.equals(paramToIgnore, ignoreCase = true)) { + keysToRemove.add(key) + } + } + + val result : MutableMap = instanceParams[0].entries.stream() + .filter { entry -> !keysToRemove.contains(entry.key) } + .collect(Collectors.toMap({it.key}, {it.value})) + + return if (result.isEmpty()) emptyList() else listOf(result) + } + + private fun createServiceInstantiationVnfList(jobId: UUID?, payload: ServiceInstantiation): ServiceInstantiationRequestDetails.ServiceInstantiationVnfList { + val cloudConfiguration = generateCloudConfiguration(payload.lcpCloudRegionId, payload.tenantId) + val isBulk = asyncInstantiationBL.isPartOfBulk(jobId) + + val vnfs = payload.vnfs + val vnfList = mutableListOf() + for (vnf in vnfs.values) { + val vfModules = vnf.vfModules + val convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules) + val filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules, isBulk) + val serviceInstantiationVnf = ServiceInstantiationRequestDetails.ServiceInstantiationVnf( + vnf.modelInfo, + cloudConfiguration, + vnf.platformName, + vnf.lineOfBusiness, + payload.productFamilyId, + buildVnfInstanceParams(vnf.instanceParams, filteredVfModules), + filteredVfModules, + getUniqueNameIfNeeded(vnf.instanceName, ResourceType.GENERIC_VNF, isBulk) + ) + vnfList.add(serviceInstantiationVnf) + } + + return ServiceInstantiationRequestDetails.ServiceInstantiationVnfList(vnfList) + } + + private fun convertVfModuleMapToList(vfModules: Map>): List { + return vfModules.values.stream().flatMap { vfModule -> + vfModule.values.stream().map { item -> + val aggregatedParams = aggregateAllInstanceParams(extractActualInstanceParams(item.instanceParams), item.supplementaryParams) + val aggregatedParamsConverted = JACKSON_OBJECT_MAPPER.convertValue(aggregatedParams, List::class.java) + + VfModuleMacro( + item.modelInfo, + item.instanceName, + item.volumeGroupInstanceName, + aggregatedParamsConverted as List>) + } + }.collect(Collectors.toList()) + } + + fun aggregateAllInstanceParams(instanceParams: Map?, supplementaryParams: Map?): List> { + var instanceParamsFinal: Map = instanceParams ?: emptyMap() + val supplementaryParamsFinal: Map = supplementaryParams ?: emptyMap() + + if (!(instanceParamsFinal.isEmpty() && supplementaryParamsFinal.isEmpty())) { + //remove duplicate keys from instanceParams if exist in supplementaryParams + instanceParamsFinal = instanceParamsFinal.entries.stream() + .filter { m -> !supplementaryParamsFinal.containsKey(m.key) } + .collect(Collectors.toMap({ it.key }, { it.value })) + + //aggregate the 2 collections and format them as UserParamMap + val aggregatedParams = UserParamMap() + aggregatedParams.putAll(instanceParamsFinal) + aggregatedParams.putAll(supplementaryParamsFinal) + + return mutableListOf(aggregatedParams) + } + + return emptyList() + } + + //Make sure we always get a one Map from InstanceParams + private fun extractActualInstanceParams(originalInstanceParams: List>?): MutableMap { + return if (originalInstanceParams.isNullOrEmpty() || originalInstanceParams[0].isNullOrEmpty()) { + mutableMapOf() + } else originalInstanceParams[0] + } + + private fun filterInstanceParamsFromVfModuleAndUniqueNames(unFilteredVfModules: List, isBulk: Boolean): List { + return unFilteredVfModules.stream().map { vfModule -> + VfModuleMacro( + vfModule.modelInfo, + getUniqueNameIfNeeded(vfModule.instanceName, ResourceType.VF_MODULE, isBulk), + getUniqueNameIfNeeded(vfModule.volumeGroupInstanceName, ResourceType.VOLUME_GROUP, isBulk), + removeUnNeededParams(vfModule.instanceParams)) + } + .collect(Collectors.toList()) + } + + fun buildVnfInstanceParams(currentVnfInstanceParams: List>, vfModules: List): List> { + val filteredVnfInstanceParams = removeUnNeededParams(currentVnfInstanceParams) + + val vnfInstanceParams = extractActualInstanceParams(filteredVnfInstanceParams) + vfModules.stream() + .map { x -> extractActualInstanceParams(x.instanceParams) } + .forEach { vnfInstanceParams.putAll(it) } + return if (vnfInstanceParams.isEmpty()) emptyList() else ImmutableList.of(vnfInstanceParams) + } + + private fun generateServiceInstantiationRequestDetails(payload: ServiceInstantiation, requestParameters: ServiceInstantiationRequestDetails.RequestParameters, serviceInstanceName: String?, userId: String): ServiceInstantiationRequestDetails { + val requestInfo = ServiceInstantiationRequestDetails.RequestInfo(serviceInstanceName, + payload.productFamilyId, + VID_SOURCE, + payload.isRollbackOnFailure, + userId) + val owningEntity = ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity(payload.owningEntityId, payload.owningEntityName) + val subscriberInfo = generateSubscriberInfo(payload) + val project = if (payload.projectName != null) ServiceInstantiationRequestDetails.Project(payload.projectName) else null + return ServiceInstantiationRequestDetails(payload.modelInfo, owningEntity, subscriberInfo, project, requestInfo, requestParameters) + } + + private fun generateSubscriberInfo(payload: ServiceInstantiation): SubscriberInfo { + val subscriberInfo = SubscriberInfo() + subscriberInfo.globalSubscriberId = payload.globalSubscriberId + return subscriberInfo + } + + private fun generateCloudConfiguration(lcpCloudRegionId: String?, tenantId: String?): CloudConfiguration { + val cloudConfiguration = CloudConfiguration(lcpCloudRegionId, tenantId) + if(lcpCloudRegionId != null){ + cloudOwnerService.enrichCloudConfigurationWithCloudOwner(cloudConfiguration, lcpCloudRegionId) + } + return cloudConfiguration + } + + private fun generateRelatedInstances(relatedInstances: Map): MutableList { + return relatedInstances.entries.stream() + .map { RelatedInstance(it.value, it.key) } + .collect(Collectors.toList()) + } + + private fun generateRequestInfo(instanceName: String?, resourceType: ResourceType?, rollbackOnFailure: Boolean?, productFamilyId: String?, userId: String) : BaseResourceInstantiationRequestDetails.RequestInfo { + return BaseResourceInstantiationRequestDetails.RequestInfo( + if (resourceType == null) null else getUniqueNameIfNeeded(instanceName, resourceType, false), + productFamilyId, + VID_SOURCE, + rollbackOnFailure, + userId) + + } + + private fun getUniqueNameIfNeeded(name: String?, resourceType: ResourceType, isBulk: Boolean): String? { + return if (StringUtils.isNotEmpty(name)) { + if (isBulk) asyncInstantiationBL.getUniqueName(name, resourceType) else name + } else { + null + } + } + + private fun generateUserParamList(): List { + return emptyList() + } + + fun generateMacroServicePre1806InstantiationRequest(payload: ServiceInstantiation, userId: String): RequestDetailsWrapper { + val requestInfo = ServiceInstantiationRequestDetails.RequestInfo(payload.instanceName, payload.productFamilyId, VID_SOURCE, payload.isRollbackOnFailure, userId) + val userParams = generateUserParamsNameAndValue(payload.instanceParams) + val requestParameters = ServiceInstantiationRequestDetails.RequestParameters(payload.subscriptionServiceType, false, userParams) + val subscriberInfo = generateSubscriberInfoPre1806(payload) + val project = if (payload.projectName != null) ServiceInstantiationRequestDetails.Project(payload.projectName) else null + val owningEntity = ServiceInstantiationRequestDetails.ServiceInstantiationOwningEntity(payload.owningEntityId, payload.owningEntityName) + val cloudConfiguration = generateCloudConfiguration(payload.lcpCloudRegionId, payload.tenantId) + val relatedInstanceList = generateRelatedInstanceListForVrfEntry(payload.vrfs) + + return RequestDetailsWrapper(ServiceInstantiationPre1806RequestDetails( + payload.modelInfo, + owningEntity, + subscriberInfo, + project, + requestInfo, + requestParameters, + cloudConfiguration, + relatedInstanceList)) + } + + private fun generateUserParamsNameAndValue(instanceParams: List>): List { + if (instanceParams == null){ + return emptyList() + } + return instanceParams.getOrElse(0, {emptyMap()}).map{x-> ServiceInstantiationRequestDetails.UserParamNameAndValue(x.key, x.value)} + } + + private fun generateSubscriberInfoPre1806(payload: ServiceInstantiation): SubscriberInfo { + val subscriberInfo = SubscriberInfo() + subscriberInfo.globalSubscriberId = payload.globalSubscriberId + subscriberInfo.subscriberName = payload.subscriberName + return subscriberInfo + } + + private fun generateRelatedInstanceListForVrfEntry(vrfEntries: MutableMap): List { + //fe send map of vrfs, with maps of networks and vpns, but actually we expect to only one vpn and one network + return if (vrfEntries.isEmpty() || vrfEntries.values.first().vpns.isEmpty() || vrfEntries.values.first().networks.isEmpty()) emptyList() + else { + val vpn = vrfEntries.values.first().vpns.values.first() + val network = vrfEntries.values.first().networks.values.first() + listOf(vpn, network).map { RelatedInstance(it.modelInfo, it.instanceId, it.instanceName) } + } + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt index e1e9b1397..50eada64f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/MsoResultHandlerService.kt @@ -7,9 +7,9 @@ * 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. @@ -44,43 +44,42 @@ class MsoResultHandlerService return jobSharedData.request as ServiceInstantiation } - fun handleRootResponse(jobUUID: UUID, msoResponse: RestObject): MsoResult { + fun handleRootResponse(sharedData: JobSharedData, msoResponse: RestObject): MsoResult { + val jobUUID:UUID = sharedData.jobUuid return if (msoResponse.statusCode in 200..399) { val jobStatus = Job.JobStatus.IN_PROGRESS val msoResourceIds = MsoResourceIds(msoResponse.get().requestReferences.requestId, msoResponse.get().requestReferences.instanceId) - asyncInstantiationBL.auditVidStatus(jobUUID, jobStatus) + auditService.auditVidStatus(jobUUID, jobStatus) setInitialRequestAuditStatusFromMso(jobUUID, msoResourceIds.requestId) asyncInstantiationBL.updateServiceInfo(jobUUID) { x -> x.jobStatus = jobStatus x.serviceInstanceId = msoResourceIds.instanceId x.msoRequestId = UUID.fromString(msoResourceIds.requestId) } - MsoResult(jobStatus, msoResourceIds) + asyncInstantiationBL.addResourceInfo(sharedData, jobStatus, msoResourceIds.instanceId) + MsoResult(Job.JobStatus.COMPLETED_WITH_NO_ACTION, msoResourceIds) } else { auditService.setFailedAuditStatusFromMso(jobUUID, null, msoResponse.statusCode, msoResponse.raw) - handleRootCommandFailed(jobUUID) + asyncInstantiationBL.addFailedResourceInfo(sharedData, msoResponse) + return MsoResult(Job.JobStatus.FAILED) } } - fun handleResponse(msoResponse: RestObject, actionDescription: String): MsoResult { + fun handleResponse(sharedData: JobSharedData, msoResponse: RestObject, actionDescription: String): MsoResult { return if (msoResponse.statusCode in 200..399) { val msoResourceIds = MsoResourceIds(msoResponse.get().requestReferences.requestId, msoResponse.get().requestReferences.instanceId) LOGGER.debug("Successfully sent $actionDescription. Request id: ${msoResourceIds.requestId}") + asyncInstantiationBL.addResourceInfo(sharedData, Job.JobStatus.IN_PROGRESS, msoResourceIds.instanceId) MsoResult(Job.JobStatus.COMPLETED_WITH_NO_ACTION, msoResourceIds) } else { LOGGER.debug("Failed to $actionDescription. Details: ${msoResponse.raw}") + asyncInstantiationBL.addFailedResourceInfo(sharedData, msoResponse) MsoResult(Job.JobStatus.FAILED) } } - - fun handleRootCommandFailed(jobUUID: UUID): MsoResult { - asyncInstantiationBL.handleFailedInstantiation(jobUUID) - return MsoResult(Job.JobStatus.FAILED) - } - private fun setInitialRequestAuditStatusFromMso(jobUUID: UUID, requestId: String) { val initialMsoRequestStatus = "REQUESTED" - asyncInstantiationBL.auditMsoStatus(jobUUID, initialMsoRequestStatus, requestId, null) + auditService.auditMsoStatus(jobUUID, initialMsoRequestStatus, requestId, null) } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkCommand.kt new file mode 100644 index 000000000..bc4de7ccd --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkCommand.kt @@ -0,0 +1,65 @@ +package org.onap.vid.job.command + +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.Network +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class NetworkCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter + ) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + override fun createChildren(): Job.JobStatus { + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + + val instantiatePath = asyncInstantiationBL.getNetworkInstantiationPath(serviceInstanceId) + val requestDetailsWrapper = msoRequestBuilder.generateNetworkInstantiationRequest( + request as Network, + serviceModelInfo, + serviceInstanceId, + userId, + testApi + ) + + val actionDescription = "create network in $serviceInstanceId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val path = asyncInstantiationBL.getNetworkDeletePath(serviceInstanceId, getRequest().instanceId) + val requestDetailsWrapper = msoRequestBuilder.generateDeleteNetworkRequest(getRequest() as Network, userId) + return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId), + "delete network ${getRequest().instanceId} from service instance $serviceInstanceId") + } + + override fun isDescendantHasAction(phase: Action): Boolean { + return false + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkInstantiationCommand.java deleted file mode 100644 index 2b7f79c15..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/NetworkInstantiationCommand.java +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.serviceInstantiation.Network; -import org.onap.vid.mso.model.NetworkInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class NetworkInstantiationCommand extends ResourceInstantiationCommand { - - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getNetworkInstantiationPath(commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID)); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateNetworkInstantiationRequest( - (Network) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "NETWORK_REQUESTED"; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/NoOpCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/NoOpCommand.java index 9be37bbf2..4cc54e5d7 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/NoOpCommand.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/NoOpCommand.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt index 7f3a05be8..0e9ab7b7a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceCommand.kt @@ -7,9 +7,9 @@ * 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. @@ -20,14 +20,14 @@ package org.onap.vid.job.command + import com.fasterxml.jackson.module.kotlin.convertValue import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate import org.onap.vid.changeManagement.RequestDetailsWrapper -import org.onap.vid.job.Job +import org.onap.vid.exceptions.AbortingException +import org.onap.vid.exceptions.TryAgainException +import org.onap.vid.job.* import org.onap.vid.job.Job.JobStatus -import org.onap.vid.job.JobAdapter -import org.onap.vid.job.JobCommand -import org.onap.vid.job.NextCommand import org.onap.vid.job.impl.JobSharedData import org.onap.vid.model.Action import org.onap.vid.model.RequestReferencesContainer @@ -38,6 +38,7 @@ import org.onap.vid.utils.getEnumFromMapOfStrings import org.springframework.http.HttpMethod import java.util.* + const val INTERNAL_STATE = "internalState" const val ACTION_PHASE = "actionPhase" const val CHILD_JOBS = "childJobs" @@ -51,7 +52,9 @@ enum class InternalState constructor(val immediate:Boolean=false) { DELETE_MYSELF, CREATE_MYSELF, IN_PROGRESS, - TERMINAL + TERMINAL, + RESUME_MYSELF, + REPLACE_MYSELF, } data class NextInternalState(val nextActionPhase: Action, val nextInternalState: InternalState) @@ -69,8 +72,10 @@ abstract class ResourceCommand( protected val restMso: RestMsoImplementation, protected val inProgressStatusService: InProgressStatusService, protected val msoResultHandlerService: MsoResultHandlerService, - protected val watchChildrenJobsBL: WatchChildrenJobsBL -) : CommandBase(), JobCommand { + protected val watchChildrenJobsBL: WatchChildrenJobsBL, + private val jobsBrokerService: JobsBrokerService, + private val jobAdapter: JobAdapter + ) : CommandBase(), JobCommand { companion object { private val Logger = EELFLoggerDelegate.getLogger(ResourceCommand::class.java) @@ -78,7 +83,7 @@ abstract class ResourceCommand( abstract fun createChildren():JobStatus - abstract fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan + abstract fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan abstract fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan @@ -86,23 +91,28 @@ abstract class ResourceCommand( Pair(InternalState.CREATING_CHILDREN, ::createChildren), Pair(InternalState.WATCHING, ::watchChildren), Pair(InternalState.CREATE_MYSELF, ::createMyself), + Pair(InternalState.RESUME_MYSELF, ::resumeMyself), Pair(InternalState.DELETE_MYSELF, ::deleteMyself), - Pair(InternalState.IN_PROGRESS, ::inProgress) + Pair(InternalState.IN_PROGRESS, ::inProgress), + Pair(InternalState.REPLACE_MYSELF, ::replaceMyself) ) private lateinit var internalState:InternalState protected lateinit var actionPhase: Action - private var commandParentData: CommandParentData = CommandParentData() - private var msoResourceIds: MsoResourceIds = EMPTY_MSO_RESOURCE_ID + protected var commandParentData: CommandParentData = CommandParentData() + protected var msoResourceIds: MsoResourceIds = EMPTY_MSO_RESOURCE_ID protected var childJobs:List = emptyList() private lateinit var cumulativeStatus:JobStatus override fun call(): NextCommand { - var jobStatus:JobStatus = invokeCommand() + var jobStatus:JobStatus = if (internalState!=InternalState.TERMINAL) invokeCommand() else cumulativeStatus jobStatus = comulateStatusAndUpdatePropertyIfFinal(jobStatus) - Logger.debug("command for job ${sharedData.jobUuid} invoked and finished with jobStatus $jobStatus") + try { + Logger.debug("job: ${this.javaClass.simpleName} ${sharedData.jobUuid} $actionPhase ${getActionType()} $internalState $jobStatus $childJobs") + } catch (e:Exception) { /* do nothing. Just failed to log...*/} + if (shallStopJob(jobStatus)) { onFinal(jobStatus) return NextCommand(jobStatus) @@ -133,7 +143,17 @@ abstract class ResourceCommand( protected open fun getExternalInProgressStatus() = JobStatus.RESOURCE_IN_PROGRESS private fun invokeCommand(): JobStatus { - return commandByInternalState.getOrDefault (internalState, ::throwIllegalState).invoke() + return try { + commandByInternalState.getOrDefault(internalState, ::throwIllegalState).invoke() + } + catch (exception: TryAgainException) { + Logger.warn("caught TryAgainException. Set job status to IN_PROGRESS") + JobStatus.IN_PROGRESS + } + catch (exception: AbortingException) { + Logger.error("caught AbortingException. Set job status to FAILED") + JobStatus.FAILED; + } } private fun throwIllegalState():JobStatus { @@ -177,7 +197,7 @@ abstract class ResourceCommand( InternalState.DELETE_MYSELF -> InternalState.IN_PROGRESS InternalState.IN_PROGRESS -> { - if (jobStatus == Job.JobStatus.COMPLETED) InternalState.TERMINAL else InternalState.IN_PROGRESS + if (jobStatus == JobStatus.COMPLETED) InternalState.TERMINAL else InternalState.IN_PROGRESS } else -> InternalState.TERMINAL @@ -187,10 +207,28 @@ abstract class ResourceCommand( protected fun calcNextStateCreatePhase(jobStatus: JobStatus, internalState: InternalState): InternalState { return when (internalState) { - InternalState.CREATE_MYSELF -> InternalState.IN_PROGRESS + InternalState.CREATE_MYSELF -> when (jobStatus) { + JobStatus.IN_PROGRESS -> InternalState.CREATE_MYSELF + else -> InternalState.IN_PROGRESS + } + + InternalState.RESUME_MYSELF -> when (jobStatus) { + JobStatus.IN_PROGRESS -> InternalState.RESUME_MYSELF + else -> InternalState.IN_PROGRESS + } + + InternalState.REPLACE_MYSELF -> when (jobStatus) { + JobStatus.IN_PROGRESS -> InternalState.REPLACE_MYSELF + else -> InternalState.IN_PROGRESS + } InternalState.IN_PROGRESS -> { - if (jobStatus == Job.JobStatus.COMPLETED) InternalState.CREATING_CHILDREN else InternalState.IN_PROGRESS + when { + jobStatus != JobStatus.COMPLETED -> InternalState.IN_PROGRESS + isDescendantHasAction(Action.Create) -> InternalState.CREATING_CHILDREN + isDescendantHasAction(Action.Replace) -> InternalState.CREATING_CHILDREN + else -> InternalState.TERMINAL + } } InternalState.CREATING_CHILDREN -> InternalState.WATCHING @@ -202,7 +240,6 @@ abstract class ResourceCommand( } } - else -> InternalState.TERMINAL } } @@ -214,7 +251,7 @@ abstract class ResourceCommand( MSO_RESOURCE_ID to msoResourceIds, CHILD_JOBS to childJobs, CUMULATIVE_STATUS to cumulativeStatus - ) + ) + commandParentData.parentData } override fun init(sharedData: JobSharedData, commandData: Map): ResourceCommand { @@ -232,13 +269,24 @@ abstract class ResourceCommand( return this } - private fun calcInitialState(commandData: Map, phase: Action):InternalState { + fun calcInitialState(commandData: Map, phase: Action):InternalState { val status:InternalState = getEnumFromMapOfStrings(commandData, INTERNAL_STATE, InternalState.INITIAL) if (status == InternalState.INITIAL) { onInitial(phase) return when (phase) { - Action.Delete -> InternalState.CREATING_CHILDREN - Action.Create -> if (isNeedToCreateMyself()) InternalState.CREATE_MYSELF else InternalState.CREATING_CHILDREN + Action.Delete -> when { + isDescendantHasAction(phase) -> InternalState.CREATING_CHILDREN + isNeedToDeleteMyself() -> InternalState.DELETE_MYSELF + else -> InternalState.TERMINAL + } + Action.Create -> when { + isNeedToCreateMyself() -> InternalState.CREATE_MYSELF + isNeedToResumeMySelf() -> InternalState.RESUME_MYSELF + isNeedToReplaceMySelf() -> InternalState.REPLACE_MYSELF + isDescendantHasAction(phase) -> InternalState.CREATING_CHILDREN + isDescendantHasAction(Action.Replace) -> InternalState.CREATING_CHILDREN + else -> InternalState.TERMINAL + } else -> throw IllegalStateException("state $internalState is not supported yet") } } @@ -269,7 +317,11 @@ abstract class ResourceCommand( protected open fun isNeedToCreateMyself(): Boolean = getActionType() == Action.Create - protected open fun inProgress(): Job.JobStatus { + protected open fun isNeedToResumeMySelf(): Boolean = getActionType() == Action.Resume + + protected open fun isNeedToReplaceMySelf(): Boolean = false + + protected open fun inProgress(): JobStatus { val requestId:String = msoResourceIds.requestId; return try { val jobStatus = inProgressStatusService.call(getExpiryChecker(), sharedData, requestId) @@ -277,29 +329,35 @@ abstract class ResourceCommand( } catch (e: javax.ws.rs.ProcessingException) { // Retry when we can't connect MSO during getStatus Logger.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, will retry: {}", requestId, e, e) - Job.JobStatus.IN_PROGRESS; + JobStatus.IN_PROGRESS; } catch (e: InProgressStatusService.BadResponseFromMso) { inProgressStatusService.handleFailedMsoResponse(sharedData.jobUuid, requestId, e.msoResponse) - Job.JobStatus.IN_PROGRESS + JobStatus.IN_PROGRESS } catch (e: RuntimeException) { Logger.error(EELFLoggerDelegate.errorLogger, "Cannot get orchestration status for {}, stopping: {}", requestId, e, e) - Job.JobStatus.STOPPED + JobStatus.STOPPED } } - fun createMyself(): Job.JobStatus { - val createMyselfCommand = planCreateMyselfRestCall(commandParentData, sharedData.request, sharedData.userId) - + fun createMyself(): JobStatus { + val createMyselfCommand = planCreateMyselfRestCall(commandParentData, sharedData.request, sharedData.userId, sharedData.testApi) return executeAndHandleMsoInstanceRequest(createMyselfCommand) } - fun deleteMyself(): Job.JobStatus { - val deleteMyselfCommand = planDeleteMyselfRestCall(commandParentData, sharedData.request, sharedData.userId) + protected open fun resumeMyself(): JobStatus { + throw NotImplementedError("Resume is not implemented for this command " + this.javaClass) + } + + protected open fun replaceMyself(): JobStatus { + throw NotImplementedError("Replace is not implemented for this command " + this.javaClass) + } + fun deleteMyself(): JobStatus { + val deleteMyselfCommand = planDeleteMyselfRestCall(commandParentData, sharedData.request, sharedData.userId) return executeAndHandleMsoInstanceRequest(deleteMyselfCommand) } - private fun executeAndHandleMsoInstanceRequest(restCallPlan: MsoRestCallPlan): JobStatus { + protected fun executeAndHandleMsoInstanceRequest(restCallPlan: MsoRestCallPlan): JobStatus { val msoResponse = restMso.restCall( restCallPlan.httpMethod, RequestReferencesContainer::class.java, @@ -309,9 +367,9 @@ abstract class ResourceCommand( ) val msoResult = if (isServiceCommand()) { - msoResultHandlerService.handleRootResponse(sharedData.jobUuid, msoResponse) + msoResultHandlerService.handleRootResponse(sharedData, msoResponse) } else { - msoResultHandlerService.handleResponse(msoResponse, restCallPlan.actionDescription) + msoResultHandlerService.handleResponse(sharedData, msoResponse, restCallPlan.actionDescription) } this.msoResourceIds = msoResult.msoResourceIds @@ -321,14 +379,14 @@ abstract class ResourceCommand( protected open fun getExpiryChecker(): ExpiryChecker = ExpiryChecker {false} protected open fun handleInProgressStatus(jobStatus: JobStatus): JobStatus { - return if (jobStatus == Job.JobStatus.PAUSE) Job.JobStatus.IN_PROGRESS else jobStatus + return if (jobStatus == JobStatus.PAUSE) JobStatus.IN_PROGRESS else jobStatus } protected open fun watchChildren():JobStatus { return watchChildrenJobsBL.retrieveChildrenJobsStatus(childJobs) } - private fun comulateStatusAndUpdatePropertyIfFinal(internalStateStatus: JobStatus): JobStatus { + protected fun comulateStatusAndUpdatePropertyIfFinal(internalStateStatus: JobStatus): JobStatus { val status = watchChildrenJobsBL.cumulateJobStatus(internalStateStatus, cumulativeStatus) //we want to update cumulativeStatus only for final status @@ -338,6 +396,44 @@ abstract class ResourceCommand( return status } + + protected fun buildDataForChild(request: BaseResource, actionPhase: Action): Map { + addMyselfToChildrenData(commandParentData, request) + commandParentData.setActionPhase(actionPhase) + return commandParentData.parentData + } + + protected open fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + // Nothing by default + } + + protected open fun isDescendantHasAction(phase:Action):Boolean = isDescendantHasAction(getRequest(), phase, true ) + + + @JvmOverloads + fun isDescendantHasAction(request: BaseResource, phase: Action, isFirstLevel:Boolean=true): Boolean { + if (!isFirstLevel && request.action == phase) { + return true; + } + + return request.children.map {this.isDescendantHasAction(it, phase, false)}.any {it} + } + + protected fun getActualInstanceId(request: BaseResource):String = + if (getActionType() == Action.Create) msoResourceIds.instanceId else request.instanceId + + + protected fun pushChildrenJobsToBroker(children:Collection, + dataForChild: Map, + jobType: JobType?=null): List { + var counter = 0; + return children + .map {Pair(it, counter++)} + .map { jobAdapter.createChildJob(jobType ?: it.first.jobType, it.first, sharedData, dataForChild, it.second) } + .map { jobsBrokerService.add(it) } + .map { it.toString() } + } + } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInProgressStatusCommand.java deleted file mode 100644 index 123d38bd0..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInProgressStatusCommand.java +++ /dev/null @@ -1,52 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class ResourceInProgressStatusCommand extends BaseInProgressStatusCommand { - - public ResourceInProgressStatusCommand() { - } - - ResourceInProgressStatusCommand(JobSharedData sharedData, String requestId, String instanceId) { - init(sharedData, requestId, instanceId); - } - - @Override - protected ExpiryChecker getExpiryChecker() { - return x->false; - } - - @Override - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - return new NextCommand(jobStatus, this); - } - - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInstantiationCommand.java deleted file mode 100644 index 98980a35d..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceInstantiationCommand.java +++ /dev/null @@ -1,107 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.JobCommand; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; -import org.onap.vid.mso.model.BaseResourceInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.onap.vid.services.AuditService; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Map; - - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public abstract class ResourceInstantiationCommand extends BaseInstantiationCommand implements JobCommand { - - - @Inject - protected RestMsoImplementation restMso; - - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - private AuditService auditService; - - @Override - public ResourceInstantiationCommand init(JobSharedData sharedData, Map commandData) { - super.init(sharedData, commandData); - return this; - } - - @Override - public Map getData() { - return commandParentData.getParentData(); - } - - @Override - public NextCommand call() { - if (!shouldInstantiateMyself()) { - return new NextCommand(Job.JobStatus.COMPLETED_WITH_NO_ACTION); - } - - RequestDetailsWrapper requestDetailsWrapper = generateMSORequest( - getSharedData().getRequest(), - getSharedData().getUserId() - ); - String instantiatePath = getRequestPath(); - - RestObject msoResponse = restMso.PostForObject(requestDetailsWrapper, - instantiatePath, RequestReferencesContainer.class); - - if (msoResponse.getStatusCode() >= 200 && msoResponse.getStatusCode() < 400) { - String requestId = msoResponse.get().getRequestReferences().getRequestId(); - String instanceId = msoResponse.get().getRequestReferences().getInstanceId(); - asyncInstantiationBL.auditMsoStatus(getSharedData().getRootJobId(), getJobAuditMSOStatus(), requestId, null); - return getNextCommand(requestId, instanceId); - } - else { - auditService.setFailedAuditStatusFromMso(getSharedData().getRootJobId(), null, msoResponse.getStatusCode(), msoResponse.getRaw()); - return new NextCommand(Job.JobStatus.FAILED); - } - } - protected NextCommand getNextCommand(String requestId, String instanceId){ - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new ResourceInProgressStatusCommand(getSharedData(), requestId, instanceId)); - } - - protected boolean shouldInstantiateMyself() { - return true; - } - - protected abstract String getRequestPath(); - protected abstract RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId); - protected abstract String getJobAuditMSOStatus(); -} - - diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceWithChildrenInProgressCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceWithChildrenInProgressCommand.java deleted file mode 100644 index 0a345c52c..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ResourceWithChildrenInProgressCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; - -import java.util.HashMap; -import java.util.Map; - - -public class ResourceWithChildrenInProgressCommand extends BaseInProgressStatusCommand { - - public ResourceWithChildrenInProgressCommand() { - } - - public ResourceWithChildrenInProgressCommand(JobSharedData sharedData, - String requestId, - String instanceId, - CommandParentData commandParentData) { - init(sharedData, requestId, instanceId, commandParentData); - } - - protected BaseInProgressStatusCommand init(JobSharedData sharedData, - String requestId, - String instanceId, - CommandParentData commandParentData) { - init(sharedData, requestId, instanceId); - this.commandParentData= commandParentData; - return this; - } - - - @Override - public Map getData() { - Map data = new HashMap<>(super.getData()); - data.putAll(buildDataForChild()); - return data; - } - - @Override - public BaseInProgressStatusCommand init(JobSharedData sharedData, Map commandData) { - return init( - sharedData, - (String) commandData.get("requestId"), - (String) commandData.get("instanceId"), - commandParentData.initParentData(commandData)); - } - - protected Map buildDataForChild() { - return commandParentData.getParentData(); - } - - - - @Override - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - return new NextCommand(jobStatus, this); - } - - @Override - protected ExpiryChecker getExpiryChecker() { - return x->false; - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt new file mode 100644 index 000000000..c4680b2bd --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/RootServiceCommand.kt @@ -0,0 +1,98 @@ +package org.onap.vid.job.command + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.job.impl.JobSharedData +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.onap.vid.services.AuditService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.HttpMethod +import java.util.* + +abstract class RootServiceCommand @Autowired constructor( + restMso: RestMsoImplementation, + inProgressStatusService: InProgressStatusService, + msoResultHandlerService: MsoResultHandlerService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter, + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + private val auditService: AuditService, + private val msoRequestBuilder: MsoRequestBuilder +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + lateinit var optimisticUniqueServiceInstanceName: String + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(RootServiceCommand::class.java) + } + + final override fun onInitial(phase: Action) { + if (phase== Action.Delete) { + asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, Job.JobStatus.IN_PROGRESS) + } + } + + final override fun getExternalInProgressStatus() = Job.JobStatus.IN_PROGRESS + + final override fun getData(): Map { + return super.getData() + mapOf(UNIQUE_INSTANCE_NAME to optimisticUniqueServiceInstanceName) + } + + final override fun onFinal(jobStatus: Job.JobStatus) { + asyncInstantiationBL.updateServiceInfoAndAuditStatus(sharedData.jobUuid, jobStatus) + if (jobStatus.isFailure) { + asyncInstantiationBL.handleFailedInstantiation(sharedData.jobUuid) + } + } + + final override fun init(sharedData: JobSharedData, commandData: Map): ResourceCommand { + optimisticUniqueServiceInstanceName = commandData.getOrDefault(UNIQUE_INSTANCE_NAME, "") as String + return super.init(sharedData, commandData) + } + + final override fun isServiceCommand(): Boolean = true + + final override fun getExpiryChecker(): ExpiryChecker { + return ServiceExpiryChecker() + } + + override fun resumeMyself(): Job.JobStatus { + val requestType = "createInstance" + val scope = "service" + val serviceInstanceId = getActualInstanceId(getRequest()) + try { + val requests = auditService.retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(serviceInstanceId, requestType, scope) + if (requests.isEmpty() || requests[0].requestId == null) { + LOGGER.error("Failed to retrieve requestId with type: $type, scope: $scope for service instanceId $serviceInstanceId ") + return Job.JobStatus.FAILED + } + val createMyselfCommand = planResumeMyselfRestCall(requests[0].requestId, sharedData.userId) + return executeAndHandleMsoInstanceRequest(createMyselfCommand) + } catch (exception: Exception) { + LOGGER.error("Failed to resume instanceId $serviceInstanceId ", exception) + return Job.JobStatus.FAILED + } + } + + private fun planResumeMyselfRestCall(requestId: String, userId: String): MsoRestCallPlan { + val path = asyncInstantiationBL.getResumeRequestPath(requestId) + return MsoRestCallPlan(HttpMethod.POST, path, Optional.empty(), Optional.of(userId), "resume request $requestId") + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val requestDetailsWrapper = msoRequestBuilder.generateServiceDeletionRequest( + request as ServiceInstantiation, userId + ) + val path = asyncInstantiationBL.getServiceDeletionPath(request.instanceId) + return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.empty(), + "delete instance with id ${request.instanceId}") + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInProgressStatusCommand.java deleted file mode 100644 index 6fd22132f..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInProgressStatusCommand.java +++ /dev/null @@ -1,120 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.apache.commons.collections.MapUtils; -import org.onap.vid.job.Job; -import org.onap.vid.job.Job.JobStatus; -import org.onap.vid.job.JobCommand; -import org.onap.vid.job.JobType; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.properties.Features; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class ServiceInProgressStatusCommand extends BaseInProgressStatusCommand { - - public ServiceInProgressStatusCommand() { - } - - ServiceInProgressStatusCommand(JobSharedData sharedData, MsoResourceIds msoResourceIds) { - init(sharedData, msoResourceIds.getRequestId(), msoResourceIds.getInstanceId()); - } - - @Override - protected ExpiryChecker getExpiryChecker() { - return new ServiceExpiryChecker(); - } - - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - JobCommand jobCommand = this; - Job.JobStatus nextJobStatus = jobStatus; - switch (jobStatus) { - case FAILED: - asyncInstantiationBL.handleFailedInstantiation(getSharedData().getJobUuid()); - return new NextCommand(nextJobStatus, jobCommand); - case PAUSE: - nextJobStatus = Job.JobStatus.IN_PROGRESS; - break; - case COMPLETED: - ServiceInstantiation request = (ServiceInstantiation) getSharedData().getRequest(); - if (isNeedToCreateChildJobs(request)) { - List childrenJobs = getChildJobs(request); - nextJobStatus = Job.JobStatus.IN_PROGRESS; - jobCommand = new WatchingCommand(getSharedData(), childrenJobs, true); - return new NextCommand(nextJobStatus, jobCommand); - } - break; - default: // for sonar - } - asyncInstantiationBL.updateServiceInfoAndAuditStatus(getSharedData().getJobUuid(), jobStatus); - return new NextCommand(nextJobStatus, jobCommand); - } - - private List getChildJobs(ServiceInstantiation request) { - Map dataForChild = buildDataForChild(request); - - Stream vnfJobs = request.getVnfs().values().stream().map( - vnf -> jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VnfInstantiation, JobStatus.CREATING , vnf, getSharedData(), dataForChild)).toString() - ); - - Stream networkJobs = request.getNetworks().values().stream().map( - network -> jobsBrokerService.add( - jobAdapter.createChildJob(JobType.NetworkInstantiation, JobStatus.CREATING , network, getSharedData(), dataForChild)).toString() - ); - - Stream instanceGroupJobs = request.getVnfGroups().values().stream().map( - instanceGroup -> jobsBrokerService.add( - jobAdapter.createChildJob(JobType.InstanceGroupInstantiation, JobStatus.CREATING , instanceGroup, getSharedData(), dataForChild)).toString() - ); - - return Stream.of(vnfJobs, networkJobs, instanceGroupJobs) - .reduce(Stream::concat) - .orElseGet(Stream::empty) - .collect(Collectors.toList()); - } - - public boolean isNeedToCreateChildJobs(ServiceInstantiation request) { - return featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF) && request.isALaCarte() && - ( - MapUtils.isNotEmpty(request.getVnfs()) || MapUtils.isNotEmpty(request.getNetworks()) || - (featureManager.isActive(Features.FLAG_1902_VNF_GROUPING) && MapUtils.isNotEmpty(request.getVnfGroups())) - ); - } - - protected Map buildDataForChild(ServiceInstantiation request) { - commandParentData.addInstanceId(CommandDataKey.SERVICE_INSTANCE_ID, this.instanceId); - commandParentData.addModelInfo(CommandDataKey.SERVICE_MODEL_INFO, request.getModelInfo()); - return commandParentData.getParentData(); - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInstantiationCommand.java deleted file mode 100644 index 414379b0d..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/ServiceInstantiationCommand.java +++ /dev/null @@ -1,126 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import com.google.common.collect.ImmutableMap; -import org.apache.commons.lang3.ObjectUtils; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.aai.ExceptionWithRequestInfo; -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.exceptions.MaxRetriesException; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobCommand; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.RequestReferencesContainer; -import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; - -import javax.inject.Inject; -import java.util.Map; - - -public abstract class ServiceInstantiationCommand extends BaseRootCommand implements JobCommand { - - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(ServiceInstantiationCommand.class); - - @Inject - protected AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - private RestMsoImplementation restMso; - - protected String optimisticUniqueServiceInstanceName; - - public ServiceInstantiationCommand() { - } - - @Override - public NextCommand call() { - RequestDetailsWrapper requestDetailsWrapper ; - try { - requestDetailsWrapper = generateServiceInstantiationRequest(); - } - - //Aai return bad response while checking names uniqueness - catch (ExceptionWithRequestInfo exception) { - return handleAaiNameUniquenessBadResponse(exception); - } - - //Vid reached to max retries while trying to find unique name in AAI - catch (MaxRetriesException exception) { - return handleMaxRetryInNameUniqueness(exception); - } - - String path = asyncInstantiationBL.getServiceInstantiationPath(getRequest()); - - RestObject msoResponse = restMso.PostForObject(requestDetailsWrapper, - path, RequestReferencesContainer.class); - - return handleRootResponse(msoResponse); - - } - - @Override - protected ServiceInstantiation getRequest() { - return (ServiceInstantiation) getSharedData().getRequest(); - } - - protected abstract RequestDetailsWrapper generateServiceInstantiationRequest(); - - private NextCommand handleMaxRetryInNameUniqueness(MaxRetriesException exception) { - LOGGER.error("Failed to find unused name in AAI. Set the job to FAILED ", exception); - return handleCommandFailed(); - } - - private NextCommand handleAaiNameUniquenessBadResponse(ExceptionWithRequestInfo exception) { - LOGGER.error("Failed to check name uniqueness in AAI. VID will try again later", exception); - //put the job in_progress so we will keep trying to check name uniqueness in AAI - //And then send the request to MSO - return new NextCommand(Job.JobStatus.IN_PROGRESS, this); - } - - @Override - public ServiceInstantiationCommand init(JobSharedData sharedData, Map commandData) { - - return init( - sharedData, - (String) commandData.get("optimisticUniqueServiceInstanceName") - ); - } - - protected ServiceInstantiationCommand init(JobSharedData sharedData, String optimisticUniqueServiceInstanceName) { - init(sharedData); - this.optimisticUniqueServiceInstanceName = ObjectUtils.defaultIfNull(optimisticUniqueServiceInstanceName, - (getRequest()).getInstanceName()); - return this; - } - - @Override - public Map getData() { - return ImmutableMap.of( - "optimisticUniqueServiceInstanceName", optimisticUniqueServiceInstanceName - ); - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt new file mode 100644 index 000000000..af52fa049 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleCommand.kt @@ -0,0 +1,106 @@ +package org.onap.vid.job.command + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.job.Job +import org.onap.vid.job.JobAdapter +import org.onap.vid.job.JobCommand +import org.onap.vid.job.JobsBrokerService +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.VfModule +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class VfmoduleCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(VfmoduleCommand::class.java) + } + + override fun createChildren(): Job.JobStatus { + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO) + val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID) + val vgInstaceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VG_INSTANCE_ID) + + val instantiatePath = asyncInstantiationBL.getVfmoduleInstantiationPath(serviceInstanceId, vnfInstanceId) + + val requestDetailsWrapper = msoRequestBuilder.generateVfModuleInstantiationRequest( + request as VfModule, + serviceModelInfo, serviceInstanceId, vnfModelInfo, vnfInstanceId, vgInstaceId, userId, testApi) + + val actionDescription = "create vfmodule in $vnfInstanceId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID) + + val path = asyncInstantiationBL.getVfModuleDeletePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId) + val requestDetailsWrapper = msoRequestBuilder.generateDeleteVfModuleRequest(getRequest(), userId) + return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId), + "delete vfmodule ${getRequest().instanceId} from service instance $serviceInstanceId and vnf $vnfInstanceId") + } + + override fun getRequest(): VfModule { + return sharedData.request as VfModule + } + + override fun isDescendantHasAction(phase: Action): Boolean { + return false + } + + private fun planReplaceMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO) + val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID) + val replacePath = asyncInstantiationBL.getVfModuleReplacePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId) + + val requestDetailsWrapper = msoRequestBuilder.generateVfModuleInstantiationRequest( + request as VfModule, serviceModelInfo, serviceInstanceId,vnfModelInfo, vnfInstanceId,null,userId, testApi) + + val actionDescription = "replace vfmodule ${request.instanceId}" + + return MsoRestCallPlan(HttpMethod.POST, replacePath, Optional.of(requestDetailsWrapper), Optional.of(userId), actionDescription) + } + + override fun replaceMyself(): Job.JobStatus { + try { + val replaceMyselfCommand = planReplaceMyselfRestCall(commandParentData, sharedData.request, sharedData.userId, sharedData.testApi ) + return executeAndHandleMsoInstanceRequest(replaceMyselfCommand) + } catch (exception: Exception) { + LOGGER.error("Failed to replace instanceId ${getRequest().instanceId} ", exception) + return Job.JobStatus.FAILED + } + } + + override fun isNeedToReplaceMySelf(): Boolean { + return getActionType() == Action.Replace + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleInstantiationCommand.java deleted file mode 100644 index 75bf97f8d..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VfmoduleInstantiationCommand.java +++ /dev/null @@ -1,64 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VfmoduleInstantiationCommand extends ResourceInstantiationCommand { - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getVfmoduleInstantiationPath(commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID),commandParentData.getInstanceId(CommandDataKey.VNF_INSTANCE_ID)); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateVfModuleInstantiationRequest( - (VfModule) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - commandParentData.getModelInfo(CommandDataKey.VNF_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.VNF_INSTANCE_ID), - commandParentData.getInstanceId(CommandDataKey.VG_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "VF_MODULE_REQUESTED"; - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt new file mode 100644 index 000000000..a89e196de --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfCommand.kt @@ -0,0 +1,140 @@ +package org.onap.vid.job.command + +import org.apache.commons.collections.MapUtils +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.asdc.AsdcCatalogException +import org.onap.vid.job.* +import org.onap.vid.job.impl.JobSharedData +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.BaseResource +import org.onap.vid.model.serviceInstantiation.VfModule +import org.onap.vid.model.serviceInstantiation.Vnf +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.properties.Features +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import org.togglz.core.manager.FeatureManager +import java.util.* +import java.util.stream.Collectors +import kotlin.properties.Delegates + +const val NEED_TO_CREATE_BASE_MODULE = "needToCreateBaseModule" + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class VnfCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter, + private val featureManager: FeatureManager +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + private var needToCreateBaseModule:Boolean by Delegates.notNull() + + override fun getData(): Map { + return super.getData() + mapOf(NEED_TO_CREATE_BASE_MODULE to needToCreateBaseModule) + } + + override fun init(sharedData: JobSharedData, commandData: Map): ResourceCommand { + super.init(sharedData, commandData) + needToCreateBaseModule = commandData.getOrDefault(NEED_TO_CREATE_BASE_MODULE, actionPhase != Action.Delete) as Boolean + return this + } + + + override fun createChildren(): Job.JobStatus { + val request:Vnf = getRequest() + if(isNeedToCreateChildJobs()){ + val dataForChild = buildDataForChild(request, actionPhase) + val vfModules:List = request.vfModules.values.stream().flatMap { vfKey -> vfKey.values.stream() }.collect(Collectors.toList()) + + try { + childJobs = pushChildrenJobsToBroker(vfModules.filter { filterModuleByNeedToCreateBase(it) }, dataForChild, JobType.VolumeGroupInstantiation) + } catch (e: AsdcCatalogException) { + LOGGER.error("Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message , e) + return Job.JobStatus.FAILED + } + } + + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + private fun filterModuleByNeedToCreateBase(it: VfModule):Boolean { + return needToCreateBaseModule == + commandUtils.isVfModuleBaseModule( + commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO).getModelVersionId(), + it.modelInfo.modelVersionId) + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + + val instantiatePath = asyncInstantiationBL.getVnfInstantiationPath(serviceInstanceId) + + val requestDetailsWrapper = msoRequestBuilder.generateVnfInstantiationRequest( + request as Vnf, + serviceModelInfo, serviceInstanceId, + userId, + testApi + ) + + val actionDescription = "create vnf in $serviceInstanceId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + + } + + override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + commandParentData.addModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO, request.modelInfo); + commandParentData.addInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID, getActualInstanceId(request)) + } + + override fun getRequest(): Vnf { + return sharedData.request as Vnf + } + + private fun isNeedToCreateChildJobs(): Boolean { + return featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE) && + MapUtils.isNotEmpty(getRequest().vfModules) + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val path = asyncInstantiationBL.getVnfDeletionPath(serviceInstanceId, getRequest().instanceId) + val requestDetailsWrapper = msoRequestBuilder.generateDeleteVnfRequest(getRequest(), userId) + return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId), + "delete vnf ${getRequest().instanceId} from service $serviceInstanceId") + + } + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(VnfCommand::class.java) + } + + //in Delete phase - we delete all non-base vf-modules first, before base vf-module + //in Create phase - we create base vf-module first, and then all the others + override fun watchChildren(): Job.JobStatus { + val childrenStatus:Job.JobStatus = comulateStatusAndUpdatePropertyIfFinal(watchChildrenJobsBL.retrieveChildrenJobsStatus(childJobs)) + if (!childrenStatus.isFinal || + childrenStatus.isFailure || + (actionPhase == Action.Create && !needToCreateBaseModule) || + (actionPhase == Action.Delete && needToCreateBaseModule)) { + return childrenStatus + } + + needToCreateBaseModule = !needToCreateBaseModule; + createChildren() + return Job.JobStatus.IN_PROGRESS + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInProgressStatusCommand.java deleted file mode 100644 index 832c575db..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInProgressStatusCommand.java +++ /dev/null @@ -1,107 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.apache.commons.collections.MapUtils; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobType; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.BaseResource; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.model.serviceInstantiation.Vnf; -import org.onap.vid.properties.Features; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VnfInProgressStatusCommand extends ResourceWithChildrenInProgressCommand { - private static final EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(VnfInProgressStatusCommand.class); - - public VnfInProgressStatusCommand(JobSharedData sharedData, - String requestId, - String instanceId, - CommandParentData commandParentData) { - super(sharedData, requestId, instanceId, commandParentData); - } - - public VnfInProgressStatusCommand() { - } - - @Override - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - if (jobStatus == Job.JobStatus.FAILED) { - return new NextCommand(jobStatus); - } - - Vnf request = (Vnf) getSharedData().getRequest(); - - if (isNeedToCreateChildJobs(jobStatus, request)) { - commandParentData.addInstanceId(CommandDataKey.VNF_INSTANCE_ID, instanceId); - commandParentData.addModelInfo(CommandDataKey.VNF_MODEL_INFO, request.getModelInfo()); - //create volume group of base module job - Map dataForChild = buildDataForChild(); - List vfModules = request.getVfModules().values().stream().flatMap(vfKey -> vfKey.values().stream()).collect(Collectors.toList()); - List vgBaseJobs = new ArrayList<>(); - for( VfModule vfModule : vfModules){ - try { - if(commandUtils.isVfModuleBaseModule(commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO).getModelVersionId(), vfModule.getModelInfo().getModelVersionId())) { - vgBaseJobs.add(jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VolumeGroupInstantiation, Job.JobStatus.CREATING, vfModule, getSharedData(), dataForChild)).toString()); - } - } catch (AsdcCatalogException e) { - LOG.error("Failed to retrieve service definitions from SDC, for VfModule is BaseModule. Error: "+e.getMessage() , e); - return new NextCommand(Job.JobStatus.COMPLETED_WITH_ERRORS); - } - } - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new WatchingCommandBaseModule(getSharedData(), vgBaseJobs, false, commandParentData)); - } - - //in case of JobStatus.PAUSE we leave the job itself as IN_PROGRESS, for keep tracking job progress - if (jobStatus == Job.JobStatus.PAUSE) { - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, this); - } - return new NextCommand(jobStatus, this); - } - - - protected boolean isNeedToCreateChildJobs(Job.JobStatus jobStatus, BaseResource request) { - return featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE) && - jobStatus == Job.JobStatus.COMPLETED && - MapUtils.isNotEmpty(((Vnf)request).getVfModules()); - } - - - @Override - protected ExpiryChecker getExpiryChecker() { - return x->false; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInstantiationCommand.java deleted file mode 100644 index d3bfde3b6..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VnfInstantiationCommand.java +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.Job; -import org.onap.vid.job.JobAdapter; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.serviceInstantiation.Vnf; -import org.onap.vid.mso.model.VnfInstantiationRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VnfInstantiationCommand extends ResourceInstantiationCommand { - - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getVnfInstantiationPath( commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID)); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateVnfInstantiationRequest( - (Vnf) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "VNF_REQUESTED"; - } - - @Override - protected NextCommand getNextCommand(String requestId, String instanceId) { - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, - new VnfInProgressStatusCommand(getSharedData(), requestId, instanceId, commandParentData)); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupCommand.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupCommand.kt new file mode 100644 index 000000000..4da1dad15 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupCommand.kt @@ -0,0 +1,94 @@ +package org.onap.vid.job.command + +import org.apache.commons.lang3.StringUtils.isNotEmpty +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.job.* +import org.onap.vid.model.Action +import org.onap.vid.model.serviceInstantiation.BaseResource +import org.onap.vid.model.serviceInstantiation.VfModule +import org.onap.vid.mso.RestMsoImplementation +import org.onap.vid.services.AsyncInstantiationBusinessLogic +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Component +import java.util.* + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +class VolumeGroupCommand @Autowired constructor( + private val asyncInstantiationBL: AsyncInstantiationBusinessLogic, + restMso: RestMsoImplementation, + private val msoRequestBuilder: MsoRequestBuilder, + msoResultHandlerService: MsoResultHandlerService, + inProgressStatusService:InProgressStatusService, + watchChildrenJobsBL: WatchChildrenJobsBL, + jobsBrokerService: JobsBrokerService, + jobAdapter: JobAdapter +) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService, + watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand { + + companion object { + private val LOGGER = EELFLoggerDelegate.getLogger(VolumeGroupCommand::class.java) + } + + override fun createChildren(): Job.JobStatus { + val request: VfModule = getRequest() + val dataForChild = buildDataForChild(request, actionPhase) + + childJobs = pushChildrenJobsToBroker(listOf(request), dataForChild, JobType.VfmoduleInstantiation) + + return Job.JobStatus.COMPLETED_WITH_NO_ACTION + } + + override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan { + + val serviceInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.SERVICE_INSTANCE_ID) + val serviceModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.SERVICE_MODEL_INFO) + val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID) + val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO) + + val instantiatePath = asyncInstantiationBL.getVolumeGroupInstantiationPath(serviceInstanceId,vnfInstanceId) + + val requestDetailsWrapper = msoRequestBuilder.generateVolumeGroupInstantiationRequest( + request as VfModule, + serviceModelInfo, serviceInstanceId, + vnfModelInfo,vnfInstanceId, + userId, + testApi + ) + + val actionDescription = "create volumeGroup in $vnfInstanceId" + + return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription) + } + + override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan { + TODO("not implemented") + } + + override fun isNeedToCreateMyself(): Boolean { + return super.isNeedToCreateMyself() && isNotEmpty(getRequest().volumeGroupInstanceName) + } + + override fun isNeedToDeleteMyself(): Boolean { + return false + } + + override fun getRequest(): VfModule { + return sharedData.request as VfModule + } + + override fun isDescendantHasAction(phase: Action): Boolean { + return phase == getRequest().action + } + + override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) { + commandParentData.addInstanceId(CommandParentData.CommandDataKey.VG_INSTANCE_ID, getActualInstanceId(request)); + } + + override fun replaceMyself(): Job.JobStatus { + return Job.JobStatus.COMPLETED + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInProgressStatusCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInProgressStatusCommand.java deleted file mode 100644 index 9c4d7b825..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInProgressStatusCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.Job; -import org.onap.vid.job.JobType; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VolumeGroupInProgressStatusCommand extends ResourceWithChildrenInProgressCommand { - - public VolumeGroupInProgressStatusCommand( - JobSharedData sharedData, - String requestId, - String instanceId, - CommandParentData parentData) { - super(sharedData, requestId, instanceId, parentData); - } - - public VolumeGroupInProgressStatusCommand() { - } - - @Override - protected NextCommand processJobStatus(Job.JobStatus jobStatus) { - if (jobStatus == Job.JobStatus.FAILED) { - return new NextCommand(Job.JobStatus.FAILED); - } - VfModule request = (VfModule) getSharedData().getRequest(); - - if (jobStatus == Job.JobStatus.COMPLETED) { - //vf module creation - Map dataForChild = buildDataForChild(); - List vfModuleJob = Arrays.asList(jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VfmoduleInstantiation, Job.JobStatus.CREATING , request, getSharedData(), dataForChild)).toString()); - - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new WatchingCommand(getSharedData(), vfModuleJob, false)); - } - - //in case of JobStatus.PAUSE we leave the job itself as IN_PROGRESS, for keep tracking job progress - if (jobStatus == Job.JobStatus.PAUSE) { - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, this); - } - return new NextCommand(jobStatus, this); - } - - @Override - protected Map buildDataForChild() { - commandParentData.addInstanceId(CommandDataKey.VG_INSTANCE_ID, this.instanceId); - return super.buildDataForChild(); - } - - @Override - protected ExpiryChecker getExpiryChecker() { - return x->false; - } -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInstantiationCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInstantiationCommand.java deleted file mode 100644 index eff12ec73..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/VolumeGroupInstantiationCommand.java +++ /dev/null @@ -1,103 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - - -import org.apache.commons.lang3.StringUtils; -import org.onap.vid.changeManagement.RequestDetailsWrapper; -import org.onap.vid.job.*; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.mso.model.VolumeGroupRequestDetails; -import org.onap.vid.services.AsyncInstantiationBusinessLogic; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class VolumeGroupInstantiationCommand extends ResourceInstantiationCommand { - @Inject - private AsyncInstantiationBusinessLogic asyncInstantiationBL; - - @Inject - protected JobsBrokerService jobsBrokerService; - - @Inject - protected JobAdapter jobAdapter; - - @Override - protected String getRequestPath() { - return asyncInstantiationBL.getVolumeGroupInstantiationPath(commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID),commandParentData.getInstanceId(CommandDataKey.VNF_INSTANCE_ID)); - } - - @Override - protected RequestDetailsWrapper generateMSORequest(JobAdapter.AsyncJobRequest request, String userId) { - return asyncInstantiationBL.generateVolumeGroupInstantiationRequest( - (VfModule) getSharedData().getRequest(), - commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.SERVICE_INSTANCE_ID), - commandParentData.getModelInfo(CommandDataKey.VNF_MODEL_INFO), - commandParentData.getInstanceId(CommandDataKey.VNF_INSTANCE_ID), - getSharedData().getUserId() - ); - } - - @Override - protected NextCommand getNextCommand(String requestId, String instanceId){ - return new NextCommand( - Job.JobStatus.RESOURCE_IN_PROGRESS, - new VolumeGroupInProgressStatusCommand(getSharedData(), requestId, instanceId, commandParentData) - ); - } - - @Override - protected String getJobAuditMSOStatus() { - return "VOLUME_GROUP_REQUESTED"; - } - - @Override - public NextCommand call() { - String vgName = ((VfModule)getSharedData().getRequest()).getVolumeGroupInstanceName(); - if(StringUtils.isNotEmpty(vgName)){ - return super.call();//create volume group - }else { - //go to vf module creation - VfModule request = (VfModule) getSharedData().getRequest(); - Map dataForChild = buildDataForChild(); - List vfModuleJob = Collections.singletonList(jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VfmoduleInstantiation, Job.JobStatus.CREATING, request, getSharedData(), dataForChild)).toString()); - - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new WatchingCommand(getSharedData(), vfModuleJob, false)); - } - - } - - private Map buildDataForChild() { - return commandParentData.getParentData(); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchChildrenJobsBL.kt b/vid-app-common/src/main/java/org/onap/vid/job/command/WatchChildrenJobsBL.kt index 7cebe2188..194fe4ba2 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchChildrenJobsBL.kt +++ b/vid-app-common/src/main/java/org/onap/vid/job/command/WatchChildrenJobsBL.kt @@ -7,9 +7,9 @@ * 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. @@ -21,11 +21,11 @@ package org.onap.vid.job.command import org.apache.commons.lang3.StringUtils -import org.onap.portalsdk.core.service.DataAccessService import org.onap.vid.job.Job import org.onap.vid.job.Job.JobStatus.* import org.onap.vid.job.impl.JobDaoImpl import org.onap.vid.utils.DaoUtils +import org.onap.portalsdk.core.service.DataAccessService import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service import java.util.* diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommand.java b/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommand.java deleted file mode 100644 index 758cb56d7..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import org.onap.vid.job.Job; -import org.onap.vid.job.NextCommand; -import org.onap.vid.job.impl.JobSharedData; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class WatchingCommand extends BaseWatchingCommand { - - public WatchingCommand() {} - - public WatchingCommand(JobSharedData sharedData, List childrenJobsIds, boolean isService) { - super(sharedData, childrenJobsIds, isService); - } - - protected NextCommand getNextCommand(Job.JobStatus cumulativeJobsStatus) { - if (cumulativeJobsStatus==Job.JobStatus.IN_PROGRESS) { - return (isService) ? new NextCommand(Job.JobStatus.IN_PROGRESS, this) - : new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, this); - } - if (isService) { - asyncInstantiationBL.updateServiceInfoAndAuditStatus(getSharedData().getJobUuid(), cumulativeJobsStatus); - } - return new NextCommand(cumulativeJobsStatus); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommandBaseModule.java b/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommandBaseModule.java deleted file mode 100644 index 258811a01..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/job/command/WatchingCommandBaseModule.java +++ /dev/null @@ -1,113 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * VID - * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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.vid.job.command; - -import com.google.common.collect.ImmutableMap; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.job.*; -import org.onap.vid.job.command.CommandParentData.CommandDataKey; -import org.onap.vid.job.impl.JobSharedData; -import org.onap.vid.model.serviceInstantiation.VfModule; -import org.onap.vid.model.serviceInstantiation.Vnf; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import javax.inject.Inject; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@Component -@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class WatchingCommandBaseModule extends BaseWatchingCommand { - @Inject - protected JobsBrokerService jobsBrokerService; - - @Inject - protected JobAdapter jobAdapter; - private static final EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(WatchingCommandBaseModule.class); - - public WatchingCommandBaseModule( - JobSharedData sharedData, - List childrenJobsIds, - boolean isService, - CommandParentData commandParentData) { - super(sharedData, childrenJobsIds, isService); - this.commandParentData = commandParentData; - } - - public WatchingCommandBaseModule() { - - } - - @Override - protected NextCommand getNextCommand(Job.JobStatus cumulativeJobsStatus) { - - if (cumulativeJobsStatus== Job.JobStatus.IN_PROGRESS) { - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, this); - } - - if(cumulativeJobsStatus==Job.JobStatus.FAILED || cumulativeJobsStatus==Job.JobStatus.COMPLETED_WITH_ERRORS){ - return new NextCommand(Job.JobStatus.COMPLETED_WITH_ERRORS); - } - Vnf request = (Vnf) getSharedData().getRequest(); - Map dataForChild = buildDataForChild(); - //Create non-base Volume groups job - List vfModules = request.getVfModules().values().stream().flatMap(vfKey -> vfKey.values().stream()).collect(Collectors.toList()); - List vgNonBaseJobs = new ArrayList<>(); - for( VfModule vfModule : vfModules){ - try { - if(!commandUtils.isVfModuleBaseModule(commandParentData.getModelInfo(CommandDataKey.SERVICE_MODEL_INFO).getModelVersionId(), vfModule.getModelInfo().getModelVersionId())) { - vgNonBaseJobs.add(jobsBrokerService.add( - jobAdapter.createChildJob(JobType.VolumeGroupInstantiation, Job.JobStatus.CREATING, vfModule, getSharedData(), dataForChild)).toString()); - } - } catch (AsdcCatalogException e) { - LOG.error("Failed to retrieve service definitions from SDC, for VfModule is BaseModule. Error: "+e.getMessage() , e); - return new NextCommand(Job.JobStatus.COMPLETED_WITH_ERRORS); - } - } - return new NextCommand(Job.JobStatus.RESOURCE_IN_PROGRESS, new WatchingCommand(getSharedData(), vgNonBaseJobs, false)); - } - - @Override - public WatchingCommandBaseModule init(JobSharedData sharedData, Map commandData) { - super.init(sharedData, commandData); - commandParentData.initParentData(commandData); - return this; - } - - protected Map buildDataForChild() { - return commandParentData.getParentData(); - } - - @Override - public Map getData() { - return ImmutableMap.builder() - .putAll(super.getData()) - .putAll(commandParentData.getParentData()) - .build(); - } - - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java new file mode 100644 index 000000000..ad4b8c95a --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsSchedulerInitializer.java @@ -0,0 +1,96 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.job.impl; + + +import static org.quartz.CronScheduleBuilder.dailyAtHourAndMinute; + +import com.google.common.collect.ImmutableMap; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import javax.annotation.PostConstruct; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.job.JobsBrokerService; +import org.quartz.JobBuilder; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.SchedulerException; +import org.quartz.Trigger; +import org.quartz.TriggerBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; +import org.springframework.stereotype.Component; + +@Component +public class DeleteOldJobsSchedulerInitializer { + + private JobsBrokerService jobsBrokerService; + private SchedulerFactoryBean schedulerFactoryBean; + private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DeleteOldJobsSchedulerInitializer.class); + + @Autowired + public DeleteOldJobsSchedulerInitializer( + JobsBrokerService jobsBrokerService, + SchedulerFactoryBean schedulerFactoryBean + ) { + this.jobsBrokerService = jobsBrokerService; + this.schedulerFactoryBean = schedulerFactoryBean; + } + + @PostConstruct + public void init() { + try { + JobDetail jobDetail = createJobDetail(); + Trigger deleteOldJobsTrigger = createTrigger(); + schedulerFactoryBean.getScheduler().scheduleJob(jobDetail, deleteOldJobsTrigger); + } catch (SchedulerException e) { + logger.error(EELFLoggerDelegate.errorLogger, "Failed to schedule trigger for delete old jobs: {}", e.getMessage()); + throw new GenericUncheckedException(e); + } + } + + JobDetail createJobDetail() { + int days = Integer.parseInt(SystemProperties.getProperty("vid.asyncJob.howLongToKeepOldJobsInDays")); + long secondsAgo = TimeUnit.DAYS.toSeconds(days); + return JobBuilder.newJob().ofType(DeleteOldJobsWorker.class) + .withIdentity("DeleteOldJobsWorker") + .withDescription("worker that delete old vid jobs from DB") + .setJobData(new JobDataMap(ImmutableMap.of( + "jobsBrokerService", jobsBrokerService, + "secondsAgo", secondsAgo + ))) + .build(); + } + + Trigger createTrigger() { + int minutes = new Random(System.nanoTime()).nextInt(59); + int hours = 6; + logger.info("trigger for DeleteOldJobs is {}:{} ", hours, minutes); + + return TriggerBuilder.newTrigger() + .withIdentity("DeleteOldJobsTrigger") + .withDescription("Trigger to run delete old vid jobs worker") + .withSchedule(dailyAtHourAndMinute(hours, minutes)) + .build(); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java new file mode 100644 index 000000000..d60ddab8d --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/DeleteOldJobsWorker.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * VID + * ================================================================================ + * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.vid.job.impl; + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.job.JobsBrokerService; +import org.quartz.JobExecutionContext; +import org.springframework.scheduling.quartz.QuartzJobBean; + +public class DeleteOldJobsWorker extends QuartzJobBean { + + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(DeleteOldJobsWorker.class); + + private JobsBrokerService jobsBrokerService; + private long secondsAgo; + + @Override + protected void executeInternal(JobExecutionContext context) { + LOGGER.info("delete old final jobs that has finished before {} seconds", secondsAgo); + jobsBrokerService.deleteOldFinalJobs(secondsAgo); + } + + //the following methods are used by quartz to inject members + public void setJobsBrokerService(JobsBrokerService jobsBrokerService) { + this.jobsBrokerService = jobsBrokerService; + } + + public void setSecondsAgo(long secondsAgo) { + this.secondsAgo = secondsAgo; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobAdapterImpl.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobAdapterImpl.java index 9ea1f1326..1bf0f43ee 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobAdapterImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobAdapterImpl.java @@ -7,9 +7,9 @@ * 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. @@ -25,7 +25,10 @@ import org.onap.vid.job.Job; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobType; import org.onap.vid.model.JobModel; +import org.onap.vid.properties.Features; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.togglz.core.manager.FeatureManager; import java.util.Map; import java.util.UUID; @@ -33,6 +36,14 @@ import java.util.UUID; @Component public class JobAdapterImpl implements JobAdapter { + private final FeatureManager featureManager; + + @Autowired + public JobAdapterImpl(FeatureManager featureManager) { + this.featureManager = featureManager; + } + + @Override public JobModel toModel(Job job) { JobModel jobModel = new JobModel(); @@ -43,9 +54,9 @@ public class JobAdapterImpl implements JobAdapter { } @Override - public Job createServiceInstantiationJob(JobType jobType, AsyncJobRequest request, UUID templateId, String userId, String optimisticUniqueServiceInstanceName, Integer indexInBulk){ + public Job createServiceInstantiationJob(JobType jobType, AsyncJobRequest request, UUID templateId, String userId, String testApi, String optimisticUniqueServiceInstanceName, Integer indexInBulk){ JobDaoImpl job = createJob(jobType, Job.JobStatus.PENDING , userId); - job.setSharedData(new JobSharedData(job.getUuid(), userId, request)); + job.setSharedData(new JobSharedData(job.getUuid(), userId, request, testApi)); job.setTypeAndData(jobType, ImmutableMap.of( "optimisticUniqueServiceInstanceName", optimisticUniqueServiceInstanceName )); @@ -55,10 +66,14 @@ public class JobAdapterImpl implements JobAdapter { } @Override - public Job createChildJob(JobType jobType, Job.JobStatus jobStatus, AsyncJobRequest request, JobSharedData parentSharedData, Map jobData) { + public Job createChildJob(JobType jobType, AsyncJobRequest request, JobSharedData parentSharedData, Map jobData, int indexInBulk) { + Job.JobStatus jobStatus = featureManager.isActive(Features.FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL) ? + Job.JobStatus.CREATING : Job.JobStatus.PENDING_RESOURCE; JobDaoImpl job = createJob(jobType, jobStatus , parentSharedData.getUserId()); job.setSharedData(new JobSharedData(job.getUuid(), request, parentSharedData)); job.setTypeAndData(jobType, jobData); + job.setTemplateId(parentSharedData.jobUuid); + job.setIndexInBulk(indexInBulk); return job; } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobDaoImpl.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobDaoImpl.java index 5cddd4d0f..7d78d4580 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobDaoImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobDaoImpl.java @@ -7,9 +7,9 @@ * 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. @@ -23,7 +23,6 @@ package org.onap.vid.job.impl; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.MoreObjects; import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.SelectBeforeUpdate; @@ -41,6 +40,8 @@ import java.util.Map; import java.util.Objects; import java.util.UUID; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + /* The following 2 annotations let hibernate to update only fields that actually have been changed. DynamicUpdate tell hibernate to update only dirty fields. @@ -52,7 +53,6 @@ import java.util.UUID; @Table(name = "vid_job") public class JobDaoImpl extends VidBaseEntity implements Job { - private static ObjectMapper objectMapper = new ObjectMapper(); private Job.JobStatus status; private JobType type; private JobData data = new JobData(); @@ -63,6 +63,7 @@ public class JobDaoImpl extends VidBaseEntity implements Job { private Integer age = 0; private Integer indexInBulk = 0; private Date deletedAt; + private String build; @Id @Column(name = "JOB_ID", columnDefinition = "CHAR(36)") @@ -107,7 +108,7 @@ public class JobDaoImpl extends VidBaseEntity implements Job { @Column(name = "JOB_DATA", columnDefinition = "VARCHAR(30000)") public String getDataRaw() { try { - return objectMapper.writeValueAsString(data); + return JACKSON_OBJECT_MAPPER.writeValueAsString(data); } catch (JsonProcessingException e) { throw new GenericUncheckedException(e); } @@ -115,7 +116,7 @@ public class JobDaoImpl extends VidBaseEntity implements Job { public void setDataRaw(String data) { try { - this.data = objectMapper.readValue(data, JobData.class); + this.data = JACKSON_OBJECT_MAPPER.readValue(data, JobData.class); } catch (IOException e) { throw new JobException("Error parsing job's data", uuid, e); } @@ -202,6 +203,15 @@ public class JobDaoImpl extends VidBaseEntity implements Job { this.deletedAt = deletedAt; } + @Column(name = "BUILD", columnDefinition = "VARCHAR(100)") + public String getBuild() { + return build; + } + + public void setBuild(String build) { + this.build = build; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -220,15 +230,15 @@ public class JobDaoImpl extends VidBaseEntity implements Job { return MoreObjects.toStringHelper(this) .add("status", status) .add("type", type) + .add("data", data) .add("templateId", templateId) .add("uuid", uuid) .add("takenBy", takenBy) .add("userId", userId) .add("age", age) - .add("created", created) - .add("modified", modified) + .add("indexInBulk", indexInBulk) .add("deletedAt", deletedAt) - .add("data", data) + .add("build", build) .toString(); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobData.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobData.java index c8e128e60..113fde38c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobData.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobData.java @@ -7,9 +7,9 @@ * 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. diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSchedulerInitializer.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSchedulerInitializer.java index 234c10614..b3ab75b23 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSchedulerInitializer.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSchedulerInitializer.java @@ -7,9 +7,9 @@ * 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. @@ -20,13 +20,13 @@ package org.onap.vid.job.impl; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.job.Job; import org.onap.vid.job.JobsBrokerService; import org.onap.vid.job.command.JobCommandFactory; -import org.onap.vid.properties.Features; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.SchedulerFactoryBean; @@ -34,6 +34,7 @@ import org.springframework.stereotype.Component; import org.togglz.core.manager.FeatureManager; import javax.annotation.PostConstruct; +import java.util.List; import static org.quartz.SimpleScheduleBuilder.simpleSchedule; @@ -51,24 +52,26 @@ public class JobSchedulerInitializer { JobsBrokerService jobsBrokerService, SchedulerFactoryBean schedulerFactoryBean, FeatureManager featureManager, - JobCommandFactory JobCommandFactory + JobCommandFactory jobCommandFactory ) { this.jobsBrokerService = jobsBrokerService; this.schedulerFactoryBean = schedulerFactoryBean; this.featureManager = featureManager; - this.jobCommandFactory = JobCommandFactory; + this.jobCommandFactory = jobCommandFactory; } + public static final List WORKERS_TOPICS = ImmutableList.of( + Job.JobStatus.PENDING, + Job.JobStatus.CREATING, + Job.JobStatus.IN_PROGRESS, + Job.JobStatus.RESOURCE_IN_PROGRESS, + Job.JobStatus.PENDING_RESOURCE + ); + @PostConstruct public void init() { - if (!featureManager.isActive(Features.FLAG_ASYNC_JOBS)) { - return; - } - scheduleJobWorker(Job.JobStatus.PENDING, 1); - scheduleJobWorker(Job.JobStatus.CREATING, 1); - scheduleJobWorker(Job.JobStatus.IN_PROGRESS, 1); - scheduleJobWorker(Job.JobStatus.RESOURCE_IN_PROGRESS, 1); + WORKERS_TOPICS.forEach(topic->scheduleJobWorker(topic, 1)); } private void scheduleJobWorker(Job.JobStatus topic, int intervalInSeconds) { diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSharedData.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSharedData.java index 66a04996e..f420f4f3e 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSharedData.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobSharedData.java @@ -7,9 +7,9 @@ * 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. @@ -32,6 +32,7 @@ public class JobSharedData { protected String userId; protected Class requestType; protected UUID rootJobId; + protected String testApi; @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, property="class") protected JobAdapter.AsyncJobRequest request; @@ -39,16 +40,17 @@ public class JobSharedData { public JobSharedData() { } - public JobSharedData(UUID jobUuid, String userId, JobAdapter.AsyncJobRequest request) { + public JobSharedData(UUID jobUuid, String userId, JobAdapter.AsyncJobRequest request, String testApi) { this.jobUuid = jobUuid; this.userId = userId; this.requestType = request.getClass(); this.request = request; this.rootJobId = jobUuid; + this.testApi = testApi; } public JobSharedData(UUID jobUuid, JobAdapter.AsyncJobRequest request, JobSharedData parentData) { - this(jobUuid, parentData.getUserId(), request); + this(jobUuid, parentData.getUserId(), request, parentData.getTestApi()); rootJobId = parentData.getRootJobId() != null ? parentData.getRootJobId() : parentData.getJobUuid(); } @@ -85,6 +87,14 @@ public class JobSharedData { return rootJobId; } + public String getTestApi() { + return testApi; + } + + public void setTestApi(String testApi) { + this.testApi = testApi; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java index 5b5d1e13d..0b277b4d2 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobWorker.java @@ -7,9 +7,9 @@ * 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. @@ -25,17 +25,17 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.job.*; import org.onap.vid.job.command.JobCommandFactory; -import org.onap.vid.properties.Features; import org.quartz.JobExecutionContext; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.stereotype.Component; -import org.togglz.core.manager.FeatureManager; import java.util.Optional; import java.util.UUID; import static org.onap.vid.job.Job.JobStatus.FAILED; import static org.onap.vid.job.Job.JobStatus.STOPPED; +import static org.onap.vid.job.command.ResourceCommandKt.ACTION_PHASE; +import static org.onap.vid.job.command.ResourceCommandKt.INTERNAL_STATE; @Component public class JobWorker extends QuartzJobBean { @@ -43,7 +43,6 @@ public class JobWorker extends QuartzJobBean { private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(JobWorker.class); private JobsBrokerService jobsBrokerService; - private FeatureManager featureManager; private JobCommandFactory jobCommandFactory; private Job.JobStatus topic; @@ -51,10 +50,6 @@ public class JobWorker extends QuartzJobBean { protected void executeInternal(JobExecutionContext context) { Optional job; - if (!isMsoNewApiActive()) { - return; - } - job = pullJob(); while (job.isPresent()) { @@ -85,10 +80,16 @@ public class JobWorker extends QuartzJobBean { } protected Job executeJobAndGetNext(Job job) { - LOGGER.debug(EELFLoggerDelegate.debugLogger, "going to execute job {} of {}: {}/{}", + Object internalState = job.getData().get(INTERNAL_STATE); + Object actionPhase = job.getData().get(ACTION_PHASE); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "going to execute job {} of {}: {}/{} {}/{}", StringUtils.substring(String.valueOf(job.getUuid()), 0, 8), StringUtils.substring(String.valueOf(job.getTemplateId()), 0, 8), - job.getStatus(), job.getType()); + job.getStatus(), + job.getType(), + actionPhase, + internalState + ); NextCommand nextCommand = executeCommandAndGetNext(job); @@ -128,10 +129,6 @@ public class JobWorker extends QuartzJobBean { return job; } - private boolean isMsoNewApiActive() { - return featureManager.isActive(Features.FLAG_ASYNC_INSTANTIATION); - } - private void tryMutingJobFromException(Exception e) { // If there's JobException in the stack, read job uuid from // the exception, and mute it in DB. @@ -158,10 +155,6 @@ public class JobWorker extends QuartzJobBean { this.jobsBrokerService = jobsBrokerService; } - public void setFeatureManager(FeatureManager featureManager) { - this.featureManager = featureManager; - } - public void setJobCommandFactory(JobCommandFactory jobCommandFactory) { this.jobCommandFactory = jobCommandFactory; } diff --git a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java index 59ca43743..74a729494 100644 --- a/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/job/impl/JobsBrokerServiceInDatabaseImpl.java @@ -7,9 +7,9 @@ * 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. @@ -22,6 +22,7 @@ package org.onap.vid.job.impl; import org.apache.commons.lang3.StringUtils; import org.hibernate.SessionFactory; +import org.jetbrains.annotations.NotNull; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.service.DataAccessService; import org.onap.portalsdk.core.util.SystemProperties; @@ -30,18 +31,19 @@ import org.onap.vid.exceptions.OperationNotAllowedException; import org.onap.vid.job.Job; import org.onap.vid.job.JobsBrokerService; import org.onap.vid.properties.VidProperties; +import org.onap.vid.services.VersionService; import org.onap.vid.utils.DaoUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; -import java.nio.ByteBuffer; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; -import static org.onap.vid.job.Job.JobStatus.CREATING; +import static org.onap.vid.job.Job.JobStatus.*; @Service public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { @@ -54,15 +56,20 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { private int maxOpenedInstantiationRequestsToMso; private int pollingIntervalSeconds; + private final VersionService versionService; + @Autowired - public JobsBrokerServiceInDatabaseImpl(DataAccessService dataAccessService, SessionFactory sessionFactory, + public JobsBrokerServiceInDatabaseImpl(DataAccessService dataAccessService, + SessionFactory sessionFactory, @Value("0") int maxOpenedInstantiationRequestsToMso, - @Value("10") int pollingIntervalSeconds) { + @Value("10") int pollingIntervalSeconds, + VersionService versionService) { // tha @Value will inject conservative defaults; overridden in @PostConstruct from configuration this.dataAccessService = dataAccessService; this.sessionFactory = sessionFactory; this.maxOpenedInstantiationRequestsToMso = maxOpenedInstantiationRequestsToMso; this.pollingIntervalSeconds = pollingIntervalSeconds; + this.versionService = versionService; } @PostConstruct @@ -78,6 +85,7 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { @Override public UUID add(Job job) { final JobDaoImpl jobDao = castToJobDaoImpl(job); + jobDao.setBuild(versionService.retrieveBuildNumber()); dataAccessService.saveDomainObject(jobDao, DaoUtils.getPropsMap()); return job.getUuid(); } @@ -120,7 +128,11 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { } private java.sql.Timestamp nowMinusInterval() { - return Timestamp.valueOf(LocalDateTime.now().minusSeconds(pollingIntervalSeconds)); + return nowMinusInterval(pollingIntervalSeconds); + } + + private java.sql.Timestamp nowMinusInterval(long seconds) { + return Timestamp.valueOf(LocalDateTime.now().minusSeconds(seconds)); } private String selectQueryByJobStatus(Job.JobStatus topic){ @@ -130,17 +142,23 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { "select * from VID_JOB" + " where" + // select only non-deleted in-progress jobs - " JOB_STATUS = '" + topic + "'" + - " and TAKEN_BY is null" + - " and DELETED_AT is null" + + filterByStatusNotTakenNotDeleted(topic) + // give some breath, don't select jos that were recently reached - intervalCondition + + intervalCondition + // take the oldest handled one " order by MODIFIED_DATE ASC" + // select only one result " limit 1"; } + @NotNull + private String filterByStatusNotTakenNotDeleted(Job.JobStatus topic) { + return " JOB_STATUS = '" + topic + "'" + + " and TAKEN_BY is null" + + " and DELETED_AT is null "+ + " and BUILD = '"+ versionService.retrieveBuildNumber() +"'"; + } + private String sqlQueryForTopic(Job.JobStatus topic) { switch (topic) { case IN_PROGRESS: @@ -148,44 +166,73 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { case CREATING: return selectQueryByJobStatus(topic); case PENDING: - return "" + - // select only pending jobs - "select vid_job.* from VID_JOB " + - // select users have in_progress jobs - "left join \n" + - " (select user_Id, 1 as has_any_in_progress_job from VID_JOB where JOB_STATUS = 'IN_PROGRESS' or TAKEN_BY IS NOT NULL \n" + - "group by user_id) users_have_any_in_progress_job_tbl\n" + - "on vid_job.user_id = users_have_any_in_progress_job_tbl.user_id " + - "where JOB_STATUS = 'PENDING' and TAKEN_BY is null" + - // job is not deleted - " AND DELETED_AT is null and (\n" + - // limit in-progress to some amount - "select sum(CASE WHEN JOB_STATUS='IN_PROGRESS' or (JOB_STATUS='PENDING' and TAKEN_BY IS NOT NULL) THEN 1 ELSE 0 END) as in_progress\n" + - "from VID_JOB ) <" + maxOpenedInstantiationRequestsToMso + " \n " + - // don't take jobs from templates that already in-progress/failed - "and TEMPLATE_Id not in \n" + - "(select TEMPLATE_Id from vid_job where" + - " TEMPLATE_Id IS NOT NULL and("+ - " (JOB_STATUS='FAILED' and DELETED_AT is null)" + // failed but not deleted - " or JOB_STATUS='IN_PROGRESS'" + - " or TAKEN_BY IS NOT NULL))" + " \n " + - // prefer older jobs, but the earlier in each bulk - "order by has_any_in_progress_job, CREATED_DATE, INDEX_IN_BULK " + - // select only one result - "limit 1"; + return selectQueryForPendingJob(); + case PENDING_RESOURCE: + return selectQueryForPendingResource(); default: throw new GenericUncheckedException("Unsupported topic to pull from: " + topic); } } + @NotNull + private String selectQueryForPendingJob() { + return "" + + // select only pending jobs + "select vid_job.* from VID_JOB " + + // select users have in_progress jobs + "left join \n" + + " (select user_Id, 1 as has_any_in_progress_job from VID_JOB where JOB_STATUS = 'IN_PROGRESS' or TAKEN_BY IS NOT NULL \n" + + "group by user_id) users_have_any_in_progress_job_tbl\n" + + "on vid_job.user_id = users_have_any_in_progress_job_tbl.user_id " + + "where "+filterByStatusNotTakenNotDeleted(Job.JobStatus.PENDING)+" and (\n" + + // limit in-progress to some amount + "select sum(CASE WHEN JOB_STATUS='IN_PROGRESS' or (JOB_STATUS='PENDING' and TAKEN_BY IS NOT NULL) THEN 1 ELSE 0 END) as in_progress\n" + + "from VID_JOB ) <" + maxOpenedInstantiationRequestsToMso + " \n " + + // don't take jobs from templates that already in-progress/failed + "and TEMPLATE_Id not in \n" + + "(select TEMPLATE_Id from vid_job where" + + " TEMPLATE_Id IS NOT NULL and("+ + " (JOB_STATUS='FAILED' and DELETED_AT is null)" + // failed but not deleted + " or JOB_STATUS='IN_PROGRESS'" + + " or TAKEN_BY IS NOT NULL))" + " \n " + + // prefer older jobs, but the earlier in each bulk + "order by has_any_in_progress_job, CREATED_DATE, INDEX_IN_BULK " + + // select only one result + "limit 1"; + } - private byte[] getUuidAsByteArray(UUID owner) { - ByteBuffer bb = ByteBuffer.wrap(new byte[16]); - bb.putLong(owner.getMostSignificantBits()); - bb.putLong(owner.getLeastSignificantBits()); - return bb.array(); + @NotNull + private String selectQueryForPendingResource() { + return "select * from vid_job as JOB left join \n" + + //count jobs + "(select template_id,count(*) as in_progress_count from vid_job \n" + + String.format("where (\n"+ + " (\n"+ + //with job_status IN_PROGRESS or RESOURCE_IN_PROGRESS + " (job_status in ('%s','%s') and DELETED_AT is NULL) \n",IN_PROGRESS, RESOURCE_IN_PROGRESS)+ + //or that with job_status PENDING_RESOURCE that are taken + String.format(" or (JOB_STATUS='%s' and TAKEN_BY IS NOT NULL)\n )\n", PENDING_RESOURCE) + + //with template ID and are not deleted + " and TEMPLATE_ID IS NOT NULL and DELETED_AT is NULL\n)\n" + + //join them to vid_job by template_id + "group by template_id)\n"+ + "as COUNTER on COUNTER.template_id=JOB.template_id \n" + + + "where (\n"+ + //select jobs with job_status PENDING_RESOURCE that are nit taken and not deleted + filterByStatusNotTakenNotDeleted(PENDING_RESOURCE) + "\n" + + //that have no count in the counter (no other in progress job with same templateId) + " and in_progress_count is NULL \n" + + //and that have valid templateId + " and JOB.template_id is not NULL \n"+ + ")\n" + + //INDEX_IN_BULK is for order them inside same templateId, + //template_id - for order between different templateId (just to be deterministic) + "order by INDEX_IN_BULK,JOB.template_id \n" + + "limit 1;"; } + @Override public void pushBack(Job job) { final JobDaoImpl remoteDaoJob = (JobDaoImpl) dataAccessService.getDomainObject(JobDaoImpl.class, job.getUuid(), null); @@ -253,7 +300,7 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { throw new OperationNotAllowedException("Service does not exist"); } - if (!remoteDaoJob.getStatus().equals(Job.JobStatus.PENDING) && !remoteDaoJob.getStatus().equals(Job.JobStatus.STOPPED) || !StringUtils.isEmpty(remoteDaoJob.getTakenBy()) ) { + if ((remoteDaoJob.getStatus() != Job.JobStatus.PENDING) && (remoteDaoJob.getStatus() != Job.JobStatus.STOPPED) || !StringUtils.isEmpty(remoteDaoJob.getTakenBy()) ) { logger.debug(EELFLoggerDelegate.debugLogger,"jobId {}: Service status does not allow deletion from the queue, status = {}", jobId, remoteDaoJob.getStatus() + ", takenBy " + remoteDaoJob.getTakenBy()); throw new OperationNotAllowedException("Service status does not allow deletion from the queue"); @@ -290,4 +337,17 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { return updatedEntities != 0; } + + private static String sqlListOfFinalStatus = + String.format("(%s)", + FINAL_STATUS.stream(). + map(x->String.format("'%s'",x)). + collect(Collectors.joining(",")) + ); + + @Override + public void deleteOldFinalJobs(long secondsAgo) { + String select = String.format(" MODIFIED_DATE <= '%s' and JOB_STATUS in %s", nowMinusInterval(secondsAgo), sqlListOfFinalStatus); + dataAccessService.deleteDomainObjects(JobDaoImpl.class, select, null); + } } -- cgit 1.2.3-korg