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
19 import org.togglz.core.manager.FeatureManager
22 typealias ToscaVfm = org.onap.vid.model.VfModule
25 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
26 class VfmoduleCommand @Autowired constructor(
27 private val asyncInstantiationBL: AsyncInstantiationBusinessLogic,
28 restMso: RestMsoImplementation,
29 private val msoRequestBuilder: MsoRequestBuilder,
30 msoResultHandlerService: MsoResultHandlerService,
31 inProgressStatusService:InProgressStatusService,
32 watchChildrenJobsBL: WatchChildrenJobsBL,
33 jobsBrokerService: JobsBrokerService,
34 jobAdapter: JobAdapter,
35 featureManager: FeatureManager
36 ) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService,
37 watchChildrenJobsBL, jobsBrokerService, jobAdapter, featureManager), JobCommand {
40 private val LOGGER = EELFLoggerDelegate.getLogger(VfmoduleCommand::class.java)
43 override fun createChildren(): Job.JobStatus {
44 return Job.JobStatus.COMPLETED_WITH_NO_ACTION
47 override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan {
48 val serviceInstanceId = serviceInstanceIdFromRequest()
49 val serviceModelInfo = serviceModelInfoFromRequest()
50 val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO)
51 val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID)
52 val vgInstaceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VG_INSTANCE_ID)
54 val instantiatePath = asyncInstantiationBL.getVfmoduleInstantiationPath(serviceInstanceId, vnfInstanceId)
56 val requestDetailsWrapper = msoRequestBuilder.generateVfModuleInstantiationRequest(
58 serviceModelInfo, serviceInstanceId, vnfModelInfo, vnfInstanceId, vgInstaceId, userId, testApi)
60 val actionDescription = "create vfmodule in $vnfInstanceId"
62 return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription)
66 override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan {
67 val serviceInstanceId = serviceInstanceIdFromRequest()
68 val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID)
70 val path = asyncInstantiationBL.getVfModuleDeletePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId)
71 val requestDetailsWrapper = msoRequestBuilder.generateDeleteVfModuleRequest(getRequest(), userId)
72 return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId),
73 "delete vfmodule ${getRequest().instanceId} from service instance $serviceInstanceId and vnf $vnfInstanceId")
76 override fun getRequest(): VfModule {
77 return sharedData.request as VfModule
80 override fun isDescendantHasAction(phase: Action): Boolean {
84 private fun planReplaceMyselfRestCall(commandParentData: CommandParentData): MsoRestCallPlan {
86 val newestModel = fetchNewestServiceModel()
88 val serviceInstanceId = serviceInstanceIdFromRequest()
89 val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID)
91 val (serviceModelInfo, vnfModelInfo, vfmModelInfo) = newestSelector(newestModel, commandParentData);
93 val originalRequestWithNewestVfmModelInfo = getRequest().cloneWith(vfmModelInfo)
95 val requestDetailsWrapper = msoRequestBuilder.generateVfModuleReplaceRequest(
96 originalRequestWithNewestVfmModelInfo, serviceModelInfo, serviceInstanceId,
97 vnfModelInfo, vnfInstanceId, null, sharedData.userId, sharedData.testApi)
100 val replacePath = asyncInstantiationBL.getVfModuleReplacePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId)
102 return MsoRestCallPlan(HttpMethod.POST, replacePath, Optional.of(requestDetailsWrapper), Optional.of(sharedData.userId),
103 "replace vfmodule ${getRequest().instanceId}")
106 data class ModelsInfoTriplet(val serviceModelInfo: ModelInfo, val vnfModelInfo: ModelInfo, val vfmModelInfo: ModelInfo)
108 private fun newestSelector(newestModel: ServiceModel, commandParentData: CommandParentData): ModelsInfoTriplet {
110 return ModelsInfoTriplet(
111 newestServiceModelInfo(newestModel),
112 newestVnfModelInfo(newestModel, commandParentData),
113 newestVfmModelInfo(newestModel)
115 } catch (e: Exception) {
116 throw GenericUncheckedException("Cannot upgrade ${serviceModelInfoFromRequest()} to ${newestModel.service}", e)
120 private fun newestServiceModelInfo(newestModel: ServiceModel) = toModelInfo(newestModel.service)
122 private fun newestVfmModelInfo(newestModel: ServiceModel): ModelInfo {
123 val vfmModelInfo = getRequest().modelInfo
124 val matchingVfm = selectVfm(newestModel, vfmModelInfo)
125 return toModelInfo(matchingVfm)
128 private fun newestVnfModelInfo(newestModel: ServiceModel, commandParentData: CommandParentData): ModelInfo {
129 val vnfModelInfo = commandParentData.getModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO)
130 val matchingVnf = selectVnf(newestModel, vnfModelInfo)
131 return toModelInfo(matchingVnf)
134 internal fun selectVfm(serviceModel: ServiceModel, modelInfo: ModelInfo): ToscaVfm =
135 exactlyOne("vfModule for modelCustomizationName \"${modelInfo.modelCustomizationName}\"") {
136 serviceModel.vfModules.values.single { it.modelCustomizationName == modelInfo.modelCustomizationName }
139 internal fun selectVnf(serviceModel: ServiceModel, modelInfo: ModelInfo): VNF =
140 exactlyOne("VNF for modelCustomizationName \"${modelInfo.modelCustomizationName}\"") {
141 serviceModel.vnfs.values.single { it.modelCustomizationName == modelInfo.modelCustomizationName }
144 private fun <T: Any> exactlyOne(predicateDescription: String, itemSupplier: () -> T): T {
146 itemSupplier.invoke()
147 } catch (cause: Exception) {
148 throw IllegalStateException("Cannot match ${predicateDescription}: ${cause.localizedMessage}", cause)
152 private fun toModelInfo(toBeConverted: VNF): ModelInfo = toModelInfo(toBeConverted, "vnf")
154 private fun toModelInfo(toBeConverted: ToscaVfm): ModelInfo = toModelInfo(toBeConverted, "vfModule")
156 private fun toModelInfo(toBeConverted: MinimalNode, modelType: String): ModelInfo {
157 val targetModelInfo = ModelInfo()
159 targetModelInfo.modelType = modelType
160 targetModelInfo.modelName = toBeConverted.name
161 targetModelInfo.modelNameVersionId = null
162 targetModelInfo.modelVersion = toBeConverted.version
163 targetModelInfo.modelVersionId = toBeConverted.uuid
164 targetModelInfo.modelInvariantId = toBeConverted.invariantUuid
166 targetModelInfo.modelCustomizationId = when (toBeConverted) {
167 is VNF -> toBeConverted.customizationUuid
168 is ToscaVfm -> toBeConverted.customizationUuid
169 else -> throw IllegalArgumentException()
172 targetModelInfo.modelCustomizationName = when (toBeConverted) {
173 is VNF -> toBeConverted.modelCustomizationName
174 is ToscaVfm -> toBeConverted.modelCustomizationName
175 else -> throw IllegalArgumentException()
178 return targetModelInfo
181 internal fun toModelInfo(toBeConverted: Service): ModelInfo {
182 val targetModelInfo = ModelInfo()
184 targetModelInfo.modelVersionId = toBeConverted.uuid
185 targetModelInfo.modelInvariantId = toBeConverted.invariantUuid
186 targetModelInfo.modelVersion = toBeConverted.version
187 targetModelInfo.modelType = "service"
188 targetModelInfo.modelName = toBeConverted.name
190 return targetModelInfo
193 override fun replaceMyself(): Job.JobStatus {
195 val replaceMyselfCommand = planReplaceMyselfRestCall(commandParentData)
196 return executeAndHandleMsoInstanceRequest(replaceMyselfCommand)
197 } catch (exception: Exception) {
198 LOGGER.error("Failed to replace instanceId ${getRequest().instanceId} ", exception)
199 return Job.JobStatus.FAILED
203 override fun isNeedToReplaceMySelf(): Boolean {
204 return getActionType() == Action.Upgrade
207 @Throws(IllegalStateException::class)
208 private fun fetchNewestServiceModel(): ServiceModel {
209 val serviceModelInfo = serviceModelInfoFromRequest()
210 val modelNewestUuid = commandUtils.getNewestModelUuid(serviceModelInfo.modelInvariantId);
212 val serviceNewestModel = commandUtils.getServiceModel(modelNewestUuid);
214 return serviceNewestModel;