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