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