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/aai/AaiClient.java | 44 +- .../java/org/onap/vid/aai/AaiClientInterface.java | 29 +- .../KeyValueModel.java | 42 ++ .../RelatedToProperty.java | 59 +- .../Relationship.java | 8 +- .../RelationshipData.java | 32 +- .../java/org/onap/vid/aai/model/ModelVersions.kt | 3 + .../org/onap/vid/aai/util/AAITreeConverter.java | 95 +-- .../org/onap/vid/aai/util/AAITreeNodeUtils.java | 49 ++ .../org/onap/vid/asdc/local/LocalAsdcClient.java | 19 +- .../org/onap/vid/asdc/parser/ToscaParserImpl2.java | 101 +-- .../onap/vid/asdc/parser/VidNotionsBuilder.java | 142 +++- .../vid/changeManagement/CloudConfiguration.java | 20 +- .../org/onap/vid/controller/AaiController.java | 15 +- .../AaiServiceInstanceStandardQueryController.java | 120 ++-- .../controller/AsyncInstantiationController.java | 69 +- .../java/org/onap/vid/controller/MsoConfig.java | 4 +- .../org/onap/vid/controller/MsoController.java | 35 +- .../java/org/onap/vid/controller/WebConfig.java | 20 +- .../onap/vid/dal/AsyncInstantiationRepository.kt | 147 +++++ .../src/main/java/org/onap/vid/dao/JobRequest.java | 111 ++++ .../org/onap/vid/exceptions/AbortingException.java | 28 + .../onap/vid/exceptions/AccessDeniedException.java | 29 + .../org/onap/vid/exceptions/TryAgainException.java | 28 + .../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 +++-- .../src/main/java/org/onap/vid/model/Action.java | 8 +- .../java/org/onap/vid/model/JobAuditStatus.java | 100 ++- .../main/java/org/onap/vid/model/ModelUtil.java | 7 - .../main/java/org/onap/vid/model/ResourceInfo.java | 144 +++++ .../main/java/org/onap/vid/model/ServiceInfo.java | 161 ++--- .../main/java/org/onap/vid/model/ServiceModel.java | 75 ++- .../java/org/onap/vid/model/VersionAndFeatures.kt | 12 + .../src/main/java/org/onap/vid/model/VidNotions.kt | 25 +- .../org/onap/vid/model/aaiTree/AAITreeNode.java | 50 +- .../org/onap/vid/model/aaiTree/AbstractNode.java | 8 +- .../onap/vid/model/aaiTree/CollectionResource.kt | 15 + .../org/onap/vid/model/aaiTree/InstanceGroup.kt | 23 + .../main/java/org/onap/vid/model/aaiTree/NCF.kt | 12 + .../java/org/onap/vid/model/aaiTree/Network.java | 116 +++- .../main/java/org/onap/vid/model/aaiTree/Node.java | 33 +- .../java/org/onap/vid/model/aaiTree/NodeType.java | 82 +++ .../org/onap/vid/model/aaiTree/RelatedVnf.java | 34 +- .../onap/vid/model/aaiTree/ServiceInstance.java | 35 +- .../java/org/onap/vid/model/aaiTree/VfModule.java | 9 +- .../main/java/org/onap/vid/model/aaiTree/Vnf.java | 18 +- .../java/org/onap/vid/model/aaiTree/VnfGroup.java | 72 --- .../java/org/onap/vid/model/aaiTree/VnfGroup.kt | 10 + .../java/org/onap/vid/model/aaiTree/VpnBinding.kt | 50 ++ .../main/java/org/onap/vid/model/aaiTree/Vrf.java | 65 ++ .../errorReport/ReportCreationParameters.java | 1 + .../model/serviceInstantiation/BaseResource.java | 86 ++- .../model/serviceInstantiation/InstanceGroup.java | 34 +- .../serviceInstantiation/InstanceGroupMember.java | 54 ++ .../vid/model/serviceInstantiation/Network.java | 42 +- .../serviceInstantiation/ServiceInstantiation.java | 62 +- .../vid/model/serviceInstantiation/VfModule.java | 49 +- .../onap/vid/model/serviceInstantiation/Vnf.java | 52 +- .../vid/model/serviceInstantiation/VrfEntry.kt | 6 + .../java/org/onap/vid/mso/MsoBusinessLogic.java | 11 +- .../org/onap/vid/mso/MsoBusinessLogicImpl.java | 149 ++--- .../src/main/java/org/onap/vid/mso/MsoUtil.java | 33 +- ...dOrRemoveInstanceGroupMemberRequestDetails.java | 51 ++ .../BaseResourceInstantiationRequestDetails.java | 35 +- .../org/onap/vid/mso/model/CloudConfiguration.java | 192 ------ .../org/onap/vid/mso/model/CloudConfiguration.kt | 12 + .../ServiceInstantiationPre1806RequestDetails.java | 51 ++ .../model/ServiceInstantiationRequestDetails.java | 8 +- .../model/VfModuleInstantiationRequestDetails.java | 16 +- .../org/onap/vid/mso/rest/AsyncRequestStatus.java | 5 +- .../java/org/onap/vid/mso/rest/RequestStatus.java | 8 + .../java/org/onap/vid/properties/Features.java | 23 +- .../org/onap/vid/properties/VidProperties.java | 93 +-- .../java/org/onap/vid/services/AAIServiceTree.java | 124 ++-- .../org/onap/vid/services/AAITreeNodeBuilder.java | 341 +++++----- .../java/org/onap/vid/services/AaiService.java | 2 +- .../java/org/onap/vid/services/AaiServiceImpl.java | 47 +- .../services/AsyncInstantiationBusinessLogic.java | 66 +- .../AsyncInstantiationBusinessLogicImpl.java | 711 +++++++-------------- .../java/org/onap/vid/services/AuditService.java | 24 +- .../org/onap/vid/services/AuditServiceImpl.java | 189 ++++-- .../org/onap/vid/services/CloudOwnerService.java | 4 +- .../vid/services/RoleGenaratorServiceImpl.java | 2 +- .../java/org/onap/vid/services/VersionService.kt | 66 ++ .../main/java/org/onap/vid/utils/KotlinUtils.kt | 2 +- .../src/main/java/org/onap/vid/utils/Tree.kt | 12 +- 142 files changed, 4962 insertions(+), 3702 deletions(-) create mode 100644 vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/KeyValueModel.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/aai/model/ModelVersions.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeNodeUtils.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/dao/JobRequest.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/exceptions/AbortingException.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/exceptions/AccessDeniedException.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/exceptions/TryAgainException.java 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 create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/ResourceInfo.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/VersionAndFeatures.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/CollectionResource.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/InstanceGroup.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NCF.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NodeType.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VpnBinding.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vrf.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VrfEntry.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/mso/model/AddOrRemoveInstanceGroupMemberRequestDetails.java delete mode 100644 vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.kt create mode 100644 vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationPre1806RequestDetails.java create mode 100644 vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt (limited to 'vid-app-common/src/main/java/org') diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java index 4ef6fbd24..015ede893 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClient.java @@ -21,11 +21,13 @@ package org.onap.vid.aai; import static java.util.Collections.emptyList; +import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toMap; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; import static org.apache.commons.lang3.StringUtils.isEmpty; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -37,6 +39,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.Function; +import java.util.stream.Stream; import javax.inject.Inject; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -49,6 +52,7 @@ import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.exceptions.InvalidAAIResponseException; +import org.onap.vid.aai.model.*; import org.onap.vid.aai.model.AaiGetAicZone.AicZones; import org.onap.vid.aai.model.AaiGetInstanceGroupsByCloudRegion; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.AaiGetNetworkCollectionDetails; @@ -117,6 +121,7 @@ public class AaiClient implements AaiClientInterface { private static final String GET_SERVICE_MODELS_RESPONSE_BODY = "{\"start\" : \"service-design-and-creation/models/\", \"query\" : \"query/serviceModels-byDistributionStatus?distributionStatus=DISTRIBUTION_COMPLETE_OK\"}"; + @Inject public AaiClient(AAIRestInterface restController, PortDetailsTranslator portDetailsTranslator, CacheProvider cacheProvider) { this.restController = restController; @@ -425,14 +430,49 @@ public class AaiClient implements AaiClientInterface { } @Override - public AaiResponse getSubscriberData(String subscriberId) { - String depth = "2"; + public AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances) { + String depth = omitServiceInstances ? "1" : "2"; AaiResponse subscriberDataResponse; Response resp = doAaiGet(BUSINESS_CUSTOMERS_CUSTOMER + subscriberId + "?depth=" + depth, false); subscriberDataResponse = processAaiResponse(resp, Services.class, null); return subscriberDataResponse; } + @Override + public ModelVer getLatestVersionByInvariantId(String modelInvariantId) { + if (modelInvariantId.isEmpty()) { + throw new GenericUncheckedException("no invariant-id provided to getLatestVersionByInvariantId; request is rejected"); + } + + // add the modelInvariantId to the payload + StringBuilder payload = new StringBuilder(GET_SERVICE_MODELS_RESPONSE_BODY); + payload.insert(50, modelInvariantId); + + Response response = doAaiPut("service-design-and-creation/models/model/", payload.toString(),false); + AaiResponse aaiResponse = processAaiResponse(response, ModelVersions.class, null, VidObjectMapperType.FASTERXML); + Stream modelVerStream = toModelVerStream(aaiResponse.getT()); + return maxModelVer(modelVerStream); + + } + + protected Stream toModelVerStream(ModelVersions modelVersions) { + + return Stream.of(modelVersions) + .map(ModelVersions::getResults) + .flatMap(java.util.Collection::stream) + .flatMap(map -> map.entrySet().stream()) + .filter(kv -> StringUtils.equals(kv.getKey(), "model-ver")) + .map(Map.Entry::getValue); + + } + + protected ModelVer maxModelVer(Stream modelVerStream) { + return modelVerStream + .filter(modelVer -> StringUtils.isNotEmpty(modelVer.getModelVersion())) + .max(comparing(ModelVer::getModelVersion, comparing(DefaultArtifactVersion::new))) + .orElseThrow(() -> new GenericUncheckedException("Could not find any version")); + } + @Override public AaiResponse getServices() { Response resp = doAaiGet("service-design-and-creation/services", false); diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java index 5f69b8769..1061ae5f5 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/AaiClientInterface.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,30 +21,37 @@ package org.onap.vid.aai; import com.fasterxml.jackson.databind.JsonNode; -import java.net.URI; -import java.util.List; -import java.util.Map; -import javax.ws.rs.core.Response; import org.onap.vid.aai.model.AaiGetOperationalEnvironments.OperationalEnvironmentList; import org.onap.vid.aai.model.AaiGetPnfs.Pnf; import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; +import org.onap.vid.aai.model.ModelVer; import org.onap.vid.aai.model.PortDetailsTranslator; import org.onap.vid.aai.model.Properties; import org.onap.vid.aai.model.ResourceType; -import org.onap.vid.services.ProbeInterface; import org.onap.vid.model.SubscriberList; +import org.onap.vid.model.probes.ExternalComponentStatus; +import org.onap.vid.services.ProbeInterface; +import org.springframework.http.HttpMethod; + +import javax.ws.rs.core.Response; +import java.net.URI; +import java.util.List; +import java.util.Map; + /** * Created by Oren on 7/4/17. */ -public interface AaiClientInterface extends ProbeInterface { +public interface AaiClientInterface extends ProbeInterface { boolean isNodeTypeExistsByName(String name, ResourceType type); T typedAaiGet(URI path, Class clz); + T typedAaiRest(URI path, Class clz, String payload, HttpMethod method, boolean propagateExceptions); + AaiResponse getAllSubscribers(); - AaiResponse getSubscriberData(String subscriberId); + AaiResponse getSubscriberData(String subscriberId, boolean omitServiceInstances); AaiResponse getServices(); @@ -68,10 +75,12 @@ public interface AaiClientInterface extends ProbeInterface { Response getVersionByInvariantId(List modelInvariantId); + ModelVer getLatestVersionByInvariantId(String modelInvariantId); + AaiResponse getServicesByProjectNames(List projectNames); AaiResponse getServiceModelsByDistributionStatus(); - + AaiResponse getPNFData(String globalCustomerId, String serviceType, String modelVersionId, String modelInvariantId, String cloudRegion, String equipVendor, String equipModel); AaiResponse getSpecificPnf(String pnfId); diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/KeyValueModel.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/KeyValueModel.java new file mode 100644 index 000000000..6e0e1c06a --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/KeyValueModel.java @@ -0,0 +1,42 @@ +/*- + * ============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.aai.model.AaiGetNetworkCollectionDetails; + +public abstract class KeyValueModel { + private String key; + private String value; + + public String getKey() { + return key; + } + public String getValue() { + return value; + } + + public void setKey(String key) { + this.key = key; + } + public void setValue(String value) { + this.value = value; + } + + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelatedToProperty.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelatedToProperty.java index d53d90fd4..7c5287770 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelatedToProperty.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelatedToProperty.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,33 +25,30 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties(ignoreUnknown = true) -public class RelatedToProperty { - - public String getPropertyKey() { - return propertyKey; - } - - - public void setPropertyKey(String propertyKey) { - this.propertyKey = propertyKey; - } - - - public String getPropertyValue() { - return propertyValue; - } - - - public void setPropertyValue(String propertyValue) { - this.propertyValue = propertyValue; - } - - - @JsonProperty("property-key") - public String propertyKey; - - - @JsonProperty("property-value") - public String propertyValue; - +public class RelatedToProperty extends KeyValueModel { + + @Override + @JsonProperty("property-key") + public String getKey() { + return super.getKey(); + } + + @Override + @JsonProperty("property-key") + public void setKey(String propertyKey) { + super.setKey(propertyKey); + } + + @Override + @JsonProperty("property-value") + public String getValue() { + return super.getValue(); + } + + @Override + @JsonProperty("property-value") + public void setValue(String propertyValue) { + super.setValue(propertyValue); + } } + diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/Relationship.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/Relationship.java index 4de11500e..110e922c1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/Relationship.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/Relationship.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. @@ -31,13 +31,13 @@ public class Relationship { @JsonProperty("related-to") public String relatedTo; - + @JsonProperty("related-link") public String relatedLink; @JsonProperty("relationship-label") public String relationshipLabel; - + @JsonProperty("relationship-data") public List relationshipData; diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelationshipData.java b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelationshipData.java index cba7f43cb..f480ef8d0 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelationshipData.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/AaiGetNetworkCollectionDetails/RelationshipData.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. @@ -24,26 +24,26 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @JsonIgnoreProperties(ignoreUnknown = true) -public class RelationshipData { +public class RelationshipData extends KeyValueModel { + + @Override @JsonProperty("relationship-key") - public String getRelationshipKey() { - return relationshipKey; + public String getKey() { + return super.getKey(); } + @Override @JsonProperty("relationship-key") - public void setRelationshipKey(String relationshipKey) { - this.relationshipKey = relationshipKey; + public void setKey(String relationshipKey) { + super.setKey(relationshipKey); } + @Override @JsonProperty("relationship-value") - public String getRelationshipValue() { - return relationshipValue; + public String getValue() { + return super.getValue(); } + @Override @JsonProperty("relationship-value") - public void setRelationshipValue(String relationshipValue) { - this.relationshipValue = relationshipValue; + public void setValue(String relationshipValue) { + super.setValue(relationshipValue); } - - public String relationshipKey; - - public String relationshipValue; - } diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/model/ModelVersions.kt b/vid-app-common/src/main/java/org/onap/vid/aai/model/ModelVersions.kt new file mode 100644 index 000000000..c4aa45d55 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/model/ModelVersions.kt @@ -0,0 +1,3 @@ +package org.onap.vid.aai.model + +data class ModelVersions(val results: List>) diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java index 5be26a0ec..48736bc01 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeConverter.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,36 +20,43 @@ package org.onap.vid.aai.util; -import org.apache.commons.lang3.StringUtils; -import org.onap.vid.model.aaiTree.*; -import org.onap.vid.mso.model.ModelInfo; -import org.onap.vid.services.AAITreeNodeBuilder; -import org.springframework.stereotype.Component; - -import java.util.Objects; - import static java.util.function.Function.identity; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; import static org.onap.vid.asdc.parser.ToscaParserImpl2.Constants.A_LA_CARTE; +import java.util.Map; +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; +import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.CollectionResource; +import org.onap.vid.model.aaiTree.Network; +import org.onap.vid.model.aaiTree.Node; +import org.onap.vid.model.aaiTree.NodeType; +import org.onap.vid.model.aaiTree.ServiceInstance; +import org.onap.vid.model.aaiTree.Vnf; +import org.onap.vid.model.aaiTree.VnfGroup; +import org.onap.vid.model.aaiTree.Vrf; +import org.onap.vid.mso.model.ModelInfo; +import org.springframework.stereotype.Component; + @Component public class AAITreeConverter { public static final String VNF_TYPE = "vnf-type"; public static final String NETWORK_TYPE = "network-type"; + public static final String NETWORK_ROLE = "network-role"; + public static final String PHYSICAL_NETWORK_NAME = "physical-network-name"; + public static final String SERVICE_INSTANCE = "service-instance"; + public static final String TENANT = "tenant"; + public static final String VPN_BINDING = "vpn-binding"; public static final String IS_BASE_VF_MODULE = "is-base-vf-module"; + public static final String SERVICE_INSTANCE_SERVICE_INSTANCE_NAME = "service-instance.service-instance-name"; + public static final String SERVICE_INSTANCE_SERVICE_INSTANCE_ID = "service-instance.service-instance-id"; + public static final String TENANT_TENANT_NAME = "tenant.tenant-name"; - public enum ModelType { - service, - vnf, - network, - instanceGroup, - vfModule - } - - public ServiceInstance convertTreeToUIModel(AAITreeNode rootNode, String globalCustomerId, String serviceType, String instantiationType) { + public ServiceInstance convertTreeToUIModel(AAITreeNode rootNode, String globalCustomerId, String serviceType, String instantiationType, String instanceRole, String instanceType) { ServiceInstance serviceInstance = new ServiceInstance(); serviceInstance.setInstanceId(rootNode.getId()); serviceInstance.setInstanceName(rootNode.getName()); @@ -58,46 +65,60 @@ public class AAITreeConverter { serviceInstance.setSubscriptionServiceType(serviceType); serviceInstance.setIsALaCarte(StringUtils.equals(instantiationType, A_LA_CARTE)); - serviceInstance.setModelInfo(createModelInfo(rootNode, ModelType.service)); + serviceInstance.setModelInfo(createModelInfo(rootNode)); //set children: vnf, network,group rootNode.getChildren().forEach(child -> { - if (child.getType().equals(AAITreeNodeBuilder.GENERIC_VNF)) { + if (child.getType() == NodeType.GENERIC_VNF) { serviceInstance.getVnfs().put(child.getUniqueNodeKey(), Vnf.from(child)); - } else if (child.getType().equals(AAITreeNodeBuilder.NETWORK)) { + } else if (child.getType() == NodeType.NETWORK) { serviceInstance.getNetworks().put(child.getUniqueNodeKey(), Network.from(child)); - } else if (child.getType().equals(AAITreeNodeBuilder.INSTANCE_GROUP)) { - serviceInstance.getVnfGroups().put(child.getUniqueNodeKey(), VnfGroup.from(child)); + } else if (child.getType() == NodeType.INSTANCE_GROUP) { + serviceInstance.getVnfGroups().put(child.getUniqueNodeKey(), new VnfGroup(child)); + } else if (child.getType() == NodeType.COLLECTION_RESOURCE) { + serviceInstance.getCollectionResources().put(child.getUniqueNodeKey(), new CollectionResource(child)); + } else if (isChildVrf(instanceType, instanceRole, child)){ + serviceInstance.getVrfs().put(child.getUniqueNodeKey(), Vrf.from(child)); } }); serviceInstance.setExistingVNFCounterMap( - serviceInstance.getVnfs().entrySet().stream() - .map(k -> k.getValue().getModelInfo().getModelVersionId()) - .collect(groupingBy(identity(), counting())) + getExistingCounterMap(serviceInstance.getVnfs()) ); serviceInstance.setExistingNetworksCounterMap( - serviceInstance.getNetworks().entrySet().stream() - .map(k -> k.getValue().getModelInfo().getModelVersionId()) - .filter(Objects::nonNull) - .collect(groupingBy(identity(), counting())) + getExistingCounterMap(serviceInstance.getNetworks()) ); serviceInstance.setExistingVnfGroupCounterMap( - serviceInstance.getVnfGroups().entrySet().stream() - .map(k -> k.getValue().getModelInfo().getModelVersionId()) - .filter(Objects::nonNull) - .collect(groupingBy(identity(), counting())) + getExistingCounterMap(serviceInstance.getVnfGroups()) + ); + + serviceInstance.setExistingVRFCounterMap( + getExistingCounterMap(serviceInstance.getVrfs()) ); return serviceInstance; } - private static ModelInfo createModelInfo(AAITreeNode aaiNode, ModelType modelType) { + protected boolean isChildVrf(String instanceType, String serviceRole, AAITreeNode child) { + return child.getType() == NodeType.CONFIGURATION && StringUtils.equalsIgnoreCase(instanceType, "BONDING") && StringUtils.equalsIgnoreCase(serviceRole, "INFRASTRUCTURE-VPN"); + } + + private Map getExistingCounterMap(Map nodeList) { + return nodeList.entrySet().stream() + .map(k -> { + ModelInfo modelInfo = k.getValue().getModelInfo(); + return StringUtils.defaultIfEmpty(modelInfo.getModelCustomizationId(), modelInfo.getModelVersionId()); + }) + .filter(Objects::nonNull) + .collect(groupingBy(identity(), counting())); + } + + private static ModelInfo createModelInfo(AAITreeNode aaiNode) { ModelInfo modelInfo = new ModelInfo(); - modelInfo.setModelType(modelType.name()); + modelInfo.setModelType(aaiNode.getType().getModelType()); modelInfo.setModelName(aaiNode.getModelName()); modelInfo.setModelVersion(aaiNode.getModelVersion()); modelInfo.setModelVersionId(aaiNode.getModelVersionId()); diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeNodeUtils.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeNodeUtils.java new file mode 100644 index 000000000..7ff6f280f --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAITreeNodeUtils.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.aai.util; + +import java.util.List; +import java.util.Optional; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.KeyValueModel; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; + +public class AAITreeNodeUtils { + + private AAITreeNodeUtils() { + } + + public static Optional findFirstRelationshipByRelatedTo(RelationshipList relationshipList, String relatedTo) { + if (relationshipList==null || relationshipList.getRelationship()==null) { + return Optional.empty(); + } + return relationshipList.getRelationship().stream().filter(x->relatedTo.equals(x.getRelatedTo())).findFirst(); + } + + public static Optional findFirstValue(List data, String key) { + if (data==null || data.isEmpty()) { + return Optional.empty(); + } + Optional optValue = data.stream().filter(x->key.equals(x.getKey())).findFirst(); + return optValue.map(KeyValueModel::getValue); + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java b/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java index 7cfd094df..ce1bbe930 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/local/LocalAsdcClient.java @@ -25,13 +25,6 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.joshworks.restclient.http.HttpResponse; -import org.json.JSONArray; -import org.json.JSONObject; -import org.onap.vid.asdc.AsdcCatalogException; -import org.onap.vid.asdc.AsdcClient; -import org.onap.vid.asdc.beans.Service; -import org.onap.vid.exceptions.GenericUncheckedException; - import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -39,6 +32,12 @@ import java.net.URLDecoder; import java.nio.file.Path; import java.nio.file.Paths; import java.util.UUID; +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.vid.asdc.AsdcCatalogException; +import org.onap.vid.asdc.AsdcClient; +import org.onap.vid.asdc.beans.Service; +import org.onap.vid.exceptions.GenericUncheckedException; /** * The Class LocalAsdcClient. @@ -147,14 +146,14 @@ public class LocalAsdcClient implements AsdcClient { return null; } ClassLoader classLoader = getClass().getClassLoader(); - File file = new File(classLoader.getResource(toscaModelURL).getFile()); try { + File file = new File(classLoader.getResource(toscaModelURL).getFile()); //using URLDecoder.decode to convert special characters from %XX to real character //see https://stackoverflow.com/questions/32251251/java-classloader-getresource-with-special-characters-in-path return Paths.get(URLDecoder.decode(file.getPath(), "UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new GenericUncheckedException(e); + } catch (RuntimeException | UnsupportedEncodingException e) { + throw new GenericUncheckedException("Can't find " + toscaModelURL, e); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/ToscaParserImpl2.java b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/ToscaParserImpl2.java index c702cf40a..735ba437c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/ToscaParserImpl2.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/ToscaParserImpl2.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,8 @@ package org.onap.vid.asdc.parser; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; import org.onap.sdc.tosca.parser.enums.FilterType; import org.onap.sdc.tosca.parser.enums.SdcTypes; @@ -29,7 +31,6 @@ import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException; import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory; import org.onap.sdc.toscaparser.api.Group; import org.onap.sdc.toscaparser.api.*; -import org.onap.sdc.toscaparser.api.elements.Metadata; import org.onap.sdc.toscaparser.api.parameters.Input; import org.onap.vid.asdc.beans.Service; import org.onap.vid.model.*; @@ -66,6 +67,7 @@ public class ToscaParserImpl2 { public static final String VF_MODULE_MODEL_NAME = "vfModuleModelName"; public static final String GET_INPUT = "get_input"; public static final String TYPE = "type"; + public static final String QUANTITY = "quantity"; public static final String INSTANTIATION_TYPE = "instantiationType"; //instantiation type @@ -106,8 +108,16 @@ public class ToscaParserImpl2 { public static final String VNF_GROUP = "VnfGroup"; + public static final String VRF_NODE_TYPE = "org.openecomp.nodes.VRFEntry"; + + public static final String PORT_MIRRORING_CONFIGURATION_NODE_TYPE = "org.openecomp.nodes.PortMirroringConfiguration"; + + public static final String PORT_MIRRORING_CONFIGURATION_BY_POLICY_NODE_TYPE = "org.openecomp.nodes.PortMirroringConfigurationByPolicy"; + public static final String NAMING_POLICY_TYPE = "org.openecomp.policies.External"; + public static final String SCALING_POLICY_TYPE = "org.openecomp.policies.scaling.Fixed"; + public static final String ECOMP_GENERATED_NAMING_PROPERTY = "ecomp_generated_naming"; } @@ -119,6 +129,7 @@ public class ToscaParserImpl2 { ServiceModel serviceModel = new ServiceModel(); ISdcCsarHelper sdcCsarHelper = getSdcCsarHelper(path); List policiesTargets = extractNamingPoliciesTargets(sdcCsarHelper); + Map scalingPolicies = extractScalingPolicyOfGroup(sdcCsarHelper); serviceModel.setService(extractServiceFromCsar(asdcServiceMetadata, sdcCsarHelper)); serviceModel.setVolumeGroups(extractVolumeGroups(sdcCsarHelper)); @@ -128,9 +139,10 @@ public class ToscaParserImpl2 { serviceModel.setServiceProxies(extractServiceProxyFromCsar(sdcCsarHelper, policiesTargets)); serviceModel.setNetworks(extractNetworksFromCsar(sdcCsarHelper, policiesTargets)); serviceModel.setPnfs(extractPnfsFromCsar(sdcCsarHelper, policiesTargets)); - serviceModel.setCollectionResource(extractCRFromCsar(sdcCsarHelper, policiesTargets)); + serviceModel.setCollectionResources(extractCRFromCsar(sdcCsarHelper, policiesTargets)); serviceModel.setFabricConfigurations(extractFabricConfigFromCsar(sdcCsarHelper, policiesTargets)); - serviceModel.setVnfGroups(extractVnfGroupsFromCsar(sdcCsarHelper, policiesTargets)); + serviceModel.setVnfGroups(extractVnfGroupsFromCsar(sdcCsarHelper, policiesTargets, scalingPolicies)); + serviceModel.setVrfs(extractVrfsFromCsar(sdcCsarHelper, policiesTargets)); serviceModel.getService().setVidNotions(vidNotionsBuilder.buildVidNotions(sdcCsarHelper, serviceModel)); return serviceModel; } @@ -248,7 +260,7 @@ public class ToscaParserImpl2 { vnf.setVfModules(getVfModulesFromVF(csarHelper, vnf.getCustomizationUuid())); vnf.setVolumeGroups(getVolumeGroupsFromVF(csarHelper, vnf.getCustomizationUuid())); vnf.setVfcInstanceGroups(getVfcInstanceGroup(csarHelper, nodeTemplate)); - if (ToscaNamingPolicy.getEcompNamingValueForNode(nodeTemplate, "nf_naming").equals("true")) { + if ("true".equals(ToscaNamingPolicy.getEcompNamingValueForNode(nodeTemplate, "nf_naming"))) { setEcompNamingProperty(vnf.getProperties(), "true"); } vnfsMaps.put(nodeTemplate.getName(), vnf); @@ -291,7 +303,8 @@ public class ToscaParserImpl2 { } private Map extractPortMirroringConfigFromCsar(ISdcCsarHelper csarHelper, List policiesTargets) { - List nodeTemplates = csarHelper.getServiceNodeTemplateBySdcType(SdcTypes.CONFIGURATION);//TODO change to + List nodeTemplates = csarHelper.getServiceNodeTemplatesByType(Constants.PORT_MIRRORING_CONFIGURATION_NODE_TYPE); + nodeTemplates.addAll(csarHelper.getServiceNodeTemplatesByType(Constants.PORT_MIRRORING_CONFIGURATION_BY_POLICY_NODE_TYPE)); Map configMaps = new HashMap<>(); for (NodeTemplate nodeTemplate : nodeTemplates) { @@ -379,7 +392,7 @@ public class ToscaParserImpl2 { Network newNetwork = new Network(); populateNodeFromNodeTemplate(nodeTemplate, csarHelper, newNetwork, policiesTargets); newNetwork.setModelCustomizationName(nodeTemplate.getName()); - if (ToscaNamingPolicy.getEcompNamingValueForNode(nodeTemplate, "exVL_naming").equals("true")) { + if ("true".equals(ToscaNamingPolicy.getEcompNamingValueForNode(nodeTemplate, "exVL_naming"))) { setEcompNamingProperty(newNetwork.getProperties(), "true"); } networksMap.put(nodeTemplate.getName(), newNetwork); @@ -389,14 +402,7 @@ public class ToscaParserImpl2 { private Map extractPnfsFromCsar(ISdcCsarHelper csarHelper, List policiesTargets) { List nodeTemplates = csarHelper.getServiceNodeTemplateBySdcType(SdcTypes.PNF); - HashMap pnfHashMap = new HashMap<>(); - - for (NodeTemplate nodeTemplate : nodeTemplates) { - Node pnf = new Node(); - populateNodeFromNodeTemplate(nodeTemplate, csarHelper, pnf, policiesTargets); - pnfHashMap.put(nodeTemplate.getName(), pnf); - } - return pnfHashMap; + return this.extractNodesFromCsar(csarHelper,policiesTargets,nodeTemplates); } private Map extractVfModuleFromCsar(ISdcCsarHelper csarHelper) { @@ -426,7 +432,7 @@ public class ToscaParserImpl2 { for (org.onap.sdc.toscaparser.api.parameters.Input input : inputList) { //Set only inputs without annotation to the service level if ( input.getAnnotations() == null ) - inputs.put(input.getName(), convertInput(input, new org.onap.vid.asdc.beans.tosca.Input(), null)); + inputs.put(input.getName(), convertInput(input, new org.onap.vid.asdc.beans.tosca.Input())); } return inputs; } @@ -546,7 +552,7 @@ public class ToscaParserImpl2 { } - public static boolean isModuleTypeIsBaseObjectSafe(Object vfModuleTypeValue) { + public static boolean isModuleTypeIsBaseObjectSafe(@Nullable Object vfModuleTypeValue) { return (vfModuleTypeValue instanceof String) && (isModuleTypeIsBase((String) vfModuleTypeValue)); } @@ -567,7 +573,7 @@ public class ToscaParserImpl2 { for (Input input : inputs) { if ( input.getName().equals(key) ) { org.onap.vid.asdc.beans.tosca.Input localInput = new org.onap.vid.asdc.beans.tosca.Input(); - localInput = convertInput(input, localInput, nodeTemplate); + localInput = convertInput(input, localInput); String name = property.getKey(); commandPropertyMap.put(name, extractCommands(name, key)); inputMap.put(name, localInput); @@ -582,23 +588,13 @@ public class ToscaParserImpl2 { return inputKey.substring(inputKey.indexOf(':') + 1); } - private org.onap.vid.asdc.beans.tosca.Input convertInput(Input parserInput, org.onap.vid.asdc.beans.tosca.Input localInput, NodeTemplate nodeTemplate){ + private org.onap.vid.asdc.beans.tosca.Input convertInput(Input parserInput, org.onap.vid.asdc.beans.tosca.Input localInput) { localInput.setDefault(parserInput.getDefault()); localInput.setDescription(parserInput.getDescription()); localInput.setRequired(parserInput.isRequired()); localInput.setType(parserInput.getType()); localInput.setConstraints(parserInput.getConstraints()); // localInput.setentry_schema() - - //if inputs of inner nodeTemplate - tell its details - if(nodeTemplate != null) { - Metadata metadata = nodeTemplate.getMetaData(); - localInput.setTemplateName(metadata.getValue("name")); - localInput.setTemplateUUID(metadata.getValue("UUID")); - localInput.setTemplateInvariantUUID(metadata.getValue("invariantUUID")); - localInput.setTemplateCustomizationUUID(metadata.getValue("customizationUUID")); - } - return localInput; } @@ -626,15 +622,30 @@ public class ToscaParserImpl2 { return validatedInstantiationType; } - private Map extractVnfGroupsFromCsar(ISdcCsarHelper csarHelper, List policiesTargets) { + private Map extractVrfsFromCsar(ISdcCsarHelper csarHelper, List policiesTargets) { + List nodeTemplates = csarHelper.getServiceNodeTemplatesByType(Constants.VRF_NODE_TYPE); + return this.extractNodesFromCsar(csarHelper,policiesTargets,nodeTemplates); + } + + private Map extractNodesFromCsar(ISdcCsarHelper csarHelper, List policiesTargets, List nodeTemplates){ + HashMap nodeHashMap = new HashMap<>(); + for (NodeTemplate nodeTemplate : nodeTemplates) { + Node node = new Node(); + populateNodeFromNodeTemplate(nodeTemplate, csarHelper, node, policiesTargets); + nodeHashMap.put(nodeTemplate.getName(), node); + } + return nodeHashMap; + } + + private Map extractVnfGroupsFromCsar(ISdcCsarHelper csarHelper, List policiesTargets, Map scalingPolicies) { List resourceGroups = csarHelper.getGroupsOfTopologyTemplateByToscaGroupType(Constants.RESOURCE_GROUP_TYPE); return resourceGroups.stream() .filter(group -> group.getProperties().get(Constants.RESOURCE_GROUP_CONTAINED_TYPE).getValue().equals("VF")) - .collect(toMap(Group::getName, group -> parseResourceGroup(group, csarHelper, policiesTargets))); + .collect(toMap(Group::getName, group -> parseResourceGroup(group, csarHelper, policiesTargets, scalingPolicies))); } - private ResourceGroup parseResourceGroup(Group group, ISdcCsarHelper csarHelper, List policiesTargets) { + private ResourceGroup parseResourceGroup(Group group, ISdcCsarHelper csarHelper, List policiesTargets, Map scalingPolicies) { return new ResourceGroup( Constants.VNF_GROUP, group.getMetadata().getValue(Constants.INVARIANT_UUID), @@ -642,16 +653,19 @@ public class ToscaParserImpl2 { group.getMetadata().getValue(Constants.VERSION), group.getMetadata().getValue(Constants.NAME), group.getMetadata().getValue(Constants.NAME), - getPropertiesOfResourceGroup(group.getProperties(), policiesTargets.contains(group.getName())), + getPropertiesOfResourceGroup(group.getProperties(), policiesTargets.contains(group.getName()), scalingPolicies.get(group.getName())), csarHelper.getGroupMembersFromTopologyTemplate(group.getName()).stream() .collect(toMap(NodeTemplate::getName, node -> getServiceProxyFromNodeTemplate(node, csarHelper, policiesTargets))) ); } - private Map getPropertiesOfResourceGroup(Map properties, boolean hasPolicyTarget) { + private Map getPropertiesOfResourceGroup(Map properties, boolean hasPolicyTarget, Integer qty) { Map propertiesMap = properties.entrySet().stream() .collect(toMap(Map.Entry::getKey, e -> e.getValue().getValue())); propertiesMap.put(Constants.ECOMP_GENERATED_NAMING_PROPERTY, String.valueOf(hasPolicyTarget)); + if (qty != null) { + propertiesMap.put(Constants.QUANTITY, qty); + } return propertiesMap; } @@ -660,9 +674,22 @@ public class ToscaParserImpl2 { List policies = csarHelper.getPoliciesOfTopologyTemplateByToscaPolicyType(Constants.NAMING_POLICY_TYPE); return policies.stream() .filter(policy -> policy.getProperties().get(Constants.TYPE) != null && - policy.getProperties().get(Constants.TYPE).getValue() != null && + policy.getProperties().get(Constants.TYPE).getValue() != null && StringUtils.equalsIgnoreCase(policy.getProperties().get(Constants.TYPE).getValue().toString(), "naming")) .flatMap(policy -> policy.getTargets().stream()) .collect(toList()); } -} + + public Map extractScalingPolicyOfGroup(ISdcCsarHelper csarHelper) { + return csarHelper.getPoliciesOfTopologyTemplateByToscaPolicyType(Constants.SCALING_POLICY_TYPE) + .stream() + .filter(policy -> policy.getProperties().containsKey(Constants.QUANTITY)) + .flatMap(policy -> { + Integer qty = Integer.parseInt(policy.getProperties().get(Constants.QUANTITY).getValue().toString()); + return policy + .getTargets().stream() + .map(target -> Pair.of(target, qty)); + }) + .collect(toMap(Pair::getKey, Pair::getValue)); + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java index a28695211..c9c2649ae 100644 --- a/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.java +++ b/vid-app-common/src/main/java/org/onap/vid/asdc/parser/VidNotionsBuilder.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,36 +20,75 @@ package org.onap.vid.asdc.parser; +import static org.apache.commons.lang3.StringUtils.equalsAnyIgnoreCase; +import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; +import static org.apache.commons.lang3.StringUtils.isEmpty; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; import org.onap.sdc.tosca.parser.api.ISdcCsarHelper; import org.onap.sdc.toscaparser.api.NodeTemplate; +import org.onap.sdc.toscaparser.api.elements.Metadata; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.VidNotions; import org.onap.vid.properties.Features; import org.togglz.core.manager.FeatureManager; -import static org.apache.commons.lang3.StringUtils.equalsAnyIgnoreCase; -import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase; - public class VidNotionsBuilder { private final FeatureManager featureManager; + //map of service type that are always macro services, and their relevant featureFlag + private static final Map macroServicesByModelCategory = ImmutableMap.of( + VidNotions.ModelCategory.INFRASTRUCTURE_VPN, Features.FLAG_1908_INFRASTRUCTURE_VPN, + VidNotions.ModelCategory.Transport, Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI, + VidNotions.ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE, Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI + ); + public VidNotionsBuilder(FeatureManager featureManager) { this.featureManager = featureManager; } - public VidNotions buildVidNotions(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { - final VidNotions.InstantiationUI instantiationUI = suggestInstantiationUI(csarHelper); + VidNotions buildVidNotions(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { + VidNotions.ModelCategory modelCategory = suggestModelCategory(csarHelper, serviceModel); + return new VidNotions( + suggestInstantiationUI(csarHelper, serviceModel), + modelCategory, + suggestViewEditUI(csarHelper, serviceModel), + suggestInstantiationType(serviceModel, modelCategory)); + } - return new VidNotions(instantiationUI, suggestModelCategory(csarHelper), suggestViewEditUI(csarHelper, serviceModel)); + private boolean isMacroTypeByModelCategory(VidNotions.ModelCategory modelCategory) { + Features featureOfMacroType = macroServicesByModelCategory.get(modelCategory); + //if featureOfMacroType is null this service is not a macro by its type + return (featureOfMacroType!=null && featureManager.isActive(featureOfMacroType)); + } + + VidNotions.InstantiationType suggestInstantiationType(ServiceModel serviceModel, VidNotions.ModelCategory modelCategory) { + if (isMacroTypeByModelCategory(modelCategory)) { + return VidNotions.InstantiationType.Macro; + } + if (serviceModel==null || serviceModel.getService()==null || isEmpty(serviceModel.getService().getInstantiationType())) { + return VidNotions.InstantiationType.ClientConfig; + } + String instantiationType = serviceModel.getService().getInstantiationType(); + if (instantiationType.equals(ToscaParserImpl2.Constants.MACRO)) { + return VidNotions.InstantiationType.Macro; + } + if (instantiationType.equals(ToscaParserImpl2.Constants.A_LA_CARTE)) { + return VidNotions.InstantiationType.ALaCarte; + } + + return VidNotions.InstantiationType.ClientConfig; } //UI route a-la-carte services to old UI only if InstantiationUI is LEGACY //So any other value for InstantiationUI other than LEGACY make UI to route //a-la-carte services to new UI - VidNotions.InstantiationUI suggestInstantiationUI(ISdcCsarHelper csarHelper) { + VidNotions.InstantiationUI suggestInstantiationUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { if(featureManager.isActive(Features.FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI) && isALaCarte(csarHelper)) { return VidNotions.InstantiationUI.ANY_ALACARTE_NEW_UI; } @@ -57,42 +96,91 @@ public class VidNotionsBuilder { return VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING; } if (featureManager.isActive(Features.FLAG_5G_IN_NEW_INSTANTIATION_UI)) { - if (isUuidExactlyHardCoded1ffce89fef3f(csarHelper)) { - return VidNotions.InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de; - } else if (isALaCarte(csarHelper) && hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(csarHelper)) { - return VidNotions.InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS; - } else if (isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { - return VidNotions.InstantiationUI.SERVICE_WITH_FABRIC_CONFIGURATION; - } + VidNotions.InstantiationUI instantiationUI = determine5GInstantiationUI(csarHelper); + if ( instantiationUI != null ) return instantiationUI; + } + if (featureManager.isActive(Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI) && isTransportService(csarHelper)){ + return VidNotions.InstantiationUI.TRANSPORT_SERVICE; + } + if (featureManager.isActive(Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI) && isServiceWithCollectionResource(serviceModel)){ + return VidNotions.InstantiationUI.SERVICE_WITH_COLLECTION_RESOURCE; + } + if (featureManager.isActive(Features.FLAG_1908_INFRASTRUCTURE_VPN) && isInfraStructureVpn(csarHelper)){ + return VidNotions.InstantiationUI.INFRASTRUCTURE_VPN; + } + if (featureManager.isActive(Features.FLAG_1908_A_LA_CARTE_VNF_NEW_INSTANTIATION_UI) && isVnfServiceRole(csarHelper)){ + return VidNotions.InstantiationUI.A_LA_CARTE_VNF_SERVICE_ROLE; } - return VidNotions.InstantiationUI.LEGACY; } - VidNotions.ModelCategory suggestModelCategory(ISdcCsarHelper csarHelper) { + private boolean isVnfServiceRole(ISdcCsarHelper csarHelper) { + final String serviceRole = csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_ROLE ); + return StringUtils.equalsIgnoreCase("VNF" , serviceRole); + } + + @Nullable + private VidNotions.InstantiationUI determine5GInstantiationUI(ISdcCsarHelper csarHelper) { + if (isUuidExactlyHardCoded1ffce89fef3f(csarHelper)) { + return VidNotions.InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de; + } else if (isALaCarte(csarHelper) && hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(csarHelper)) { + return VidNotions.InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS; + } else if (isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { + return VidNotions.InstantiationUI.SERVICE_WITH_FABRIC_CONFIGURATION; + } + return null; + } + + private boolean isTransportService(ISdcCsarHelper csarHelper) { + return ("TRANSPORT".equalsIgnoreCase(csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_TYPE))); + } + + private boolean isServiceWithCollectionResource(ServiceModel serviceModel){ + return MapUtils.isNotEmpty(serviceModel.getCollectionResources()); + } + + private boolean isInfraStructureVpn(ISdcCsarHelper csarHelper) { + Metadata serviceMetadata = csarHelper.getServiceMetadata(); + return ("BONDING".equalsIgnoreCase(serviceMetadata.getValue(ToscaParserImpl2.Constants.SERVICE_TYPE)) && + "INFRASTRUCTURE-VPN".equalsIgnoreCase(serviceMetadata.getValue(ToscaParserImpl2.Constants.SERVICE_ROLE))); + } + + VidNotions.ModelCategory suggestModelCategory(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { if (isALaCarte(csarHelper) && hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(csarHelper)){ return VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL; - } else if(isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { + } + if(isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) { return VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL; - } else { - return VidNotions.ModelCategory.OTHER; } + if (isInfraStructureVpn(csarHelper)) { + return VidNotions.ModelCategory.INFRASTRUCTURE_VPN; + } + if (isTransportService(csarHelper)) { + return VidNotions.ModelCategory.Transport; + } + if (isServiceWithCollectionResource(serviceModel)) { + return VidNotions.ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE; + } + return VidNotions.ModelCategory.OTHER; } VidNotions.InstantiationUI suggestViewEditUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel) { - if (!featureManager.isActive(Features.FLAG_ASYNC_INSTANTIATION)){ - return VidNotions.InstantiationUI.LEGACY; - } if (featureManager.isActive(Features.FLAG_1902_VNF_GROUPING) && isGrouping(csarHelper)) { return VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING; } + if (featureManager.isActive(Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI) && + featureManager.isActive(Features.FLAG_1908_RESUME_MACRO_SERVICE) && + isServiceWithCollectionResource(serviceModel)) { + return VidNotions.InstantiationUI.SERVICE_WITH_COLLECTION_RESOURCE; + } + if (featureManager.isActive(Features.FLAG_1902_NEW_VIEW_EDIT)) { if (isMacro(serviceModel) && !isMacroExcludedFromAsyncFlow(serviceModel)) { return VidNotions.InstantiationUI.MACRO_SERVICE; } - VidNotions.InstantiationUI instantiationUISuggestion = suggestInstantiationUI(csarHelper); + VidNotions.InstantiationUI instantiationUISuggestion = suggestInstantiationUI(csarHelper, serviceModel); if (instantiationUISuggestion!=VidNotions.InstantiationUI.LEGACY) { return instantiationUISuggestion; } @@ -137,10 +225,8 @@ public class VidNotionsBuilder { boolean isMacroExcludedFromAsyncFlow(ServiceModel serviceModel) { return (MapUtils.isNotEmpty(serviceModel.getPnfs()) || - MapUtils.isNotEmpty(serviceModel.getCollectionResource()) || + MapUtils.isNotEmpty(serviceModel.getCollectionResources()) || (MapUtils.isNotEmpty(serviceModel.getNetworks()) && !featureManager.isActive(Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION))); - - } private boolean isGrouping(ISdcCsarHelper csarHelper) { diff --git a/vid-app-common/src/main/java/org/onap/vid/changeManagement/CloudConfiguration.java b/vid-app-common/src/main/java/org/onap/vid/changeManagement/CloudConfiguration.java index da4fd0aa5..f24e2615f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/changeManagement/CloudConfiguration.java +++ b/vid-app-common/src/main/java/org/onap/vid/changeManagement/CloudConfiguration.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. @@ -27,8 +27,8 @@ import java.util.Map; @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ -"lcpCloudRegionId", -"tenantId" + "lcpCloudRegionId", + "tenantId" }) public class CloudConfiguration { @JsonProperty("lcpCloudRegionId") @@ -40,32 +40,32 @@ public class CloudConfiguration { @JsonProperty("lcpCloudRegionId") public String getLcpCloudRegionId() { - return lcpCloudRegionId; + return lcpCloudRegionId; } @JsonProperty("lcpCloudRegionId") public void setLcpCloudRegionId(String lcpCloudRegionId) { - this.lcpCloudRegionId = lcpCloudRegionId; + this.lcpCloudRegionId = lcpCloudRegionId; } @JsonProperty("tenantId") public String getTenantId() { - return tenantId; + return tenantId; } @JsonProperty("tenantId") public void setTenantId(String tenantId) { - this.tenantId = tenantId; + this.tenantId = tenantId; } @JsonAnyGetter public Map getAdditionalProperties() { - return this.additionalProperties; + return this.additionalProperties; } @JsonAnySetter public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); + this.additionalProperties.put(name, value); } } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java index 4a4f3d300..eee2acc51 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AaiController.java @@ -50,6 +50,7 @@ import org.onap.vid.aai.model.AaiGetPnfs.Pnf; import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse; import org.onap.vid.aai.util.AAIRestInterface; import org.onap.vid.model.VersionByInvariantIdsRequest; +import org.onap.vid.properties.Features; import org.onap.vid.roles.Role; import org.onap.vid.roles.RoleProvider; import org.onap.vid.roles.RoleValidator; @@ -68,6 +69,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.ModelAndView; +import org.togglz.core.manager.FeatureManager; @RestController @@ -80,17 +82,22 @@ public class AaiController extends RestrictedBaseController { private AAIRestInterface aaiRestInterface; private RoleProvider roleProvider; private SystemPropertiesWrapper systemPropertiesWrapper; + private FeatureManager featureManager; + @Autowired public AaiController(AaiService aaiService, AAIRestInterface aaiRestInterface, RoleProvider roleProvider, - SystemPropertiesWrapper systemPropertiesWrapper) { + SystemPropertiesWrapper systemPropertiesWrapper, + FeatureManager featureManager + ) { this.aaiService = aaiService; this.aaiRestInterface = aaiRestInterface; this.roleProvider = roleProvider; this.systemPropertiesWrapper = systemPropertiesWrapper; + this.featureManager = featureManager; } @RequestMapping(value = {"/subscriberSearch"}, method = RequestMethod.GET) @@ -261,13 +268,13 @@ public class AaiController extends RestrictedBaseController { } @RequestMapping(value = "/aai_sub_details/{subscriberId}", method = RequestMethod.GET) - public ResponseEntity GetSubscriberDetails(HttpServletRequest request, - @PathVariable("subscriberId") String subscriberId) throws IOException { + public ResponseEntity getSubscriberDetails(HttpServletRequest request, @PathVariable("subscriberId") String subscriberId, + @RequestParam(value="omitServiceInstances", required = false, defaultValue = "false") boolean omitServiceInstances) throws IOException { ObjectMapper objectMapper = new ObjectMapper(); ResponseEntity responseEntity; List roles = roleProvider.getUserRoles(request); RoleValidator roleValidator = RoleValidator.by(roles); - AaiResponse subscriberData = aaiService.getSubscriberData(subscriberId, roleValidator); + AaiResponse subscriberData = aaiService.getSubscriberData(subscriberId, roleValidator, featureManager.isActive(Features.FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH) && omitServiceInstances); String httpMessage = subscriberData.getT() != null ? objectMapper.writeValueAsString(subscriberData.getT()) : subscriberData.getErrorMessage(); diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java index 8f56f7795..015f8dc96 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AaiServiceInstanceStandardQueryController.java @@ -21,48 +21,54 @@ package org.onap.vid.controller; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Network; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.ServiceInstance; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Vlan; -import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Vnf; -import org.onap.vid.aai.util.ServiceInstanceStandardQuery; +import static java.util.stream.Collectors.toList; + +import com.google.common.collect.ImmutableMap; +import java.util.Collection; +import java.util.Collections; +import java.util.Objects; +import java.util.UUID; +import javax.servlet.http.HttpServletRequest; +import org.apache.commons.text.StrSubstitutor; import org.onap.vid.asdc.AsdcCatalogException; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.VidNotions; +import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.properties.Features; +import org.onap.vid.services.AAIServiceTree; import org.onap.vid.services.VidService; -import org.onap.vid.utils.Multival; +import org.onap.vid.utils.Tree; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.togglz.core.manager.FeatureManager; -import javax.servlet.http.HttpServletRequest; -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; - -import static java.util.stream.Collectors.toList; - @RestController @RequestMapping(AaiServiceInstanceStandardQueryController.AAI_STANDARD_QUERY) public class AaiServiceInstanceStandardQueryController extends VidRestrictedBaseController { - public static final String AAI_STANDARD_QUERY = "aai/standardQuery"; + static final String AAI_STANDARD_QUERY = "aai/standardQuery"; + private static final String SERVICE_INSTANCE_URI_TEMPLATE = "" + + "business/customers/customer/${global-customer-id}" + + "/service-subscriptions/service-subscription/${service-type}" + + "/service-instances/service-instance/${service-instance-id}"; - private final ServiceInstanceStandardQuery serviceInstanceStandardQuery; private final FeatureManager featureManager; private final VidService sdcService; + private final AAIServiceTree aaiServiceTree; @Autowired - public AaiServiceInstanceStandardQueryController(FeatureManager featureManager, ServiceInstanceStandardQuery serviceInstanceStandardQuery, VidService sdcService) { + public AaiServiceInstanceStandardQueryController(FeatureManager featureManager, + VidService sdcService, AAIServiceTree aaiServiceTree) { this.featureManager = featureManager; - this.serviceInstanceStandardQuery = serviceInstanceStandardQuery; this.sdcService = sdcService; + this.aaiServiceTree = aaiServiceTree; } @RequestMapping(value = "vlansByNetworks", method = RequestMethod.GET) @@ -80,54 +86,50 @@ public class AaiServiceInstanceStandardQueryController extends VidRestrictedBase return new VlansByNetworksHierarchy(); } - final ServiceInstance serviceInstance = - serviceInstanceStandardQuery.fetchServiceInstance(globalCustomerId, serviceType, serviceInstanceId); + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(NodeType.SERVICE_INSTANCE)); + pathsToSearch.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.NETWORK, NodeType.VLAN_TAG)); + pathsToSearch.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.NETWORK, NodeType.VLAN_TAG)); - Multival>> l3NetworksWithVlansForVnfForService = fetchVnfsForService(serviceInstance); - Multival> l3NetworksWithVlansForService = fetchNetworksForService(serviceInstance); + AAITreeNode aaiTree = aaiServiceTree.buildAAITree(getServiceInstanceUri(globalCustomerId, serviceType, serviceInstanceId), + null, HttpMethod.GET, pathsToSearch, false).get(0); // translate to response's format return new VlansByNetworksHierarchy( - l3NetworksWithVlansForService.getValues().stream().map(this::translateNetworksFormat - ).collect(toList()), - - l3NetworksWithVlansForVnfForService.getValues().stream().map(vnfWithNetworks -> - new VnfVlansByNetworks(vnfWithNetworks.getKey().getVnfId(), - vnfWithNetworks.getValues().stream().map(this::translateNetworksFormat - ).collect(toList()) - ) - ).collect(toList()) + aaiTree.getChildren().stream() + .filter(child -> child.getType() == NodeType.NETWORK) + .map(this::translateNetworksFormat) + .collect(toList()), + + aaiTree.getChildren().stream() + .filter(child -> child.getType() == NodeType.GENERIC_VNF) + .map(vnf -> new VnfVlansByNetworks(vnf.getId(), + vnf.getChildren().stream() + .map(this::translateNetworksFormat) + .collect(toList()) + )) + .collect(toList()) ); } - private Multival>> fetchVnfsForService(ServiceInstance serviceInstance) { - final Multival vnfsForService = - serviceInstanceStandardQuery.fetchRelatedVnfs(serviceInstance); - - final Multival> vnfsWithL3NetworksForService = - vnfsForService.mapEachVal(vnf -> serviceInstanceStandardQuery.fetchRelatedL3Networks("vnf", vnf)); - - return vnfsWithL3NetworksForService.mapEachVal(vnfMulti-> - vnfMulti.mapEachVal(serviceInstanceStandardQuery::fetchRelatedVlanTags) - ); + private String getServiceInstanceUri(String globalCustomerId, String serviceType, String serviceInstanceId) { + return new StrSubstitutor(ImmutableMap.of( + "global-customer-id", globalCustomerId, + "service-type", serviceType, + "service-instance-id", serviceInstanceId + )).replace(SERVICE_INSTANCE_URI_TEMPLATE); } - private Multival> fetchNetworksForService(ServiceInstance serviceInstance) { - final Multival l3NetworksForService = - serviceInstanceStandardQuery.fetchRelatedL3Networks("service", serviceInstance); - - return l3NetworksForService.mapEachVal(serviceInstanceStandardQuery::fetchRelatedVlanTags); - } - - private NetworksToVlans translateNetworksFormat(Multival networkWithVlan) { + private NetworksToVlans translateNetworksFormat(AAITreeNode networkWithVlan) { return new NetworksToVlans( - networkWithVlan.getKey().getNetworkId(), - networkWithVlan.getKey().getNetworkName(), - networkWithVlan.getKey().getNetworkType(), - networkWithVlan.getKey().getOrchestrationStatus(), - networkWithVlan.getValues().stream().map( - vlan -> new NetworksToVlans.Vlan(vlan.getVlanIdInner()) + networkWithVlan.getId(), + networkWithVlan.getName(), + Objects.toString(networkWithVlan.getAdditionalProperties().get("network-type"), null), + networkWithVlan.getOrchestrationStatus(), + networkWithVlan.getChildren().stream().map( + vlan -> new NetworksToVlans.Vlan( + Objects.toString(vlan.getAdditionalProperties().get("vlan-id-outer"), null) + ) ).collect(toList()) ); } @@ -138,8 +140,8 @@ public class AaiServiceInstanceStandardQueryController extends VidRestrictedBase throw new GenericUncheckedException("Internal error while fetching Service Model: " + sdcModelUuid); } VidNotions.ModelCategory serviceModelCategory = serviceModel.getService().getVidNotions().getModelCategory(); - return serviceModelCategory.equals(VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL) || - serviceModelCategory.equals(VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL); + return (serviceModelCategory == VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL) || + (serviceModelCategory == VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL); } protected static class VlansByNetworksHierarchy { @@ -182,10 +184,10 @@ public class AaiServiceInstanceStandardQueryController extends VidRestrictedBase } private static class Vlan { - public final String vlanIdInner; + public final String vlanIdOuter; - private Vlan(String vlanIdInner) { - this.vlanIdInner = vlanIdInner; + private Vlan(String vlanIdOuter) { + this.vlanIdOuter = vlanIdOuter; } } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java index 081e3c640..01b005c4b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/AsyncInstantiationController.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,25 +20,28 @@ package org.onap.vid.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.exceptions.AccessDeniedException; import org.onap.vid.exceptions.OperationNotAllowedException; import org.onap.vid.model.ExceptionResponse; import org.onap.vid.model.JobAuditStatus; import org.onap.vid.model.ServiceInfo; import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.MsoResponseWrapper2; +import org.onap.vid.properties.Features; +import org.onap.vid.roles.RoleProvider; import org.onap.vid.services.AsyncInstantiationBusinessLogic; import org.onap.vid.services.AuditService; import org.onap.vid.utils.SystemPropertiesWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.togglz.core.manager.FeatureManager; import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.UUID; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import static org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED; @@ -51,14 +54,18 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { protected final AsyncInstantiationBusinessLogic asyncInstantiationBL; private final SystemPropertiesWrapper systemPropertiesWrapper; - protected ObjectMapper objectMapper = new ObjectMapper(); + private final RoleProvider roleProvider; + + private final FeatureManager featureManager; @Autowired protected AuditService auditService; @Autowired - public AsyncInstantiationController(AsyncInstantiationBusinessLogic asyncInstantiationBL, SystemPropertiesWrapper systemPropertiesWrapper) { + public AsyncInstantiationController(AsyncInstantiationBusinessLogic asyncInstantiationBL, RoleProvider roleProvider, FeatureManager featureManager, SystemPropertiesWrapper systemPropertiesWrapper) { this.asyncInstantiationBL = asyncInstantiationBL; + this.roleProvider = roleProvider; + this.featureManager = featureManager; this.systemPropertiesWrapper = systemPropertiesWrapper; } @@ -82,14 +89,25 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { public MsoResponseWrapper2> createBulkOfServices(@RequestBody ServiceInstantiation request, HttpServletRequest httpServletRequest) { //Push to DB according the model try { - LOGGER.debug(EELFLoggerDelegate.debugLogger, "incoming ServiceInstantiation request: "+ objectMapper.writeValueAsString(request)); + LOGGER.debug(EELFLoggerDelegate.debugLogger, "incoming ServiceInstantiation request: "+ JACKSON_OBJECT_MAPPER.writeValueAsString(request)); } catch (Exception e) { LOGGER.error(EELFLoggerDelegate.errorLogger, "failed to log incoming ServiceInstantiation request ", e); } String userId = new ControllersUtils(systemPropertiesWrapper).extractUserId(httpServletRequest); - List uuids = asyncInstantiationBL.pushBulkJob(request, userId); + throwExceptionIfAccessDenied(request, httpServletRequest, userId); + List uuids = asyncInstantiationBL.pushBulkJob(request, userId); + return new MsoResponseWrapper2(200, uuids); + } + + + + @RequestMapping(value = "retryJobWithChangedData/{jobId}", method = RequestMethod.POST) + public MsoResponseWrapper2> retryJobWithChangedData(@RequestBody ServiceInstantiation request, @PathVariable(value="jobId") UUID jobId, HttpServletRequest httpServletRequest) { + + String userId = new ControllersUtils(systemPropertiesWrapper).extractUserId(httpServletRequest); + List uuids = asyncInstantiationBL.retryJob(request, jobId, userId); return new MsoResponseWrapper2(200, uuids); } @@ -105,7 +123,7 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { @RequestMapping(value = "auditStatus/{jobId}", method = RequestMethod.GET) public List getJobAuditStatus(HttpServletRequest request, @PathVariable(value="jobId") UUID jobId, @RequestParam(value="source") JobAuditStatus.SourceStatus source){ - return asyncInstantiationBL.getAuditStatuses(jobId, source); + return auditService.getAuditStatuses(jobId, source); } @RequestMapping(value = "auditStatus/{jobId}/mso", method = RequestMethod.GET) @@ -114,7 +132,7 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { @RequestParam(value="requestId", required = false) UUID requestId, @RequestParam(value="serviceInstanceId", required = false) UUID serviceInstanceId){ if (serviceInstanceId != null) { - return auditService.getAuditStatusFromMsoByServiceInstanceId(jobId, serviceInstanceId); + return auditService.getAuditStatusFromMsoByInstanceId(JobAuditStatus.ResourceTypeFilter.SERVICE, serviceInstanceId, jobId); } if (requestId != null){ return auditService.getAuditStatusFromMsoByRequestId(jobId, requestId); @@ -123,5 +141,36 @@ public class AsyncInstantiationController extends VidRestrictedBaseController { } + @RequestMapping(value = "auditStatus/{type}/{instanceId}/mso", method = RequestMethod.GET) + public List getAuditStatusFromMsoByInstanceId(HttpServletRequest request, + @PathVariable(value="type") JobAuditStatus.ResourceTypeFilter resourceTypeFilter, + @PathVariable(value="instanceId") UUID instanceId) { + return auditService.getAuditStatusFromMsoByInstanceId(resourceTypeFilter, instanceId, null); + } + + @RequestMapping(value = "/bulkForRetry/{jobId}", method = RequestMethod.GET) + public ServiceInstantiation getBulkForRetry(HttpServletRequest request, @PathVariable(value="jobId") UUID jobId) { + return asyncInstantiationBL.getBulkForRetry(jobId); + } + + @RequestMapping(value = "retry/{jobId}", method = RequestMethod.POST) + public MsoResponseWrapper2> retryJobRequest(HttpServletRequest httpServletRequest, + @PathVariable(value="jobId") UUID jobId) { + + String userId = new ControllersUtils(systemPropertiesWrapper).extractUserId(httpServletRequest); + List uuids = asyncInstantiationBL.retryJob(jobId, userId); + return new MsoResponseWrapper2(200, uuids); + } + + @RequestMapping(value = "/auditStatusForRetry/{trackById}", method = RequestMethod.GET) + public JobAuditStatus getResourceAuditStatus(HttpServletRequest request, @PathVariable(value="trackById") String trackById) { + return auditService.getResourceAuditStatus(trackById); + } + + private void throwExceptionIfAccessDenied(ServiceInstantiation request, HttpServletRequest httpServletRequest, String userId) { + if (featureManager.isActive(Features.FLAG_1906_INSTANTIATION_API_USER_VALIDATION) && !roleProvider.getUserRolesValidator(httpServletRequest).isServicePermitted(request.getGlobalSubscriberId(), request.getSubscriptionServiceType())) { + throw new AccessDeniedException(String.format("User %s is not allowed to make this request", userId)); + } + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java b/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java index 8d5fbbdbb..20cf6f038 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/MsoConfig.java @@ -56,8 +56,8 @@ public class MsoConfig { @Bean - public MsoBusinessLogic getMsoBusinessLogic(MsoInterface msoClient, FeatureManager featureManager){ - return new MsoBusinessLogicImpl(msoClient, featureManager); + public MsoBusinessLogic getMsoBusinessLogic(MsoInterface msoClient){ + return new MsoBusinessLogicImpl(msoClient); } @Bean diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java b/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java index db3a21910..fc718f0d2 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/MsoController.java @@ -20,9 +20,9 @@ package org.onap.vid.controller; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import static org.onap.vid.utils.Logging.getMethodName; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.LinkedHashMap; import java.util.List; @@ -31,10 +31,14 @@ import javax.servlet.http.HttpServletResponse; import org.onap.portalsdk.core.controller.RestrictedBaseController; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.model.ExceptionResponse; +import org.onap.vid.model.RequestReferencesContainer; import org.onap.vid.model.SoftDeleteRequest; import org.onap.vid.mso.MsoBusinessLogic; import org.onap.vid.mso.MsoResponseWrapper; import org.onap.vid.mso.MsoResponseWrapper2; +import org.onap.vid.mso.RestMsoImplementation; +import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.rest.MsoRestClientNew; import org.onap.vid.mso.rest.Request; import org.onap.vid.mso.rest.RequestDetails; import org.onap.vid.mso.rest.RequestDetailsWrapper; @@ -82,11 +86,13 @@ public class MsoController extends RestrictedBaseController { public static final String START_LOG = " start"; private final MsoBusinessLogic msoBusinessLogic; + private final RestMsoImplementation restMso; private final CloudOwnerService cloudOwnerService; @Autowired - public MsoController(MsoBusinessLogic msoBusinessLogic, CloudOwnerService cloudOwnerService) { + public MsoController(MsoBusinessLogic msoBusinessLogic, MsoRestClientNew msoClientInterface, CloudOwnerService cloudOwnerService) { this.msoBusinessLogic = msoBusinessLogic; + this.restMso = msoClientInterface; this.cloudOwnerService = cloudOwnerService; } @@ -678,30 +684,35 @@ public class MsoController extends RestrictedBaseController { @RequestMapping(value = "/mso_activate_fabric_configuration/{serviceInstanceId}", method = RequestMethod.POST) public MsoResponseWrapper2 activateFabricConfiguration( - @PathVariable("serviceInstanceId") String serviceInstanceId, - @RequestBody RequestDetails requestDetails) { + @PathVariable("serviceInstanceId") String serviceInstanceId , + @RequestBody RequestDetails requestDetails) { String methodName = "activateFabricConfiguration"; LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); - return msoBusinessLogic.activateFabricConfiguration(serviceInstanceId, requestDetails); + String path = msoBusinessLogic.getActivateFabricConfigurationPath(serviceInstanceId); + RestObject msoResponse = restMso.PostForObject(requestDetails, path, RequestReferencesContainer.class); + + return new MsoResponseWrapper2<>(msoResponse); } @RequestMapping(value = "/mso_vfmodule_soft_delete/{serviceInstanceId}/{vnfInstanceId}/{vfModuleInstanceId}", method = RequestMethod.POST) public MsoResponseWrapper2 deactivateAndCloudDelete( - @PathVariable("serviceInstanceId") String serviceInstanceId, - @PathVariable("vnfInstanceId") String vnfInstanceId, - @PathVariable("vfModuleInstanceId") String vfModuleInstanceId, - @RequestBody SoftDeleteRequest softDeleteRequest) { + @PathVariable("serviceInstanceId") String serviceInstanceId, + @PathVariable("vnfInstanceId") String vnfInstanceId, + @PathVariable("vfModuleInstanceId") String vfModuleInstanceId, + @RequestBody SoftDeleteRequest softDeleteRequest) { String methodName = "deactivateAndCloudDelete"; LOGGER.debug(EELFLoggerDelegate.debugLogger, "<== " + methodName + START_LOG); + String path = msoBusinessLogic.getDeactivateAndCloudDeletePath(serviceInstanceId, vnfInstanceId, vfModuleInstanceId); RequestDetails requestDetails = msoBusinessLogic.buildRequestDetailsForSoftDelete(softDeleteRequest); cloudOwnerService.enrichRequestWithCloudOwner(requestDetails); - return msoBusinessLogic - .deactivateAndCloudDelete(serviceInstanceId, vnfInstanceId, vfModuleInstanceId, requestDetails); + RestObject msoResponse = restMso.PostForObject(new org.onap.vid.changeManagement.RequestDetailsWrapper<>(requestDetails), path, RequestReferencesContainer.class); + + return new MsoResponseWrapper2<>(msoResponse); } /** @@ -723,7 +734,7 @@ public class MsoController extends RestrictedBaseController { exceptionResponse.setException(e.getClass().toString().replaceFirst("^.*\\.", "")); exceptionResponse.setMessage(e.getMessage()); - response.getWriter().write(new ObjectMapper().writeValueAsString(exceptionResponse)); + response.getWriter().write(JACKSON_OBJECT_MAPPER.writeValueAsString(exceptionResponse)); response.flushBuffer(); } diff --git a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java index 8d55c62c6..6f4ce4ddb 100644 --- a/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java +++ b/vid-app-common/src/main/java/org/onap/vid/controller/WebConfig.java @@ -21,6 +21,8 @@ package org.onap.vid.controller; +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; + import static org.apache.commons.lang3.StringUtils.isEmpty; import com.fasterxml.jackson.core.JsonProcessingException; @@ -29,6 +31,7 @@ import io.joshworks.restclient.http.mapper.ObjectMapper; import java.io.File; import java.io.IOException; import javax.servlet.ServletContext; +import java.util.concurrent.Executors; import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.aai.AaiClient; import org.onap.vid.aai.AaiClientInterface; @@ -54,6 +57,7 @@ import org.onap.vid.asdc.rest.SdcRestClient; import org.onap.vid.client.SyncRestClient; import org.onap.vid.client.SyncRestClientInterface; import org.onap.vid.properties.AsdcClientConfiguration; +import org.onap.vid.properties.VidProperties; import org.onap.vid.scheduler.SchedulerService; import org.onap.vid.scheduler.SchedulerServiceImpl; import org.onap.vid.services.AAIServiceTree; @@ -73,6 +77,12 @@ import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import javax.servlet.ServletContext; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ExecutorService; + @EnableSwagger2 @Configuration public class WebConfig { @@ -95,8 +105,8 @@ public class WebConfig { @Bean public AaiService getAaiService(AaiClientInterface aaiClient, AaiOverTLSClientInterface aaiOverTLSClient, - AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree) { - return new AaiServiceImpl(aaiClient, aaiOverTLSClient, aaiResponseTranslator, aaiTreeNode, aaiServiceTree); + AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, AAIServiceTree aaiServiceTree, ExecutorService executorService) { + return new AaiServiceImpl(aaiClient, aaiOverTLSClient, aaiResponseTranslator, aaiTreeNode, aaiServiceTree, executorService); } @Bean @@ -223,4 +233,10 @@ public class WebConfig { .paths(PathSelectors.any()) .build(); } + + @Bean + public ExecutorService executorService() { + int threadsCount = defaultIfNull(Integer.parseInt(SystemProperties.getProperty(VidProperties.VID_THREAD_COUNT)), 1); + return Executors.newFixedThreadPool(threadsCount); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt b/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt new file mode 100644 index 000000000..79c7297a3 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/dal/AsyncInstantiationRepository.kt @@ -0,0 +1,147 @@ +/*- + * ============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.dal + +import org.onap.portalsdk.core.domain.support.DomainVo +import org.onap.portalsdk.core.service.DataAccessService +import org.onap.vid.dao.JobRequest +import org.onap.vid.exceptions.GenericUncheckedException +import org.onap.vid.exceptions.NotFoundException +import org.onap.vid.job.Job +import org.onap.vid.model.JobAuditStatus +import org.onap.vid.model.ResourceInfo +import org.onap.vid.model.ServiceInfo +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation +import org.onap.vid.utils.DaoUtils +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Repository +import java.sql.Timestamp +import java.time.LocalDateTime +import java.util.* +import kotlin.collections.HashMap + +@Repository +class AsyncInstantiationRepository @Autowired constructor(val dataAccessService:DataAccessService) { + + fun addJobRequest(jobUuid: UUID, request:ServiceInstantiation) { + save(JobRequest(jobUuid, request)) + } + + fun getJobRequest(jobUuid: UUID):ServiceInstantiation? { + return getSingleItem(JobRequest::class.java, "JOB_ID", jobUuid).request + } + + fun saveResourceInfo(resource:ResourceInfo) { + save(resource) + } + + fun getResourceInfoByRootJobId(rootJobId: UUID): Map { + val resourceInfoList:List = getResultList(ResourceInfo::class.java, "ROOT_JOB_ID", rootJobId) + + if (resourceInfoList.isEmpty()) { + throw GenericUncheckedException("Failed to retrieve resource info with rootJobId " + rootJobId + " from ResourceInfo table. no resource found") + } + return resourceInfoList.fold(HashMap(), { accumulator, item -> + accumulator.put(item.trackById, item); accumulator}) + } + + fun getResourceInfoByTrackId(trackById: String):ResourceInfo { + return getSingleItem(ResourceInfo::class.java, "TRACK_BY_ID", trackById) + } + + fun saveServiceInfo(serviceInfo: ServiceInfo) { + save(serviceInfo) + } + + fun getServiceInfoByJobId(jobUuid: UUID): ServiceInfo { + return getSingleItem(ServiceInfo::class.java, "jobId", jobUuid) + } + + fun getServiceInfoByTemplateIdAndJobStatus(templateId: UUID, jobStatus: Job.JobStatus): List { + return getResultList(ServiceInfo::class.java, mapOf("templateId" to templateId, "jobStatus" to jobStatus), "AND") + } + + fun getAllServicesInfo(): List { + return dataAccessService.getList(ServiceInfo::class.java, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null) as List + } + + private fun filterByCreationDateAndNotDeleted(): String { + val minus3Months = LocalDateTime.now().minusMonths(3) + val filterDate = Timestamp.valueOf(minus3Months) + return " WHERE" + + " hidden = false" + + " and deleted_at is null" + // don't fetch deleted + + " and created >= '" + filterDate + "' " + } + + private fun orderByCreatedDateAndStatus(): String { + return " createdBulkDate DESC ,\n" + + " (CASE jobStatus\n" + + " WHEN 'COMPLETED' THEN 0\n" + + " WHEN 'FAILED' THEN 0\n" + + " WHEN 'COMPLETED_WITH_ERRORS' THEN 0\n" + + " WHEN 'IN_PROGRESS' THEN 1\n" + + " WHEN 'PAUSE' THEN 2\n" + + " WHEN 'PENDING' THEN 3\n" + + " WHEN 'STOPPED' THEN 3 END),\n" + + " statusModifiedDate " + } + + fun getAuditStatuses(jobUUID: UUID, source: JobAuditStatus.SourceStatus): List { + // order by ORDINAL. + // CREATED_DATE is kept for backward compatibility: when all Ordinals are zero + return getResultList(JobAuditStatus::class.java, mapOf("SOURCE" to source, "JOB_ID" to jobUUID), "AND", " ORDINAL, CREATED_DATE ") + } + + fun addJobAudiStatus(jobAuditStatus:JobAuditStatus) { + save(jobAuditStatus) + } + + private fun save(item:T) { + dataAccessService.saveDomainObject(item, DaoUtils.getPropsMap()) + } + + private fun getSingleItem(className:Class, filterKey:String, filterValue:Any): T { + val resultList:List = getResultList(className, filterKey, filterValue) + if (resultList.size < 1) { + throw NotFoundException("Failed to retrieve $className with $filterKey $filterValue from table. no resource found") + }else if (resultList.size > 1) { + throw GenericUncheckedException("Failed to retrieve $className with $filterKey $filterValue from table. found more than 1 resources") + } + return resultList[0] + } + + private fun getResultList(className:Class, filterKey:String, filterValue:Any): List { + return getResultList(className, mapOf(filterKey to filterValue), "AND", null) + } + + private fun getResultList(className:Class, filters: Map, conditionType: String): List { + return getResultList(className, filters, conditionType, null) + } + + private fun getResultList(className:Class, filters: Map, conditionType: String, orderBy: String?): List { + var condition:String = filters + .map{f -> f.key + " = '" + f.value + "'"} + .joinToString(" $conditionType ") + return dataAccessService.getList(className, " WHERE $condition", orderBy, null) as List + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/dao/JobRequest.java b/vid-app-common/src/main/java/org/onap/vid/dao/JobRequest.java new file mode 100644 index 000000000..eb4035836 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/dao/JobRequest.java @@ -0,0 +1,111 @@ +/*- + * ============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.dao; + +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.io.IOException; +import java.util.Objects; +import java.util.UUID; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SelectBeforeUpdate; +import org.hibernate.annotations.Type; +import org.onap.vid.model.VidBaseEntity; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; + + +@DynamicUpdate +@SelectBeforeUpdate +@Entity +@Table(name = "vid_job_request") +public class JobRequest extends VidBaseEntity { + + private UUID jobId; + private ServiceInstantiation request; + + + public JobRequest(UUID jobId, ServiceInstantiation request) { + this.jobId = jobId; + this.request = request; + } + + public JobRequest() { + } + + @Id + @Column(name = "JOB_ID", columnDefinition = "CHAR(36)") + @Type(type = "org.hibernate.type.UUIDCharType") + public UUID getJobId() { + return jobId; + } + + public void setJobId(UUID jobId) { + this.jobId = jobId; + } + + @Transient + public ServiceInstantiation getRequest() { + return request; + } + + public void setRequest(ServiceInstantiation request) { + this.request = request; + } + + //the columnDefinition is used only in UT + @Column(name = "REQUEST", columnDefinition = "VARCHAR(30000)") + public String getRequestRaw() { + try { + return JACKSON_OBJECT_MAPPER.writeValueAsString(request); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public void setRequestRaw(String raw) { + try { + this.request = JACKSON_OBJECT_MAPPER.readValue(raw, ServiceInstantiation.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof JobRequest)) return false; + JobRequest that = (JobRequest) o; + return Objects.equals(getJobId(), that.getJobId()) && + Objects.equals(getRequest(), that.getRequest()); + } + + @Override + public int hashCode() { + return Objects.hash(getJobId(), getRequest()); + } +} + diff --git a/vid-app-common/src/main/java/org/onap/vid/exceptions/AbortingException.java b/vid-app-common/src/main/java/org/onap/vid/exceptions/AbortingException.java new file mode 100644 index 000000000..22c312513 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/exceptions/AbortingException.java @@ -0,0 +1,28 @@ +/*- + * ============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.exceptions; + +public class AbortingException extends RuntimeException { + + public AbortingException(Throwable cause) { + super(cause); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/exceptions/AccessDeniedException.java b/vid-app-common/src/main/java/org/onap/vid/exceptions/AccessDeniedException.java new file mode 100644 index 000000000..e82bfbc9d --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/exceptions/AccessDeniedException.java @@ -0,0 +1,29 @@ +/*- + * ============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.exceptions; + +public class AccessDeniedException extends GenericUncheckedException { + public AccessDeniedException(String message) { + super(message); + } + + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/exceptions/TryAgainException.java b/vid-app-common/src/main/java/org/onap/vid/exceptions/TryAgainException.java new file mode 100644 index 000000000..f46e7e3b5 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/exceptions/TryAgainException.java @@ -0,0 +1,28 @@ +/*- + * ============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.exceptions; + +public class TryAgainException extends RuntimeException { + + public TryAgainException(Throwable cause) { + super(cause); + } +} 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); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/Action.java b/vid-app-common/src/main/java/org/onap/vid/model/Action.java index ebaa691af..c0d4fae6a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/Action.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/Action.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,9 @@ package org.onap.vid.model; public enum Action { Create(ServiceInfo.ServiceAction.INSTANTIATE), Delete(ServiceInfo.ServiceAction.DELETE), - None(ServiceInfo.ServiceAction.UPDATE); + None(ServiceInfo.ServiceAction.UPDATE), + Resume(ServiceInfo.ServiceAction.RESUME), + Replace(ServiceInfo.ServiceAction.REPLACE); private final ServiceInfo.ServiceAction serviceAction; Action(ServiceInfo.ServiceAction serviceAction){ diff --git a/vid-app-common/src/main/java/org/onap/vid/model/JobAuditStatus.java b/vid-app-common/src/main/java/org/onap/vid/model/JobAuditStatus.java index 49e25ecb0..645934530 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/JobAuditStatus.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/JobAuditStatus.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,6 +20,21 @@ package org.onap.vid.model; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; +import java.util.UUID; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -29,14 +44,6 @@ import org.hibernate.annotations.Type; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.job.Job.JobStatus; -import javax.persistence.*; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; -import java.util.UUID; - /* The following 2 annotations let hibernate to update only fields that actually have been changed. DynamicUpdate tell hibernate to update only dirty fields. @@ -54,43 +61,40 @@ public class JobAuditStatus extends VidBaseEntity { public JobAuditStatus(){} - public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source){ + private JobAuditStatus(UUID jobId, String instanceName, String instanceType, String jobStatus, + SourceStatus source, UUID requestId, String additionalInfo, Date date, int ordinal) { this.jobId = jobId; + this.instanceName = instanceName; + this.instanceType = instanceType; this.jobStatus = jobStatus; this.source = source; + this.requestId = requestId; + setAdditionalInfo(additionalInfo); + this.ordinal = ordinal; + this.created = date; } - public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source, Date date){ - this(jobId, jobStatus, source); - this.created = date; + public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source){ + this(jobId, null, null, jobStatus, source, null, null, null, 0); } public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source, UUID requestId, String additionalInfo) { - this(jobId, jobStatus, source); - this.requestId = requestId; - setAdditionalInfo(additionalInfo); + this(jobId, null, null, jobStatus, source, requestId, additionalInfo, null, 0); } - public JobAuditStatus(UUID jobId, String jobStatus, SourceStatus source, UUID requestId, String additionalInfo, Date date){ - this(jobId, jobStatus, source, requestId, additionalInfo); - this.created = date; + public JobAuditStatus(String instanceName, String jobStatus, UUID requestId, String additionalInfo, String date, String instanceType) { + this(null, instanceName, instanceType, jobStatus, null, requestId, additionalInfo, null, 0); + this.created = dateStringToDate(date); } - public JobAuditStatus(String instanceName, String jobStatus, UUID requestId, String additionalInfo) { - this.instanceName = instanceName; - this.jobStatus = jobStatus; - this.requestId = requestId; - this.additionalInfo = additionalInfo; - + public static JobAuditStatus createForTest(UUID jobId, String jobStatus, SourceStatus source, Date date, int ordinal) { + return new JobAuditStatus(jobId, null, null, jobStatus, source, null, null, date, ordinal); } - public JobAuditStatus(String instanceName, String jobStatus, UUID requestId, String additionalInfo, String date, String instanceType) { - this(instanceName, jobStatus, requestId, additionalInfo); - this.created = dateStringToDate(date); - this.instanceType = instanceType; + public static JobAuditStatus createForTest(UUID jobId, String jobStatus, SourceStatus source, UUID requestId, String additionalInfo, Date date) { + return new JobAuditStatus(jobId, null, null, jobStatus, source, requestId, additionalInfo, date, 0); } - private Date dateStringToDate(String dateAsString){ if (StringUtils.isEmpty(dateAsString)) { return null; @@ -121,6 +125,7 @@ public class JobAuditStatus extends VidBaseEntity { .append(source, that.source) .append(requestId, that.requestId) .append(additionalInfo, that.additionalInfo) + // ordinal is not part of equality (similarly to "created" field) .isEquals(); } @@ -132,6 +137,7 @@ public class JobAuditStatus extends VidBaseEntity { .append(source) .append(requestId) .append(additionalInfo) + // ordinal is not part of equality (similarly to "created" field) .toHashCode(); } @@ -140,6 +146,25 @@ public class JobAuditStatus extends VidBaseEntity { VID } + public enum ResourceTypeFilter { + SERVICE("serviceInstanceId"), + VNF("vnfInstanceId"), + VFMODULE("vfModuleInstanceId"), + NETWORK("networkInstanceId"), + VNFGROUP("instanceGroupId"); + + private final String filterBy; + + ResourceTypeFilter(String filterBy) { + this.filterBy = filterBy; + } + + public String getFilterBy() { + return filterBy; + } + } + + private UUID jobId; private String instanceName; private String instanceType; @@ -147,6 +172,7 @@ public class JobAuditStatus extends VidBaseEntity { private SourceStatus source; private UUID requestId; private String additionalInfo; + private int ordinal; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -206,6 +232,18 @@ public class JobAuditStatus extends VidBaseEntity { this.additionalInfo = StringUtils.substring(additionalInfo, 0, MAX_ADDITIONAL_INFO_LENGTH); } + @Column(name = "ORDINAL", columnDefinition = "INT") + public int getOrdinal() { + // Ordinal allows sorting audit statuses by + // insertion order, regardless of "created" + // field + return ordinal; + } + + public void setOrdinal(int ordinal) { + this.ordinal = ordinal; + } + @Transient public String getInstanceName() { return instanceName; diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java b/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java index 98514f0c1..45e100fb1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/ModelUtil.java @@ -18,15 +18,8 @@ * ============LICENSE_END========================================================= */ -/** - * - */ package org.onap.vid.model; -/** - * The Class ModelUtil. - * - */ public class ModelUtil { /** * Gets the tags for the given element according to the configured namespace diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ResourceInfo.java b/vid-app-common/src/main/java/org/onap/vid/model/ResourceInfo.java new file mode 100644 index 000000000..deda23f37 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/ResourceInfo.java @@ -0,0 +1,144 @@ +/*- + * ============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.model; + +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.io.IOException; +import java.util.Objects; +import java.util.UUID; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Transient; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SelectBeforeUpdate; +import org.hibernate.annotations.Type; +import org.onap.vid.exceptions.GenericUncheckedException; +import org.onap.vid.job.Job; +import org.onap.vid.job.JobException; +import org.onap.vid.mso.rest.AsyncRequestStatus; + +@DynamicUpdate +@SelectBeforeUpdate +@Entity +@Table(name = "vid_resource_info") +public class ResourceInfo extends VidBaseEntity { + + private String trackById; + private UUID rootJobId; + private String instanceId; + private Job.JobStatus jobStatus; + private AsyncRequestStatus errorMessage; + + public ResourceInfo(){} + + public ResourceInfo(String trackById, UUID rootJobId, String instanceId, Job.JobStatus jobStatus, AsyncRequestStatus errorMessage) { + this.trackById = trackById; + this.rootJobId = rootJobId; + this.instanceId = instanceId; + this.jobStatus = jobStatus; + this.errorMessage = errorMessage; + } + + @Id + @Column(name = "TRACK_BY_ID", columnDefinition = "CHAR(36)") + public String getTrackById() { + return trackById; + } + + @Column(name = "ROOT_JOB_ID", columnDefinition = "CHAR(36)") + @Type(type="org.hibernate.type.UUIDCharType") + public UUID getRootJobId() { + return rootJobId; + } + + @Column(name="JOB_STATUS") + @Enumerated(EnumType.STRING) + public Job.JobStatus getJobStatus() { + return jobStatus; + } + + @Column(name="INSTANCE_ID") + public String getInstanceId() { + return instanceId; + } + + public void setTrackById(String trackById) { + this.trackById = trackById; + } + + public void setRootJobId(UUID rootJobId) { + this.rootJobId = rootJobId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + public void setJobStatus(Job.JobStatus jobStatus) { + this.jobStatus = jobStatus; + } + + @Column(name = "ERROR_MESSAGE", columnDefinition = "VARCHAR(30000)") + public String getErrorMessageRaw() { + try { + return JACKSON_OBJECT_MAPPER.writeValueAsString(errorMessage); + } catch (JsonProcessingException e) { + throw new GenericUncheckedException(e); + } + } + + public void setErrorMessageRaw(String failedMessage) { + try { + this.errorMessage = JACKSON_OBJECT_MAPPER.readValue(failedMessage, AsyncRequestStatus.class); + } catch (IOException e) { + throw new JobException("Error parsing mso failed message", rootJobId, e); + } + } + + @Transient + public AsyncRequestStatus getErrorMessage() { + return this.errorMessage; + } + + public void setErrorMessage(AsyncRequestStatus errorMessage) { + this.errorMessage = errorMessage; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ResourceInfo that = (ResourceInfo) o; + return Objects.equals(trackById, that.trackById) && + Objects.equals(instanceId, that.instanceId) && + jobStatus == that.jobStatus; + } + + @Override + public int hashCode() { + return Objects.hash(trackById, instanceId, jobStatus); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ServiceInfo.java b/vid-app-common/src/main/java/org/onap/vid/model/ServiceInfo.java index 3b49eedca..1e1e6c2a7 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/ServiceInfo.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/ServiceInfo.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. @@ -18,22 +18,22 @@ * ============LICENSE_END========================================================= */ - package org.onap.vid.model; +package org.onap.vid.model; - import com.fasterxml.jackson.annotation.JsonProperty; - import org.hibernate.annotations.DynamicUpdate; - import org.hibernate.annotations.SelectBeforeUpdate; - import org.hibernate.annotations.Type; - import org.onap.portalsdk.core.domain.support.DomainVo; - import org.onap.vid.job.Job; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SelectBeforeUpdate; +import org.hibernate.annotations.Type; +import org.onap.portalsdk.core.domain.support.DomainVo; +import org.onap.vid.job.Job; - import javax.persistence.*; - import java.io.Serializable; - import java.util.Date; - import java.util.Objects; - import java.util.Set; - import java.util.UUID; +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; /* The following 2 annotations let hibernate to update only fields that actually have been changed. @@ -49,11 +49,9 @@ public class ServiceInfo extends DomainVo { public enum ServiceAction { INSTANTIATE, DELETE, - UPDATE - } - - public void setUserId(String userId) { - this.userId = userId; + UPDATE, + RESUME, + REPLACE } private UUID jobId; @@ -65,6 +63,7 @@ public class ServiceInfo extends DomainVo { private Date statusModifiedDate; private boolean hidden; private boolean pause; + private boolean retryEnabled; private Date deletedAt; private String owningEntityId; private String owningEntityName; @@ -90,7 +89,12 @@ public class ServiceInfo extends DomainVo { } - public ServiceInfo(String userId, Boolean aLaCarte, Job.JobStatus jobStatus, boolean pause, UUID jobId, UUID templateId, String owningEntityId, String owningEntityName, String project, String aicZoneId, String aicZoneName, String tenantId, String tenantName, String regionId, String regionName, String serviceType, String subscriberName, String subscriberId, String serviceInstanceId, String serviceInstanceName, String serviceModelId, String serviceModelName, String serviceModelVersion, Date createdBulkDate, ServiceAction action) { + public ServiceInfo(String userId, Boolean aLaCarte, Job.JobStatus jobStatus, boolean pause, UUID jobId, UUID templateId, + String owningEntityId, String owningEntityName, String project, String aicZoneId, String aicZoneName, + String tenantId, String tenantName, String regionId, String regionName, String serviceType, + String subscriberName, String subscriberId, String serviceInstanceId, String serviceInstanceName, + String serviceModelId, String serviceModelName, String serviceModelVersion, Date createdBulkDate, + ServiceAction action, boolean retryEnabled) { this.userId = userId; this.aLaCarte = aLaCarte; this.jobStatus = jobStatus; @@ -116,6 +120,7 @@ public class ServiceInfo extends DomainVo { this.serviceModelVersion = serviceModelVersion; this.createdBulkDate = createdBulkDate; this.action = action; + this.retryEnabled = retryEnabled; } @Column(name = "JOB_ID", columnDefinition = "CHAR(36)") @@ -168,6 +173,12 @@ public class ServiceInfo extends DomainVo { return pause; } + @Column(name="IS_RETRY_ENABLED") + @JsonProperty("isRetryEnabled") + public boolean isRetryEnabled() { + return retryEnabled; + } + @Column(name="OWNING_ENTITY_ID") public String getOwningEntityId() { return owningEntityId; @@ -260,8 +271,8 @@ public class ServiceInfo extends DomainVo { @Column(name="DELETED_AT") public Date getDeletedAt() { - return deletedAt; - } + return deletedAt; + } @Column(name="ACTION") @Enumerated(EnumType.STRING) @@ -319,6 +330,9 @@ public class ServiceInfo extends DomainVo { return super.getAuditTrail(); } + public void setUserId(String userId) { + this.userId = userId; + } public void setJobId(UUID jobId) { this.jobId = jobId; } @@ -351,6 +365,10 @@ public class ServiceInfo extends DomainVo { this.pause = pause; } + public void setRetryEnabled(boolean retryEnabled) { + this.retryEnabled = retryEnabled; + } + public void setOwningEntityId(String owningEntityId) { this.owningEntityId = owningEntityId; } @@ -424,55 +442,54 @@ public class ServiceInfo extends DomainVo { } public void setDeletedAt(Date deletedAt) { - this.deletedAt = deletedAt; - } + this.deletedAt = deletedAt; + } public void setAction(ServiceAction action) { this.action = action; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ServiceInfo)) return false; - ServiceInfo that = (ServiceInfo) o; - return isHidden() == that.isHidden() && - isPause() == that.isPause() && - isALaCarte() == that.isALaCarte() && - Objects.equals(getDeletedAt(), that.getDeletedAt()) && - Objects.equals(getJobId(), that.getJobId()) && - Objects.equals(getTemplateId(), that.getTemplateId()) && - Objects.equals(getUserId(), that.getUserId()) && - Objects.equals(getMsoRequestId(), that.getMsoRequestId()) && - getJobStatus() == that.getJobStatus() && - Objects.equals(getStatusModifiedDate(), that.getStatusModifiedDate()) && - Objects.equals(getOwningEntityId(), that.getOwningEntityId()) && - Objects.equals(getOwningEntityName(), that.getOwningEntityName()) && - Objects.equals(getProject(), that.getProject()) && - Objects.equals(getAicZoneId(), that.getAicZoneId()) && - Objects.equals(getAicZoneName(), that.getAicZoneName()) && - Objects.equals(getTenantId(), that.getTenantId()) && - Objects.equals(getTenantName(), that.getTenantName()) && - Objects.equals(getRegionId(), that.getRegionId()) && - Objects.equals(getRegionName(), that.getRegionName()) && - Objects.equals(getServiceType(), that.getServiceType()) && - Objects.equals(getSubscriberName(), that.getSubscriberName()) && - Objects.equals(getSubscriberId(), that.getSubscriberId()) && - Objects.equals(getServiceInstanceId(), that.getServiceInstanceId()) && - Objects.equals(getServiceInstanceName(), that.getServiceInstanceName()) && - Objects.equals(getServiceModelId(), that.getServiceModelId()) && - Objects.equals(getServiceModelName(), that.getServiceModelName()) && - Objects.equals(getServiceModelVersion(), that.getServiceModelVersion()) && - Objects.equals(getCreatedBulkDate(), that.getCreatedBulkDate()) && - Objects.equals(getAction(), that.getAction()); - } - - @Override - public int hashCode() { - - return Objects.hash(getJobId(), getTemplateId(), getUserId(), getMsoRequestId(), isALaCarte(), getJobStatus(), getStatusModifiedDate(), - isHidden(), isPause(), getDeletedAt(), getOwningEntityId(), getOwningEntityName(), getProject(), - getAicZoneId(), getAicZoneName(), getTenantId(), getTenantName(), getRegionId(), - getRegionName(), getServiceType(), getSubscriberName(), getSubscriberId(), getServiceInstanceId(), - getServiceInstanceName(), getServiceModelId(), getServiceModelName(), - getServiceModelVersion(), getCreatedBulkDate(), getAction()); - } - } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ServiceInfo)) return false; + ServiceInfo that = (ServiceInfo) o; + return aLaCarte == that.aLaCarte && + isHidden() == that.isHidden() && + isPause() == that.isPause() && + isRetryEnabled() == that.isRetryEnabled() && + Objects.equals(getJobId(), that.getJobId()) && + Objects.equals(getTemplateId(), that.getTemplateId()) && + Objects.equals(getUserId(), that.getUserId()) && + Objects.equals(getMsoRequestId(), that.getMsoRequestId()) && + getJobStatus() == that.getJobStatus() && + Objects.equals(getStatusModifiedDate(), that.getStatusModifiedDate()) && + Objects.equals(getDeletedAt(), that.getDeletedAt()) && + Objects.equals(getOwningEntityId(), that.getOwningEntityId()) && + Objects.equals(getOwningEntityName(), that.getOwningEntityName()) && + Objects.equals(getProject(), that.getProject()) && + Objects.equals(getAicZoneId(), that.getAicZoneId()) && + Objects.equals(getAicZoneName(), that.getAicZoneName()) && + Objects.equals(getTenantId(), that.getTenantId()) && + Objects.equals(getTenantName(), that.getTenantName()) && + Objects.equals(getRegionId(), that.getRegionId()) && + Objects.equals(getRegionName(), that.getRegionName()) && + Objects.equals(getServiceType(), that.getServiceType()) && + Objects.equals(getSubscriberName(), that.getSubscriberName()) && + Objects.equals(getSubscriberId(), that.getSubscriberId()) && + Objects.equals(getServiceInstanceId(), that.getServiceInstanceId()) && + Objects.equals(getServiceInstanceName(), that.getServiceInstanceName()) && + Objects.equals(getServiceModelId(), that.getServiceModelId()) && + Objects.equals(getServiceModelName(), that.getServiceModelName()) && + Objects.equals(getServiceModelVersion(), that.getServiceModelVersion()) && + Objects.equals(getCreatedBulkDate(), that.getCreatedBulkDate()) && + getAction() == that.getAction(); + } + + @Override + public int hashCode() { + return Objects.hash(getJobId(), getTemplateId(), getUserId(), getMsoRequestId(), aLaCarte, getJobStatus(), + getStatusModifiedDate(), isHidden(), isPause(), isRetryEnabled(), getDeletedAt(), getOwningEntityId(), getOwningEntityName(), + getProject(), getAicZoneId(), getAicZoneName(), getTenantId(), getTenantName(), getRegionId(), getRegionName(), getServiceType(), + getSubscriberName(), getSubscriberId(), getServiceInstanceId(), getServiceInstanceName(), getServiceModelId(), getServiceModelName(), + getServiceModelVersion(), getCreatedBulkDate(), getAction()); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java b/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java index c1e403587..121c7e4c1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/ServiceModel.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * VID * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 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. @@ -40,14 +40,14 @@ public class ServiceModel { /** The service. */ private Service service; - + /** The vnfs. */ private Map vnfs; - + /** The networks. */ private Map networks; - private Map collectionResource; + private Map collectionResources; /** Port Mirroring Configuration node templates */ private Map configurations; @@ -60,12 +60,12 @@ public class ServiceModel { /** * The vf modules. The VNF also has vfmodules but the vfmodules at the service level may have additional info - * that is not present in the VNF, like the vf module customization String + * that is not present in the VNF, like the vf module customization String */ private Map vfModules; - /** - * The volume groups. The VNF also has volume groups but the volume groups will be populated at the service level - * for newer models + /** + * The volume groups. The VNF also has volume groups but the volume groups will be populated at the service level + * for newer models */ private Map volumeGroups; @@ -74,12 +74,15 @@ public class ServiceModel { /** Resource groups of VF (VNF) type. */ private Map vnfGroups; - + + /** The vrfs */ + private Map vrfs; + /** * Instantiates a new service model. */ public ServiceModel() {} - + /** * Gets the service. * @@ -140,6 +143,10 @@ public class ServiceModel { return vnfGroups; } + public Map getVrfs() { + return vrfs; + } + /** * Sets the service. * @@ -230,12 +237,16 @@ public class ServiceModel { this.vnfGroups = vnfGroups; } - public Map getCollectionResource() { - return collectionResource; + public void setVrfs(Map vrfs) { + this.vrfs = vrfs; } - public void setCollectionResource(Map collectionResource) { - this.collectionResource = collectionResource; + public Map getCollectionResources() { + return collectionResources; + } + + public void setCollectionResources(Map collectionResources) { + this.collectionResources = collectionResources; } public Map getFabricConfigurations() { @@ -254,9 +265,9 @@ public class ServiceModel { * @return the service */ public static Service extractService(ToscaModel serviceToscaModel, org.onap.vid.asdc.beans.Service asdcServiceMetadata) { - + final Service service = new Service(); - + service.setCategory(serviceToscaModel.getMetadata().getCategory()); service.setInvariantUuid(serviceToscaModel.getMetadata().getInvariantUUID()); service.setName(serviceToscaModel.getMetadata().getName()); @@ -274,18 +285,18 @@ public class ServiceModel { public static void extractGroups (ToscaModel serviceToscaModel,ServiceModel serviceModel) { // Get the groups. The groups may duplicate the groups that are in the VNF model and have // additional data like the VF module customization String> - + final Map vfModules = new HashMap<> (); final Map volumeGroups = new HashMap<> (); - + String asdcModelNamespace = VidProperties.getAsdcModelNamespace(); - String vfModuleTag = asdcModelNamespace + ModelConstants.VF_MODULE; - + String vfModuleTag = asdcModelNamespace + ModelConstants.VF_MODULE; + for (Entry component : serviceToscaModel.gettopology_template().getGroups().entrySet()) { final Group group = component.getValue(); final String type = group.getType(); final String customizationName = component.getKey(); - + if (type.startsWith(vfModuleTag)) { VfModule vfMod = VfModule.extractVfModule(customizationName, group); vfModules.put(customizationName, vfMod); @@ -298,14 +309,14 @@ public class ServiceModel { // add this point vfModules and volume groups are disconnected from VNF serviceModel.setVfModules (vfModules); serviceModel.setVolumeGroups (volumeGroups); - + } /** * Populate the vf modules and volume groups that we may have under the service level under each VNF. */ public void associateGroups() { String methodName = "associateGroups()"; - LOG.debug(EELFLoggerDelegate.debugLogger, methodName + " start"); + LOG.debug(EELFLoggerDelegate.debugLogger, methodName + " start"); // go through the vnfs, get the vnf normalized name and look for a vf module with a customization name that starts // with vnf + ".." String vnfCustomizationName = null; @@ -319,13 +330,13 @@ public class ServiceModel { LOG.debug(EELFLoggerDelegate.debugLogger, methodName + " VNF customizationName=" + vnfCustomizationName + "normalized customization name=" + normalizedVnfCustomizationName); - + // now check to see if there is a vf module with customization name that starts with normalizedVnfCustomizationName if (!MapUtils.isEmpty(getVolumeGroups())) { for (Entry vfModuleComponent : getVfModules().entrySet()) { vfModuleCustomizationName = vfModuleComponent.getValue().getModelCustomizationName(); - + LOG.debug(EELFLoggerDelegate.debugLogger, methodName + " VF Module customizationName=" + vfModuleCustomizationName ); if ( vfModuleCustomizationName.startsWith(normalizedVnfCustomizationName + ".." )) { @@ -335,7 +346,7 @@ public class ServiceModel { } } } - + } @@ -346,14 +357,14 @@ public class ServiceModel { (tmpVnf.getVfModules()).put(vfModuleComponent.getKey(), vfModuleComponent.getValue()); LOG.debug(EELFLoggerDelegate.debugLogger, methodName + - " Associated VF Module customizationName=" + vfModuleComponent.getKey() + " with VNF customization name=" + vnfCustomizationName); + " Associated VF Module customizationName=" + vfModuleComponent.getKey() + " with VNF customization name=" + vnfCustomizationName); // now find if this vf module has volume groups, if so, find the volume group with the same customization name and put it under the VNF if ( vfModuleComponent.getValue().isVolumeGroupAllowed() ) { if (isVolumeGroupsContainsVfModuleCustomName(vfModuleCustomizationName)) { - (vnfComponent.getValue().getVolumeGroups()).put(vfModuleCustomizationName, (getVolumeGroups()).get(vfModuleCustomizationName)); - } - } + (vnfComponent.getValue().getVolumeGroups()).put(vfModuleCustomizationName, (getVolumeGroups()).get(vfModuleCustomizationName)); + } + } } private boolean isVolumeGroupsContainsVfModuleCustomName(String vfModuleCustomizationName) { diff --git a/vid-app-common/src/main/java/org/onap/vid/model/VersionAndFeatures.kt b/vid-app-common/src/main/java/org/onap/vid/model/VersionAndFeatures.kt new file mode 100644 index 000000000..730e382d3 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/VersionAndFeatures.kt @@ -0,0 +1,12 @@ +package org.onap.vid.model + +data class VersionAndFeatures( + val features:String, + val build:String, + val displayVersion:String +) { + companion object { + val unknown: VersionAndFeatures = VersionAndFeatures("unknown", "unknown", "unknown") + } +} + diff --git a/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt b/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt index 7f06bfe2f..f67d8fbd9 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.kt +++ b/vid-app-common/src/main/java/org/onap/vid/model/VidNotions.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. @@ -26,7 +26,10 @@ import com.fasterxml.jackson.annotation.JsonValue import com.google.common.base.CaseFormat class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) - val instantiationUI: InstantiationUI, val modelCategory: ModelCategory, val viewEditUI: InstantiationUI) { + val instantiationUI: InstantiationUI, + val modelCategory: ModelCategory, + val viewEditUI: InstantiationUI, + val instantiationType: InstantiationType) { enum class InstantiationUI { NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS, SERVICE_WITH_FABRIC_CONFIGURATION, @@ -34,7 +37,12 @@ class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de, ANY_ALACARTE_NEW_UI, MACRO_SERVICE, - SERVICE_WITH_VNF_GROUPING; + SERVICE_WITH_VNF_GROUPING, + TRANSPORT_SERVICE, + SERVICE_WITH_COLLECTION_RESOURCE, + A_LA_CARTE_VNF_SERVICE_ROLE, + INFRASTRUCTURE_VPN + ; @JsonValue fun toLowerCamel(): String { @@ -48,7 +56,16 @@ class VidNotions(@get:JsonInclude(JsonInclude.Include.NON_NULL) IS_5G_PROVIDER_NETWORK_MODEL, @JsonProperty("5G Fabric Configuration") IS_5G_FABRIC_CONFIGURATION_MODEL, + Transport, + SERVICE_WITH_COLLECTION_RESOURCE, + INFRASTRUCTURE_VPN, @JsonProperty("other") OTHER } + + enum class InstantiationType { + Macro, + ALaCarte, + ClientConfig + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AAITreeNode.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AAITreeNode.java index 4b16b3122..f092c9ae6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AAITreeNode.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AAITreeNode.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,17 +20,19 @@ package org.onap.vid.model.aaiTree; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.apache.commons.lang3.StringUtils; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; +import org.onap.vid.mso.model.CloudConfiguration; import java.util.*; public class AAITreeNode { - private String type; - private int uniqueNumber; + private NodeType type; private String orchestrationStatus; private String provStatus; - private Boolean inMaint = null; + private boolean inMaint; private String modelVersionId; private String modelCustomizationId; private String modelInvariantId; @@ -41,25 +43,19 @@ public class AAITreeNode { private String modelCustomizationName; private final List children = Collections.synchronizedList(new LinkedList<>()); private Map additionalProperties = new HashMap<>(); + private CloudConfiguration cloudConfiguration; + private RelationshipList relationshipList; private String keyInModel; private AAITreeNode parent; - public String getType() { + public NodeType getType() { return type; } - public void setType(String type) { + public void setType(NodeType type) { this.type = type; } - public int getUniqueNumber() { - return uniqueNumber; - } - - public void setUniqueNumber(int uniqueNumber) { - this.uniqueNumber = uniqueNumber; - } - public String getOrchestrationStatus() { return orchestrationStatus; } @@ -76,11 +72,11 @@ public class AAITreeNode { this.provStatus = provStatus; } - public Boolean getInMaint() { + public boolean getInMaint() { return inMaint; } - public void setInMaint(Boolean inMaint) { + public void setInMaint(boolean inMaint) { this.inMaint = inMaint; } @@ -169,7 +165,7 @@ public class AAITreeNode { } public String getUniqueNodeKey() { - return getNodeKey() + ":" + String.format("%03d", this.uniqueNumber); + return this.id; } public void setKeyInModel(String keyInModel) { @@ -180,6 +176,8 @@ public class AAITreeNode { return keyInModel; } + //prevent cyclic serialization of parent and children + @JsonIgnore public AAITreeNode getParent() { return parent; } @@ -188,6 +186,22 @@ public class AAITreeNode { this.parent = parent; } + public CloudConfiguration getCloudConfiguration() { + return cloudConfiguration; + } + + public void setCloudConfiguration(CloudConfiguration cloudConfiguration) { + this.cloudConfiguration = cloudConfiguration; + } + + public RelationshipList getRelationshipList() { + return relationshipList; + } + + public void setRelationshipList(RelationshipList relationshipList) { + this.relationshipList = relationshipList; + } + public void addChildren(List children) { for (AAITreeNode child : children) { child.setParent(this); diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AbstractNode.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AbstractNode.java index 64e953e17..a0fa60e97 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AbstractNode.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/AbstractNode.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 abstract class AbstractNode { protected String productFamilyId; protected String lcpCloudRegionId; protected String tenantId; + protected String cloudOwner; protected ModelInfo modelInfo; public AbstractNode() { @@ -70,4 +71,7 @@ public abstract class AbstractNode { return modelInfo; } + public String getCloudOwner() { + return cloudOwner; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/CollectionResource.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/CollectionResource.kt new file mode 100644 index 000000000..054618dd5 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/CollectionResource.kt @@ -0,0 +1,15 @@ +package org.onap.vid.model.aaiTree + +import org.apache.commons.lang.StringUtils + +fun isNfc(node: AAITreeNode): Boolean { + return node.type == NodeType.INSTANCE_GROUP && + node.additionalProperties["instance-group-type"] != null && + StringUtils.equalsIgnoreCase(node.additionalProperties["instance-group-type"].toString(), "L3-NETWORK") +} + +class CollectionResource(node: AAITreeNode) : Node(node) { + + val ncfs: Map = node.children.filter { isNfc(it) }.map { it.uniqueNodeKey to NCF(it) }.toMap() + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/InstanceGroup.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/InstanceGroup.kt new file mode 100644 index 000000000..490853aa1 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/InstanceGroup.kt @@ -0,0 +1,23 @@ +package org.onap.vid.model.aaiTree + +open class InstanceGroup(aaiNode: AAITreeNode) : Node(aaiNode) { + var instanceGroupRole: String? = null + var instanceGroupFunction: String? = null + + init { + val INSTANCE_GROUP_TYPE = "instance-group-type" + val INSTANCE_GROUP_ROLE = "instance-group-role" + val INSTANCE_GROUP_FUNCTION = "instance-group-function" + + if (aaiNode.additionalProperties[INSTANCE_GROUP_TYPE] != null) { + instanceType = aaiNode.additionalProperties[INSTANCE_GROUP_TYPE].toString() + } + if (aaiNode.additionalProperties[INSTANCE_GROUP_FUNCTION] != null) { + instanceGroupFunction = aaiNode.additionalProperties[INSTANCE_GROUP_FUNCTION].toString() + } + if (aaiNode.additionalProperties[INSTANCE_GROUP_ROLE] != null) { + instanceGroupRole = aaiNode.additionalProperties[INSTANCE_GROUP_ROLE].toString() + } + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NCF.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NCF.kt new file mode 100644 index 000000000..6d407da4c --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NCF.kt @@ -0,0 +1,12 @@ +package org.onap.vid.model.aaiTree + +import org.apache.commons.lang.StringUtils + +class NCF(node: AAITreeNode) : InstanceGroup(node) { + val numberOfNetworks: Int = if (node.relationshipList != null && node.relationshipList.relationship != null) { + node.relationshipList.relationship + .filter { StringUtils.equalsIgnoreCase(it.relatedTo, "L3-NETWORK") } + .count() + } else 0 +} + diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Network.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Network.java index e80e57520..6b3023332 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Network.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Network.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,21 +20,121 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; - +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; +import static org.onap.vid.aai.util.AAITreeConverter.NETWORK_ROLE; import static org.onap.vid.aai.util.AAITreeConverter.NETWORK_TYPE; +import static org.onap.vid.aai.util.AAITreeConverter.PHYSICAL_NETWORK_NAME; +import static org.onap.vid.aai.util.AAITreeConverter.SERVICE_INSTANCE; +import static org.onap.vid.aai.util.AAITreeConverter.SERVICE_INSTANCE_SERVICE_INSTANCE_ID; +import static org.onap.vid.aai.util.AAITreeConverter.SERVICE_INSTANCE_SERVICE_INSTANCE_NAME; +import static org.onap.vid.aai.util.AAITreeConverter.TENANT; +import static org.onap.vid.aai.util.AAITreeConverter.TENANT_TENANT_NAME; +import static org.onap.vid.aai.util.AAITreeConverter.VPN_BINDING; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.commons.collections.CollectionUtils; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; +import org.onap.vid.aai.util.AAITreeNodeUtils; +@JsonInclude(NON_NULL) public class Network extends Node { - public Network(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.network); + private String role; + private String physicalName; + private String serviceName; + private String serviceUUID; + private String tenantName; + private Boolean isBoundToVpn; + private RouteTarget routeTarget; + + public Network(){} + + private Network(AAITreeNode node) { + super(node); + fillCloudConfigurationProperties(this, node.getCloudConfiguration()); } public static Network from(AAITreeNode node) { Network network = new Network(node); - if (node.getAdditionalProperties().get(NETWORK_TYPE) != null) { - network.setInstanceType(node.getAdditionalProperties().get(NETWORK_TYPE).toString()); + network.setInstanceType(readValueAsStringFromAdditionalProperties(node, NETWORK_TYPE)); + network.setRole(readValueAsStringFromAdditionalProperties(node, NETWORK_ROLE)); + network.setPhysicalName(readValueAsStringFromAdditionalProperties(node, PHYSICAL_NETWORK_NAME)); + RelationshipList relationshipList = node.getRelationshipList(); + Relationship serviceInstanceRelationship = AAITreeNodeUtils.findFirstRelationshipByRelatedTo(relationshipList, SERVICE_INSTANCE).orElse(null); + if (serviceInstanceRelationship != null) { + network.setServiceName(AAITreeNodeUtils.findFirstValue(serviceInstanceRelationship.getRelatedToPropertyList(), SERVICE_INSTANCE_SERVICE_INSTANCE_NAME).orElse(null)); + network.setServiceUUID(AAITreeNodeUtils.findFirstValue(serviceInstanceRelationship.getRelationDataList(), SERVICE_INSTANCE_SERVICE_INSTANCE_ID).orElse(null)); } + AAITreeNodeUtils.findFirstRelationshipByRelatedTo(relationshipList, TENANT).ifPresent( + tenantRelationship -> network.setTenantName(AAITreeNodeUtils.findFirstValue(tenantRelationship.getRelatedToPropertyList(), TENANT_TENANT_NAME).orElse(null)) + ); + // We are ignoring "is-bound-to-vpn" parameter from additionalProperties because there is a requirement to define vpn binding presence from by related-to: vpn-binding + network.setBoundToVpn(AAITreeNodeUtils.findFirstRelationshipByRelatedTo(relationshipList, VPN_BINDING).isPresent()); + + //get the route target + node.getChildren().stream() + .filter(x->x.getType()== NodeType.VPN_BINDING) // get all VPN_BINDING related to the network + .map(x->VpnBindingKt.from(x)) // create VPN_BINDING nodes + .filter(x-> CollectionUtils.isNotEmpty(x.getRouteTargets())) // get the RouteTargets that are not empty + .findFirst() // get the first one + .ifPresent(x->network.setRouteTarget(x.getRouteTargets().get(0))); // If there is a route target - add it to the network return network; } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getPhysicalName() { + return physicalName; + } + + public void setPhysicalName(String physicalName) { + this.physicalName = physicalName; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getServiceUUID() { + return serviceUUID; + } + + public void setServiceUUID(String serviceUUID) { + this.serviceUUID = serviceUUID; + } + + public String getTenantName() { + return tenantName; + } + + public void setTenantName(String tenantName) { + this.tenantName = tenantName; + } + + public Boolean isBoundToVpn() { + return isBoundToVpn; + } + + public void setBoundToVpn(Boolean boundToVpn) { + isBoundToVpn = boundToVpn; + } + + public RouteTarget getRouteTarget() { + return routeTarget; + } + + public void setRouteTarget(RouteTarget routeTarget) { + this.routeTarget = routeTarget; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Node.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Node.java index 5ce5eec43..435f70f1a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Node.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Node.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,9 +20,12 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; +import org.onap.vid.mso.model.CloudConfiguration; import org.onap.vid.mso.model.ModelInfo; +import java.util.Objects; +import java.util.UUID; + public class Node extends AbstractNode { private String instanceType; @@ -38,7 +41,11 @@ public class Node extends AbstractNode { private final String trackById; - public Node(AAITreeNode aaiNode, AAITreeConverter.ModelType modelType) { + public Node() { + trackById = UUID.randomUUID().toString(); + } + + public Node(AAITreeNode aaiNode) { super(); this.instanceId = aaiNode.getId(); this.instanceName = aaiNode.getName(); @@ -46,11 +53,13 @@ public class Node extends AbstractNode { this.provStatus = aaiNode.getProvStatus(); this.inMaint = aaiNode.getInMaint(); this.uuid = aaiNode.getModelVersionId(); - this.originalName = aaiNode.getModelCustomizationName(); + this.originalName = aaiNode.getKeyInModel(); this.trackById = aaiNode.getUniqueNodeKey(); ModelInfo nodeModelInfo = new ModelInfo(); - nodeModelInfo.setModelType(modelType.name()); + if (aaiNode.getType() != null) { + nodeModelInfo.setModelType(aaiNode.getType().getModelType()); + } nodeModelInfo.setModelName(aaiNode.getModelName()); nodeModelInfo.setModelVersion(aaiNode.getModelVersion()); nodeModelInfo.setModelVersionId(aaiNode.getModelVersionId()); @@ -156,4 +165,16 @@ public class Node extends AbstractNode { public String getTrackById() { return trackById; } + + public static void fillCloudConfigurationProperties(AbstractNode that, CloudConfiguration cloudConfiguration) { + if (cloudConfiguration !=null) { + that.lcpCloudRegionId = cloudConfiguration.getLcpCloudRegionId(); + that.tenantId = cloudConfiguration.getTenantId(); + that.cloudOwner = cloudConfiguration.getCloudOwner(); + } + } + + public static String readValueAsStringFromAdditionalProperties(AAITreeNode node, String key) { + return Objects.toString(node.getAdditionalProperties().get(key), null); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NodeType.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NodeType.java new file mode 100644 index 000000000..5e1228f9f --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/NodeType.java @@ -0,0 +1,82 @@ +/*- + * ============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.model.aaiTree; + +public enum NodeType { + SERVICE_INSTANCE("service-instance", "service-instance-id", "service-instance-name", "service"), + GENERIC_VNF ("generic-vnf", "vnf-id", "vnf-name", "vnf"), + NETWORK ("l3-network", "network-id", "network-name", "network"), + FAILURE ("failure_node", NodeType.NONE, NodeType.NONE, NodeType.NONE), + COLLECTION_RESOURCE ("collection", "collection-id", "collection-name", "collection"), + CONFIGURATION ("configuration", "configuration-id", "configuration-name", "configuration"), + PNF ("pnf", "pnf-id", "pnf-name", "pnf"), + VF_MODULE ("vf-module", "vf-module-id", "vf-module-name", "vfModule"), + INSTANCE_GROUP ("instance-group", "id", "instance-group-name", "instanceGroup"), + PORT ("l-interface", "interface-id", "interface-name", "connectionPoint"), + VOLUME_GROUP ("volume-group", "volume-group-id", "volume-group-name", "volumeGroup"), + VLAN_TAG("vlan-tag", "vlan-tag-id", NodeType.NONE, NodeType.NONE), + VPN_BINDING("vpn-binding", "vpn-id", "vpn-name", "vpnBinding"), + ; + + private String type; + private String id; + private String name; + private String modelType; + + public static final String NONE = ""; + + NodeType(String type, String id, String name, String modelType) { + this.type = type; + this.id = id; + this.name = name; + this.modelType = modelType; + } + + public String getType() { + return type; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getModelType() { + return modelType; + } + + public static NodeType fromString(String type) { + for (NodeType nodeType : NodeType.values()) { + if (nodeType.type.equalsIgnoreCase(type)) { + return nodeType; + } + } + return null; + } + + @Override + public String toString() { + return this.type; + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/RelatedVnf.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/RelatedVnf.java index 37dc45afd..febd8e0fd 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/RelatedVnf.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/RelatedVnf.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,10 +20,10 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; - import static org.onap.vid.aai.util.AAITreeConverter.VNF_TYPE; +import org.apache.commons.lang3.builder.ToStringBuilder; + public class RelatedVnf extends Node { private String serviceInstanceId; @@ -55,13 +55,15 @@ public class RelatedVnf extends Node { } public RelatedVnf(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.vnf); + super(node); } public static RelatedVnf from(AAITreeNode node) { RelatedVnf vnf = new RelatedVnf(node); - vnf.setServiceInstanceId(node.getParent().getId()); - vnf.setServiceInstanceName(node.getParent().getName()); + if (node.getParent() != null && node.getParent().getType() == NodeType.SERVICE_INSTANCE) { + vnf.setServiceInstanceId(node.getParent().getId()); + vnf.setServiceInstanceName(node.getParent().getName()); + } if (node.getAdditionalProperties().get(VNF_TYPE) != null) { vnf.setInstanceType(node.getAdditionalProperties().get(VNF_TYPE).toString()); @@ -69,4 +71,22 @@ public class RelatedVnf extends Node { return vnf; } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("serviceInstanceId", serviceInstanceId) + .append("serviceInstanceName", serviceInstanceName) + .append("tenantName", tenantName) + .append("action", action) + .append("instanceName", instanceName) + .append("instanceId", instanceId) + .append("orchStatus", orchStatus) + .append("productFamilyId", productFamilyId) + .append("lcpCloudRegionId", lcpCloudRegionId) + .append("tenantId", tenantId) + .append("cloudOwner", cloudOwner) + .append("modelInfo", modelInfo) + .toString(); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java index 111e98b25..923be132f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/ServiceInstance.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,10 +20,9 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.mso.model.ModelInfo; - import java.util.HashMap; import java.util.Map; +import org.onap.vid.mso.model.ModelInfo; public class ServiceInstance extends AbstractNode { @@ -43,13 +42,17 @@ public class ServiceInstance extends AbstractNode { private Map vnfs = new HashMap<>(); private Map networks = new HashMap<>(); + private Map vrfs = new HashMap<>(); + private Map vnfGroups = new HashMap<>(); + private Map collectionResources = new HashMap<>(); private int validationCounter; private Map existingVNFCounterMap; private Map existingNetworksCounterMap; private Map existingVnfGroupCounterMap; + private Map existingVRFCounterMap; public void setInstanceName(String instanceName) { this.instanceName = instanceName; @@ -175,6 +178,14 @@ public class ServiceInstance extends AbstractNode { this.networks = networks; } + public Map getCollectionResources() { + return collectionResources; + } + + public void setCollectionResources(Map collectionResources) { + this.collectionResources = collectionResources; + } + public Map getVnfGroups() { return vnfGroups; } public void setVnfGroups(Map vnfGroups) { this.vnfGroups = vnfGroups; } @@ -210,4 +221,20 @@ public class ServiceInstance extends AbstractNode { public void setExistingVnfGroupCounterMap(Map existingVnfGroupCounterMap) { this.existingVnfGroupCounterMap = existingVnfGroupCounterMap; } + + public Map getVrfs() { + return vrfs; + } + + public void setVrfs(Map vrfs) { + this.vrfs = vrfs; + } + + public Map getExistingVRFCounterMap() { + return existingVRFCounterMap; + } + + public void setExistingVRFCounterMap(Map existingVRFCounterMap) { + this.existingVRFCounterMap = existingVRFCounterMap; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VfModule.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VfModule.java index 2a4c83b2a..0db27eaa4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VfModule.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VfModule.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,8 +20,6 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; - import static org.onap.vid.aai.util.AAITreeConverter.IS_BASE_VF_MODULE; public class VfModule extends Node { @@ -30,7 +28,8 @@ public class VfModule extends Node { private String volumeGroupName; public VfModule(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.vfModule); + super(node); + fillCloudConfigurationProperties(this, node.getCloudConfiguration()); } public boolean getIsBase() { diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vnf.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vnf.java index 03c1508f9..2df5bdcf6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vnf.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vnf.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,21 +20,19 @@ package org.onap.vid.model.aaiTree; -import org.onap.vid.aai.util.AAITreeConverter; -import org.onap.vid.services.AAITreeNodeBuilder; +import static org.onap.vid.aai.util.AAITreeConverter.VNF_TYPE; import java.util.HashMap; import java.util.Map; -import static org.onap.vid.aai.util.AAITreeConverter.VNF_TYPE; - public class Vnf extends Node { private Map> vfModules = new HashMap<>(); private Map networks = new HashMap<>(); public Vnf(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.vnf); + super(node); + fillCloudConfigurationProperties(this, node.getCloudConfiguration()); } public Map> getVfModules() { @@ -60,11 +58,11 @@ public class Vnf extends Node { } node.getChildren().forEach(child -> { - if (child.getType().equals(AAITreeNodeBuilder.VF_MODULE)) { + if (child.getType() == NodeType.VF_MODULE) { vnf.getVfModules().putIfAbsent(child.getNodeKey(), new HashMap<>()); vnf.getVfModules().get(child.getNodeKey()) - .put(child.getUniqueNodeKey(), VfModule.from(child)); - } else if (child.getType().equals(AAITreeNodeBuilder.NETWORK)) { + .put(child.getUniqueNodeKey(), VfModule.from(child)); + } else if (child.getType() == NodeType.NETWORK) { vnf.getNetworks().put(child.getUniqueNodeKey(), Network.from(child)); } }); diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.java deleted file mode 100644 index 21e5ca45e..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.java +++ /dev/null @@ -1,72 +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.model.aaiTree; - -import org.onap.vid.aai.util.AAITreeConverter; - - -public class VnfGroup extends Node { - - public static final String INSTANCE_GROUP_TYPE = "instance-group-type"; - public static final String INSTANCE_GROUP_ROLE = "instance-group-role"; - public static final String INSTANCE_GROUP_FUNCTION = "instance-group-function"; - - private String instanceGroupRole; - private String instanceGroupFunction; - - - public VnfGroup(AAITreeNode node) { - super(node, AAITreeConverter.ModelType.instanceGroup); - } - - public static VnfGroup from(AAITreeNode node) { - VnfGroup vnfGroup = new VnfGroup(node); - if (node.getAdditionalProperties().get(INSTANCE_GROUP_TYPE) != null) { - vnfGroup.setInstanceType(node.getAdditionalProperties().get(INSTANCE_GROUP_TYPE).toString()); - } - if (node.getAdditionalProperties().get(INSTANCE_GROUP_FUNCTION) != null) { - vnfGroup.setInstanceGroupFunction(node.getAdditionalProperties().get(INSTANCE_GROUP_FUNCTION).toString()); - } - if (node.getAdditionalProperties().get(INSTANCE_GROUP_ROLE) != null) { - vnfGroup.setInstanceGroupRole(node.getAdditionalProperties().get(INSTANCE_GROUP_ROLE).toString()); - } - - return vnfGroup; - } - - public String getInstanceGroupRole() { - return instanceGroupRole; - } - - public void setInstanceGroupRole(String instanceGroupRole) { - this.instanceGroupRole = instanceGroupRole; - } - - public String getInstanceGroupFunction() { - return instanceGroupFunction; - } - - public void setInstanceGroupFunction(String instanceGroupFunction) { - this.instanceGroupFunction = instanceGroupFunction; - } - - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.kt new file mode 100644 index 000000000..47a6c98be --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VnfGroup.kt @@ -0,0 +1,10 @@ +package org.onap.vid.model.aaiTree + +class VnfGroup(node: AAITreeNode) : InstanceGroup(node) { + + val vnfs: Map = node.children + .filter { it.type == NodeType.GENERIC_VNF } + .map { it.uniqueNodeKey to RelatedVnf.from(it) } + .toMap() + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VpnBinding.kt b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VpnBinding.kt new file mode 100644 index 000000000..d43bf26f0 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/VpnBinding.kt @@ -0,0 +1,50 @@ +package org.onap.vid.model.aaiTree + +import com.fasterxml.jackson.annotation.JsonAlias +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.core.type.TypeReference +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.vid.utils.JACKSON_OBJECT_MAPPER + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +class VpnBinding(aaiNode: AAITreeNode) : Node(aaiNode) { + @JsonCreator + constructor() : this(AAITreeNode()) + var region: String? = null + var customerId: String? = null + var routeTargets: List? = null +} + +val LOGGER: EELFLoggerDelegate = EELFLoggerDelegate.getLogger(VpnBinding::class.java) + +fun from(node: AAITreeNode): VpnBinding { + val vpnBinding = VpnBinding(node) + vpnBinding.platformName = Node.readValueAsStringFromAdditionalProperties(node, "vpn-platform") + vpnBinding.instanceType = Node.readValueAsStringFromAdditionalProperties(node, "vpn-type") + vpnBinding.region = Node.readValueAsStringFromAdditionalProperties(node, "vpn-region") + vpnBinding.customerId = Node.readValueAsStringFromAdditionalProperties(node, "customer-vpn-id") + + vpnBinding.routeTargets = try { + JACKSON_OBJECT_MAPPER.convertValue( + node.additionalProperties.getOrDefault("route-targets", emptyList()), + object : TypeReference>() {}) + } catch (exception: Exception) { + LOGGER.error("Failed to parse route-targets of vpn with id:${vpnBinding.instanceId}", exception) + listOf(RouteTarget("ParsingFailure", "ParsingFailure")) + } + + return vpnBinding +} + +@JsonIgnoreProperties(ignoreUnknown = true) +data class RouteTarget( + + @JsonAlias("global-route-target") + val globalRouteTarget: String? = null, + + @JsonAlias("route-target-role") + val routeTargetRole: String? = null +) diff --git a/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vrf.java b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vrf.java new file mode 100644 index 000000000..d6ef7ab0e --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/aaiTree/Vrf.java @@ -0,0 +1,65 @@ +/*- + * ============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.model.aaiTree; + +import java.util.HashMap; +import java.util.Map; + +public class Vrf extends Node { + + private Map networks = new HashMap<>(); + private Map vpns = new HashMap<>(); + + + public Vrf(AAITreeNode node){ + super(node); + } + + public static Vrf from(AAITreeNode node) { + Vrf vrf = new Vrf(node); + + node.getChildren().forEach(child -> { + if (child.getType() == NodeType.NETWORK) { + vrf.getNetworks().put(child.getUniqueNodeKey(), Network.from(child)); + } + if (child.getType() == NodeType.VPN_BINDING) { + vrf.getVpns().put(child.getUniqueNodeKey(), VpnBindingKt.from(child)); + } + }); + return vrf; + } + + public Map getNetworks() { + return networks; + } + + public void setNetworks(Map networks) { + this.networks = networks; + } + + public Map getVpns() { + return vpns; + } + + public void setVpns(Map vpns) { + this.vpns = vpns; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/errorReport/ReportCreationParameters.java b/vid-app-common/src/main/java/org/onap/vid/model/errorReport/ReportCreationParameters.java index babbf8906..e7b7fa67d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/errorReport/ReportCreationParameters.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/errorReport/ReportCreationParameters.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.vid.model.errorReport; public class ReportCreationParameters { diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.java index fe9ebc037..926dc3cdc 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/BaseResource.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,25 +20,29 @@ package org.onap.vid.model.serviceInstantiation; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.StringUtils; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.model.Action; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; public abstract class BaseResource implements JobAdapter.AsyncJobRequest { - protected final String instanceId; + protected String instanceId; + protected ModelInfo modelInfo; protected String instanceName; - protected final Action action; + protected Action action; protected String lcpCloudRegionId; @@ -48,13 +52,21 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest { protected boolean rollbackOnFailure; - private static final Map actionStingToEnumMap = ImmutableMap.of( - "Delete", Action.Delete, - "Create", Action.Create, - "None", Action.None, - "Update_Delete", Action.Delete, - "None_Delete", Action.Delete - ); + protected String trackById; + + protected Boolean isFailed; + + protected String statusMessage; + + private static final Map actionStingToEnumMap = ImmutableMap.builder() + .put("Delete", Action.Delete) + .put("Create", Action.Create) + .put("None", Action.None) + .put("Update_Delete", Action.Delete) + .put("None_Delete", Action.Delete) + .put("Resume", Action.Resume) + .put("Replace", Action.Replace) + .build(); protected BaseResource(@JsonProperty("modelInfo") ModelInfo modelInfo, @@ -65,16 +77,22 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest { @JsonProperty("tenantId") String tenantId, @JsonProperty("instanceParams") List> instanceParams, @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, - @JsonProperty("instanceId") String instanceId) { + @JsonProperty("instanceId") String instanceId, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { this.modelInfo = modelInfo; this.modelInfo.setModelType(getModelType()); this.rollbackOnFailure = rollbackOnFailure; - this.instanceName = StringUtils.defaultString(instanceName, "");; + this.instanceName = StringUtils.defaultString(instanceName, ""); this.action = actionStringToEnum(action); this.lcpCloudRegionId = StringUtils.isNotEmpty(legacyRegion) ? legacyRegion : lcpCloudRegionId; this.tenantId = tenantId; this.instanceParams = instanceParams; this.instanceId = instanceId; + this.trackById = trackById; + this.isFailed = isFailed!= null ? isFailed: false; + this.statusMessage = statusMessage; } private Action actionStringToEnum(String actionAsString) { @@ -90,7 +108,7 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest { } public Action getAction() { - return action; + return (action == null ? Action.Create : action); } public String getLcpCloudRegionId() { @@ -105,11 +123,49 @@ public abstract class BaseResource implements JobAdapter.AsyncJobRequest { return instanceParams == null ? Collections.emptyList() : instanceParams; } - public boolean isRollbackOnFailure() { return rollbackOnFailure; } + public boolean isRollbackOnFailure() { return rollbackOnFailure; } public String getInstanceId() { return instanceId; } protected abstract String getModelType(); + + public String getTrackById() { + return trackById; + } + + public void setTrackById(String trackById) { + this.trackById = trackById; + } + + public Boolean getIsFailed() { + return isFailed; + } + + public void setIsFailed(Boolean isFailed) { + this.isFailed = isFailed; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + public void setAction(Action action) { + this.action = action; + } + + public String getStatusMessage() { + return statusMessage; + } + + public void setStatusMessage(String statusMessage) { + this.statusMessage = statusMessage; + } + + @JsonIgnore + public abstract Collection getChildren(); + + @JsonIgnore + public abstract JobType getJobType(); } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.java index 3fda8429b..b945f1327 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroup.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,21 +22,47 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + public class InstanceGroup extends BaseResource implements JobAdapter.AsyncJobRequest { + private final Map vnfGroupMembers; + public InstanceGroup(@JsonProperty("modelInfo") ModelInfo modelInfo, @JsonProperty("instanceName") String instanceName, @JsonProperty("action") String action, @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, - @JsonProperty("instanceId") String instanceId) { + @JsonProperty("instanceId") String instanceId, + @JsonProperty("vnfs") Map vnfGroupMembers, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { - super(modelInfo, instanceName, action, null, null, null, null, rollbackOnFailure, instanceId); + super(modelInfo, instanceName, action, null, null, null, null, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); + this.vnfGroupMembers = vnfGroupMembers; } @Override protected String getModelType() { return "instanceGroup"; } + + @Override + public Collection getChildren() { + return getVnfGroupMembers().values(); + } + + public Map getVnfGroupMembers() { + return vnfGroupMembers == null ? Collections.emptyMap() : vnfGroupMembers; + } + + @Override + public JobType getJobType() { + return JobType.InstanceGroup; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java new file mode 100644 index 000000000..7bfaf02b1 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/InstanceGroupMember.java @@ -0,0 +1,54 @@ +/*- + * ============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.model.serviceInstantiation; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collection; +import java.util.Collections; +import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; +import org.onap.vid.mso.model.ModelInfo; + +public class InstanceGroupMember extends BaseResource implements JobAdapter.AsyncJobRequest{ + + public InstanceGroupMember(@JsonProperty("instanceId") String instanceId, + @JsonProperty("action") String action, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { + super(new ModelInfo(), null, action, null, null, null, null, false, instanceId, trackById, isFailed, statusMessage); + } + + @Override + protected String getModelType() { + return "vnf"; + } + + @Override + public Collection getChildren() { + return Collections.emptyList(); + } + + @Override + public JobType getJobType() { + return JobType.InstanceGroupMember; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java index addd7e1ee..797e28a02 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Network.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * VID * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 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. @@ -22,8 +22,11 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -36,19 +39,22 @@ public class Network extends BaseResource implements JobAdapter.AsyncJobRequest private final String lineOfBusiness; public Network(@JsonProperty("modelInfo") ModelInfo modelInfo, - @JsonProperty("productFamilyId") String productFamilyId, - @JsonProperty("instanceName") String instanceName, + @JsonProperty("productFamilyId") String productFamilyId, + @JsonProperty("instanceName") String instanceName, @JsonProperty("action") String action, - @JsonProperty("platformName") String platformName, - @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, + @JsonProperty("platformName") String platformName, + @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, @JsonProperty("legacyRegion") String legacyRegion, - @JsonProperty("tenantId") String tenantId, - @JsonProperty("instanceParams") List> instanceParams, - @JsonProperty("lineOfBusinessName") String lineOfBusiness, - @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, - @JsonProperty("instanceId") String instanceId) { + @JsonProperty("tenantId") String tenantId, + @JsonProperty("instanceParams") List> instanceParams, + @JsonProperty("lineOfBusinessName") String lineOfBusiness, + @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, + @JsonProperty("instanceId") String instanceId, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { - super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId); + super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); this.productFamilyId = productFamilyId; this.platformName = platformName; this.lineOfBusiness = lineOfBusiness; @@ -71,4 +77,14 @@ public class Network extends BaseResource implements JobAdapter.AsyncJobRequest return "network"; } + @Override + public Collection getChildren() { + return Collections.emptyList(); + } + + @Override + public JobType getJobType() { + return JobType.NetworkInstantiation; + } + } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java index 5d963134b..afc8534a1 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/ServiceInstantiation.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,18 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang3.ObjectUtils; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; +import org.onap.vid.model.VidNotions; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class ServiceInstantiation extends BaseResource implements JobAdapter.AsyncJobRequest { @@ -58,12 +64,15 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy private final boolean isPause; - private final int bulkSize; + private int bulkSize; private final String testApi; private final boolean isALaCarte; + private final VidNotions vidNotions; + private Map vrfs; + public ServiceInstantiation(@JsonProperty("modelInfo") ModelInfo modelInfo, @JsonProperty("owningEntityId") String owningEntityId, @JsonProperty("owningEntityName") String owningEntityName, @@ -82,6 +91,7 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy @JsonProperty("vnfs") Map vnfs, @JsonProperty("networks") Map networks, @JsonProperty("vnfGroups") Map vnfGroups, + @JsonProperty("vrfs") Map vrfs, @JsonProperty("instanceParams") List> instanceParams, @JsonProperty("pause") boolean isPause, @JsonProperty("bulkSize") int bulkSize, @@ -89,9 +99,12 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy @JsonProperty("isALaCarte") boolean isALaCarte, @JsonProperty("testApi") String testApi, @JsonProperty("instanceId") String instanceId, - @JsonProperty("action") String action - ) { - super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId); + @JsonProperty("action") String action, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage, + @JsonProperty("vidNotions") VidNotions vidNotions) { + super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); this.owningEntityId = owningEntityId; this.owningEntityName = owningEntityName; this.projectName = projectName; @@ -105,12 +118,15 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy this.vnfs = vnfs; this.networks = networks; this.vnfGroups = vnfGroups; + this.vrfs = vrfs; this.isPause = isPause; this.bulkSize = bulkSize; this.isALaCarte = isALaCarte; this.testApi = isALaCarte ? testApi : null; + this.vidNotions = vidNotions; } + public String getOwningEntityId() { return owningEntityId; } @@ -152,15 +168,19 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy } public Map getVnfs() { - return vnfs == null ? Collections.emptyMap() : vnfs; + return emptyMapIfNull(vnfs); } public Map getNetworks() { - return networks == null ? Collections.emptyMap() : networks; + return emptyMapIfNull(networks); } public Map getVnfGroups() { - return vnfGroups == null ? Collections.emptyMap() : vnfGroups; + return emptyMapIfNull(vnfGroups); + } + + public Map getVrfs() { + return emptyMapIfNull(vrfs); } public boolean isPause() { @@ -169,11 +189,24 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy public int getBulkSize() { return bulkSize; } + public void setBulkSize(int bulkSize) { + this.bulkSize = bulkSize; + } + + public VidNotions getVidNotions() { + return vidNotions; + } + @Override protected String getModelType() { return "service"; } + @Override + public Collection getChildren() { + return Stream.of(getNetworks().values(), getVnfs().values(), getVnfGroups().values()).flatMap(Collection::stream).collect(Collectors.toList()); + } + @JsonProperty("isALaCarte") public boolean isALaCarte() { return isALaCarte; @@ -183,4 +216,13 @@ public class ServiceInstantiation extends BaseResource implements JobAdapter.Asy return this.testApi; } -} + @Override + public JobType getJobType() { + return JobType.ALaCarteService; + } + + private Map emptyMapIfNull(Map map) { + return ObjectUtils.defaultIfNull(map, Collections.emptyMap()); + } + +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java index b56f116cd..97b23af20 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VfModule.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * VID * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 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. @@ -23,8 +23,11 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -37,22 +40,25 @@ import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest { @JsonInclude(NON_NULL) private final String volumeGroupInstanceName; - private boolean usePreload; + @JsonInclude(NON_NULL) private Boolean usePreload; private Map supplementaryParams; public VfModule( @JsonProperty("modelInfo") ModelInfo modelInfo, - @JsonProperty("instanceName") String instanceName, - @JsonProperty("volumeGroupName") String volumeGroupInstanceName, + @JsonProperty("instanceName") String instanceName, + @JsonProperty("volumeGroupName") String volumeGroupInstanceName, @JsonProperty("action") String action, - @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, - @JsonProperty("legacyRegion") String legacyRegion, - @JsonProperty("tenantId") String tenantId, - @JsonProperty("instanceParams") List> instanceParams, - @JsonProperty("supplementaryFileContent") Map supplementaryParams, - @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, - @JsonProperty("sdncPreLoad") boolean usePreload, - @JsonProperty("instanceId") String instanceId) { - super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId); + @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, + @JsonProperty("legacyRegion") String legacyRegion, + @JsonProperty("tenantId") String tenantId, + @JsonProperty("instanceParams") List> instanceParams, + @JsonProperty("supplementaryFileContent") Map supplementaryParams, + @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, + @JsonProperty("sdncPreLoad") Boolean usePreload, + @JsonProperty("instanceId") String instanceId, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { + super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); this.volumeGroupInstanceName = volumeGroupInstanceName; this.usePreload = usePreload; this.supplementaryParams = supplementaryParams; @@ -62,7 +68,8 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest return volumeGroupInstanceName; } - public boolean isUsePreload() { + public Boolean isUsePreload() { + return usePreload; } @@ -75,5 +82,13 @@ public class VfModule extends BaseResource implements JobAdapter.AsyncJobRequest return "vfModule"; } + @Override + public Collection getChildren() { + return Collections.emptyList(); + } -} + @Override + public JobType getJobType() { + return JobType.VfmoduleInstantiation; + } +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java index 2619533a7..0da3f0695 100644 --- a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/Vnf.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * VID * ================================================================================ - * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017 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. @@ -23,10 +23,12 @@ package org.onap.vid.model.serviceInstantiation; import com.fasterxml.jackson.annotation.JsonProperty; import org.onap.vid.job.JobAdapter; +import org.onap.vid.job.JobType; import org.onap.vid.mso.model.ModelInfo; -import java.util.List; -import java.util.Map; +import java.util.*; + +import static java.util.stream.Collectors.toList; /** * The Class VNF. @@ -42,24 +44,27 @@ public class Vnf extends BaseResource implements JobAdapter.AsyncJobRequest { private final Map> vfModules; public Vnf(@JsonProperty("modelInfo") ModelInfo modelInfo, - @JsonProperty("productFamilyId") String productFamilyId, - @JsonProperty("instanceName") String instanceName, + @JsonProperty("productFamilyId") String productFamilyId, + @JsonProperty("instanceName") String instanceName, @JsonProperty("action") String action, - @JsonProperty("platformName") String platformName, - @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, - @JsonProperty("legacyRegion") String legacyRegion, - @JsonProperty("tenantId") String tenantId, - @JsonProperty("instanceParams") List> instanceParams, - @JsonProperty("lineOfBusinessName") String lineOfBusiness, - @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, + @JsonProperty("platformName") String platformName, + @JsonProperty("lcpCloudRegionId") String lcpCloudRegionId, + @JsonProperty("legacyRegion") String legacyRegion, + @JsonProperty("tenantId") String tenantId, + @JsonProperty("instanceParams") List> instanceParams, + @JsonProperty("lineOfBusinessName") String lineOfBusiness, + @JsonProperty("rollbackOnFailure") boolean rollbackOnFailure, @JsonProperty("instanceId") String instanceId, - @JsonProperty("vfModules") Map> vfModules) { + @JsonProperty("vfModules") Map> vfModules, + @JsonProperty("trackById") String trackById, + @JsonProperty("isFailed") Boolean isFailed, + @JsonProperty("statusMessage") String statusMessage) { - super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId); + super(modelInfo, instanceName, action, lcpCloudRegionId, legacyRegion, tenantId, instanceParams, rollbackOnFailure, instanceId, trackById, isFailed, statusMessage); this.productFamilyId = productFamilyId; this.platformName = platformName; this.lineOfBusiness = lineOfBusiness; - this.vfModules = vfModules; + this.vfModules = vfModules==null ? Collections.emptyMap() : vfModules; } public String getProductFamilyId() { @@ -82,4 +87,17 @@ public class Vnf extends BaseResource implements JobAdapter.AsyncJobRequest { protected String getModelType() { return "vnf"; } + + @Override + public Collection getChildren() { + return getVfModules().values().stream() + .filter(Objects::nonNull) + .flatMap(x->x.values().stream()) + .collect(toList()); + } + + @Override + public JobType getJobType() { + return JobType.VnfInstantiation; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VrfEntry.kt b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VrfEntry.kt new file mode 100644 index 000000000..5c9ac9095 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/model/serviceInstantiation/VrfEntry.kt @@ -0,0 +1,6 @@ +package org.onap.vid.model.serviceInstantiation + +import org.onap.vid.model.aaiTree.Network +import org.onap.vid.model.aaiTree.VpnBinding + +data class VrfEntry(val networks: Map, val vpns: Map) diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogic.java b/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogic.java index cc3231582..949fdab70 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogic.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogic.java @@ -21,10 +21,11 @@ package org.onap.vid.mso; +import java.util.List; +import java.util.UUID; import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.changeManagement.WorkflowRequestDetail; import org.onap.vid.controller.OperationalEnvironmentController; -import org.onap.vid.services.ProbeInterface; import org.onap.vid.model.SOWorkflowList; import org.onap.vid.model.SoftDeleteRequest; import org.onap.vid.mso.model.OperationalEnvironmentActivateInfo; @@ -33,9 +34,7 @@ import org.onap.vid.mso.rest.OperationalEnvironment.OperationEnvironmentRequestD import org.onap.vid.mso.rest.Request; import org.onap.vid.mso.rest.RequestDetails; import org.onap.vid.mso.rest.Task; - -import java.util.List; -import java.util.UUID; +import org.onap.vid.services.ProbeInterface; public interface MsoBusinessLogic extends ProbeInterface { @@ -137,9 +136,5 @@ public interface MsoBusinessLogic extends ProbeInterface { RequestDetails buildRequestDetailsForSoftDelete(SoftDeleteRequest softDeleteRequest); - MsoResponseWrapper2 deactivateAndCloudDelete(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId, RequestDetails requestDetails); - - MsoResponseWrapper2 activateFabricConfiguration(String serviceInstanceId, RequestDetails requestDetails); - SOWorkflowList getWorkflowListByModelId(String modelVersionId); } diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogicImpl.java b/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogicImpl.java index 4cb495e2f..9146e8f1b 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogicImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/MsoBusinessLogicImpl.java @@ -20,6 +20,24 @@ */ package org.onap.vid.mso; +import static com.fasterxml.jackson.module.kotlin.ExtensionsKt.jacksonObjectMapper; +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.toList; +import static org.apache.commons.lang.StringUtils.upperCase; +import static org.onap.vid.changeManagement.ChangeManagementRequest.MsoChangeManagementRequest; +import static org.onap.vid.controller.MsoController.CONFIGURATION_ID; +import static org.onap.vid.controller.MsoController.REQUEST_TYPE; +import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; +import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; +import static org.onap.vid.controller.MsoController.WORKFLOW_ID; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_CLOUD_RESOURCES_REQUEST_STATUS; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_ACTIVATE; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_CREATE; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_DEACTIVATE; +import static org.onap.vid.mso.MsoProperties.MSO_REST_API_WORKFLOW_SPECIFICATIONS; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; +import static org.onap.vid.utils.Logging.debugRequestDetails; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -27,6 +45,18 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.joshworks.restclient.http.HttpResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.ws.rs.BadRequestException; import org.apache.commons.collections4.ListUtils; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.util.SystemProperties; @@ -35,7 +65,6 @@ import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.changeManagement.WorkflowRequestDetail; import org.onap.vid.controller.OperationalEnvironmentController; import org.onap.vid.exceptions.GenericUncheckedException; -import org.onap.vid.model.RequestReferencesContainer; import org.onap.vid.model.SOWorkflowList; import org.onap.vid.model.SoftDeleteRequest; import org.onap.vid.model.probes.ExternalComponentStatus; @@ -58,37 +87,6 @@ import org.onap.vid.mso.rest.TaskList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; -import org.togglz.core.manager.FeatureManager; - -import javax.ws.rs.BadRequestException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.toList; -import static org.apache.commons.lang.StringUtils.upperCase; -import static org.onap.vid.changeManagement.ChangeManagementRequest.MsoChangeManagementRequest; -import static org.onap.vid.controller.MsoController.CONFIGURATION_ID; -import static org.onap.vid.controller.MsoController.REQUEST_TYPE; -import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; -import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; -import static org.onap.vid.controller.MsoController.WORKFLOW_ID; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_CLOUD_RESOURCES_REQUEST_STATUS; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_ACTIVATE; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_CREATE; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_OPERATIONAL_ENVIRONMENT_DEACTIVATE; -import static org.onap.vid.mso.MsoProperties.MSO_REST_API_WORKFLOW_SPECIFICATIONS; -import static org.onap.vid.properties.Features.FLAG_UNASSIGN_SERVICE; -import static org.onap.vid.utils.Logging.debugRequestDetails; public class MsoBusinessLogicImpl implements MsoBusinessLogic { @@ -120,12 +118,10 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { * This should be replaced with mso client factory. */ private final MsoInterface msoClientInterface; - FeatureManager featureManager; @Autowired - public MsoBusinessLogicImpl(MsoInterface msoClientInterface, FeatureManager featureManager) { + public MsoBusinessLogicImpl(MsoInterface msoClientInterface) { this.msoClientInterface = msoClientInterface; - this.featureManager = featureManager; } public static String validateEndpointPath(String endpointEnvVariable) { @@ -168,17 +164,19 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { public MsoResponseWrapper createNwInstance(RequestDetails requestDetails, String serviceInstanceId) { logInvocationInDebug("createNwInstance"); - String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); + String endpoint; + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); - String nw_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - return msoClientInterface.createNwInstance(requestDetails, nw_endpoint); + String nwEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + return msoClientInterface.createNwInstance(requestDetails, nwEndpoint); } @Override public MsoResponseWrapper createVolumeGroupInstance(RequestDetails requestDetails, String serviceInstanceId, String vnfInstanceId) { logInvocationInDebug("createVolumeGroupInstance"); - String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); + String endpoint; + endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); String vnfEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); vnfEndpoint = vnfEndpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); @@ -192,10 +190,10 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); - String partial_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - String vf_module_endpoint = partial_endpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + String partialEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String vfModuleEndpoint = partialEndpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - return msoClientInterface.createVfModuleInstance(requestDetails, vf_module_endpoint); + return msoClientInterface.createVfModuleInstance(requestDetails, vfModuleEndpoint); } @Override @@ -259,19 +257,15 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { logInvocationInDebug("deleteSvcInstance"); String endpoint; - if (featureManager.isActive(FLAG_UNASSIGN_SERVICE)) { - endpoint = validateEndpointPath(MsoProperties.MSO_DELETE_OR_UNASSIGN_REST_API_SVC_INSTANCE); - if (shouldUnassignService(serviceStatus)) { - logger.debug(EELFLoggerDelegate.debugLogger, "unassign service"); - String svc_endpoint = endpoint + "/" + serviceInstanceId + "/unassign"; - return msoClientInterface.unassignSvcInstance(requestDetails, svc_endpoint); - } - } else { - endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_SVC_INSTANCE); + endpoint = validateEndpointPath(MsoProperties.MSO_DELETE_OR_UNASSIGN_REST_API_SVC_INSTANCE); + if (shouldUnassignService(serviceStatus)){ + logger.debug(EELFLoggerDelegate.debugLogger, "unassign service"); + String svcEndpoint = endpoint + "/" + serviceInstanceId + "/unassign"; + return msoClientInterface.unassignSvcInstance(requestDetails, svcEndpoint); } - String svc_endpoint = endpoint + "/" + serviceInstanceId; - return msoClientInterface.deleteSvcInstance(requestDetails, svc_endpoint); + String svcEndpoint = endpoint + "/" + serviceInstanceId; + return msoClientInterface.deleteSvcInstance(requestDetails, svcEndpoint); } private boolean shouldUnassignService(String serviceStatus) { @@ -294,10 +288,10 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { logInvocationInDebug("deleteVfModule"); String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE); - String vf__modules_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId).replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - String delete_vf_endpoint = vf__modules_endpoint + '/' + vfModuleId; + String vfModulesEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId).replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + String deleteVfEndpoint = vfModulesEndpoint + '/' + vfModuleId; - return msoClientInterface.deleteVfModule(requestDetails, delete_vf_endpoint); + return msoClientInterface.deleteVfModule(requestDetails, deleteVfEndpoint); } @Override @@ -305,11 +299,11 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { logInvocationInDebug("deleteVolumeGroupInstance"); String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE); - String svc_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - String vnfEndpoint = svc_endpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); - String delete_volume_group_endpoint = vnfEndpoint + "/" + volumeGroupId; + String svcEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String vnfEndpoint = svcEndpoint.replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + String deleteVolumeGroupEndpoint = vnfEndpoint + "/" + volumeGroupId; - return msoClientInterface.deleteVolumeGroupInstance(requestDetails, delete_volume_group_endpoint); + return msoClientInterface.deleteVolumeGroupInstance(requestDetails, deleteVolumeGroupEndpoint); } @Override @@ -317,10 +311,10 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { logInvocationInDebug("deleteNwInstance"); String endpoint = validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE); - String svc_endpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); - String delete_nw_endpoint = svc_endpoint + "/" + networkInstanceId; + String svcEndpoint = endpoint.replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); + String deleteNwEndpoint = svcEndpoint + "/" + networkInstanceId; - return msoClientInterface.deleteNwInstance(requestDetails, delete_nw_endpoint); + return msoClientInterface.deleteNwInstance(requestDetails, deleteNwEndpoint); } @Override @@ -400,7 +394,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { private List deserializeOrchestrationRequestsJson(String orchestrationRequestsJson) { logInvocationInDebug("deserializeOrchestrationRequestsJson"); - ObjectMapper mapper = new ObjectMapper(); + ObjectMapper mapper = jacksonObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true); RequestList requestList; @@ -423,7 +417,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { String path = p + "?originalRequestId=" + originalRequestId; RestObject restObjStr = new RestObject<>(); - String str = new String(); + String str = ""; restObjStr.set(str); MsoResponseWrapper msoResponseWrapper = msoClientInterface.getManualTasksByRequestId(str, "", path, restObjStr); @@ -438,9 +432,8 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { private List deserializeManualTasksJson(String manualTasksJson) { logInvocationInDebug("deserializeManualTasksJson"); - ObjectMapper mapper = new ObjectMapper(); try { - TaskList taskList = mapper.readValue(manualTasksJson, TaskList.class); + TaskList taskList = JACKSON_OBJECT_MAPPER.readValue(manualTasksJson, TaskList.class); return taskList.getTaskList(); } catch (IOException e) { throw new GenericUncheckedException(e); @@ -457,7 +450,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { String path = p + "/" + taskId + "/complete"; RestObject restObjStr = new RestObject<>(); - String str = new String(); + String str = ""; restObjStr.set(str); return msoClientInterface.completeManualTask(requestDetails, str, "", path, restObjStr); @@ -561,9 +554,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { requestInfo.setRequestorId(softDeleteRequest.getUserId()); requestDetails.setRequestInfo(requestInfo); - CloudConfiguration cloudConfiguration = new CloudConfiguration(); - cloudConfiguration.setTenantId(softDeleteRequest.getTenantId()); - cloudConfiguration.setLcpCloudRegionId(softDeleteRequest.getLcpCloudRegionId()); + CloudConfiguration cloudConfiguration = new CloudConfiguration(softDeleteRequest.getLcpCloudRegionId(), softDeleteRequest.getTenantId(), null); requestDetails.setCloudConfiguration(cloudConfiguration); ModelInfo modelInfo = new ModelInfo(); @@ -577,18 +568,6 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { return requestDetails; } - @Override - public MsoResponseWrapper2 deactivateAndCloudDelete(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId, RequestDetails requestDetails) { - String path = getDeactivateAndCloudDeletePath(serviceInstanceId, vnfInstanceId, vfModuleInstanceId); - return new MsoResponseWrapper2<>(msoClientInterface.post(path, requestDetails, RequestReferencesContainer.class)); - } - - @Override - public MsoResponseWrapper2 activateFabricConfiguration(String serviceInstanceId, RequestDetails requestDetails) { - String path = getActivateFabricConfigurationPath(serviceInstanceId); - return new MsoResponseWrapper2<>(msoClientInterface.post(path, requestDetails, RequestReferencesContainer.class)); - } - @Override public SOWorkflowList getWorkflowListByModelId(String modelVersionId) { logInvocationInDebug("getWorkflowListByModelId"); @@ -634,7 +613,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { } Object payloadRaw = requestDetails.getRequestParameters().getAdditionalProperties().get("payload"); try { - return objectMapper.readValue((String) payloadRaw, Map.class); + return JACKSON_OBJECT_MAPPER.readValue((String) payloadRaw, Map.class); } catch (Exception exception) { throw new BadRequestException(message); } @@ -912,7 +891,7 @@ public class MsoBusinessLogicImpl implements MsoBusinessLogic { } } - enum RequestType { + public enum RequestType { CREATE_INSTANCE("createInstance"), DELETE_INSTANCE("deleteInstance"), diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java b/vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java index 562182a3c..fcc20fafd 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/MsoUtil.java @@ -21,15 +21,20 @@ package org.onap.vid.mso; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.joshworks.restclient.http.HttpResponse; +import java.io.IOException; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; - +import org.onap.vid.exceptions.GenericUncheckedException; public class MsoUtil { - final static ObjectMapper objectMapper = new ObjectMapper(); + static final ObjectMapper objectMapper = new ObjectMapper(); private MsoUtil() { } @@ -48,12 +53,30 @@ public class MsoUtil { T body = httpResponse.getBody(); String entityStr = body instanceof String ? (String) body : objectMapper.writeValueAsString(httpResponse.getBody()); msoResponseWrapper.setEntity(entityStr); - } - catch(JsonProcessingException e) - { + } catch(JsonProcessingException e) { ExceptionUtils.rethrow(e); } } return msoResponseWrapper; } + + public static String formatExceptionAdditionalInfo(int statusCode, String msoResponse) { + String errorMsg = "Http Code:" + statusCode; + if (!StringUtils.isEmpty(msoResponse)) { + String filteredJson; + try { + filteredJson = StringUtils.defaultIfEmpty( + JACKSON_OBJECT_MAPPER.readTree(msoResponse).path("serviceException").toString().replaceAll("[\\{\\}]","") , + msoResponse + ); + } catch (JsonParseException e) { + filteredJson = msoResponse; + } catch (IOException e) { + throw new GenericUncheckedException(e); + } + + errorMsg = errorMsg + ", " + filteredJson; + } + return errorMsg; + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/AddOrRemoveInstanceGroupMemberRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/AddOrRemoveInstanceGroupMemberRequestDetails.java new file mode 100644 index 000000000..f6b8a4241 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/AddOrRemoveInstanceGroupMemberRequestDetails.java @@ -0,0 +1,51 @@ +/*- + * ============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.mso.model; + +import java.util.List; + +/* +Based on this model: +{ + "requestDetails": { + "requestInfo": { + "source": "VID", + "requestorId": "az2016" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "{the to be removed/added as member vnf-id}", + "modelInfo": { + "modelType": "vnf" + } + } + } + ] + } +} +*/ + +public class AddOrRemoveInstanceGroupMemberRequestDetails extends BaseResourceInstantiationRequestDetails { + public AddOrRemoveInstanceGroupMemberRequestDetails(RequestInfo requestInfo, List relatedInstanceList) { + super(null, null, requestInfo, null, null, relatedInstanceList, null); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/BaseResourceInstantiationRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/BaseResourceInstantiationRequestDetails.java index c6eb53832..43f5b0070 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/BaseResourceInstantiationRequestDetails.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/BaseResourceInstantiationRequestDetails.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,15 +20,15 @@ package org.onap.vid.mso.model; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; - import java.util.List; -import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; - @JsonInclude(NON_NULL) public class BaseResourceInstantiationRequestDetails { @@ -83,21 +83,21 @@ public class BaseResourceInstantiationRequestDetails { this.requestParameters = requestParameters; } - public static class RequestInfo { + public static class RequestInfo { - @JsonInclude(NON_NULL) public final String instanceName; - @JsonInclude(NON_NULL) public final String productFamilyId; + @JsonInclude(NON_EMPTY) public final String instanceName; + @JsonInclude(NON_EMPTY) public final String productFamilyId; public final String source; - public final boolean suppressRollback; + @JsonInclude(NON_NULL) public final Boolean suppressRollback; public final String requestorId; - public RequestInfo(String instanceName, String productFamilyId, String source, boolean rollbackOnFailure, String requestorId) { + public RequestInfo(String instanceName, String productFamilyId, String source, Boolean rollbackOnFailure, String requestorId) { this.instanceName = instanceName; this.productFamilyId = productFamilyId; this.source = source; this.requestorId = requestorId; // in the FE we are asking for "RollbackOnFailure" but to MSO we are passing the negative value "suppressRollback" - this.suppressRollback = !rollbackOnFailure; + this.suppressRollback = rollbackOnFailure != null ? (!rollbackOnFailure) : null; } } @@ -120,9 +120,13 @@ public class BaseResourceInstantiationRequestDetails { public static class LineOfBusiness{ public final String lineOfBusinessName; - public LineOfBusiness(String lineOfBusiness) { + private LineOfBusiness(String lineOfBusiness) { this.lineOfBusinessName = lineOfBusiness; } + + public static LineOfBusiness of(String lineOfBusiness) { + return lineOfBusiness==null ? null : new LineOfBusiness(lineOfBusiness); + } } @JsonTypeName("relatedInstance") @@ -150,13 +154,18 @@ public class BaseResourceInstantiationRequestDetails { public static class RequestParameters { public final List userParams; - public RequestParameters(List userParams) { + @JsonInclude(NON_NULL) public final String testApi; + public RequestParameters(List userParams, String testApi) { this.userParams = userParams; + this.testApi = testApi; } public List getUserParams() { return userParams; } + public String getTestApi() { + return testApi; + } } } diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.java deleted file mode 100644 index 2e0991755..000000000 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.java +++ /dev/null @@ -1,192 +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.mso.model; - -import com.fasterxml.jackson.annotation.*; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; - -import java.util.HashMap; -import java.util.Map; - - -/** - * fields communicating the cloud configuration in a standard way - * - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonPropertyOrder({ - "nodeLocation", - "lcpCloudRegionId", - "tenantId", - "cloudOwner" -}) -public class CloudConfiguration { - - /** - * Location identifier for the node - * - */ - @JsonProperty("nodeLocation") - private String nodeLocation; - /** - * LCP Node Location identifier - * - */ - @JsonProperty("lcpCloudRegionId") - private String lcpCloudRegionId; - /** - * Openstack tenant id - * - */ - @JsonProperty("tenantId") - private String tenantId; - /** - * the cloud owner - * - */ - @JsonProperty("cloudOwner") - private String cloudOwner; - @JsonIgnore - private Map additionalProperties = new HashMap<>(); - - /** - * Location identifier for the node - * - * @return - * The nodeLocation - */ - @JsonProperty("nodeLocation") - public String getNodeLocation() { - return nodeLocation; - } - - /** - * Location identifier for the node - * - * @param nodeLocation - * The nodeLocation - */ - @JsonProperty("nodeLocation") - public void setNodeLocation(String nodeLocation) { - this.nodeLocation = nodeLocation; - } - - /** - * LCP Node Location identifier - * - * @return - * The lcpCloudRegionId - */ - @JsonProperty("lcpCloudRegionId") - public String getLcpCloudRegionId() { - return lcpCloudRegionId; - } - - /** - * LCP Node Location identifier - * - * @param lcpCloudRegionId - * The lcpCloudRegionId - */ - @JsonProperty("lcpCloudRegionId") - public void setLcpCloudRegionId(String lcpCloudRegionId) { - this.lcpCloudRegionId = lcpCloudRegionId; - } - - /** - * Openstack tenant id - * - * @return - * The tenantId - */ - @JsonProperty("tenantId") - public String getTenantId() { - return tenantId; - } - - /** - * Openstack tenant id - * - * @param tenantId - * The tenantId - */ - @JsonProperty("tenantId") - public void setTenantId(String tenantId) { - this.tenantId = tenantId; - } - - /** - * the cloud owner - * - * @return - * The cloudOwner - */ - @JsonProperty("cloudOwner") - public String getCloudOwner() { - return cloudOwner; - } - - /** - * the cloud owner - * - * @param cloudOwner - * The cloudOwner - */ - @JsonProperty("cloudOwner") - public void setCloudOwner(String cloudOwner) { - this.cloudOwner = cloudOwner; - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } - - @JsonAnyGetter - public Map getAdditionalProperties() { - return this.additionalProperties; - } - - @JsonAnySetter - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - - @Override - public int hashCode() { - return new HashCodeBuilder().append(nodeLocation).append(lcpCloudRegionId).append(tenantId).append(cloudOwner).append(additionalProperties).toHashCode(); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if (!(other instanceof CloudConfiguration)) { - return false; - } - CloudConfiguration rhs = ((CloudConfiguration) other); - return new EqualsBuilder().append(nodeLocation, rhs.nodeLocation).append(lcpCloudRegionId, rhs.lcpCloudRegionId).append(tenantId, rhs.tenantId).append(cloudOwner, rhs.cloudOwner).append(additionalProperties, rhs.additionalProperties).isEquals(); - } - -} diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.kt b/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.kt new file mode 100644 index 000000000..d603e5b87 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/CloudConfiguration.kt @@ -0,0 +1,12 @@ +package org.onap.vid.mso.model + +import com.fasterxml.jackson.annotation.JsonInclude + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +//tenantId and might be null for supporting create configuration API (port mirroring) +//cloudOwner might because MSO enable it and it might be used in some flows (default value in MSO "irma-aic") +data class CloudConfiguration @JvmOverloads constructor( + var lcpCloudRegionId: String? = null, + var tenantId:String? = null, + var cloudOwner: String? = null +) \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationPre1806RequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationPre1806RequestDetails.java new file mode 100644 index 000000000..effc10a08 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationPre1806RequestDetails.java @@ -0,0 +1,51 @@ +/*- + * ============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.mso.model; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; +import static org.onap.vid.mso.model.BaseResourceInstantiationRequestDetails.RelatedInstance; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.onap.vid.mso.rest.SubscriberInfo; + +public class ServiceInstantiationPre1806RequestDetails extends ServiceInstantiationRequestDetails { + + @JsonInclude(NON_NULL) + public final CloudConfiguration cloudConfiguration; + @JsonInclude(NON_EMPTY) + public final List relatedInstanceList; + + public ServiceInstantiationPre1806RequestDetails(ModelInfo modelInfo, ServiceInstantiationOwningEntity owningEntity, + SubscriberInfo subscriberInfo, Project project, RequestInfo requestInfo, + RequestParameters requestParameters, CloudConfiguration cloudConfiguration, + List relatedInstanceList) { + super(modelInfo, owningEntity, subscriberInfo, project, requestInfo, requestParameters); + if ((cloudConfiguration != null) && (!StringUtils.isEmpty(cloudConfiguration.getLcpCloudRegionId())) && (!StringUtils.isEmpty(cloudConfiguration.getTenantId()))){ + this.cloudConfiguration = cloudConfiguration; + } else { + this.cloudConfiguration = null; + } + this.relatedInstanceList = relatedInstanceList; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java index 700f43857..8f8dd681a 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/ServiceInstantiationRequestDetails.java @@ -76,8 +76,8 @@ public class ServiceInstantiationRequestDetails { public static class RequestInfo { - @JsonInclude(NON_NULL) public final String instanceName; - @JsonInclude(NON_NULL) public final String productFamilyId; + @JsonInclude(NON_EMPTY) public final String instanceName; + @JsonInclude(NON_EMPTY) public final String productFamilyId; public final String source; public final boolean suppressRollback; public final String requestorId; @@ -150,7 +150,7 @@ public class ServiceInstantiationRequestDetails { private static class ServiceInstantiationServiceInner implements UserParamTypes { public ModelInfo modelInfo = new ModelInfo(); - @JsonInclude(NON_NULL) + @JsonInclude(NON_EMPTY) public String instanceName; public List> instanceParams; public ServiceInstantiationVnfList resources; @@ -182,7 +182,7 @@ public class ServiceInstantiationRequestDetails { public final String productFamilyId; public final List> instanceParams; @JsonInclude(NON_EMPTY) public final List vfModules; - @JsonInclude(NON_NULL) public final String instanceName; + @JsonInclude(NON_EMPTY) public final String instanceName; public ServiceInstantiationVnf(ModelInfo modelInfo, CloudConfiguration cloudConfiguration, String platform, String lineOfBusiness, String productFamilyId, List> instanceParams, List vfModules, String instanceName) { this.modelInfo = modelInfo; diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java b/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java index 4e6f074c2..3b6cd1d3d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/model/VfModuleInstantiationRequestDetails.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,8 +20,10 @@ package org.onap.vid.mso.model; -import com.fasterxml.jackson.annotation.JsonProperty; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -109,14 +111,14 @@ public class VfModuleInstantiationRequestDetails extends BaseResourceInstantiati } public static class RequestParametersVfModule extends BaseResourceInstantiationRequestDetails.RequestParameters { - private final boolean usePreload; + @JsonInclude(NON_NULL) private final Boolean usePreload; - public RequestParametersVfModule(List userParams, boolean usePreload) { - super(userParams); + public RequestParametersVfModule(List userParams, Boolean usePreload, String testApi) { + super(userParams, testApi); this.usePreload = usePreload; } - public boolean isUsePreload() { + public Boolean isUsePreload() { return usePreload; } } diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/rest/AsyncRequestStatus.java b/vid-app-common/src/main/java/org/onap/vid/mso/rest/AsyncRequestStatus.java index 12bf20549..61e0d3af6 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/rest/AsyncRequestStatus.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/rest/AsyncRequestStatus.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. @@ -53,6 +53,7 @@ public class AsyncRequestStatus { public String requestId; public String requestScope; + public String requestType; /** * The instance ids. diff --git a/vid-app-common/src/main/java/org/onap/vid/mso/rest/RequestStatus.java b/vid-app-common/src/main/java/org/onap/vid/mso/rest/RequestStatus.java index 031eaec23..29356aa4d 100644 --- a/vid-app-common/src/main/java/org/onap/vid/mso/rest/RequestStatus.java +++ b/vid-app-common/src/main/java/org/onap/vid/mso/rest/RequestStatus.java @@ -43,6 +43,14 @@ import java.util.Map; }) public class RequestStatus { + public RequestStatus() {} + + public RequestStatus(String requestState, String statusMessage, String timestamp) { + this.requestState = requestState; + this.statusMessage = statusMessage; + this.timestamp = timestamp; + } + /** * percentage complete estimate from 0 to 100 * 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 ea047d698..c96efe6f5 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 @@ -29,22 +29,17 @@ public enum Features implements Feature { * Use /docs/feature-flags.md for details */ - FLAG_ASYNC_JOBS, CREATE_INSTANCE_TEST, EMPTY_DRAWING_BOARD_TEST, FLAG_ADD_MSO_TESTAPI_FIELD, - FLAG_ASYNC_INSTANTIATION, FLAG_SERVICE_MODEL_CACHE, - FLAG_UNASSIGN_SERVICE, FLAG_NETWORK_TO_ASYNC_INSTANTIATION, - FLAG_COLLECTION_RESOURCE_SUPPORT, FLAG_SHOW_ASSIGNMENTS, + FLAG_UNASSIGN_SERVICE, FLAG_FABRIC_CONFIGURATION_ASSIGNMENTS, FLAG_SHOW_VERIFY_SERVICE, // AKA POMBA - FLAG_DUPLICATE_VNF, FLAG_DEFAULT_VNF, FLAG_SETTING_DEFAULTS_IN_DRAWING_BOARD, - FLAG_PNP_INSTANTIATION, FLAG_RESTRICTED_SELECT, FLAG_5G_IN_NEW_INSTANTIATION_UI, FLAG_ASYNC_ALACARTE_VNF, @@ -52,7 +47,6 @@ public enum Features implements Feature { FLAG_PRESENT_PROVIDER_NETWORKS_ASSOCIATIONS, FLAG_ASYNC_ALACARTE_VFMODULE, FLAG_SUPPLEMENTARY_FILE, - FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF, FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI, FLAG_1810_CR_LET_SELECTING_COLLECTOR_TYPE_UNCONDITIONALLY, FLAG_1810_CR_ADD_CLOUD_OWNER_TO_MSO_REQUEST, @@ -62,10 +56,25 @@ public enum Features implements Feature { FLAG_1902_NEW_VIEW_EDIT, FLAG_EXP_USE_DEFAULT_HOST_NAME_VERIFIER, FLAG_1902_VNF_GROUPING, + FLAG_1902_RETRY_JOB, + FLAG_VF_MODULE_RESUME_STATUS_CREATE, + FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL, + FLAG_1906_COMPONENT_INFO, + FLAG_1906_INSTANTIATION_API_USER_VALIDATION, + FLAG_1906_AAI_SUB_DETAILS_REDUCE_DEPTH, + FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI, + FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI, + FLAG_1908_INFRASTRUCTURE_VPN, + FLAG_1908_RESUME_MACRO_SERVICE, + FLAG_1908_RELEASE_TENANT_ISOLATION, + FLAG_1908_A_LA_CARTE_VNF_NEW_INSTANTIATION_UI, + FLAG_FLASH_REPLACE_VF_MODULE, + FLAG_PNP_INSTANTIATION, FLAG_HANDLE_SO_WORKFLOWS, FLAG_CREATE_ERROR_REPORTS ; + public boolean isActive() { return FeatureContext.getFeatureManager().isActive(this); } diff --git a/vid-app-common/src/main/java/org/onap/vid/properties/VidProperties.java b/vid-app-common/src/main/java/org/onap/vid/properties/VidProperties.java index 24b72fdff..8331886c0 100644 --- a/vid-app-common/src/main/java/org/onap/vid/properties/VidProperties.java +++ b/vid-app-common/src/main/java/org/onap/vid/properties/VidProperties.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,9 +21,9 @@ package org.onap.vid.properties; import org.apache.commons.lang3.StringUtils; +import org.onap.vid.model.ModelConstants; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.portalsdk.core.util.SystemProperties; -import org.onap.vid.model.ModelConstants; /** * The Class VidProperties. */ @@ -38,59 +38,62 @@ public class VidProperties extends SystemProperties { /** The Constant VID_TRUSTSTORE_FILENAME. */ public static final String VID_TRUSTSTORE_FILENAME = "vid.truststore.filename"; - + /** The Constant VID_TRUSTSTORE_PASSWD_X. */ public static final String VID_TRUSTSTORE_PASSWD_X = "vid.truststore.passwd.x"; - + /** The Constant FILESEPARATOR. */ public static final String FILESEPARATOR = (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); - + /** The Constant LOG. */ private static final EELFLoggerDelegate LOG = EELFLoggerDelegate.getLogger(VidProperties.class); - public static final String VID_JOB_MAX_HOURS_IN_PROGRESS = "vid.asyncJob.maxHoursInProgress"; + public static final String VID_JOB_MAX_HOURS_IN_PROGRESS = "vid.asyncJob.maxHoursInProgress"; + + public static final String VID_THREAD_COUNT = "vid.thread.count"; + public static final String VID_THREAD_TIMEOUT = "vid.thread.timeout"; /** * Gets the asdc model namespace prefix property - * + * * @return the property value or a default value */ public static String getAsdcModelNamespace() { String methodName = "getAsdcModelNamespace "; String asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; - try { - asdcModelNamespace = SystemProperties.getProperty(ModelConstants.ASDC_MODEL_NAMESPACE); - if ( asdcModelNamespace == null || asdcModelNamespace.isEmpty()) { - asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; - } - } - catch ( Exception e ) { - LOG.error (EELFLoggerDelegate.errorLogger, methodName + "unable to find the value, using the default " - + ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE); - asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; - } - return (asdcModelNamespace); + try { + asdcModelNamespace = SystemProperties.getProperty(ModelConstants.ASDC_MODEL_NAMESPACE); + if ( asdcModelNamespace == null || asdcModelNamespace.isEmpty()) { + asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; + } + } + catch ( Exception e ) { + LOG.error (EELFLoggerDelegate.errorLogger, methodName + "unable to find the value, using the default " + + ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE); + asdcModelNamespace = ModelConstants.DEFAULT_ASDC_MODEL_NAMESPACE; + } + return (asdcModelNamespace); } /** * Gets the specified property value. If the property is not defined, returns a default value. - * + * * @return the property value or a default value */ public static String getPropertyWithDefault ( String propName, String defaultValue ) { String methodName = "getPropertyWithDefault "; String propValue = defaultValue; - try { - propValue = SystemProperties.getProperty(propName); - if ( propValue == null || propValue.isEmpty()) { - propValue = defaultValue; - } - } - catch ( Exception e ) { - LOG.error (EELFLoggerDelegate.errorLogger, methodName + "unable to find the value, using the default " - + defaultValue); - propValue = defaultValue; - } - return (propValue); + try { + propValue = SystemProperties.getProperty(propName); + if ( propValue == null || propValue.isEmpty()) { + propValue = defaultValue; + } + } + catch ( Exception e ) { + LOG.error (EELFLoggerDelegate.errorLogger, methodName + "unable to find the value, using the default " + + defaultValue); + propValue = defaultValue; + } + return (propValue); } public static long getLongProperty(String key) { @@ -98,16 +101,16 @@ public class VidProperties extends SystemProperties { } public static long getLongProperty(String key, long defaultValue) { - if (!containsProperty(key)) { - LOG.debug(EELFLoggerDelegate.debugLogger, "No such property: {}. {} value is used", key, defaultValue); - return defaultValue; - } - String configValue = getProperty(key); - if (StringUtils.isNumeric(configValue)) { - return Long.parseLong(configValue); - } else { - LOG.debug(EELFLoggerDelegate.debugLogger, "{} property value is not valid: {}. {} value is used", key, configValue, defaultValue); - return defaultValue; - } - } + if (!containsProperty(key)) { + LOG.debug(EELFLoggerDelegate.debugLogger, "No such property: {}. {} value is used", key, defaultValue); + return defaultValue; + } + String configValue = getProperty(key); + if (StringUtils.isNumeric(configValue)) { + return Long.parseLong(configValue); + } else { + LOG.debug(EELFLoggerDelegate.debugLogger, "{} property value is not valid: {}. {} value is used", key, configValue, defaultValue); + return defaultValue; + } + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java index 6199c4e58..d62d5d5d4 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAIServiceTree.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,7 +21,6 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.AaiClientInterface; @@ -31,21 +30,24 @@ import org.onap.vid.asdc.parser.ServiceModelInflator; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceModel; import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.model.aaiTree.ServiceInstance; import org.onap.vid.utils.Tree; +import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import javax.inject.Inject; import javax.ws.rs.core.Response; import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import static java.lang.Thread.sleep; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toSet; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; -import static org.onap.vid.services.AAITreeNodeBuilder.*; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; @Component public class AAIServiceTree { @@ -60,38 +62,58 @@ public class AAIServiceTree { private final ServiceModelInflator serviceModelInflator; - private final ObjectMapper mapper = new ObjectMapper(); + private final ExecutorService executorService; private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAIServiceTree.class); public static final Tree AAI_TREE_PATHS = - new Tree<>(new AaiRelationship(SERVICE_INSTANCE)); + new Tree<>(new AaiRelationship(NodeType.SERVICE_INSTANCE)); static { - AAI_TREE_PATHS.addPath(toAaiRelationshipList(GENERIC_VNF, VG)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(NETWORK)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(GENERIC_VNF, NETWORK)); - AAI_TREE_PATHS.addPath(toAaiRelationshipList(INSTANCE_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.VOLUME_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.VF_MODULE)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.INSTANCE_GROUP, NodeType.GENERIC_VNF)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.COLLECTION_RESOURCE, NodeType.INSTANCE_GROUP)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.CONFIGURATION, NodeType.NETWORK, NodeType.VPN_BINDING)); + AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.CONFIGURATION, NodeType.VPN_BINDING)); + } + + public static List toAaiRelationshipList(NodeType... types) { + return Stream.of(types).map(AAIServiceTree.AaiRelationship::new).collect(Collectors.toList()); } @Inject public AAIServiceTree(AaiClientInterface aaiClient, AAITreeNodeBuilder aaiTreeNodeBuilder, AAITreeConverter aaiTreeConverter, VidService sdcService, - ServiceModelInflator serviceModelInflator) { + ServiceModelInflator serviceModelInflator, ExecutorService executorService) { this.aaiClient = aaiClient; this.aaiTreeNodeBuilder = aaiTreeNodeBuilder; this.aaiTreeConverter = aaiTreeConverter; this.sdcService = sdcService; this.serviceModelInflator = serviceModelInflator; + this.executorService = executorService; + } + + List buildAAITreeForUniqueResource(String getUrl, NodeType nodeType) { + return buildAAITreeForUniqueResourceFromCustomQuery(getUrl, null, HttpMethod.GET, nodeType); + } + + List buildAAITreeForUniqueResourceFromCustomQuery(String url, String payload, HttpMethod method, NodeType nodeType) { + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(nodeType)); + return buildAAITree(url, payload, method, pathsToSearch, false); } - public List buildAAITree(String getUrl, Tree pathsToSearch) { + public List buildAAITree(String url, String payload, HttpMethod method, Tree pathsToSearch, boolean enrichWithModelVersion) { ConcurrentSkipListSet nodesAccumulator = createNodesAccumulator(); - List aaiTreeNodes = fetchAAITree(getUrl, pathsToSearch, nodesAccumulator, true); + List aaiTreeNodes = fetchAAITree(url, payload, method, pathsToSearch, nodesAccumulator); - enrichNodesWithModelVersionAndModelName(nodesAccumulator); + if (enrichWithModelVersion) { + enrichNodesWithModelVersionAndModelName(nodesAccumulator); + } return aaiTreeNodes; } @@ -105,7 +127,7 @@ public class AAIServiceTree { //Used later to get the nodes UUID ConcurrentSkipListSet nodesAccumulator = createNodesAccumulator(); - AAITreeNode aaiTree = fetchAAITree(getURL, AAI_TREE_PATHS, nodesAccumulator, false).get(0); + AAITreeNode aaiTree = fetchAAITree(getURL, null, HttpMethod.GET, AAI_TREE_PATHS, nodesAccumulator).get(0); //Populate nodes with model-name & model-version (from aai) enrichNodesWithModelVersionAndModelName(nodesAccumulator); @@ -115,28 +137,28 @@ public class AAIServiceTree { //Populate nodes with model-customization-name (from sdc model) enrichNodesWithModelCustomizationName(nodesAccumulator, serviceModel); - return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(serviceModel)); + return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(serviceModel), getInstanceRole(serviceModel), getInstanceType(serviceModel)); } - private List fetchAAITree(String getUrl, Tree pathsToSearch, - ConcurrentSkipListSet nodesAccumulator, boolean partialTreeOnTimeout) { - ThreadPoolExecutor threadPool = getThreadPool(); - - List aaiTree = aaiTreeNodeBuilder.buildNode(SERVICE_INSTANCE, - getUrl, defaultIfNull(nodesAccumulator, createNodesAccumulator()), - threadPool, new ConcurrentLinkedQueue<>(), - new AtomicInteger(0), pathsToSearch); - - boolean timeoutOccurred = waitForTreeFetch(threadPool); + private String getInstanceType(ServiceModel serviceModel){ + if (serviceModel != null && serviceModel.getService() != null) { + return serviceModel.getService().getServiceType(); + } + return ""; + } - if (timeoutOccurred) { - if (!partialTreeOnTimeout) { - throw new GenericUncheckedException("Timeout on fetchAAITree. Fetched " + nodesAccumulator.size() + " nodes for url: " + getUrl); - } - LOGGER.warn(EELFLoggerDelegate.errorLogger, "Timeout on fetchAAITree for url: " + getUrl); + private String getInstanceRole(ServiceModel serviceModel) { + if (serviceModel != null && serviceModel.getService() != null) { + return serviceModel.getService().getServiceRole(); } + return ""; + } - return aaiTree; + private List fetchAAITree(String url, String payload, HttpMethod method, Tree pathsToSearch, + ConcurrentSkipListSet nodesAccumulator) { + return aaiTreeNodeBuilder.buildNode(NodeType.fromString(pathsToSearch.getRootValue().type), + url, payload, method, defaultIfNull(nodesAccumulator, createNodesAccumulator()), + executorService, pathsToSearch); } private ConcurrentSkipListSet createNodesAccumulator() { @@ -204,12 +226,12 @@ public class AAIServiceTree { private JsonNode getModels(AaiClientInterface aaiClient, Collection invariantIDs) { Response response = aaiClient.getVersionByInvariantId(ImmutableList.copyOf(invariantIDs)); try { - JsonNode responseJson = mapper.readTree(response.readEntity(String.class)); + JsonNode responseJson = JACKSON_OBJECT_MAPPER.readTree(response.readEntity(String.class)); return responseJson.get("model"); } catch (Exception e) { LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to getVersionByInvariantId from A&AI", e); } - return mapper.createObjectNode(); + return JACKSON_OBJECT_MAPPER.createObjectNode(); } private Set getModelInvariantIds(Collection nodes) { @@ -219,30 +241,6 @@ public class AAIServiceTree { .collect(toSet()); } - private boolean waitForTreeFetch(ThreadPoolExecutor threadPool) { - int timer = 60; - try { - //Stop fetching information if it takes more than 1 minute - while (threadPool.getActiveCount() != 0 && - timer > 0) { - sleep(1000); - timer--; - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new GenericUncheckedException(e); - } - threadPool.shutdown(); - return (timer == 0); - } - - private ThreadPoolExecutor getThreadPool() { - //Use at least one thread, and never more than 75% of the available thread. - int cores = Math.max((int)(Runtime.getRuntime().availableProcessors() * 0.75), 1); - BlockingQueue queue = new LinkedBlockingQueue<>(); - return new ThreadPoolExecutor(1, cores, 10, TimeUnit.SECONDS, queue); - } - public static class AaiRelationship { public final String type; @@ -251,6 +249,10 @@ public class AAIServiceTree { this.type = type; } + public AaiRelationship(NodeType nodeType) { + this.type = nodeType.getType(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java index e06088264..d53eba8d3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AAITreeNodeBuilder.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,66 +21,49 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.portalsdk.core.util.SystemProperties; import org.onap.vid.aai.AaiClientInterface; import org.onap.vid.aai.ExceptionWithRequestInfo; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship; +import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipData; import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelationshipList; +import org.onap.vid.aai.util.AAITreeNodeUtils; +import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.aaiTree.AAITreeNode; import org.onap.vid.model.aaiTree.FailureAAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; +import org.onap.vid.mso.model.CloudConfiguration; +import org.onap.vid.properties.VidProperties; import org.onap.vid.utils.Streams; import org.onap.vid.utils.Tree; import org.onap.vid.utils.Unchecked; +import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import javax.inject.Inject; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.*; +import java.util.concurrent.*; import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.stream.Collectors.*; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; import static org.onap.vid.utils.Streams.not; @Component public class AAITreeNodeBuilder { + private static final String RESULTS = "results"; private AaiClientInterface aaiClient; - private final ObjectMapper mapper = new ObjectMapper(); - private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAITreeNodeBuilder.class); - //List of all the node types the tree should include - public static final String SERVICE_INSTANCE = "service-instance"; - public static final String GENERIC_VNF = "generic-vnf"; - public static final String NETWORK = "l3-network"; - public static final String FAILURE = "failure_node"; - public static final String COLLECTION_RESOURCE = "collection"; - public static final String CONFIGURATION = "configuration"; - public static final String PNF = "pnf"; - public static final String VF_MODULE = "vf-module"; - public static final String INSTANCE_GROUP = "instance-group"; - public static final String PORT = "l-interface"; - public static final String VG = "volume-group"; - public static final String VLAN_TAG = "vlan-tag"; - - //Hashmap that defines the node-type and the tag that should be used to find it's ID key in the JSON. - private static HashMap nodeTypeToIdKeyMap = generateTypeToIdKeyMap(); - - //Hashmap that defines the node-type and the tag that should be used to find it's NAMR key in the JSON. - private static HashMap nodeTypeToNameKeyMap = generateTypeToNameKeyMap(); public enum AAIBaseProperties { ORCHESTRATION_STATUS("orchestration-status"), @@ -102,63 +85,121 @@ public class AAITreeNodeBuilder { } } - public static List toAaiRelationshipList(String... types) { - return Stream.of(types).map(AAIServiceTree.AaiRelationship::new).collect(Collectors.toList()); - } - @Inject public AAITreeNodeBuilder(AaiClientInterface aaiClient) { this.aaiClient = aaiClient; } - public List buildNode(String nodeType, - String requestURL, - ConcurrentSkipListSet nodesAccumulator, ExecutorService threadPool, - ConcurrentLinkedQueue visitedNodes, - AtomicInteger nodesCounter, - Tree pathsTree) { + List buildNode(NodeType nodeType, + String requestURL, + String payload, + HttpMethod method, + ConcurrentSkipListSet nodesAccumulator, + ExecutorService threadPool, + Tree pathsTree) { - JsonNode topLevelJson = aaiClient.typedAaiGet(Unchecked.toURI(requestURL), JsonNode.class); + JsonNode jsonNode = aaiClient.typedAaiRest(Unchecked.toURI(requestURL), JsonNode.class, payload, method, false); - if (topLevelJson.has(nodeType) && topLevelJson.get(nodeType).isArray()) { - return Streams.fromIterable(topLevelJson.get(nodeType)) - .map(item -> parseNodeAndGetChildren(nodeType, requestURL, item, - nodesAccumulator, threadPool, visitedNodes, nodesCounter, pathsTree)) - .collect(toList()); - } else { - return ImmutableList.of(parseNodeAndGetChildren(nodeType, requestURL, topLevelJson, - nodesAccumulator, threadPool, visitedNodes, nodesCounter, pathsTree)); + List>> nodes = getNodesWithRelationships(jsonNode, nodeType, nodesAccumulator, pathsTree); + + String timeout = SystemProperties.getProperty(VidProperties.VID_THREAD_TIMEOUT); + long timeoutNum = Long.parseLong(StringUtils.defaultIfEmpty(timeout, "30")); + + for (Pair> entry : nodes) { + fetchChildrenAsync(threadPool, nodesAccumulator, entry.getKey(), entry.getValue(), pathsTree, timeoutNum); + + if (getNextLevelInPathsTree(pathsTree, NodeType.VF_MODULE.getType()) != null) { + getRelatedVfModules(threadPool, nodesAccumulator, requestURL, entry.getKey()); + } } + + return nodes.stream() + .map(Pair::getKey) + .collect(Collectors.toList()); } - private AAITreeNode parseNodeAndGetChildren(String nodeType, - String requestURL, - JsonNode topLevelJson, - ConcurrentSkipListSet nodesAccumulator, ExecutorService threadPool, - ConcurrentLinkedQueue visitedNodes, - AtomicInteger nodesCounter, - Tree pathsTree) { - AAITreeNode node = jsonToAaiNode(nodeType, topLevelJson, nodesAccumulator, nodesCounter); - - RelationshipList relationships = mapper.convertValue(topLevelJson.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class); - if (relationships != null) { - getChildren(threadPool, nodesAccumulator, relationships.getRelationship(), visitedNodes, node, nodesCounter, pathsTree); - } - if (StringUtils.equals(node.getType(), GENERIC_VNF)) { - getRelatedVfModules(threadPool, nodesAccumulator, requestURL, node, nodesCounter); + private List>> getNodesWithRelationships(JsonNode jsonNode, NodeType nodeType, + ConcurrentSkipListSet nodesAccumulator, + Tree pathsTree) { + if (isListOfKeyResults(jsonNode)) { + return Streams.fromIterable(jsonNode.get(RESULTS)) + .filter(item -> item.has(nodeType.getType())) + .map(item -> item.get(nodeType.getType())) + .map(item -> parseNodeAndFilterRelationships(item, nodeType, nodesAccumulator, pathsTree)) + .collect(Collectors.toList()); + } else if (isArray(jsonNode, nodeType)) { + return Streams.fromIterable(jsonNode.get(nodeType.getType())) + .map(item -> parseNodeAndFilterRelationships(item, nodeType, nodesAccumulator, pathsTree)) + .collect(Collectors.toList()); + } else { + return ImmutableList.of(parseNodeAndFilterRelationships(jsonNode, nodeType, nodesAccumulator, pathsTree)); } - return node; } - private AAITreeNode jsonToAaiNode(String nodeType, JsonNode topLevelJson, ConcurrentSkipListSet nodesAccumulator, AtomicInteger nodesCounter) { - AAITreeNode node = fillNodeMetaData(nodeType, topLevelJson, nodesCounter); + Pair> parseNodeAndFilterRelationships(JsonNode jsonNode, NodeType nodeType, + ConcurrentSkipListSet nodesAccumulator, + Tree pathsTree) { + AAITreeNode node = createAaiNode(nodeType, jsonNode, nodesAccumulator); + + enrichPlacementData(node); + + List filteredRelationships = getFilteredRelationships(jsonNode, pathsTree); + + return ImmutablePair.of(node, filteredRelationships); + } + + boolean isArray(JsonNode json, NodeType nodeType) { + return json != null && json.has(nodeType.getType()) && json.get(nodeType.getType()).isArray(); + } + + boolean isListOfKeyResults(JsonNode jsonNode) { + return jsonNode != null && jsonNode.has(RESULTS) && jsonNode.get(RESULTS).isArray(); + } + + AAITreeNode createAaiNode(NodeType nodeType, JsonNode jsonNode, ConcurrentSkipListSet nodesAccumulator) { + AAITreeNode node = jsonNodeToAaiNode(nodeType, jsonNode); nodesAccumulator.add(node); return node; } - private void getRelatedVfModules(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, String parentURL, AAITreeNode parentNode, AtomicInteger nodesCounter) { + private void addChildren(AAITreeNode node, Future> children) { + try { + node.addChildren(children.get()); + } catch (Exception e) { + node.getChildren().add(createFailureNode(e)); + } + } + + private Map convertRelationshipDataToMap(List relationshipData) { + return relationshipData.stream().collect( + Collectors.toMap(RelationshipData::getKey, RelationshipData::getValue)); + } + + void enrichPlacementData(AAITreeNode node){ + Optional tenantRelationShip = AAITreeNodeUtils.findFirstRelationshipByRelatedTo(node.getRelationshipList(), "tenant"); + enrichPlacementDataUsingTenantInfo(node, tenantRelationShip); + } + + void enrichPlacementDataUsingTenantInfo(AAITreeNode node, Optional tenantRelationShip) { + //no tenant relationship in this node - so no placement data + if (!tenantRelationShip.isPresent()) { + return; + } + try { + Map relationshipsDataMap = convertRelationshipDataToMap(tenantRelationShip.get().getRelationDataList()); + node.setCloudConfiguration(new CloudConfiguration( + relationshipsDataMap.get("cloud-region.cloud-region-id"), + relationshipsDataMap.get("tenant.tenant-id"), + relationshipsDataMap.get("cloud-region.cloud-owner"))); + } + catch (Exception exception) { + LOGGER.error("Failed to extract placement form tenant relationship of {}:{}", node.getType(), node.getId(), exception); + } + } + + private void getRelatedVfModules(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, String parentURL, AAITreeNode parentNode) { /* VNFs do not report their direct related-to vf-modules, so try directly fetching a resource URI. @@ -166,73 +207,100 @@ public class AAITreeNodeBuilder { threadPool.execute(() -> { // the response is an array of vf-modules - final JsonNode topLevelJson; + final JsonNode jsonNode; try { - topLevelJson = aaiClient.typedAaiGet(Unchecked.toURI(parentURL + "/vf-modules"), JsonNode.class); + jsonNode = aaiClient.typedAaiGet(Unchecked.toURI(parentURL + "/vf-modules"), JsonNode.class); } catch (ExceptionWithRequestInfo e) { if (e.getHttpCode().equals(404)) { // it's ok, as we're just optimistically fetching - // the /vf-modules uri; 404 says this time it was - // a bad guess + // the /vf-modules uri; 404 says this time it was a bad guess return; } else { throw e; } } - if (topLevelJson != null) { - parentNode.getChildren().addAll( - Streams.fromIterable(topLevelJson.get(VF_MODULE)) - .map(vfModuleNode -> jsonToAaiNode(VF_MODULE, vfModuleNode, nodesAccumulator, nodesCounter)) - .collect(toList()) - ); + if (isArray(jsonNode, NodeType.VF_MODULE)) { + + //create list of AAITreeNode represent the VfModules from AAI result + List vfModules = Streams.fromIterable(jsonNode.get(NodeType.VF_MODULE.getType())) + .map(vfModuleNode -> createAaiNode(NodeType.VF_MODULE, vfModuleNode, nodesAccumulator)) + .collect(toList()); + //enrich each of the VfModule with placement info + vfModules.forEach(vfModule-> enrichPlacementDataUsingTenantInfo( + vfModule, + AAITreeNodeUtils.findFirstRelationshipByRelatedTo(vfModule.getRelationshipList(), "vserver") + )); + //add all VfModules to children list of parent node + parentNode.getChildren().addAll(vfModules); } else { LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to get vf-modules for vnf " + parentNode.getId()); } }); } - private void getChildren(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, - List relationships, ConcurrentLinkedQueue visitedNodes, AAITreeNode parent, AtomicInteger nodesCounter, Tree pathsTree) { - for (Relationship relationship : relationships) { - createChildNode(threadPool, nodesAccumulator, relationship, visitedNodes, parent, nodesCounter, pathsTree); + List getFilteredRelationships(JsonNode json, Tree pathsTree) { + RelationshipList relationshipList = JACKSON_OBJECT_MAPPER.convertValue(json.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class); + if (relationshipList != null) { + return relationshipList.getRelationship().stream() + .filter(rel -> getNextLevelInPathsTree(pathsTree, rel.getRelatedTo()) != null) + .filter(rel -> !Objects.equals(rel.getRelatedTo(), NodeType.VF_MODULE.getType())) // vf-modules are handled separately + .collect(toList()); } + + return Collections.emptyList(); } - private void createChildNode(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, - Relationship relationship, ConcurrentLinkedQueue visitedNodes, AAITreeNode parent, AtomicInteger nodesCounter, Tree pathsTree) { - String newNodeType = relationship.getRelatedTo(); - Tree subTree = pathsTree.getSubTree(new AAIServiceTree.AaiRelationship(newNodeType)); - if (subTree!=null) { - String newNodeUrl = relationship.getRelatedLink(); - if (!visitedNodes.contains(newNodeUrl)) { - visitedNodes.add(newNodeUrl); - threadPool.execute(() -> { - try { - parent.addChildren(buildNode(newNodeType, newNodeUrl, nodesAccumulator, threadPool, visitedNodes, nodesCounter, subTree)); - } catch (Exception e) { - parent.getChildren().add(createFailureNode(e)); - } - } - ); + void fetchChildrenAsync(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, + AAITreeNode node, List relationships, Tree pathsTree, long timeout) { + + if (!relationships.isEmpty()) { + List>> tasks = relationships.stream() + .map(relationship -> + (Callable>) () -> + getChildNode(threadPool, nodesAccumulator, relationship.getRelatedTo(), + relationship.getRelatedLink(), pathsTree)) + .collect(Collectors.toList()); + + try { + int depth = pathsTree.getChildrenDepth(); + threadPool.invokeAll(tasks, timeout * depth, TimeUnit.SECONDS) + .forEach(future -> + addChildren(node, future) + ); + } catch (Exception e) { + throw new GenericUncheckedException(e); } } } - private AAITreeNode fillNodeMetaData(String nodeType, JsonNode model, @NotNull AtomicInteger nodesCounter) { + private List getChildNode(ExecutorService threadPool, ConcurrentSkipListSet nodesAccumulator, + String childNodeType, String childNodeUrl, + Tree pathsTree) { + + Tree subTree = getNextLevelInPathsTree(pathsTree, childNodeType); + + return buildNode(NodeType.fromString(childNodeType), childNodeUrl, null, HttpMethod.GET, nodesAccumulator, threadPool, subTree); + } + + Tree getNextLevelInPathsTree(Tree pathsTree, String nodeType) { + return pathsTree.getSubTree(new AAIServiceTree.AaiRelationship(nodeType)); + } + + //ADD TEST + private AAITreeNode jsonNodeToAaiNode(NodeType nodeType, JsonNode jsonNode) { AAITreeNode node = new AAITreeNode(); node.setType(nodeType); - node.setUniqueNumber(nodesCounter.getAndIncrement()); - node.setOrchestrationStatus(getStringDataFromJsonIfExists(model, AAIBaseProperties.ORCHESTRATION_STATUS.getAaiKey())); - node.setProvStatus(getStringDataFromJsonIfExists(model, AAIBaseProperties.PROV_STATUS.getAaiKey())); - node.setInMaint(getBooleanDataFromJsonIfExists(model, AAIBaseProperties.IN_MAINT.getAaiKey())); - node.setModelVersionId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_VERSION_ID.getAaiKey())); - node.setModelCustomizationId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_CUSTOMIZATION_ID.getAaiKey())); - node.setModelInvariantId(getStringDataFromJsonIfExists(model, AAIBaseProperties.MODEL_INVARIANT_ID.getAaiKey())); - node.setId(getStringDataFromJsonIfExists(model, nodeTypeToIdKeyMap.get(nodeType))); - node.setName(getStringDataFromJsonIfExists(model, nodeTypeToNameKeyMap.get(nodeType))); - node.setAdditionalProperties(aggregateAllOtherProperties(model, nodeType)); - + node.setOrchestrationStatus(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.ORCHESTRATION_STATUS.getAaiKey())); + node.setProvStatus(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.PROV_STATUS.getAaiKey())); + node.setInMaint(getBooleanDataFromJsonIfExists(jsonNode, AAIBaseProperties.IN_MAINT.getAaiKey())); + node.setModelVersionId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_VERSION_ID.getAaiKey())); + node.setModelCustomizationId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_CUSTOMIZATION_ID.getAaiKey())); + node.setModelInvariantId(getStringDataFromJsonIfExists(jsonNode, AAIBaseProperties.MODEL_INVARIANT_ID.getAaiKey())); + node.setId(getStringDataFromJsonIfExists(jsonNode, nodeType.getId())); + node.setName(getStringDataFromJsonIfExists(jsonNode, nodeType.getName())); + node.setAdditionalProperties(aggregateAllOtherProperties(jsonNode, nodeType)); + node.setRelationshipList(JACKSON_OBJECT_MAPPER.convertValue(jsonNode.get(AAIBaseProperties.RELATIONSHIP_LIST.getAaiKey()), RelationshipList.class)); return node; } @@ -241,7 +309,7 @@ public class AAITreeNodeBuilder { } private String getStringDataFromJsonIfExists(JsonNode model, String key) { - if (model.has(key)) { + if (!NodeType.NONE.equals(key) && model.has(key)) { return model.get(key).asText(); } return null; @@ -254,48 +322,17 @@ public class AAITreeNodeBuilder { return false; } - private Map aggregateAllOtherProperties(JsonNode model, String nodeType) { + Map aggregateAllOtherProperties(JsonNode model, NodeType nodeType) { Set ignoreProperties = Stream.of(AAIBaseProperties.values()) .map(AAIBaseProperties::getAaiKey).collect(toSet()); - return Streams.fromIterator(model.fields()) - .filter(not(field -> StringUtils.equals(field.getKey(), nodeTypeToIdKeyMap.get(nodeType)))) - .filter(not(field -> StringUtils.equals(field.getKey(), nodeTypeToNameKeyMap.get(nodeType)))) + .filter(not(field -> StringUtils.equals(field.getKey(), nodeType.getId()))) + .filter(not(field -> StringUtils.equals(field.getKey(), nodeType.getName()))) .filter(not(field -> ignoreProperties.contains(field.getKey()))) - .collect(toMap(Map.Entry::getKey, v -> v.getValue().asText())); - } - - private static HashMap generateTypeToIdKeyMap() { - HashMap result = new HashMap<>(); - result.put(SERVICE_INSTANCE, "service-instance-id"); - result.put(GENERIC_VNF, "vnf-id"); - result.put(NETWORK, "network-id"); - result.put(COLLECTION_RESOURCE, "collection-id"); - result.put(CONFIGURATION, "configuration-id"); - result.put(PNF, "pnf-id"); - result.put(VF_MODULE, "vf-module-id"); - result.put(INSTANCE_GROUP, "id"); - result.put(PORT, "l-interface-id"); - result.put(VG, "volume-group-id"); - result.put(VLAN_TAG, "vlan-id"); - - return result; + .collect(toMap(Map.Entry::getKey, v -> ifTextualGetAsText(v.getValue()))); } - private static HashMap generateTypeToNameKeyMap() { - HashMap result = new HashMap<>(); - result.put(SERVICE_INSTANCE, "service-instance-name"); - result.put(GENERIC_VNF, "vnf-name"); - result.put(NETWORK, "network-name"); - result.put(COLLECTION_RESOURCE, "collection-name"); - result.put(CONFIGURATION, "configuration-name"); - result.put(PNF, "pnf-name"); - result.put(VF_MODULE, "vf-module-name"); - result.put(INSTANCE_GROUP, "instance-group-name"); - result.put(PORT, "l-interface-name"); - result.put(VG, "volume-group-name"); - result.put(VLAN_TAG, "vlan-name"); - - return result; + private Object ifTextualGetAsText(JsonNode jsonNode) { + return jsonNode.isTextual() ? jsonNode.asText() : jsonNode; } -} +} \ No newline at end of file diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java b/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java index 910b34112..76efbd0ea 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AaiService.java @@ -48,7 +48,7 @@ public interface AaiService { SubscriberFilteredResults getFullSubscriberList(RoleValidator roleValidator); - AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator); + AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances); AaiResponse getServiceInstanceSearchResults(String subscriberId, String instanceIdentifier, RoleValidator roleProvider, List owningEntities, List projects); diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java index d01f0f7ad..961f11096 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AaiServiceImpl.java @@ -24,6 +24,7 @@ package org.onap.vid.services; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.joshworks.restclient.http.HttpResponse; +import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; import org.onap.vid.aai.*; @@ -39,16 +40,19 @@ import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.model.ServiceInstanceSearchResult; import org.onap.vid.model.SubscriberList; import org.onap.vid.model.aaiTree.AAITreeNode; +import org.onap.vid.model.aaiTree.NodeType; import org.onap.vid.model.aaiTree.RelatedVnf; import org.onap.vid.roles.RoleValidator; import org.onap.vid.utils.Intersection; import org.onap.vid.utils.Tree; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; +import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; /** @@ -68,6 +72,8 @@ public class AaiServiceImpl implements AaiService { private AaiResponseTranslator aaiResponseTranslator; private AAITreeNodeBuilder aaiTreeNode; private AAIServiceTree aaiServiceTree; + private ExecutorService executorService; + private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class); @@ -77,13 +83,15 @@ public class AaiServiceImpl implements AaiService { AaiOverTLSClientInterface aaiOverTLSClient, AaiResponseTranslator aaiResponseTranslator, AAITreeNodeBuilder aaiTreeNode, - AAIServiceTree aaiServiceTree) + AAIServiceTree aaiServiceTree, + ExecutorService executorService) { this.aaiClient = aaiClient; this.aaiOverTLSClient = aaiOverTLSClient; this.aaiResponseTranslator = aaiResponseTranslator; this.aaiTreeNode = aaiTreeNode; this.aaiServiceTree = aaiServiceTree; + this.executorService = executorService; } private List convertModelToService(Model model) { @@ -220,8 +228,8 @@ public class AaiServiceImpl implements AaiService { } @Override - public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator) { - AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId); + public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances) { + AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId, omitServiceInstances); String subscriberGlobalId = subscriberResponse.getT().globalCustomerId; for (ServiceSubscription serviceSubscription : subscriberResponse.getT().serviceSubscriptions.serviceSubscription) { String serviceType = serviceSubscription.serviceType; @@ -254,7 +262,7 @@ public class AaiServiceImpl implements AaiService { private List getServicesBySubscriber(String subscriberId, String instanceIdentifier, RoleValidator roleValidator) { - AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId); + AaiResponse subscriberResponse = aaiClient.getSubscriberData(subscriberId, false); String subscriberGlobalId = subscriberResponse.getT().globalCustomerId; String subscriberName = subscriberResponse.getT().subscriberName; ServiceSubscriptions serviceSubscriptions = subscriberResponse.getT().serviceSubscriptions; @@ -483,26 +491,37 @@ public class AaiServiceImpl implements AaiService { @Override public List searchGroupMembers(String globalCustomerId, String serviceType, String invariantId, String groupType, String groupRole) { String getURL = "business/customers/customer/" + - globalCustomerId + "/service-subscriptions/service-subscription/" + - serviceType + "/service-instances?model-invariant-id=" + invariantId; + globalCustomerId + "/service-subscriptions/service-subscription/" + + serviceType + "/service-instances?model-invariant-id=" + invariantId; - Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(AAITreeNodeBuilder.SERVICE_INSTANCE)); - pathsToSearch.addPath(AAITreeNodeBuilder.toAaiRelationshipList(AAITreeNodeBuilder.GENERIC_VNF, AAITreeNodeBuilder.INSTANCE_GROUP)); + Tree pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(NodeType.SERVICE_INSTANCE)); + pathsToSearch.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.INSTANCE_GROUP)); //get all vnfs related to service-instances from the model-invariant-id - List aaiTree = aaiServiceTree.buildAAITree(getURL, pathsToSearch); + List aaiTree = aaiServiceTree.buildAAITree(getURL, null, HttpMethod.GET, pathsToSearch, true); //filter by instance-group-role & instance-group-type properties (from getAdditionalProperties) //only vnfs has related instance-group with the same groupType & groupRole - are filtered out. List filteredVnfs = filterByInstanceGroupRoleAndType(aaiTree, groupRole, groupType); //convert vnfs to expected result - return filteredVnfs.stream() + List convertedVnfs = filteredVnfs.stream() .map(RelatedVnf::from) - .map(this::enrichRelatedVnfWithCloudRegionAndTenant) .collect(Collectors.toList()); + + try { + return executorService.submit(() -> + convertedVnfs.parallelStream() + .map(this::enrichRelatedVnfWithCloudRegionAndTenant) + .collect(Collectors.toList()) + ).get(); + } catch (Exception e) { + LOGGER.error(EELFLoggerDelegate.errorLogger, "Search group Members - Failed to enrich vnf with cloud region", e); + return convertedVnfs; + } } + private List filterByInstanceGroupRoleAndType(List aaiTree, String groupRole, String groupType) { return aaiTree.stream() @@ -544,10 +563,10 @@ public class AaiServiceImpl implements AaiService { } private void getInstanceGroupInfoFromRelationship(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship, List instanceGroupInfoList) { - if(relationship.getRelatedTo().equals("instance-group")){ + if(StringUtils.equals(relationship.getRelatedTo(),"instance-group")){ for(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelatedToProperty relatedToProperty: relationship.getRelatedToPropertyList()){ - if(relatedToProperty.getPropertyKey().equals("instance-group.instance-group-name")){ - instanceGroupInfoList.add(new InstanceGroupInfo(relatedToProperty.getPropertyValue())); + if(StringUtils.equals(relatedToProperty.getKey(),"instance-group.instance-group-name")){ + instanceGroupInfoList.add(new InstanceGroupInfo(relatedToProperty.getValue())); } } } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java index 603f13867..1202fc9e3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AsyncInstantiationBusinessLogic.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,17 +21,15 @@ package org.onap.vid.services; import org.onap.vid.aai.model.ResourceType; -import org.onap.vid.changeManagement.RequestDetailsWrapper; import org.onap.vid.job.Job; -import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.*; -import org.onap.vid.mso.model.*; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; +import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.UUID; import java.util.function.Consumer; @@ -43,23 +41,7 @@ public interface AsyncInstantiationBusinessLogic { List pushBulkJob(ServiceInstantiation request, String userId); - RequestDetailsWrapper generateMacroServiceInstantiationRequest(UUID uuid, ServiceInstantiation details, String optimisticUniqueServiceInstanceName, String userId); - - RequestDetailsWrapper generateALaCarteServiceInstantiationRequest(UUID uuid, ServiceInstantiation details, String optimisticUniqueServiceInstanceName, String userId); - - RequestDetailsWrapper generateALaCarteServiceDeletionRequest(UUID uuid, ServiceInstantiation details, String userId); - - RequestDetailsWrapper generateVnfInstantiationRequest(Vnf vnfDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - RequestDetailsWrapper generateVfModuleInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String vgInstanceId, String userId); - - RequestDetailsWrapper generateVolumeGroupInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String userId); - - RequestDetailsWrapper generateNetworkInstantiationRequest(Network networkDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - RequestDetailsWrapper generateInstanceGroupInstantiationRequest(InstanceGroup request, ModelInfo serviceModelInfo, String serviceInstanceId, String userId); - - List> buildVnfInstanceParams(List> currentVnfInstanceParams, List vfModules); + boolean isPartOfBulk(UUID jobId); String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest); @@ -67,32 +49,34 @@ public interface AsyncInstantiationBusinessLogic { String getVnfInstantiationPath(String serviceInstanceId); + String getVnfDeletionPath(String serviceInstanceId, String vnfInstanceId); + String getNetworkInstantiationPath(String serviceInstanceId); String getVfmoduleInstantiationPath(String serviceInstanceId, String vnfInstanceId); + String getVfModuleReplacePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId); + + String getVfModuleDeletePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId); + String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId); String getInstanceGroupInstantiationPath(); + String getInstanceGroupMemberInstantiationPath(String vnfGroupInstanceId); + String getInstanceGroupDeletePath(String instanceGroupId); - String getOrchestrationRequestsPath(); + String getInstanceGroupMemberDeletePath(String vnfGroupInstanceId); - ServiceInfo getServiceInfoByJobId(UUID jobUUID); + String getNetworkDeletePath(String serviceInstanceId, String networkInstanceId); - List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source); + String getOrchestrationRequestsPath(); ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater); ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, Job.JobStatus jobStatus); - void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus); - - void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus); - - void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo); - Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus); void handleFailedInstantiation(UUID jobUUID); @@ -109,5 +93,21 @@ public interface AsyncInstantiationBusinessLogic { String getUniqueName(String name, ResourceType resourceType); + ServiceInstantiation prepareServiceToBeUnique(ServiceInstantiation serviceInstantiation); + + ServiceInstantiation enrichBulkForRetry(ServiceInstantiation serviceInstantiation, UUID jobId); + + List retryJob(UUID jobId, String userId); + + List retryJob(ServiceInstantiation request, UUID oldJobId, String userId); + + void addResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, String instanceId); + + void addFailedResourceInfo(JobSharedData sharedData, RestObject msoResponse); + + void updateResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, AsyncRequestStatus message); + + ServiceInstantiation getBulkForRetry(UUID jobId); + String getResumeRequestPath(String requestId); } 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 73056db71..92a6d5fd7 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 @@ -20,18 +20,28 @@ package org.onap.vid.services; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableList; +import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; +import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; +import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; +import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER; + import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; import org.apache.commons.lang3.StringUtils; import org.hibernate.SessionFactory; import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.portalsdk.core.service.DataAccessService; 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.dal.AsyncInstantiationRepository; import org.onap.vid.exceptions.DbFailureUncheckedException; import org.onap.vid.exceptions.GenericUncheckedException; import org.onap.vid.exceptions.MaxRetriesException; @@ -41,37 +51,26 @@ import org.onap.vid.job.Job.JobStatus; import org.onap.vid.job.JobAdapter; import org.onap.vid.job.JobType; import org.onap.vid.job.JobsBrokerService; +import org.onap.vid.job.impl.JobSharedData; import org.onap.vid.model.Action; -import org.onap.vid.model.JobAuditStatus; import org.onap.vid.model.NameCounter; +import org.onap.vid.model.ResourceInfo; import org.onap.vid.model.ServiceInfo; -import org.onap.vid.model.serviceInstantiation.*; +import org.onap.vid.model.serviceInstantiation.BaseResource; +import org.onap.vid.model.serviceInstantiation.ServiceInstantiation; import org.onap.vid.mso.MsoBusinessLogicImpl; import org.onap.vid.mso.MsoProperties; -import org.onap.vid.mso.model.*; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.RequestParameters; -import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.*; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.RequestParametersVfModule; -import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.UserParamMap; +import org.onap.vid.mso.MsoUtil; +import org.onap.vid.mso.RestObject; import org.onap.vid.mso.rest.AsyncRequestStatus; -import org.onap.vid.mso.rest.SubscriberInfo; +import org.onap.vid.mso.rest.RequestStatus; import org.onap.vid.properties.Features; import org.onap.vid.utils.DaoUtils; +import org.onap.vid.utils.TimeUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.togglz.core.manager.FeatureManager; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.*; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; -import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID; -import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID; -import static org.onap.vid.utils.Logging.debugRequestDetails; - @Service public class AsyncInstantiationBusinessLogicImpl implements AsyncInstantiationBusinessLogic { @@ -79,9 +78,6 @@ public class AsyncInstantiationBusinessLogicImpl implements private static final int MAX_RETRIES_GETTING_COUNTER = 100; private static final int MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI = 10000; public static final String NAME_FOR_CHECK_AAI_STATUS = "NAME_FOR_CHECK_AAI_STATUS"; - private static final String VID_SOURCE = "VID"; - - private final DataAccessService dataAccessService; private final JobAdapter jobAdapter; @@ -89,12 +85,17 @@ public class AsyncInstantiationBusinessLogicImpl implements private final CloudOwnerService cloudOwnerService; + private final AsyncInstantiationRepository asyncInstantiationRepository; + private SessionFactory sessionFactory; private AaiClientInterface aaiClient; private FeatureManager featureManager; + private AuditService auditService; + + private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI; private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class); @@ -107,51 +108,34 @@ public class AsyncInstantiationBusinessLogicImpl implements .put("pending", JobStatus.IN_PROGRESS) .put("pendingmanualtask", JobStatus.PAUSE) .put("unlocked", JobStatus.IN_PROGRESS) + .put("aborted", JobStatus.COMPLETED_WITH_ERRORS) + .put("rolledback", JobStatus.FAILED) + .put("rolledbacktoassigned", JobStatus.FAILED) + .put("rolledbacktocreated", JobStatus.FAILED) .build(); @Autowired - public AsyncInstantiationBusinessLogicImpl(DataAccessService dataAccessService, - JobAdapter jobAdapter, + public AsyncInstantiationBusinessLogicImpl(JobAdapter jobAdapter, JobsBrokerService jobService, SessionFactory sessionFactory, AaiClientInterface aaiClient, FeatureManager featureManager, - CloudOwnerService cloudOwnerService) { - this.dataAccessService = dataAccessService; + CloudOwnerService cloudOwnerService, AsyncInstantiationRepository asyncInstantiationRepository, + AuditService auditService) { this.jobAdapter = jobAdapter; this.jobService = jobService; this.sessionFactory = sessionFactory; this.aaiClient = aaiClient; this.featureManager = featureManager; this.cloudOwnerService = cloudOwnerService; + this.asyncInstantiationRepository = asyncInstantiationRepository; + this.auditService = auditService; } @Override public List getAllServicesInfo() { - return dataAccessService.getList(ServiceInfo.class, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null); - } - - private String filterByCreationDateAndNotDeleted() { - LocalDateTime minus3Months = LocalDateTime.now().minusMonths(3); - Timestamp filterDate = Timestamp.valueOf(minus3Months); - return " where" + - " hidden = false" + - " and deleted_at is null" + // don't fetch deleted - " and created >= '" + filterDate + "' "; - } - - private String orderByCreatedDateAndStatus() { - return " createdBulkDate DESC ,\n" + - " (CASE jobStatus\n" + - " WHEN 'COMPLETED' THEN 0\n" + - " WHEN 'FAILED' THEN 0\n" + - " WHEN 'COMPLETED_WITH_ERRORS' THEN 0\n" + - " WHEN 'IN_PROGRESS' THEN 1\n" + - " WHEN 'PAUSE' THEN 2\n" + - " WHEN 'PENDING' THEN 3\n" + - " WHEN 'STOPPED' THEN 3 END),\n" + - " statusModifiedDate "; + return asyncInstantiationRepository.getAllServicesInfo(); } JobType getJobType(ServiceInstantiation request) { @@ -171,19 +155,26 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public List pushBulkJob(ServiceInstantiation request, String userId) { + List uuids = new ArrayList<>(); Date createdBulkDate = Calendar.getInstance().getTime(); int bulkSize = request.getBulkSize(); UUID templateId = UUID.randomUUID(); for (int i = 0; i < bulkSize; i++) { - ServiceInfo.ServiceAction serviceAction = getAction(request); - JobType jobType = getJobType(request); - final String optimisticUniqueServiceInstanceName = getOptimisticUniqueServiceInstanceName(request); - Job job = jobAdapter.createServiceInstantiationJob(jobType, request, templateId, userId, optimisticUniqueServiceInstanceName, i); - UUID jobId = jobService.add(job); - dataAccessService.saveDomainObject(createServiceInfo(userId, request, jobId, templateId, createdBulkDate, optimisticUniqueServiceInstanceName, serviceAction), DaoUtils.getPropsMap()); - auditVidStatus(jobId, job.getStatus()); + ServiceInstantiation requestPerJob = prepareServiceToBeUnique(request); + ServiceInfo.ServiceAction serviceAction = getAction(requestPerJob); + JobType jobType = getJobType(requestPerJob); + final String optimisticUniqueServiceInstanceName = bulkSize>1 ? //only bulk with more than 1 service need to get multiple names + getOptimisticUniqueServiceInstanceName(requestPerJob.getInstanceName()) : requestPerJob.getInstanceName(); + Job job = jobAdapter.createServiceInstantiationJob(jobType, requestPerJob, templateId, userId, request.getTestApi(), optimisticUniqueServiceInstanceName, i); + UUID jobId = job.getUuid(); + + asyncInstantiationRepository.saveServiceInfo(createServiceInfo(userId, requestPerJob, jobId, templateId, createdBulkDate, optimisticUniqueServiceInstanceName, serviceAction)); + asyncInstantiationRepository.addJobRequest(jobId, requestPerJob); + auditService.auditVidStatus(jobId, job.getStatus()); uuids.add(jobId); + + jobService.add(job); } return uuids; } @@ -197,8 +188,8 @@ public class AsyncInstantiationBusinessLogicImpl implements } - private String getOptimisticUniqueServiceInstanceName(ServiceInstantiation request) { - return StringUtils.isNotEmpty(request.getInstanceName()) ? getUniqueNameFromDbOnly(request.getInstanceName()) : request.getInstanceName(); + private String getOptimisticUniqueServiceInstanceName(String instanceName) { + return StringUtils.isNotEmpty(instanceName) ? getUniqueNameFromDbOnly(instanceName) : instanceName; } protected ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate, String optimisticUniqueServiceInstanceName, ServiceInfo.ServiceAction serviceAction) { @@ -224,359 +215,32 @@ public class AsyncInstantiationBusinessLogicImpl implements serviceInstantiation.getModelInfo().getModelName(), serviceInstantiation.getModelInfo().getModelVersion(), createdBulkDate, - serviceAction - ); - } - - - @Override - public RequestDetailsWrapper generateMacroServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName, String userId) { - String serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - - List serviceInstantiationServiceList = generateServiceInstantiationServicesList(payload, serviceInstanceName, createServiceInstantiationVnfList(payload)); - - RequestParameters requestParameters = new RequestParameters(payload.getSubscriptionServiceType(), false, serviceInstantiationServiceList); - - ServiceInstantiationRequestDetails requestDetails = generateServiceInstantiationRequestDetails(payload,requestParameters,serviceInstanceName, userId); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - - return requestDetailsWrapper; + serviceAction, + false); } @Override - public RequestDetailsWrapper generateALaCarteServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName, String userId) { - String serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - - List userParams = generateUserParamList(); - - RequestParameters requestParameters = new RequestParameters(payload.getSubscriptionServiceType(), true, userParams, payload.getTestApi()); - - ServiceInstantiationRequestDetails requestDetails = generateServiceInstantiationRequestDetails(payload,requestParameters,serviceInstanceName, userId); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - return requestDetailsWrapper; - } - - - @Override - public RequestDetailsWrapper generateALaCarteServiceDeletionRequest(UUID jobId, ServiceInstantiation payload, String userId){ - - ServiceDeletionRequestDetails.RequestParameters requestParameters = new ServiceDeletionRequestDetails.RequestParameters( true, payload.getTestApi()); - - ServiceDeletionRequestDetails.RequestInfo requestInfo = new ServiceDeletionRequestDetails.RequestInfo( - VID_SOURCE, - userId); - - ServiceDeletionRequestDetails requestDetails = new ServiceDeletionRequestDetails(payload.getModelInfo(), requestInfo, requestParameters); - - RequestDetailsWrapper requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails); - debugRequestDetails(requestDetailsWrapper, logger); - return requestDetailsWrapper; + public boolean isPartOfBulk(UUID jobId) { + if (jobId == null) { + return false; } - - @Override - public RequestDetailsWrapper generateVnfInstantiationRequest(Vnf vnfDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - - VnfInstantiationRequestDetails.RequestInfo requestInfo = new VnfInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vnfDetails.getInstanceName(), ResourceType.GENERIC_VNF), - vnfDetails.getProductFamilyId(), - VID_SOURCE, - vnfDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vnfDetails.getLcpCloudRegionId(), vnfDetails.getTenantId()); - VnfInstantiationRequestDetails.Platform platform = new VnfInstantiationRequestDetails.Platform(vnfDetails.getPlatformName()); - VnfInstantiationRequestDetails.LineOfBusiness lineOfBusiness = new VnfInstantiationRequestDetails.LineOfBusiness(vnfDetails.getLineOfBusiness()); - VnfInstantiationRequestDetails.RequestParameters requestParameters = new VnfInstantiationRequestDetails.RequestParameters(generateUserParamList()); - VnfInstantiationRequestDetails.RelatedInstance serviceInstance = new VnfInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - return new RequestDetailsWrapper<>(new VnfInstantiationRequestDetails(vnfDetails.getModelInfo(), cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobId); + UUID templateId = serviceInfo.getTemplateId(); + if (templateId != null) { + return getNumberOfJobsInBulk(templateId) > 1; } + return false; - @Override - public RequestDetailsWrapper generateVfModuleInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String vgInstanceId, String userId) { - - VfModuleInstantiationRequestDetails.RequestInfo requestInfo = new VfModuleInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vfModuleDetails.getInstanceName(), ResourceType.VF_MODULE), - null, - VID_SOURCE, - vfModuleDetails.isRollbackOnFailure(), - userId); - - //cloud configuration - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vfModuleDetails.getLcpCloudRegionId(), vfModuleDetails.getTenantId()); - - //request parameters - List> userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.getInstanceParams()), vfModuleDetails.getSupplementaryParams()); - RequestParametersVfModule requestParameters = new RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload()); - - //related instance list - VfModuleInstantiationRequestDetails.RelatedInstance serviceInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - VfModuleInstantiationRequestDetails.RelatedInstance vnfInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(vnfModelInfo, vnfInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - relatedInstanceList.add(vnfInstance); - if (vgInstanceId != null) { - ModelInfo volumeGroupModel = new ModelInfo(); - volumeGroupModel.setModelType("volumeGroup"); - VfModuleInstantiationRequestDetails.RelatedInstance volumeGroupInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(volumeGroupModel, vgInstanceId, vfModuleDetails.getVolumeGroupInstanceName()); - relatedInstanceList.add(volumeGroupInstance); - } - - return new RequestDetailsWrapper<>(new VfModuleInstantiationRequestDetails(vfModuleDetails.getModelInfo(), cloudConfiguration, requestInfo, relatedInstanceList, requestParameters)); } - protected CloudConfiguration generateCloudConfiguration(String lcpCloudRegionId, String tenantId) { - CloudConfiguration cloudConfiguration = new CloudConfiguration(); - cloudConfiguration.setLcpCloudRegionId(lcpCloudRegionId); - cloudConfiguration.setTenantId(tenantId); - cloudOwnerService.enrichCloudConfigurationWithCloudOwner(cloudConfiguration, lcpCloudRegionId); - return cloudConfiguration; - } - - @Override - public RequestDetailsWrapper generateVolumeGroupInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String userId) { - VolumeGroupRequestDetails.RequestInfo requestInfo = new VolumeGroupRequestDetails.RequestInfo( - getUniqueNameIfNeeded(vfModuleDetails.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP), - null, - VID_SOURCE, - vfModuleDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(vfModuleDetails.getLcpCloudRegionId(), vfModuleDetails.getTenantId()); - - List> userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.getInstanceParams()), vfModuleDetails.getSupplementaryParams()); - RequestParametersVfModule requestParameters = new RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload()); - - VfModuleInstantiationRequestDetails.RelatedInstance serviceInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - VfModuleInstantiationRequestDetails.RelatedInstance vnfInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(vnfModelInfo, vnfInstanceId); - List relatedInstancs = ImmutableList.of(serviceInstance, vnfInstance); - - ModelInfo modelInfo = vfModuleDetails.getModelInfo(); - modelInfo.setModelType("volumeGroup"); - return new RequestDetailsWrapper<>(new VolumeGroupRequestDetails(modelInfo, cloudConfiguration, requestInfo, relatedInstancs, requestParameters)); - } - - protected List> aggregateAllInstanceParams(Map instanceParams, Map supplementaryParams) { - Map instanceParamsFinal = defaultIfNull(instanceParams, new HashMap<>()); - Map supplementaryParamsFinal = defaultIfNull(supplementaryParams, new HashMap<>()); - - if (!(instanceParamsFinal.isEmpty() && supplementaryParamsFinal.isEmpty())) { - //remove duplicate keys from instanceParams if exist in supplementaryParams - instanceParamsFinal = instanceParams.entrySet().stream().filter(m-> - !supplementaryParamsFinal.containsKey(m.getKey()) - ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - //aggregate the 2 collections and format them as UserParamMap - UserParamMap aggregatedParams = new UserParamMap<>(); - aggregatedParams.putAll(instanceParamsFinal); - aggregatedParams.putAll(supplementaryParamsFinal); - - return ImmutableList.of(aggregatedParams); - } - - return Collections.emptyList(); - } - - @Override - public RequestDetailsWrapper generateNetworkInstantiationRequest(Network networkDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - - NetworkInstantiationRequestDetails.RequestInfo requestInfo = new NetworkInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(networkDetails.getInstanceName(), ResourceType.L3_NETWORK), - networkDetails.getProductFamilyId(), - VID_SOURCE, - networkDetails.isRollbackOnFailure(), - userId); - CloudConfiguration cloudConfiguration = generateCloudConfiguration(networkDetails.getLcpCloudRegionId(), networkDetails.getTenantId()); - NetworkInstantiationRequestDetails.Platform platform = new NetworkInstantiationRequestDetails.Platform(networkDetails.getPlatformName()); - NetworkInstantiationRequestDetails.LineOfBusiness lineOfBusiness = new NetworkInstantiationRequestDetails.LineOfBusiness(networkDetails.getLineOfBusiness()); - NetworkInstantiationRequestDetails.RequestParameters requestParameters = new NetworkInstantiationRequestDetails.RequestParameters(generateUserParamList()); - NetworkInstantiationRequestDetails.RelatedInstance serviceInstance = new NetworkInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = new ArrayList<>(); - relatedInstanceList.add(serviceInstance); - return new RequestDetailsWrapper<>(new NetworkInstantiationRequestDetails(networkDetails.getModelInfo(), cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters)); - } - - @Override - public RequestDetailsWrapper generateInstanceGroupInstantiationRequest(InstanceGroup instanceGroupDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) { - InstanceGroupInstantiationRequestDetails.RequestInfo requestInfo = new InstanceGroupInstantiationRequestDetails.RequestInfo( - getUniqueNameIfNeeded(instanceGroupDetails.getInstanceName(), ResourceType.INSTANCE_GROUP), - null, - "VID", - instanceGroupDetails.isRollbackOnFailure(), - userId); - InstanceGroupInstantiationRequestDetails.RequestParameters requestParameters = new InstanceGroupInstantiationRequestDetails.RequestParameters(generateUserParamList()); - InstanceGroupInstantiationRequestDetails.RelatedInstance serviceInstance = new InstanceGroupInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId); - List relatedInstanceList = ImmutableList.of(serviceInstance); - return new RequestDetailsWrapper<>(new InstanceGroupInstantiationRequestDetails(instanceGroupDetails.getModelInfo(), requestInfo, relatedInstanceList, requestParameters)); - } - - // TODO - private List generateUserParamList() { - return Collections.emptyList(); - } - - protected List generateServiceInstantiationServicesList(ServiceInstantiation payload, String serviceInstanceName, ServiceInstantiationVnfList vnfList) { - List serviceInstantiationServiceList = new LinkedList<>(); - List> unFilteredInstanceParams = defaultIfNull(payload.getInstanceParams(), Collections.emptyList()); - List> filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams); - ServiceInstantiationService serviceInstantiationService = new ServiceInstantiationService( - payload.getModelInfo(), - serviceInstanceName, - filteredInstanceParams, - vnfList + private int getNumberOfJobsInBulk(UUID templateId) { + String hqlSelectJob = "from JobDaoImpl where templateId = :templateId"; + return DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> + session.createQuery(hqlSelectJob) + .setText("templateId", templateId.toString()) + .list() + .size() ); - serviceInstantiationServiceList.add(serviceInstantiationService); - return serviceInstantiationServiceList; - } - - private ServiceInstantiationRequestDetails generateServiceInstantiationRequestDetails(ServiceInstantiation payload, RequestParameters requestParameters, String serviceInstanceName, String userId) { - ServiceInstantiationRequestDetails.RequestInfo requestInfo = new ServiceInstantiationRequestDetails.RequestInfo(serviceInstanceName, - payload.getProductFamilyId(), - VID_SOURCE, - payload.isRollbackOnFailure(), - userId); - ServiceInstantiationOwningEntity owningEntity = new ServiceInstantiationOwningEntity(payload.getOwningEntityId(), payload.getOwningEntityName()); - SubscriberInfo subscriberInfo = generateSubscriberInfo(payload); - Project project = payload.getProjectName() != null ? new Project(payload.getProjectName()) : null; - return new ServiceInstantiationRequestDetails(payload.getModelInfo(), owningEntity, subscriberInfo, project, requestInfo, requestParameters); - } - - - protected SubscriberInfo generateSubscriberInfo(ServiceInstantiation payload) { - SubscriberInfo subscriberInfo = new SubscriberInfo(); - subscriberInfo.setGlobalSubscriberId(payload.getGlobalSubscriberId()); - return subscriberInfo; - } - - protected String generateServiceName(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName) { - String serviceInstanceName = null; - if(StringUtils.isNotEmpty(optimisticUniqueServiceInstanceName)) { - serviceInstanceName = peekServiceName(jobId, payload, optimisticUniqueServiceInstanceName); - } - return serviceInstanceName; - } - - protected String peekServiceName(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName) { - String serviceInstanceName; - // unique name already exist in service info. If it's free in AAI we use it - if (isNameFreeInAai(optimisticUniqueServiceInstanceName, ResourceType.SERVICE_INSTANCE)) { - serviceInstanceName = optimisticUniqueServiceInstanceName; - } - //otherwise we used the original service instance name (from payload) to get a new unique name from DB and AAI - else { - serviceInstanceName = getUniqueName(payload.getInstanceName(), ResourceType.SERVICE_INSTANCE); - } - - //update serviceInfo with new name if needed - try { - updateServiceInfo(jobId, x -> x.setServiceInstanceName(serviceInstanceName)); - } catch (Exception e) { - logger.error("Failed updating service name {} in serviceInfo", serviceInstanceName, e); - } - - return serviceInstanceName; - } - - @Override - public List> buildVnfInstanceParams(List> currentVnfInstanceParams, List vfModules){ - List> filteredVnfInstanceParams = removeUnNeededParams(currentVnfInstanceParams); - - if (!featureManager.isActive(Features.FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF)) { - return filteredVnfInstanceParams; - } - - Map vnfInstanceParams = extractActualInstanceParams(filteredVnfInstanceParams); - vfModules.stream() - .map(x->extractActualInstanceParams(x.getInstanceParams())) - .forEach(vnfInstanceParams::putAll); - return vnfInstanceParams.isEmpty() ? Collections.emptyList() : ImmutableList.of(vnfInstanceParams); - } - - //Make sure we always get a one Map from InstanceParams - private Map extractActualInstanceParams(List> originalInstanceParams) { - if (originalInstanceParams==null || originalInstanceParams.isEmpty() || originalInstanceParams.get(0)==null) { - return new HashMap<>(); - } - return originalInstanceParams.get(0); - } - - private List> removeUnNeededParams(List> instanceParams) { - List keysToRemove = new ArrayList<>(); - if (instanceParams == null || instanceParams.isEmpty()) { - return Collections.emptyList(); - } - - for (String key : instanceParams.get(0).keySet()) { - for (String paramToIgnore : PARAMS_TO_IGNORE) - if ((key.equalsIgnoreCase(paramToIgnore))) { - keysToRemove.add(key); - } - } - - Map result = instanceParams.get(0).entrySet().stream() - .filter(entry->!keysToRemove.contains(entry.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - return result.isEmpty() ? Collections.emptyList() : Collections.singletonList(result); - } - - private ServiceInstantiationVnfList createServiceInstantiationVnfList(ServiceInstantiation payload) { - CloudConfiguration cloudConfiguration = generateCloudConfiguration(payload.getLcpCloudRegionId(), payload.getTenantId()); - - Map vnfs = payload.getVnfs(); - List vnfList = new ArrayList<>(); - for (Vnf vnf : vnfs.values()) { - Map> vfModules = vnf.getVfModules(); - List convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules); - List filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules); - ServiceInstantiationVnf serviceInstantiationVnf = new ServiceInstantiationVnf( - vnf.getModelInfo(), - cloudConfiguration, - vnf.getPlatformName(), - vnf.getLineOfBusiness(), - payload.getProductFamilyId(), - buildVnfInstanceParams(vnf.getInstanceParams(), filteredVfModules), - filteredVfModules, - getUniqueNameIfNeeded(vnf.getInstanceName(), ResourceType.GENERIC_VNF) - ); - vnfList.add(serviceInstantiationVnf); - } - - return new ServiceInstantiationVnfList(vnfList); - } - - private List convertVfModuleMapToList(Map> vfModules) { - ObjectMapper mapper = new ObjectMapper(); - return vfModules.values().stream().flatMap(vfModule -> - vfModule.values().stream().map(item -> { - List> aggregatedParams = aggregateAllInstanceParams(extractActualInstanceParams(item.getInstanceParams()), item.getSupplementaryParams()); - List> aggregatedParamsConverted = mapper.convertValue(aggregatedParams, new TypeReference>(){}); - - return new VfModuleMacro( - item.getModelInfo(), - item.getInstanceName(), - item.getVolumeGroupInstanceName(), - aggregatedParamsConverted); - } - ) - ).collect(Collectors.toList()); - } - - private List filterInstanceParamsFromVfModuleAndUniqueNames(List unFilteredVfModules) { - return unFilteredVfModules.stream().map(vfModule -> - new VfModuleMacro( - vfModule.getModelInfo(), - getUniqueNameIfNeeded(vfModule.getInstanceName(), ResourceType.VF_MODULE), - getUniqueNameIfNeeded(vfModule.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP), - removeUnNeededParams(vfModule.getInstanceParams()))) - .collect(Collectors.toList()); - } - - private String getUniqueNameIfNeeded(String name, ResourceType resourceType) { - return StringUtils.isNotEmpty(name) ? getUniqueName(name, resourceType) : null; } @Override @@ -599,6 +263,13 @@ public class AsyncInstantiationBusinessLogicImpl implements replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); } + @Override + public String getVnfDeletionPath(String serviceInstanceId, String vnfInstanceId) { + return (MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE) + + '/' + vnfInstanceId) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId).replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); + } + @Override public String getNetworkInstantiationPath(String serviceInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE). @@ -612,6 +283,24 @@ public class AsyncInstantiationBusinessLogicImpl implements .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId); } + @Override + public String getVfModuleReplacePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId) + { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId) + .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId) + + "/" + vfModuleInstanceId + + "/replace"; + } + + @Override + public String getVfModuleDeletePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId) + .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId) + + "/" + vfModuleInstanceId; + } + @Override public String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE) @@ -625,79 +314,64 @@ public class AsyncInstantiationBusinessLogicImpl implements } @Override - public String getInstanceGroupDeletePath(String instanceGroupId) { + public String getInstanceGroupMemberInstantiationPath(String vnfGroupInstanceId) { return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) - + '/' + instanceGroupId; + + '/' + vnfGroupInstanceId + "/addMembers"; } @Override - public String getOrchestrationRequestsPath() { - return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ); + public String getInstanceGroupDeletePath(String instanceGroupId) { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) + + '/' + instanceGroupId; } @Override - public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater) { - ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID); - serviceUpdater.accept(serviceInfo); - dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap()); - return serviceInfo; + public String getInstanceGroupMemberDeletePath(String vnfGroupInstanceId){ + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP) + + '/' + vnfGroupInstanceId + "/removeMembers"; } @Override - public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) { - auditVidStatus(jobUuid,jobStatus); - return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus)); - } - - private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) { - serviceInfo.setJobStatus(jobStatus); - serviceInfo.setStatusModifiedDate(new Date()); - } - - public ServiceInfo getServiceInfoByJobId(UUID jobUUID) { - List serviceInfoList = dataAccessService.getList(ServiceInfo.class, String.format(" where jobId = '%s' ", jobUUID), null, null); - if (serviceInfoList.size() != 1) { - throw new GenericUncheckedException("Failed to retrieve job with uuid " + jobUUID + " from ServiceInfo table. Instances found: " + serviceInfoList.size()); - } - return serviceInfoList.get(0); + public String getNetworkDeletePath(String serviceInstanceId, String networkInstanceId) { + return (MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE) + + "/" + networkInstanceId) + .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId); } - public List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) { - return dataAccessService.getList( - JobAuditStatus.class, - String.format(" where SOURCE = '%s' and JOB_ID = '%s'",source, jobUUID), - " CREATED_DATE ", null); - } - - private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){ - List list = getAuditStatuses(jobUUID,source); - return !list.isEmpty() ? list.get(list.size()-1) : null; + @Override + public String getResumeRequestPath(String requestId) { + return MsoBusinessLogicImpl.validateEndpointPath("mso.restapi.resume.orc.req") + .replaceFirst("", requestId); } @Override - public void auditVidStatus(UUID jobUUID, JobStatus jobStatus){ - JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID); - auditStatus(vidStatus); + public String getOrchestrationRequestsPath() { + return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ); } @Override - public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){ - auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage()); + public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer serviceUpdater) { + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); + serviceUpdater.accept(serviceInfo); + asyncInstantiationRepository.saveServiceInfo(serviceInfo); + return serviceInfo; } @Override - public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){ - JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO, - requestId != null ? UUID.fromString(requestId) : null, - additionalInfo); - auditStatus(msoStatus); + public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) { + auditService.auditVidStatus(jobUuid, jobStatus); + return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus)); } - private void auditStatus(JobAuditStatus jobAuditStatus){ - JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(), jobAuditStatus.getSource()); - if (latestStatus == null || !latestStatus.equals(jobAuditStatus)) - dataAccessService.saveDomainObject(jobAuditStatus, DaoUtils.getPropsMap()); + private boolean isRetryEnabledForStatus(JobStatus jobStatus) { + return featureManager.isActive(Features.FLAG_1902_RETRY_JOB) && + (jobStatus==JobStatus.COMPLETED_WITH_ERRORS || jobStatus==JobStatus.FAILED); + } + private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) { + serviceInfo.setJobStatus(jobStatus); + serviceInfo.setStatusModifiedDate(new Date()); + serviceInfo.setRetryEnabled(isRetryEnabledForStatus(jobStatus)); } public Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus) { @@ -708,13 +382,8 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public void handleFailedInstantiation(UUID jobUUID) { - ServiceInfo serviceInfo = updateServiceInfoAndAuditStatus(jobUUID, JobStatus.FAILED); - List serviceInfoList = dataAccessService.getList( - ServiceInfo.class, - String.format(" where templateId = '%s' and jobStatus = '%s'", - serviceInfo.getTemplateId(), - JobStatus.PENDING), - null, null); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); + List serviceInfoList = asyncInstantiationRepository.getServiceInfoByTemplateIdAndJobStatus(serviceInfo.getTemplateId(), JobStatus.PENDING); serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED)); } @@ -727,16 +396,16 @@ public class AsyncInstantiationBusinessLogicImpl implements @Override public void hideServiceInfo(UUID jobUUID) { - ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID); + ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID); if (!serviceInfo.getJobStatus().isFinal()) { - String message = String.format( "jobId %s: Service status does not allow hide service, status = %s", + String message = String.format("jobId %s: Service status does not allow hide service, status = %s", serviceInfo.getJobId(), serviceInfo.getJobStatus()); logger.error(EELFLoggerDelegate.errorLogger, message); throw new OperationNotAllowedException(message); } serviceInfo.setHidden(true); - dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap()); + asyncInstantiationRepository.saveServiceInfo(serviceInfo); } @Override @@ -818,7 +487,84 @@ public class AsyncInstantiationBusinessLogicImpl implements } } - throw new MaxRetriesException("find unused name for "+name, getMaxRetriesGettingFreeNameFromAai()); + throw new MaxRetriesException("can't find unused name for "+name, getMaxRetriesGettingFreeNameFromAai()); + } + + @Override + public ServiceInstantiation prepareServiceToBeUnique(ServiceInstantiation serviceInstantiation) { + try { + ServiceInstantiation clonedServiceInstantiation = JACKSON_OBJECT_MAPPER.readValue( + JACKSON_OBJECT_MAPPER.writeValueAsBytes(serviceInstantiation), ServiceInstantiation.class); + clonedServiceInstantiation.setBulkSize(1); + return replaceAllTrackById(clonedServiceInstantiation); + } catch (IOException e) { + throw new GenericUncheckedException(e); + } + + } + + private T replaceAllTrackById(T resource) { + resource.setTrackById(UUID.randomUUID().toString()); + resource.getChildren().forEach(this::replaceAllTrackById); + return resource; + } + + @Override + public List retryJob(ServiceInstantiation request, UUID jobId, String userId ) { + updateServiceInfo(jobId, si->si.setRetryEnabled(false)); + return pushBulkJob(request, userId); + } + + @Override + public List retryJob(UUID jobId, String userId) { + ServiceInstantiation serviceInstantiationRequest = asyncInstantiationRepository.getJobRequest(jobId); + enrichBulkForRetry(serviceInstantiationRequest, jobId); + + try { + logger.debug(EELFLoggerDelegate.debugLogger, "retry ServiceInstantiation request: "+ + JACKSON_OBJECT_MAPPER.writeValueAsString(serviceInstantiationRequest)); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, "failed to log retry of ServiceInstantiation request ", e); + } + return retryJob(serviceInstantiationRequest, jobId, userId); + } + + @Override + public ServiceInstantiation getBulkForRetry(UUID jobId) { + return enrichBulkForRetry( asyncInstantiationRepository.getJobRequest(jobId), jobId); + } + + @Override + public void addResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, String instanceId) { + String trackById = ((BaseResource) sharedData.getRequest()).getTrackById(); + ResourceInfo resourceInfo = new ResourceInfo(trackById, sharedData.getRootJobId(), instanceId, jobStatus, null); + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + @Override + public void addFailedResourceInfo(JobSharedData sharedData, RestObject msoResponse) { + String trackById = ((BaseResource) sharedData.getRequest()).getTrackById(); + String errorMessage = MsoUtil.formatExceptionAdditionalInfo(msoResponse.getStatusCode(), msoResponse.getRaw()); + AsyncRequestStatus asyncRequestStatus = convertMessageToAsyncRequestStatus(errorMessage); + ResourceInfo resourceInfo = new ResourceInfo(trackById, sharedData.getRootJobId(), null, JobStatus.FAILED, asyncRequestStatus); + + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + @Override + public void updateResourceInfo(JobSharedData sharedData, JobStatus jobStatus, AsyncRequestStatus message) { + ResourceInfo resourceInfo = asyncInstantiationRepository.getResourceInfoByTrackId(((BaseResource) sharedData.getRequest()).getTrackById()); + resourceInfo.setJobStatus(jobStatus); + if (jobStatus.isFailure()) { + resourceInfo.setErrorMessage(message); + } + asyncInstantiationRepository.saveResourceInfo(resourceInfo); + } + + public AsyncRequestStatus convertMessageToAsyncRequestStatus(String message) { + RequestStatus requestStatus = new RequestStatus("FAILED", message, TimeUtils.zonedDateTimeToString(ZonedDateTime.now())); + AsyncRequestStatus.Request request = new AsyncRequestStatus.Request(requestStatus); + return new AsyncRequestStatus(request); } protected String getUniqueNameFromDbOnly(String name) { @@ -835,4 +581,35 @@ public class AsyncInstantiationBusinessLogicImpl implements return !aaiClient.isNodeTypeExistsByName(name, resourceType); } + @Override + public ServiceInstantiation enrichBulkForRetry(ServiceInstantiation serviceInstantiation, UUID jobId){ + Map resourceInfoByTrackId = asyncInstantiationRepository.getResourceInfoByRootJobId(jobId); + + return setResourceStatus(resourceInfoByTrackId, serviceInstantiation); + } + + protected String readStatusMsg(ResourceInfo resourceInfo){ + if(resourceInfo!=null && resourceInfo.getErrorMessage()!=null && resourceInfo.getErrorMessage().request != null &&resourceInfo.getErrorMessage().request.requestStatus != null ) { + return resourceInfo.getErrorMessage().request.requestStatus.getStatusMessage(); + } + return null; + } + + private T setResourceStatus(Map resourceInfoByTrackId, T resource) { + ResourceInfo resourceInfo = resourceInfoByTrackId.get(resource.getTrackById()); + if(resourceInfo != null) { + boolean failed = resourceInfo.getJobStatus().isFailure(); + resource.setIsFailed(failed); + resource.setStatusMessage(readStatusMsg(resourceInfo)); + if (!failed) { + // if(resource.getAction().equals(Action.Delete)){ + // TODO not yet implemented- completed after delete should remove the node + resource.setAction(Action.None); + resource.setInstanceId(resourceInfo.getInstanceId()); + } + } + resource.getChildren().forEach(child -> setResourceStatus(resourceInfoByTrackId, child)); + return resource; + } + } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java b/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java index ef60c321d..6370b1862 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AuditService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AuditService.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,19 +20,31 @@ package org.onap.vid.services; -import org.onap.vid.model.JobAuditStatus; - import java.util.List; import java.util.UUID; +import org.onap.vid.job.Job; +import org.onap.vid.model.JobAuditStatus; +import org.onap.vid.mso.rest.AsyncRequestStatus; public interface AuditService { void setFailedAuditStatusFromMso(UUID jobUuid, String requestId, int statusCode, String msoResponse); - List getAuditStatusFromMsoByRequestId(UUID jobId, UUID requestId); - List getAuditStatusFromMsoByServiceInstanceId(UUID jobId, UUID serviceInstanceId); + List getAuditStatusFromMsoByInstanceId(JobAuditStatus.ResourceTypeFilter resourceTypeFilter, UUID instanceId, UUID jobId); List getAuditStatusFromMsoByJobId(UUID jobId); + + void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus); + + void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus); + + void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo); + + List retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(String instanceId, String requestType, String modelType); + + List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source); + + JobAuditStatus getResourceAuditStatus(String trackById); } diff --git a/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java index 7fb126e23..287a771d3 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/AuditServiceImpl.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,22 +20,20 @@ package org.onap.vid.services; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.lang3.StringUtils; -import org.onap.vid.exceptions.GenericUncheckedException; +import static org.apache.commons.lang3.ObjectUtils.notEqual; + +import org.jetbrains.annotations.NotNull; +import org.onap.vid.dal.AsyncInstantiationRepository; +import org.onap.vid.job.Job; import org.onap.vid.model.JobAuditStatus; -import org.onap.vid.mso.MsoBusinessLogicImpl; -import org.onap.vid.mso.MsoProperties; -import org.onap.vid.mso.RestMsoImplementation; -import org.onap.vid.mso.RestObject; +import org.onap.vid.mso.*; import org.onap.vid.mso.rest.AsyncRequestStatus; import org.onap.vid.mso.rest.AsyncRequestStatusList; import org.springframework.stereotype.Service; import javax.inject.Inject; -import java.io.IOException; import java.util.List; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; @@ -43,41 +41,20 @@ import java.util.stream.Collectors; @Service public class AuditServiceImpl implements AuditService{ - private final AsyncInstantiationBusinessLogic asyncInstantiationBL; private final RestMsoImplementation restMso; + private final AsyncInstantiationRepository asyncInstantiationRepository; @Inject - public AuditServiceImpl(AsyncInstantiationBusinessLogic asyncInstantiationBL, RestMsoImplementation restMso) { - this.asyncInstantiationBL = asyncInstantiationBL; + public AuditServiceImpl(RestMsoImplementation restMso, AsyncInstantiationRepository asyncInstantiationRepository) { this.restMso = restMso; + this.asyncInstantiationRepository = asyncInstantiationRepository; } @Override public void setFailedAuditStatusFromMso(UUID jobUuid, String requestId, int statusCode, String msoResponse){ final String failedMsoRequestStatus = "FAILED"; - String additionalInfo = formatExceptionAdditionalInfo(statusCode, msoResponse); - asyncInstantiationBL.auditMsoStatus(jobUuid, failedMsoRequestStatus, requestId, additionalInfo); - } - - private String formatExceptionAdditionalInfo(int statusCode, String msoResponse) { - String errorMsg = "Http Code:" + statusCode; - if (!StringUtils.isEmpty(msoResponse)) { - String filteredJson; - try { - ObjectMapper objectMapper = new ObjectMapper(); - filteredJson = StringUtils.defaultIfEmpty( - objectMapper.readTree(msoResponse).path("serviceException").toString().replaceAll("[\\{\\}]","") , - msoResponse - ); - } catch (JsonParseException e) { - filteredJson = msoResponse; - } catch (IOException e) { - throw new GenericUncheckedException(e); - } - - errorMsg = errorMsg + ", " + filteredJson; - } - return errorMsg; + String additionalInfo = MsoUtil.formatExceptionAdditionalInfo(statusCode, msoResponse); + auditMsoStatus(jobUuid, failedMsoRequestStatus, requestId, additionalInfo); } @Override @@ -87,64 +64,133 @@ public class AuditServiceImpl implements AuditService{ } @Override - public List getAuditStatusFromMsoByServiceInstanceId(UUID jobId, UUID serviceInstanceId) { - String filter = "serviceInstanceId:EQUALS:" + serviceInstanceId; - return getAuditStatusFromMso(jobId, filter, serviceInstanceId); + public List getAuditStatusFromMsoByInstanceId(JobAuditStatus.ResourceTypeFilter resourceTypeFilter, UUID instanceId, UUID jobId) { + String filter = resourceTypeFilter.getFilterBy() + ":EQUALS:" + instanceId; + return getAuditStatusFromMso(jobId, filter, instanceId); } @Override public List getAuditStatusFromMsoByJobId(UUID jobId) { - List auditStatuses = asyncInstantiationBL.getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO); + List auditStatuses = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO); String instanceName = getInstanceNameFromServiceInfo(jobId); auditStatuses.stream().forEach(status -> - status.setInstanceName(instanceName) + status.setInstanceName(instanceName) ); return auditStatuses; } + @Override + public void auditVidStatus(UUID jobUUID, Job.JobStatus jobStatus){ + JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID); + auditStatus(vidStatus); + } + @Override + public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){ + auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage()); + } + + @Override + public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){ + JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO, + requestId != null ? UUID.fromString(requestId) : null, + additionalInfo); + auditStatus(msoStatus); + } - private List getAuditStatusFromMso(UUID jobId, String filter, UUID serviceInstanceId) { + private void auditStatus(JobAuditStatus jobAuditStatus){ + JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(), jobAuditStatus.getSource()); + if (notEqual(jobAuditStatus, latestStatus)) { + jobAuditStatus.setOrdinal(nextOrdinalAfter(latestStatus)); + asyncInstantiationRepository.addJobAudiStatus(jobAuditStatus); + } + } + + protected int nextOrdinalAfter(JobAuditStatus jobAuditStatus) { + return jobAuditStatus == null ? 0 : (jobAuditStatus.getOrdinal() + 1); + } + + private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){ + List list = getAuditStatuses(jobUUID, source); + return !list.isEmpty() ? list.get(list.size()-1) : null; + } + + public List getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) { + return asyncInstantiationRepository.getAuditStatuses(jobUUID, source); + } + + @Override + //modelType is requestScope in MSO response + public List retrieveRequestsFromMsoByServiceIdAndRequestTypeAndScope(String instanceId, String requestType, String modelType) { + String filter = JobAuditStatus.ResourceTypeFilter.SERVICE.getFilterBy() + ":EQUALS:" + instanceId; + List msoStatuses = getAsyncRequestStatusListFromMso(filter); + return msoStatuses.stream() + .filter(x -> Objects.equals(x.request.requestType, requestType) && Objects.equals(x.request.requestScope, modelType)) + .map(x -> x.request) + .collect(Collectors.toList()); + } + + private List getAuditStatusFromMso(UUID jobId, String filter, UUID instanceId) { + + List msoStatuses = getAsyncRequestStatusListFromMso(filter); + + //add service name from service info for each audit status (in case that serviceInstanceId is null all statuses belong to service) + String userInstanceName = (instanceId == null && jobId != null) ? getInstanceNameFromServiceInfo(jobId) : null; + return convertMsoResponseStatusToJobAuditStatus(msoStatuses, userInstanceName); + } + + @NotNull + private List getAsyncRequestStatusListFromMso(String filter) { String path = MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQS) + "filter=" + filter; RestObject msoResponse = restMso.GetForObject(path , AsyncRequestStatusList.class); if (msoResponse.getStatusCode() >= 400 || msoResponse.get() == null) { throw new BadResponseFromMso(msoResponse); } - - //add service name from service info for each audit status (in case that serviceInstanceId is null all statuses belong to service) - String userInstanceName = serviceInstanceId == null ? getInstanceNameFromServiceInfo(jobId): null; - return convertMsoResponseStatusToJobAuditStatus(msoResponse.get().getRequestList(), userInstanceName); + return msoResponse.get().getRequestList(); } private String getInstanceNameFromServiceInfo(UUID jobId) { - return asyncInstantiationBL.getServiceInfoByJobId(jobId).getServiceInstanceName(); + return asyncInstantiationRepository.getServiceInfoByJobId(jobId).getServiceInstanceName(); } protected List convertMsoResponseStatusToJobAuditStatus(List msoStatuses, String defaultName){ - return msoStatuses.stream().map(status -> { - UUID requestId = null; - String instanceName = defaultName; - String jobStatus = null; - String additionalInfo = null; - String created = null; - String instanceType = null; - - AsyncRequestStatus.Request request = status.request; - if(request != null) { + return msoStatuses.stream().map(status -> + convertAsyncRequestStatusToJobAuditStatus(status, defaultName) + ).collect(Collectors.toList()); + } + + private JobAuditStatus convertAsyncRequestStatusToJobAuditStatus(AsyncRequestStatus status, String defaultName){ + if (status == null) { + return null; + } + + UUID requestId = null; + String instanceName = defaultName; + String jobStatus = null; + String additionalInfo = null; + String created = null; + String instanceType = null; + + AsyncRequestStatus.Request request = status.request; + if(request != null) { + if (request.requestId != null) { requestId = UUID.fromString(request.requestId); - instanceName = extractInstanceName(instanceName, request); - instanceType = request.requestScope; - if(request.requestStatus != null) { - jobStatus = request.requestStatus.getRequestState(); - additionalInfo = request.requestStatus.getStatusMessage(); - if(!request.requestStatus.getAdditionalProperties().isEmpty()) { - created = request.requestStatus.getAdditionalProperties().get("finishTime") != null? request.requestStatus.getAdditionalProperties().get("finishTime").toString() : request.requestStatus.getTimestamp(); - } + } + instanceName = extractInstanceName(instanceName, request); + instanceType = request.requestScope; + if(request.requestStatus != null) { + jobStatus = request.requestStatus.getRequestState(); + additionalInfo = request.requestStatus.getStatusMessage(); + if(!request.requestStatus.getAdditionalProperties().isEmpty() && + request.requestStatus.getAdditionalProperties().get("finishTime") != null) { + created = request.requestStatus.getAdditionalProperties().get("finishTime").toString(); + } else { + created = request.requestStatus.getTimestamp(); } } - return new JobAuditStatus(instanceName, jobStatus, requestId, additionalInfo, created, instanceType); - }).collect(Collectors.toList()); + } + return new JobAuditStatus(instanceName, jobStatus, requestId, additionalInfo, created, instanceType); } private String extractInstanceName(String instanceName, AsyncRequestStatus.Request request) { @@ -154,6 +200,13 @@ public class AuditServiceImpl implements AuditService{ return instanceName; } + @Override + public JobAuditStatus getResourceAuditStatus(String trackById) { + AsyncRequestStatus asyncRequestStatus = asyncInstantiationRepository.getResourceInfoByTrackId(trackById).getErrorMessage(); + return convertAsyncRequestStatusToJobAuditStatus(asyncRequestStatus, null); + } + + public static class BadResponseFromMso extends RuntimeException { private final RestObject msoResponse; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java index 199fff0c7..f6b82c734 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/CloudOwnerService.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/services/RoleGenaratorServiceImpl.java b/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java index 790dbfa55..a24a72e46 100644 --- a/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java +++ b/vid-app-common/src/main/java/org/onap/vid/services/RoleGenaratorServiceImpl.java @@ -71,7 +71,7 @@ public class RoleGenaratorServiceImpl implements RoleGeneratorService { String availableRoles=""; HashMap servicesNames = new HashMap<>(); for (Subscriber subscriber: subscribers.customer) { - AaiResponse subscriberResponse = client.getSubscriberData(subscriber.globalCustomerId); + AaiResponse subscriberResponse = client.getSubscriberData(subscriber.globalCustomerId, true); for(ServiceSubscription service: subscriberResponse.getT().serviceSubscriptions.serviceSubscription) { servicesNames.put(service.serviceType,""); String roleName = "'" + subscriber.subscriberName + ModelConstants.ROLE_DELIMITER + service.serviceType + "'"; diff --git a/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt b/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt new file mode 100644 index 000000000..2fb3e0c08 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/services/VersionService.kt @@ -0,0 +1,66 @@ +package org.onap.vid.services + +import com.fasterxml.jackson.module.kotlin.readValue +import org.apache.commons.lang3.StringUtils +import org.apache.commons.lang3.StringUtils.substringAfterLast +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate +import org.onap.portalsdk.core.util.SystemProperties +import org.onap.vid.model.VersionAndFeatures +import org.onap.vid.utils.JACKSON_OBJECT_MAPPER +import org.springframework.stereotype.Service +import java.util.regex.Pattern +import javax.inject.Inject +import javax.servlet.ServletContext + +@Service +class VersionService +@Inject +constructor(internal var servletContext: ServletContext) { + + private val Logger = EELFLoggerDelegate.getLogger(VersionService::class.java) + + private val versionAndFeatures: VersionAndFeatures by lazy { + loadVersionAndFeatures() + } + + private fun readBuildNumber(): String { + val resource = servletContext.getResource("/app/vid/scripts/constants/version.json") + return JACKSON_OBJECT_MAPPER.readValue>(resource)["Version"]!! + } + + //protected so can be easily tested in UT + protected fun readFeatureSet(): String { + return SystemProperties.getProperty("features.set.filename") + } + + //protected so can be easily tested in UT + protected fun buildDisplayVersion(features: String, build: String): String { + val matcher = Pattern.compile("([^/]+?)(\\.features|$)").matcher(features) + val majorByFeatures = if (matcher.find()) matcher.group(1) else features + + val buildByVersion = StringUtils.defaultIfBlank(substringAfterLast(build, "."), build) + + return StringUtils.join(majorByFeatures, ".", buildByVersion) + } + + fun retrieveVersionAndFeatures(): VersionAndFeatures { + return try { + versionAndFeatures + } catch (exception: Exception) { + Logger.error("Failed to read build number or feature properties settings from version file", exception) + VersionAndFeatures.unknown + } + } + + private fun loadVersionAndFeatures(): VersionAndFeatures { + val featureSet = readFeatureSet(); + val build = readBuildNumber(); + val displayVersion = buildDisplayVersion(featureSet, build) + return VersionAndFeatures(featureSet, build, displayVersion) + } + + //might throw an exception + fun retrieveBuildNumber(): String { + return versionAndFeatures.build + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt b/vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt index 6866477c3..cf532624c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt +++ b/vid-app-common/src/main/java/org/onap/vid/utils/KotlinUtils.kt @@ -27,4 +27,4 @@ inline fun > getEnumFromMapOfStrings(map: Map, k return java.lang.Enum.valueOf(E::class.java, (map.getOrDefault(key, defaultValue.name) as String)) } -val JACKSON_OBJECT_MAPPER: ObjectMapper = jacksonObjectMapper() +@JvmField val JACKSON_OBJECT_MAPPER: ObjectMapper = jacksonObjectMapper() diff --git a/vid-app-common/src/main/java/org/onap/vid/utils/Tree.kt b/vid-app-common/src/main/java/org/onap/vid/utils/Tree.kt index 35e913d16..62453756f 100644 --- a/vid-app-common/src/main/java/org/onap/vid/utils/Tree.kt +++ b/vid-app-common/src/main/java/org/onap/vid/utils/Tree.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. @@ -41,6 +41,14 @@ data class Tree(private val root:Node) { } } + fun getChildrenDepth(): Int { + return getMaxDepth(root) - 1 + } + + private fun getMaxDepth(level:Node): Int { + return (level.children.map{getMaxDepth(it.value)}.max() ?: 0) + 1 + } + fun getSubTree(vararg path: T): Tree? { return getSubTree(path.asList()) } -- cgit 1.2.3-korg