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

org.dasein.cloud.rackspace.compute.CloudServers Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2009-2012 enStratus Networks 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.rackspace.compute;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.dasein.cloud.CloudErrorType;
import org.dasein.cloud.CloudException;
import org.dasein.cloud.InternalException;
import org.dasein.cloud.OperationNotSupportedException;
import org.dasein.cloud.ProviderContext;
import org.dasein.cloud.Requirement;
import org.dasein.cloud.ResourceStatus;
import org.dasein.cloud.Tag;
import org.dasein.cloud.compute.Architecture;
import org.dasein.cloud.compute.ImageClass;
import org.dasein.cloud.compute.MachineImage;
import org.dasein.cloud.compute.Platform;
import org.dasein.cloud.compute.VMLaunchOptions;
import org.dasein.cloud.compute.VMScalingCapabilities;
import org.dasein.cloud.compute.VMScalingOptions;
import org.dasein.cloud.compute.VirtualMachine;
import org.dasein.cloud.compute.VirtualMachineProduct;
import org.dasein.cloud.compute.VirtualMachineSupport;
import org.dasein.cloud.compute.VmState;
import org.dasein.cloud.compute.VmStatistics;
import org.dasein.cloud.dc.DataCenter;
import org.dasein.cloud.identity.ServiceAction;
import org.dasein.cloud.rackspace.RackspaceCloud;
import org.dasein.cloud.rackspace.RackspaceException;
import org.dasein.cloud.rackspace.RackspaceMethod;
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.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


public class CloudServers implements VirtualMachineSupport {
    static private HashMap> cachedProducts = new HashMap>();
    
    static public final int NAME_LIMIT = 30;
    static public final int TAG_LIMIT  = 4;
    
    private RackspaceCloud provider;
    
    CloudServers(@Nonnull RackspaceCloud provider) { this.provider = provider; }

    @Override
    public VirtualMachine alterVirtualMachine(@Nonnull String vmId, @Nonnull VMScalingOptions options) throws InternalException, CloudException {
        throw new OperationNotSupportedException("Not supported");
    }

    @Override
    public @Nonnull VirtualMachine clone(@Nonnull String vmId, @Nullable String intoDcId, @Nonnull String name, @Nonnull String description, boolean powerOn, @Nullable String... firewallIds) throws InternalException, CloudException {
        throw new OperationNotSupportedException("Rackspace foes not support the cloning of servers.");
    }

    @Override
    public VMScalingCapabilities describeVerticalScalingCapabilities() throws CloudException, InternalException {
        return null;
    }

    @Override
    public void disableAnalytics(@Nonnull String vmId) throws InternalException, CloudException {
        // NO-OP
    }

    @Override
    public void enableAnalytics(@Nonnull String vmId) throws InternalException, CloudException {
        // NO-OP
    }

    @Override
    public @Nonnull String getConsoleOutput(@Nonnull String vmId) throws InternalException, CloudException {
        return "";
    }

    @Override
    public int getCostFactor(@Nonnull VmState state) throws InternalException, CloudException {
        return 100;
    }

    @Override
    public int getMaximumVirtualMachineCount() throws CloudException, InternalException {
        return -2;
    }

    @Override
    public @Nullable VirtualMachineProduct getProduct(@Nonnull String productId) throws InternalException, CloudException {
        Logger std = RackspaceCloud.getLogger(CloudServers.class, "std");
        
        if( std.isTraceEnabled() ) {
            std.trace("enter - " + CloudServers.class.getName() + ".getProduct(" + productId + ")");
        }
        try {
            if( !provider.isMyRegion() ) {
                return null;
            }
            for( VirtualMachineProduct product : listProducts(Architecture.I64) ) {
                if( product.getProviderProductId().equals(productId) ) {
                    return product;
                }
            }
            return null;
        }
        finally {
            if( std.isTraceEnabled() ) {
                std.trace("exit - " + CloudServers.class.getName() + ".getProduct()");
            }
        }
    }

    @Override
    public @Nonnull String getProviderTermForServer(@Nonnull Locale locale) {
        return "server";
    }

    @Override
    public @Nullable VirtualMachine getVirtualMachine(@Nonnull String vmId) throws InternalException, CloudException {
        Logger std = RackspaceCloud.getLogger(CloudServers.class, "std");
        
        if( std.isTraceEnabled() ) {
            std.trace("enter - " + CloudServers.class.getName() + ".getVirtualMachine(" + vmId + ")");
        }
        try {
            /*
            if( !provider.isMyRegion() ) {
                return null;
            }
            */
            RackspaceMethod method = new RackspaceMethod(provider);
            JSONObject ob = method.getServers("/servers", vmId);

            if( ob == null ) {
                return null;
            }
            try {
                if( ob.has("server") ) {
                    JSONObject server = ob.getJSONObject("server");
                    VirtualMachine vm = toVirtualMachine(server);
                        
                    if( vm != null ) {
                        return vm;
                    }
                }
            }
            catch( JSONException e ) {
                std.error("getVirtualMachine(): Unable to identify expected values in JSON: " + e.getMessage());
                throw new CloudException(CloudErrorType.COMMUNICATION, 200, "invalidJson", "Missing JSON element for servers");
            }
            return null;
        }
        finally {
            if( std.isTraceEnabled() ) {
                std.trace("exit - " + CloudServers.class.getName() + ".getVirtualMachine()");
            }
        }
    }

    @Override
    public @Nullable VmStatistics getVMStatistics(@Nonnull String vmId, long from, long to) throws InternalException, CloudException {
        return null;
    }

    @Override
    public @Nonnull Iterable getVMStatisticsForPeriod(@Nonnull String vmId, long from, long to) throws InternalException, CloudException {
        return Collections.emptyList();
    }

    @Nonnull
    @Override
    public Requirement identifyImageRequirement(@Nonnull ImageClass cls) throws CloudException, InternalException {
        return (cls.equals(ImageClass.MACHINE) ? Requirement.REQUIRED : Requirement.NONE);
    }

    @Override
    public @Nonnull Requirement identifyPasswordRequirement() throws CloudException, InternalException {
        return Requirement.NONE;
    }

    @Nonnull
    @Override
    public Requirement identifyPasswordRequirement(Platform platform) throws CloudException, InternalException {
        return Requirement.NONE;
    }

    @Override
    public @Nonnull Requirement identifyRootVolumeRequirement() throws CloudException, InternalException {
        return Requirement.NONE;
    }

    @Override
    public @Nonnull Requirement identifyShellKeyRequirement() throws CloudException, InternalException {
        return Requirement.NONE;
    }

    @Nonnull
    @Override
    public Requirement identifyShellKeyRequirement(Platform platform) throws CloudException, InternalException {
        return Requirement.NONE;
    }

    @Nonnull
    @Override
    public Requirement identifyStaticIPRequirement() throws CloudException, InternalException {
        return Requirement.NONE;
    }

    @Override
    public @Nonnull Requirement identifyVlanRequirement() throws CloudException, InternalException {
        return Requirement.NONE;
    }

    @Override
    public boolean isAPITerminationPreventable() throws CloudException, InternalException {
        return false;
    }

    @Override
    public boolean isBasicAnalyticsSupported() throws CloudException, InternalException {
        return false;
    }

    @Override
    public boolean isExtendedAnalyticsSupported() throws CloudException, InternalException {
        return false;
    }

    @Override
    public boolean isSubscribed() throws CloudException, InternalException {
        return (provider.isMyRegion() && provider.testContext() != null);
    }

    @Override
    public boolean isUserDataSupported() throws CloudException, InternalException {
        return false;
    }

    @Override
    public @Nonnull VirtualMachine launch(@Nonnull VMLaunchOptions withLaunchOptions) throws CloudException, InternalException {
        Logger logger = RackspaceCloud.getLogger(CloudServers.class, "std");

        if( logger.isTraceEnabled() ) {
            logger.trace("enter - " + CloudServers.class.getName() + ".launch(" + withLaunchOptions + ")");
        }
        try {
            if( !provider.isMyRegion() ) {
                throw new CloudException("Unable to launch any servers in " + provider.getContext().getRegionId());
            }
            String fromMachineImageId = withLaunchOptions.getMachineImageId();
            String productId = withLaunchOptions.getStandardProductId();
            Map meta = withLaunchOptions.getMetaData();

            MachineImage targetImage = provider.getComputeServices().getImageSupport().getImage(fromMachineImageId);
            HashMap wrapper = new HashMap();
            HashMap json = new HashMap();

            json.put("imageId", Long.parseLong(fromMachineImageId));
            json.put("flavorId", Long.parseLong(productId));
            HashMap metaData = new HashMap();
            boolean safeName = false;
            int tagCount = 0;

            if( meta != null ) {
                for( Map.Entry tag : meta.entrySet() ) {
                    if( tag.getKey() != null && tag.getValue() != null && tag.getKey().length() > 0 && tag.getValue().toString().length() > 0 ) {
                        metaData.put(tag.getKey(), tag.getValue());
                        tagCount++;
                        if( tagCount >= TAG_LIMIT ) {
                            break;
                        }
                    }
                }
            }
            if( tagCount < TAG_LIMIT && !targetImage.getPlatform().equals(Platform.UNKNOWN) ) {
                metaData.put("dsnPlatform", targetImage.getPlatform().name());
                tagCount++;
            }
            if( tagCount < TAG_LIMIT ) {
                metaData.put("dsnDescription", withLaunchOptions.getDescription());
                tagCount++;
            }
            if( tagCount < TAG_LIMIT ) {
                metaData.put("dsnName", withLaunchOptions.getFriendlyName());
                safeName = true;
            }
            metaData.put("dsnTrueImage", targetImage.getProviderMachineImageId());
            json.put("metadata", metaData);
            json.put("name", validateName(withLaunchOptions.getHostName(), safeName));

            wrapper.put("server", json);
            RackspaceMethod method = new RackspaceMethod(provider);
            JSONObject result = method.postServers("/servers", null, new JSONObject(wrapper));

            if( result.has("server") ) {
                try {
                    JSONObject server = result.getJSONObject("server");
                    VirtualMachine vm = toVirtualMachine(server);

                    if( vm != null ) {
                        return vm;
                    }
                }
                catch( JSONException e ) {
                    logger.error("launch(): Unable to understand launch response: " + e.getMessage());
                    if( logger.isTraceEnabled() ) {
                        e.printStackTrace();
                    }
                    throw new CloudException(e);
                }
            }
            logger.error("launch(): No server was created by the launch attempt, and no error was returned");
            throw new CloudException("No virtual machine was launched");

        }
        finally {
            if( logger.isTraceEnabled() ) {
                logger.trace("exit - " + CloudServers.class.getName() + ".launch()");
            }
        }
    }

    @Override
    public @Nonnull VirtualMachine launch(@Nonnull String fromMachineImageId, @Nonnull VirtualMachineProduct product, @Nullable String dataCenterId, @Nonnull String name, @Nonnull String description, @Nullable String withKeypairId, @Nullable String inVlanId, boolean withAnalytics, boolean asSandbox, @Nullable String... firewallIds) throws InternalException, CloudException {
        return launch(fromMachineImageId, product, dataCenterId, name, description, withKeypairId, inVlanId, withAnalytics, asSandbox, firewallIds, new Tag[0]);
    }

    @Override
    public @Nonnull VirtualMachine launch(@Nonnull String fromMachineImageId, @Nonnull VirtualMachineProduct product, @Nullable String dataCenterId, @Nonnull String name, @Nonnull String description, @Nullable String withKeypairId, @Nullable String inVlanId, boolean withAnalytics, boolean asSandbox, @Nullable String[] firewallIds, @Nullable Tag... tags) throws InternalException, CloudException {
        ProviderContext ctx = provider.getContext();

        if( ctx == null ) {
            throw new CloudException("No context was provided for this request");
        }
        //noinspection ConstantConditions
        if( description == null ) {
            description = name;
        }
        if( dataCenterId == null ) {
            for( DataCenter dc : provider.getDataCenterServices().listDataCenters(ctx.getRegionId()) ) {
                if( dc != null ) {
                    dataCenterId = dc.getProviderDataCenterId();
                    break;
                }
            }
        }
        VMLaunchOptions options;

        if( inVlanId == null ) {
            //noinspection ConstantConditions
            options = VMLaunchOptions.getInstance(product.getProviderProductId(), fromMachineImageId, name, description).inDataCenter(dataCenterId);
        }
        else {
            //noinspection ConstantConditions
            options = VMLaunchOptions.getInstance(product.getProviderProductId(), fromMachineImageId, name, description).inVlan(null, dataCenterId, inVlanId);
        }
        if( withKeypairId != null ) {
            options = options.withBoostrapKey(withKeypairId);
        }
        if( tags != null ) {
            for( Tag t : tags ) {
                options = options.withMetaData(t.getKey(), t.getValue());
            }
        }
        if( firewallIds != null ) {
            options = options.behindFirewalls(firewallIds);
        }
        return launch(options);
    }

    @Override
    public @Nonnull Iterable listFirewalls(@Nonnull String vmId) throws InternalException, CloudException {
        return Collections.emptyList();
    }

    @Override
    public @Nonnull Iterable listProducts(@Nonnull Architecture architecture) throws InternalException, CloudException {
       Logger std = RackspaceCloud.getLogger(CloudServers.class, "std");
        
        if( std.isTraceEnabled() ) {
            std.trace("enter - " + CloudServers.class.getName() + ".listProducts()");
        }
        try {
            if( !provider.isMyRegion() ) {
                return Collections.emptyList();
            }
            if( architecture.equals(Architecture.I32) ) {
                return Collections.emptyList();
            }
            Collection products = cachedProducts.get(provider.getContext().getRegionId());
            
            if( products == null ) {
                if( std.isDebugEnabled() ) {
                    std.debug("listProducts(): Cache for " + provider.getContext().getRegionId() + " is empty, fetching values from cloud");
                }
                RackspaceMethod method = new RackspaceMethod(provider);
                JSONObject ob = method.getServers("/flavors", null);
                
                products = new ArrayList();
                try {
                    if( ob.has("flavors") ) {
                        JSONArray list = ob.getJSONArray("flavors");
                        
                        for( int i=0; i architectures;

    @Override
    public Iterable listSupportedArchitectures() throws InternalException, CloudException {
        if( architectures == null ) {
            ArrayList tmp = new ArrayList();

            tmp.add(Architecture.I32);
            tmp.add(Architecture.I64);
            architectures = Collections.unmodifiableList(tmp);
        }
        return architectures;
    }

    @Nonnull
    @Override
    public Iterable listVirtualMachineStatus() throws InternalException, CloudException {
        ArrayList status = new ArrayList();

        for( VirtualMachine vm : listVirtualMachines() ) {
            status.add(new ResourceStatus(vm.getProviderVirtualMachineId(), vm.getCurrentState()));
        }
        return status;
    }

    @Override
    public @Nonnull Iterable listVirtualMachines() throws InternalException, CloudException {
        Logger std = RackspaceCloud.getLogger(CloudServers.class, "std");
        
        if( std.isTraceEnabled() ) {
            std.trace("enter - " + CloudServers.class.getName() + ".listVirtualMachines()");
        }
        try {
            if( !provider.isMyRegion() ) {
                return Collections.emptyList();
            }
            RackspaceMethod method = new RackspaceMethod(provider);
            JSONObject ob = method.getServers("/servers", null);
            ArrayList servers = new ArrayList();
            
            try {
                if( ob.has("servers") ) {
                    JSONArray list = ob.getJSONArray("servers");
                    
                    for( int i=0; i json = new HashMap();
            HashMap action = new HashMap();
            
            action.put("type", "HARD");
            json.put("reboot", action);

            RackspaceMethod method = new RackspaceMethod(provider);
            
            method.postServers("/servers", vmId, new JSONObject(json));
        }
        finally {
            if( logger.isTraceEnabled() ) {
                logger.trace("exit - " + CloudServers.class.getName() + ".reboot()");
            }            
        }
    }

    @Override
    public void resume(@Nonnull String vmId) throws CloudException, InternalException {
        throw new OperationNotSupportedException("Rackspace does not support suspend/resume of servers.");
    }

    @Override
    public void start(@Nonnull String vmId) throws InternalException, CloudException {
        throw new OperationNotSupportedException("Rackspace does not support start/stop of servers.");
    }

    @Override
    public void stop(@Nonnull String vmId) throws InternalException, CloudException {
        stop(vmId, false);
    }

    @Override
    public void stop(@Nonnull String vmId, boolean force) throws InternalException, CloudException {
        throw new OperationNotSupportedException("Rackspace does not support start/stop of servers");
    }

    @Override
    public boolean supportsAnalytics() throws CloudException, InternalException {
        return false;
    }

    @Override
    public boolean supportsPauseUnpause(@Nonnull VirtualMachine vm) {
        return false;
    }

    @Override
    public boolean supportsStartStop(@Nonnull VirtualMachine vm) {
        return false;
    }

    @Override
    public boolean supportsSuspendResume(@Nonnull VirtualMachine vm) {
        return false;
    }

    @Override
    public void suspend(@Nonnull String vmId) throws CloudException, InternalException {
        throw new OperationNotSupportedException("Rackspace does not support suspend/resume of servers.");
    }

    @Override
    public void terminate(@Nonnull String vmId) throws InternalException, CloudException {
        Logger std = RackspaceCloud.getLogger(CloudServers.class, "std");
        
        if( std.isTraceEnabled() ) {
            std.trace("enter - " + CloudServers.class.getName() + ".terminate(" + vmId + ")");
        }
        try {
            RackspaceMethod method = new RackspaceMethod(provider);
            long timeout = System.currentTimeMillis() + CalendarWrapper.HOUR;

            do {
                try {
                    method.deleteServers("/servers", vmId);
                    return;
                }
                catch( RackspaceException e ) {
                    if( e.getHttpCode() != HttpServletResponse.SC_CONFLICT ) {
                        throw e;
                    }
                }
                try { Thread.sleep(CalendarWrapper.MINUTE); }
                catch( InterruptedException e ) { /* ignore */ }
            } while( System.currentTimeMillis() < timeout );
        }
        finally {
            if( std.isTraceEnabled() ) {
                std.trace("exit - " + CloudServers.class.getName() + ".terminate()");
            }
        }
    }

    @Override
    public void unpause(@Nonnull String vmId) throws CloudException, InternalException {
        throw new OperationNotSupportedException("Rackspace does not support pause/unpause.");
    }

    @Override
    public void updateTags(@Nonnull String vmId, @Nonnull Tag... tags) throws CloudException, InternalException {
        // NO-OP
    }

    private @Nullable VirtualMachineProduct toProduct(@Nullable JSONObject json) throws JSONException, InternalException, CloudException {
        Logger std = RackspaceCloud.getLogger(CloudServers.class, "std");
        
        if( std.isTraceEnabled() ) {
            std.trace("enter - " + CloudServers.class.getName() + ".toProduct(" + json + ")");
        }
        try {
            if( json == null ) {
                return null;
            }
            VirtualMachineProduct product = new VirtualMachineProduct();
            
            if( json.has("id") ) {
                product.setProviderProductId(json.getString("id"));
            }
            if( json.has("name") ) {
                product.setName(json.getString("name"));
            }
            if( json.has("description") ) {
                product.setDescription(json.getString("description"));
            }
            if( json.has("ram") ) {
                product.setRamSize(new Storage(json.getInt("ram"), Storage.MEGABYTE));
            }
            if( json.has("disk") ) {
                product.setRootVolumeSize(new Storage(json.getInt("disk"), Storage.GIGABYTE));
            }
            product.setCpuCount(1);
            if( product.getProviderProductId() == null ) {
                return null;
            }
            if( product.getName() == null ) {
                product.setName(product.getProviderProductId());
            }
            if( product.getDescription() == null ) {
                product.setDescription(product.getName());
            }
            return product;
        }
        finally {
            if( std.isTraceEnabled() ) {
                std.trace("enter - " + CloudServers.class.getName() + ".toProduct()");
            }            
        }
    }
    
    private @Nullable VirtualMachine toVirtualMachine(@Nullable JSONObject server) throws JSONException, InternalException, CloudException {
        Logger std = RackspaceCloud.getLogger(CloudServers.class, "std");
        
        if( std.isTraceEnabled() ) {
            std.trace("enter - " + CloudServers.class.getName() + ".toVirtualMachine(" + server + ")");
        }
        try {
            if( server == null ) {
                return null;
            }
            VirtualMachine vm = new VirtualMachine();
            
            vm.setCurrentState(VmState.RUNNING);
            vm.setArchitecture(Architecture.I64);
            vm.setClonable(false);
            vm.setCreationTimestamp(-1L);
            vm.setImagable(false);
            vm.setLastBootTimestamp(-1L);
            vm.setLastPauseTimestamp(-1L);
            vm.setPausable(false);
            vm.setPersistent(true);
            vm.setPlatform(Platform.UNKNOWN);
            vm.setRebootable(true);
            vm.setProviderOwnerId(provider.getContext().getAccountNumber());
            if( server.has("id") ) {
                vm.setProviderVirtualMachineId(String.valueOf(server.getLong("id")));
            }
            if( server.has("name") ) {
                vm.setName(server.getString("name"));
            }
            if( server.has("description") ) {
                vm.setDescription(server.getString("description"));
            }
            if( server.has("imageId") ) {
                vm.setProviderMachineImageId(server.getString("imageId"));
            }
            if( vm.getDescription() == null ) {
                HashMap map = new HashMap();
                
                if( server.has("metadata") ) {
                    JSONObject md = server.getJSONObject("metadata");
                    
                    if( md.has("dsnDescription") ) {
                        vm.setDescription(md.getString("dsnDescription"));
                    }
                    else if( md.has("dsnTrueImage") ) { // this will override the nonsense Rackspace is sending us
                        String imageId = md.getString("dsnTrueImage");
                        
                        if( imageId != null && imageId.length() > 0 ) {
                            vm.setProviderMachineImageId(imageId);
                        }
                    }
                    else if( md.has("Server Label") ) {
                        vm.setDescription(md.getString("Server Label"));
                    }
                    if( md.has("dsnName") ) {
                        String str = md.getString("dsnName");
                        
                        if( str != null && str.length() > 0 ) {
                            vm.setName(str);
                        }
                    }
                    if( md.has("dsnPlatform") ) {
                        try {
                            vm.setPlatform(Platform.valueOf(md.getString("dsnPlatform")));
                        }
                        catch( Throwable ignore ) {
                            // ignore
                        }
                    }
                    String[] keys = JSONObject.getNames(md);
                    
                    if( keys != null ) {
                        for( String key : keys ) {
                            String value = md.getString(key);
                            
                            if( value != null ) {
                                map.put(key, value);
                            }
                        }
                    }
                }
                if( vm.getDescription() == null ) {
                    if( vm.getName() == null ) {
                        vm.setName(vm.getProviderVirtualMachineId());
                    }
                    vm.setDescription(vm.getName());
                }
                if( server.has("hostId") ) {
                    map.put("host", server.getString("hostId"));
                }
                vm.setTags(map);
            }
            if( server.has("flavorId") ) {
                vm.setProductId(server.getString("flavorId"));
            }
            if( server.has("adminPass") ) {
                vm.setRootPassword(server.getString("adminPass"));
            }
            if( server.has("status") ) {
                String s = server.getString("status").toLowerCase();
                
                if( s.equals("active") ) {
                    vm.setCurrentState(VmState.RUNNING);
                }
                else if( s.equals("building") || s.equals("build") ) {
                    vm.setCurrentState(VmState.PENDING);
                }
                else if( s.equals("deleted") ) {
                    vm.setCurrentState(VmState.TERMINATED);
                }
                else if( s.equals("suspended") ) {
                    vm.setCurrentState(VmState.SUSPENDED);
                }
                else if( s.equals("error") ) {
                    return null;
                }
                else if( s.equals("reboot") || s.equals("hard_reboot") ) {
                    vm.setCurrentState(VmState.REBOOTING);
                }
                else {
                    std.warn("toVirtualMachine(): Unknown server state: " + s);
                    vm.setCurrentState(VmState.PENDING);
                }
            }
            if( server.has("addresses") ) {
                JSONObject addrs = server.getJSONObject("addresses");
                
                if( addrs.has("public") ) {
                    JSONArray arr = addrs.getJSONArray("public");
                    String[] addresses = new String[arr.length()];
                    
                    for( int i=0; i= 'a' && c <= 'z' ) {
                if( last == '-' && !str.toString().endsWith("-") ) {
                    str.append('-');
                }
                str.append(c);
            }
            last = c;            
        }
        if( name.length() < 1 ) {
            name = "a";
        }
        String test = name;
        int idx = 1;
        
        while( serverExists(test) && idx<1000000 ) {
            test = name + "-" + (idx++);
        }
        return test;
    }
    
    private String validateName(String name, boolean safeName) throws InternalException, CloudException {
        if( safeName ) {
            name = name.toLowerCase().replaceAll(" ", "-");
        }
        if( name.length() > NAME_LIMIT ) {
            name = name.substring(0,NAME_LIMIT);
        }
        StringBuilder str = new StringBuilder();
        
        for( int i=0; i 0 || Character.isLetter(c) ) {
                        str.append(c);
                    }
                }
            }
            else {
                if( (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' ) {
                    if( str.length() > 0 || Character.isLetter(c) ) {
                        str.append(c);
                    }
                }
            }
        }
        if( str.length() < 1 ) {
            return makeUpName(name);
        }
        name = str.toString();
        while( !Character.isLetterOrDigit(name.charAt(name.length()-1)) ) {
            if( name.length() < 2 ) {
                return makeUpName(name);
            }
            name = name.substring(0, name.length()-1);
        }
        if( serverExists(name) ) {
            return makeUpName(name);
        }
        return name;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy