com.dell.asm.asmcore.asmmanager.client.util.ServiceTemplateClientUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.dell.asm.asmcore.asmmanager.client.util.ServiceTemplateClientUtil.java

Source

/**************************************************************************
 *   Copyright (c) 2015 Dell Inc. All rights reserved.                    *
 *                                                                        *
 * DELL INC. CONFIDENTIAL AND PROPRIETARY INFORMATION. This software may  *
 * only be supplied under the terms of a license agreement or             *
 * nondisclosure agreement with Dell Inc. and may not be copied or        *
 * disclosed except in accordance with the terms of such agreement.       *
 **************************************************************************/
package com.dell.asm.asmcore.asmmanager.client.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.dell.asm.asmcore.asmmanager.client.networkconfiguration.NetworkConfiguration;
import com.dell.asm.asmcore.asmmanager.client.servicetemplate.Network;
import com.dell.asm.asmcore.asmmanager.client.servicetemplate.ServiceTemplate;
import com.dell.asm.asmcore.asmmanager.client.servicetemplate.ServiceTemplateCategory;
import com.dell.asm.asmcore.asmmanager.client.servicetemplate.ServiceTemplateComponent;
import com.dell.asm.asmcore.asmmanager.client.servicetemplate.ServiceTemplateOption;
import com.dell.asm.asmcore.asmmanager.client.servicetemplate.ServiceTemplateSetting;
import com.dell.asm.asmcore.asmmanager.client.servicetemplate.ServiceTemplateSetting.ServiceTemplateSettingType;
import com.dell.asm.asmcore.asmmanager.client.servicetemplate.ServiceTemplateSettingIDs;
import com.dell.pg.asm.identitypool.api.common.model.NetworkType;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;

public class ServiceTemplateClientUtil {

    private static final Logger LOGGER = Logger.getLogger(ServiceTemplateClientUtil.class);
    /**
     * max number of port groups with the same network name i.e. ISCSI 1, ISCSI 2 etc
     */
    private static final int MAX_PG_NUM = 2;

    private static final ObjectMapper OBJECT_MAPPER = buildObjectMapper();

    private static ObjectMapper buildObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        AnnotationIntrospector ai = new JaxbAnnotationIntrospector(mapper.getTypeFactory());
        mapper.setAnnotationIntrospector(ai);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return mapper;
    }

    /**
     * Utility method that adds the upgraded service template components to the given service template
     *
     * @param serviceTemplate
     * @param upgradedComponents
     */
    public static void updateServiceTemplateWithUpgradedSettings(final ServiceTemplate serviceTemplate,
            final List<ServiceTemplateComponent> upgradedComponents) {

        if (serviceTemplate != null && CollectionUtils.isNotEmpty(upgradedComponents)) {
            final Map<String, ParameterEntry> parameterMap = generateServiceTemplateParameterMap(serviceTemplate);

            // override/update components with updates
            for (final ServiceTemplateComponent upgradedComponent : upgradedComponents) {
                for (final ServiceTemplateCategory upgradedResource : upgradedComponent.getResources()) {
                    for (final ServiceTemplateSetting upgradedParameter : upgradedResource.getParameters()) {
                        final String parameterMapKey = generateParameterMapKey(upgradedComponent, upgradedResource,
                                upgradedParameter);
                        if (parameterMap.containsKey(parameterMapKey)) {
                            final ParameterEntry parameterEntry = parameterMap.get(parameterMapKey);
                            parameterEntry.getParameter().setValue(upgradedParameter.getValue());
                        } else {
                            // this is a new parameter ??? LOG error
                            LOGGER.error("Parameter " + upgradedParameter.getId() + " cannot be found for resource "
                                    + upgradedResource.getId() + " on component " + upgradedComponent.getId());
                        }
                    }
                }
            }
        }
    }

    /**
     * Utility method to get a service template with only the invalid components that need to be upgraded
     *
     * @param serviceTemplate
     */
    public static void filterServiceTemplateForOnlyUpgradableSettings(final ServiceTemplate serviceTemplate) {
        if (serviceTemplate != null) {
            if (CollectionUtils.isEmpty(serviceTemplate.getComponents())) {
                // there are no components so there is nothing to upgrade 
                LOGGER.warn("Service template " + serviceTemplate.getId()
                        + " does not have any components to filter for upgradable parameters!");
                return;
            }

            Map<String, Map<String, ParameterEntry>> settingsMap = generateServiceTemplateSettingsMap(
                    serviceTemplate);
            // loop through template and add upgradable parameters to map
            final Map<String, ParameterEntry> upgradableParameterMap = new HashMap<String, ParameterEntry>();
            final List<String> importantDependencyTargets = new ArrayList();

            if (!serviceTemplate.getTemplateValid().isValid()) {
                for (final ServiceTemplateComponent component : serviceTemplate.getComponents()) {
                    if (!component.getComponentValid().isValid()) {
                        upgradeServiceTemplateComponents(upgradableParameterMap, settingsMap, component);
                    }
                }

                // create a map of dependency targets for options in all upgradable settings in template
                for (ParameterEntry entry : upgradableParameterMap.values()) {
                    if (entry.getParameter().getOptions() != null) {
                        for (ServiceTemplateOption option : entry.getParameter().getOptions()) {
                            if (StringUtils.isNotEmpty(option.getDependencyTarget())
                                    && !importantDependencyTargets.contains(option.getDependencyTarget())) {
                                importantDependencyTargets.add(option.getDependencyTarget());
                            }
                        }
                    }
                }

            }

            // now that the upgradable map has been generated loop through the templates parameters and
            // filter out parameters that are not upgradable
            for (final Iterator<ServiceTemplateComponent> componentIter = serviceTemplate.getComponents()
                    .iterator(); componentIter.hasNext();) {
                final ServiceTemplateComponent component = componentIter.next();
                if (CollectionUtils.isEmpty(component.getResources())) {
                    LOGGER.warn("Service template component " + component.getId()
                            + " does not have any resources to filter for upgradable parameters!");
                    continue;
                }
                for (final Iterator<ServiceTemplateCategory> resourceIter = component.getResources()
                        .iterator(); resourceIter.hasNext();) {
                    final ServiceTemplateCategory resource = resourceIter.next();
                    if (CollectionUtils.isEmpty(resource.getParameters())) {
                        LOGGER.warn("Service template resource " + resource.getId()
                                + " does not have any parameters to filter for upgradable parameters!");
                        continue;
                    }
                    for (final Iterator<ServiceTemplateSetting> parameterIter = resource.getParameters()
                            .iterator(); parameterIter.hasNext();) {
                        final ServiceTemplateSetting parameter = parameterIter.next();
                        if (!isImportantParameter(upgradableParameterMap, component, resource, parameter,
                                importantDependencyTargets)) {
                            parameterIter.remove();
                        }
                    }
                    // if there are no parameters left in the resource then remove
                    if (CollectionUtils.isEmpty(resource.getParameters())) {
                        resourceIter.remove();
                    }
                }
                // if there are no resources left in the component then remove
                if (CollectionUtils.isEmpty(component.getResources())) {
                    componentIter.remove();
                }
            }
        }
    }

    /**
     * Recursive Method for determing upgradable settings and finding all parent and child dependencies
     * along with the dependencies of the dependents.
     *
     * @param upgradableParameterMap
     * @param settingsMap
     * @param component
     */
    private static void upgradeServiceTemplateComponents(Map<String, ParameterEntry> upgradableParameterMap,
            Map<String, Map<String, ParameterEntry>> settingsMap, ServiceTemplateComponent component) {
        if (!component.getComponentValid().isValid()) {
            for (final ServiceTemplateCategory resource : component.getResources()) {
                for (final ServiceTemplateSetting parameter : resource.getParameters()) {
                    String parameterKey = generateParameterMapKey(component, resource, parameter);
                    //If already in the upgradable map ignore
                    if (upgradableParameterMap.get(parameterKey) == null) {
                        //determine if child of a setting already added to the upgradable map
                        if (childDependencyForUpgradableParameter(settingsMap, component, parameter,
                                upgradableParameterMap)) {
                            LOGGER.info("Found child dependency parameter of parameter that needs to be upgraded "
                                    + parameter);
                            updateUpgradableMapParameters(settingsMap, upgradableParameterMap, component,
                                    parameterKey, findSettingDependency(settingsMap, component, parameter.getId()));
                        } else if (isVisibleRequiredParameter(parameter)
                                && requiredDependenciesSatisfied(settingsMap, component, parameter)
                                && isMissingPasswordOrBlank(parameter)) {
                            LOGGER.info("Found invalid parameter that needs to be upgraded " + parameter);
                            updateUpgradableMapParameters(settingsMap, upgradableParameterMap, component,
                                    parameterKey, findSettingDependency(settingsMap, component, parameter.getId()));
                        }
                    }
                }
            }
        }
    }

    /**
     * For the passed parameter check its options - if an option has a dependency target, add this D.T. to a map.
     * Also if a parameter has dependency target itself - add it to a map.
     *
     * @param settingsMap
     * @param upgradableParameterMap
     * @param component
     * @param parameterKey
     * @param parameterEntry
     */
    private static void updateUpgradableMapParameters(Map<String, Map<String, ParameterEntry>> settingsMap,
            Map<String, ParameterEntry> upgradableParameterMap, ServiceTemplateComponent component,
            String parameterKey, ParameterEntry parameterEntry) {

        if (upgradableParameterMap.get(parameterKey) == null) {
            // check if the upgradable setting has an option with a dependency target
            for (ServiceTemplateOption option : parameterEntry.getParameter().getOptions()) {
                if (StringUtils.isNotBlank(option.getDependencyTarget())) {
                    LOGGER.info("Found option dependency parameter " + option.getDependencyTarget()
                            + " of parameter that needs to be upgraded " + parameterEntry.getParameter().getId());
                    ParameterEntry optionParameterEntry = findSettingDependency(settingsMap, component,
                            option.getDependencyTarget());
                    String optionTargetKey = generateParameterMapKey(optionParameterEntry.getComponent(),
                            optionParameterEntry.getResource(), optionParameterEntry.getParameter());
                    if (upgradableParameterMap.get(optionTargetKey) == null) {
                        upgradableParameterMap.put(optionTargetKey, optionParameterEntry);
                        upgradeServiceTemplateComponents(upgradableParameterMap, settingsMap, component);
                    }
                }
            }

            if (StringUtils.isNotBlank(parameterEntry.getParameter().getDependencyTarget())) {
                ParameterEntry dependentEntry = findSettingDependency(settingsMap, component,
                        parameterEntry.getParameter().getDependencyTarget());
                if (dependentEntry != null) {
                    String componentDependencyTargetKey = generateParameterMapKey(dependentEntry.getComponent(),
                            dependentEntry.getResource(), dependentEntry.getParameter());
                    updateUpgradableMapParameters(settingsMap, upgradableParameterMap, component,
                            componentDependencyTargetKey, dependentEntry);
                }
            }

            upgradableParameterMap.put(parameterKey, parameterEntry);
            upgradeServiceTemplateComponents(upgradableParameterMap, settingsMap, component);
        }
    }

    /**
     * Adds a setting to the settingsMap
     *
     * @param settingsMap
     * @param component
     * @param resource
     * @param parameter
     */
    private static void updateSettingsMap(Map<String, Map<String, ParameterEntry>> settingsMap,
            ServiceTemplateComponent component, ServiceTemplateCategory resource,
            ServiceTemplateSetting parameter) {
        String settingKey = generateSimpleKey(component.getId(), parameter.getId());
        Map<String, ParameterEntry> settingEntry = settingsMap.get(settingKey);
        if (settingEntry == null) {
            settingEntry = new HashMap<String, ParameterEntry>();
            settingsMap.put(settingKey, settingEntry);
        }
        settingEntry.put(generateParameterMapKey(component, resource, parameter),
                new ParameterEntry(component, resource, parameter));
    }

    /**
     * Searches the settingsMap for an entry and then returns the ParameterEntry for the setting id
     *
     * @param settingsMap
     * @param component
     * @param parameterId
     * @return
     */
    private static ParameterEntry findSettingDependency(final Map<String, Map<String, ParameterEntry>> settingsMap,
            ServiceTemplateComponent component, String parameterId) {
        ParameterEntry parameterEntry = null;
        String settingsKey = generateSimpleKey(component.getId(), parameterId);
        Map<String, ParameterEntry> settingsEntry = settingsMap.get(settingsKey);
        if (settingsEntry != null) {
            //Should only be one entry in the list.
            for (Map.Entry<String, ParameterEntry> entry : settingsEntry.entrySet()) {
                parameterEntry = entry.getValue();
            }
        }
        return parameterEntry;
    }

    /**
     * Check to see if the parameter should be kept
     *
     * @param upgradableParameterMap
     * @param component
     * @param resource
     * @param parameter
     * @return
     */
    private static boolean isImportantParameter(Map<String, ParameterEntry> upgradableParameterMap,
            ServiceTemplateComponent component, ServiceTemplateCategory resource, ServiceTemplateSetting parameter,
            List<String> importantDependencyTargets) {
        String parameterKey = generateParameterMapKey(component, resource, parameter);
        if (upgradableParameterMap.containsKey(parameterKey))
            return true;

        // check options for each parameter. They might depend on this parameter. We can't catch it earlier.
        if (importantDependencyTargets.contains(parameter.getId()))
            return true;

        return false;
    }

    public static boolean containsUpgradableSettings(final ServiceTemplate serviceTemplate) {
        if (serviceTemplate != null) {
            if (CollectionUtils.isEmpty(serviceTemplate.getComponents())) {
                // there are no components so there is nothing to upgrade
                return false;
            }

            Map<String, Map<String, ParameterEntry>> settingsMap = generateServiceTemplateSettingsMap(
                    serviceTemplate);
            // loop through template and find upgradable parameters
            if (!serviceTemplate.getTemplateValid().isValid()) {
                for (final ServiceTemplateComponent component : serviceTemplate.getComponents()) {
                    if (!component.getComponentValid().isValid()) {
                        for (final ServiceTemplateCategory resource : component.getResources()) {
                            for (final ServiceTemplateSetting parameter : resource.getParameters()) {
                                if (isVisibleRequiredParameter(parameter)
                                        && requiredDependenciesSatisfied(settingsMap, component, parameter)
                                        && isMissingPasswordOrBlank(parameter)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    private static boolean isVisibleRequiredParameter(final ServiceTemplateSetting parameter) {
        if (parameter != null) {
            return !parameter.isHideFromTemplate() && parameter.isRequired();
        }
        return Boolean.FALSE;
    }

    private static boolean requiredDependenciesSatisfied(final Map<String, Map<String, ParameterEntry>> settingsMap,
            final ServiceTemplateComponent component, final ServiceTemplateSetting parameter) {
        if (StringUtils.isBlank(parameter.getDependencyTarget())) {
            // there are no further dependencies
            return Boolean.TRUE;
        } else {
            final String settingsKey = generateSimpleKey(component.getId(), parameter.getId());
            Map<String, ParameterEntry> settingsEntry = settingsMap.get(settingsKey);
            if (settingsEntry != null) {
                final ParameterEntry dependencyTarget = findSettingDependency(settingsMap, component,
                        parameter.getDependencyTarget());
                if (dependencyTarget != null) {
                    final String dependencyValue = dependencyTarget.getParameter().getValue();
                    for (final String value : StringUtils.split(parameter.getDependencyValue(), ",")) {
                        if (StringUtils.equals(dependencyValue, value)) {
                            LOGGER.info("Found required dependency " + dependencyTarget.getParameter().getId()
                                    + ": " + value);
                            // NOTE[fcarta] Its understood there is a possibility for circular dependencies. In the
                            // event an error like this should occur we are ok with a StackOverflowException being
                            // thrown. This would indicate a programmatic error in a default template. Currently users dont
                            // have the ability to modify default templates.
                            return requiredDependenciesSatisfied(settingsMap, component,
                                    dependencyTarget.getParameter());
                        }
                    }
                }
            }
        }
        // dependency not found or dependency value match not made
        return Boolean.FALSE;
    }

    /**
     * Check to see if dependency is in the upgradable map
     *
     * @param component
     * @param parameter
     * @param upgradableParameterMap
     * @return
     */
    private static boolean childDependencyForUpgradableParameter(
            Map<String, Map<String, ParameterEntry>> settingsMap, ServiceTemplateComponent component,
            ServiceTemplateSetting parameter, Map<String, ParameterEntry> upgradableParameterMap) {
        if (StringUtils.isBlank(parameter.getDependencyTarget())) {
            // there are no further dependencies
            return Boolean.FALSE;
        } else {
            final ParameterEntry dependencyEntry = findSettingDependency(settingsMap, component,
                    parameter.getDependencyTarget());
            final String parentDependencyKey = generateParameterMapKey(dependencyEntry.getComponent(),
                    dependencyEntry.getResource(), dependencyEntry.getParameter());
            if (upgradableParameterMap.get(parentDependencyKey) != null) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    private static boolean isMissingPasswordOrBlank(final ServiceTemplateSetting parameter) {
        if (parameter != null) {
            if (ServiceTemplateSettingType.PASSWORD.equals(parameter.getType())) {
                // if this is a password field determine if its is missing (when it is "") or just removed (when null)
                return parameter.getValue() != null && StringUtils.isBlank(parameter.getValue());
            } else {
                // not a password field
                return StringUtils.isBlank(parameter.getValue());
            }
        }
        return Boolean.FALSE;
    }

    private static Map<String, ParameterEntry> generateServiceTemplateParameterMap(
            final ServiceTemplate serviceTemplate) {
        final Map<String, ParameterEntry> parameterMap = new HashMap<String, ParameterEntry>();
        for (final ServiceTemplateComponent component : serviceTemplate.getComponents()) {
            for (final ServiceTemplateCategory resource : component.getResources()) {
                for (final ServiceTemplateSetting parameter : resource.getParameters()) {
                    parameterMap.put(generateParameterMapKey(component, resource, parameter),
                            new ParameterEntry(component, resource, parameter));
                }
            }
        }
        return parameterMap;
    }

    /**
     * Loops through all components, resources, and parameters building a reference based on component and parameter
     *
     * @param serviceTemplate
     * @return
     */
    private static Map<String, Map<String, ParameterEntry>> generateServiceTemplateSettingsMap(
            final ServiceTemplate serviceTemplate) {
        final Map<String, Map<String, ParameterEntry>> settingsMap = new HashMap<String, Map<String, ParameterEntry>>();
        for (final ServiceTemplateComponent component : serviceTemplate.getComponents()) {
            for (final ServiceTemplateCategory resource : component.getResources()) {
                for (final ServiceTemplateSetting parameter : resource.getParameters()) {
                    updateSettingsMap(settingsMap, component, resource, parameter);
                }
            }
        }
        return settingsMap;
    }

    private static String generateParameterMapKey(final ServiceTemplateComponent component,
            final ServiceTemplateCategory resource, final ServiceTemplateSetting parameter) {
        return generateSimpleKey(component.getId(), resource.getId(), parameter.getId());
    }

    private static String generateSimpleKey(final String... keys) {
        return StringUtils.join(keys, "_");
    }

    private static class ParameterEntry {
        private final ServiceTemplateComponent component;
        private final ServiceTemplateCategory resource;
        private final ServiceTemplateSetting parameter;

        private ParameterEntry(final ServiceTemplateComponent component, final ServiceTemplateCategory resource,
                final ServiceTemplateSetting parameter) {
            this.component = component;
            this.resource = resource;
            this.parameter = parameter;
        }

        public ServiceTemplateComponent getComponent() {
            return component;
        }

        public ServiceTemplateCategory getResource() {
            return resource;
        }

        public ServiceTemplateSetting getParameter() {
            return parameter;
        }
    }

    public static List<Network> findManagementNetworks(ServiceTemplateComponent component) {
        ServiceTemplateCategory networkResource = component
                .getTemplateResource(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_NETWORKING_COMP_ID);
        if (networkResource == null) {
            return null;
        }

        // Check the network configuration widget
        ServiceTemplateSetting networking = networkResource
                .getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_NETWORK_CONFIG_ID);
        if (networking != null && networking.getNetworkConfiguration() != null) {
            return networking.getNetworkConfiguration().getNetworks(NetworkType.HYPERVISOR_MANAGEMENT);
        } else {
            // Could be minimal sever component that just has a drop-down for management network
            ServiceTemplateSetting networkSetting = networkResource
                    .getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_HYPERVISOR_NETWORK_ID);
            if (networkSetting != null) {
                return networkSetting.getNetworks();
            }
        }

        return null;
    }

    public static Network findDefaultStaticNetwork(ServiceTemplateComponent component) {
        String defStaticNetworkId = getDefaultGateway(component);
        if (defStaticNetworkId != null && !defStaticNetworkId.equals("")) {
            List<Network> networks = findStaticNetworks(component);
            if (networks != null && !networks.isEmpty()) {
                for (Network net : networks) {
                    if (net.getId().equals(defStaticNetworkId)) {
                        return net;
                    }
                }
            }
        }
        return null;
    }

    public static String getDefaultGateway(ServiceTemplateComponent component) {
        return component.getParameterValue(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_NETWORKING_COMP_ID,
                ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_NETWORK_DEFAULT_GATEWAY_ID);
    }

    public static List<Network> findStaticManagementNetworks(ServiceTemplateComponent component) {
        List<Network> networks = findManagementNetworks(component);
        List<Network> ret = new ArrayList<>();
        if (networks != null) {
            for (Network network : networks) {
                if (network != null && network.isStatic() && network.getStaticNetworkConfiguration() != null
                        && StringUtils.isNotBlank(network.getStaticNetworkConfiguration().getIpAddress())) {
                    ret.add(network);
                }
            }
        }
        return ret;
    }

    public static List<Network> findStaticUINetworks(ServiceTemplateComponent component) {
        List<Network> networks = findStaticNetworks(component);
        List<Network> uiNetworks = new ArrayList<>();
        for (Network network : networks) {
            if (NetworkType.PRIVATE_LAN.equals(network.getType())
                    || NetworkType.PUBLIC_LAN.equals(network.getType())
                    || NetworkType.HYPERVISOR_MANAGEMENT.equals(network.getType())) {
                uiNetworks.add(network);
            }
        }
        return uiNetworks;
    }

    public static List<Network> findStaticNetworks(ServiceTemplateComponent component) {
        List<Network> networks = ServiceTemplateClientUtil.findNetworks(component);

        List<Network> ret = new ArrayList<>();
        if (networks != null) {
            for (Network network : networks) {
                if (network != null && network.isStatic() && network.getStaticNetworkConfiguration() != null) {
                    ret.add(network);
                }
            }
        }
        return ret;
    }

    public static List<Network> findNetworks(ServiceTemplate serviceTemplate) {
        List<Network> networks = new ArrayList<Network>();

        for (ServiceTemplateComponent component : serviceTemplate.getComponents()) {
            networks.addAll(ServiceTemplateClientUtil.findNetworks(component));
        }

        return networks;
    }

    public static List<Network> findNetworks(ServiceTemplateComponent component) {
        List<Network> networks = new ArrayList<Network>();

        if (ServiceTemplateComponent.ServiceTemplateComponentType.SERVER.equals(component.getType())) {
            ServiceTemplateCategory networkResource = component
                    .getTemplateResource(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_NETWORKING_COMP_ID);
            if (networkResource != null) {
                // Check the network configuration widget
                ServiceTemplateSetting networking = networkResource
                        .getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_NETWORK_CONFIG_ID);
                if (networking != null && networking.getNetworkConfiguration() != null
                        && networking.getNetworkConfiguration().getNetworks() != null) {
                    networks.addAll(networking.getNetworkConfiguration().getNetworks());
                } else {
                    // Could be minimal sever component that just has a drop-down for management network
                    ServiceTemplateSetting networkSetting = networkResource
                            .getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_HYPERVISOR_NETWORK_ID);
                    if (networkSetting != null && networkSetting.getNetworks() != null) {
                        networks.addAll(networkSetting.getNetworks());
                    }
                }
            }
        } else if (ServiceTemplateComponent.ServiceTemplateComponentType.VIRTUALMACHINE
                .equals(component.getType())) {
            ServiceTemplateCategory vmSettingsResource = component
                    .getTemplateResource(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VM_RESOURCE);
            if (vmSettingsResource == null) {
                vmSettingsResource = component
                        .getTemplateResource(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_HV_VM_RESOURCE);
            }
            if (vmSettingsResource != null) {
                ServiceTemplateSetting networkInterfaces = vmSettingsResource
                        .getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VM_NETWORK_ID);
                if (networkInterfaces != null && networkInterfaces.getNetworks() != null
                        && networkInterfaces.getNetworks().size() > 0) {
                    networks.addAll(networkInterfaces.getNetworks());
                }
            }
        }

        return networks;
    }

    public static void addDefaultSelectOption(ServiceTemplateSetting setting) {
        setting.getOptions().add(new ServiceTemplateOption(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SELECT,
                ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SELECT_ID, null, null));
        setting.setValue(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SELECT_ID);
    }

    /**
     * Helper to add a setting "Create new ..."
     *
     * @param component      component to process
     * @param options        list of options to select from
     * @param setId          ID of target param  (i.e. volume, datacenter, cluster etc)
     * @param labelCreateNew label in drop down "Create new ..."
     * @param labelNew       label in front of new input field "new xxx"
     */
    public static ServiceTemplateSetting processNewSetting(ServiceTemplateComponent component,
            Collection<ServiceTemplateOption> options, String setId, String labelCreateNew, String labelNew,
            boolean hideFromTemplate) {

        for (ServiceTemplateCategory resource : component.getResources()) {
            ServiceTemplateSetting set = processNewSetting(resource, options, setId, labelCreateNew, labelNew,
                    hideFromTemplate);
            if (set != null)
                return set;
        }
        return null;
    }

    /**
     * Helper to add a setting "Create new ..."
     *
     * @param resource       Resource to process
     * @param options        list of options to select from
     * @param setId          ID of target param  (i.e. volume, datacenter, cluster etc)
     * @param labelCreateNew label in drop down "Create new ..."
     * @param labelNew       label in front of new input field "new xxx"
     */
    public static ServiceTemplateSetting processNewSetting(ServiceTemplateCategory resource,
            Collection<ServiceTemplateOption> options, String setId, String labelCreateNew, String labelNew,
            boolean hideFromTemplate) {

        for (int i = 0; i < resource.getParameters().size(); i++) {
            ServiceTemplateSetting set = resource.getParameters().get(i);
            if (set.getId().equals(setId)) {
                set.getOptions().clear();
                addDefaultSelectOption(set);
                set.getOptions().add(new ServiceTemplateOption(labelCreateNew,
                        ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CREATE_NEW_PREFIX, null, null));
                if (options != null) {
                    set.getOptions().addAll(options);
                }
                set.setType(ServiceTemplateSetting.ServiceTemplateSettingType.ENUMERATED);

                ServiceTemplateSetting setNew = new ServiceTemplateSetting();
                setNew.setType(ServiceTemplateSetting.ServiceTemplateSettingType.STRING);
                setNew.setId(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CREATE_NEW_PREFIX + setId);
                setNew.setDisplayName(labelNew);
                setNew.setRequired(set.isRequired());
                setNew.setRequiredAtDeployment(set.isRequiredAtDeployment());
                setNew.setHideFromTemplate(hideFromTemplate);
                setNew.setGroup(set.getGroup());
                setNew.setDependencyTarget(setId);
                setNew.setDependencyValue(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CREATE_NEW_PREFIX);

                resource.getParameters().add(i + 1, setNew);

                return setNew;
            }
        }
        return null;
    }

    /**
     * Create unique identifier for VDS name setting
     *
     * @param networksId Unique ID for networks combination, i.e. PXE + HVM or WKL1 + WKL2 + WKL3
     * @return
     */
    public static String createVDSID(String networksId) {
        return ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_NAME_ID + "::" + networksId;
    }

    /**
     * Create unique identifier for port group setting
     *
     * @param networksId Unique ID for networks combination, i.e. PXE + HVM or WKL1 + WKL2 + WKL3
     * @param networkId  Network ID for port group
     * @param pgIdx      Index of the port group if there are more than one for the same network type in the same VDS, i.e. ISCSI1
     * @return
     */
    public static String createVDSPGID(String networksId, String networkId, int pgIdx) {
        return ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_PG_ID + "::" + networksId + "::" + networkId
                + "::" + pgIdx;
    }

    /**
     * Create VDS Name setting
     *
     * @param cluster
     * @param vdsCategory
     * @param id
     * @param displayName
     * @param groupName
     * @param options
     * @return
     */
    public static ServiceTemplateSetting createVDSNameSetting(ServiceTemplateComponent cluster,
            ServiceTemplateCategory vdsCategory, String id, String displayName, String groupName,
            Collection<ServiceTemplateOption> options) {
        ServiceTemplateSetting set = createVDSSetting(vdsCategory, id, displayName, groupName);
        ServiceTemplateSetting setNew = processNewSetting(cluster, options, id, "Create VDS Name ...",
                "New VDS Name", false);
        setNew.setGenerated(true);
        return set;
    }

    /**
     * Create VFDS port group setting
     *
     * @param vdsCategory
     * @param id
     * @param displayName
     * @param groupName
     * @param options
     * @return
     */
    public static ServiceTemplateSetting createVDSPGSetting(ServiceTemplateComponent cluster,
            ServiceTemplateCategory vdsCategory, String id, String displayName, String groupName,
            Collection<ServiceTemplateOption> options) {
        ServiceTemplateSetting set = createVDSSetting(vdsCategory, id, displayName, groupName);
        ServiceTemplateSetting setNew = processNewSetting(cluster, options, id, "Create Port Group ...",
                "New Port Group", false);
        setNew.setGenerated(true);
        return set;
    }

    private static ServiceTemplateSetting createVDSSetting(ServiceTemplateCategory vdsCategory, String id,
            String displayName, String groupName) {
        ServiceTemplateSetting vdsNameSetting = new ServiceTemplateSetting();
        vdsNameSetting.setDisplayName(displayName);
        vdsNameSetting.setId(id);
        vdsNameSetting.setType(ServiceTemplateSetting.ServiceTemplateSettingType.ENUMERATED);
        vdsNameSetting.setGroup(groupName);
        vdsNameSetting.setDependencyTarget(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_CLUSTER_VDS_ID);
        vdsNameSetting.setDependencyValue(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_CLUSTER_VDS_DST_ID);
        vdsNameSetting.setRequired(false);
        vdsNameSetting.setGenerated(true);
        // add in the end of Group
        int i = 0;
        int idx = -1;
        for (ServiceTemplateSetting parameter : vdsCategory.getParameters()) {
            i++;
            if (parameter.getGroup() != null && parameter.getGroup().equals(groupName)) {
                idx = i;
            }
        }
        if (idx < 0)
            idx = vdsCategory.getParameters().size();

        vdsCategory.getParameters().add(idx, vdsNameSetting);
        return vdsNameSetting;
    }

    /**
     * Clone options and set new dependency target.
     *
     * @param options
     * @param vdsNameId New dependency target ID
     * @return
     */
    public static List<ServiceTemplateOption> copyOptions(Collection<ServiceTemplateOption> options,
            String vdsNameId) {
        List<ServiceTemplateOption> newOptions = new ArrayList<>();
        for (ServiceTemplateOption option : options) {
            ServiceTemplateOption newOption = new ServiceTemplateOption(option.getName(), option.getValue(),
                    option.getDependencyTarget(), option.getDependencyValue(),
                    new HashMap<>(option.getAttributes()));

            if (vdsNameId != null)
                newOption.setDependencyTarget(vdsNameId);
            newOptions.add(newOption);
        }
        return newOptions;
    }

    /**
     * Find existing port group setting or create new one.
     *
     * @param cluster    template component - Cluster
     * @param networksId ID for networks combo
     * @param name       PG network display name i.e. "Workload"
     * @param networkId  PG network ID
     * @param idx        PG network index i.e. 1 or 2
     * @return
     */
    public static ServiceTemplateSetting getPortGroup(ServiceTemplateComponent cluster, String networksId,
            String name, String networkId, int idx, boolean createNew) {
        ServiceTemplateCategory vdsCategory = cluster
                .getTemplateResource(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_ESX_CLUSTER_COMP_VDS_ID);
        if (vdsCategory == null)
            return null;

        ServiceTemplateSetting vdsName = cluster.getParameter(
                ServiceTemplateSettingIDs.SERVICE_TEMPLATE_ESX_CLUSTER_COMP_VDS_ID, createVDSID(networksId));

        if (vdsName == null)
            return null;

        String pgID = createVDSPGID(networksId, networkId, idx);

        // this group must always exist
        ServiceTemplateSetting vdsPG1 = cluster.getParameter(
                ServiceTemplateSettingIDs.SERVICE_TEMPLATE_ESX_CLUSTER_COMP_VDS_ID,
                ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_PG_ID);

        for (ServiceTemplateSetting vdsPG : vdsCategory.getParameters()) {
            if (vdsPG.getId().equals(pgID)) {
                vdsPG.setOptions(copyOptions(vdsPG1.getOptions(), vdsName.getId()));
                return vdsPG;
            }
        }

        // reached the end of created PGs, create new
        if (createNew)
            return createVDSPGSetting(cluster, vdsCategory, pgID, name, vdsName.getGroup(),
                    copyOptions(vdsPG1.getOptions(), vdsName.getId()));
        else
            return null;
    }

    /**
     * Returns true if given PG belongs to VDS name
     *
     * @param vdsId VDS name ID
     * @param pgId  VDS PG ID
     * @return
     */
    public static boolean isVDSGroup(String vdsId, String pgId) {
        if (vdsId == null || pgId == null)
            return false;

        if (!vdsId.contains(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_NAME_ID + "::"))
            return false;

        if (!pgId.contains(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_PG_ID + "::"))
            return false;

        String[] arrVDS = vdsId.split("::");
        String[] arrPG = pgId.split("::");

        if (arrVDS.length < 2 || arrPG.length < 2)
            return false;

        return arrPG[1].equals(arrVDS[1]);
    }

    /**
     * From VDS name or PG setting ID get the IDs of partition networks, i.e. xxx::yyy::zzz
     *
     * @param vdsId
     * @return
     */
    public static String extractNetworksID(String vdsId) {
        if (vdsId == null)
            return null;

        if (!vdsId.contains(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_NAME_ID + "::")
                && !vdsId.contains(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_PG_ID + "::"))
            return null;

        String[] arrVDS = vdsId.split("::");
        if (arrVDS.length < 2)
            return null;

        return arrVDS[1];
    }

    /**
     * From VDS PG setting ID get the network ID
     * Used by ASMUI
     *
     * @param vdsId
     * @return
     */
    public static String extractNetworkID(String vdsId) {
        if (vdsId == null)
            return null;

        if (!vdsId.contains(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_PG_ID + "::"))
            return null;

        String[] arrVDS = vdsId.split("::");
        if (arrVDS.length < 3)
            return null;

        return arrVDS[2];
    }

    /**
     * From VDS name or PG setting ID get the IDs of partition networks, i.e. xxx::yyy::zzz
     *
     * @param vdsId
     * @return
     */
    public static String replaceNetworksID(String vdsId, String newNetworksID) {
        if (vdsId == null)
            return null;

        if (!vdsId.contains(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_NAME_ID + "::")
                && !vdsId.contains(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CLUSTER_VDS_PG_ID + "::"))
            return null;

        String[] arrVDS = vdsId.split("::");
        if (arrVDS.length < 2)
            return null;

        arrVDS[1] = newNetworksID;

        return StringUtils.join(arrVDS, "::");
    }

    public static boolean scaleupNetworkPortGroups(ServiceTemplateComponent cluster, String portGroupName,
            boolean newPortGroup, List<String> networks, String networkId, String networkName, int maxPgNum) {
        ServiceTemplateCategory vdsCategory = cluster
                .getTemplateResource(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_ESX_CLUSTER_COMP_VDS_ID);
        if (vdsCategory == null) {
            LOGGER.error("No VDS category found");
            return false;
        }

        // old ID for this VDS
        Collections.sort(networks);
        String networksId = StringUtils.join(networks, ":");

        // new ID for this VDS. Order of networks is significant!
        List<String> newNetworkList = new ArrayList<>();
        newNetworkList.addAll(networks);
        newNetworkList.add(networkId);
        Collections.sort(newNetworkList);
        String newNetworksId = StringUtils.join(newNetworkList, ":");

        ServiceTemplateSetting vdsName = cluster.getParameter(
                ServiceTemplateSettingIDs.SERVICE_TEMPLATE_ESX_CLUSTER_COMP_VDS_ID, createVDSID(networksId));

        // VDS may exist if we have redundancy = true and such call was already made for the first port
        if (vdsName != null) {

            // new ID
            String newVDSID = createVDSID(newNetworksId);

            for (ServiceTemplateSetting vdsPG : vdsCategory.getParameters()) {
                if (isVDSGroup(vdsName.getId(), vdsPG.getId())) {
                    // replace VDS ID
                    String newId = replaceNetworksID(vdsPG.getId(), newNetworksId);
                    if (newId == null) {
                        LOGGER.error("Cannot replace VDS networks ID for " + vdsPG.getId());
                        return false;
                    }
                    // lookup for dependency targets with such ID
                    replaceIDinDependencies(vdsCategory.getParameters(), vdsPG.getId(), newId);
                    vdsPG.setId(newId);
                }
            }

            // lookup for dependency targets with such ID
            replaceIDinDependencies(vdsCategory.getParameters(), vdsName.getId(), newVDSID);
            // replace VDS name ID
            vdsName.setId(newVDSID);
            // don't forget about $new$
            String vID = createVDSID(networksId);
            vdsName = cluster.getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_ESX_CLUSTER_COMP_VDS_ID,
                    ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CREATE_NEW_PREFIX + vID);
            vdsName.setId(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CREATE_NEW_PREFIX + newVDSID);
        } else {

            vdsName = cluster.getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_ESX_CLUSTER_COMP_VDS_ID,
                    createVDSID(newNetworksId));

            // make sure we have new VDS at this point
            if (vdsName == null) {
                LOGGER.error("No VDS found in the cluster parameters " + newNetworksId);
                return false;
            }
        }

        // add new group
        for (int i = 1; i <= maxPgNum; i++) {
            String portGroupDisplayName = networkName + " Port Group";
            if (i > 1)
                portGroupDisplayName += " " + i;

            ServiceTemplateSetting vdsPG = getPortGroup(cluster, newNetworksId, portGroupDisplayName, networkId, i,
                    false);
            if (vdsPG == null) {
                vdsPG = getPortGroup(cluster, newNetworksId, portGroupDisplayName, networkId, i, true);
                if (vdsPG == null) {
                    LOGGER.error("Cannot create VDS PG for  " + networkName);
                    return false;
                }

                vdsPG.setHideFromTemplate(false);
                if (newPortGroup) {
                    vdsPG.setValue(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CREATE_NEW_PREFIX);
                    vdsPG = cluster.getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_ESX_CLUSTER_COMP_VDS_ID,
                            ServiceTemplateSettingIDs.SERVICE_TEMPLATE_CREATE_NEW_PREFIX + vdsPG.getId());
                }
                vdsPG.setValue(portGroupName);
                return true;
            }
        }

        LOGGER.warn("Cannot add more than " + maxPgNum + " port groups to VDS. All groups already exist.");
        return true;
    }

    private static void replaceIDinDependencies(List<ServiceTemplateSetting> parameters, String oldId,
            String newId) {
        if (parameters == null || oldId == null)
            return;
        for (ServiceTemplateSetting vdsPG : parameters) {
            if (oldId.equals(vdsPG.getDependencyTarget())) {
                vdsPG.setDependencyTarget(newId);
            }
        }
    }

    /**
     * Returns all of the NetworkIds that are assigned in the ServiceTemplate.
     *
     * @param serviceTemplate the template whose NetworkIds will be returned.
     * @return all of the NetworkIds that are assigned in the ServiceTemplate.
     */
    public static Set<String> getNetworkIds(ServiceTemplate serviceTemplate) {

        HashSet<String> networkIds = new HashSet<String>();

        if (serviceTemplate != null) {
            for (ServiceTemplateComponent component : serviceTemplate.getComponents()) {

                if (ServiceTemplateComponent.ServiceTemplateComponentType.SERVER.equals(component.getType())
                        || ServiceTemplateComponent.ServiceTemplateComponentType.VIRTUALMACHINE
                                .equals(component.getType())) {
                    for (ServiceTemplateCategory resource : component.getResources()) {
                        // if server networking category or esxi vm category or hyperv vm category
                        if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_NETWORKING_COMP_ID
                                .equals(resource.getId())
                                || ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VM_RESOURCE.equals(resource.getId())
                                || ServiceTemplateSettingIDs.SERVICE_TEMPLATE_HV_VM_RESOURCE
                                        .equals(resource.getId())) {
                            for (ServiceTemplateSetting param : resource.getParameters()) {
                                // if server networking configuration parameter
                                if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_NETWORK_CONFIG_ID
                                        .equals(param.getId())) {
                                    NetworkConfiguration configuration = ServiceTemplateClientUtil
                                            .deserializeNetwork(param.getValue());
                                    networkIds.addAll(configuration.getAllNetworkIds());
                                } else if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_SERVER_HYPERVISOR_NETWORK_ID
                                        .equals((param.getId()))
                                        || ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VM_NETWORK_ID
                                                .equals(param.getId())) {
                                    if (!(param.getValue().isEmpty() || param.getValue().equals("-1"))) {
                                        // value may be a comma-separated list, but if that is the case it will lead with a comma,
                                        // e.g. ,1,2,3.  The reject below gets rid of the initial empty element
                                        if (param != null && param.getNetworks() != null) {
                                            for (Network network : param.getNetworks()) {
                                                if (network != null && network.getId() != null) {
                                                    networkIds.add(network.getId());
                                                }
                                            }
                                        }
                                        // NetworkIds are stored in a comma separated list as values of this param 
                                        for (String guid : param.getValue().split(",")) {
                                            if (!guid.isEmpty()) {
                                                networkIds.add(guid);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return networkIds;
    }

    /**
     * Currently uses ObjectMapper. Will NOT throw exception but return null if json is wrong.
     * It does NOT require adding "networkConfiguration:" to JSON as for MarshalUtil.fromJSON
     *
     * @param value
     * @return
     */
    public static com.dell.asm.asmcore.asmmanager.client.networkconfiguration.NetworkConfiguration deserializeNetwork(
            String value) {
        try {
            return OBJECT_MAPPER.readValue(value,
                    com.dell.asm.asmcore.asmmanager.client.networkconfiguration.NetworkConfiguration.class);
            //String configString = "{ \"networkConfiguration\" : " + value + "}";
            //return MarshalUtil.fromJSON(com.dell.asm.asmcore.asmmanager.client.networkconfiguration.NetworkConfiguration.class, configString);
        } catch (IOException e) {
            LOGGER.error("Network configuration has invalid value: " + value);
        }

        return null;
    }

    public static List<Network> findVMStaticNetworks(ServiceTemplateComponent component) {
        List<Network> ret = new ArrayList<>();
        ServiceTemplateSetting setNetwork = component.getParameter(
                ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VM_RESOURCE,
                ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VM_NETWORK_ID);
        if (setNetwork == null) {
            setNetwork = component.getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_HV_VM_RESOURCE,
                    ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VM_NETWORK_ID);
        }

        if (setNetwork != null && setNetwork.getNetworks() != null) {
            for (Network network : setNetwork.getNetworks()) {
                if (network.isStatic() && network.getStaticNetworkConfiguration() != null
                        && network.getStaticNetworkConfiguration().getIpAddress() != null) {
                    ret.add(network);
                }
            }
        }
        return ret;
    }

    /**
     * For given storage components finds volume name which could be stored in different settings.
     * If volume name is to be entered at deployment, or generated and is currently mull the method will
     * return empty string.
     * Returns null only if the resource is not storage or expected attributes are not there.
     *
     * @param resource
     * @return
     */
    public static String getVolumeNameForStorageComponent(ServiceTemplateCategory resource) {
        if (resource == null) {
            return null;
        }
        for (ServiceTemplateSetting param : resource.getParameters()) {
            if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_TITLE_ID.equals(param.getId())) {
                ServiceTemplateSetting nameSetting = null;
                if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_AUTOGENERATE
                        .equals(param.getValue())) {
                    nameSetting = resource
                            .getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_GENERATED);
                } else if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_EXISTING
                        .equals(param.getValue())) {
                    nameSetting = resource
                            .getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_EXISTING);
                } else if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_CREATE_NOW
                        .equals(param.getValue())) {
                    nameSetting = resource.getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_NEW);
                } else if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_CREATE_DEPLOYMENT
                        .equals(param.getValue())) {
                    nameSetting = resource
                            .getParameter(ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_NEW_AT_DEPLOYMENT);
                }
                if (nameSetting == null) {
                    String err = "Cannot find volume name setting in the service template, volume mode: "
                            + param.getValue() + "\n";
                    try {
                        err += param.getValue() + OBJECT_MAPPER.writeValueAsString(resource);
                    } catch (JsonProcessingException e) {
                        LOGGER.error("JSON serialization failed", e);
                    }
                    LOGGER.error(err);
                    return null;
                }

                return nameSetting.getValue() != null ? nameSetting.getValue() : "";
            }
        }
        return null;
    }

    /**
     * Returns true if storage volume in this template resource meant to be new - either user entered or generated
     *
     * @param resource
     * @return
     */
    public static boolean isNewStorageVolume(ServiceTemplateCategory resource, boolean includeGenerated) {
        if (resource == null)
            return false;

        for (ServiceTemplateSetting param : resource.getParameters()) {
            if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_TITLE_ID.equals(param.getId())) {
                return isNewStorageVolume(param, includeGenerated);
            }
        }
        return false;
    }

    /**
     * Returns true if storage volume in this template resource was entered as "existing"
     *
     * @param resource
     * @return
     */
    public static boolean isExistingVolume(ServiceTemplateCategory resource) {
        if (resource == null)
            return false;

        for (ServiceTemplateSetting param : resource.getParameters()) {
            if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_TITLE_ID.equals(param.getId())) {
                return (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_EXISTING
                        .equals(param.getValue()));
            }
        }
        return false;
    }

    /**
     * Returns true if storage volume in this template resource was entered as "generated"
     *
     * @param resource
     * @return
     */
    public static boolean isGeneratedVolume(ServiceTemplateCategory resource) {
        if (resource == null)
            return false;

        for (ServiceTemplateSetting param : resource.getParameters()) {
            if (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_TITLE_ID.equals(param.getId())) {
                return (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_AUTOGENERATE
                        .equals(param.getValue()));
            }
        }
        return false;
    }

    /**
     * Returns true if storage volume in this template resource meant to be new - either user entered or generated
     *
     * @param param
     * @return
     */
    public static boolean isNewStorageVolume(ServiceTemplateSetting param, boolean includeGenerated) {
        if (param == null)
            return false;

        return (ServiceTemplateSettingIDs.SERVICE_TEMPLATE_TITLE_ID.equals(param.getId())
                && ((includeGenerated && ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_AUTOGENERATE
                        .equals(param.getValue()))
                        || ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_CREATE_NOW
                                .equals(param.getValue())
                        || ServiceTemplateSettingIDs.SERVICE_TEMPLATE_VOLUME_NAME_OPTION_CREATE_DEPLOYMENT
                                .equals(param.getValue())));
    }
}