Don't use EELFLoggerDelegate.errorLogger in Async jobs
[vid.git] / vid-app-common / src / main / java / org / onap / vid / job / command / VfmoduleCommand.kt
1 package org.onap.vid.job.command
2
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 java.util.*
20
21 typealias ToscaVfm = org.onap.vid.model.VfModule
22
23 @Component
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 {
36
37     companion object {
38         private val LOGGER = EELFLoggerDelegate.getLogger(VfmoduleCommand::class.java)
39     }
40
41     override fun createChildren(): Job.JobStatus {
42         return Job.JobStatus.COMPLETED_WITH_NO_ACTION
43     }
44
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)
51
52          val instantiatePath = asyncInstantiationBL.getVfmoduleInstantiationPath(serviceInstanceId, vnfInstanceId)
53
54         val requestDetailsWrapper = msoRequestBuilder.generateVfModuleInstantiationRequest(
55                 request as VfModule,
56                 serviceModelInfo, serviceInstanceId, vnfModelInfo, vnfInstanceId, vgInstaceId, userId, testApi)
57
58         val actionDescription = "create vfmodule in $vnfInstanceId"
59
60         return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription)
61
62     }
63
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)
67
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")
72     }
73
74     override fun getRequest(): VfModule {
75         return sharedData.request as VfModule
76     }
77
78     override fun isDescendantHasAction(phase: Action): Boolean {
79         return false
80     }
81
82     private fun planReplaceMyselfRestCall(commandParentData: CommandParentData): MsoRestCallPlan {
83
84         val newestModel = fetchNewestServiceModel()
85
86         val serviceInstanceId = serviceInstanceIdFromRequest()
87         val vnfInstanceId = commandParentData.getInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID)
88
89         val (serviceModelInfo, vnfModelInfo, vfmModelInfo) = newestSelector(newestModel, commandParentData);
90
91         val originalRequestWithNewestVfmModelInfo = getRequest().cloneWith(vfmModelInfo)
92
93         val requestDetailsWrapper = msoRequestBuilder.generateVfModuleReplaceRequest(
94                 originalRequestWithNewestVfmModelInfo, serviceModelInfo, serviceInstanceId,
95                 vnfModelInfo, vnfInstanceId, null, sharedData.userId, sharedData.testApi)
96
97
98         val replacePath = asyncInstantiationBL.getVfModuleReplacePath(serviceInstanceId, vnfInstanceId, getRequest().instanceId)
99
100         return MsoRestCallPlan(HttpMethod.POST, replacePath, Optional.of(requestDetailsWrapper), Optional.of(sharedData.userId),
101                 "replace vfmodule ${getRequest().instanceId}")
102     }
103
104     data class ModelsInfoTriplet(val serviceModelInfo: ModelInfo, val vnfModelInfo: ModelInfo, val vfmModelInfo: ModelInfo)
105
106     private fun newestSelector(newestModel: ServiceModel, commandParentData: CommandParentData): ModelsInfoTriplet {
107         try {
108             return ModelsInfoTriplet(
109                     newestServiceModelInfo(newestModel),
110                     newestVnfModelInfo(newestModel, commandParentData),
111                     newestVfmModelInfo(newestModel)
112             )
113         } catch (e: Exception) {
114             throw GenericUncheckedException("Cannot upgrade ${serviceModelInfoFromRequest()} to ${newestModel.service}", e)
115         }
116     }
117
118     private fun newestServiceModelInfo(newestModel: ServiceModel) = toModelInfo(newestModel.service)
119
120     private fun newestVfmModelInfo(newestModel: ServiceModel): ModelInfo {
121         val vfmModelInfo = getRequest().modelInfo
122         val matchingVfm = selectVfm(newestModel, vfmModelInfo)
123         return toModelInfo(matchingVfm)
124     }
125
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)
130     }
131
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 }
135             }
136
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 }
140             }
141
142     private fun <T: Any> exactlyOne(predicateDescription: String, itemSupplier: () -> T): T {
143         return try {
144             itemSupplier.invoke()
145         } catch (cause: Exception) {
146             throw IllegalStateException("Cannot match ${predicateDescription}: ${cause.localizedMessage}", cause)
147         }
148     }
149
150     private fun toModelInfo(toBeConverted: VNF): ModelInfo = toModelInfo(toBeConverted, "vnf")
151
152     private fun toModelInfo(toBeConverted: ToscaVfm): ModelInfo = toModelInfo(toBeConverted, "vfModule")
153
154     private fun toModelInfo(toBeConverted: MinimalNode, modelType: String): ModelInfo {
155         val targetModelInfo = ModelInfo()
156
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
163
164         targetModelInfo.modelCustomizationId = when (toBeConverted) {
165             is VNF -> toBeConverted.customizationUuid
166             is ToscaVfm -> toBeConverted.customizationUuid
167             else -> throw IllegalArgumentException()
168         }
169
170         targetModelInfo.modelCustomizationName = when (toBeConverted) {
171             is VNF -> toBeConverted.modelCustomizationName
172             is ToscaVfm -> toBeConverted.modelCustomizationName
173             else -> throw IllegalArgumentException()
174         }
175
176         return targetModelInfo
177     }
178
179     internal fun toModelInfo(toBeConverted: Service): ModelInfo {
180         val targetModelInfo = ModelInfo()
181
182         targetModelInfo.modelVersionId = toBeConverted.uuid
183         targetModelInfo.modelInvariantId = toBeConverted.invariantUuid
184         targetModelInfo.modelVersion = toBeConverted.version
185         targetModelInfo.modelType = "service"
186         targetModelInfo.modelName = toBeConverted.name
187
188         return targetModelInfo
189     }
190
191     override fun replaceMyself(): Job.JobStatus {
192         try {
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
198         }
199     }
200
201     override fun isNeedToReplaceMySelf(): Boolean {
202         return getActionType() == Action.Upgrade
203     }
204
205     @Throws(IllegalStateException::class)
206     private fun fetchNewestServiceModel(): ServiceModel {
207         val serviceModelInfo = serviceModelInfoFromRequest()
208         val modelNewestUuid = commandUtils.getNewestModelUuid(serviceModelInfo.modelInvariantId);
209
210         val serviceNewestModel = commandUtils.getServiceModel(modelNewestUuid);
211
212         return serviceNewestModel;
213     }
214 }