diff options
20 files changed, 205 insertions, 62 deletions
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 9861d0703..230e70fa6 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 @@ -68,6 +68,7 @@ public interface Job { CREATING(false), PENDING_RESOURCE(false), COMPLETED_AND_PAUSED(true, false), + FAILED_AND_PAUSED(true, true), ; private final Boolean finalStatus; 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 502d8344d..09357e519 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 @@ -25,9 +25,11 @@ 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.properties.Features import org.onap.vid.utils.DaoUtils import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service +import org.togglz.core.manager.FeatureManager import java.util.* import java.util.stream.Collectors import java.util.stream.Stream @@ -35,7 +37,7 @@ import java.util.stream.Stream @Service class WatchChildrenJobsBL @Autowired -constructor(private val dataAccessService: DataAccessService) { +constructor(private val dataAccessService: DataAccessService, private val featureManager: FeatureManager) { fun retrieveChildrenJobsStatus(childrenJobsIds: List<String>): Job.JobStatus { val jobs = getAllChildrenJobs(childrenJobsIds) @@ -47,14 +49,16 @@ constructor(private val dataAccessService: DataAccessService) { else -> it.status }} - return cumulateJobStatus(jobsStatuses) + return if(featureManager.isActive(Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE)) + cumulateJobStatusWithPauseOnFailure(jobsStatuses) else cumulateJobStatus(jobsStatuses) } fun cumulateJobStatus(childrenComulatedStatus: Job.JobStatus, fatherJobStatus: Job.JobStatus): Job.JobStatus { - return cumulateJobStatus(Stream.of(childrenComulatedStatus, fatherJobStatus)) + return if(featureManager.isActive(Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE)) + cumulateJobStatusWithPauseOnFailure(Stream.of(childrenComulatedStatus, fatherJobStatus)) + else cumulateJobStatus(Stream.of(childrenComulatedStatus, fatherJobStatus)) } - private fun cumulateJobStatus(jobsStatuses: Stream<Job.JobStatus>): Job.JobStatus { return jobsStatuses.reduce{ a, b -> @@ -70,7 +74,21 @@ constructor(private val dataAccessService: DataAccessService) { } } .orElse(COMPLETED_WITH_NO_ACTION) } + private fun cumulateJobStatusWithPauseOnFailure(jobsStatuses: Stream<Job.JobStatus>): Job.JobStatus { + return jobsStatuses.reduce{ a, b -> + when { + a == FAILED_AND_PAUSED || b == FAILED_AND_PAUSED-> FAILED_AND_PAUSED + a == COMPLETED && b.isFailure -> FAILED_AND_PAUSED + b == COMPLETED && a.isFailure -> FAILED_AND_PAUSED + !a.isFinal || !b.isFinal -> IN_PROGRESS + a == COMPLETED_AND_PAUSED || b == COMPLETED_AND_PAUSED -> COMPLETED_AND_PAUSED + a == COMPLETED || b == COMPLETED -> COMPLETED + a.isFailure || b.isFailure -> FAILED + else -> COMPLETED_WITH_NO_ACTION + } + } .orElse(COMPLETED_WITH_NO_ACTION) + } private fun getAllChildrenJobs(childrenJobsIds: List<String>): Map<UUID, JobDaoImpl> { val jobs:MutableList<JobDaoImpl> = dataAccessService.getList(JobDaoImpl::class.java, filterByJobIds(childrenJobsIds), null, DaoUtils.getPropsMap()) as MutableList<JobDaoImpl> return jobs.stream().collect(Collectors.toMap( { it.uuid }, { it })) 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 51803891a..7391f41a9 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 @@ -45,12 +45,14 @@ import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.exceptions.OperationNotAllowedException; import org.onap.vid.job.Job; import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.properties.Features; 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 org.togglz.core.manager.FeatureManager; @Service public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { @@ -64,19 +66,21 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { private int pollingIntervalSeconds; private final VersionService versionService; - + private final FeatureManager featureManager; @Autowired public JobsBrokerServiceInDatabaseImpl(DataAccessService dataAccessService, SessionFactory sessionFactory, @Value("0") int maxOpenedInstantiationRequestsToMso, @Value("10") int pollingIntervalSeconds, - VersionService versionService) { + VersionService versionService, + FeatureManager featureManager) { // 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; + this.featureManager = featureManager; } @PostConstruct @@ -199,7 +203,7 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { "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 + " (JOB_STATUS IN('FAILED','FAILED_AND_PAUSED') 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 @@ -232,13 +236,24 @@ public class JobsBrokerServiceInDatabaseImpl implements JobsBrokerService { " and in_progress_count is NULL \n" + //and that have valid templateId " and JOB.template_id is not NULL \n"+ - ")\n" + + + filterFailedStatusForPendingResource() + + + ")" + //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;"; } - + private String filterFailedStatusForPendingResource() { + String sql = "and JOB.template_id not in \n" + + "(select TEMPLATE_Id from vid_job where" + + " TEMPLATE_Id IS NOT NULL and (JOB_STATUS IN('FAILED','FAILED_AND_PAUSED') " + + " AND JOB_TYPE NOT IN('NetworkInstantiation','InstanceGroup','InstanceGroupMember') and DELETED_AT is null)" + // failed but not deleted + " or TAKEN_BY IS NOT NULL)"; + return featureManager.isActive(Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE) ? + sql : ""; + } @Override public void pushBack(Job job) { diff --git a/vid-app-common/src/main/java/org/onap/vid/properties/Features.java b/vid-app-common/src/main/java/org/onap/vid/properties/Features.java index f863b3025..9d3faa062 100644 --- a/vid-app-common/src/main/java/org/onap/vid/properties/Features.java +++ b/vid-app-common/src/main/java/org/onap/vid/properties/Features.java @@ -102,6 +102,7 @@ public enum Features implements Feature { FLAG_2008_CREATE_VFMODULE_INSTANTIATION_ORDER_NUMBER, FLAG_2008_PAUSE_INSTANTIATION_ON_VFMODULE_POPUP, FLAG_2008_REMOVE_PAUSE_INSTANTIATION, + FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE, ; public boolean isActive() { diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java index 91801973b..bf0344c6b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogicImpl.java @@ -436,7 +436,7 @@ public class AsyncInstantiationBusinessLogicImpl implements private boolean isRetryEnabledForStatus(JobStatus jobStatus) { return jobStatus==JobStatus.COMPLETED_AND_PAUSED || (featureManager.isActive(Features.FLAG_1902_RETRY_JOB) && - (jobStatus==JobStatus.COMPLETED_WITH_ERRORS || jobStatus==JobStatus.FAILED)); + (jobStatus==JobStatus.COMPLETED_WITH_ERRORS || jobStatus==JobStatus.FAILED || jobStatus==JobStatus.FAILED_AND_PAUSED)); } private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) { diff --git a/vid-app-common/src/main/webapp/WEB-INF/conf/dev.features.properties b/vid-app-common/src/main/webapp/WEB-INF/conf/dev.features.properties index 92be1c74b..2c73281b2 100644 --- a/vid-app-common/src/main/webapp/WEB-INF/conf/dev.features.properties +++ b/vid-app-common/src/main/webapp/WEB-INF/conf/dev.features.properties @@ -34,3 +34,4 @@ FLAG_SHOW_ORCHESTRATION_TYPE = false FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE = false FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI = false FLAG_GUILIN_CHANGEMG_SUBMIT_TO_SO = true +FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE = false
\ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java b/vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java index 468fb41c3..ecec705a1 100644 --- a/vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java +++ b/vid-app-common/src/test/java/org/onap/vid/config/JobCommandsConfigWithMockedMso.java @@ -79,7 +79,7 @@ public class JobCommandsConfigWithMockedMso { @Bean public JobsBrokerService jobsBrokerService(DataAccessService dataAccessService, SessionFactory sessionFactory, VersionService versionService) { - return new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0,versionService); + return new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0,versionService,featureManager()); } @Bean @@ -314,7 +314,7 @@ public class JobCommandsConfigWithMockedMso { @Bean public WatchChildrenJobsBL watchChildrenJobsService(DataAccessService dataAccessService) { - return new WatchChildrenJobsBL(dataAccessService); + return new WatchChildrenJobsBL(dataAccessService,featureManager()); } } diff --git a/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java index fad32bba6..a8613f7a7 100644 --- a/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/job/command/WatchChildrenJobsBLTest.java @@ -37,10 +37,12 @@ import org.mockito.MockitoAnnotations; import org.onap.portalsdk.core.service.DataAccessService; import org.onap.vid.job.Job.JobStatus; import org.onap.vid.job.impl.JobDaoImpl; +import org.onap.vid.properties.Features; import org.onap.vid.utils.DaoUtils; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.togglz.core.manager.FeatureManager; public class WatchChildrenJobsBLTest { @Mock @@ -49,6 +51,9 @@ public class WatchChildrenJobsBLTest { @InjectMocks private WatchChildrenJobsBL watchChildrenJobsBL; + @Mock + private static FeatureManager featureManager; + @BeforeClass public void initMocks() { MockitoAnnotations.initMocks(this); @@ -80,16 +85,16 @@ public class WatchChildrenJobsBLTest { {Arrays.asList(JobStatus.COMPLETED, JobStatus.COMPLETED), JobStatus.COMPLETED}, {Arrays.asList(JobStatus.COMPLETED, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.COMPLETED}, {Arrays.asList(JobStatus.FAILED, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.FAILED}, - {Arrays.asList(JobStatus.FAILED, JobStatus.COMPLETED), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(JobStatus.FAILED, JobStatus.COMPLETED), getErrorStatus()}, {Arrays.asList(JobStatus.RESOURCE_IN_PROGRESS, JobStatus.FAILED), JobStatus.IN_PROGRESS}, {Arrays.asList(JobStatus.PAUSE, JobStatus.FAILED), JobStatus.IN_PROGRESS}, {Arrays.asList(JobStatus.PENDING, JobStatus.FAILED), JobStatus.IN_PROGRESS}, {Arrays.asList(JobStatus.IN_PROGRESS, JobStatus.COMPLETED), JobStatus.IN_PROGRESS}, {Arrays.asList(JobStatus.IN_PROGRESS, JobStatus.IN_PROGRESS), JobStatus.IN_PROGRESS}, - {Arrays.asList(JobStatus.COMPLETED, JobStatus.COMPLETED_WITH_ERRORS), JobStatus.COMPLETED_WITH_ERRORS}, - {Arrays.asList(JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED), JobStatus.COMPLETED_WITH_ERRORS}, - {Arrays.asList(JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED_WITH_ERRORS), JobStatus.COMPLETED_WITH_ERRORS}, - {Arrays.asList(JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.COMPLETED_WITH_ERRORS}, + {Arrays.asList(JobStatus.COMPLETED, getErrorStatus()), getErrorStatus()}, + {Arrays.asList(getErrorStatus(), JobStatus.FAILED), getErrorStatus()}, + {Arrays.asList(getErrorStatus(), getErrorStatus()), getErrorStatus()}, + {Arrays.asList(getErrorStatus(), JobStatus.COMPLETED_WITH_NO_ACTION), getErrorStatus()}, {Arrays.asList(JobStatus.COMPLETED_WITH_NO_ACTION, JobStatus.COMPLETED_WITH_NO_ACTION), JobStatus.COMPLETED_WITH_NO_ACTION}, {Arrays.asList(JobStatus.COMPLETED_AND_PAUSED, JobStatus.RESOURCE_IN_PROGRESS), JobStatus.IN_PROGRESS}, {Arrays.asList(JobStatus.COMPLETED_AND_PAUSED, JobStatus.COMPLETED), JobStatus.COMPLETED_AND_PAUSED}, @@ -117,4 +122,8 @@ public class WatchChildrenJobsBLTest { public void whenCumulate2JobStatus_thenResultAsExpected(List<JobStatus> jobs, JobStatus expectedChildrenJobsStatus) { assertEquals(expectedChildrenJobsStatus, watchChildrenJobsBL.cumulateJobStatus(jobs.get(0), jobs.get(1))); } + private static JobStatus getErrorStatus() { + return featureManager.isActive(Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE) ? + JobStatus.FAILED_AND_PAUSED : JobStatus.COMPLETED_WITH_ERRORS; + } } diff --git a/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java b/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java index 00b2b959b..df8f5034b 100644 --- a/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/services/JobsBrokerServiceTest.java @@ -103,6 +103,7 @@ import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.togglz.core.manager.FeatureManager; @ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, JobAdapterConfig.class}) public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { @@ -124,6 +125,9 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { private static final String DELETE_SERVICE_NOT_EXIST_EXCEPTION_MESSAGE = "Service does not exist"; private JobsBrokerService broker; + @Mock + private FeatureManager featureManager; + @Inject JobAdapter jobAdapter; @Inject @@ -144,7 +148,7 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { public void initializeBroker() { MockitoAnnotations.initMocks(this); when(versionService.retrieveBuildNumber()).thenReturn("aBuildNumber"); - broker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0, versionService); + broker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, 200, 0, versionService, featureManager); ((JobsBrokerServiceInDatabaseImpl) broker).deleteAll(); } @@ -607,7 +611,7 @@ public class JobsBrokerServiceTest extends AbstractTestNGSpringContextTests { @Test(dataProvider = "jobs") public void givenSomeJobs_pullNextJob_returnNextOrNothingAsExpected(List<Jobber> jobbers, int msoLimit, int expectedIndexSelected, Job.JobStatus topic, String assertionReason) { - JobsBrokerServiceInDatabaseImpl aBroker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, msoLimit, 20, versionService); + JobsBrokerServiceInDatabaseImpl aBroker = new JobsBrokerServiceInDatabaseImpl(dataAccessService, sessionFactory, msoLimit, 20, versionService, featureManager); final List<JobDaoImpl> jobs = addJobsWithModifiedDate(jobbers, aBroker); Optional<Job> nextJob = aBroker.pull(topic, UUID.randomUUID().toString()); boolean shouldAnyBeSelected = expectedIndexSelected >= 0; diff --git a/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java b/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java index f4dd6780a..e5da62adb 100644 --- a/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java +++ b/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java @@ -135,7 +135,8 @@ public class AsyncInstantiationBase extends BaseMsoApiTest { } protected boolean getExpectedRetryEnabled(JobStatus jobStatus) { - return Features.FLAG_1902_RETRY_JOB.isActive() && (jobStatus==JobStatus.FAILED || jobStatus==JobStatus.COMPLETED_WITH_ERRORS); + return Features.FLAG_1902_RETRY_JOB.isActive() && (jobStatus==JobStatus.FAILED || jobStatus==JobStatus.COMPLETED_WITH_ERRORS + || jobStatus==JobStatus.FAILED_AND_PAUSED); } public List<BasePreset> getPresets(List<PresetMSOBaseDelete> presetOnDeleteList, List<PresetMSOBaseCreateInstancePost> presetOnCreateList, List<PresetMSOOrchestrationRequestGet> presetInProgressList) { @@ -203,7 +204,7 @@ public class AsyncInstantiationBase extends BaseMsoApiTest { return ImmutableList.of( vidAuditStatus(jobId, "PENDING", false), vidAuditStatus(jobId, "IN_PROGRESS", false), - vidAuditStatus(jobId, "COMPLETED_WITH_ERRORS", true) + vidAuditStatus(jobId, "COMPLETED_WITH_ERROR", true) ); } @@ -214,7 +215,13 @@ public class AsyncInstantiationBase extends BaseMsoApiTest { vidAuditStatus(jobId, "FAILED", true) ); } - + protected ImmutableList<JobAuditStatus> vidAuditStatusesFailedAndPaused(String jobId) { + return ImmutableList.of( + vidAuditStatus(jobId, "PENDING", false), + vidAuditStatus(jobId, "IN_PROGRESS", false), + vidAuditStatus(jobId, "FAILED_AND_PAUSED", true) + ); + } protected JobAuditStatus vidAuditStatus(String jobId, String jobStatus, boolean isFinal) { return new JobAuditStatus(UUID.fromString(jobId), jobStatus, JobAuditStatus.SourceStatus.VID, null, null, isFinal); } @@ -578,4 +585,8 @@ public class AsyncInstantiationBase extends BaseMsoApiTest { org.junit.Assert.assertEquals("MSO instanceType #" + i + " is not as expected", expectedStatus.getInstanceType(), actualStatus.getInstanceType()); }); } + protected static JobStatus getErrorStatus() { + return Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE.isActive() ? + JobStatus.FAILED_AND_PAUSED : JobStatus.COMPLETED_WITH_ERRORS; + } } diff --git a/vid-automation/src/main/java/org/onap/vid/api/CreateServiceWithFailedVnf.java b/vid-automation/src/main/java/org/onap/vid/api/CreateServiceWithFailedVnf.java index 30076a964..a8bcc9f75 100644 --- a/vid-automation/src/main/java/org/onap/vid/api/CreateServiceWithFailedVnf.java +++ b/vid-automation/src/main/java/org/onap/vid/api/CreateServiceWithFailedVnf.java @@ -13,6 +13,7 @@ import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceToscaMo import org.onap.vid.model.asyncInstantiation.ServiceInfo; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import vid.automation.test.infra.Features; import vid.automation.test.infra.ModelInfo; import vid.automation.test.model.JobStatus; import vid.automation.test.model.ServiceAction; @@ -105,9 +106,13 @@ Legit Preset || deploy 1 Service, 1 VNF which will fail public void firstTimeAssertion() { assertThat(uuids, hasSize(1)); originalJobId = uuids.get(0); + boolean isPauseOnFailureFlagOn = Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE.isActive(); - asyncInstantiationBase.assertServiceInfoSpecific1(originalJobId, JobStatus.COMPLETED_WITH_ERRORS, names.get(SERVICE_NAME), "us16807000", firstIds.serviceId, ServiceAction.INSTANTIATE); - asyncInstantiationBase.assertAuditStatuses(originalJobId, asyncInstantiationBase.vidAuditStatusesCompletedWithErrors(originalJobId),null); + asyncInstantiationBase.assertServiceInfoSpecific1(originalJobId, isPauseOnFailureFlagOn ? + JobStatus.FAILED_AND_PAUSED : JobStatus.COMPLETED_WITH_ERRORS, names.get(SERVICE_NAME), "us16807000", firstIds.serviceId, ServiceAction.INSTANTIATE); + asyncInstantiationBase.assertAuditStatuses(originalJobId, isPauseOnFailureFlagOn ? + asyncInstantiationBase.vidAuditStatusesFailedAndPaused(originalJobId) : + asyncInstantiationBase.vidAuditStatusesCompletedWithErrors(originalJobId),null); assertThat(SimulatorApi.retrieveRecordedRequestsPathCounter(), allOf( hasOrLacksOfEntry(createPresets.get(0).getReqPath(), 1L), hasOrLacksOfEntry(createPresets.get(1).getReqPath(), 1L), diff --git a/vid-automation/src/main/java/vid/automation/test/infra/Features.java b/vid-automation/src/main/java/vid/automation/test/infra/Features.java index 3e499de2f..ba7ebdf0e 100644 --- a/vid-automation/src/main/java/vid/automation/test/infra/Features.java +++ b/vid-automation/src/main/java/vid/automation/test/infra/Features.java @@ -71,6 +71,7 @@ public enum Features implements Feature { FLAG_2008_CREATE_VFMODULE_INSTANTIATION_ORDER_NUMBER, FLAG_2008_PAUSE_INSTANTIATION_ON_VFMODULE_POPUP, FLAG_2008_REMOVE_PAUSE_INSTANTIATION, + FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE, ; public boolean isActive() { return FeatureContext.getFeatureManager().isActive(this); diff --git a/vid-automation/src/main/java/vid/automation/test/model/JobStatus.java b/vid-automation/src/main/java/vid/automation/test/model/JobStatus.java index bbe1e3e86..cfe32bc9a 100644 --- a/vid-automation/src/main/java/vid/automation/test/model/JobStatus.java +++ b/vid-automation/src/main/java/vid/automation/test/model/JobStatus.java @@ -9,5 +9,6 @@ public enum JobStatus { PENDING, STOPPED, COMPLETED_AND_PAUSED, - COMPLETED_WITH_ERRORS; + COMPLETED_WITH_ERRORS, + FAILED_AND_PAUSED; } diff --git a/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest.java b/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest.java index 20fce4012..c032d5fed 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest.java +++ b/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest.java @@ -208,7 +208,7 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { assertThat(uuids, hasSize(1)); final String jobId = uuids.get(0); - assertServiceInfoSpecificDeletion(jobId, JobStatus.COMPLETED_WITH_ERRORS, "SERVICE_INSTANCE_NAME", "service-instance-type"); + assertServiceInfoSpecificDeletion(jobId, getErrorStatus(), "SERVICE_INSTANCE_NAME", "service-instance-type"); assertThat(SimulatorApi.retrieveRecordedRequestsPathCounter(), allOf( TestUtils.hasOrLacksOfEntry(deletePresets.get(0).getReqPath(), 1L), TestUtils.hasOrLacksOfEntry(deletePresets.get(1).getReqPath(), 1L), @@ -324,29 +324,42 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { String parentServiceInstanceId = "service-instance-id"; String vnfGroupToDeleteInstanceId = "VNF_GROUP1_INSTANCE_ID"; + SimulatorApi.clearExpectations(); + //failed to create vnf group, failed to remove 1 member (and then also vnf group isn't deleted) viewEditVnfGroup_registerPresets(parentServiceInstanceId, vnfGroupToDeleteInstanceId, MSO_FAILED_STATUS); final List<String> uuids = createBulkOfInstances(false, 1, ImmutableMap.of(), VIEW_EDIT_VNF_GROUPS_REQUEST); + try { + Thread.sleep(20000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + assertThat(uuids, hasSize(1)); final String jobId = uuids.get(0); - assertServiceInfoSpecificUpdate(jobId, JobStatus.COMPLETED_WITH_ERRORS, "SERVICE_INSTANCE_NAME"); - assertExpectedStatus(JobStatus.COMPLETED_WITH_ERRORS, jobId); + assertServiceInfoSpecificUpdate(jobId, getErrorStatus(), "SERVICE_INSTANCE_NAME"); + assertExpectedStatus(getErrorStatus(), jobId); Map<String, Long> recordedRequest = SimulatorApi.retrieveRecordedRequestsPathCounter(); assertThat(recordedRequest, allOf( TestUtils.hasOrLacksOfEntry("/mso/serviceInstantiation/v./instanceGroups/" + vnfGroupToDeleteInstanceId, 0L), //delete vnf group TestUtils.hasOrLacksOfEntry("/mso/serviceInstantiation/v./instanceGroups", 1L), //create vnf group TestUtils.hasOrLacksOfEntry("/mso/serviceInstantiation/v./instanceGroups/" + vnfGroupToDeleteInstanceId + "/removeMembers", 3L) //remove vnf group members )); - + SimulatorApi.clearExpectations(); //retry - vnf group create, 1 member remove, vnf group delete viewEditVnfGroup_registerPresets(parentServiceInstanceId, vnfGroupToDeleteInstanceId, MSO_COMPLETE_STATUS); final List<String> retryUuids = retryJob(jobId); assertThat(retryUuids, hasSize(1)); final String retryJobId = retryUuids.get(0); + try { + Thread.sleep(20000); + } catch (InterruptedException e) { + e.printStackTrace(); + } assertServiceInfoSpecificUpdate(retryJobId, JobStatus.COMPLETED, "SERVICE_INSTANCE_NAME"); assertExpectedStatus(JobStatus.COMPLETED, retryJobId); assertThat(SimulatorApi.retrieveRecordedRequestsPathCounter(), allOf( @@ -406,26 +419,67 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { @DataProvider Object[][] data_deploy1ServiceFromCypress__verifyStatusAndMsoCalls() { - return Features.FLAG_ASYNC_ALACARTE_VFMODULE.isActive() ? new Object[][]{ - {"none", emptyMap(), emptyMap(), true}, - {"none", emptyMap(), emptyMap(), false}, - {"instance", ImmutableMap.of("vnfs", 0L, "networks", 0L, "vfModules", 0L, "volumeGroups", 0L), - ImmutableMap.of("serviceInstances", 1L, "vnfs", 1L, "networks", 1L, "vfModules", 3L, "volumeGroups", 1L),true}, - {"network", emptyMap(), - ImmutableMap.of("networks", 1L), true}, - {"vnf0", ImmutableMap.of("vfModules", 0L, "volumeGroups", 0L), - ImmutableMap.of("vnfs", 1L, "vfModules", 3L, "volumeGroups", 1L), true}, - {"vfModule0", ImmutableMap.of("vfModules", 1L, "volumeGroups", 0L), - ImmutableMap.of("vfModules", 3L, "volumeGroups", 1L), true}, - {"volumeGroup", ImmutableMap.of("vfModules", 2L), - ImmutableMap.of("vfModules", 1L, "volumeGroups", 1L), true}, - {"vfModule1", emptyMap(), - ImmutableMap.of("vfModules", 1L, "volumeGroups", 1L), true}, - {"vfModule2", emptyMap(), - ImmutableMap.of("vfModules", 1L), true} - } : new Object[][]{ - {"none", ImmutableMap.of("vfModules", 0L, "volumeGroups", 0L), emptyMap(), true} - }; + boolean isAsyncAlacarteVfModuleWithPauseOnFailure = Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE.isActive() && + Features.FLAG_ASYNC_ALACARTE_VFMODULE.isActive() ; + + if(isAsyncAlacarteVfModuleWithPauseOnFailure) { + return new Object[][] { + {"none", ImmutableMap.of("vfModules", 3L), emptyMap() , true}, + {"none", ImmutableMap.of("vfModules", 3L), emptyMap() , false}, + {"instance", + ImmutableMap.of("vnfs", 0L, "networks", 0L, "vfModules", 0L, "volumeGroups", 0L), + ImmutableMap.of("serviceInstances", 1L, "vnfs", 1L, "networks", 1L, "vfModules", 3L, "volumeGroups", 1L), + true}, + {"network", + ImmutableMap.of("vnfs", 1L, "networks", 1L, "vfModules", 3L, "volumeGroups", 1L, "serviceInstances", 1L), + ImmutableMap.of("networks", 1L), + true}, + {"vnf0", + ImmutableMap.of("vfModules", 0L, "volumeGroups", 0L), + ImmutableMap.of("vnfs", 1L, "vfModules", 3L, "volumeGroups", 1L), + true}, + {"vfModule0", ImmutableMap.of("vfModules", 1L, "volumeGroups", 0L), + ImmutableMap.of("vfModules", 3L, "volumeGroups", 1L), + true}, +// {"volumeGroup", +// ImmutableMap.of("vnfs", 1L, "networks", 1L, "vfModules", 1L, "volumeGroups", 1L, "serviceInstances", 1L), +// ImmutableMap.of("vfModules", 1L, "volumeGroups", 1L), +// true}, + {"vfModule1", + ImmutableMap.of("vfModules", 2L, "volumeGroups", 1L) , + ImmutableMap.of("vfModules", 2L, "volumeGroups", 1L) , + true}, + {"vfModule2", + ImmutableMap.of("vfModules", 3L, "volumeGroups", 1L), + ImmutableMap.of("vfModules", 1L, "volumeGroups", 0L), + true } + }; + } else if (Features.FLAG_ASYNC_ALACARTE_VFMODULE.isActive()) { + return new Object[][]{ + {"none", emptyMap(), emptyMap(), true}, + {"none", emptyMap(), emptyMap(), false}, + {"instance", ImmutableMap.of("vnfs", 0L, "networks", 0L, "vfModules", 0L, "volumeGroups", 0L), + ImmutableMap.of("serviceInstances", 1L, "vnfs", 1L, "networks", 1L, "vfModules", 3L, "volumeGroups", + 1L), true}, + {"network", emptyMap(), + ImmutableMap.of("networks", 1L), true}, + {"vnf0", ImmutableMap.of("vfModules", 0L, "volumeGroups", 0L), + ImmutableMap.of("vnfs", 1L, "vfModules", 3L, "volumeGroups", 1L), true}, + {"vfModule0", ImmutableMap.of("vfModules", 1L, "volumeGroups", 0L), + ImmutableMap.of("vfModules", 3L, "volumeGroups", 1L), true}, + {"volumeGroup", ImmutableMap.of("vfModules", 2L), + ImmutableMap.of("vfModules", 1L, "volumeGroups", 1L), true}, + {"vfModule1", emptyMap(), + ImmutableMap.of("vfModules", 1L, "volumeGroups", 1L), true}, + {"vfModule2", emptyMap(), + ImmutableMap.of("vfModules", 1L), true} + }; + } else { + return new Object[][]{ + {"none", ImmutableMap.of("vfModules", 0L, "volumeGroups", 0L), emptyMap(), true} + }; + } + } @Test(dataProvider = "data_deploy1ServiceFromCypress__verifyStatusAndMsoCalls") @@ -443,7 +497,7 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { switch (whatToFail) { case "none": finalJobStatus = JobStatus.COMPLETED; break; case "instance": finalJobStatus = JobStatus.FAILED; break; - default: finalJobStatus = JobStatus.COMPLETED_WITH_ERRORS; break; + default: finalJobStatus = getErrorStatus(); break; } assertServiceInfoSpecific2(jobId, finalJobStatus, names.get(SERVICE_NAME)); assertRecordedRequests(pathCounterOverride, 1L, vnfRequestId); @@ -486,7 +540,8 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { final String msoURL = "/mso"; - deploy1ServiceFromCypress__verifyStatusAndMsoCalls_andRetry("none", emptyMap(), emptyMap(), true); + deploy1ServiceFromCypress__verifyStatusAndMsoCalls_andRetry("none", + Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE.isActive() ? ImmutableMap.of("vfModules", 3L):emptyMap(), emptyMap(), true); List<String> logLines = LoggerFormatTest.getLogLinesAsList(LogName.metrics2019, 200, 1, restTemplate, uri); List<RecordedRequests> underTestRequests = retrieveRecordedRequests(); @@ -603,7 +658,8 @@ public class AsyncInstantiationALaCarteApiTest extends AsyncInstantiationBase { pathCounterOverride.getOrDefault("volumeGroups", defaultValue)), TestUtils.hasOrLacksOfEntry("/mso/serviceInstantiation/v./serviceInstances/" + DEFAULT_INSTANCE_ID + "/vnfs/" + vnfRequestId + "/vfModules", - pathCounterOverride.getOrDefault("vfModules", vfModulesDefaultValue)) + pathCounterOverride.getOrDefault("vfModules", + Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE.isActive() ? defaultValue : vfModulesDefaultValue)) )); } diff --git a/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest3.java b/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest3.java index 07b81a46c..2e21653d0 100644 --- a/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest3.java +++ b/vid-automation/src/test/java/org/onap/vid/api/AsyncInstantiationALaCarteApiTest3.java @@ -135,7 +135,9 @@ public class AsyncInstantiationALaCarteApiTest3 extends AsyncInstantiationBase { } else if (expectedStatus.equals("SERVICE_FAILED")){ vidAuditStatuses = vidAuditStatusesFailed(jobId); } else { - vidAuditStatuses = vidAuditStatusesCompletedWithErrors(jobId); + vidAuditStatuses = Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE.isActive() ? + vidAuditStatusesFailedAndPaused(jobId) : + vidAuditStatusesCompletedWithErrors(jobId); } assertServiceInfoSpecific3(jobId, expectedJobStatus , names.get(SERVICE_NAME)); @@ -145,7 +147,12 @@ public class AsyncInstantiationALaCarteApiTest3 extends AsyncInstantiationBase { @DataProvider Object[][] multipleVnfDataProvider() { - return new Object[][]{{MSO_FAILED_STATUS, JobStatus.COMPLETED_WITH_ERRORS},{MSO_COMPLETE_STATUS, JobStatus.COMPLETED}, {"SERVICE_FAILED", JobStatus.FAILED}}; + return new Object[][]{ + { + MSO_FAILED_STATUS, Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE.isActive() ? JobStatus.FAILED_AND_PAUSED : + JobStatus.COMPLETED_WITH_ERRORS }, + { MSO_COMPLETE_STATUS, JobStatus.COMPLETED }, + { "SERVICE_FAILED", JobStatus.FAILED } }; } @Test @@ -197,7 +204,9 @@ public class AsyncInstantiationALaCarteApiTest3 extends AsyncInstantiationBase { return new Object[][]{ {MSO_COMPLETE_STATUS, MSO_COMPLETE_STATUS, JobStatus.COMPLETED}, {MSO_FAILED_STATUS, MSO_FAILED_STATUS, JobStatus.FAILED}, - {MSO_COMPLETE_STATUS, MSO_FAILED_STATUS, JobStatus.COMPLETED_WITH_ERRORS} + {MSO_FAILED_STATUS, MSO_COMPLETE_STATUS, + Features.FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE.isActive() ? + JobStatus.FAILED_AND_PAUSED : JobStatus.COMPLETED_WITH_ERRORS } }; } @@ -535,6 +544,8 @@ public class AsyncInstantiationALaCarteApiTest3 extends AsyncInstantiationBase { return vidAuditStatusesFailed(jobId); case IN_PROGRESS: return vidAuditStatusesInProgress(jobId); + case FAILED_AND_PAUSED: + return vidAuditStatusesFailedAndPaused(jobId); } return null; diff --git a/vid-automation/src/test/resources/features.properties b/vid-automation/src/test/resources/features.properties index a1a6cf733..35a044fdb 100644 --- a/vid-automation/src/test/resources/features.properties +++ b/vid-automation/src/test/resources/features.properties @@ -33,4 +33,4 @@ FLAG_1911_INSTANTIATION_ORDER_IN_ASYNC_ALACARTE = false FLAG_SHOW_ORCHESTRATION_TYPE = false FLAG_1911_INSTANTIATION_ORDER_BUTTON_IN_ASYNC_ALACARTE = false FLAG_A_LA_CARTE_PLATFORM_MULTI_SELECT = false - +FLAG_2008_PAUSE_VFMODULE_INSTANTIATION_FAILURE = false diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts index 5d7d89804..5652923cd 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.spec.ts @@ -1,6 +1,7 @@ import {getTestBed, TestBed} from '@angular/core/testing'; import { COMPLETED_WITH_ERRORS, + FAILED_AND_PAUSED, INPROGRESS, InstantiationStatusComponentService, PAUSE, @@ -150,6 +151,7 @@ describe('Instantiation Status Service', () => { 'COMPLETED_WITH_ERRORS': 'Completed with errors: some of the planned actions where successfully committed while other have not.\n Open the service to check it out.', 'UNEXPECTED_RANDOM_STATUS': 'Unexpected status: "UNEXPECTED_RANDOM_STATUS"', 'COMPLETED_AND_PAUSED': 'Pause upon completion. you may resume the instantiation.\n Open the service to check it out.', + 'FAILED_AND_PAUSED': 'Failed and Paused: you may re-deploy the instantiation.\n Open the service to check it out.', })) { test(`getStatusTooltip should return status popover: status=${status}`, () => { @@ -213,6 +215,9 @@ describe('Instantiation Status Service', () => { result = service.getStatus('COMPLETED_AND_PAUSED'); expect(result.iconClassName).toEqual(PAUSE_UPON_COMPLETION); + result = service.getStatus('FAILED_AND_PAUSED'); + expect(result.iconClassName).toEqual(FAILED_AND_PAUSED); + result = service.getStatus(undefined); expect(result.iconClassName).toEqual(UNKNOWN); }); diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts index cdbe890a5..709cb89ba 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.service.ts @@ -23,6 +23,7 @@ export let SUCCESS_CIRCLE : string = "success-circle-o"; export let STOPPED : string = "stop"; export let COMPLETED_WITH_ERRORS : string = "success_with_warning"; export let PAUSE_UPON_COMPLETION : string = "stopped-upon-success"; +export let FAILED_AND_PAUSED : string = "success_with_warning"; export let UNKNOWN : string = "question-mark-circle-o"; @@ -172,6 +173,8 @@ export class InstantiationStatusComponentService { return new ServiceStatus(COMPLETED_WITH_ERRORS, 'success', 'Completed with errors: some of the planned actions where successfully committed while other have not.\n Open the service to check it out.'); case 'COMPLETED_AND_PAUSED' : return new ServiceStatus(PAUSE_UPON_COMPLETION, 'default','Pause upon completion. you may resume the instantiation.\n Open the service to check it out.' ); + case 'FAILED_AND_PAUSED' : + return new ServiceStatus(FAILED_AND_PAUSED, 'success','Failed and Paused: you may re-deploy the instantiation.\n Open the service to check it out.' ); default: return new ServiceStatus(UNKNOWN, 'primary', `Unexpected status: "${status}"`); } diff --git a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts index 5e0c2a8cd..676c3a451 100644 --- a/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts +++ b/vid-webpack-master/src/app/instantiationStatus/instantiationStatus.component.ts @@ -196,17 +196,17 @@ export class InstantiationStatusComponent implements OnInit { isOpenEnabled(item: ServiceInfoModel):boolean { switch(item.action) { case ServiceAction.DELETE: - return _.includes([ JobStatus.PENDING, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED], item.jobStatus); + return _.includes([ JobStatus.PENDING, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED, JobStatus.FAILED_AND_PAUSED], item.jobStatus); case ServiceAction.UPDATE: - return _.includes([JobStatus.PENDING, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED, JobStatus.FAILED], item.jobStatus); + return _.includes([JobStatus.PENDING, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.FAILED_AND_PAUSED], item.jobStatus); default: - return _.includes([JobStatus.COMPLETED, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus); + return _.includes([JobStatus.COMPLETED, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED_AND_PAUSED], item.jobStatus); } } isAuditInfoEnabled(item: ServiceInfoModel): boolean { if(item.action === ServiceAction.DELETE || item.action=== ServiceAction.UPDATE) { - return _.includes([JobStatus.FAILED, JobStatus.IN_PROGRESS, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.PAUSE, JobStatus.COMPLETED], item.jobStatus); + return _.includes([JobStatus.FAILED, JobStatus.IN_PROGRESS, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED_AND_PAUSED, JobStatus.PAUSE, JobStatus.COMPLETED], item.jobStatus); } return true;// ServiceAction.INSTANTIATE } @@ -219,7 +219,7 @@ export class InstantiationStatusComponent implements OnInit { } isHideEnabled(item: ServiceInfoModel):boolean { - return _.includes([JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.STOPPED, JobStatus.COMPLETED_WITH_ERRORS], item.jobStatus); + return _.includes([JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.STOPPED, JobStatus.COMPLETED_WITH_ERRORS, JobStatus.FAILED_AND_PAUSED], item.jobStatus); } public onContextMenu($event: MouseEvent, item: any): void { diff --git a/vid-webpack-master/src/app/shared/models/serviceInstanceActions.ts b/vid-webpack-master/src/app/shared/models/serviceInstanceActions.ts index e7eb55d89..900b19e5f 100644 --- a/vid-webpack-master/src/app/shared/models/serviceInstanceActions.ts +++ b/vid-webpack-master/src/app/shared/models/serviceInstanceActions.ts @@ -26,7 +26,8 @@ export enum JobStatus { COMPLETED_WITH_ERRORS = 'COMPLETED_WITH_ERRORS', CREATING = 'CREATING', PAUSE_UPON_COMPLETION = 'PAUSE_UPON_COMPLETION', - COMPLETED_AND_PAUSED = 'COMPLETED_AND_PAUSED' + COMPLETED_AND_PAUSED = 'COMPLETED_AND_PAUSED', + FAILED_AND_PAUSED = 'FAILED_AND_PAUSED' } export enum PauseStatus { AFTER_COMPLETION = 'afterCompletion', |