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