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