org.xlcloud.service.manager.VirtualClustersManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.xlcloud.service.manager.VirtualClustersManagerImpl.java

Source

/*
 * Copyright 2012 AMG.lab, a Bull Group Company
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.xlcloud.service.manager;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.log4j.Logger;

import org.xlcloud.service.Application;
import org.xlcloud.service.Applications;
import org.xlcloud.service.Project;
import org.xlcloud.service.VirtualCluster;
import org.xlcloud.service.VirtualCluster.Parameters;
import org.xlcloud.service.VirtualCluster.Parameters.Parameter;
import org.xlcloud.service.VirtualClusterDefinition;
import org.xlcloud.service.VirtualClusters;
import org.xlcloud.service.dao.VirtualClusterDefinitionsDao;
import org.xlcloud.service.dao.VirtualClustersDao;
import org.xlcloud.service.dao.utils.QueryContext;
import org.xlcloud.service.exception.VcmsDuplicatedEntityException;
import org.xlcloud.service.exception.VcmsForbiddenException;
import org.xlcloud.service.exception.VcmsObjectNotFoundException;
import org.xlcloud.service.exception.VcmsValidationException;
import org.xlcloud.service.heat.template.Template;
import org.xlcloud.service.model.ApplicationModel;
import org.xlcloud.service.model.VirtualClusterDefinitionModel;
import org.xlcloud.service.model.VirtualClusterModel;
import org.xlcloud.service.model.VirtualClusterParameterModel;
import org.xlcloud.service.transformer.Transformer;

/**
 * Logic implementation for services virtual clusters actions.
 * 
 * @author Maciej Osyda, AMG.net
 */
public class VirtualClustersManagerImpl implements VirtualClustersManager {

    private static final Logger LOG = Logger.getLogger(VirtualClustersManagerImpl.class);

    @Inject
    QueryContext queryContext;

    @Inject
    private VirtualClustersDao virtualClustersDao;

    @Inject
    private VirtualClusterDefinitionsDao vcdDao;

    @Inject
    private ApplicationsManager applicationsManager;

    @Inject
    private ProjectsManager projectsManager;

    @Inject
    private VcbsManager vcbsManager;

    @Inject
    private VirtualClusterDefinitionsManager vcDefManager;

    @Inject
    private Transformer<VirtualClusterModel, VirtualCluster> virtualClusterTransformer;

    @Inject
    private Transformer<VirtualClusterParameterModel, Parameter> parameterTransformer;

    @Inject
    private Transformer<ApplicationModel, Application> applicationTransformer;

    private static final boolean PAGED = true;

    /** {@inheritDoc} */
    @Override
    public VirtualClusters getVirtualClusters() {
        queryContext.setTotalCount(virtualClustersDao.findAllCount());
        List<VirtualClusterModel> models = virtualClustersDao.findAll(PAGED);
        LOG.debug("Listed all virtual clusters. Found: " + models.size());
        Collection<VirtualCluster> dtos = virtualClusterTransformer.transformToDtos(models);
        VirtualClusters vClusters = new VirtualClusters();
        if (dtos != null && !dtos.isEmpty()) {
            vClusters.getVirtualCluster().addAll(dtos);
        }
        return vClusters;
    }

    /** {@inheritDoc} */
    @Override
    public VirtualCluster getVirtualCluster(long id) {
        LOG.debug("Trying to get virtual cluster with id: " + id);
        VirtualClusterModel model = getVcModel(id);
        return virtualClusterTransformer.transformFromModel(model);
    }

    /** {@inheritDoc} */
    @Override
    public VirtualCluster addVirtualCluster(VirtualCluster virtualCluster) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Trying to create virtual cluster: "
                    + ToStringBuilder.reflectionToString(virtualCluster, ToStringStyle.SHORT_PREFIX_STYLE));
        }
        // validate VC
        if (virtualCluster == null) {
            LOG.info("Request does not contain mandatory 'virtualCluster' object.");
            throw new VcmsValidationException("Request does not contain mandatory 'virtualCluster' object.");
        } else if (virtualCluster.getName() == null) {
            LOG.info("Virtual Cluster does not contain mandatory 'name' field");
            throw new VcmsValidationException("Virtual Cluster does not contain mandatory 'name' field");
        }
        Long projectId = virtualCluster.getProjectId();
        if (projectsManager.get(projectId) == null) {
            LOG.info("Virtual Cluster's project (id " + projectId + ") not found.");
            throw new VcmsObjectNotFoundException("project with id '" + projectId + "' not found");
        }

        VirtualClusterDefinition definition = getDefinitionForVirtualCluster(
                virtualCluster.getVirtualClusterDefinitionId());

        // Save required info in database
        VirtualClusterModel model = virtualClusterTransformer.transformFromDto(virtualCluster);
        // fill required fields
        if (model.getParameters() == null) {
            model.setParameters(new LinkedList<VirtualClusterParameterModel>());
        }
        VirtualClusterDefinitionModel vcdModel = vcdDao.find(model.getVirtualClusterDefinition().getId());
        // validate applications
        //        for(ApplicationModel applicationModel : model.getApplications()) {
        //            Application application = applicationsManager.getApplication(applicationModel.getId());
        //            validateRequirements(application, vcdModel);
        //        }
        model.setVirtualClusterDefinition(vcdModel);

        validateParameters(model.getParameters(), definition.getTemplate());
        completeParameters(model, definition.getTemplate());

        Project project = projectsManager.get(virtualCluster.getProjectId());
        model.setAccountId(project.getAccountId());

        if (clusterExists(virtualCluster)) {
            String message = "Cluster with name " + virtualCluster.getName() + " already exists in project "
                    + virtualCluster.getProjectId();
            LOG.info(message);
            throw new VcmsDuplicatedEntityException(message);
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("Creating virtual cluster in IAM: " + model);
        }
        //TODO: przemyslec gdzie to id powinno byc
        //        model.setBackendId(iamCluster.getId().toString());

        if (LOG.isDebugEnabled()) {
            LOG.debug("Saving virtual cluster model in database: " + model);
        }

        model = virtualClustersDao.createOrUpdate(model);
        virtualCluster.setId(model.getId());
        //TODO: check if we can just return iamVcManager
        return getVirtualCluster(model.getVirtualClusterId());
    }

    private void validateParameters(Collection<VirtualClusterParameterModel> parameters, Template template) {
        Map<String, org.xlcloud.service.heat.template.Parameter> templateParametersMap = new HashMap<String, org.xlcloud.service.heat.template.Parameter>();

        for (org.xlcloud.service.heat.template.Parameter templateParameter : template.getParameters()
                .getParameter()) {
            templateParametersMap.put(templateParameter.getName(), templateParameter);
        }

        for (VirtualClusterParameterModel vcParam : parameters) {
            org.xlcloud.service.heat.template.Parameter templateParameter = templateParametersMap
                    .get(vcParam.getName());
            if (templateParameter == null) {
                throw new VcmsValidationException("Template described as: " + template.getDescription()
                        + " does not contain parameter \"" + vcParam.getName() + "\".");
            }

            if (templateParameter.getAllowedValues() != null && !templateParameter.getAllowedValues().isEmpty()) {
                List<String> allowedValues = templateParameter.getAllowedValues();
                if (!allowedValues.contains(vcParam.getValue())) {
                    throw new VcmsValidationException("\"" + vcParam.getValue()
                            + "\" is not allowed value for the parameter " + templateParameter.getName());
                }
            }
        }
    }

    private void completeParameters(VirtualClusterModel model, Template template) {
        org.xlcloud.service.heat.template.Parameters templateParameters = template.getParameters();

        Set<String> vcParamSet = new HashSet<String>();
        for (VirtualClusterParameterModel vcParam : model.getParameters()) {
            vcParamSet.add(vcParam.getName());
            vcParam.setVirtualCluster(model); // FIXME: is it ok?
        }

        for (org.xlcloud.service.heat.template.Parameter templateParameter : templateParameters.getParameter()) {
            if (!vcParamSet.contains(templateParameter.getName())) {
                VirtualClusterParameterModel newParam = new VirtualClusterParameterModel();
                newParam.setName(templateParameter.getName());
                newParam.setValue(templateParameter.getDefaultValue());
                newParam.setVirtualCluster(model);
                model.getParameters().add(newParam);
            }
        }
    }

    private void updateParameters(VirtualClusterModel vcModel, Collection<VirtualClusterParameterModel> params) {
        Map<String, VirtualClusterParameterModel> oldParams = new HashMap<String, VirtualClusterParameterModel>();
        for (VirtualClusterParameterModel oldParam : vcModel.getParameters()) {
            oldParams.put(oldParam.getName(), oldParam);
        }
        for (VirtualClusterParameterModel newParam : params) {
            VirtualClusterParameterModel correspondingOldParam = oldParams.get(newParam.getName());
            correspondingOldParam.setName(newParam.getName());
            correspondingOldParam.setValue(newParam.getValue());
        }
    }

    private VirtualClusterDefinition getDefinitionForVirtualCluster(Long definitionId) {
        if (definitionId == null) {
            LOG.info("Virtual Cluster does not contain mandatory 'virtualClusterDefinitionId' attribute");
            throw new VcmsValidationException(
                    "Virtual Cluster does not contain mandatory 'virtualClusterDefinitionId' attribute");
        }

        VirtualClusterDefinition definition = vcDefManager.get(definitionId);
        if (definition == null) {
            LOG.info("Virtual Cluster Definition with id: " + definitionId + " does not exist.");
            throw new VcmsObjectNotFoundException(
                    "Virtual Cluster Definition with id: " + definitionId + " does not exist.");
        }

        return definition;
    }

    /** {@inheritDoc} */
    @Override
    public VirtualClusters getProjectVirtualClusters(Long projectId) {
        LOG.debug("Trying to get virtual clusters for project: " + projectId);
        List<VirtualClusterModel> list = virtualClustersDao.getVirtualClustersByProjectId(projectId);
        Collection<VirtualCluster> dtos = virtualClusterTransformer.transformFromModels(list);
        VirtualClusters vClusters = new VirtualClusters();
        if (dtos != null && !dtos.isEmpty()) {
            vClusters.getVirtualCluster().addAll(dtos);
        }
        return vClusters;
    }

    private VirtualClusterModel getVcModel(long vcId) {
        VirtualClusterModel vcModel = virtualClustersDao.find(vcId);
        if (vcModel == null) {
            LOG.info("VirtualCluster with id: '" + vcId + "' does not exist.");
            throw new VcmsObjectNotFoundException("VirtualCluster with id: '" + vcId + "' does not exist.");
        }
        return vcModel;
    }

    private boolean clusterExists(VirtualCluster virtualCluster) {
        return (virtualClustersDao.getClusterByProjectAndName(virtualCluster.getProjectId(),
                virtualCluster.getName()) != null);
    }

    /** {@inheritDoc} */
    @Override
    public Applications getApplications(Long vcId) {
        VirtualClusterModel model = virtualClustersDao.find(vcId);
        Collection<Application> dtos = applicationTransformer.transformToDtos(model.getApplications());
        Applications applications = new Applications();
        if (dtos != null && !dtos.isEmpty()) {
            applications.getApplication().addAll(dtos);
        }
        return applications;
    }

    /** {@inheritDoc} */
    @Override
    public Application addAplication(Long vcId, Long appId) {
        LOG.debug("Adding app: " + appId + " to virtual cluster " + vcId);
        Application application = applicationsManager.getApplication(appId);
        VirtualClusterModel vcModel = getVcModel(vcId);
        for (ApplicationModel app : vcModel.getApplications()) {
            if (app.getId().equals(appId)) {
                throw new VcmsDuplicatedEntityException(
                        "Virtual cluster with id " + vcId + " already has application with id " + appId);
            }
        }

        //        validateRequirements(application, vcModel.getVirtualClusterDefinition());

        ApplicationModel appModel = new ApplicationModel();
        appModel.setAppId(appId);
        vcModel.getApplications().add(appModel);
        LOG.debug("VirtualCluster " + vcModel.getId() + " app " + appModel.getId());
        vcModel = virtualClustersDao.createOrUpdate(vcModel); // necessary?
        return application;
    }

    // don't use it yet - we need to be sure we want such validation!
    @Deprecated
    private void validateRequirements(Application application, VirtualClusterDefinitionModel vcdModel) {
        String appType = application.getType();
        if (appType == null || !appType.equals(vcdModel.getType())) {
            throw new VcmsForbiddenException("Virtual cluster definition (id:" + vcdModel.getId()
                    + ") does not fulfill application requirements (not matching types)");
        }
        for (String appTag : application.getTag()) {
            if (!vcdModel.getTags().contains(appTag)) {
                throw new VcmsForbiddenException("Virtual cluster definition (id:" + vcdModel.getId()
                        + ") does not fulfill application requirements (required tag \"" + appTag
                        + "\" not satisfied by virtual cluster");
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public void removeApplication(Long vcId, Long applicationId) {
        VirtualClusterModel vcModel = getVcModel(vcId);
        ApplicationModel appModel = null;
        for (ApplicationModel app : vcModel.getApplications()) {
            if (applicationId.equals(app.getId())) {
                appModel = app;
            }
        }
        if (appModel == null) {
            throw new VcmsObjectNotFoundException(
                    "Virtual cluster with id " + vcId + " does not contain application with id " + applicationId);
        }
        vcModel.getApplications().remove(appModel);
        virtualClustersDao.createOrUpdate(vcModel); // not necessary?
    }

    /** {@inheritDoc} */
    @Override
    public Parameters getParameters(Long vcId) {
        VirtualClusterModel model = getVcModel(vcId);
        List<VirtualClusterParameterModel> params = model.getParameters();
        Collection<Parameter> dtos = parameterTransformer.transformToDtos(params);
        Parameters parameters = new Parameters();
        if (dtos != null && !dtos.isEmpty()) {
            parameters.getParameter().addAll(dtos);
        }
        return parameters;

    }

    /** {@inheritDoc} */
    @Override
    public VirtualCluster updateParameters(Long vcId, Parameters parameters) {
        Collection<VirtualClusterParameterModel> models = parameterTransformer
                .transformFromDtos(parameters.getParameter());
        VirtualClusterModel vcModel = virtualClustersDao.find(vcId);
        //TODO: przemyslec czy taka sytuacja powinna byc obsluzona
        //      if(!State.PAUSED.equals(vcModel.getCurrentStatus())) {
        //          throw new VcmsForbiddenException("Virtual cluster \""+vcModel.getName()+"\" is not is PAUSED state.");
        //      }

        VirtualClusterDefinition definition = getDefinitionForVirtualCluster(
                vcModel.getVirtualClusterDefinition().getId());
        validateParameters(models, definition.getTemplate());

        updateParameters(vcModel, models);
        vcModel = virtualClustersDao.createOrUpdate(vcModel);
        return virtualClusterTransformer.transformToDto(vcModel);
    }

    @Override
    public VirtualClusters listForAccount(Long id) {
        List<VirtualClusterModel> models = virtualClustersDao.getVirtualClustersByAccountId(id, PAGED);
        LOG.debug("Listed virtual clusters for account " + id + ". Found: " + models.size());
        Collection<VirtualCluster> dtos = virtualClusterTransformer.transformToDtos(models);
        VirtualClusters vClusters = new VirtualClusters();
        if (dtos != null && !dtos.isEmpty()) {
            vClusters.getVirtualCluster().addAll(dtos);
        }
        return vClusters;
    }
}