1 package org.onap.vid.job.command
3 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate
4 import org.onap.vid.exceptions.GenericUncheckedException
5 import org.onap.vid.job.Job
6 import org.onap.vid.job.JobAdapter
7 import org.onap.vid.job.JobCommand
8 import org.onap.vid.job.JobsBrokerService
9 import org.onap.vid.model.*
10 import org.onap.vid.model.serviceInstantiation.VfModule
11 import org.onap.vid.mso.RestMsoImplementation
12 import org.onap.vid.mso.model.ModelInfo
13 import org.onap.vid.services.AsyncInstantiationBusinessLogic
14 import org.springframework.beans.factory.annotation.Autowired
15 import org.springframework.beans.factory.config.ConfigurableBeanFactory
16 import org.springframework.context.annotation.Scope
17 import org.springframework.http.HttpMethod
18 import org.springframework.stereotype.Component
21 typealias ToscaVfm = org.onap.vid.model.VfModule
24 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
25 class VfmoduleCommand @Autowired constructor(
26 private val asyncInstantiationBL: AsyncInstantiationBusinessLogic,
27 restMso: RestMsoImplementation,
28 private val msoRequestBuilder: MsoRequestBuilder,
29 msoResultHandlerService: MsoResultHandlerService,
30 inProgressStatusService:InProgressStatusService,
31 watchChildrenJobsBL: WatchChildrenJobsBL,
32 jobsBrokerService: JobsBrokerService,
33 jobAdapter: JobAdapter
34 ) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService,
35 watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand {
38 private val LOGGER = EELFLoggerDelegate.getLogger(VfmoduleCommand::class.java)
41 override fun createChildren(): Job.JobStatus {
42 return Job.JobStatus.COMPLETED_WITH_NO_ACTION
45 override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan {
46 val serviceInstanceId = serviceInstanceIdFromRequest()
47 val serviceModelInfo = serviceModelInfoFromRequest()
48 val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO)
49 val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID)
50 val vgInstaceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VG_INSTANCE_ID)
52 val instantiatePath = asyncInstantiationBL.getVfmoduleInstantiationPath(serviceInstanceId, vnfInstanceId)
54 val requestDetailsWrapper = msoRequestBuilder.generateVfModuleInstantiationRequest(
56 serviceModelInfo, serviceInstanceId, vnfModelInfo, vnfInstanceId, vgInstaceId, userId, testApi)
58 val actionDescription = "create vfmodule in $vnfInstanceId"
60 return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription)
64 override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan {
65 val serviceInstanceId = serviceInstanceIdFromRequest()
66 val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID)
68 val path = asyncInstantiationBL.getVfModuleDeletePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId)
69 val requestDetailsWrapper = msoRequestBuilder.generateDeleteVfModuleRequest(getRequest(), userId)
70 return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId),
71 "delete vfmodule ${getRequest().instanceId} from service instance $serviceInstanceId and vnf $vnfInstanceId")
74 override fun getRequest(): VfModule {
75 return sharedData.request as VfModule
78 override fun isDescendantHasAction(phase: Action): Boolean {
82 private fun planReplaceMyselfRestCall(commandParentData: CommandParentData): MsoRestCallPlan {
84 val newestModel = fetchNewestServiceModel()
86 val serviceInstanceId = serviceInstanceIdFromRequest()
87 val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID)
89 val (serviceModelInfo, vnfModelInfo, vfmModelInfo) = newestSelector(newestModel, commandParentData);
91 val originalRequestWithNewestVfmModelInfo = getRequest().cloneWith(vfmModelInfo)
93 val requestDetailsWrapper = msoRequestBuilder.generateVfModuleReplaceRequest(
94 originalRequestWithNewestVfmModelInfo, serviceModelInfo, serviceInstanceId,
95 vnfModelInfo, vnfInstanceId, null, sharedData.userId, sharedData.testApi)
98 val replacePath = asyncInstantiationBL.getVfModuleReplacePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId)
100 return MsoRestCallPlan(HttpMethod.POST, replacePath, Optional.of(requestDetailsWrapper), Optional.of(sharedData.userId),
101 "replace vfmodule ${getRequest().instanceId}")
104 data class ModelsInfoTriplet(val serviceModelInfo: ModelInfo, val vnfModelInfo: ModelInfo, val vfmModelInfo: ModelInfo)
106 private fun newestSelector(newestModel: ServiceModel, commandParentData: CommandParentData): ModelsInfoTriplet {
108 return ModelsInfoTriplet(
109 newestServiceModelInfo(newestModel),
110 newestVnfModelInfo(newestModel, commandParentData),
111 newestVfmModelInfo(newestModel)
113 } catch (e: Exception) {
114 throw GenericUncheckedException("Cannot upgrade ${serviceModelInfoFromRequest()} to ${newestModel.service}", e)
118 private fun newestServiceModelInfo(newestModel: ServiceModel) = toModelInfo(newestModel.service)
120 private fun newestVfmModelInfo(newestModel: ServiceModel): ModelInfo {
121 val vfmModelInfo = getRequest().modelInfo
122 val matchingVfm = selectVfm(newestModel, vfmModelInfo)
123 return toModelInfo(matchingVfm)
126 private fun newestVnfModelInfo(newestModel: ServiceModel, commandParentData: CommandParentData): ModelInfo {
127 val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO)
128 val matchingVnf = selectVnf(newestModel, vnfModelInfo)
129 return toModelInfo(matchingVnf)
132 internal fun selectVfm(serviceModel: ServiceModel, modelInfo: ModelInfo): ToscaVfm =
133 exactlyOne("vfModule for modelCustomizationName \"${modelInfo.modelCustomizationName}\"") {
134 serviceModel.vfModules.values.single { it.modelCustomizationName == modelInfo.modelCustomizationName }
137 internal fun selectVnf(serviceModel: ServiceModel, modelInfo: ModelInfo): VNF =
138 exactlyOne("VNF for modelCustomizationName \"${modelInfo.modelCustomizationName}\"") {
139 serviceModel.vnfs.values.single { it.modelCustomizationName == modelInfo.modelCustomizationName }
142 private fun <T: Any> exactlyOne(predicateDescription: String, itemSupplier: () -> T): T {
144 itemSupplier.invoke()
145 } catch (cause: Exception) {
146 throw IllegalStateException("Cannot match ${predicateDescription}: ${cause.localizedMessage}", cause)
150 private fun toModelInfo(toBeConverted: VNF): ModelInfo = toModelInfo(toBeConverted, "vnf")
152 private fun toModelInfo(toBeConverted: ToscaVfm): ModelInfo = toModelInfo(toBeConverted, "vfModule")
154 private fun toModelInfo(toBeConverted: MinimalNode, modelType: String): ModelInfo {
155 val targetModelInfo = ModelInfo()
157 targetModelInfo.modelType = modelType
158 targetModelInfo.modelName = toBeConverted.name
159 targetModelInfo.modelNameVersionId = null
160 targetModelInfo.modelVersion = toBeConverted.version
161 targetModelInfo.modelVersionId = toBeConverted.uuid
162 targetModelInfo.modelInvariantId = toBeConverted.invariantUuid
164 targetModelInfo.modelCustomizationId = when (toBeConverted) {
165 is VNF -> toBeConverted.customizationUuid
166 is ToscaVfm -> toBeConverted.customizationUuid
167 else -> throw IllegalArgumentException()
170 targetModelInfo.modelCustomizationName = when (toBeConverted) {
171 is VNF -> toBeConverted.modelCustomizationName
172 is ToscaVfm -> toBeConverted.modelCustomizationName
173 else -> throw IllegalArgumentException()
176 return targetModelInfo
179 internal fun toModelInfo(toBeConverted: Service): ModelInfo {
180 val targetModelInfo = ModelInfo()
182 targetModelInfo.modelVersionId = toBeConverted.uuid
183 targetModelInfo.modelInvariantId = toBeConverted.invariantUuid
184 targetModelInfo.modelVersion = toBeConverted.version
185 targetModelInfo.modelType = "service"
186 targetModelInfo.modelName = toBeConverted.name
188 return targetModelInfo
191 override fun replaceMyself(): Job.JobStatus {
193 val replaceMyselfCommand = planReplaceMyselfRestCall(commandParentData)
194 return executeAndHandleMsoInstanceRequest(replaceMyselfCommand)
195 } catch (exception: Exception) {
196 LOGGER.error("Failed to replace instanceId ${getRequest().instanceId} ", exception)
197 return Job.JobStatus.FAILED
201 override fun isNeedToReplaceMySelf(): Boolean {
202 return getActionType() == Action.Upgrade
205 @Throws(IllegalStateException::class)
206 private fun fetchNewestServiceModel(): ServiceModel {
207 val serviceModelInfo = serviceModelInfoFromRequest()
208 val modelNewestUuid = commandUtils.getNewestModelUuid(serviceModelInfo.modelInvariantId);
210 check(!modelNewestUuid.equals(serviceModelInfo.modelVersionId, true)) {
211 "Model version id ${serviceModelInfo.modelVersionId} is already the latest version of model's invariant id ${serviceModelInfo.modelInvariantId}" }
213 val serviceNewestModel = commandUtils.getServiceModel(modelNewestUuid);
215 return serviceNewestModel;