Search in sources :

Example 1 with MsoHeatEnvironmentEntry

use of org.onap.so.openstack.utils.MsoHeatEnvironmentEntry in project so by onap.

the class MsoVnfAdapterImpl method updateVfModule.

public void updateVfModule(String cloudSiteId, String cloudOwner, String tenantId, String vnfType, String vnfVersion, String vnfName, String requestType, String volumeGroupHeatStackId, String baseVfHeatStackId, String vfModuleStackId, String modelCustomizationUuid, Map<String, Object> inputs, MsoRequest msoRequest, Holder<Map<String, String>> outputs, Holder<VnfRollback> rollback) throws VnfException {
    String vfModuleName = vnfName;
    String vfModuleType = vnfType;
    StringBuilder sbInit = new StringBuilder();
    sbInit.append("updateVfModule: \n");
    sbInit.append("cloudOwner=" + cloudOwner + "\n");
    sbInit.append("cloudSiteId=" + cloudSiteId + "\n");
    sbInit.append("tenantId=" + tenantId + "\n");
    sbInit.append("vnfType=" + vnfType + "\n");
    sbInit.append("vnfVersion=" + vnfVersion + "\n");
    sbInit.append("vnfName=" + vnfName + "\n");
    sbInit.append("requestType=" + requestType + "\n");
    sbInit.append("volumeGroupHeatStackId=" + volumeGroupHeatStackId + "\n");
    sbInit.append("baseVfHeatStackId=" + baseVfHeatStackId + "\n");
    sbInit.append("vfModuleStackId=" + vfModuleStackId + "\n");
    sbInit.append("modelCustomizationUuid=" + modelCustomizationUuid + "\n");
    logger.debug(sbInit.toString());
    String mcu = modelCustomizationUuid;
    boolean useMCUuid = false;
    if (mcu != null && !mcu.isEmpty()) {
        if ("null".equalsIgnoreCase(mcu)) {
            logger.debug("modelCustomizationUuid: passed in as the string 'null' - will ignore: {}", modelCustomizationUuid);
            useMCUuid = false;
            mcu = "";
        } else {
            logger.debug("Found modelCustomizationUuid! Will use that: {}", mcu);
            useMCUuid = true;
        }
    }
    String requestTypeString = "";
    if (requestType != null && !"".equals(requestType)) {
        requestTypeString = requestType;
    }
    String nestedStackId = null;
    if (volumeGroupHeatStackId != null && !"".equals(volumeGroupHeatStackId) && !"null".equalsIgnoreCase(volumeGroupHeatStackId)) {
        nestedStackId = volumeGroupHeatStackId;
    }
    String nestedBaseStackId = null;
    if (baseVfHeatStackId != null && !"".equals(baseVfHeatStackId) && !"null".equalsIgnoreCase(baseVfHeatStackId)) {
        nestedBaseStackId = baseVfHeatStackId;
    }
    if (inputs == null) {
        // Create an empty set of inputs
        inputs = new HashMap<>();
        logger.debug("inputs == null - setting to empty");
    }
    boolean isBaseRequest = false;
    boolean isVolumeRequest = false;
    if (requestTypeString.startsWith("VOLUME")) {
        isVolumeRequest = true;
    }
    if ((vfModuleName == null || "".equals(vfModuleName.trim())) && vfModuleStackId != null) {
        vfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
    }
    logger.debug("Updating VFModule: " + vfModuleName + " of type " + vfModuleType + "in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId);
    logger.debug("requestTypeString = " + requestTypeString + ", nestedVolumeStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
    // Build a default rollback object (no actions performed)
    VnfRollback vfRollback = new VnfRollback();
    vfRollback.setCloudSiteId(cloudSiteId);
    vfRollback.setCloudOwner(cloudOwner);
    vfRollback.setTenantId(tenantId);
    vfRollback.setMsoRequest(msoRequest);
    vfRollback.setRequestType(requestTypeString);
    vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
    vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
    vfRollback.setIsBase(isBaseRequest);
    vfRollback.setVfModuleStackId(vfModuleStackId);
    vfRollback.setModelCustomizationUuid(mcu);
    StackInfo heatStack;
    logger.debug("UpdateVfModule - querying for {}", vfModuleName);
    try {
        heatStack = msoHeatUtils.queryStack(cloudSiteId, cloudOwner, tenantId, vfModuleName);
    } catch (MsoException me) {
        // Failed to query the Stack due to an openstack exception.
        // Convert to a generic VnfException
        me.addContext("UpdateVFModule");
        String error = "Update VFModule: Query " + vfModuleName + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
        logger.error(LoggingAnchor.NINE, MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, OPENSTACK, QUERY_STACK, ErrorCode.DataError.getValue(), "Exception - " + QUERY_STACK, me);
        logger.debug(error);
        throw new VnfException(me);
    }
    // TODO - do we need to check for the other status possibilities?
    if (heatStack == null || heatStack.getStatus() == HeatStatus.NOTFOUND) {
        // Not Found
        String error = "Update VF: Stack " + vfModuleName + " does not exist in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId;
        logger.error(LoggingAnchor.NINE, MessageEnum.RA_VNF_NOT_EXIST.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, OPENSTACK, QUERY_STACK, ErrorCode.DataError.getValue(), error);
        throw new VnfNotFound(cloudSiteId, cloudOwner, tenantId, vfModuleName);
    } else {
        logger.debug("Found Existing stack, status={}", heatStack.getStatus());
        // Populate the outputs from the existing stack.
        outputs.value = copyStringOutputs(heatStack.getOutputs());
        // Default rollback - no updates performed
        rollback.value = vfRollback;
    }
    // 1604 Cinder Volume support - handle a nestedStackId if sent (volumeGroupHeatStackId):
    StackInfo nestedHeatStack = null;
    if (nestedStackId != null) {
        try {
            logger.debug("Querying for nestedStackId = {}", nestedStackId);
            nestedHeatStack = msoHeatUtils.queryStack(cloudSiteId, cloudOwner, tenantId, nestedStackId);
        } catch (MsoException me) {
            // Failed to query the Stack due to an openstack exception.
            // Convert to a generic VnfException
            me.addContext("UpdateVFModule");
            String error = "Update VF: Attached heatStack ID Query " + nestedStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
            logger.error(LoggingAnchor.NINE, MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudOwner, cloudSiteId, tenantId, OPENSTACK, QUERY_STACK, ErrorCode.DataError.getValue(), "Exception - " + error, me);
            logger.debug("ERROR trying to query nested stack= {}", error);
            throw new VnfException(me);
        }
        if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
            String error = "Update VFModule: Attached volume heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " " + USER_ERROR;
            logger.error(LoggingAnchor.TEN, MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudOwner, cloudSiteId, tenantId, error, OPENSTACK, QUERY_STACK, ErrorCode.DataError.getValue(), error);
            logger.debug(error);
            throw new VnfException(error, MsoExceptionCategory.USERDATA);
        } else {
            logger.debug("Found nested heat stack - copying values to inputs *later*");
            msoHeatUtils.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
        }
    }
    // handle a nestedBaseStackId if sent - this is the stack ID of the base.
    StackInfo nestedBaseHeatStack = null;
    if (nestedBaseStackId != null) {
        try {
            logger.debug("Querying for nestedBaseStackId = {}", nestedBaseStackId);
            nestedBaseHeatStack = msoHeatUtils.queryStack(cloudSiteId, cloudOwner, tenantId, nestedBaseStackId);
        } catch (MsoException me) {
            // Failed to query the Stack due to an openstack exception.
            // Convert to a generic VnfException
            me.addContext("UpdateVfModule");
            String error = "Update VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
            logger.error(LoggingAnchor.NINE, MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, OPENSTACK, QUERY_STACK, ErrorCode.DataError.getValue(), "Exception - " + error, me);
            logger.debug("ERROR trying to query nested base stack= {}", error);
            throw new VnfException(me);
        }
        if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
            String error = "Update VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " " + USER_ERROR;
            logger.error(LoggingAnchor.TEN, MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, error, OPENSTACK, QUERY_STACK, ErrorCode.DataError.getValue(), error);
            logger.debug(error);
            throw new VnfException(error, MsoExceptionCategory.USERDATA);
        } else {
            logger.debug("Found nested base heat stack - copying values to inputs *later*");
            msoHeatUtils.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
        }
    }
    // Retrieve the VF definition
    VnfResource vnfResource = null;
    VfModule vf = null;
    VfModuleCustomization vfmc = null;
    if (useMCUuid) {
        vfmc = vfModuleCustomRepo.findFirstByModelCustomizationUUIDOrderByCreatedDesc(modelCustomizationUuid);
        vf = vfmc != null ? vfmc.getVfModule() : null;
        if (vf == null) {
            logger.debug("Unable to find a vfModule matching modelCustomizationUuid={}", mcu);
        }
    } else {
        logger.debug("1707 and later - MUST PROVIDE Model Customization UUID!");
    }
    if (vf == null) {
        String error = "Update VfModule: unable to find vfModule with modelCustomizationUuid=" + mcu;
        logger.error(LoggingAnchor.SIX, MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VF Module Type", vfModuleType, OPENSTACK, ErrorCode.DataError.getValue(), error);
        throw new VnfException(error, MsoExceptionCategory.USERDATA);
    }
    logger.debug("Got VF module definition from Catalog: {}", vf.toString());
    if (vf.getIsBase()) {
        isBaseRequest = true;
        logger.debug("This a BASE update request");
    } else {
        logger.debug("This is *not* a BASE VF update request");
        if (!isVolumeRequest && nestedBaseStackId == null) {
            logger.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
        }
    }
    // if we have a vf Module - then we have to query to get the VnfResource record.
    if (vf.getModelUUID() != null) {
        String vnfResourceModelUuid = vf.getModelUUID();
        vnfResource = vf.getVnfResources();
        if (vnfResource == null) {
            logger.debug("Unable to find vnfResource at ? will not error for now...", vnfResourceModelUuid);
        }
    }
    String minVersionVnf = null;
    String maxVersionVnf = null;
    if (vnfResource != null) {
        try {
            minVersionVnf = vnfResource.getAicVersionMin();
            maxVersionVnf = vnfResource.getAicVersionMax();
        } catch (Exception e) {
            logger.debug("Unable to pull min/max version for this VNF Resource entry", e);
            minVersionVnf = null;
            maxVersionVnf = null;
        }
        if (minVersionVnf != null && "".equals(minVersionVnf)) {
            minVersionVnf = null;
        }
        if (maxVersionVnf != null && "".equals(maxVersionVnf)) {
            maxVersionVnf = null;
        }
    }
    if (minVersionVnf != null && maxVersionVnf != null) {
        MavenLikeVersioning aicV = new MavenLikeVersioning();
        // double check
        if (this.cloudConfig != null) {
            Optional<CloudSite> cloudSiteOpt = this.cloudConfig.getCloudSite(cloudSiteId);
            if (cloudSiteOpt.isPresent()) {
                aicV.setVersion(cloudSiteOpt.get().getCloudVersion());
                boolean moreThanMin = true;
                boolean equalToMin = true;
                boolean moreThanMax = true;
                boolean equalToMax = true;
                boolean doNotTest = false;
                try {
                    moreThanMin = aicV.isMoreRecentThan(minVersionVnf);
                    equalToMin = aicV.isTheSameVersion(minVersionVnf);
                    moreThanMax = aicV.isMoreRecentThan(maxVersionVnf);
                    equalToMax = aicV.isTheSameVersion(maxVersionVnf);
                } catch (Exception e) {
                    logger.debug("An exception occured while trying to test AIC Version {} - will default to not check", e.getMessage(), e);
                    doNotTest = true;
                }
                if (!doNotTest) {
                    if (// aic >= min
                    (moreThanMin || equalToMin) && ((equalToMax) || !(moreThanMax))) {
                        // aic <= max
                        logger.debug("VNF Resource " + vnfResource.getModelName() + " " + VERSION_MIN + " =" + minVersionVnf + " " + VERSION_MAX + " :" + maxVersionVnf + " supported on Cloud: " + cloudSiteId + " with AIC_Version:" + aicV);
                    } else {
                        // ERROR
                        String error = "VNF Resource type: " + vnfResource.getModelName() + " " + VERSION_MIN + " =" + minVersionVnf + " " + VERSION_MAX + " :" + maxVersionVnf + " NOT supported on Cloud: " + cloudSiteId + " with AIC_Version:" + aicV;
                        logger.error(LoggingAnchor.FIVE, MessageEnum.RA_CONFIG_EXC.toString(), error, OPENSTACK, ErrorCode.BusinessProcessError.getValue(), "Exception - setVersion");
                        logger.debug(error);
                        throw new VnfException(error, MsoExceptionCategory.USERDATA);
                    }
                } else {
                    logger.debug("bypassing testing AIC version...");
                }
            }
        // let this error out downstream to avoid introducing uncertainty at this stage
        } else {
            logger.debug("cloudConfig is NULL - cannot check cloud site version");
        }
    } else {
        logger.debug("AIC Version not set in VNF_Resource - do not error for now - not checked.");
    }
    // End Version check 1607
    HeatTemplate heatTemplate = null;
    HeatEnvironment heatEnvironment = null;
    if (isVolumeRequest) {
        heatTemplate = vf.getVolumeHeatTemplate();
        heatEnvironment = vfmc.getVolumeHeatEnv();
    } else {
        heatTemplate = vf.getModuleHeatTemplate();
        heatEnvironment = vfmc.getHeatEnvironment();
    }
    if (heatTemplate == null) {
        String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", modelCustomizationUuid=" + mcu + ", vfModuleUuid=" + vf.getModelUUID() + ", reqType=" + requestTypeString;
        logger.error(LoggingAnchor.SIX, MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template ID", vfModuleType, OPENSTACK, ErrorCode.DataError.getValue(), error);
        throw new VnfException(error, MsoExceptionCategory.INTERNAL);
    } else {
        logger.debug("Got HEAT Template from DB: {}", heatTemplate.getHeatTemplate());
    }
    if (heatEnvironment == null) {
        String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType + ", modelCustomizationUuid=" + mcu + ", vfModuleUuid=" + vf.getModelUUID() + ", reqType=" + requestTypeString;
        logger.error(LoggingAnchor.FIVE, MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Environment ID", OPENSTACK, ErrorCode.DataError.getValue(), error);
        throw new VnfException(error, MsoExceptionCategory.INTERNAL);
    } else {
        logger.debug("Got Heat Environment from DB: {}", heatEnvironment.getEnvironment());
    }
    logger.debug("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId={}", heatTemplate.getArtifactUuid());
    List<HeatTemplate> nestedTemplates = heatTemplate.getChildTemplates();
    Map<String, Object> nestedTemplatesChecked = new HashMap<>();
    if (nestedTemplates != null && !nestedTemplates.isEmpty()) {
        // for debugging print them out
        logger.debug("Contents of nestedTemplates - to be added to files: on stack:");
        for (HeatTemplate entry : nestedTemplates) {
            nestedTemplatesChecked.put(entry.getTemplateName(), entry.getTemplateBody());
            logger.debug(entry.getTemplateName() + " -> " + entry.getTemplateBody());
        }
    } else {
        logger.debug("No nested templates found - nothing to do here");
        nestedTemplatesChecked = null;
    }
    // Also add the files: for any get_files associated with this VfModule
    // *if* there are any
    logger.debug("In MsoVnfAdapterImpl.updateVfModule, about to call db.getHeatFiles avec vfModuleId={}", vf.getModelUUID());
    List<HeatFiles> heatFiles = null;
    Map<String, Object> heatFilesObjects = new HashMap<>();
    // Add ability to turn on adding get_files with volume requests (by property).
    boolean addGetFilesOnVolumeReq = false;
    try {
        String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ);
        if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
            addGetFilesOnVolumeReq = true;
            logger.debug("AddGetFilesOnVolumeReq - setting to true! {}", propertyString);
        }
    } catch (Exception e) {
        logger.debug("An error occured trying to get property {} - default to false", MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ, e);
    }
    if (!isVolumeRequest || addGetFilesOnVolumeReq) {
        logger.debug("In MsoVnfAdapterImpl updateVfModule, about to call db.getHeatFilesForVfModule avec " + "vfModuleId={}", vf.getModelUUID());
        heatFiles = vf.getHeatFiles();
        if (heatFiles != null && !heatFiles.isEmpty()) {
            // add these to stack - to be done in createStack
            // here, we will map them to Map<String, Object> from Map<String, HeatFiles>
            // this will match the nested templates format
            logger.debug("Contents of heatFiles - to be added to files: on stack:");
            for (HeatFiles heatfile : heatFiles) {
                logger.debug(heatfile.getFileName() + " -> " + heatfile.getFileBody());
                heatFilesObjects.put(heatfile.getFileName(), heatfile.getFileBody());
            }
        } else {
            logger.debug("No heat files found -nothing to do here");
            heatFilesObjects = null;
        }
    }
    // Check that required parameters have been supplied
    String missingParams = null;
    List<String> paramList = new ArrayList<>();
    // New for 1510 - consult the PARAM_ALIAS field to see if we've been
    // supplied an alias. Only check if we don't find it initially.
    // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
    // And also new - add parameter to turn off checking all together if we find we're blocking orders we
    // shouldn't
    boolean checkRequiredParameters = true;
    try {
        String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
        if ("false".equalsIgnoreCase(propertyString) || "n".equalsIgnoreCase(propertyString)) {
            checkRequiredParameters = false;
            logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking...", MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
        }
    } catch (Exception e) {
        // No problem - default is true
        logger.debug("An exception occured trying to get property {}", MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
    }
    // 1604 - Add enhanced environment & parameter checking
    // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
    // Part 2: only submit to openstack the parameters in the envt that are in the heat template
    // Note this also removes any comments
    MsoHeatEnvironmentEntry mhee = null;
    if (heatEnvironment != null && heatEnvironment.getEnvironment().toLowerCase().contains("parameters:")) {
        logger.debug("Enhanced environment checking enabled - 1604");
        StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
        mhee = new MsoHeatEnvironmentEntry(sb);
        StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
        for (HeatTemplateParam parm : heatTemplate.getParameters()) {
            sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
        }
        if (!mhee.isValid()) {
            sb2.append("Environment says it's not valid! " + mhee.getErrorString());
        } else {
            sb2.append("\nEnvironment:");
            sb2.append(mhee.toFullString());
        }
        logger.debug(sb2.toString());
    } else {
        logger.debug("NO ENVIRONMENT for this entry");
    }
    // New for 1607 - support params of json type
    HashMap<String, JsonNode> jsonParams = new HashMap<>();
    boolean hasJson = false;
    for (HeatTemplateParam parm : heatTemplate.getParameters()) {
        logger.debug("Parameter:'" + parm.getParamName() + "', isRequired=" + parm.isRequired() + ", alias=" + parm.getParamAlias());
        // handle json
        String parameterType = parm.getParamType();
        if (parameterType == null || "".equals(parameterType.trim())) {
            parameterType = "String";
        }
        JsonNode jsonNode = null;
        if ("json".equalsIgnoreCase(parameterType) && inputs != null) {
            if (inputs.containsKey(parm.getParamName())) {
                hasJson = true;
                String jsonString = null;
                try {
                    jsonString = JSON_MAPPER.writeValueAsString(inputs.get(parm.getParamName()));
                    jsonNode = JSON_MAPPER.readTree(jsonString);
                } catch (JsonParseException jpe) {
                    // TODO - what to do here?
                    // for now - send the error to debug
                    logger.debug("Json Error Converting {} - {}", parm.getParamName(), jpe.getMessage(), jpe);
                    hasJson = false;
                    jsonNode = null;
                } catch (Exception e) {
                    // or here?
                    logger.debug("Json Error Converting {} {}", parm.getParamName(), e.getMessage(), e);
                    hasJson = false;
                    jsonNode = null;
                }
                if (jsonNode != null) {
                    jsonParams.put(parm.getParamName(), jsonNode);
                }
            } else if (inputs.containsKey(parm.getParamAlias())) {
                hasJson = true;
                String jsonString = null;
                try {
                    jsonString = (String) inputs.get(parm.getParamAlias());
                    jsonNode = JSON_MAPPER.readTree(jsonString);
                } catch (JsonParseException jpe) {
                    // TODO - what to do here?
                    // for now - send the error to debug, but just leave it as a String
                    String errorMessage = jpe.getMessage();
                    logger.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage, jpe);
                    hasJson = false;
                    jsonNode = null;
                } catch (Exception e) {
                    // or here?
                    logger.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage(), e);
                    hasJson = false;
                    jsonNode = null;
                }
                if (jsonNode != null) {
                    // Notice here - we add it to the jsonParams hashMap with the actual name -
                    // then manipulate the inputs so when we check for aliases below - it will not
                    // get flagged.
                    jsonParams.put(parm.getParamName(), jsonNode);
                    inputs.remove(parm.getParamAlias());
                    inputs.put(parm.getParamName(), jsonString);
                }
            }
        // TODO add a check for the parameter in the env file
        }
        if (parm.isRequired() && (inputs == null || !inputs.containsKey(parm.getParamName()))) {
            if (inputs.containsKey(parm.getParamAlias())) {
                // They've submitted using an alias name. Remove that from inputs, and add back using real name.
                String realParamName = parm.getParamName();
                String alias = parm.getParamAlias();
                Object value = inputs.get(alias);
                logger.debug("*Found an Alias: paramName=" + realParamName + ",alias=" + alias + ",value=" + value);
                inputs.remove(alias);
                inputs.put(realParamName, value);
                logger.debug("{} entry removed from inputs, added back using {}", alias, realParamName);
            } else // enhanced - check if it's in the Environment (note: that method
            if (mhee != null && mhee.containsParameter(parm.getParamName())) {
                logger.debug("Required parameter {} appears to be in environment - do not count as missing", parm.getParamName());
            } else {
                logger.debug("adding to missing parameters list: {}", parm.getParamName());
                if (missingParams == null) {
                    missingParams = parm.getParamName();
                } else {
                    missingParams += "," + parm.getParamName();
                }
            }
        }
        paramList.add(parm.getParamName());
    }
    if (missingParams != null) {
        // Problem - missing one or more required parameters
        if (checkRequiredParameters) {
            String error = "Update VNF: Missing Required inputs: " + missingParams;
            logger.error(LoggingAnchor.FIVE, MessageEnum.RA_MISSING_PARAM.toString(), missingParams, OPENSTACK, ErrorCode.DataError.getValue(), error);
            throw new VnfException(error, MsoExceptionCategory.USERDATA);
        } else {
            logger.debug("found missing parameters - but checkRequiredParameters is false - will not block");
        }
    }
    // Just submit the envt entry as received from the database
    String newEnvironmentString = null;
    if (mhee != null) {
        newEnvironmentString = mhee.getRawEntry().toString();
    }
    // Remove any extraneous parameters (don't throw an error)
    if (inputs != null) {
        List<String> extraParams = new ArrayList<>();
        extraParams.addAll(inputs.keySet());
        // This is not a valid parameter for this template
        extraParams.removeAll(paramList);
        if (!extraParams.isEmpty()) {
            logger.warn(LoggingAnchor.SIX, MessageEnum.RA_VNF_EXTRA_PARAM.toString(), vnfType, extraParams.toString(), OPENSTACK, ErrorCode.DataError.getValue(), "Extra params");
            inputs.keySet().removeAll(extraParams);
        }
    }
    Map<String, Object> goldenInputs = copyStringInputs(inputs);
    // 1607 - when we get here - we have clean inputs. Create inputsTwo in case we have json
    Map<String, Object> inputsTwo = null;
    if (hasJson && jsonParams.size() > 0) {
        inputsTwo = new HashMap<>();
        for (Map.Entry<String, Object> entry : inputs.entrySet()) {
            String keyParamName = entry.getKey();
            Object value = entry.getValue();
            if (jsonParams.containsKey(keyParamName)) {
                inputsTwo.put(keyParamName, jsonParams.get(keyParamName));
            } else {
                inputsTwo.put(keyParamName, value);
            }
        }
        goldenInputs = inputsTwo;
    }
    // "Fix" the template if it has CR/LF (getting this from Oracle)
    String template = heatTemplate.getHeatTemplate();
    template = template.replaceAll("\r\n", "\n");
    // because we already checked for those.
    try {
        heatStack = heatU.updateStack(cloudSiteId, cloudOwner, tenantId, vfModuleName, template, goldenInputs, true, heatTemplate.getTimeoutMinutes(), newEnvironmentString, // heatEnvironmentString,
        nestedTemplatesChecked, heatFilesObjects);
    } catch (MsoException me) {
        me.addContext("UpdateVFModule");
        String error = "Update VFModule " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
        logger.error(LoggingAnchor.EIGHT, MessageEnum.RA_UPDATE_VNF_ERR.toString(), vfModuleType, cloudOwner, cloudSiteId, tenantId, OPENSTACK, ErrorCode.DataError.getValue(), "Exception - " + error, me);
        throw new VnfException(me);
    }
    // Reach this point if updateStack is successful.
    // Populate remaining rollback info and response parameters.
    vfRollback.setVnfId(heatStack.getCanonicalName());
    vfRollback.setVnfCreated(true);
    outputs.value = copyStringOutputs(heatStack.getOutputs());
    rollback.value = vfRollback;
}
Also used : HashMap(java.util.HashMap) HeatEnvironment(org.onap.so.db.catalog.beans.HeatEnvironment) ArrayList(java.util.ArrayList) VnfNotFound(org.onap.so.adapters.vnf.exceptions.VnfNotFound) JsonNode(com.fasterxml.jackson.databind.JsonNode) JsonParseException(com.fasterxml.jackson.core.JsonParseException) VfModule(org.onap.so.db.catalog.beans.VfModule) VnfResource(org.onap.so.db.catalog.beans.VnfResource) VnfRollback(org.onap.so.openstack.beans.VnfRollback) VnfException(org.onap.so.adapters.vnf.exceptions.VnfException) HeatFiles(org.onap.so.db.catalog.beans.HeatFiles) StackInfo(org.onap.so.openstack.beans.StackInfo) MavenLikeVersioning(org.onap.so.db.catalog.utils.MavenLikeVersioning) MsoException(org.onap.so.openstack.exceptions.MsoException) MsoHeatNotFoundException(org.onap.so.openstack.exceptions.MsoHeatNotFoundException) JsonParseException(com.fasterxml.jackson.core.JsonParseException) VnfException(org.onap.so.adapters.vnf.exceptions.VnfException) MsoException(org.onap.so.openstack.exceptions.MsoException) MsoHeatEnvironmentEntry(org.onap.so.openstack.utils.MsoHeatEnvironmentEntry) HeatTemplate(org.onap.so.db.catalog.beans.HeatTemplate) CloudSite(org.onap.so.db.catalog.beans.CloudSite) VfModuleCustomization(org.onap.so.db.catalog.beans.VfModuleCustomization) HashMap(java.util.HashMap) Map(java.util.Map) HeatTemplateParam(org.onap.so.db.catalog.beans.HeatTemplateParam)

Example 2 with MsoHeatEnvironmentEntry

use of org.onap.so.openstack.utils.MsoHeatEnvironmentEntry in project so by onap.

the class MsoVnfPluginAdapterImpl method createVfModule.

/**
 * This is the "Create VF Module" web service implementation. It will instantiate a new VF Module of the requested
 * type in the specified cloud and tenant. The tenant must exist before this service is called.
 *
 * If a VF Module with the same name already exists, this can be considered a success or failure, depending on the
 * value of the 'failIfExists' parameter.
 *
 * All VF Modules are defined in the MSO catalog. The caller must request one of the pre-defined module types or an
 * error will be returned. Within the catalog, each VF Module references (among other things) a collection of
 * artifacts that are used to deploy the required cloud resources (VMs, networks, etc.).
 *
 * Depending on the module templates, a variable set of input parameters will be defined, some of which are
 * required. The caller is responsible to pass the necessary input data for the module or an error will be thrown.
 *
 * The method returns the vfModuleId, a Map of output attributes, and a VnfRollback object. This last object can be
 * passed as-is to the rollbackVnf operation to undo everything that was created for the Module. This is useful if a
 * VF module is successfully created but the orchestration fails on a subsequent step.
 *
 * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
 * @param cloudOwner cloud owner of the cloud site in which to create the VNF
 * @param tenantId Openstack tenant identifier
 * @param vfModuleType VF Module type key, should match a VNF definition in catalog DB. Deprecated - should use
 *        modelCustomizationUuid
 * @param vnfVersion VNF version key, should match a VNF definition in catalog DB Deprecated - VF Module versions
 *        also captured by modelCustomizationUuid
 * @param vnfId - VNF ID
 * @param vfModuleName Name to be assigned to the new VF Module
 * @param vfModuleId Id fo the new VF Module
 * @param requestType Indicates if this is a Volume Group or Module request
 * @param volumeGroupId Identifier (i.e. deployment ID) for a Volume Group to attach to a VF Module
 * @param baseVfModuleId Identifier (i.e. deployment ID) of the Base Module if this is an Add-on module
 * @param modelCustomizationUuid Unique ID for the VF Module's model. Replaces the use of vfModuleType.
 * @param inputs Map of key=value inputs for VNF stack creation
 * @param failIfExists Flag whether already existing VNF should be considered
 * @param backout Flag whether to suppress automatic backout (for testing)
 * @param msoRequest Request tracking information for logs
 * @param vnfId Holder for output VF Module instance ID in the cloud
 * @param outputs Holder for Map of VNF outputs from Deployment (assigned IPs, etc)
 * @param rollback Holder for returning VnfRollback object
 */
public void createVfModule(String cloudSiteId, String cloudOwner, String tenantId, String vfModuleType, String vnfVersion, String genericVnfId, String vfModuleName, String vfModuleId, String requestType, String volumeGroupId, String baseVfModuleId, String modelCustomizationUuid, Map<String, Object> inputs, Boolean failIfExists, Boolean backout, Boolean enableBridge, MsoRequest msoRequest, Holder<String> vnfId) throws VnfException {
    // Will capture execution time for metrics
    long startTime = System.currentTimeMillis();
    // Require a model customization ID. Every VF Module definition must have one.
    if (modelCustomizationUuid == null || modelCustomizationUuid.isEmpty()) {
        logger.debug("Missing required input: modelCustomizationUuid");
        String error = "Create vfModule error: Missing required input: modelCustomizationUuid";
        logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VF Module ModelCustomizationUuid", "VDU", ErrorCode.DataError, "Create VF Module: " + "Missing required input: modelCustomizationUuid");
        logger.debug(error);
        throw new VnfException(error, MsoExceptionCategory.USERDATA);
    }
    // Clean up some inputs to make comparisons easier
    if (requestType == null)
        requestType = "";
    if ("".equals(volumeGroupId) || "null".equals(volumeGroupId))
        volumeGroupId = null;
    if ("".equals(baseVfModuleId) || "null".equals(baseVfModuleId))
        baseVfModuleId = null;
    if (inputs == null) {
        // Create an empty set of inputs
        inputs = new HashMap<>();
        logger.debug("inputs == null - setting to empty");
    } else {
        this.sendMapToDebug(inputs);
    }
    // Check if this is for a "Volume" module
    boolean isVolumeRequest = false;
    if (requestType.startsWith("VOLUME")) {
        isVolumeRequest = true;
    }
    logger.debug("requestType = " + requestType + ", volumeGroupStackId = " + volumeGroupId + ", baseStackId = " + baseVfModuleId);
    // Get the VNF/VF Module definition from the Catalog DB first.
    // There are three relevant records: VfModule, VfModuleCustomization, VnfResource
    VfModule vfModule = null;
    VnfResource vnfResource = null;
    VfModuleCustomization vfModuleCust = null;
    try {
        vfModuleCust = vfModuleCustomRepo.findFirstByModelCustomizationUUIDOrderByCreatedDesc(modelCustomizationUuid);
        if (vfModuleCust == null) {
            String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid=" + modelCustomizationUuid;
            logger.debug(error);
            logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VF Module ModelCustomizationUuid", modelCustomizationUuid, "CatalogDb", ErrorCode.DataError, error);
            throw new VnfException(error, MsoExceptionCategory.USERDATA);
        } else {
            logger.debug("Found vfModuleCust entry {}", vfModuleCust.toString());
        }
        // Get the vfModule and vnfResource records
        vfModule = vfModuleCust.getVfModule();
        vnfResource = vfModuleCust.getVfModule().getVnfResources();
    } catch (Exception e) {
        logger.debug("unhandled exception in create VF - [Query]" + e.getMessage());
        throw new VnfException("Exception during create VF " + e.getMessage());
    }
    // Perform a version check against cloudSite
    // Obtain the cloud site information where we will create the VF Module
    Optional<CloudSite> cloudSiteOp = cloudConfig.getCloudSite(cloudSiteId);
    if (!cloudSiteOp.isPresent()) {
        // If cloudSiteId is not present in the catalog DB, then default to multicloud
        logger.debug("{} is not present in cloud_site catalog DB, defaulting to Multicloud plugin adapter", cloudSiteId);
    } else {
        CloudSite cloudSite = cloudSiteOp.get();
        MavenLikeVersioning aicV = new MavenLikeVersioning();
        aicV.setVersion(cloudSite.getCloudVersion());
        String vnfMin = vnfResource.getAicVersionMin();
        String vnfMax = vnfResource.getAicVersionMax();
        if ((vnfMin != null && !(aicV.isMoreRecentThan(vnfMin) || aicV.isTheSameVersion(vnfMin))) || (vnfMax != null && aicV.isMoreRecentThan(vnfMax))) {
            // ERROR
            String error = "VNF Resource type: " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID() + " VersionMin=" + vnfMin + " VersionMax:" + vnfMax + " NOT supported on Cloud: " + cloudSiteId + " with AIC_Version:" + cloudSite.getCloudVersion();
            logger.error("{} {} {} {} {}", MessageEnum.RA_CONFIG_EXC.toString(), error, "OpenStack", ErrorCode.BusinessProcessError.getValue(), "Exception - setVersion");
            logger.debug(error);
            throw new VnfException(error, MsoExceptionCategory.USERDATA);
        }
    }
    // End Version check
    VduInstance vduInstance = null;
    CloudInfo cloudInfo = new CloudInfo(cloudSiteId, cloudOwner, tenantId, null);
    // Use the VduPlugin.
    VduPlugin vduPlugin = getVduPlugin(cloudSiteId, cloudOwner);
    long subStartTime1 = System.currentTimeMillis();
    try {
        vduInstance = vduPlugin.queryVdu(cloudInfo, vfModuleName);
    } catch (VduException me) {
        // Failed to query the VDU due to a plugin exception.
        String error = "Create VF Module: Query " + vfModuleName + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
        logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, "VDU", "queryVdu", ErrorCode.DataError.getValue(), "Exception - queryVdu", me);
        logger.debug(error);
        // Convert to a generic VnfException
        me.addContext("CreateVFModule");
        throw new VnfException(me);
    }
    // More precise handling/messaging if the Module already exists
    if (vduInstance != null && !(vduInstance.getStatus().getState() == VduStateType.NOTFOUND)) {
        VduStateType status = vduInstance.getStatus().getState();
        logger.debug("Found Existing VDU, status=" + status);
        if (status == VduStateType.INSTANTIATED) {
            if (failIfExists != null && failIfExists) {
                // fail - it exists
                String error = "Create VF: Deployment " + vfModuleName + " already exists in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId;
                logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, "VDU", "queryVdu", ErrorCode.DataError.getValue(), "VF Module " + vfModuleName + " already exists");
                logger.debug(error);
                throw new VnfAlreadyExists(vfModuleName, cloudSiteId, cloudOwner, tenantId, vduInstance.getVduInstanceId());
            } else {
                // Found existing deployment and client has not requested "failIfExists".
                // Populate the outputs from the existing deployment.
                vnfId.value = vduInstance.getVduInstanceId();
                return;
            }
        } else // Check through various detailed error cases
        if (status == VduStateType.INSTANTIATING || status == VduStateType.DELETING || status == VduStateType.UPDATING) {
            // fail - it's in progress - return meaningful error
            String error = "Create VF: Deployment " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + "; please wait for it to complete, or fix manually.";
            logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, "VDU", "queryVdu", ErrorCode.DataError.getValue(), "VF Module " + vfModuleName + " already exists");
            logger.debug(error);
            throw new VnfAlreadyExists(vfModuleName, cloudSiteId, cloudOwner, tenantId, vduInstance.getVduInstanceId());
        } else if (status == VduStateType.FAILED) {
            // fail - it exists and is in a FAILED state
            String error = "Create VF: Deployment " + vfModuleName + " already exists and is in FAILED state in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
            logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, "VDU", "queryVdu", ErrorCode.DataError.getValue(), "VF Module " + vfModuleName + " already exists and is in FAILED state");
            logger.debug(error);
            throw new VnfAlreadyExists(vfModuleName, cloudSiteId, cloudOwner, tenantId, vduInstance.getVduInstanceId());
        } else if (status == VduStateType.UNKNOWN) {
            // fail - it exists and is in a UNKNOWN state
            String error = "Create VF: Deployment " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
            logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, "VDU", "queryVdu", ErrorCode.DataError.getValue(), "VF Module " + vfModuleName + " already exists and is in " + status.toString() + " state");
            logger.debug(error);
            throw new VnfAlreadyExists(vfModuleName, cloudSiteId, cloudOwner, tenantId, vduInstance.getVduInstanceId());
        } else {
            // Unexpected, since all known status values have been tested for
            String error = "Create VF: Deployment " + vfModuleName + " already exists with unexpected status " + status.toString() + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
            logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, "VDU", "queryVdu", ErrorCode.DataError.getValue(), "VF Module " + vfModuleName + " already exists and is in an unknown state");
            logger.debug(error);
            throw new VnfAlreadyExists(vfModuleName, cloudSiteId, cloudOwner, tenantId, vduInstance.getVduInstanceId());
        }
    }
    // Collect outputs from Base Modules and Volume Modules
    Map<String, Object> baseModuleOutputs = null;
    Map<String, Object> volumeGroupOutputs = null;
    // If a Volume Group was provided, query its outputs for inclusion in Module input parameters
    if (volumeGroupId != null) {
        long subStartTime2 = System.currentTimeMillis();
        VduInstance volumeVdu = null;
        try {
            volumeVdu = vduPlugin.queryVdu(cloudInfo, volumeGroupId);
        } catch (VduException me) {
            // Failed to query the Volume Group VDU due to a plugin exception.
            String error = "Create VF Module: Query Volume Group " + volumeGroupId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
            logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), volumeGroupId, cloudOwner, cloudSiteId, tenantId, "VDU", "queryVdu(volume)", ErrorCode.DataError.getValue(), "Exception - queryVdu(volume)", me);
            logger.debug(error);
            // Convert to a generic VnfException
            me.addContext("CreateVFModule(QueryVolume)");
            throw new VnfException(me);
        }
        if (volumeVdu == null || volumeVdu.getStatus().getState() == VduStateType.NOTFOUND) {
            String error = "Create VFModule: Attached Volume Group DOES NOT EXIST " + volumeGroupId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " USER ERROR";
            logger.error("{} {} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), volumeGroupId, cloudOwner, cloudSiteId, tenantId, error, "VDU", "queryVdu(volume)", ErrorCode.BusinessProcessError.getValue(), "Create VFModule: Attached Volume Group " + "DOES NOT EXIST");
            logger.debug(error);
            throw new VnfException(error, MsoExceptionCategory.USERDATA);
        } else {
            logger.debug("Found nested volume group");
            volumeGroupOutputs = volumeVdu.getOutputs();
            this.sendMapToDebug(volumeGroupOutputs, "volumeGroupOutputs");
        }
    }
    if (vfModule.getIsBase()) {
        logger.debug("This is a BASE Module request");
    } else {
        logger.debug("This is an Add-On Module request");
        // Add-on Volume requests may or may not specify a base.
        if (!isVolumeRequest && baseVfModuleId == null) {
            logger.debug("WARNING:  Add-on Module request - no Base Module ID provided");
        }
        if (baseVfModuleId != null) {
            long subStartTime2 = System.currentTimeMillis();
            VduInstance baseVdu = null;
            try {
                baseVdu = vduPlugin.queryVdu(cloudInfo, baseVfModuleId);
            } catch (MsoException me) {
                // Failed to query the Base VF Module due to a Vdu Plugin exception.
                String error = "Create VF Module: Query Base " + baseVfModuleId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
                logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), baseVfModuleId, cloudOwner, cloudSiteId, tenantId, "VDU", "queryVdu(Base)", ErrorCode.DataError.getValue(), "Exception - queryVdu(Base)", me);
                logger.debug(error);
                // Convert to a generic VnfException
                me.addContext("CreateVFModule(QueryBase)");
                throw new VnfException(me);
            }
            if (baseVdu == null || baseVdu.getStatus().getState() == VduStateType.NOTFOUND) {
                String error = "Create VFModule: Base Module DOES NOT EXIST " + baseVfModuleId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " USER ERROR";
                logger.error("{} {} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), baseVfModuleId, cloudOwner, cloudSiteId, tenantId, error, "VDU", "queryVdu(Base)", ErrorCode.BusinessProcessError.getValue(), "Create VFModule: Base Module DOES NOT EXIST");
                logger.debug(error);
                throw new VnfException(error, MsoExceptionCategory.USERDATA);
            } else {
                logger.debug("Found base module");
                baseModuleOutputs = baseVdu.getOutputs();
                this.sendMapToDebug(baseModuleOutputs, "baseModuleOutputs");
            }
        }
    }
    // NOTE: For this section, heatTemplate is used for all template artifacts.
    // In final implementation (post-POC), the template object would either be generic or there would
    // be a separate DB Table/Object for different sub-orchestrators.
    // NOTE: The template is fixed for the VF Module. The environment is part of the customization.
    HeatTemplate heatTemplate = null;
    HeatEnvironment heatEnvironment = null;
    if (isVolumeRequest) {
        heatTemplate = vfModule.getVolumeHeatTemplate();
        heatEnvironment = vfModuleCust.getVolumeHeatEnv();
    } else {
        heatTemplate = vfModule.getModuleHeatTemplate();
        heatEnvironment = vfModuleCust.getHeatEnvironment();
    }
    if (heatTemplate == null) {
        String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", modelCustomizationUuid=" + modelCustomizationUuid + ", vfModuleUuid=" + vfModule.getModelUUID() + ", reqType=" + requestType;
        logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template ID", vfModuleType, "VNF", ErrorCode.DataError.getValue(), error);
        logger.debug(error);
        throw new VnfException(error, MsoExceptionCategory.INTERNAL);
    } else {
        logger.debug("Got HEAT Template from DB: " + heatTemplate.getHeatTemplate());
    }
    if (heatEnvironment == null) {
        String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType + ", modelCustomizationUuid=" + modelCustomizationUuid + ", vfModuleUuid=" + vfModule.getModelUUID() + ", reqType=" + requestType;
        logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Environment ID", "OpenStack", ErrorCode.DataError.getValue(), error);
        throw new VnfException(error, MsoExceptionCategory.INTERNAL);
    } else {
        logger.debug("Got Heat Environment from DB: " + heatEnvironment.getEnvironment());
    }
    // Create the combined set of parameters from the incoming request, base-module outputs,
    // volume-module outputs. Also, convert all variables to their native object types.
    HashMap<String, Object> goldenInputs = new HashMap<String, Object>();
    List<String> extraInputs = new ArrayList<String>();
    Boolean skipInputChecks = false;
    if (skipInputChecks) {
        goldenInputs = new HashMap<String, Object>();
        for (String key : inputs.keySet()) {
            goldenInputs.put(key, inputs.get(key));
        }
    } else {
        // Build maps for the parameters (including aliases) to simplify checks
        HashMap<String, HeatTemplateParam> params = new HashMap<String, HeatTemplateParam>();
        Set<HeatTemplateParam> paramSet = heatTemplate.getParameters();
        logger.debug("paramSet has " + paramSet.size() + " entries");
        for (HeatTemplateParam htp : paramSet) {
            params.put(htp.getParamName(), htp);
            // Include aliases.
            String alias = htp.getParamAlias();
            if (alias != null && !alias.equals("") && !params.containsKey(alias)) {
                params.put(alias, htp);
            }
        }
        // First, convert all inputs to their "template" type
        for (String key : inputs.keySet()) {
            if (params.containsKey(key)) {
                Object value = convertInputValue(inputs.get(key), params.get(key));
                if (value != null) {
                    goldenInputs.put(key, value);
                } else {
                    logger.debug("Failed to convert input " + key + "='" + inputs.get(key) + "' to " + params.get(key).getParamType());
                }
            } else {
                extraInputs.add(key);
            }
        }
        if (!extraInputs.isEmpty()) {
            // Add multicloud inputs
            for (String key : MsoMulticloudUtils.MULTICLOUD_INPUTS) {
                if (extraInputs.contains(key)) {
                    goldenInputs.put(key, inputs.get(key));
                    extraInputs.remove(key);
                    if (extraInputs.isEmpty()) {
                        break;
                    }
                }
            }
            logger.debug("Ignoring extra inputs: " + extraInputs);
        }
        // Next add in Volume Group Outputs if there are any. Copy directly without conversions.
        if (volumeGroupOutputs != null && !volumeGroupOutputs.isEmpty()) {
            for (String key : volumeGroupOutputs.keySet()) {
                if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
                    goldenInputs.put(key, volumeGroupOutputs.get(key));
                }
            }
        }
        // Next add in Base Module Outputs if there are any. Copy directly without conversions.
        if (baseModuleOutputs != null && !baseModuleOutputs.isEmpty()) {
            for (String key : baseModuleOutputs.keySet()) {
                if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
                    goldenInputs.put(key, baseModuleOutputs.get(key));
                }
            }
        }
        // TODO: The model should support a mechanism to pre-assign default parameter values
        // per "customization" (i.e. usage) of a given module. In HEAT, this is specified by
        // an Environment file. There is not a general mechanism in the model to handle this.
        // For the general case, any such parameter/values can be added dynamically to the
        // inputs (only if not already specified).
        // Check that required parameters have been supplied from any of the sources
        String missingParams = null;
        boolean checkRequiredParameters = true;
        try {
            String propertyString = this.environment.getProperty(MsoVnfPluginAdapterImpl.CHECK_REQD_PARAMS);
            if ("false".equalsIgnoreCase(propertyString) || "n".equalsIgnoreCase(propertyString)) {
                checkRequiredParameters = false;
                logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking..." + MsoVnfPluginAdapterImpl.CHECK_REQD_PARAMS);
            }
        } catch (Exception e) {
            // No problem - default is true
            logger.debug("An exception occured trying to get property " + MsoVnfPluginAdapterImpl.CHECK_REQD_PARAMS, e);
        }
        // Do the actual parameter checking.
        // Include looking at the ENV file as a valid definition of a parameter value.
        // TODO: This handling of ENV applies only to Heat. A general mechanism to
        // support pre-set parameter/values does not yet exist in the model.
        // 
        StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
        MsoHeatEnvironmentEntry mhee = new MsoHeatEnvironmentEntry(sb);
        for (HeatTemplateParam parm : heatTemplate.getParameters()) {
            if (parm.isRequired() && (!goldenInputs.containsKey(parm.getParamName()))) {
                if (mhee != null && mhee.containsParameter(parm.getParamName())) {
                    logger.debug("Required parameter " + parm.getParamName() + " appears to be in environment - do not count as missing");
                } else {
                    logger.debug("adding to missing parameters list: " + parm.getParamName());
                    if (missingParams == null) {
                        missingParams = parm.getParamName();
                    } else {
                        missingParams += "," + parm.getParamName();
                    }
                }
            }
        }
        if (missingParams != null) {
            if (checkRequiredParameters) {
                // Problem - missing one or more required parameters
                String error = "Create VFModule: Missing Required inputs: " + missingParams;
                logger.error("{} {} {} {} {}", MessageEnum.RA_MISSING_PARAM.toString(), missingParams, "VDU", ErrorCode.DataError.getValue(), "Create VFModule: Missing Required inputs");
                logger.debug(error);
                throw new VnfException(error, MsoExceptionCategory.USERDATA);
            } else {
                logger.debug("found missing parameters [" + missingParams + "] - but checkRequiredParameters is false - " + "will not block");
            }
        } else {
            logger.debug("No missing parameters found - ok to proceed");
        }
    }
    // NOTE: END PARAMETER CHECKING
    // Here we go... ready to deploy the VF Module.
    long instantiateVduStartTime = System.currentTimeMillis();
    if (backout == null)
        backout = true;
    try {
        // Construct the VDU Model structure to pass to the targeted VduPlugin
        VduModelInfo vduModel = null;
        if (!isVolumeRequest) {
            vduModel = vduMapper.mapVfModuleCustomizationToVdu(vfModuleCust);
        } else {
            vduModel = vduMapper.mapVfModuleCustVolumeToVdu(vfModuleCust);
        }
        // Invoke the VduPlugin to instantiate the VF Module
        vduInstance = vduPlugin.instantiateVdu(cloudInfo, vfModuleName, goldenInputs, vduModel, backout);
    } catch (VduException me) {
        // Failed to instantiate the VDU.
        me.addContext("CreateVFModule");
        String error = "Create VF Module " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
        logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudOwner, cloudSiteId, tenantId, "VDU", ErrorCode.DataError.getValue(), "MsoException - instantiateVdu", me);
        logger.debug(error);
        // Convert to a generic VnfException
        throw new VnfException(me);
    } catch (NullPointerException npe) {
        String error = "Create VFModule " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + npe;
        logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudOwner, cloudSiteId, tenantId, "VDU", ErrorCode.DataError.getValue(), "NullPointerException - instantiateVdu", npe);
        logger.debug(error);
        logger.debug("NULL POINTER EXCEPTION at vduPlugin.instantiateVdu", npe);
        throw new VnfException("NullPointerException during instantiateVdu");
    } catch (Exception e) {
        String error = "Create VFModule " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + e;
        logger.debug("Unhandled exception at vduPlugin.instantiateVdu", e);
        logger.debug(error);
        throw new VnfException("Exception during instantiateVdu: " + e.getMessage());
    }
    vnfId.value = vduInstance.getVduInstanceId();
    logger.debug("VF Module " + vfModuleName + " successfully created");
    return;
}
Also used : HashMap(java.util.HashMap) HeatEnvironment(org.onap.so.db.catalog.beans.HeatEnvironment) VnfAlreadyExists(org.onap.so.adapters.vnf.exceptions.VnfAlreadyExists) ArrayList(java.util.ArrayList) VfModule(org.onap.so.db.catalog.beans.VfModule) VnfResource(org.onap.so.db.catalog.beans.VnfResource) VnfException(org.onap.so.adapters.vnf.exceptions.VnfException) MavenLikeVersioning(org.onap.so.db.catalog.utils.MavenLikeVersioning) VduPlugin(org.onap.so.adapters.vdu.VduPlugin) MsoException(org.onap.so.openstack.exceptions.MsoException) CloudInfo(org.onap.so.adapters.vdu.CloudInfo) VduInstance(org.onap.so.adapters.vdu.VduInstance) VduException(org.onap.so.adapters.vdu.VduException) JsonParseException(com.fasterxml.jackson.core.JsonParseException) VnfException(org.onap.so.adapters.vnf.exceptions.VnfException) MsoException(org.onap.so.openstack.exceptions.MsoException) MsoHeatEnvironmentEntry(org.onap.so.openstack.utils.MsoHeatEnvironmentEntry) VduStateType(org.onap.so.adapters.vdu.VduStateType) HeatTemplate(org.onap.so.db.catalog.beans.HeatTemplate) CloudSite(org.onap.so.db.catalog.beans.CloudSite) VduModelInfo(org.onap.so.adapters.vdu.VduModelInfo) VfModuleCustomization(org.onap.so.db.catalog.beans.VfModuleCustomization) VduException(org.onap.so.adapters.vdu.VduException) HeatTemplateParam(org.onap.so.db.catalog.beans.HeatTemplateParam)

Example 3 with MsoHeatEnvironmentEntry

use of org.onap.so.openstack.utils.MsoHeatEnvironmentEntry in project so by onap.

the class MsoVnfAdapterImpl method createVfModule.

// TODO remove polling
public void createVfModule(String cloudSiteId, String cloudOwner, String tenantId, String vnfType, String vnfVersion, String genericVnfName, String vnfName, String vfModuleId, String requestType, String volumeGroupHeatStackId, String baseVfHeatStackId, String modelCustomizationUuid, Map<String, Object> inputs, Boolean failIfExists, Boolean backout, Boolean enableBridge, MsoRequest msoRequest, Holder<String> stackId) throws VnfException {
    String vfModuleName = vnfName;
    String vfModuleType = vnfType;
    String vfVersion = vnfVersion;
    String mcu = modelCustomizationUuid;
    boolean useMCUuid = false;
    if (mcu != null && !mcu.isEmpty()) {
        if ("null".equalsIgnoreCase(mcu)) {
            logger.debug("modelCustomizationUuid: passed in as the string 'null' - will ignore: " + modelCustomizationUuid);
            useMCUuid = false;
            mcu = "";
        } else {
            logger.debug("Found modelCustomizationUuid! Will use that: {}", mcu);
            useMCUuid = true;
        }
    }
    String requestTypeString = "";
    if (requestType != null && !"".equals(requestType)) {
        requestTypeString = requestType;
    }
    String nestedStackId = null;
    if (volumeGroupHeatStackId != null && !"".equals(volumeGroupHeatStackId) && !"null".equalsIgnoreCase(volumeGroupHeatStackId)) {
        nestedStackId = volumeGroupHeatStackId;
    }
    String nestedBaseStackId = null;
    if (baseVfHeatStackId != null && !"".equals(baseVfHeatStackId) && !"null".equalsIgnoreCase(baseVfHeatStackId)) {
        nestedBaseStackId = baseVfHeatStackId;
    }
    // This method will also handle doing things the "old" way - i.e., just orchestrate a VNF
    boolean oldWay = false;
    if (requestTypeString.startsWith("X")) {
        oldWay = true;
        logger.debug("orchestrating a VNF - *NOT* a module!");
        requestTypeString = requestTypeString.substring(1);
    }
    // let's parse out the request type we're being sent
    boolean isBaseRequest = false;
    boolean isVolumeRequest = false;
    if (requestTypeString.startsWith("VOLUME")) {
        isVolumeRequest = true;
    }
    logger.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
    // handle a nestedStackId if sent- this one would be for the volume - so applies to both Vf and Vnf
    StackInfo nestedHeatStack = null;
    Map<String, Object> nestedVolumeOutputs = null;
    if (nestedStackId != null) {
        try {
            logger.debug("Querying for nestedStackId = {}", nestedStackId);
            nestedHeatStack = msoHeatUtils.queryStack(cloudSiteId, cloudOwner, tenantId, nestedStackId);
        } catch (MsoException me) {
            // Failed to query the Stack due to an openstack exception.
            // Convert to a generic VnfException
            me.addContext(CREATE_VFM_MODULE);
            String error = "Create VFModule: Attached heatStack ID Query " + nestedStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
            logger.error(LoggingAnchor.NINE, MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, OPENSTACK, QUERY_STACK, ErrorCode.BusinessProcessError.getValue(), "MsoException trying to query nested stack", me);
            logger.debug("ERROR trying to query nested stack= {}", error);
            throw new VnfException(me);
        }
        if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
            String error = "Create VFModule: Attached heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " " + USER_ERROR;
            logger.error(LoggingAnchor.TEN, MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, error, OPENSTACK, QUERY_STACK, ErrorCode.BusinessProcessError.getValue(), "Create VFModule: Attached heatStack ID " + "DOES NOT EXIST");
            logger.debug(error);
            throw new VnfException(error, MsoExceptionCategory.USERDATA);
        } else {
            logger.debug("Found nested volume heat stack - copying values to inputs *later*");
            nestedVolumeOutputs = nestedHeatStack.getOutputs();
        }
    }
    // handle a nestedBaseStackId if sent- this is the stack ID of the base. Should be null for VNF requests
    StackInfo nestedBaseHeatStack = null;
    Map<String, Object> baseStackOutputs = null;
    if (nestedBaseStackId != null) {
        try {
            logger.debug("Querying for nestedBaseStackId = {}", nestedBaseStackId);
            nestedBaseHeatStack = msoHeatUtils.queryStack(cloudSiteId, cloudOwner, tenantId, nestedBaseStackId);
        } catch (MsoException me) {
            // Failed to query the Stack due to an openstack exception.
            // Convert to a generic VnfException
            me.addContext(CREATE_VFM_MODULE);
            String error = "Create VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
            logger.error(LoggingAnchor.NINE, MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, OPENSTACK, QUERY_STACK, ErrorCode.BusinessProcessError.getValue(), "MsoException trying to query nested base stack", me);
            logger.debug("ERROR trying to query nested base stack= {}", error);
            throw new VnfException(me);
        }
        if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
            String error = "Create VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " " + USER_ERROR;
            logger.error(LoggingAnchor.TEN, MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId, tenantId, error, OPENSTACK, QUERY_STACK, ErrorCode.BusinessProcessError.getValue(), "Create VFModule: Attached base heatStack ID DOES NOT EXIST");
            logger.debug("Exception occurred", error);
            throw new VnfException(error, MsoExceptionCategory.USERDATA);
        } else {
            logger.debug("Found nested base heat stack - these values will be copied to inputs *later*");
            baseStackOutputs = nestedBaseHeatStack.getOutputs();
        }
    }
    try {
        VfModule vf = null;
        VnfResource vnfResource = null;
        VfModuleCustomization vfmc = null;
        if (useMCUuid) {
            vfmc = vfModuleCustomRepo.findFirstByModelCustomizationUUIDOrderByCreatedDesc(mcu);
            if (vfmc != null)
                vf = vfmc.getVfModule();
            else
                vf = null;
            // this will be the new way going forward. We find the vf by mcu - otherwise, code is the same.
            if (vf == null) {
                logger.debug("Unable to find vfModuleCust with modelCustomizationUuid={}", mcu);
                String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid=" + mcu;
                logger.error(LoggingAnchor.SIX, MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VF Module ModelCustomizationUuid", modelCustomizationUuid, OPENSTACK, ErrorCode.DataError.getValue(), "Create VF Module: Unable to find vfModule with " + "modelCustomizationUuid=" + mcu);
                logger.debug(error);
                throw new VnfException(error, MsoExceptionCategory.USERDATA);
            } else {
                logger.trace("Found vfModuleCust entry {}", vfmc.toString());
            }
            if (vf.getIsBase()) {
                isBaseRequest = true;
                logger.debug("This is a BASE VF request!");
            } else {
                logger.debug("This is *not* a BASE VF request!");
                if (!isVolumeRequest && nestedBaseStackId == null) {
                    logger.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
                }
            }
        } else {
            // This is to support gamma only - get info from vnf_resource table
            if (vfVersion != null && !vfVersion.isEmpty()) {
                vnfResource = vnfResourceRepo.findByModelNameAndModelVersion(vnfType, vnfVersion);
            } else {
                vnfResource = vnfResourceRepo.findByModelName(vnfType);
            }
            if (vnfResource == null) {
                String error = "Create VNF: Unknown VNF Type: " + vnfType;
                logger.error(LoggingAnchor.SIX, MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VNF Type", vnfType, OPENSTACK, ErrorCode.DataError.getValue(), "Create VNF: Unknown VNF Type");
                logger.debug(error);
                throw new VnfException(error, MsoExceptionCategory.USERDATA);
            }
            logger.debug("Got VNF module definition from Catalog: {}", vnfResource.toString());
        }
        // if we have a vf Module - then we have to query to get the VnfResource record.
        if (!oldWay) {
            if (vf != null) {
                vnfResource = vf.getVnfResources();
            }
            if (vnfResource == null) {
                logger.debug("Unable to find vnfResource will not error for now...");
            }
        }
        String minVersionVnf = null;
        String maxVersionVnf = null;
        if (vnfResource != null) {
            try {
                minVersionVnf = vnfResource.getAicVersionMin();
                maxVersionVnf = vnfResource.getAicVersionMax();
            } catch (Exception e) {
                logger.debug("Unable to pull min/max version for this VNF Resource entry", e);
                minVersionVnf = null;
                maxVersionVnf = null;
            }
            if (minVersionVnf != null && "".equals(minVersionVnf)) {
                minVersionVnf = null;
            }
            if (maxVersionVnf != null && "".equals(maxVersionVnf)) {
                maxVersionVnf = null;
            }
        }
        if (minVersionVnf != null && maxVersionVnf != null) {
            MavenLikeVersioning aicV = new MavenLikeVersioning();
            // double check
            if (this.cloudConfig != null) {
                Optional<CloudSite> cloudSiteOpt = this.cloudConfig.getCloudSite(cloudSiteId);
                if (cloudSiteOpt.isPresent()) {
                    aicV.setVersion(cloudSiteOpt.get().getCloudVersion());
                    // Add code to handle unexpected values in here
                    boolean moreThanMin = true;
                    boolean equalToMin = true;
                    boolean moreThanMax = true;
                    boolean equalToMax = true;
                    boolean doNotTest = false;
                    try {
                        moreThanMin = aicV.isMoreRecentThan(minVersionVnf);
                        equalToMin = aicV.isTheSameVersion(minVersionVnf);
                        moreThanMax = aicV.isMoreRecentThan(maxVersionVnf);
                        equalToMax = aicV.isTheSameVersion(maxVersionVnf);
                    } catch (Exception e) {
                        logger.debug("An exception occurred while trying to test Cloud Version {} - will default to not check", e.getMessage(), e);
                        doNotTest = true;
                    }
                    if (!doNotTest) {
                        if (// aic >= min
                        (moreThanMin || equalToMin) && (equalToMax || !(moreThanMax))) {
                            // aic <= max
                            logger.debug("VNF Resource " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID() + " " + VERSION_MIN + " =" + minVersionVnf + " " + VERSION_MAX + " :" + maxVersionVnf + " supported on Cloud: " + cloudSiteId + " with AIC_Version:" + cloudSiteOpt.get().getCloudVersion());
                        } else {
                            // ERROR
                            String error = "VNF Resource type: " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID() + " " + VERSION_MIN + " =" + minVersionVnf + " " + VERSION_MAX + " :" + maxVersionVnf + " NOT supported on Cloud: " + cloudSiteId + " with AIC_Version:" + cloudSiteOpt.get().getCloudVersion();
                            logger.error(LoggingAnchor.FIVE, MessageEnum.RA_CONFIG_EXC.toString(), error, OPENSTACK, ErrorCode.BusinessProcessError.getValue(), "Exception - setVersion");
                            logger.debug(error);
                            throw new VnfException(error, MsoExceptionCategory.USERDATA);
                        }
                    } else {
                        logger.debug("bypassing testing Cloud version...");
                    }
                }
            // let this error out downstream to avoid introducing uncertainty at this stage
            } else {
                logger.debug("cloudConfig is NULL - cannot check cloud site version");
            }
        }
        // By the time we get here - heatTemplateId and heatEnvtId should be populated (or null)
        HeatTemplate heatTemplate = null;
        HeatEnvironment heatEnvironment = null;
        if (oldWay) {
            // This will handle old Gamma BrocadeVCE VNF
            heatTemplate = vnfResource.getHeatTemplates();
        } else {
            if (vf != null) {
                if (isVolumeRequest) {
                    heatTemplate = vf.getVolumeHeatTemplate();
                    heatEnvironment = vfmc.getVolumeHeatEnv();
                } else {
                    heatTemplate = vf.getModuleHeatTemplate();
                    heatEnvironment = vfmc.getHeatEnvironment();
                }
            }
        }
        if (heatTemplate == null) {
            String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", modelCustomizationUuid=" + mcu + ", vfModuleUuid=" + (vf != null ? vf.getModelUUID() : "null") + ", vnfResourceModelUuid=" + vnfResource.getModelUUID() + ", reqType=" + requestTypeString;
            logger.error(LoggingAnchor.SIX, MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template " + "ID", vfModuleType, OPENSTACK, ErrorCode.DataError.getValue(), error);
            logger.debug(error);
            throw new VnfException(error, MsoExceptionCategory.INTERNAL);
        } else {
            logger.debug("Got HEAT Template from DB: {}", heatTemplate.getHeatTemplate());
        }
        if (oldWay) {
            // This will handle old Gamma BrocadeVCE VNF
            logger.debug("No environment parameter found for this Type " + vfModuleType);
        } else {
            if (heatEnvironment == null) {
                String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType + ", modelCustomizationUuid=" + mcu + ", vfModuleUuid=" + (vf != null ? vf.getModelUUID() : "null") + ", vnfResourceModelUuid=" + vnfResource.getModelUUID() + ", reqType=" + requestTypeString;
                logger.error(LoggingAnchor.FIVE, MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat " + "Environment ID", OPENSTACK, ErrorCode.DataError.getValue(), error);
                logger.debug(error);
                throw new VnfException(error, MsoExceptionCategory.INTERNAL);
            } else {
                logger.debug("Got Heat Environment from DB: {}", heatEnvironment.getEnvironment());
            }
        }
        logger.debug("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId=" + heatTemplate.getArtifactUuid());
        List<HeatTemplate> nestedTemplates = heatTemplate.getChildTemplates();
        Map<String, Object> nestedTemplatesChecked = new HashMap<>();
        if (nestedTemplates != null && !nestedTemplates.isEmpty()) {
            // for debugging print them out
            logger.debug("Contents of nestedTemplates - to be added to files: on stack:");
            for (HeatTemplate entry : nestedTemplates) {
                nestedTemplatesChecked.put(entry.getTemplateName(), entry.getTemplateBody());
                logger.debug("Adding Nested Template", entry.getTemplateName());
            }
        } else {
            logger.debug("No nested templates found - nothing to do here");
            nestedTemplatesChecked = null;
        }
        // Also add the files: for any get_files associated with this vnf_resource_id
        // *if* there are any
        List<HeatFiles> heatFiles = null;
        Map<String, Object> heatFilesObjects = new HashMap<>();
        // Add ability to turn on adding get_files with volume requests (by property).
        boolean addGetFilesOnVolumeReq = false;
        try {
            String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ);
            if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
                addGetFilesOnVolumeReq = true;
                logger.debug("AddGetFilesOnVolumeReq - setting to true! {}", propertyString);
            }
        } catch (Exception e) {
            logger.debug("An error occured trying to get property " + MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ + " - default to false", e);
        }
        if (!isVolumeRequest || addGetFilesOnVolumeReq) {
            if (oldWay) {
                logger.debug("In MsoVnfAdapterImpl createVfModule, this should not happen, no heat files!");
            } else {
                // now use VF_MODULE_TO_HEAT_FILES table
                logger.debug("In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFilesForVfModule avec vfModuleId=" + vf.getModelUUID());
                heatFiles = vf.getHeatFiles();
            }
            if (heatFiles != null && !heatFiles.isEmpty()) {
                // add these to stack - to be done in createStack
                // here, we will map them to Map<String, Object> from
                // Map<String, HeatFiles>
                // this will match the nested templates format
                logger.debug("Contents of heatFiles - to be added to files: on stack");
                for (HeatFiles heatfile : heatFiles) {
                    logger.debug(heatfile.getFileName() + " -> " + heatfile.getFileBody());
                    heatFilesObjects.put(heatfile.getFileName(), heatfile.getFileBody());
                }
            } else {
                logger.debug("No heat files found -nothing to do here");
                heatFilesObjects = null;
            }
        }
        // Check that required parameters have been supplied
        String missingParams = null;
        List<String> paramList = new ArrayList<>();
        // consult the PARAM_ALIAS field to see if we've been
        // supplied an alias. Only check if we don't find it initially.
        // don't flag missing parameters if there's an environment - because they might be there.
        // And also new - add parameter to turn off checking all together if we find we're blocking orders we
        // shouldn't
        boolean checkRequiredParameters = true;
        try {
            String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
            if ("false".equalsIgnoreCase(propertyString) || "n".equalsIgnoreCase(propertyString)) {
                checkRequiredParameters = false;
                logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking..." + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
            }
        } catch (Exception e) {
            // No problem - default is true
            logger.debug("An exception occured trying to get property {}", MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
        }
        // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
        // Part 2: only submit to openstack the parameters in the envt that are in the heat template
        // Note this also removes any comments
        MsoHeatEnvironmentEntry mhee = null;
        if (heatEnvironment != null && heatEnvironment.getEnvironment() != null && heatEnvironment.getEnvironment().contains("parameters:")) {
            StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
            mhee = new MsoHeatEnvironmentEntry(sb);
            StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
            for (HeatTemplateParam parm : heatTemplate.getParameters()) {
                sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
            }
            if (!mhee.isValid()) {
                sb2.append("Environment says it's not valid! " + mhee.getErrorString());
            } else {
                sb2.append("\nEnvironment:");
                sb2.append(mhee.toFullString());
            }
            logger.debug(sb2.toString());
        } else {
            logger.debug("NO ENVIRONMENT for this entry");
        }
        // all variables converted to their native object types
        Map<String, Object> goldenInputs = null;
        ArrayList<String> parameterNames = new ArrayList<>();
        HashMap<String, String> aliasToParam = new HashMap<>();
        StringBuilder sb = new StringBuilder("\nTemplate Parameters:\n");
        int cntr = 0;
        try {
            for (HeatTemplateParam htp : heatTemplate.getParameters()) {
                sb.append("param[" + cntr++ + "]=" + htp.getParamName());
                parameterNames.add(htp.getParamName());
                if (htp.getParamAlias() != null && !"".equals(htp.getParamAlias())) {
                    aliasToParam.put(htp.getParamAlias(), htp.getParamName());
                    sb.append(" ** (alias=" + htp.getParamAlias() + ")");
                }
                sb.append("\n");
            }
            logger.debug(sb.toString());
        } catch (Exception e) {
            logger.debug("??An exception occurred trying to go through Parameter Names {}", e.getMessage(), e);
        }
        // Step 1 - convert what we got as inputs (Map<String, String>) to a
        // Map<String, Object> - where the object matches the param type identified in the template
        // This will also not copy over params that aren't identified in the template
        goldenInputs = msoHeatUtils.convertInputMap(inputs, heatTemplate);
        // Step 2 - now simply add the outputs as we received them - no need to convert to string
        logger.debug("Now add in the base stack outputs if applicable");
        msoHeatUtils.copyBaseOutputsToInputs(goldenInputs, baseStackOutputs, parameterNames, aliasToParam);
        // Step 3 - add the volume inputs if any
        logger.debug("Now add in the volume stack outputs if applicable");
        msoHeatUtils.copyBaseOutputsToInputs(goldenInputs, nestedVolumeOutputs, parameterNames, aliasToParam);
        for (HeatTemplateParam parm : heatTemplate.getParameters()) {
            logger.debug("Parameter:'" + parm.getParamName() + "', isRequired=" + parm.isRequired() + ", alias=" + parm.getParamAlias());
            if (parm.isRequired() && (goldenInputs == null || !goldenInputs.containsKey(parm.getParamName()))) {
                // The check for an alias was moved to the method in MsoHeatUtils - when we converted the
                // Map<String, String> to Map<String, Object>
                logger.debug("**Parameter " + parm.getParamName() + " is required and not in the inputs...check " + "environment");
                if (mhee != null && mhee.containsParameter(parm.getParamName())) {
                    logger.debug("Required parameter {} appears to be in environment - do not count as missing", parm.getParamName());
                } else {
                    logger.debug("adding to missing parameters list: {}", parm.getParamName());
                    if (missingParams == null) {
                        missingParams = parm.getParamName();
                    } else {
                        missingParams += "," + parm.getParamName();
                    }
                }
            }
            paramList.add(parm.getParamName());
        }
        if (missingParams != null) {
            if (checkRequiredParameters) {
                // Problem - missing one or more required parameters
                String error = "Create VFModule: Missing Required inputs: " + missingParams;
                logger.error(LoggingAnchor.FIVE, MessageEnum.RA_MISSING_PARAM.toString(), missingParams, OPENSTACK, ErrorCode.DataError.getValue(), "Create VFModule: Missing Required inputs");
                logger.debug(error);
                throw new VnfException(error, MsoExceptionCategory.USERDATA);
            } else {
                logger.debug("found missing parameters - but checkRequiredParameters is false - will not block");
            }
        } else {
            logger.debug("No missing parameters found - ok to proceed");
        }
        // We can now remove the recreating of the ENV with only legit params - that check is done for us,
        // and it causes problems with json that has arrays
        String newEnvironmentString = null;
        if (mhee != null) {
            newEnvironmentString = mhee.getRawEntry().toString();
        }
        // "Fix" the template if it has CR/LF (getting this from Oracle)
        String template = heatTemplate.getHeatTemplate();
        template = template.replaceAll("\r\n", "\n");
        // Have the tenant. Now deploy the stack itself
        // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
        // because we already checked for those.
        StackInfo heatStack = null;
        try {
            if (backout == null) {
                backout = true;
            }
            if (failIfExists == null) {
                failIfExists = false;
            }
            if (msoHeatUtils != null) {
                heatStack = msoHeatUtils.createStack(cloudSiteId, cloudOwner, tenantId, vfModuleName, null, template, goldenInputs, false, heatTemplate.getTimeoutMinutes(), newEnvironmentString, nestedTemplatesChecked, heatFilesObjects, backout.booleanValue(), failIfExists);
                String resource = VF_MODULE;
                if (isVolumeRequest) {
                    resource = VOLUME_GROUP;
                }
                if (msoRequest.getRequestId() != null) {
                    msoHeatUtils.updateResourceStatus(msoRequest.getRequestId(), heatStack.isOperationPerformed() ? String.format(RESOURCE_CREATED_STATUS_MESSAGE, resource) : String.format(RESOURCE_EXIST_STATUS_MESSAGE, resource, resource));
                }
            } else {
                throw new MsoHeatNotFoundException();
            }
        } catch (MsoException me) {
            me.addContext(CREATE_VFM_MODULE);
            logger.error("Error creating Stack", me);
            throw new VnfException(me);
        } catch (NullPointerException npe) {
            logger.error("Error creating Stack", npe);
            throw new VnfException("NullPointerException during heat.createStack");
        } catch (Exception e) {
            logger.error("Error creating Stack", e);
            throw new VnfException("Exception during heat.createStack! " + e.getMessage());
        }
        stackId.value = heatStack.getCanonicalName();
        logger.debug("VF Module {} successfully created", vfModuleName);
    } catch (Exception e) {
        logger.debug("unhandled exception in create VF", e);
        throw new VnfException("Exception during create VF " + e.getMessage());
    }
}
Also used : HashMap(java.util.HashMap) HeatEnvironment(org.onap.so.db.catalog.beans.HeatEnvironment) ArrayList(java.util.ArrayList) VfModule(org.onap.so.db.catalog.beans.VfModule) VnfResource(org.onap.so.db.catalog.beans.VnfResource) VnfException(org.onap.so.adapters.vnf.exceptions.VnfException) HeatFiles(org.onap.so.db.catalog.beans.HeatFiles) StackInfo(org.onap.so.openstack.beans.StackInfo) MavenLikeVersioning(org.onap.so.db.catalog.utils.MavenLikeVersioning) MsoException(org.onap.so.openstack.exceptions.MsoException) MsoHeatNotFoundException(org.onap.so.openstack.exceptions.MsoHeatNotFoundException) MsoHeatNotFoundException(org.onap.so.openstack.exceptions.MsoHeatNotFoundException) JsonParseException(com.fasterxml.jackson.core.JsonParseException) VnfException(org.onap.so.adapters.vnf.exceptions.VnfException) MsoException(org.onap.so.openstack.exceptions.MsoException) MsoHeatEnvironmentEntry(org.onap.so.openstack.utils.MsoHeatEnvironmentEntry) HeatTemplate(org.onap.so.db.catalog.beans.HeatTemplate) CloudSite(org.onap.so.db.catalog.beans.CloudSite) VfModuleCustomization(org.onap.so.db.catalog.beans.VfModuleCustomization) HeatTemplateParam(org.onap.so.db.catalog.beans.HeatTemplateParam)

Aggregations

JsonParseException (com.fasterxml.jackson.core.JsonParseException)3 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 VnfException (org.onap.so.adapters.vnf.exceptions.VnfException)3 CloudSite (org.onap.so.db.catalog.beans.CloudSite)3 HeatEnvironment (org.onap.so.db.catalog.beans.HeatEnvironment)3 HeatTemplate (org.onap.so.db.catalog.beans.HeatTemplate)3 HeatTemplateParam (org.onap.so.db.catalog.beans.HeatTemplateParam)3 VfModule (org.onap.so.db.catalog.beans.VfModule)3 VfModuleCustomization (org.onap.so.db.catalog.beans.VfModuleCustomization)3 VnfResource (org.onap.so.db.catalog.beans.VnfResource)3 MavenLikeVersioning (org.onap.so.db.catalog.utils.MavenLikeVersioning)3 MsoException (org.onap.so.openstack.exceptions.MsoException)3 MsoHeatEnvironmentEntry (org.onap.so.openstack.utils.MsoHeatEnvironmentEntry)3 HeatFiles (org.onap.so.db.catalog.beans.HeatFiles)2 StackInfo (org.onap.so.openstack.beans.StackInfo)2 MsoHeatNotFoundException (org.onap.so.openstack.exceptions.MsoHeatNotFoundException)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 Map (java.util.Map)1 CloudInfo (org.onap.so.adapters.vdu.CloudInfo)1