1 package org.openecomp.sdc.validation.impl.validators.namingconvention;
3 import org.openecomp.core.validation.ErrorMessageCode;
4 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
5 import org.openecomp.core.validation.types.GlobalValidationContext;
6 import org.openecomp.sdc.datatypes.error.ErrorLevel;
7 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
8 import org.openecomp.sdc.heat.datatypes.model.Resource;
9 import org.openecomp.sdc.heat.services.HeatConstants;
10 import org.openecomp.sdc.heat.services.HeatStructureUtil;
11 import org.openecomp.sdc.validation.ResourceValidator;
12 import org.openecomp.sdc.validation.ValidationContext;
13 import org.openecomp.sdc.validation.type.NamingConventionValidationContext;
15 import java.util.Arrays;
16 import java.util.List;
18 import java.util.Objects;
19 import java.util.Optional;
21 import java.util.stream.Collectors;
22 import java.util.stream.Stream;
24 import static org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes.CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE;
25 import static org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE;
26 import static org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes.NOVA_SERVER_RESOURCE_TYPE;
30 * @since February 05, 2018
33 public class VirtualMachineInterfaceGuidelineValidator implements ResourceValidator {
34 private static final ErrorMessageCode ERROR_CODE_VLAN_GUIDELINE1 = new ErrorMessageCode
36 private static final ErrorMessageCode ERROR_CODE_VLAN_GUIDELINE2 = new ErrorMessageCode
38 private static final ErrorMessageCode ERROR_CODE_VLAN_GUIDELINE3 = new ErrorMessageCode
40 private static final String UNDERSCORE = "_";
41 private static final String VMI = "vmi";
45 public void validate(String fileName, Map.Entry<String, Resource> resourceEntry,
46 GlobalValidationContext globalContext, ValidationContext validationContext) {
47 NamingConventionValidationContext namingConventionValidationContext =
48 (NamingConventionValidationContext) validationContext;
49 Optional<Object> tagPropertyValue = getVlanTagPropertyValue(resourceEntry.getValue());
51 if (tagPropertyValue.isPresent()) {
52 validateModeledByResourceGroup(fileName, resourceEntry, globalContext,
53 namingConventionValidationContext);
54 validateSingleVirtualMachineInterfaceInFile(fileName, globalContext,
55 namingConventionValidationContext);
56 validateNamingConvention(fileName, resourceEntry, globalContext
61 private void validateModeledByResourceGroup(String fileName,
62 Map.Entry<String, Resource> resourceEntry,
63 GlobalValidationContext globalContext,
64 NamingConventionValidationContext namingConventionValidationContext) {
66 Object refsPropertyValue = resourceEntry.getValue().getProperties()
67 .get(HeatConstants.VMI_REFS_PROPERTY_NAME);
68 if (Objects.isNull(refsPropertyValue)) {
69 addViolationToContext(fileName, globalContext, ErrorLevel.WARNING, ERROR_CODE_VLAN_GUIDELINE1,
70 Messages.VLAN_GUIDELINE_VALIDATION_NOT_MODELED_THROUGH_RESOURCE_GROUP,
71 resourceEntry.getKey());
74 final boolean modeledThroughResourceGroup =
75 isModeledThroughResourceGroup(fileName, globalContext,
76 namingConventionValidationContext,
78 if (!modeledThroughResourceGroup) {
79 addViolationToContext(fileName, globalContext, ErrorLevel.WARNING, ERROR_CODE_VLAN_GUIDELINE1,
80 Messages.VLAN_GUIDELINE_VALIDATION_NOT_MODELED_THROUGH_RESOURCE_GROUP,
81 resourceEntry.getKey());
87 private void validateNamingConvention(String fileName, Map.Entry<String, Resource>
88 resourceEntry, GlobalValidationContext globalContext) {
89 final String resourceId = resourceEntry.getKey();
90 final String networkRole = extractNetworkRoleFromResourceId(resourceId);
91 if (Objects.isNull(networkRole)) {
92 addViolationToContext(fileName, globalContext, ErrorLevel.WARNING, ERROR_CODE_VLAN_GUIDELINE3,
93 Messages.VLAN_GUIDELINE_VALIDATION_NAMING_CONVENTION, resourceId);
97 private void validateSingleVirtualMachineInterfaceInFile(String fileName,
98 GlobalValidationContext globalContext,
99 NamingConventionValidationContext
100 namingConventionValidationContext) {
101 Set<String> forbiddenTypes = Stream.of(NOVA_SERVER_RESOURCE_TYPE.getHeatResource(),
102 NEUTRON_PORT_RESOURCE_TYPE.getHeatResource()).collect(Collectors.toSet());
104 final Map<String, Resource> resources =
105 namingConventionValidationContext.getHeatOrchestrationTemplate().getResources();
107 if ((countVlanResources(resources) > 1) || fileContainsNonVlanResources(resources,
109 addViolationToContext(fileName, globalContext, ErrorLevel.ERROR, ERROR_CODE_VLAN_GUIDELINE2,
110 Messages.VLAN_GUIDELINE_VALIDATION_SINGLE_VLAN, fileName);
116 private boolean fileContainsNonVlanResources(Map<String, Resource> resources,
117 Set<String> forbiddenTypes) {
118 for (String resourceName : resources.keySet()) {
119 if (forbiddenTypes.contains(resources.get(resourceName).getType())) {
126 private int countVlanResources(Map<String, Resource> resources) {
127 int numVlanResources = 0;
128 for (String resourceName : resources.keySet()) {
129 final String resourceType = resources.get(resourceName).getType();
130 if (resourceType.equals
131 (CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE.getHeatResource())) {
136 return numVlanResources;
140 private void addViolationToContext(String fileName, GlobalValidationContext globalContext,
141 ErrorLevel error, ErrorMessageCode errorCodeVlanGuideline1,
142 Messages vlanGuidelineValidationNotModeledThroughResourceGroup,
144 globalContext.addMessage(fileName, error, ErrorMessagesFormatBuilder
145 .getErrorWithParameters(errorCodeVlanGuideline1,
146 vlanGuidelineValidationNotModeledThroughResourceGroup.getErrorMessage(),
151 private Optional<Object> getVlanTagPropertyValue(Resource resource) {
152 Object vmiProperties = resource.getProperties()
153 .get(HeatConstants.VMI_PROPERTIES_PROPERTY_NAME);
154 if (Objects.nonNull(vmiProperties) && vmiProperties instanceof Map) {
155 return Optional.ofNullable(((Map) vmiProperties)
156 .get(HeatConstants.VMI_SUB_INTERFACE_VLAN_TAG_PROPERTY_NAME));
158 return Optional.empty();
163 * This method verifies whether the propertyValue is a list containing a single get_param
164 * whose value is string
166 * @param fileName on which the validation is currently run
167 * @param globalContext global validation context
168 * @param namingConventionValidationContext heat resource validation context
169 * @param propertyValue the value which is examined
170 * @return whether the propertyValue is a list containing a single get_param
171 * whose value is string
173 private static boolean isModeledThroughResourceGroup(String fileName, GlobalValidationContext
174 globalContext, NamingConventionValidationContext namingConventionValidationContext,
175 Object propertyValue) {
176 final boolean isList = propertyValue instanceof List;
177 if (!isList || ((List) propertyValue).size() != 1) {
181 final Object listValue = ((List) propertyValue).get(0);
183 final Set<String> getParamValues =
184 HeatStructureUtil.getReferencedValuesByFunctionName(fileName, "get_param",
185 listValue, globalContext);
186 if (getParamValues.isEmpty()) {
187 return false; //this is not a get_param
190 //validating get_param value
191 return (getParamValues.size() == 1) &&
192 validateGetParamValueOfType(getParamValues, namingConventionValidationContext,
193 DefinedHeatParameterTypes.STRING.getType());
197 private static boolean validateGetParamValueOfType(Set<String> values,
198 NamingConventionValidationContext
199 namingConventionValidationContext,
202 return values.stream().anyMatch(e -> Objects.equals(
203 namingConventionValidationContext.getHeatOrchestrationTemplate().getParameters().get(e)
208 private static String extractNetworkRoleFromResourceId(String resourceId) {
210 List<String> splitSubInterfaceResourceId =
211 Arrays.asList(resourceId.toLowerCase().split(UNDERSCORE));
213 int vmiIndex = splitSubInterfaceResourceId.indexOf(VMI);
215 return splitSubInterfaceResourceId.get(vmiIndex - 1);
222 private enum Messages {
223 VLAN_GUIDELINE_VALIDATION_NOT_MODELED_THROUGH_RESOURCE_GROUP("VLAN Resource will not be " +
224 "translated as the VLAN Sub-interface [%s] is not modeled as resource group"),
225 VLAN_GUIDELINE_VALIDATION_SINGLE_VLAN("There should not be any Compute Server Node, Port, " +
226 "Parent Port in nested file [%s]"),
227 VLAN_GUIDELINE_VALIDATION_NAMING_CONVENTION(
228 "Network role associated with VLAN Sub-interface " +
230 "[%s] is not following the naming convention");
232 private final String errorMessage;
234 Messages(String errorMessage) {
235 this.errorMessage = errorMessage;
238 String getErrorMessage() {