com.abiquo.abiserver.scheduler.SchedulerRestrictions.java Source code

Java tutorial

Introduction

Here is the source code for com.abiquo.abiserver.scheduler.SchedulerRestrictions.java

Source

/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS IS" 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is available at http://www.abiquo.com/.....
 * 
 * The Initial Developer of the Original Code is Soluciones Grid, S.L. (www.abiquo.com),
 * Consell de Cent 296, Principal 2, 08007 Barcelona, Spain.
 * 
 * No portions of the Code have been created by third parties. 
 * All Rights Reserved.
 * 
 * Contributor(s): ______________________________________.
 * 
 * Graphical User Interface of this software may be used under the terms
 * of the Common Public Attribution License Version 1.0 (the  "CPAL License", 
 * available at http://cpal.abiquo.com/), in which case the 
 * provisions of CPAL License are applicable instead of those above. In relation 
 * of this portions of the Code, a Legal Notice according to Exhibits A and B of 
 * CPAL Licence should be provided in any distribution of the corresponding Code 
 * to Graphical User Interface.
 */
package com.abiquo.abiserver.scheduler;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import com.abiquo.abiserver.business.hibernate.pojohb.infrastructure.HypervisorHB;
import com.abiquo.abiserver.business.hibernate.pojohb.infrastructure.PhysicalmachineHB;
import com.abiquo.abiserver.business.hibernate.util.HibernateUtil;
import com.abiquo.abiserver.pojo.infrastructure.HyperVisor;
import com.abiquo.abiserver.pojo.infrastructure.PhysicalMachine;
import com.abiquo.abiserver.pojo.infrastructure.State;
import com.abiquo.abiserver.pojo.infrastructure.VirtualMachine;
import com.abiquo.abiserver.pojo.virtualimage.VirtualImage;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;

/**
 * Abstract IScheduler implementation, contains database transactions (Hibernate ->DB layer).
 * Selects form database only the PhysicalMachines with enough cpu, ram and hd on the selectMachine
 * function. Convert ''selectMachines'' to ''select'' with a PhysicalMachines candidate (all capable
 * to deploy the image) list.
 */
public abstract class SchedulerRestrictions implements IScheduler {

    /** The logger object */
    private final static Logger log = Logger.getLogger(SchedulerRestrictions.class);

    /** The remote desktop min port **/
    private final static int minRemoteDesktopPort = 3389;

    /**
     * Select one PhysicalMachine form the candidate list. Strategy pattern implementation.
     * 
     * @param candidateMachines a list of PhysicalMachines with enough resources for the target
     *            VirtualImage.
     * @return a PhysicalMachine contained on candidateMachines.
     */
    public abstract PhysicalMachine select(List<PhysicalMachine> candidateMachines);

    /**
     * @see com.abiquo.abiserver.scheduler.IScheduler#selectMachine
     */
    public VirtualMachine selectMachine(VirtualImage targetImage, String dataCenter) throws SchedulerException {
        ImageRequired required;
        List<PhysicalMachine> physicalCandidates;
        PhysicalMachine physicalTarget;
        VirtualMachine virtualTarget;

        required = new ImageRequired(targetImage.getCpuRequired(), targetImage.getHdRequired(),
                targetImage.getRamRequired(), dataCenter);

        log.debug("TargetImage name:" + targetImage.getName() + "at dataCenter:" + dataCenter + " REQUIRE hd:"
                + required.getHd() + " ram:" + required.getRam());

        physicalCandidates = getFilteredMachines(required);

        log.debug("There are " + physicalCandidates.size() + "physical machine candidates ");

        physicalTarget = select(physicalCandidates);

        log.info("Selected PhysicalMachine !!! " + physicalTarget.getName());

        updateUsageDeployedPhysicalMachine(physicalTarget, required, true);

        log.debug("Updated physical resources usage");

        virtualTarget = instantiate(physicalTarget, targetImage);

        log.debug("Instantiated VirtualMachine " + virtualTarget.getName());

        return virtualTarget;
    }

    /**
     * @see com.abiquo.abiserver.scheduler.IScheduler#selectMachine Iterative: requirements are take
     *      one by one. (TODO: requirement sort)
     */
    public List<VirtualMachine> selectMachines(List<VirtualImage> targetImages, String dataCenter)
            throws SchedulerException {
        List<VirtualMachine> virtuals;

        virtuals = new ArrayList<VirtualMachine>();

        log.warn("Iterative allocate multiple VirtualMachines");

        for (VirtualImage image : targetImages) {
            virtuals.add(selectMachine(image, dataCenter));
        }

        return virtuals;
    }

    /**
     * Get all the available PhysicalMachines with enough resources for the VirtualImage. It access
     * DB throw Hibernate.
     * 
     * @param required, the resources capacity used on the target VirtualImage (ram, hd,
     *            dataCenter).
     * @return all PhysicalMachines available to instantiate a VirtualMachine for the target
     *         VirtualImage.
     * @throws SchedulerException, if there is not any PhysicalMachine with enough resources.
     */
    @SuppressWarnings("unchecked")
    // PhysicalmachineHB
    private List<PhysicalMachine> getFilteredMachines(ImageRequired required) throws SchedulerException {
        List<PhysicalMachine> machines;
        List<PhysicalmachineHB> machinesHibernate;

        Query physicalFiler;
        Session session;

        session = HibernateUtil.getSession();

        physicalFiler = session.createQuery("select pm "
                + "from com.abiquo.abiserver.business.hibernate.pojohb.infrastructure.PhysicalmachineHB pm "
                + "join pm.rack rk " + "join rk.datacenter dc " + "where " + "dc.name in  ('"
                + required.getDataCenter() + "') and " + "(pm.ram - pm.ramUsed) >= " + required.getRam() + " "
                + "and (pm.hd  - pm.hdUsed)  >= " + required.getHd());

        log.debug("HQL : " + physicalFiler.getQueryString());

        machinesHibernate = physicalFiler.list();

        if (machinesHibernate.size() == 0) {

            throw new SchedulerException(
                    "Not enough physical machine capacity to instantiate the required virtual appliance", required);
        }

        machines = new ArrayList<PhysicalMachine>();

        for (PhysicalmachineHB machineHib : machinesHibernate) {
            log.debug("PhysicalMachine candidate : " + machineHib.getName());
            machines.add((PhysicalMachine) machineHib.toPojo());
        }

        return machines;
    }

    /**
     * Set the resource usage on PhysicalMachine after instantiating the new VirtualMachine. It
     * access DB throw Hibernate.
     * 
     * @param machine, the machine to reduce/increase its resource capacity.
     * @param used, the VirtualImage requirements to substract/add.
     * @param isAdd, true if reducing the amount of resources on the PhysicalMachine. Else it adds
     *            capacity (as a rollback on VirtualImage deploy Exception).
     */
    private void updateUsageDeployedPhysicalMachine(PhysicalMachine machine, ImageRequired used,
            boolean isReducing) {
        PhysicalmachineHB machineHib;
        Session session;

        session = HibernateUtil.getSession();

        log.debug("ram used: " + used.getRam() + "hd used: " + used.getHd());
        machineHib = (PhysicalmachineHB) session.get(PhysicalmachineHB.class, machine.getId());

        if (isReducing) {
            // machineHib.setCpuUsed(machineHib.getCpuUsed().add(used.getCpu()));
            machineHib.setRamUsed(machineHib.getRamUsed() + used.getRam());
            machineHib.setHdUsed(machineHib.getHdUsed() + used.getHd());
        } else {
            // machineHib.setCpuUsed(machineHib.getCpuUsed().subtract(used.getCpu()));
            machineHib.setRamUsed(machineHib.getRamUsed() - used.getRam());
            machineHib.setHdUsed(machineHib.getHdUsed() - used.getHd());
        }

        session.update(machineHib);
    }

    /**
     * Create a Virtual Machine on the given PhysicalMachine to deploy the given VirtualMachine.
     * 
     * @param physical, the target PhysicalMachine where create a new VirtualMachine (using
     *            PhysicalMachine's Hypervisor)
     * @param image, the target VirtaulImage to be deployed on the returned VirtualMachine (used to
     *            allocate resource usage)
     * @return a new VirtualMachine instance inside physical to load image. TODO: creating default
     *         Hypervisor instance TODO: VdrpIP, VdrpPort
     */
    private VirtualMachine instantiate(PhysicalMachine physical, VirtualImage image) {
        HyperVisor hypervisor;
        VirtualMachine virtual;

        // The hypervisors shall be discovered when the physical machine are loaded so we recover
        // the hypervisors from the DB
        Session session;
        PhysicalmachineHB physicalMachineHB;
        Set<HypervisorHB> hypervisorsHB;

        session = HibernateUtil.getSession();

        physicalMachineHB = (PhysicalmachineHB) session.get(PhysicalmachineHB.class, physical.getId());
        hypervisorsHB = physicalMachineHB.getHypervisors();

        // Getting one hypervisor from the list. TODO Change this decision when multihypervisors are
        // used
        HypervisorHB hypervisorHB = hypervisorsHB.iterator().next();
        log.info("The hypervisor: " + hypervisorHB.getType().getName() + " will be used");
        hypervisor = (HyperVisor) hypervisorHB.toPojo();

        State state = new State();
        // state.setDescription(statePojo.getDescription());
        state.setId(State.NOT_DEPLOYED);

        // TODO default also high disponibility flag)
        virtual = new VirtualMachine();
        virtual.setVirtualImage(image);
        virtual.setName(UUID.randomUUID().toString()); // TODO
        virtual.setDescription(image.getDescription());
        virtual.setCpu(image.getCpuRequired());
        virtual.setHd(image.getHdRequired());
        virtual.setRam(image.getRamRequired());
        virtual.setState(state);
        // Setting the default VRDP acces
        virtual.setVdrpIP(hypervisor.getIp());
        // Selecting the max port
        Integer rdpPort = null;
        Integer maxRdpPort = (Integer) session.createQuery("select MAX(vdrpPort)"
                + "from com.abiquo.abiserver.business.hibernate.pojohb.infrastructure.VirtualmachineHB "
                + "where idHypervisor = " + hypervisor.getId()).uniqueResult();

        if (maxRdpPort == null) {
            rdpPort = minRemoteDesktopPort;
        } else {
            rdpPort = maxRdpPort + 1;
            log.debug("The assigned port is: " + rdpPort);
        }
        virtual.setVdrpPort(rdpPort);
        virtual.setUUID(UUID.randomUUID().toString());
        virtual.setAssignedTo(hypervisor);

        /**
         * TODO virtualMachine.setHighDisponibility(virtualMachinePojo.get)
         * virtual.setVdrpIP(virtualMachinePojo.getVdrpIp());
         * virtual.setVdrpPort(virtualMachinePojo.getVdrpPort());
         **/

        return virtual;
    }

    /**
     * @param physicalMachine
     * @see com.abiquo.abiserver.scheduler.IScheduler#rollback
     */
    public void rollback(VirtualMachine virtual, PhysicalMachine physicalMachine) {
        ImageRequired required;

        required = new ImageRequired(virtual.getCpu(), virtual.getHd(), virtual.getRam(), "nodatacenter");

        updateUsageDeployedPhysicalMachine(physicalMachine, required, false);
    }

}

/**
 * Pojo class maintaining the resource requirements for a VirtualImage
 */
class ImageRequired {
    int cpu;

    long hd;

    int ram;

    String dataCenter;

    public ImageRequired(int i, long l, int ram, String dataCenter) {
        this.cpu = i;
        this.hd = l;
        this.ram = ram;
        this.dataCenter = dataCenter;
    }

    public String getDataCenter() {
        return dataCenter;
    }

    public void setDataCenter(String dataCenter) {
        this.dataCenter = dataCenter;
    }

    public int getCpu() {
        return cpu;
    }

    public long getHd() {
        return hd;
    }

    public int getRam() {
        return ram;
    }
}