identify macro services without instantiation type in BE by feature flag
[vid.git] / vid-app-common / src / main / java / org / onap / vid / asdc / parser / VidNotionsBuilder.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.vid.asdc.parser;
22
23 import static java.util.stream.Collectors.toSet;
24 import static org.apache.commons.lang3.StringUtils.equalsAnyIgnoreCase;
25 import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;
26 import static org.apache.commons.lang3.StringUtils.isEmpty;
27 import static org.hibernate.annotations.common.util.StringHelper.isNotEmpty;
28 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
29
30 import com.google.common.collect.ImmutableMap;
31 import java.io.IOException;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.UUID;
35 import java.util.stream.Stream;
36 import org.apache.commons.collections.MapUtils;
37 import org.apache.commons.lang3.StringUtils;
38 import org.jetbrains.annotations.NotNull;
39 import org.jetbrains.annotations.Nullable;
40 import org.onap.sdc.tosca.parser.api.ISdcCsarHelper;
41 import org.onap.sdc.toscaparser.api.NodeTemplate;
42 import org.onap.sdc.toscaparser.api.elements.Metadata;
43 import org.onap.vid.exceptions.GenericUncheckedException;
44 import org.onap.vid.model.ServiceModel;
45 import org.onap.vid.model.VidNotions;
46 import org.onap.vid.model.VidNotions.InstantiationType;
47 import org.onap.vid.model.VidNotions.InstantiationUI;
48 import org.onap.vid.model.VidNotions.ModelCategory;
49 import org.onap.vid.properties.Features;
50 import org.togglz.core.manager.FeatureManager;
51
52 public class VidNotionsBuilder {
53
54     private final FeatureManager featureManager;
55     private final Set<UUID> invariantToMacro;
56
57     //map of service type that are always macro services, and their relevant featureFlag
58     private static final Map<VidNotions.ModelCategory, Features> macroServicesByModelCategory = ImmutableMap.of(
59             VidNotions.ModelCategory.INFRASTRUCTURE_VPN, Features.FLAG_1908_INFRASTRUCTURE_VPN,
60             VidNotions.ModelCategory.Transport, Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI,
61             VidNotions.ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE, Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI
62     );
63
64     public VidNotionsBuilder(FeatureManager featureManager) {
65         this.featureManager = featureManager;
66         invariantToMacro = loadInvariantMacroUUIDsFromFile();
67     }
68
69     @NotNull
70     private Set<UUID> loadInvariantMacroUUIDsFromFile()  {
71         try {
72             return Stream.of(JACKSON_OBJECT_MAPPER.readValue(
73                         VidNotionsBuilder.class.getResource("/macro_services_by_invariant_uuid.json"),
74                         String[].class
75                     )).map(UUID::fromString).collect(toSet());
76         } catch (IOException e) {
77             throw new GenericUncheckedException(e);
78         }
79     }
80
81     VidNotions buildVidNotions(ISdcCsarHelper csarHelper, ServiceModel serviceModel) {
82         VidNotions.ModelCategory modelCategory = suggestModelCategory(csarHelper, serviceModel);
83         final InstantiationType instantiationType = suggestInstantiationType(serviceModel, modelCategory);
84         return new VidNotions(
85                 suggestInstantiationUI(csarHelper, serviceModel, modelCategory, instantiationType),
86                 modelCategory,
87                 suggestViewEditUI(csarHelper, serviceModel, modelCategory, instantiationType),
88                 instantiationType
89         );
90     }
91
92     private boolean isMacroTypeByModelCategory(VidNotions.ModelCategory modelCategory) {
93         Features featureOfMacroType = macroServicesByModelCategory.get(modelCategory);
94         //if featureOfMacroType is null this service is not a macro by its type
95         return (featureOfMacroType!=null && featureManager.isActive(featureOfMacroType));
96     }
97
98     InstantiationType suggestInstantiationType(ServiceModel serviceModel, VidNotions.ModelCategory modelCategory) {
99         if (isMacroTypeByModelCategory(modelCategory)) {
100             return InstantiationType.Macro;
101         }
102         if (serviceModel==null || serviceModel.getService()==null) {
103             return defaultInstantiationType();
104         }
105
106         if (StringUtils.equals(serviceModel.getService().getInstantiationType(), ToscaParserImpl2.Constants.MACRO)) {
107             return InstantiationType.Macro;
108         }
109
110         if (StringUtils.equals(serviceModel.getService().getInstantiationType(), ToscaParserImpl2.Constants.A_LA_CARTE)) {
111             return InstantiationType.ALaCarte;
112         }
113
114         if (!featureManager.isActive(Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND))
115             return InstantiationType.ClientConfig;
116
117         return isMacroByInvariantUuid(serviceModel.getService().getInvariantUuid()) ?
118             InstantiationType.Macro :
119             InstantiationType.ALaCarte;
120     }
121
122     @NotNull
123     private InstantiationType defaultInstantiationType() {
124         return featureManager.isActive(Features.FLAG_2002_IDENTIFY_INVARIANT_MACRO_UUID_BY_BACKEND) ?
125             InstantiationType.ALaCarte :
126             InstantiationType.ClientConfig;
127     }
128
129     //UI route a-la-carte services to old UI only if InstantiationUI is LEGACY
130     //So any other value for InstantiationUI other than LEGACY make UI to route
131     //a-la-carte services to new UI
132     VidNotions.InstantiationUI suggestInstantiationUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel, ModelCategory modelCategory, InstantiationType instantiationType) {
133         if(featureManager.isActive(Features.FLAG_EXP_ANY_ALACARTE_NEW_INSTANTIATION_UI) && isALaCarte(csarHelper)) {
134             return VidNotions.InstantiationUI.ANY_ALACARTE_NEW_UI;
135         }
136
137         if (featureManager.isActive(Features.FLAG_2002_ANY_ALACARTE_BESIDES_EXCLUDED_NEW_INSTANTIATION_UI) &&
138             !isMacro(instantiationType) &&
139             !isAlacarteExcludedByCategory(modelCategory)) {
140             return InstantiationUI.ANY_ALACARTE_WHICH_NOT_EXCLUDED;
141         }
142
143         if (featureManager.isActive(Features.FLAG_1902_VNF_GROUPING) && isGrouping(csarHelper)) {
144             return VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING;
145         }
146         if (featureManager.isActive(Features.FLAG_5G_IN_NEW_INSTANTIATION_UI)) {
147             VidNotions.InstantiationUI instantiationUI = determine5GInstantiationUI(csarHelper);
148             if ( instantiationUI != null ) return instantiationUI;
149         }
150         if (featureManager.isActive(Features.FLAG_1908_TRANSPORT_SERVICE_NEW_INSTANTIATION_UI) && isTransportService(csarHelper)){
151             return VidNotions.InstantiationUI.TRANSPORT_SERVICE;
152         }
153         if (featureManager.isActive(Features.FLAG_1908_COLLECTION_RESOURCE_NEW_INSTANTIATION_UI) && isServiceWithCollectionResource(serviceModel)){
154             return VidNotions.InstantiationUI.SERVICE_WITH_COLLECTION_RESOURCE;
155         }
156         if (featureManager.isActive(Features.FLAG_1908_INFRASTRUCTURE_VPN) && isInfraStructureVpn(csarHelper)){
157             return VidNotions.InstantiationUI.INFRASTRUCTURE_VPN;
158         }
159         if (featureManager.isActive(Features.FLAG_1908_A_LA_CARTE_VNF_NEW_INSTANTIATION_UI) && isVnfServiceRole(csarHelper)){
160             return VidNotions.InstantiationUI.A_LA_CARTE_VNF_SERVICE_ROLE;
161         }
162         return VidNotions.InstantiationUI.LEGACY;
163
164     }
165
166     private boolean isAlacarteExcludedByCategory(ModelCategory modelCategory) {
167         return modelCategory==ModelCategory.PORT_MIRRORING || modelCategory==ModelCategory.VLAN_TAGGING ;
168     }
169
170     private boolean isVnfServiceRole(ISdcCsarHelper csarHelper) {
171         final String serviceRole = csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_ROLE );
172         return StringUtils.equalsIgnoreCase("VNF" , serviceRole);
173     }
174
175     @Nullable
176     private VidNotions.InstantiationUI determine5GInstantiationUI(ISdcCsarHelper csarHelper) {
177         if (isUuidExactlyHardCoded1ffce89fef3f(csarHelper)) {
178             return VidNotions.InstantiationUI.SERVICE_UUID_IS_1ffce89f_ef3f_4cbb_8b37_82134590c5de;
179         } else if (isALaCarte(csarHelper) && hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(csarHelper)) {
180             return VidNotions.InstantiationUI.NETWORK_WITH_PROPERTY_NETWORK_TECHNOLOGY_EQUALS_STANDARD_SRIOV_OR_OVS;
181         } else if (isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) {
182             return VidNotions.InstantiationUI.SERVICE_WITH_FABRIC_CONFIGURATION;
183         }
184         return null;
185     }
186
187     private boolean isTransportService(ISdcCsarHelper csarHelper) {
188         return ("TRANSPORT".equalsIgnoreCase(csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_TYPE)));
189     }
190
191     private boolean isServiceWithCollectionResource(ServiceModel serviceModel){
192         return MapUtils.isNotEmpty(serviceModel.getCollectionResources());
193     }
194
195     private boolean isInfraStructureVpn(ISdcCsarHelper csarHelper) {
196         Metadata serviceMetadata = csarHelper.getServiceMetadata();
197         return ("BONDING".equalsIgnoreCase(serviceMetadata.getValue(ToscaParserImpl2.Constants.SERVICE_TYPE)) &&
198                 "INFRASTRUCTURE-VPN".equalsIgnoreCase(serviceMetadata.getValue(ToscaParserImpl2.Constants.SERVICE_ROLE)));
199     }
200
201     VidNotions.ModelCategory suggestModelCategory(ISdcCsarHelper csarHelper, ServiceModel serviceModel) {
202         if (isALaCarte(csarHelper) && hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(csarHelper)){
203             return VidNotions.ModelCategory.IS_5G_PROVIDER_NETWORK_MODEL;
204         }
205         if(isALaCarte(csarHelper) && hasFabricConfiguration(csarHelper)) {
206             return VidNotions.ModelCategory.IS_5G_FABRIC_CONFIGURATION_MODEL;
207         }
208         if (isPortMirroringService(serviceModel)) {
209             return ModelCategory.PORT_MIRRORING;
210         }
211         if (isVlanTaggingService(serviceModel)) {
212             return ModelCategory.VLAN_TAGGING;
213         }
214         if (isInfraStructureVpn(csarHelper)) {
215             return VidNotions.ModelCategory.INFRASTRUCTURE_VPN;
216         }
217         if (isTransportService(csarHelper)) {
218             return VidNotions.ModelCategory.Transport;
219         }
220         if (isServiceWithCollectionResource(serviceModel)) {
221             return VidNotions.ModelCategory.SERVICE_WITH_COLLECTION_RESOURCE;
222         }
223         return VidNotions.ModelCategory.OTHER;
224     }
225
226     VidNotions.InstantiationUI suggestViewEditUI(ISdcCsarHelper csarHelper, ServiceModel serviceModel, ModelCategory modelCategory, InstantiationType instantiationType) {
227         if (featureManager.isActive(Features.FLAG_1902_VNF_GROUPING) && isGrouping(csarHelper)) {
228             return VidNotions.InstantiationUI.SERVICE_WITH_VNF_GROUPING;
229         }
230
231         if (featureManager.isActive(Features.FLAG_1908_MACRO_NOT_TRANSPORT_NEW_VIEW_EDIT) &&
232             isMacro(instantiationType) &&
233             !isTransportService(csarHelper) &&
234             //till new view/edit would support fabric service activation
235             !hasFabricConfiguration(csarHelper)) {
236             return VidNotions.InstantiationUI.MACRO_SERVICE;
237         }
238
239         if (featureManager.isActive(Features.FLAG_1902_NEW_VIEW_EDIT)) {
240             VidNotions.InstantiationUI instantiationUISuggestion = suggestInstantiationUI(csarHelper, serviceModel, modelCategory, instantiationType);
241             if (instantiationUISuggestion!=VidNotions.InstantiationUI.LEGACY) {
242                 return instantiationUISuggestion;
243             }
244         }
245
246         return VidNotions.InstantiationUI.LEGACY;
247     }
248
249     private boolean isMacro(InstantiationType instantiationType) {
250         return instantiationType==InstantiationType.Macro;
251     }
252
253     private boolean isUuidExactlyHardCoded1ffce89fef3f(ISdcCsarHelper csarHelper) {
254         return equalsIgnoreCase(
255                 csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.UUID), "95eb2c44-bff2-4e8b-ad5d-8266870b7717");
256     }
257
258     private boolean hasAnyNetworkWithPropertyNetworkTechnologyEqualsStandardSriovOrOvs(ISdcCsarHelper csarHelper) {
259         return hasAnyNetworkWithPropertyEqualsToAnyOf(csarHelper, "network_technology","Standard-SR-IOV","OVS") ;
260     }
261
262     boolean hasFabricConfiguration(ISdcCsarHelper csarHelper) {
263         return csarHelper.getServiceNodeTemplates().stream()
264                 .flatMap(nodeTemplate -> csarHelper.getNodeTemplateChildren(nodeTemplate).stream())
265                 .anyMatch(child -> child.getType().equals(ToscaParserImpl2.Constants.FABRIC_CONFIGURATION_TYPE));
266     }
267
268     boolean hasAnyNetworkWithPropertyEqualsToAnyOf(ISdcCsarHelper csarHelper, String propertyName,  String... propertyValues) {
269         return csarHelper
270                 .getServiceVlList().stream()
271                 .map(NodeTemplate::getProperties)
272                 .flatMap(props -> props.entrySet().stream())
273                 .filter(prop -> equalsIgnoreCase(prop.getKey(), propertyName))
274                 // getValue().getValue() because value is Entry, where it's inner value is what we're looking for
275                 .anyMatch(prop -> equalsAnyIgnoreCase(prop.getValue().getValue().toString(), propertyValues));
276     }
277
278     boolean isALaCarte(ISdcCsarHelper csarHelper) {
279         final String instantiationType = csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.INSTANTIATION_TYPE);
280         return StringUtils.equalsIgnoreCase(instantiationType, ToscaParserImpl2.Constants.A_LA_CARTE);
281     }
282
283     boolean isMacroExcludedFromAsyncFlow(ServiceModel serviceModel) {
284         return (MapUtils.isNotEmpty(serviceModel.getPnfs()) ||
285                 MapUtils.isNotEmpty(serviceModel.getCollectionResources()) ||
286                 (MapUtils.isNotEmpty(serviceModel.getNetworks()) && !featureManager.isActive(Features.FLAG_NETWORK_TO_ASYNC_INSTANTIATION)));
287     }
288
289     private boolean isGrouping(ISdcCsarHelper csarHelper) {
290         final String serviceRole = csarHelper.getServiceMetadata().getValue(ToscaParserImpl2.Constants.SERVICE_ROLE);
291         return StringUtils.equalsIgnoreCase(serviceRole, ToscaParserImpl2.Constants.GROUPING);
292     }
293
294     private boolean isPortMirroringService(ServiceModel serviceModel) {
295         return (serviceModel.getService()!=null &&
296             StringUtils.equals(serviceModel.getService().getServiceType(), "PORT-MIRROR"));
297     }
298
299     private boolean isVlanTaggingService(ServiceModel serviceModel) {
300         if (serviceModel==null || serviceModel.getVnfs()==null) {
301             return false;
302         }
303
304         return serviceModel.getVnfs().values().stream().anyMatch(
305             vnf-> MapUtils.isNotEmpty(vnf.getVfcInstanceGroups())
306         );
307
308     }
309
310     protected boolean isMacroByInvariantUuid(String uuid) {
311         try {
312             return invariantToMacro.contains(UUID.fromString(uuid));
313         }
314         catch (IllegalArgumentException | NullPointerException e) { //not a uuid
315             return false;
316         }
317     }
318 }