net.emotivecloud.scheduler.drp4ost.DRP4OST.java Source code

Java tutorial

Introduction

Here is the source code for net.emotivecloud.scheduler.drp4ost.DRP4OST.java

Source

/**
 * Copyright (C) 2010-2013 Barcelona Supercomputing Center
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version. This library is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details. You should have received a copy of
 * the GNU Lesser General Public License along with this library; if not, write
 * to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307 USA
 */
package net.emotivecloud.scheduler.drp4ost;

import com.sun.jersey.spi.resource.Singleton;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.xml.bind.JAXBException;
import javax.xml.bind.MarshalException;
import javax.xml.bind.PropertyException;
import javax.xml.bind.UnmarshalException;
import javax.xml.bind.ValidationException;
import net.emotivecloud.commons.ListStrings;
import net.emotivecloud.utils.ovf.EmotiveOVF;
import net.emotivecloud.utils.ovf.OVFAux;
import net.emotivecloud.utils.ovf.OVFDisk;
import net.emotivecloud.utils.ovf.OVFException;
import net.emotivecloud.utils.ovf.OVFNetwork;
import net.emotivecloud.utils.ovf.OVFWrapper;
import net.emotivecloud.utils.ovf.OVFWrapperFactory;
import org.apache.commons.io.FileUtils;
import org.dmtf.schemas.ovf.envelope._1.ProductSectionType;
import org.dmtf.schemas.ovf.envelope._1.SectionType;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

/**
 * *************************************************************************
 * Este es el componente con el cual la capa de Gestin de Cloud Federada *
 * interacta directamente. Se trata de un interfaz REST. La implementacin* que
 * se har ser mediante el protocolo HTTP y los mtodos GET, POST, PUT* y
 * DELETE. *
 *
 * ------------------------------------------------------------------------*
 * Skeleton reused by ENG with BSC fine OVFWrapper to use OpenNebula OCA *
 * ************************************************************************
 */
/**
 * This is the OCCI API interface with whom the VMManager interacts with
 * OpenStack. It is an extension of the REST OCCI API which transforms the http
 * requests to http requests that OpenNebula can execute.
 *
 * REST Interface:
 *
 * @GET
 * @Path("/compute"):
 * @GET
 * @Path("/compute/{envid}"):
 * @GET
 * @Path("/compute/all"):
 * @GET
 * @Path("/environments/{envid}/status"):
 * @GET
 * @Path("/environments/{envid}/{taskid}"):
 *
 * @POST /compute:
 *
 * @DELETE
 * @Path("/compute/{envid}"):
 *
 * @author
 */
@Path("/")
@Singleton
/**
 * Class
 * <code>DRP4OST</code> the class providing the REST service implementation
 *
 * @author smendoza
 */
public class DRP4OST { // implements Closeable {

    private OStackClient oStackClient = null;
    private String tmpPath = "/tmp/";

    public DRP4OST() {
        oStackClient = new OStackClient();
    }

    @GET
    @Path("/info")
    @Produces("text/plain")
    public String info() {
        return "DRP is running";
    }

    @GET
    @Path("/mergetest")
    public void merge() {
        String isoImage = "/home/smendoza/contextiso.iso.test";
        String qcow2Image = "/home/smendoza/interoperabilityTest.qcow2.test";
        System.out.println("DRP4OST-merge()> isoImage=" + isoImage + ", qcow2Image=" + qcow2Image);
        ImageMerge.merge(isoImage, qcow2Image);
    }

    /**
     * *************************************************************************
     * Methods with a correspondence in the OCCI interface. *
     * ************************************************************************
     */
    /**
     * Method to manage the get to http://host/ovf4one/compute/[envid], that
     * retrieves data about the given VM instance
     *
     * @param envId a <code>String</code> the ID of the VM instance we are
     * interested in
     * @param request an <code>HttpServletRequest</code> with the full http
     * request
     * @return a <code>String</code> an OVF file with the required informations
     * @exception DRPOneException If something goes wrong, what else ?
     *
     */
    /**
     * Creates a VM on OpenStack with the information received from the *.ovf
     * content received attached to the POST request. Returns an OVF with the VM
     * launched
     *
     * @param ovfXml
     * @return String containin an OVF input with the VM instance ID
     * @throws DRPOSTException
     */
    @POST
    @Path("/compute")
    @Consumes("application/xml")
    @Produces("application/xml")
    public String createCompute(String ovfXml) throws DRPOSTException {

        HashMap<String, String> hmap = new HashMap<String, String>();

        String vmName = null;
        String vmID = null;

        System.out.println("**********************************************");
        System.out.println("**********************************************");
        System.out.println("**********************************************");
        System.out.println("THE OVF: \n" + ovfXml);
        System.out.println("**********************************************");
        System.out.println("**********************************************");
        System.out.println("**********************************************");

        //(0) Parse the info from the *.ovf
        if (ovfXml == null) {
            throw new DRPOSTException("\nFailed createCompute method!!\n." + "\nThe ovf xml is" + ovfXml
                    + "\n.Please enter correct xml ovf and try again.\n", StatusCodes.BAD_OVF);
        }
        OVFWrapper ovf;
        try {
            ovf = parse(ovfXml);
        } catch (DRPOSTException e) {
            // This one is expectet to be thrown, and should pass unchanged
            throw e;
        } catch (Exception e) {
            throw new DRPOSTException("\nFailed createCompute method!!\n"
                    + "An error occured to parse ovfXml.\n The parse of ovfxml is " + e.getCause()
                    + "\n.Please enter correct xml ovf anf try again.\n", StatusCodes.BAD_OVF);

        }
        EmotiveOVF emotiveOvf = new EmotiveOVF(ovf);
        List<SectionType> sections = OVFAux.findSections(emotiveOvf.getOVFEnvelope().getSection(),
                ProductSectionType.class);
        ProductSectionType ps = null;
        for (SectionType s : sections) {
            if (s instanceof ProductSectionType
                    && ((ProductSectionType) s).getClazz().equals(OVFWrapper.class.getName())) {
                ps = (ProductSectionType) s;
                break;

            }
        }
        if (ps != null) {
            List cop = ps.getCategoryOrProperty();
            ProductSectionType.Property propertyToRemove = null;
            for (Object prop : cop) {
                if (prop instanceof ProductSectionType.Property) {
                    ProductSectionType.Property p = (ProductSectionType.Property) prop;
                    hmap.put(p.getKey(), p.getValueAttribute());
                }
            }
        }

        //(1) we must create an Image for the VM

        //(1.1) Merge ISO & QCOW2
        Collection<OVFDisk> tmpDisks = ovf.getDisks().values();
        OVFDisk oDisks[] = tmpDisks.toArray(new OVFDisk[tmpDisks.size()]);
        String baseImageID = emotiveOvf.getBaseImage();
        String pathLocalIso = null;
        String pathLocalBaseImage = null;
        OVFDisk baseDisk = null;
        boolean isoFound = false;
        boolean baseFound = false;

        String name = emotiveOvf.getId();

        for (OVFDisk disk : oDisks) {

            String path = disk.getHref();

            System.out.println("DRP4OST>createCompute()Disk info- disk.getId()=" + disk.getId()
                    + ", disk.getHref()=" + disk.getHref());
            System.out.println("DRP4OST>createCompute()Disk info- disk.getHref()=" + disk.getHref());

            if (path.trim().endsWith(".iso")) {
                pathLocalIso = this.tmpPath + getFileNameFromPath(path);
                downloadImage(path, pathLocalIso);
                isoFound = true;
                System.out.println("DRP4OST>createCompute()Found ISO to merge isoPath=" + pathLocalIso);
            } else if (path.contains(baseImageID)) {
                pathLocalBaseImage = this.tmpPath + getFileNameFromPath(path);
                downloadImage(path, pathLocalBaseImage);
                baseDisk = disk;
                baseFound = true;
                System.out.println(
                        "DRP4OST>createCompute()Found baseImage to merge baseImagePath=" + pathLocalBaseImage);
            } else {
                // if not base, and not iso, leave the images
                System.out.println(
                        "DRP4OST>createCompute(), This disk will be ignored (suposed to use just QCOW2 and ISO)");
            }
        }

        // Verify that merge is possible
        if (isoFound && baseFound) {
            ImageMerge.merge(pathLocalIso, pathLocalBaseImage);
        } else {
            System.out.println("DRP4OST>createCompute() -> ISO or BASE missing: isoFound=" + isoFound
                    + ", baseFound=" + baseFound);
        }

        //(1.2) Create the baseImage at the OpenStack repository (if iso found, it has been merged)
        if (!existsImage(getFileNameFromPath(baseDisk.getHref()))) {
            baseImageID = createImage(baseDisk, pathLocalBaseImage);
        } else {
            System.out.println("DRP4OST>CREATE IMAGE: NO (ALREADY exist), baseDisk.getId()=" + baseDisk.getId());
            //TODO: get image ID
        }

        //Remove the downloaded images, after merged and uploaded to OpenStack
        FileUtils.deleteQuietly(new File(pathLocalBaseImage));
        FileUtils.deleteQuietly(new File(pathLocalIso));

        //(2) we must create a flavor for the VM
        String flavorID = createFlavor(emotiveOvf);

        //(3) we must create VM with Flavor & Image created at sections (1)&(2)
        vmName = ovf.getId(); // + "_" + (new Random()).nextInt(99999999);

        String host = emotiveOvf.getProductProperty(EmotiveOVF.PROPERTYNAME_DESTINATION_HOST);

        if (host != null) {
            String response = oStackClient.createVM(flavorID, baseImageID, vmName, host);
            // Parsing the JSON response to get the flavor ID
            JSONObject jo = (JSONObject) JSONValue.parse(response);
            jo = (JSONObject) jo.get("server");
            vmID = jo.get("id").toString();
        } else {
            String response = oStackClient.createVM(flavorID, baseImageID, vmName);
            JSONObject jo = (JSONObject) JSONValue.parse(response);
            jo = (JSONObject) jo.get("server");
            vmID = jo.get("id").toString();
        }
        System.out.println("DRP4OST>DRP4OST.createImage(), VM created vmID=" + vmID);

        // get the network properties
        //        Collection<OVFNetwork> tmpNets = ovf.getNetworks().values();
        //        OVFNetwork nets[] = tmpNets.toArray(new OVFNetwork[tmpNets.size()]);

        //        public OVFNetwork(String connectionName, String ip, String mac, String netmask, String gateway)
        OVFNetwork nets[] = this.getNetworks(vmID);

        // Create the ovf
        String xx = OVFWrapperFactory.create(vmID, ovf.getCPUsNumber(), ovf.getMemoryMB(), oDisks, nets, hmap)
                .toCleanString();

        return xx;
    }

    @POST
    @Path("/compute/{vmId}/migrate")
    @Produces("application/xml")
    public String migrate(@PathParam("vmId") String vmId, @QueryParam("dstHost") String dstHost)
            throws DRPOSTException {

        System.out.println("DRP4OST: VMID: " + vmId);
        System.out.println("DRP4OST: DSTHOST: " + dstHost);
        //        int intVmId = Integer.parseInt(vmId);
        //        int intDstHost = Integer.parseInt(dstHost);
        //        intVmId = 4;
        //        intDstHost = 6;
        oStackClient.migrate(vmId, dstHost);
        // Create the ovf
        //        String xx = OVFWrapperFactory.create(String.valueOf(baseImageID),
        //                ovf.getCPUsNumber(), ovf.getMemoryMB(), oDisks, nets, hmap)
        //                .toCleanString();
        //
        //        return xx;
        return "el retorno";
    }

    @GET
    @Path("/compute/{envid}")
    @Produces("application/xml")
    public String getCompute(@PathParam("envid") String envId) throws DRPOSTException {

        String vmDetails = null;

        vmDetails = oStackClient.getServerAsOVF(envId);

        return vmDetails;
    }

    /**
     *
     * @return A ListStrings object containing the vmIDs of the VMs launched by
     * the user
     */
    @GET
    @Path("/compute")
    @Produces("application/xml")
    public ListStrings getComputes() {

        ArrayList<String> allVMsIDs = oStackClient.getAllVMsIDs();
        ListStrings vmsIDsList = new ListStrings();
        vmsIDsList.addAll(allVMsIDs);

        return vmsIDsList;

    }

    /**
     * <code>deleteCompute</code> Kills an instance of a VM
     *
     * @param envid a <code>String</code> the id of the VM to kill
     * @exception DRPOSTException when something goes wrong.
     */
    @DELETE
    @Path("/compute/{envid}")
    public void deleteCompute(@PathParam("envid") String envId) throws DRPOSTException {

        String imageId = oStackClient.getServerImage(envId);

        int nactive = oStackClient.activeInstancesWithImage(imageId);
        boolean deleteAccepted = oStackClient.deleteVM(envId);

        //If the delete request was accepted and it was the last VM, proceed deleting the Image
        if (deleteAccepted && nactive == 1) {
            System.out.println("DRP4OST-deleteCompute()> DELETING image=" + imageId
                    + ", oStackClient.activeInstancesWithImage(" + imageId + ")="
                    + oStackClient.activeInstancesWithImage(imageId));
            oStackClient.deleteImage(imageId);
        } else {
            System.out.println("DRP4OST-deleteCompute()> NOT DELETING image=" + imageId
                    + ", oStackClient.activeInstancesWithImage(" + imageId + ")="
                    + oStackClient.activeInstancesWithImage(imageId));
        }

    }

    /**
     * *************************COMPUTE methods.******************************
     */
    /**
     * Get a List with all the running environments.
     *
     * @return A ListStrings object containing a List with a set of OVFWrapper
     * objects expressed in XML, as Strings (using OVFWrapper.toCleanString).
     * They can be converted back to OVFWrapper objects using
     * OVFWrapperFactory.parse(String ovfxml).
     */
    @GET
    @Path("/compute/all")
    @Produces("application/xml")
    public ListStrings getAllEnvironments() {

        OVFWrapper[] w = this.getAllServersWrappers();
        ListStrings ret = new ListStrings();

        for (OVFWrapper ovf : w) {
            ret.add(ovf.toCleanString());
        }

        return ret;
    }

    @GET
    @Path("/environments/{envid}/status") //antic state, falta el destroy per arreglar, al VtM ho fa be
    @Produces("text/plain")
    public String getState(@PathParam("envid") String envId) {
        String status = "Unknown";

        try {
            // Status receives the OpenStack STATUS, we should transform to the equivalent in EMOTIVE
            // cause is the unique understood by the DRP4OST clients
            status = oStackClient.getVMStatus(envId);
        } catch (Exception e) {
            throw new DRPOSTException("Exception getting VM status", StatusCodes.BAD_REQUEST);
        }

        return status;
    }

    /**
     * *********************NODE MANAGEMENT methods.**************************
     */
    @GET
    @Path("/")
    @Produces("text/plain")
    public String getLocation(@QueryParam("id") String id) {
        String ret = "";
        if (id != null) {
            try {
                //                ret = super.getLocation(id, SecureSessionInfo.getUserDN(req));
                //            } catch (VRMMSchedulerException e) { //catch (ItemNotFoundException e) {
                //                e.printStackTrace();
                //                if (e.getMessage().contains("cannot be found in any node")) {
                //                    throw new WebApplicationException(e, 426);
                //                } else if (e.getMessage().contains("VirtMonitor")) {//REPAIR:VirtMonitor: getDomainId error.
                //                    throw new WebApplicationException(e, 420);
                //                } else if (e.getMessage().contains("Not enough resources")) {//REPAIR:INFO: Not enough resources: Memory
                //                    throw new WebApplicationException(e, 425);
                //                } else if (e.getMessage().contains("VM does not exist")) {//REPAIR:INFO: Not enough resources: Memory
                //                    throw new WebApplicationException(e, 427);
                //                } else if (e.getMessage().contains("No available nodes")) {
                //                    throw new WebApplicationException(e, 428);
                //                } else if (e.getMessage().contains("Cannot connect with the Scheduler ")) {
                //                    throw new WebApplicationException(e, 429);
                //                } else if (e.getMessage().contains("Cannot connect with Simple Scheduler")) {
                //                    throw new WebApplicationException(e, 430);
                //                } else if (e.getMessage().contains("Cannot connect with Hadoop Scheduler")) {
                //                    throw new WebApplicationException(e, 431);
                //                } else if (e.getMessage().contains("Cannot recognize address ")) {
                //                    throw new WebApplicationException(e, 432);
                //                } else if (e.getMessage().contains("is not in any VM")) {
                //                    throw new WebApplicationException(e, 433);
                //                } else if (e.getMessage().contains("cannot be found in any node")) {
                //                    throw new WebApplicationException(e, 434);
                //                } else {
                //                    throw new WebApplicationException(e, 424);
                //                }
                //            }
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new DRPOSTException("Exception getting Location", StatusCodes.BAD_REQUEST);
            }
        }
        return ret;
    }

    @GET
    @Path("/resources")
    @Produces("application/xml")
    public ListStrings getNodes() {
        ListStrings list = new ListStrings();
        ArrayList<String> hostsNames = new ArrayList<String>();

        String hosts = oStackClient.getHosts();
        JSONObject jsonHosts = (JSONObject) JSONValue.parse(hosts);
        JSONArray jsonHostsArray = (JSONArray) jsonHosts.get("hosts");

        for (int i = 0; i < jsonHostsArray.size(); ++i) {
            JSONObject flavor = (JSONObject) jsonHostsArray.get(i);
            String hostName = flavor.get("host_name").toString();
            hostsNames.add(hostName);
        }

        list.addAll(hostsNames);

        //        list.addAll(super.getNodes());
        //GenericEntity<ListStrings> entity = new GenericEntity<ListStrings>(list) {};
        //Response response = Response.ok(entity).build();
        return list;
    }

    @POST
    @Path("/resources")
    public void nodeUp(@QueryParam("node") String nodeId) {
        //        super.nodeUp(nodeId);
        oStackClient.startup(nodeId);

    }

    @DELETE
    @Path("/resources")
    public void nodeDown(@QueryParam("node") String node, @QueryParam("cause") String type) {
        //        super.nodeDown(node, type);
        oStackClient.shutdown(node);
    }

    //    public String getLocation(String id) throws VRMMSchedulerException {
    //        return getLocation(id, (String) null);
    //    }
    /*
     * *************************************************************************
     * Functions to help OCCI Interface
     * *************************************************************************
     */
    /**
     *
     * @param username
     * @param psswd
     * @param projectName
     * @return
     */
    private String getToken(String username, String psswd, String projectName) {

        return oStackClient.getToken(username, psswd, projectName);

    }

    /**
     * Returns the private IPs associated to the server ID
     *
     * @param vmID
     * @return
     */
    public String[] getIPs(String serverID) {

        ArrayList<String> ips = new ArrayList<String>();
        String serverDetails = null;
        String status = "UNKNOWN";

        // Until VM has ACTIVE status, no IP is assigned
        while (!status.equals("ACTIVE")) {
            serverDetails = oStackClient.getServer(serverID);
            status = oStackClient.getVMStatus(serverID);
            System.out.println("DRP4OST>DRP4OST.getIPs(), VM has status=" + status);
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // Parsing the JSON response to get all the images
        JSONObject allFlavors = (JSONObject) JSONValue.parse(serverDetails);
        JSONObject jsonServer = (JSONObject) allFlavors.get("server");
        JSONObject jsonAddresses = (JSONObject) jsonServer.get("addresses");
        JSONArray jsonPrivate = (JSONArray) jsonAddresses.get("private");

        for (int i = 0; i < jsonPrivate.size(); ++i) {
            JSONObject addr = (JSONObject) jsonPrivate.get(i);
            String tmpAddr = addr.get("addr").toString();
            ips.add(tmpAddr);
            System.out.println("DRP4OST>DRP4OST.getIPs(), VM has ip=" + tmpAddr);
        }

        String[] ipsArray = ips.toArray(new String[ips.size()]);
        return ipsArray;

    }

    private OVFNetwork[] getNetworks(String serverID) {

        String[] ips = this.getIPs(serverID);

        OVFNetwork[] nets = new OVFNetwork[ips.length];

        for (int i = 0; i < ips.length; ++i) {
            //public OVFNetwork(String connectionName, String ip, String mac, String netmask, String gateway)
            //            nets[i] = new OVFNetwork(null, ips[i], null, null, null);
            nets[i] = new OVFNetwork("public", ips[i], null, null, null);
        }

        return nets;
    }

    //    //        public OVFNetwork(String connectionName, String ip, String mac, String netmask, String gateway)
    //    private OVFNetwork getNetworkDetails(String label) {
    //        String apiAddress = ":8774/v2/" + projectID + "/os-networks/" + networkID;
    //        OVFNetwork net = null;
    //        String connectionName = null;
    //        String ip = null;
    //        String mac = null;
    //        String netmask = null;
    //        String gateway = null;
    //
    //        //Instantiate an HttpClient
    //        HttpClient client = new DefaultHttpClient();
    //        try {
    //            //Instantiate a GET HTTP method
    //            HttpGet request = new HttpGet(this.serverIP + apiAddress);
    //            request.setHeader("X-Auth-Token", this.token);
    //
    //            //Execute the request, obtain a Response
    //            HttpResponse response = client.execute(request);
    //
    //            //If the response is not OK, throw an exception
    //            if (response.getStatusLine().getStatusCode() != 200) {
    //                throw new DRPOSTException(response.getStatusLine().getReasonPhrase(), StatusCodes.BAD_REQUEST);
    //            }
    //
    //            //Get the Response Content in a String
    //            String responseContent = IOUtils.toString(response.getEntity().getContent());
    //            images = responseContent;
    //
    //        } catch (IOException ex) {
    //            throw new DRPOSTException("Exception getting all images", StatusCodes.BAD_REQUEST);
    //        }
    //
    //        return net;
    //    }
    // Generates a VM description starting from an ovf disk
    private String createImage(OVFDisk disk, String pathLocalBaseImage) {

        String name = oStackClient.createImage(disk, pathLocalBaseImage);

        //        return "e487d76e-ffdd-4356-9c9b-6f6356542262"; // La imagen del cirros por defecto
        return name;
    }

    /**
     * This function creates a Flavor with the extracted information from the
     * *.ovf . To create the Flavor, I'll need disk space (disk), VM ram (ram),
     * number of virtual CPU's (vcpus), Flavor name (name) and flavor
     * identification (name)
     *
     * @param ovf
     * @return ID of the created Flavor
     */
    private String createFlavor(EmotiveOVF ovf) {

        String flavorID = oStackClient.createFlavor(ovf);

        return flavorID;
    }

    private boolean existsImage(String imageID) {
        boolean exists = false;

        //Get the Response Content in a String
        String images = oStackClient.getAllImages();

        // Parsing the JSON response to get all the images
        JSONObject allImages = (JSONObject) JSONValue.parse(images);
        JSONArray jsonImages = (JSONArray) allImages.get("images");

        for (int i = 0; i < jsonImages.size(); ++i) {
            JSONObject image = (JSONObject) jsonImages.get(i);
            String tmpImgID = image.get("name").toString();
            if (tmpImgID.equals(imageID)) {
                exists = true;
                break;
            }
        }
        return exists;
    }

    private OVFWrapper[] getAllServersWrappers() {
        ArrayList<OVFWrapper> wrappers = new ArrayList<OVFWrapper>();
        String servers = oStackClient.getAllServers();

        JSONObject allServers = (JSONObject) JSONValue.parse(servers);
        JSONArray jsonServers = (JSONArray) allServers.get("servers");

        for (int i = 0; i < jsonServers.size(); ++i) {
            JSONObject server = (JSONObject) jsonServers.get(i);
            OVFWrapper wTmp = this.parse(server.toString());
            wrappers.add(wTmp);
        }

        OVFWrapper vms[] = wrappers.toArray(new OVFWrapper[wrappers.size()]);

        return vms;
    }

    private OVFWrapper parse(String ovfXml) {
        OVFWrapper rv = null;
        StringBuilder cause = new StringBuilder();

        try {
            rv = OVFWrapperFactory.parse(ovfXml);
        } catch (JAXBException e) {
            if (e instanceof PropertyException) {
                cause.append("Access to property failed: " + e.getErrorCode());
            } else if (e instanceof MarshalException) {
                cause.append("Marshalling failed: " + e.getLocalizedMessage());
            } else if (e instanceof UnmarshalException) {
                cause.append("Unmarshalling failed: " + e.getCause());
            } else if (e instanceof ValidationException) {
                cause.append("XML Validation failed: " + e.getErrorCode());
            } else {
                cause.append("Unespected " + e.getErrorCode());
                cause.append(e.getClass().getName());
                cause.append(": ");
            }

            cause.append(e.getMessage());

            throw new DRPOSTException(cause.toString(), e, StatusCodes.XML_PROBLEM);
        } catch (OVFException e) {
            cause.append("Problems parsing OVF file: ");
            cause.append(e.getMessage());

            throw new DRPOSTException(cause.toString(), e, StatusCodes.XML_PROBLEM);
        }
        return rv;
    }

    private void downloadImage(String imageURL, String dest) {
        try {
            //            System.out.println("DRP4OST.downloadImage()>START Downloading from imageURL=" + imageURL + " to dest=" + dest);
            FileUtils.copyURLToFile(new URL(imageURL), new File(dest));
            //            System.out.println("DRP4OST.downloadImage()>FINISH Downloading from imageURL=" + imageURL + " to dest=" + dest);
        } catch (Exception e) {
            System.out.println("DRP4OST.downloadImage()>Exception downloading the file");
            e.printStackTrace();
        }
    }

    private String getFileNameFromPath(String path) {
        String[] pathSplit = path.split("[/]");
        String fileName = pathSplit[pathSplit.length - 1];
        return fileName;

    }
}