Added oparent to sdc main
[sdc.git] / openecomp-be / lib / openecomp-sdc-validation-lib / openecomp-sdc-validation-impl / src / main / java / org / openecomp / sdc / validation / impl / validators / namingconvention / VirtualMachineInterfaceGuidelineValidator.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 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 package org.openecomp.sdc.validation.impl.validators.namingconvention;
21
22 import static org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes.CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE;
23 import static org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE;
24 import static org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes.NOVA_SERVER_RESOURCE_TYPE;
25
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Objects;
29 import java.util.Optional;
30 import java.util.Set;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
33
34 import org.openecomp.core.validation.ErrorMessageCode;
35 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
36 import org.openecomp.core.validation.types.GlobalValidationContext;
37 import org.openecomp.sdc.datatypes.error.ErrorLevel;
38 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
39 import org.openecomp.sdc.heat.datatypes.model.Resource;
40 import org.openecomp.sdc.heat.services.HeatConstants;
41 import org.openecomp.sdc.heat.services.HeatResourceUtil;
42 import org.openecomp.sdc.heat.services.HeatStructureUtil;
43 import org.openecomp.sdc.validation.ResourceValidator;
44 import org.openecomp.sdc.validation.ValidationContext;
45 import org.openecomp.sdc.validation.type.NamingConventionValidationContext;
46
47 public class VirtualMachineInterfaceGuidelineValidator implements ResourceValidator {
48   private static final ErrorMessageCode ERROR_CODE_VLAN_GUIDELINE1 = new ErrorMessageCode
49       ("VlANG1");
50   private static final ErrorMessageCode ERROR_CODE_VLAN_GUIDELINE2 = new ErrorMessageCode
51       ("VlANG2");
52   private static final ErrorMessageCode ERROR_CODE_VLAN_GUIDELINE3 = new ErrorMessageCode
53       ("VlANG3");
54
55
56   @Override
57   public void validate(String fileName, Map.Entry<String, Resource> resourceEntry,
58                        GlobalValidationContext globalContext, ValidationContext validationContext) {
59       NamingConventionValidationContext namingConventionValidationContext =
60           (NamingConventionValidationContext) validationContext;
61       Optional<Object> tagPropertyValue = getVlanTagPropertyValue(resourceEntry.getValue());
62
63       if (tagPropertyValue.isPresent()) {
64         validateModeledByResourceGroup(fileName, resourceEntry, globalContext,
65             namingConventionValidationContext);
66         validateSingleVirtualMachineInterfaceInFile(fileName, globalContext,
67             namingConventionValidationContext);
68         validateSubInterfaceNamingConvention(fileName, resourceEntry, globalContext);
69       }
70   }
71
72   private void validateModeledByResourceGroup(String fileName,
73                                               Map.Entry<String, Resource> resourceEntry,
74                                               GlobalValidationContext globalContext,
75                                               NamingConventionValidationContext namingConventionValidationContext) {
76
77     Object refsPropertyValue = resourceEntry.getValue().getProperties().get(HeatConstants.VMI_REFS_PROPERTY_NAME);
78     if (Objects.isNull(refsPropertyValue)) {
79       addViolationToContext(fileName, globalContext, ErrorLevel.WARNING, ERROR_CODE_VLAN_GUIDELINE1,
80           Messages.VLAN_GUIDELINE_VALIDATION_NOT_MODELED_THROUGH_RESOURCE_GROUP, resourceEntry.getKey());
81       return;
82     }
83     final boolean modeledThroughResourceGroup = isModeledThroughResourceGroup(fileName, globalContext,
84             namingConventionValidationContext, refsPropertyValue);
85     if (!modeledThroughResourceGroup) {
86       addViolationToContext(fileName, globalContext, ErrorLevel.WARNING, ERROR_CODE_VLAN_GUIDELINE1,
87           Messages.VLAN_GUIDELINE_VALIDATION_NOT_MODELED_THROUGH_RESOURCE_GROUP, resourceEntry.getKey());
88     }
89
90   }
91
92
93   private void validateSubInterfaceNamingConvention(String fileName, Map.Entry<String, Resource> resourceEntry,
94                                                     GlobalValidationContext globalContext) {
95     final String resourceId = resourceEntry.getKey();
96     final Optional<String> networkRole = HeatResourceUtil.extractNetworkRoleFromSubInterfaceId(resourceId, resourceEntry
97             .getValue().getType());
98     if (!networkRole.isPresent()) {
99       addViolationToContext(fileName, globalContext, ErrorLevel.WARNING, ERROR_CODE_VLAN_GUIDELINE3,
100           Messages.VLAN_GUIDELINE_VALIDATION_NAMING_CONVENTION, resourceId);
101     }
102   }
103
104   private void validateSingleVirtualMachineInterfaceInFile(String fileName,
105                                                            GlobalValidationContext globalContext,
106                                                            NamingConventionValidationContext
107                                                                namingConventionValidationContext) {
108     Set<String> forbiddenTypes = Stream.of(NOVA_SERVER_RESOURCE_TYPE.getHeatResource(),
109         NEUTRON_PORT_RESOURCE_TYPE.getHeatResource()).collect(Collectors.toSet());
110
111     final Map<String, Resource> resources =
112         namingConventionValidationContext.getHeatOrchestrationTemplate().getResources();
113
114     if ((countVlanResources(resources) > 1) || fileContainsNonVlanResources(resources,
115         forbiddenTypes)) {
116       addViolationToContext(fileName, globalContext, ErrorLevel.ERROR, ERROR_CODE_VLAN_GUIDELINE2,
117           Messages.VLAN_GUIDELINE_VALIDATION_SINGLE_VLAN, fileName);
118     }
119
120
121   }
122
123   private boolean fileContainsNonVlanResources(Map<String, Resource> resources,
124                                                Set<String> forbiddenTypes) {
125     for (Map.Entry<String, Resource> resourceEntry : resources.entrySet()) {
126       if (forbiddenTypes.contains(resourceEntry.getValue().getType())) {
127         return true;
128       }
129     }
130     return false;
131   }
132
133   private int countVlanResources(Map<String, Resource> resources) {
134     int numVlanResources = 0;
135     for (Map.Entry<String, Resource> resourceEntry : resources.entrySet()) {
136       final String resourceType = resourceEntry.getValue().getType();
137       if (resourceType.equals
138           (CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE.getHeatResource())) {
139         numVlanResources++;
140       }
141     }
142
143     return numVlanResources;
144   }
145
146
147   private void addViolationToContext(String fileName, GlobalValidationContext globalContext,
148                                      ErrorLevel error, ErrorMessageCode errorCodeVlanGuideline1,
149                                      Messages vlanGuidelineValidationNotModeledThroughResourceGroup,
150                                      String key) {
151     globalContext.addMessage(fileName, error, ErrorMessagesFormatBuilder
152         .getErrorWithParameters(errorCodeVlanGuideline1,
153             vlanGuidelineValidationNotModeledThroughResourceGroup.getErrorMessage(),
154             key));
155   }
156
157
158   private Optional<Object> getVlanTagPropertyValue(Resource resource) {
159     Object vmiProperties = resource.getProperties().get(HeatConstants.VMI_PROPERTIES_PROPERTY_NAME);
160     if (Objects.nonNull(vmiProperties) && vmiProperties instanceof Map) {
161       return Optional.ofNullable(((Map) vmiProperties)
162           .get(HeatConstants.VMI_SUB_INTERFACE_VLAN_TAG_PROPERTY_NAME));
163     }
164     return Optional.empty();
165   }
166
167
168   /**
169    * This method verifies whether the propertyValue is a list containing a single get_param
170    * whose value is string
171    *
172    * @param fileName                          on which the validation is currently run
173    * @param globalContext                     global validation context
174    * @param namingConventionValidationContext heat resource validation context
175    * @param propertyValue                     the value which is examined
176    * @return whether  the propertyValue is a list containing a single get_param
177    * whose value is string
178    */
179   private static boolean isModeledThroughResourceGroup(String fileName, GlobalValidationContext
180       globalContext, NamingConventionValidationContext namingConventionValidationContext,
181                                                        Object propertyValue) {
182     final boolean isList = propertyValue instanceof List;
183     if (!isList || ((List) propertyValue).size() != 1) {
184       return false;
185     }
186
187     final Object listValue = ((List) propertyValue).get(0);
188
189     final Set<String> getParamValues =
190         HeatStructureUtil.getReferencedValuesByFunctionName(fileName, "get_param",
191             listValue, globalContext);
192     if (getParamValues.isEmpty()) {
193       return false; //this is not a get_param
194     }
195
196     //validating get_param value
197     return (getParamValues.size() == 1) &&
198         validateGetParamValueOfType(getParamValues, namingConventionValidationContext,
199             DefinedHeatParameterTypes.STRING.getType());
200
201   }
202
203   private static boolean validateGetParamValueOfType(Set<String> values,
204                                                      NamingConventionValidationContext
205                                                          namingConventionValidationContext,
206                                                      String type) {
207
208     return values.stream().anyMatch(e -> Objects.equals(
209         namingConventionValidationContext.getHeatOrchestrationTemplate().getParameters().get(e)
210             .getType(), type));
211   }
212
213
214
215   private enum Messages {
216     VLAN_GUIDELINE_VALIDATION_NOT_MODELED_THROUGH_RESOURCE_GROUP("VLAN Resource will not be " +
217         "translated as the VLAN Sub-interface [%s] is not modeled as resource group"),
218     VLAN_GUIDELINE_VALIDATION_SINGLE_VLAN("There should not be any Compute Server Node, Port, " +
219         "Parent Port in nested file [%s]"),
220     VLAN_GUIDELINE_VALIDATION_NAMING_CONVENTION(
221         "Network role associated with VLAN Sub-interface id[%s] is not following the naming convention");
222
223     private final String errorMessage;
224
225     Messages(String errorMessage) {
226       this.errorMessage = errorMessage;
227     }
228
229     String getErrorMessage() {
230       return errorMessage;
231     }
232   }
233
234
235 }