2 * Copyright © 2016-2017 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.validation.impl.validators.namingconvention;
19 import static java.util.Objects.nonNull;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Comparator;
25 import java.util.HashMap;
26 import java.util.LinkedList;
27 import java.util.List;
29 import java.util.Objects;
30 import java.util.TreeMap;
32 import org.apache.commons.collections4.MapUtils;
33 import org.apache.commons.lang3.tuple.ImmutablePair;
34 import org.apache.commons.lang3.tuple.Pair;
35 import org.openecomp.core.validation.ErrorMessageCode;
36 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
37 import org.openecomp.core.validation.types.GlobalValidationContext;
38 import org.openecomp.sdc.common.errors.Messages;
39 import org.openecomp.sdc.datatypes.error.ErrorLevel;
40 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
41 import org.openecomp.sdc.heat.datatypes.model.Environment;
42 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
43 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
44 import org.openecomp.sdc.heat.datatypes.model.Resource;
45 import org.openecomp.sdc.heat.datatypes.model.ResourceReferenceFunctions;
46 import org.openecomp.sdc.heat.services.HeatStructureUtil;
47 import org.openecomp.sdc.validation.ResourceValidator;
48 import org.openecomp.sdc.validation.ValidationContext;
49 import org.openecomp.sdc.validation.type.NamingConventionValidationContext;
50 import org.openecomp.sdc.validation.util.ValidationUtil;
52 public class NovaServerNamingConventionGuideLineValidator implements ResourceValidator {
53 private static final String AVAILABILITY_ZONE = "availability_zone";
54 private static final String SERVER = "Server";
55 private static final ErrorMessageCode ERROR_CODE_NNS1 = new ErrorMessageCode("NNS1");
56 private static final ErrorMessageCode ERROR_CODE_NNS2 = new ErrorMessageCode("NNS2");
57 private static final ErrorMessageCode ERROR_CODE_NNS3 = new ErrorMessageCode("NNS3");
58 private static final ErrorMessageCode ERROR_CODE_NNS4 = new ErrorMessageCode("NNS4");
59 private static final ErrorMessageCode ERROR_CODE_NNS5 = new ErrorMessageCode("NNS5");
60 private static final ErrorMessageCode ERROR_CODE_NNS6 = new ErrorMessageCode("NNS6");
61 private static final ErrorMessageCode ERROR_CODE_NNS7 = new ErrorMessageCode("NNS7");
62 private static final ErrorMessageCode ERROR_CODE_NNS8 = new ErrorMessageCode("NNS8");
63 private static final ErrorMessageCode ERROR_CODE_NNS9 = new ErrorMessageCode("NNS9");
64 private static final ErrorMessageCode ERROR_CODE_NNS10 = new ErrorMessageCode("NNS10");
65 private static final ErrorMessageCode ERROR_CODE_NNS11 = new ErrorMessageCode("NNS11");
66 private static final ErrorMessageCode ERROR_CODE_NNS12 = new ErrorMessageCode("NNS12");
67 private static final ErrorMessageCode ERROR_CODE_NNS13 = new ErrorMessageCode("NNS13");
68 private static final ErrorMessageCode ERROR_CODE_NNS14 = new ErrorMessageCode("NNS14");
71 public void validate(String fileName, Map.Entry<String, Resource> resourceEntry,
72 GlobalValidationContext globalContext, ValidationContext validationContext) {
74 NamingConventionValidationContext namingConventionValidationContext =
75 (NamingConventionValidationContext)validationContext;
76 validateHeatNovaResource(fileName, namingConventionValidationContext.getEnvFileName(),
77 namingConventionValidationContext.getHeatOrchestrationTemplate(),
81 private void validateHeatNovaResource(String fileName, String envFileName,
82 HeatOrchestrationTemplate heatOrchestrationTemplate,
83 GlobalValidationContext globalContext) {
84 Map<String, String> uniqueResourcePortNetworkRole = new HashMap<>();
85 //if no resources exist return
86 if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources())) {
90 heatOrchestrationTemplate
94 .filter(entry -> entry.getValue().getType()
95 .equals(HeatResourcesTypes.NOVA_SERVER_RESOURCE_TYPE.getHeatResource()))
96 .forEach( entry -> validateNovaServerResourceType(entry.getKey(), fileName, envFileName,
97 entry, uniqueResourcePortNetworkRole, heatOrchestrationTemplate, globalContext));
100 private void validateNovaServerResourceType(String resourceId, String fileName,
102 Map.Entry<String, Resource> resourceEntry,
103 Map<String, String> uniqueResourcePortNetworkRole,
104 HeatOrchestrationTemplate heatOrchestrationTemplate,
105 GlobalValidationContext globalContext) {
106 validateNovaServerResourceMetaData(fileName, resourceId,
107 heatOrchestrationTemplate.getResources().get(resourceId), globalContext);
108 validateNovaServerResourceNetworkUniqueRole(fileName, resourceId, uniqueResourcePortNetworkRole,
109 heatOrchestrationTemplate, globalContext);
110 validateAvailabilityZoneName(fileName, resourceEntry, globalContext);
111 validateNovaServerNameImageAndFlavor(fileName, envFileName, resourceEntry, globalContext);
114 @SuppressWarnings("unchecked")
115 private void validateNovaServerResourceMetaData(String fileName, String resourceId,
117 GlobalValidationContext globalValidationContext) {
118 Map<String, Object> novaServerProp = resource.getProperties();
119 Object novaServerPropMetadata;
120 if (MapUtils.isNotEmpty(novaServerProp)) {
121 novaServerPropMetadata = novaServerProp.get("metadata");
122 if (novaServerPropMetadata == null) {
123 globalValidationContext.addMessage(
126 ErrorMessagesFormatBuilder
127 .getErrorWithParameters(
128 ERROR_CODE_NNS1, Messages.MISSING_NOVA_SERVER_METADATA.getErrorMessage(),
130 } else if (novaServerPropMetadata instanceof Map) {
131 TreeMap<String, Object> propertyMap = new TreeMap((Comparator<String>) String::compareToIgnoreCase);
132 propertyMap.putAll((Map) novaServerPropMetadata);
133 if (!propertyMap.containsKey("vf_module_id")) {
134 globalValidationContext.addMessage(
137 ErrorMessagesFormatBuilder.getErrorWithParameters(
138 ERROR_CODE_NNS2, Messages.MISSING_NOVA_SERVER_VF_MODULE_ID.getErrorMessage(),
141 if (!propertyMap.containsKey("vnf_id")) {
142 globalValidationContext.addMessage(
143 fileName, ErrorLevel.WARNING,
144 ErrorMessagesFormatBuilder
145 .getErrorWithParameters(
146 ERROR_CODE_NNS3, Messages.MISSING_NOVA_SERVER_VNF_ID.getErrorMessage(),
153 private void validateNovaServerResourceNetworkUniqueRole(String fileName, String resourceId,
154 Map<String, String> uniqueResourcePortNetworkRole,
155 HeatOrchestrationTemplate heatOrchestrationTemplate,
156 GlobalValidationContext globalValidationContext) {
157 if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources().get(resourceId).getProperties())) {
160 Object propertyNetworkValue =
161 heatOrchestrationTemplate.getResources().get(resourceId).getProperties().get("networks");
162 if (propertyNetworkValue != null && propertyNetworkValue instanceof List) {
163 List<String> portResourceIdList =
164 getNovaNetworkPortResourceList(fileName, (List) propertyNetworkValue,
165 globalValidationContext);
166 for (String portResourceId : portResourceIdList) {
167 Resource portResource = heatOrchestrationTemplate.getResources().get(portResourceId);
169 if (portResource != null && portResource.getType()
170 .equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) {
171 validateUniqueResourcePortNetworkRole(fileName, resourceId,
172 uniqueResourcePortNetworkRole, globalValidationContext,
173 portResourceId, portResource);
179 private void validateUniqueResourcePortNetworkRole(String fileName, String resourceId,
180 Map<String, String> uniqueResourcePortNetworkRole,
181 GlobalValidationContext globalValidationContext,
182 String portResourceId, Resource portResource) {
186 getPortNetwork(fileName, resourceId, portResource, globalValidationContext);
187 if (Objects.nonNull(portNetwork)) {
188 network = portNetwork.get("get_param");
189 if (Objects.nonNull(network)) {
190 if (network instanceof String ){
191 role = getNetworkRole((String)network);
192 }else if (network instanceof List){
193 role = getNetworkRole((String)((List) network).get(0));
195 if (role != null && uniqueResourcePortNetworkRole.containsKey(role)) {
196 globalValidationContext.addMessage(
199 ErrorMessagesFormatBuilder.getErrorWithParameters(
200 ERROR_CODE_NNS12, Messages.RESOURCE_CONNECTED_TO_TWO_EXTERNAL_NETWORKS_WITH_SAME_ROLE
201 .getErrorMessage(), resourceId, role));
203 uniqueResourcePortNetworkRole.put(role, portResourceId);
209 private List<String> getNovaNetworkPortResourceList(String filename, List propertyNetworkValue,
210 GlobalValidationContext globalContext) {
211 globalContext.setMessageCode(ERROR_CODE_NNS14);
212 List<String> portResourceIdList = new ArrayList<>();
213 for (Object propValue : propertyNetworkValue) {
214 Object portPropValue = ((Map) propValue).get("port");
215 Collection<String> portResourceIds = HeatStructureUtil
216 .getReferencedValuesByFunctionName(filename, "get_resource", portPropValue,
218 if (portResourceIds != null) {
219 portResourceIdList.addAll(portResourceIds);
223 return portResourceIdList;
226 private String getNetworkRole(String network) {
227 if (network == null) {
230 if (network.contains("_net_id")) {
231 return network.substring(0, network.indexOf("_net_id"));
232 } else if (network.contains("_net_name")) {
233 return network.substring(0, network.indexOf("_net_name"));
234 } else if (network.contains("_net_fqdn")) {
235 return network.substring(0, network.indexOf("_net_fqdn"));
240 private Map getPortNetwork(String fileName, String resourceId, Resource portResource,
241 GlobalValidationContext globalValidationContext) {
242 Object portNetwork = portResource.getProperties().get("network_id");
243 if (portNetwork == null) {
244 portNetwork = portResource.getProperties().get("network");
246 if (!(portNetwork instanceof Map)) {
247 globalValidationContext.addMessage(
250 ErrorMessagesFormatBuilder
251 .getErrorWithParameters(
252 ERROR_CODE_NNS4, Messages.MISSING_GET_PARAM.getErrorMessage(),
253 "network or network_id", resourceId));
256 return (Map) portNetwork;
259 private void validateAvailabilityZoneName(String fileName,
260 Map.Entry<String, Resource> resourceEntry,
261 GlobalValidationContext globalContext) {
262 String[] regexList = new String[]{"availability_zone_(\\d+)"};
264 if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) {
268 Object availabilityZoneMap = resourceEntry.getValue().getProperties()
269 .get(AVAILABILITY_ZONE);
271 if (nonNull(availabilityZoneMap)) {
272 if (availabilityZoneMap instanceof Map) {
273 String availabilityZoneName = ValidationUtil.getWantedNameFromPropertyValueGetParam
274 (availabilityZoneMap);
276 if (availabilityZoneName != null && !ValidationUtil
277 .evalPattern(availabilityZoneName, regexList)) {
278 globalContext.addMessage(
280 ErrorLevel.WARNING, ErrorMessagesFormatBuilder.getErrorWithParameters(
281 ERROR_CODE_NNS5, Messages.PARAMETER_NAME_NOT_ALIGNED_WITH_GUIDELINES.getErrorMessage(),
282 ValidationUtil.getMessagePartAccordingToResourceType(resourceEntry),
283 "Availability Zone", availabilityZoneName, resourceEntry.getKey()));
286 globalContext.addMessage(
288 ErrorLevel.WARNING, ErrorMessagesFormatBuilder
289 .getErrorWithParameters(
290 ERROR_CODE_NNS6, Messages.MISSING_GET_PARAM.getErrorMessage(),
291 AVAILABILITY_ZONE, resourceEntry.getKey()));
296 private void validateNovaServerNameImageAndFlavor(String fileName, String envFileName,
297 Map.Entry<String, Resource> resourceEntry,
298 GlobalValidationContext globalContext) {
300 validateNovaServerNamingConvention(fileName, envFileName, resourceEntry, globalContext);
301 Map<String, String> legalNovaNamingConventionMap =
302 validateImageAndFlavorFromNovaServer(fileName, resourceEntry, globalContext);
304 if (Objects.nonNull(novaName)) {
305 legalNovaNamingConventionMap.put("name", novaName);
308 if (legalNovaNamingConventionMap.keySet().size() > 1) {
309 validateNovaServerNameImageAndFlavorSync(fileName, resourceEntry,
310 legalNovaNamingConventionMap, globalContext);
314 private String validateNovaServerNamingConvention(String fileName, String envFileName,
315 Map.Entry<String, Resource> resourceEntry,
316 GlobalValidationContext globalContext) {
317 if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) {
320 return checkIfNovaNameByGuidelines(fileName, envFileName, resourceEntry, globalContext);
323 private Map<String, String> validateImageAndFlavorFromNovaServer(String fileName,
324 Map.Entry<String, Resource> resourceEntry,
325 GlobalValidationContext globalContext) {
326 Map<String, String> imageAndFlavorLegalNames = new HashMap<>();
328 if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) {
329 return imageAndFlavorLegalNames;
332 Pair<String, String> imagePair = new ImmutablePair<>("image", ".*_image_name");
333 Pair<String, String> flavorPair = new ImmutablePair<>("flavor", ".*_flavor_name");
334 List<Pair<String, String>> imageFlavorPairs = Arrays.asList(imagePair, flavorPair);
335 Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties();
337 for (Pair<String, String> imageOrFlavor : imageFlavorPairs) {
338 boolean isErrorInImageOrFlavor =
339 isErrorExistWhenValidatingImageOrFlavorNames(fileName, imageOrFlavor, resourceEntry,
340 propertiesMap, globalContext);
341 if (!isErrorInImageOrFlavor) {
342 Object nameValue = propertiesMap.get(imageOrFlavor.getKey());
343 String imageOrFlavorName = ValidationUtil.getWantedNameFromPropertyValueGetParam
345 imageAndFlavorLegalNames.put(imageOrFlavor.getKey(), imageOrFlavorName);
348 return imageAndFlavorLegalNames;
351 private String checkIfNovaNameByGuidelines(String fileName, String envFileName,
352 Map.Entry<String, Resource> resourceEntry,
353 GlobalValidationContext globalContext) {
354 if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) {
357 Object novaNameGetParam = getNovaServerName(resourceEntry);
358 String novaName = null;
359 if (nonNull(novaNameGetParam)) {
361 checkNovaNameGetParamValueMap(fileName, novaNameGetParam, resourceEntry, globalContext);
362 checkIfNovaNameParameterInEnvIsStringOrList(fileName, envFileName, novaName, resourceEntry,
365 globalContext.addMessage(
367 ErrorLevel.WARNING, ErrorMessagesFormatBuilder
368 .getErrorWithParameters(
369 ERROR_CODE_NNS7, Messages.MISSING_GET_PARAM.getErrorMessage(),
370 "nova server name", resourceEntry.getKey()));
376 private boolean isErrorExistWhenValidatingImageOrFlavorNames(String fileName,
377 Pair<String, String> propertyNameAndRegex,
378 Map.Entry<String, Resource> resourceEntry,
379 Map<String, Object> propertiesMap,
380 GlobalValidationContext globalContext) {
381 String propertyName = propertyNameAndRegex.getKey();
382 Object nameValue = propertiesMap.get(propertyName);
383 String[] regexList = new String[]{propertyNameAndRegex.getValue()};
386 if (nonNull(nameValue)) {
387 if (nameValue instanceof Map) {
388 globalContext.setMessageCode(ERROR_CODE_NNS13);
389 if (ValidationUtil.validateMapPropertyValue(fileName, resourceEntry, globalContext,
391 nameValue, regexList)) {
395 globalContext.addMessage(
397 ErrorLevel.WARNING, ErrorMessagesFormatBuilder
398 .getErrorWithParameters(
399 ERROR_CODE_NNS8, Messages.MISSING_GET_PARAM.getErrorMessage(),
400 propertyName, resourceEntry.getKey()));
409 private Object getNovaServerName(Map.Entry<String, Resource> resourceEntry) {
410 Object novaServerName = resourceEntry.getValue().getProperties().get("name");
412 if (nonNull(novaServerName) && novaServerName instanceof Map) {
413 novaNameMap = (Map) novaServerName;
414 return novaNameMap.get(ResourceReferenceFunctions.GET_PARAM.getFunction());
420 @SuppressWarnings("unchecked")
421 private String checkNovaNameGetParamValueMap(String fileName, Object getParamValue,
422 Map.Entry<String, Resource> resourceEntry,
423 GlobalValidationContext globalContext) {
424 if (getParamValue instanceof List) {
425 List<Object> getParamNameList = (List) getParamValue;
426 String[] regexName = new String[]{".*_names"};
427 return isNovaNameAsListLegal(fileName, regexName, getParamNameList, resourceEntry,
429 } else if (getParamValue instanceof String) {
430 String[] regexName = new String[]{".*_name_(\\d+)"};
431 return isNovaNameAsStringLegal(fileName, (String) getParamValue, regexName, resourceEntry,
438 private void checkIfNovaNameParameterInEnvIsStringOrList(String fileName,
440 String novaServerName,
441 Map.Entry<String, Resource> resourceEntry,
442 GlobalValidationContext globalContext) {
443 if (nonNull(envFileName)) {
444 Environment environment = ValidationUtil.validateEnvContent(envFileName, globalContext);
446 if (environment != null && MapUtils.isNotEmpty(environment.getParameters())) {
447 Object novaServerNameEnvValue = environment.getParameters()
448 .get(novaServerName);
449 if (Objects.nonNull(novaServerNameEnvValue) && !DefinedHeatParameterTypes
450 .isNovaServerEnvValueIsFromRightType(novaServerNameEnvValue)) {
451 globalContext.addMessage(
453 ErrorLevel.WARNING, ErrorMessagesFormatBuilder.getErrorWithParameters(
454 ERROR_CODE_NNS9, Messages.PARAMETER_NAME_NOT_ALIGNED_WITH_GUIDELINES.getErrorMessage(),
456 novaServerNameEnvValue.toString(), resourceEntry.getKey()));
462 private String isNovaNameAsListLegal(String fileName,
464 List<Object> getParamNameList,
465 Map.Entry<String, Resource> resourceEntry,
466 GlobalValidationContext globalContext) {
468 if (getParamNameList.size() != 2 || !ValidationUtil.evalPattern(getParamNameList.get(0),
470 globalContext.addMessage(
473 ErrorMessagesFormatBuilder.getErrorWithParameters(
474 ERROR_CODE_NNS10, Messages.PARAMETER_NAME_NOT_ALIGNED_WITH_GUIDELINES.getErrorMessage(),
476 "name", getParamNameList.toString(), resourceEntry.getKey()));
480 return (String) getParamNameList.get(0);
483 private String isNovaNameAsStringLegal(String fileName,
486 Map.Entry<String, Resource> resourceEntry,
487 GlobalValidationContext globalContext) {
488 if (!ValidationUtil.evalPattern(novaName, regexName)) {
489 globalContext.addMessage(
492 ErrorMessagesFormatBuilder.getErrorWithParameters(
493 ERROR_CODE_NNS10, Messages.PARAMETER_NAME_NOT_ALIGNED_WITH_GUIDELINES.getErrorMessage(),
495 "name", novaName, resourceEntry.getKey()));
501 private void validateNovaServerNameImageAndFlavorSync(String fileName,
502 Map.Entry<String, Resource> resourceEntry,
503 Map<String, String> legalNovaNamingConventionNames,
504 GlobalValidationContext globalContext) {
505 List<String> vmNames = new LinkedList<>();
507 for (Map.Entry<String, String> nameEntry : legalNovaNamingConventionNames.entrySet()) {
508 vmNames.add(getVmName(nameEntry.getValue(), nameEntry.getKey()));
511 vmNames.removeIf(Objects::isNull);
513 if (!isVmNameSync(vmNames)) {
514 globalContext.addMessage(
517 ErrorMessagesFormatBuilder.getErrorWithParameters(
518 ERROR_CODE_NNS11, Messages.NOVA_NAME_IMAGE_FLAVOR_NOT_CONSISTENT.getErrorMessage(),
519 resourceEntry.getKey()));
523 private String getVmName(String nameToGetVmNameFrom, String stringToGetIndexOf) {
525 nameToGetVmNameFrom == null ? -1 : nameToGetVmNameFrom.indexOf(stringToGetIndexOf);
526 String vmName = null;
527 if (nameToGetVmNameFrom != null) {
528 vmName = vmIndex < 0 ? null
529 : trimNonAlphaNumericCharactersFromEndOfString(nameToGetVmNameFrom.substring(0, vmIndex));
534 private boolean isVmNameSync(List<String> namesToCompare) {
535 int size = namesToCompare.size();
536 for (int i = 0; i < size - 1; i++) {
537 if (!namesToCompare.get(i).equals(namesToCompare.get(i + 1))) {
544 private String trimNonAlphaNumericCharactersFromEndOfString(String toTrim) {
545 int stringSize = toTrim.length();
546 int stringLength = stringSize - 1;
547 String[] regexList = new String[]{"[^a-zA-Z0-9]"};
549 while (stringLength >= 0) {
550 if (!ValidationUtil.evalPattern(String.valueOf(toTrim.charAt(stringLength)), regexList)) {
556 return toTrim.substring(0, stringLength + 1);