All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dasein.cloud.cloudstack.compute.VirtualMachines Maven / Gradle / Ivy

Go to download

Implements the Dasein Cloud API for Cloud.com Cloudstack-based public and private clouds.

There is a newer version: 2015.10.5
Show newest version
/**
 * Copyright (C) 2009-2015 Dell, Inc.
 *
 * ====================================================================
 * 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.dasein.cloud.cloudstack.compute;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.dasein.cloud.*;
import org.dasein.cloud.cloudstack.*;
import org.dasein.cloud.cloudstack.network.Network;
import org.dasein.cloud.cloudstack.network.SecurityGroup;
import org.dasein.cloud.compute.*;
import org.dasein.cloud.network.RawAddress;
import org.dasein.cloud.util.APITrace;
import org.dasein.cloud.util.Cache;
import org.dasein.cloud.util.CacheLevel;
import org.dasein.util.CalendarWrapper;
import org.dasein.util.uom.storage.Gigabyte;
import org.dasein.util.uom.storage.Megabyte;
import org.dasein.util.uom.storage.Storage;
import org.dasein.util.uom.time.Hour;
import org.dasein.util.uom.time.TimePeriod;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class VirtualMachines extends AbstractVMSupport {
    static public final Logger logger = Logger.getLogger(VirtualMachines.class);
    
    static private final String DEPLOY_VIRTUAL_MACHINE  = "deployVirtualMachine";
    static private final String DESTROY_VIRTUAL_MACHINE = "destroyVirtualMachine";
    static private final String GET_VIRTUAL_MACHINE_PASSWORD = "getVMPassword";
    static private final String LIST_VIRTUAL_MACHINES   = "listVirtualMachines";
    static private final String LIST_SERVICE_OFFERINGS  = "listServiceOfferings";
    static private final String REBOOT_VIRTUAL_MACHINE  = "rebootVirtualMachine";
    static private final String RESET_VIRTUAL_MACHINE_PASSWORD = "resetPasswordForVirtualMachine";
    static private final String RESIZE_VIRTUAL_MACHINE  = "scaleVirtualMachine";
    static private final String START_VIRTUAL_MACHINE   = "startVirtualMachine";
    static private final String STOP_VIRTUAL_MACHINE    = "stopVirtualMachine";
    
    static private Properties                              cloudMappings;
    static private Map>          customNetworkMappings;
    static private Map>>     customServiceMappings;
    
    public VirtualMachines(CSCloud provider) {
        super(provider);
    }

    @Override
    public VirtualMachine alterVirtualMachineSize( @Nonnull String vmId, @Nullable String cpuCount, @Nullable String ramInMB ) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.alterVirtualMachineSize");
        try {
            CSMethod method = new CSMethod(getProvider());

            VirtualMachine vm = getVirtualMachine(vmId);

            boolean restart = false;
            if (!vm.getCurrentState().equals(VmState.STOPPED)) {
                restart = true;
                stop(vmId, true);
            }

            long timeout = System.currentTimeMillis()+(CalendarWrapper.MINUTE*20L);
            while (System.currentTimeMillis() < timeout) {
                if (!vm.getCurrentState().equals(VmState.STOPPED)) {
                    try {
                        Thread.sleep(15000L);
                        vm = getVirtualMachine(vmId);
                    }
                    catch (InterruptedException ignore) {}
                }
                else {
                    break;
                }
            }
            vm = getVirtualMachine(vmId);
            if (!vm.getCurrentState().equals(VmState.STOPPED)) {
                throw new CloudException("Unable to stop vm for scaling");
            }
            List params = new ArrayList();
            params.add(new Param("id", vmId));
            params.add(new Param("serviceOfferingId", vm.getProductId()));
            int index = 0;
            if( cpuCount != null ) {
                params.add(new Param("details["+index+"].cpunumber", cpuCount));
                index++;
            }
            if( ramInMB != null ) {
                params.add(new Param("details["+index+"].memory", ramInMB));
            }
            Document doc = method.get(method.buildUrl(RESIZE_VIRTUAL_MACHINE, params), RESIZE_VIRTUAL_MACHINE);

            NodeList matches = doc.getElementsByTagName("scalevirtualmachineresponse");
            String jobId = null;

            for( int i=0; i 0) {
                    Node virtualMachine = nodeList.item(0);
                    vm = toVirtualMachine(virtualMachine);
                    if( vm != null ) {
                        if (restart) {
                            start(vmId);
                        }
                        return vm;
                    }
                }
            }
            if (restart) {
                start(vmId);
            }
            return getVirtualMachine(vmId);
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public VirtualMachine alterVirtualMachineProduct(@Nonnull String vmId, @Nonnull String productId) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.alterVirtualMachineProduct");
        try {
            CSMethod method = new CSMethod(getProvider());

            VirtualMachine vm = getVirtualMachine(vmId);
            if (vm.getProductId().equals(productId)) {
                return vm;
            }

            boolean restart = false;
            if (!vm.getCurrentState().equals(VmState.STOPPED)) {
                restart = true;
                stop(vmId, true);
            }

            long timeout = System.currentTimeMillis()+(CalendarWrapper.MINUTE*20L);
            while (System.currentTimeMillis() < timeout) {
                if (!vm.getCurrentState().equals(VmState.STOPPED)) {
                    try {
                        Thread.sleep(15000L);
                        vm = getVirtualMachine(vmId);
                    }
                    catch (InterruptedException ignore) {}
                }
                else {
                    break;
                }
            }
            vm = getVirtualMachine(vmId);
            if (!vm.getCurrentState().equals(VmState.STOPPED)) {
                throw new CloudException("Unable to stop vm for scaling");
            }
            Document doc = method.get(method.buildUrl(RESIZE_VIRTUAL_MACHINE, new Param("id", vmId), new Param("serviceOfferingId", productId)), RESIZE_VIRTUAL_MACHINE);

            NodeList matches = doc.getElementsByTagName("scalevirtualmachineresponse");
            String jobId = null;

            for( int i=0; i 0) {
                    Node virtualMachine = nodeList.item(0);
                    vm = toVirtualMachine(virtualMachine);
                    if( vm != null ) {
                        if (restart) {
                            start(vmId);
                        }
                        return vm;
                    }
                }
            }
            if (restart) {
                start(vmId);
            }
            return getVirtualMachine(vmId);
        }
        finally {
            APITrace.end();
        }
    }

    private transient volatile VMCapabilities capabilities;
    @Nonnull
    @Override
    public VirtualMachineCapabilities getCapabilities() throws InternalException, CloudException {
        if( capabilities == null ) {
            capabilities = new VMCapabilities(getProvider());
        }
        return capabilities;
    }

    @Nullable
    @Override
    public VMScalingCapabilities describeVerticalScalingCapabilities() throws CloudException, InternalException {
        return VMScalingCapabilities.getInstance(false,true,Requirement.NONE,Requirement.NONE);
    }

    @Nullable
    @Override
    public String getPassword(@Nonnull String vmId) throws InternalException, CloudException {
        return getRootPassword(vmId);
    }

    private String getRootPassword(@Nonnull String serverId) throws CloudException, InternalException {
        APITrace.begin(getProvider(), "VM.getPassword");
        try {
            ProviderContext ctx = getContext();

            if( ctx == null ) {
                throw new CloudException("No context was specified for this request");
            }

            CSMethod method = new CSMethod(getProvider());
            Document doc = method.get(method.buildUrl(GET_VIRTUAL_MACHINE_PASSWORD, new Param("id", serverId)), GET_VIRTUAL_MACHINE_PASSWORD);

            if (doc != null){
                NodeList matches = doc.getElementsByTagName("getvmpasswordresponse");

                for( int i=0; i 0 ) {
                                value = attribute.getFirstChild().getNodeValue();
                            }
                            else {
                                value = null;
                            }
                            if( name.equals("password") ) {
                                NodeList nodes = attribute.getChildNodes();
                                for( int k=0; k 0 ) {
                                        value = password.getFirstChild().getNodeValue();
                                    }
                                    else {
                                        value = null;
                                    }
                                    if( name.equals("encryptedpassword") ) {
                                        return value;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            logger.warn("Unable to find password for vm with id "+serverId);
            return null;
        }
        catch (CSException e) {
            if (e.getHttpCode() == 431) {
                logger.warn("No password found for vm "+serverId);
            }
            return null;
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public @Nullable VirtualMachine getVirtualMachine(@Nonnull String serverId) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.getVirtualMachine");
        try {

            CSMethod method = new CSMethod(getProvider());

            try {
                Document doc = method.get(method.buildUrl(LIST_VIRTUAL_MACHINES, new Param("id", serverId)), LIST_VIRTUAL_MACHINES);
                NodeList matches = doc.getElementsByTagName("virtualmachine");

                if( matches.getLength() < 1 ) {
                    return null;
                }
                for( int i=0; i 0 ) {
                for( Tag tag : tags ) {
                    userData.append(tag.getKey());
                    userData.append("=");
                    userData.append(tag.getValue());
                    userData.append("\n");
                }
            }
            else {
                userData.append("created=Dasein Cloud\n");
            }
            return launch22(imageId, product, inZoneId, name, usingKey, withVlanId, protectedByFirewalls, userData.toString());
        }
        else {
            return launch21(imageId, product, inZoneId, name);
        }
    }
    
    private VirtualMachine launch21(String imageId, VirtualMachineProduct product, String inZoneId, String name) throws InternalException, CloudException {
        CSMethod method = new CSMethod(getProvider());
        return launch(method.get(method.buildUrl(DEPLOY_VIRTUAL_MACHINE, new Param("zoneId", getContext().getRegionId()), new Param("serviceOfferingId", product.getProviderProductId()), new Param("templateId", imageId), new Param("displayName", name) ), DEPLOY_VIRTUAL_MACHINE));
    }
    
    private void load() {
        try {
            InputStream input = VirtualMachines.class.getResourceAsStream("/cloudMappings.cfg");
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
            Properties properties = new Properties();
            String line;
            
            while( (line = reader.readLine()) != null ) {
                if( line.startsWith("#") ) {
                    continue;
                }
                int idx = line.indexOf('=');
                if( idx < 0 || line.endsWith("=") ) {
                    continue;
                }
                String cloudUrl = line.substring(0, idx);
                String cloudId = line.substring(idx+1);
                properties.put(cloudUrl, cloudId);
            }
            cloudMappings = properties;
        }
        catch( Throwable ignore ) {
            // ignore
        }        
        try {
            InputStream input = VirtualMachines.class.getResourceAsStream("/customNetworkMappings.cfg");
            Map> mapping = new HashMap>();
            Properties properties = new Properties();
            
            properties.load(input);
            for( Object key : properties.keySet() ) {
                String[] trueKey = ((String)key).split(",");
                Map current = mapping.get(trueKey[0]);
                
                if( current == null ) {
                    current = new HashMap();
                    mapping.put(trueKey[0], current);
                }
                current.put(trueKey[1], (String)properties.get(key));
            }
            customNetworkMappings = mapping;
        }
        catch( Throwable ignore ) {
            // ignore
        }
        try {
            InputStream input = VirtualMachines.class.getResourceAsStream("/customServiceMappings.cfg");
            Map>> mapping = new HashMap>>();
            Properties properties = new Properties();
            
            properties.load(input);
            
            for( Object key : properties.keySet() ) {
                String value = (String)properties.get(key);
                
                if( value != null ) {
                    String[] trueKey = ((String)key).split(",");
                    Map> tmp = mapping.get(trueKey[0]);
                    
                    if( tmp == null ) {
                        tmp =new HashMap>();
                        mapping.put(trueKey[0], tmp);
                    }
                    TreeSet m = new TreeSet();
                    String[] offerings = value.split(",");
                    
                    if( offerings == null || offerings.length < 1 ) {
                        m.add(value);
                    }
                    else {
                        Collections.addAll(m, offerings);
                    }
                    tmp.put(trueKey[1], m);
                }
            }
            customServiceMappings = mapping;
        }
        catch( Throwable ignore ) {
            // ignore
        }
    }
    
    private @Nonnull VirtualMachine launch22(@Nonnull String imageId, @Nonnull VirtualMachineProduct product, @Nullable String inZoneId, @Nonnull String name, @Nullable String withKeypair, @Nullable String targetVlanId, @Nullable String[] protectedByFirewalls, @Nullable String userData) throws InternalException, CloudException {
        ProviderContext ctx = getContext();
        List vlans = null;

        if( ctx == null ) {
            throw new InternalException("No context was provided for this request");
        }
        String regionId = ctx.getRegionId();

        if( inZoneId == null || inZoneId.isEmpty() ) {
            inZoneId = regionId;
        }

        if( inZoneId == null || inZoneId.isEmpty() ) {
            throw new InternalException("No region is established for this request");
        }

       String prdId = product.getProviderProductId();

        if( customNetworkMappings == null ) {
            load();
        }
        if( customNetworkMappings != null ) {
            String cloudId = cloudMappings.getProperty(ctx.getCloud().getEndpoint());
            
            if( cloudId != null ) {
                Map map = customNetworkMappings.get(cloudId);
                
                if( map != null ) {
                    String id = map.get(prdId);
                    
                    if( id != null ) {
                        targetVlanId = id;
                    }
                }
            }
        }
        if( targetVlanId != null && targetVlanId.length() < 1 ) {
            targetVlanId = null;
        }
        if( userData == null ) {
            userData = "";
        }
        String securityGroupIds = null;

        if( protectedByFirewalls != null && protectedByFirewalls.length > 0 ) {
            StringBuilder str = new StringBuilder();
            int idx = 0;
            
            for( String fw : protectedByFirewalls ) {
                fw = fw.trim();
                if( !fw.equals("") ) {
                    str.append(fw);
                    if( (idx++) < protectedByFirewalls.length-1 ) {
                        str.append(",");
                    }
                }
            }
            securityGroupIds = str.toString();
        }
        if( targetVlanId == null ) {
            Network vlan = getProvider().getNetworkServices().getVlanSupport();
            
            if( vlan != null && vlan.isSubscribed() ) {
                if( getCapabilities().identifyVlanRequirement().equals(Requirement.REQUIRED) ) {
                    vlans = vlan.findFreeNetworks();
                }
            }
        }
        else {
            vlans = new ArrayList();
            vlans.add(targetVlanId);
        }
        if( securityGroupIds != null && securityGroupIds.length() > 0 ) {
            // TODO: shouldn't we throw OpNotSupported if firewalls aren't supported but still requested?
            // otherwise it's like a confusion, no?
            if (!getProvider().getDataCenterServices().supportsSecurityGroups(regionId, vlans == null || vlans.size() < 1)) {
                securityGroupIds = null;
            }
            else {
                if( !getProvider().getServiceProvider().equals(CSServiceProvider.DATAPIPE) ) {
                    securityGroupIds = null;
                }
            }
        }
        else if( getProvider().getDataCenterServices().supportsSecurityGroups(regionId, vlans == null || vlans.size() < 1) ) {
            /*
            String sgId = null;
            
            if( withVlanId == null ) {
                Collection firewalls = getProvider().getNetworkServices().getFirewallSupport().list();
                
                for( Firewall fw : firewalls ) {
                    if( fw.getName().equalsIgnoreCase("default") && fw.getProviderVlanId() == null ) {
                        sgId = fw.getProviderFirewallId();
                        break;
                    }
                }
                if( sgId == null ) {
                    try {
                        sgId = getProvider().getNetworkServices().getFirewallSupport().create("default", "Default security group");
                    }
                    catch( Throwable t ) {
                        logger.warn("Unable to create a default security group, gonna try anyways: " + t.getMessage());
                    }
                }
                if( sgId != null ) {
                    securityGroupIds = sgId;
                }
            }
            else {
                Collection firewalls = getProvider().getNetworkServices().getFirewallSupport().list();
                
                for( Firewall fw : firewalls ) {
                    if( (fw.getName().equalsIgnoreCase("default") || fw.getName().equalsIgnoreCase("default-" + withVlanId)) && withVlanId.equals(fw.getProviderVlanId()) ) {
                        sgId = fw.getProviderFirewallId();
                        break;
                    }
                }
                if( sgId == null ) {
                    try {
                        sgId = getProvider().getNetworkServices().getFirewallSupport().createInVLAN("default-" + withVlanId, "Default " + withVlanId + " security group", withVlanId);
                    }
                    catch( Throwable t ) {
                        logger.warn("Unable to create a default security group, gonna try anyways: " + t.getMessage());
                    }
                }
            }
            if( sgId != null ) {
                securityGroupIds = sgId;
                count++;
            }    
            */            
        }
        List params = new ArrayList();

        params.add(new Param("zoneId", inZoneId));
        params.add(new Param("serviceOfferingId", prdId));
        params.add(new Param("templateId", imageId));
        params.add(new Param("displayName", name));
        if( userData != null && userData.length() > 0 ) {
            try {
                params.add(new Param("userdata", new String(Base64.encodeBase64(userData.getBytes("utf-8")), "utf-8")));
            }
            catch( UnsupportedEncodingException e ) {
//                e.printStackTrace();
            }
        }
        if( withKeypair != null ) {
            params.add(new Param("keypair", withKeypair));
        }
        if( securityGroupIds != null && securityGroupIds.length() > 0 ) {
            params.add(new Param("securitygroupids", securityGroupIds));
        }
        if( vlans != null && vlans.size() > 0 ) {
            CloudException lastError = null;

            for( String withVlanId : vlans ) {
                params.add(new Param("networkIds", withVlanId));

                try {
                    CSMethod method = new CSMethod(getProvider());

                    return launch(method.get(method.buildUrl(DEPLOY_VIRTUAL_MACHINE, params.toArray(new Param[params.size()])), DEPLOY_VIRTUAL_MACHINE));
                }
                catch( CloudException e ) {
                    if( e.getMessage().contains("sufficient address capacity") ) {
                        lastError = e;
                        continue;
                    }
                    throw e;
                }
            }
            if( lastError == null ) {
                throw lastError;
            }
            throw new CloudException("Unable to identify a network into which a VM can be launched");
        }
        else {
            CSMethod method = new CSMethod(getProvider());

            return launch(method.get(method.buildUrl(DEPLOY_VIRTUAL_MACHINE, params.toArray(new Param[params.size()])), DEPLOY_VIRTUAL_MACHINE));
        }
    }
    
    private @Nonnull VirtualMachine launch(@Nonnull Document doc) throws InternalException, CloudException {
        NodeList matches = doc.getElementsByTagName("deployvirtualmachineresponse");
        String serverId = null;
        String jobId = null;
        
        for( int i=0; i 0) {
                Node virtualMachine = nodeList.item(0);
                vm = toVirtualMachine(virtualMachine);
                if( vm != null ) {
                    return vm;
                }
            }
        }
        
        if (vm == null){
        	vm = getVirtualMachine(serverId);
        }
        if( vm == null ) {
            throw new CloudException("No virtual machine provided: " + serverId);
        }
        return vm;
    }

    @Override
    public @Nonnull Iterable listFirewalls(@Nonnull String vmId) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.listFirewalls");
        try {
            SecurityGroup support = getProvider().getNetworkServices().getFirewallSupport();

            if( support == null ) {
                return Collections.emptyList();
            }
            return support.listFirewallsForVM(vmId);
        }
        finally {
            APITrace.end();
        }
    }

    private void setFirewalls(@Nonnull VirtualMachine vm) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.setFirewalls");
        try {
            SecurityGroup support = getProvider().getNetworkServices().getFirewallSupport();

            if( support == null ) {
                return;
            }
            ArrayList ids = new ArrayList();

            for( String id : support.listFirewallsForVM(vm.getProviderVirtualMachineId()) ) {
                ids.add(id);
            }
            vm.setProviderFirewallIds(ids.toArray(new String[ids.size()]));
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public Iterable listProducts(VirtualMachineProductFilterOptions options, Architecture architecture) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.listProducts");
        try {
            ProviderContext ctx = getContext();

            if( ctx == null ) {
                throw new CloudException("No context was configured for this request");
            }

            Cache cache = Cache.getInstance(getProvider(), "ServerProducts", VirtualMachineProduct.class, CacheLevel.REGION_ACCOUNT, new TimePeriod(4, TimePeriod.HOUR));
            Collection products = (Collection)cache.get(getContext());
            if(products == null){
                Set mapping = null;

                if( customServiceMappings == null ) {
                    load();
                }
                if( customServiceMappings != null ) {
                    String cloudId = cloudMappings.getProperty(getContext().getCloud().getEndpoint());

                    if( cloudId != null ) {
                        Map> map = customServiceMappings.get(cloudId);

                        if( map != null ) {
                            mapping = map.get(getContext().getRegionId());
                        }
                    }
                }
                products = new ArrayList();

                CSMethod method = new CSMethod(getProvider());
                Document doc = method.get(method.buildUrl(LIST_SERVICE_OFFERINGS, new Param("zoneId", ctx.getRegionId())), LIST_SERVICE_OFFERINGS);
                NodeList matches = doc.getElementsByTagName("serviceoffering");

                for( int i=0; i 0 ) {
                            value = n.getFirstChild().getNodeValue();
                        }
                        else {
                            value = null;
                        }
                        if( n.getNodeName().equals("id") ) {
                            id = value;
                        }
                        else if( n.getNodeName().equals("name") ) {
                            name = value;
                        }
                        else if( n.getNodeName().equals("cpunumber") ) {
                            cpu = Integer.parseInt(value);
                        }
                        else if( n.getNodeName().equals("memory") ) {
                            memory = Integer.parseInt(value);
                        }
                        else if( n.getNodeName().equals("iscustomized") ) {
                            customized = Boolean.valueOf(value);
                        }
                        if( id != null && name != null && cpu > 0 && memory > 0 && customized != null) {
                            break;
                        }
                    }
                    if( id != null  && name != null && cpu > 0 && memory > 0 && !customized) {
                        if( mapping == null || mapping.contains(id) ) {
                            VirtualMachineProduct product;

                            product = new VirtualMachineProduct();
                            product.setProviderProductId(id);
                            product.setName(name + " (" + cpu + " CPU/" + memory + "MB RAM)");
                            product.setDescription(name + " (" + cpu + " CPU/" + memory + "MB RAM)");
                            product.setRamSize(new Storage(memory, Storage.MEGABYTE));
                            product.setCpuCount(cpu);
                            product.setRootVolumeSize(new Storage(1, Storage.GIGABYTE));
                            if (options != null) {
                                if (options.matches(product)) {
                                    products.add(product);
                                }
                            }
                            else {
                                products.add(product);
                            }
                        }
                    }
                }
                cache.put(getContext(), products);
            }
            return products;
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public @Nonnull Iterable listVirtualMachineStatus() throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.listVirtualMachineStatus");
        try {
            ProviderContext ctx = getContext();

            if( ctx == null ) {
                throw new CloudException("No context was specified for this request");
            }
            CSMethod method = new CSMethod(getProvider());
            Document doc = method.get(method.buildUrl(LIST_VIRTUAL_MACHINES, new Param("zoneId", ctx.getRegionId())), LIST_VIRTUAL_MACHINES);
            ArrayList servers = new ArrayList();

            int numPages = 1;
            NodeList nodes = doc.getElementsByTagName("count");
            Node n = nodes.item(0);
            if (n != null) {
                String value = n.getFirstChild().getNodeValue().trim();
                int count = Integer.parseInt(value);
                numPages = count/500;
                int remainder = count % 500;
                if (remainder > 0) {
                    numPages++;
                }
            }

            for (int page = 1; page <= numPages; page++) {
                if (page > 1) {
                    String nextPage = String.valueOf(page);
                    doc = method.get(method.buildUrl(LIST_VIRTUAL_MACHINES, new Param("zoneId", ctx.getRegionId()), new Param("pagesize", "500"), new Param("page", nextPage)), LIST_VIRTUAL_MACHINES);
                }
                NodeList matches = doc.getElementsByTagName("virtualmachine");

                for( int i=0; i listVirtualMachines() throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.listVirtualMachines");
        try {
            ProviderContext ctx = getContext();

            if( ctx == null ) {
                throw new CloudException("No context was specified for this request");
            }
            CSMethod method = new CSMethod(getProvider());
            Document doc = method.get(method.buildUrl(LIST_VIRTUAL_MACHINES, new Param("zoneId", ctx.getRegionId())), LIST_VIRTUAL_MACHINES);
            ArrayList servers = new ArrayList();

            int numPages = 1;
            NodeList nodes = doc.getElementsByTagName("count");
            Node n = nodes.item(0);
            if (n != null) {
                String value = n.getFirstChild().getNodeValue().trim();
                int count = Integer.parseInt(value);
                numPages = count/500;
                int remainder = count % 500;
                if (remainder > 0) {
                    numPages++;
                }
            }

            for (int page = 1; page <= numPages; page++) {
                if (page > 1) {
                    String nextPage = String.valueOf(page);
                    doc = method.get(method.buildUrl(LIST_VIRTUAL_MACHINES, new Param("zoneId", ctx.getRegionId()), new Param("pagesize", "500"), new Param("page", nextPage)), LIST_VIRTUAL_MACHINES);
                }
                NodeList matches = doc.getElementsByTagName("virtualmachine");

                for( int i=0; i 0 ) {
                                value = attribute.getFirstChild().getNodeValue();
                            }
                            else {
                                value = null;
                            }
                            if( name.equals("password") ) {
                                return value;
                            }
                        }
                    }
                }
            }


            logger.warn("Unable to find password for vm with id "+serverId);
            return null;
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public void reboot(@Nonnull String serverId) throws CloudException, InternalException {
        APITrace.begin(getProvider(), "VM.reboot");
        try {
            CSMethod method = new CSMethod(getProvider());
        
            method.get(method.buildUrl(REBOOT_VIRTUAL_MACHINE, new Param("id", serverId)), REBOOT_VIRTUAL_MACHINE);
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public void start(@Nonnull String serverId) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.start");
        try {
            CSMethod method = new CSMethod(getProvider());

            method.get(method.buildUrl(START_VIRTUAL_MACHINE, new Param("id", serverId)), START_VIRTUAL_MACHINE);
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public void stop(@Nonnull String vmId, boolean force) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.stop");
        try {
            CSMethod method = new CSMethod(getProvider());

            method.get(method.buildUrl(STOP_VIRTUAL_MACHINE, new Param("id", vmId), new Param("forced", String.valueOf(force))), STOP_VIRTUAL_MACHINE);
        }
        finally {
            APITrace.end();
        }
    }

    @Override
    public void terminate(@Nonnull String serverId, @Nullable String explanation) throws InternalException, CloudException {
        APITrace.begin(getProvider(), "VM.terminate");
        try {
            CSMethod method = new CSMethod(getProvider());
            List params = new ArrayList();
            params.add(new Param("id", serverId));
            if( getProvider().isAdminAccount() ) {
                params.add(new Param("expunge", "true"));
            }
            method.get(method.buildUrl(DESTROY_VIRTUAL_MACHINE, params), DESTROY_VIRTUAL_MACHINE);
        }
        finally {
            APITrace.end();
        }
    }

    private @Nullable ResourceStatus toStatus(@Nullable Node node) throws CloudException, InternalException {
        if( node == null ) {
            return null;
        }
        NodeList attributes = node.getChildNodes();
        VmState state = null;
        String serverId = null;

        for( int i=0; i 0 ) {
                value = attribute.getFirstChild().getNodeValue();
            }
            else {
                value = null;
            }
            if( name.equals("virtualmachineid") || name.equals("id") ) {
                serverId = value;
            }
            else if( name.equals("state") ) {
                if( value == null ) {
                    state = VmState.PENDING;
                }
                else if( value.equalsIgnoreCase("stopped") ) {
                    state = VmState.STOPPED;
                }
                else if( value.equalsIgnoreCase("running") ) {
                    state = VmState.RUNNING;
                }
                else if( value.equalsIgnoreCase("stopping") ) {
                    state = VmState.STOPPING;
                }
                else if( value.equalsIgnoreCase("starting") ) {
                    state = VmState.PENDING;
                }
                else if( value.equalsIgnoreCase("creating") ) {
                    state = VmState.PENDING;
                }
                else if( value.equalsIgnoreCase("migrating") ) {
                    state = VmState.REBOOTING;
                }
                else if( value.equalsIgnoreCase("destroyed") ) {
                    state = VmState.TERMINATED;
                }
                else if( value.equalsIgnoreCase("error") ) {
                    logger.warn("VM is in an error state.");
                    return null;
                }
                else if( value.equalsIgnoreCase("expunging") ) {
                    state = VmState.TERMINATED;
                }
                else if( value.equalsIgnoreCase("ha") ) {
                    state = VmState.REBOOTING;
                }
                else {
                    throw new CloudException("Unexpected server state: " + value);
                }
            }
            if( serverId != null && state != null ) {
                break;
            }
        }
        if( serverId == null ) {
            return null;
        }
        if( state == null ) {
            state = VmState.PENDING;
        }
        return new ResourceStatus(serverId, state);
    }

    private @Nullable VirtualMachine toVirtualMachine(@Nullable Node node) throws CloudException, InternalException {
        if( node == null ) {
            return null;
        }
        HashMap properties = new HashMap();
        VirtualMachine server = new VirtualMachine();
        NodeList attributes = node.getChildNodes();
        String productId = null;
        
        server.setProviderOwnerId(getContext().getAccountNumber());
        server.setClonable(false);
        server.setImagable(false);
        server.setPausable(true);
        server.setPersistent(true);
        server.setArchitecture(Architecture.I64);
        for( int i=0; i 0 ) {
                value = attribute.getFirstChild().getNodeValue();                
            }
            else {
                value = null;
            }
            if( name.equals("virtualmachineid") || name.equals("id") ) {
                server.setProviderVirtualMachineId(value);                
            }
            else if( name.equals("name") ) {
                server.setDescription(value);
            }
            /*
            else if( name.equals("haenable") ) {
                server.setPersistent(value != null && value.equalsIgnoreCase("true"));
            }
            */
            else if( name.equals("displayname") ) {
                server.setName(value);
            }
            else if( name.equals("ipaddress") ) { // v2.1
                if( value != null ) {
                    server.setPrivateAddresses(new RawAddress(value));
                }
                server.setPrivateDnsAddress(value);
            }
            else if( name.equals("password") ) {
                server.setRootPassword(value);
            }
            else if( name.equals("nic") ) { // v2.2
                if( attribute.hasChildNodes() ) {                    
                    NodeList parts = attribute.getChildNodes();
                    String addr = null;
                    
                    for( int j=0; j 31 ) {
                                            pub = true;
                                        }
                                    }
                                    catch( NumberFormatException ignore ) {
                                        // ignore
                                    }
                                }
                            }
                            else {
                                pub = true;
                            }
                        }
                        if( pub ) {
                            server.setPublicAddresses(new RawAddress(addr));
                            if( server.getPublicDnsAddress() == null ) {
                                server.setPublicDnsAddress(addr);
                            }
                        }
                        else {
                            server.setPrivateAddresses(new RawAddress(addr));
                            if( server.getPrivateDnsAddress() == null ) {
                                server.setPrivateDnsAddress(addr);
                            }
                        }
                    }
                }
            }
            else if( name.equals("osarchitecture") ) {
                if( value != null && value.equals("32") ) {
                    server.setArchitecture(Architecture.I32);
                }
                else {
                    server.setArchitecture(Architecture.I64);                  
                }
            }
            else if( name.equals("created") ) {
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); //2009-02-03T05:26:32.612278
                
                try {
                    server.setCreationTimestamp(df.parse(value).getTime());
                }
                catch( ParseException e ) {
                    logger.warn("Invalid date: " + value);
                    server.setLastBootTimestamp(0L);
                }
            }
            else if( name.equals("state") ) {
                VmState state;

                //(Running, Stopped, Stopping, Starting, Creating, Migrating, HA).
                if( value.equalsIgnoreCase("stopped") ) {
                    state = VmState.STOPPED;
                    server.setImagable(true);
                }
                else if( value.equalsIgnoreCase("running") ) {
                    state = VmState.RUNNING;
                }
                else if( value.equalsIgnoreCase("stopping") ) {
                    state = VmState.STOPPING;
                }
                else if( value.equalsIgnoreCase("starting") ) {
                    state = VmState.PENDING;
                }
                else if( value.equalsIgnoreCase("creating") ) {
                    state = VmState.PENDING;
                }
                else if( value.equalsIgnoreCase("migrating") ) {
                    state = VmState.REBOOTING;
                }
                else if( value.equalsIgnoreCase("destroyed") ) {
                    state = VmState.TERMINATED;
                }
                else if( value.equalsIgnoreCase("error") ) {
                    state = VmState.ERROR;
                }
                else if( value.equalsIgnoreCase("expunging") ) {
                    state = VmState.TERMINATED;
                }
                else if( value.equalsIgnoreCase("ha") ) {
                    state = VmState.REBOOTING;
                }
                else {
                    throw new CloudException("Unexpected server state: " + value);
                }
                server.setCurrentState(state);                
            }
            else if( name.equals("zoneid") ) {
                server.setProviderRegionId(value);
                server.setProviderDataCenterId(value);
            }
            else if( name.equals("templateid") ) {
                server.setProviderMachineImageId(value);
            }
            else if( name.equals("templatename") ) {
                server.setPlatform(Platform.guess(value));
            }
            else if( name.equals("serviceofferingid") ) {
                productId = value;
            }
            else if( value != null ) {
                properties.put(name, value);
            }
        }
        if( server.getName() == null ) {
            server.setName(server.getProviderVirtualMachineId());
        }
        if( server.getDescription() == null ) {
            server.setDescription(server.getName());
        }
        server.setProviderAssignedIpAddressId(null);
        if( server.getProviderRegionId() == null ) {
            server.setProviderRegionId(getContext().getRegionId());
        }
        if( server.getProviderDataCenterId() == null ) {
            server.setProviderDataCenterId(getContext().getRegionId());
        }
        if( productId != null ) {
            server.setProductId(productId);
        }

        /*final String finalServerId = server.getProviderVirtualMachineId();
        // commenting out for now until we can find a way to return plain text rather than encrypted
            server.setPasswordCallback(new Callable() {
            @Override
            public String call() throws Exception {
                return getRootPassword(finalServerId);
            }
        }
        );  */
        server.setTags(properties);
        return server;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy