vfmodule tenant and region are dictated by parent VNF values
[vid.git] / vid-app-common / src / main / java / org / onap / vid / job / command / VnfCommand.kt
1 package org.onap.vid.job.command
2
3 import org.apache.commons.collections.MapUtils
4 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate
5 import org.onap.vid.asdc.AsdcCatalogException
6 import org.onap.vid.job.*
7 import org.onap.vid.job.impl.JobSharedData
8 import org.onap.vid.model.Action
9 import org.onap.vid.model.serviceInstantiation.BaseResource
10 import org.onap.vid.model.serviceInstantiation.VfModule
11 import org.onap.vid.model.serviceInstantiation.Vnf
12 import org.onap.vid.mso.RestMsoImplementation
13 import org.onap.vid.properties.Features
14 import org.onap.vid.services.AsyncInstantiationBusinessLogic
15 import org.onap.vid.utils.isNotActive
16 import org.springframework.beans.factory.annotation.Autowired
17 import org.springframework.beans.factory.config.ConfigurableBeanFactory
18 import org.springframework.context.annotation.Scope
19 import org.springframework.http.HttpMethod
20 import org.springframework.stereotype.Component
21 import org.togglz.core.manager.FeatureManager
22 import java.util.*
23 import java.util.stream.Collectors
24 import kotlin.properties.Delegates
25
26 const val NEED_TO_CREATE_BASE_MODULE = "needToCreateBaseModule"
27
28 @Component
29 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
30 class VnfCommand @Autowired constructor(
31         private val asyncInstantiationBL: AsyncInstantiationBusinessLogic,
32         restMso: RestMsoImplementation,
33         private val msoRequestBuilder: MsoRequestBuilder,
34         msoResultHandlerService: MsoResultHandlerService,
35         inProgressStatusService:InProgressStatusService,
36         watchChildrenJobsBL: WatchChildrenJobsBL,
37         jobsBrokerService: JobsBrokerService,
38         jobAdapter: JobAdapter,
39         private val featureManager: FeatureManager
40 ) : ResourceCommand(restMso, inProgressStatusService, msoResultHandlerService,
41         watchChildrenJobsBL, jobsBrokerService, jobAdapter), JobCommand {
42
43     private var needToCreateBaseModule:Boolean by Delegates.notNull<Boolean>()
44
45     override fun getData(): Map<String, Any?> {
46         return super.getData() + mapOf(NEED_TO_CREATE_BASE_MODULE to needToCreateBaseModule)
47     }
48
49     override fun init(sharedData: JobSharedData, commandData: Map<String, Any>): ResourceCommand {
50         super<ResourceCommand>.init(sharedData, commandData)
51         needToCreateBaseModule = commandData.getOrDefault(NEED_TO_CREATE_BASE_MODULE, actionPhase != Action.Delete) as Boolean
52         return this
53     }
54
55
56     override fun createChildren(): Job.JobStatus {
57         val request:Vnf = getRequest()
58         if(isNeedToCreateChildJobs()){
59             val dataForChild = buildDataForChild(request, actionPhase)
60             val vfModules:List<VfModule> = request.vfModules.values.stream().flatMap { vfKey -> vfKey.values.stream() }.collect(Collectors.toList<VfModule>())
61
62             try {
63                 childJobs = pushChildrenJobsToBroker(vfModulesForChildrenJobs(vfModules), dataForChild, JobType.VolumeGroupInstantiation)
64             } catch (e: AsdcCatalogException) {
65                 LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to retrieve service definitions from SDC, for VfModule is BaseModule.. Error: " + e.message, e)
66                 //return Job.JobStatus.FAILED
67                 throw e;
68             }
69         }
70
71         return Job.JobStatus.COMPLETED_WITH_NO_ACTION
72     }
73
74     private fun vfModulesForChildrenJobs(vfModules: List<VfModule>): List<VfModule> =
75             vfModules
76                     .filter { filterModuleByNeedToCreateBase(it) }
77                     .map { childVfModuleWithVnfRegionAndTenant(it) }
78
79     internal fun childVfModuleWithVnfRegionAndTenant(vfModule: VfModule): VfModule {
80         if (featureManager.isNotActive(Features.FLAG_2006_VFMODULE_TAKES_TENANT_AND_REGION_FROM_VNF)) {
81             return vfModule
82         }
83
84         val vnfLcpCloudRegionId = getRequest().lcpCloudRegionId
85         val vnfTenantId = getRequest().tenantId
86         return vfModule.cloneWith(vnfLcpCloudRegionId, vnfTenantId)
87     }
88
89     private fun filterModuleByNeedToCreateBase(vfModule: VfModule): Boolean {
90         return needToCreateBaseModule ==
91                 commandUtils.isVfModuleBaseModule(
92                         serviceModelInfoFromRequest().modelVersionId,
93                         vfModule.modelInfo.modelVersionId)
94     }
95
96     override fun planCreateMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String, testApi: String?): MsoRestCallPlan {
97         val serviceInstanceId = serviceInstanceIdFromRequest()
98
99         val instantiatePath = asyncInstantiationBL.getVnfInstantiationPath(serviceInstanceId)
100
101         val requestDetailsWrapper = msoRequestBuilder.generateVnfInstantiationRequest(
102                 request as Vnf,
103                 serviceModelInfoFromRequest(), serviceInstanceId,
104                 userId,
105                 testApi
106         )
107
108         val actionDescription = "create vnf in $serviceInstanceId"
109
110         return MsoRestCallPlan(HttpMethod.POST, instantiatePath, Optional.of(requestDetailsWrapper), Optional.empty(), actionDescription)
111
112     }
113
114     override fun addMyselfToChildrenData(commandParentData: CommandParentData, request: BaseResource) {
115         commandParentData.addModelInfo(CommandParentData.CommandDataKey.VNF_MODEL_INFO, request.modelInfo);
116         commandParentData.addInstanceId(CommandParentData.CommandDataKey.VNF_INSTANCE_ID, getActualInstanceId(request))
117     }
118
119     override fun getRequest(): Vnf {
120         return sharedData.request as Vnf
121     }
122
123     private fun isNeedToCreateChildJobs(): Boolean {
124         return featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE) &&
125                 MapUtils.isNotEmpty(getRequest().vfModules)
126     }
127
128     override fun planDeleteMyselfRestCall(commandParentData: CommandParentData, request: JobAdapter.AsyncJobRequest, userId: String): MsoRestCallPlan {
129         val serviceInstanceId = serviceInstanceIdFromRequest()
130         val path = asyncInstantiationBL.getVnfDeletionPath(serviceInstanceId, getRequest().instanceId)
131         val requestDetailsWrapper = msoRequestBuilder.generateDeleteVnfRequest(getRequest(), userId)
132         return MsoRestCallPlan(HttpMethod.DELETE, path, Optional.of(requestDetailsWrapper), Optional.of(userId),
133                 "delete vnf ${getRequest().instanceId} from service $serviceInstanceId")
134
135     }
136
137     companion object {
138         private val LOGGER = EELFLoggerDelegate.getLogger(VnfCommand::class.java)
139     }
140
141     //in Delete phase - we delete all non-base vf-modules first, before base vf-module
142     //in Create phase - we create base vf-module first, and then all the others
143     override fun watchChildren(): Job.JobStatus {
144         val childrenStatus:Job.JobStatus = comulateStatusAndUpdatePropertyIfFinal(watchChildrenJobsBL.retrieveChildrenJobsStatus(childJobs))
145         if (!childrenStatus.isFinal ||
146                 childrenStatus.isFailure ||
147                 (actionPhase == Action.Create && !needToCreateBaseModule) ||
148                 (actionPhase == Action.Delete && needToCreateBaseModule)) {
149             return childrenStatus
150         }
151
152         needToCreateBaseModule = !needToCreateBaseModule;
153         createChildren()
154         return Job.JobStatus.IN_PROGRESS
155     }
156 }