Repository: stratos
Updated Branches:
  refs/heads/4.0.0-cloudstack [created] ddf449670


Backporting cloudstack support to stratos 4.0.0


Project: http://git-wip-us.apache.org/repos/asf/stratos/repo
Commit: http://git-wip-us.apache.org/repos/asf/stratos/commit/ddf44967
Tree: http://git-wip-us.apache.org/repos/asf/stratos/tree/ddf44967
Diff: http://git-wip-us.apache.org/repos/asf/stratos/diff/ddf44967

Branch: refs/heads/4.0.0-cloudstack
Commit: ddf4496702d8115f17df1a03a675ed0292aa8f31
Parents: fcc90fc
Author: Imesh Gunaratne <[email protected]>
Authored: Thu Nov 13 17:34:00 2014 +0530
Committer: Imesh Gunaratne <[email protected]>
Committed: Thu Nov 13 17:34:00 2014 +0530

----------------------------------------------------------------------
 .../org.apache.stratos.cloud.controller/pom.xml |   5 +
 .../cloud/controller/iaases/CloudStackIaas.java | 542 +++++++++++++++++++
 .../util/CloudControllerConstants.java          |   6 +
 .../validate/CloudstackPartitionValidator.java  |  53 ++
 .../pom.xml                                     |   7 +-
 .../main/resources/conf/cloud-controller.xml    | 123 +++--
 6 files changed, 682 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/stratos/blob/ddf44967/components/org.apache.stratos.cloud.controller/pom.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/pom.xml 
b/components/org.apache.stratos.cloud.controller/pom.xml
index c551566..cb11ed0 100644
--- a/components/org.apache.stratos.cloud.controller/pom.xml
+++ b/components/org.apache.stratos.cloud.controller/pom.xml
@@ -184,6 +184,11 @@
                        <artifactId>jclouds-enterprise</artifactId>
                        <version>${jclouds.version}</version>
                </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.api</groupId>
+            <artifactId>cloudstack</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
                <dependency>
                        <groupId>org.apache.stratos</groupId>
                        <artifactId>ec2</artifactId>

http://git-wip-us.apache.org/repos/asf/stratos/blob/ddf44967/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/CloudStackIaas.java
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/CloudStackIaas.java
 
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/CloudStackIaas.java
new file mode 100644
index 0000000..ddffd1f
--- /dev/null
+++ 
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/CloudStackIaas.java
@@ -0,0 +1,542 @@
+package org.apache.stratos.cloud.controller.iaases;
+
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.exception.CloudControllerException;
+import org.apache.stratos.cloud.controller.exception.InvalidHostException;
+import org.apache.stratos.cloud.controller.exception.InvalidRegionException;
+import org.apache.stratos.cloud.controller.exception.InvalidZoneException;
+import org.apache.stratos.cloud.controller.interfaces.Iaas;
+import org.apache.stratos.cloud.controller.jcloud.ComputeServiceBuilderUtil;
+import org.apache.stratos.cloud.controller.pojo.IaasProvider;
+import org.apache.stratos.cloud.controller.util.CloudControllerConstants;
+import 
org.apache.stratos.cloud.controller.validate.CloudStackPartitionValidator;
+import 
org.apache.stratos.cloud.controller.validate.interfaces.PartitionValidator;
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
+import org.jclouds.cloudstack.domain.*;
+import org.jclouds.cloudstack.features.VolumeApi;
+import org.jclouds.cloudstack.options.ListPublicIPAddressesOptions;
+import org.jclouds.cloudstack.options.ListZonesOptions;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.Location;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeoutException;
+
+public class CloudStackIaas extends Iaas {
+
+    private static final Log log = LogFactory.getLog(CloudStackIaas.class);
+
+    public CloudStackIaas(IaasProvider iaasProvider) {
+        super(iaasProvider);
+    }
+
+    @Override
+    public void buildComputeServiceAndTemplate() {
+        // builds and sets Compute Service
+        
ComputeServiceBuilderUtil.buildDefaultComputeService(getIaasProvider());
+        // builds and sets Template
+        buildTemplate();
+    }
+
+    @Override
+    public void buildTemplate() {
+
+        IaasProvider iaasInfo = getIaasProvider();
+
+        //if compute service is not available
+        if (iaasInfo.getComputeService() == null) {
+            String msg = "Compute service is null for IaaS provider: "
+                    + iaasInfo.getName();
+            log.error(msg);
+            throw new CloudControllerException(msg);
+        }
+
+        //create templateBuilder
+        TemplateBuilder templateBuilder = iaasInfo.getComputeService()
+                .templateBuilder();
+
+        //**SET PROPERTIES TO templateBuilder OBJECT**//
+
+        /**
+         * PROPERTY - 1
+         * set image id specified
+         */
+        templateBuilder.imageId(iaasInfo.getImage());
+
+        /**
+         *  PROPERTY-2
+         *  if user has specified a zone in cloud-controller.xml, set the zone 
into templateBuilder object
+         *  (user should provide the zone id for this, because zone name is 
not unique in cloudstack)
+         */
+        if (iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) 
!= null) {
+            Set<? extends Location> locations = 
iaasInfo.getComputeService().listAssignableLocations();
+            for (Location location : locations) {
+                if 
(location.getId().equals(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE)))
 {
+                    //if the zone is valid set the zone to templateBuilder 
Object
+                    templateBuilder.locationId(location.getId());
+                    log.info("Zone has been set as " + 
iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE)
+                            + " with id: " + location.getId());
+                    break;
+                }
+            }
+        }
+
+        /**
+         * PROPERTY-3
+         * if user has specified an instance type in cloud-controller.xml, set 
the instance type into templateBuilder
+         * object.(service offering)
+         *Important:Specify the Service Offering type ID. Not the name. 
Because the name is not unique in cloudstack.
+         */
+        if (iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE) != 
null) {
+            
templateBuilder.hardwareId(iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE));
+        }
+
+        //build the template
+        Template template = templateBuilder.build();
+
+        /**if you wish to auto assign IPs, instance spawning call should be
+         * blocking, but if you
+         * wish to assign IPs manually, it can be non-blocking.
+         * is auto-assign-ip mode or manual-assign-ip mode?
+         */
+        boolean blockUntilRunning = Boolean.parseBoolean(iaasInfo
+                .getProperty(CloudControllerConstants.AUTO_ASSIGN_IP));
+        template.getOptions().as(TemplateOptions.class)
+                .blockUntilRunning(blockUntilRunning);
+
+        // this is required in order to avoid creation of additional security
+        // groups by Jclouds.
+        template.getOptions().as(TemplateOptions.class)
+                .inboundPorts(new int[]{});
+
+
+        //**SET CLOUDSTACK SPECIFIC PROPERTIES TO TEMPLATE OBJECT**//
+
+        //set security group - If you are using basic zone
+        if (iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUP_IDS) 
!= null) {
+            template.getOptions()
+                    .as(CloudStackTemplateOptions.class)
+                    
.securityGroupIds(Arrays.asList(iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUP_IDS)
+                            .split(CloudControllerConstants.ENTRY_SEPARATOR)));
+        }
+
+
+        /**
+         * set network ID - If you are using advanced zone
+         * in cloudstack sometimes we get unautorized exception if we didn't 
specify the
+         * domain ID and user name
+         */
+        if (iaasInfo.getProperty(CloudControllerConstants.NETWORK_IDS) != 
null) {
+            template.getOptions()
+                    .as(CloudStackTemplateOptions.class)
+                    
.networks(Arrays.asList(iaasInfo.getProperty(CloudControllerConstants.NETWORK_IDS)
+                            .split(CloudControllerConstants.ENTRY_SEPARATOR)));
+        }
+
+        //set user name
+        if (iaasInfo.getProperty(CloudControllerConstants.USER_NAME) != null) {
+            template.getOptions().as(CloudStackTemplateOptions.class)
+                    
.account(iaasInfo.getProperty(CloudControllerConstants.USER_NAME));
+        }
+        //set domain ID
+        if (iaasInfo.getProperty(CloudControllerConstants.DOMAIN_ID) != null) {
+            template.getOptions().as(CloudStackTemplateOptions.class)
+                    
.domainId(iaasInfo.getProperty(CloudControllerConstants.DOMAIN_ID));
+        }
+
+        /**
+         *Set key pair
+         * in cloudstack sometimes we get unauthorized exception if we didn't 
specify the
+         * domain ID and user name
+         */
+        if (iaasInfo.getProperty(CloudControllerConstants.KEY_PAIR) != null) {
+            template.getOptions().as(CloudStackTemplateOptions.class)
+                    
.keyPair(iaasInfo.getProperty(CloudControllerConstants.KEY_PAIR));
+        }
+
+        // ability to define tags
+        if (iaasInfo.getProperty(CloudControllerConstants.TAGS) != null) {
+            template.getOptions()
+                    .as(CloudStackTemplateOptions.class)
+                    
.tags(Arrays.asList(iaasInfo.getProperty(CloudControllerConstants.TAGS)
+                            .split(CloudControllerConstants.ENTRY_SEPARATOR)));
+        }
+        //set disk offering to the instance
+        if (iaasInfo.getProperty(CloudControllerConstants.DISK_OFFERING) != 
null) {
+            template.getOptions()
+                    .as(CloudStackTemplateOptions.class)
+                    
.diskOfferingId(iaasInfo.getProperty(CloudControllerConstants.DISK_OFFERING));
+        }
+
+        // set Template
+        iaasInfo.setTemplate(template);
+    }
+
+    @Override
+    public void setDynamicPayload() {
+        IaasProvider iaasInfo = getIaasProvider();
+        if (iaasInfo.getTemplate() != null && iaasInfo.getPayload() != null) {
+            
iaasInfo.getTemplate().getOptions().as(CloudStackTemplateOptions.class)
+                    
.userMetadata(convertByteArrayToHashMap(iaasInfo.getPayload()));
+        }
+    }
+
+    /**
+     * IMPORTANT
+     * In cloudstack we can assign public IPs, if we are using an advanced 
zone only. If we are using a basic zone
+     * we cannot assign public ips.
+     * <p/>
+     * When we use an advanced zone, a public IP address will get 
automatically assigned to the vm. So we don't need
+     * to find an unallocated IP address and assign that address to the vm. If 
you are using a basic zone you cannot
+     * assign public IPs
+     * <p/>
+     * So  this method will find the IP that has been assigned to the vm and 
return it.
+     */
+    @Override
+    public String associateAddress(NodeMetadata node) {
+
+        IaasProvider iaasInfo = getIaasProvider();
+        ComputeServiceContext context = 
iaasInfo.getComputeService().getContext();
+        CloudStackApi cloudStackApi = context.unwrapApi(CloudStackApi.class);
+        String ip = null;
+
+        // get all allocated IPs
+        ListPublicIPAddressesOptions listPublicIPAddressesOptions = new 
ListPublicIPAddressesOptions();
+        
listPublicIPAddressesOptions.zoneId(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE));
+
+        Set<PublicIPAddress> publicIPAddresses = cloudStackApi.getAddressApi()
+                .listPublicIPAddresses(listPublicIPAddressesOptions);
+
+        String id = node.getProviderId(); //vm ID
+
+        for (PublicIPAddress publicIPAddress : publicIPAddresses) {
+            if (publicIPAddress.getVirtualMachineId().equals(id)) { //check 
whether this instance has
+                // already got an public ip or not
+                ip = publicIPAddress.getIPAddress(); //A public ip has been 
successfully assigned to the vm
+                log.info("Successfully associated an IP address " + ip
+                        + " for node with id: " + node.getId());
+                break;
+            }
+
+        }
+
+        if (ip == null || ip.isEmpty()) { //IP has not been successfully 
assigned to VM(That means there are
+            //  no more IPs  available for the VM)
+            String msg = "No address associated for node with id: " + 
node.getId();
+            log.warn(msg);
+            throw new CloudControllerException(msg);
+        }
+
+        return ip;
+    }
+
+    @Override
+    public String associatePredefinedAddress(NodeMetadata node, String ip) {
+        return "";
+    }
+
+    @Override
+    public void releaseAddress(String ip) {
+        IaasProvider iaasInfo = getIaasProvider();
+        ComputeServiceContext context = 
iaasInfo.getComputeService().getContext();
+        CloudStackApi cloudStackApi = context.unwrapApi(CloudStackApi.class);
+        cloudStackApi.getAddressApi().disassociateIPAddress(ip);
+    }
+
+    @Override
+    public boolean createKeyPairFromPublicKey(String region, String 
keyPairName, String publicKey) {
+
+        IaasProvider iaasInfo = getIaasProvider();
+        ComputeServiceContext context = 
iaasInfo.getComputeService().getContext();
+        CloudStackApi cloudStackApi = context.unwrapApi(CloudStackApi.class);
+        SshKeyPair sshKeyPair = 
cloudStackApi.getSSHKeyPairApi().createSSHKeyPair(keyPairName);
+
+        if (sshKeyPair != null) {
+
+            
iaasInfo.getTemplate().getOptions().as(CloudStackTemplateOptions.class)
+                    .keyPair(sshKeyPair.getName());
+
+            log.info("A key-pair is created successfully - Key Pair Name: " + 
sshKeyPair.getName());
+            return true;
+        }
+        log.error("Key-pair is unable to create");
+        return false;
+    }
+
+    @Override
+    public boolean isValidRegion(String region) throws InvalidRegionException {
+
+        IaasProvider iaasInfo = getIaasProvider();
+        //no such method in Jclouds cloudstack api
+        String msg = "Invalid region: " + region + " in the iaas: " + 
iaasInfo.getType();
+        log.error(msg);
+        throw new InvalidRegionException(msg);
+    }
+
+    @Override
+    public boolean isValidZone(String region, String zone) throws 
InvalidZoneException {
+
+        IaasProvider iaasInfo = getIaasProvider();
+        ComputeServiceContext context = 
iaasInfo.getComputeService().getContext();
+        CloudStackApi cloudStackApi = context.unwrapApi(CloudStackApi.class);
+        ListZonesOptions listZonesOptions = new ListZonesOptions();
+        listZonesOptions.available(true);
+        Set<Zone> zoneSet = 
cloudStackApi.getZoneApi().listZones(listZonesOptions);
+
+        for (org.jclouds.cloudstack.domain.Zone configuredZone : zoneSet) {
+            if (configuredZone.getName().equalsIgnoreCase(zone)) {
+                return true;
+            }
+        }
+        String msg = "Invalid zone: " + zone + " in the iaas: " + 
iaasInfo.getType();
+        log.error(msg);
+        throw new InvalidZoneException(msg);
+    }
+
+    @Override
+    public boolean isValidHost(String zone, String host) throws 
InvalidHostException {
+
+        IaasProvider iaasInfo = getIaasProvider();
+        // there's no such method in jclouds cloustack api
+        String msg = "Invalid host: " + host + " in the zone: " + zone + " and 
of the iaas: " + iaasInfo.getType();
+        log.error(msg);
+        throw new InvalidHostException(msg);
+
+    }
+
+    @Override
+    public PartitionValidator getPartitionValidator() {
+        return new CloudStackPartitionValidator();
+    }
+
+    @Override
+    public String createVolume(int sizeGB) {
+
+        // Snapshot id is not there in IaaS.createVolume() method in stratos 
4.0.0
+        String snapshotId = null;
+        //todo return volume ID if volume is created
+        IaasProvider iaasInfo = getIaasProvider();
+        ComputeServiceContext context = iaasInfo.getComputeService()
+                .getContext();
+
+        String zone = ComputeServiceBuilderUtil.extractZone(iaasInfo);
+        String diskOfferingID = 
iaasInfo.getTemplate().getOptions().as(CloudStackTemplateOptions.class)
+                .getDiskOfferingId();
+        if (zone == null && diskOfferingID == null) {
+            log.error("Could not create a volume in the , [zone] : " + zone + 
" of Iaas : " + iaasInfo);
+            return null;
+        }
+
+        VolumeApi volumeApi = 
context.unwrapApi(CloudStackApi.class).getVolumeApi();
+
+        Volume volume;
+        if (StringUtils.isEmpty(snapshotId)) {
+            if (log.isInfoEnabled()) {
+                log.info("Creating a volume in the zone " + zone);
+            }
+
+            //cloudstack jcloud api does not return a volume object
+            volumeApi.createVolumeFromCustomDiskOfferingInZone(null, 
diskOfferingID, zone, sizeGB);
+
+            //  volume = blockStoreApi.createVolumeInAvailabilityZone(zone, 
sizeGB);
+        } else {
+            if (log.isInfoEnabled()) {
+                log.info("Creating a volume in the zone " + zone + " from the 
snapshot " + snapshotId);
+            }
+            volumeApi.createVolumeFromSnapshotInZone(null, diskOfferingID, 
zone);
+        }
+
+        return null;
+    }
+
+    @Override
+    public String attachVolume(String instanceId, String volumeId, String 
deviceName) {
+        IaasProvider iaasInfo = getIaasProvider();
+        ComputeServiceContext context = iaasInfo.getComputeService()
+                .getContext();
+        CloudStackApi cloudStackApi = context.unwrapApi(CloudStackApi.class);
+
+        //get volume
+        org.jclouds.cloudstack.domain.Volume volume = 
cloudStackApi.getVolumeApi().getVolume(volumeId);
+
+        //get current volume state
+        Volume.State volumeState = volume.getState();
+
+        if (log.isDebugEnabled()) {
+            log.debug("Volume " + volumeId + " is in state " + volumeState);
+        }
+
+        //if volume is not available, not allocated or cannot use
+        //volume state ALLOCATED   means that volume has not been attached to 
any instance.
+
+        //TODO there is an error with logic.
+        if (!(volumeState == Volume.State.ALLOCATED || volumeState == 
Volume.State.CREATING
+                || volumeState == Volume.State.READY)) {
+            log.error(String.format("Volume %s can not be attached. Volume 
status is %s", volumeId, volumeState));
+        }
+
+        //check whether the account of volume and instance is same
+        if (!volume.getAccount().equals(cloudStackApi.getVirtualMachineApi()
+                .getVirtualMachine(instanceId).getAccount())) {
+            log.error(String.format("Volume %s can not be attached. Instance 
account and Volume account " +
+                    "are not the same ", volumeId));
+        }
+
+        boolean volumeBecameAvailable = false, volumeBecameAttached = false;
+
+        try {
+            if (volumeState == Volume.State.CREATING) {
+
+                volumeBecameAvailable = waitForStatus(volumeId, 
Volume.State.ALLOCATED, 5);
+
+            } else if (volumeState == Volume.State.READY) {
+                volumeBecameAvailable = true;
+            }
+
+        } catch (TimeoutException e) {
+            log.error("[Volume ID] " + volumeId + "did not become ALLOCATED 
within expected timeout");
+        }
+
+        //if volume state is 'ALLOCATED'
+        if (volumeBecameAvailable) {
+
+            //attach volume into instance
+            cloudStackApi.getVolumeApi().attachVolume(volumeId, instanceId);
+
+            try {
+                volumeBecameAttached = waitForStatus(volumeId, 
Volume.State.READY, 2);
+            } catch (TimeoutException e) {
+                log.error("[Volume ID] " + volumeId + "did not become READY 
within expected timeout");
+            }
+        }
+
+        try {
+            // waiting 5seconds till volumes are actually attached.
+            Thread.sleep(5000);
+        } catch (InterruptedException ignored) {
+
+        }
+
+        //If volume state is not 'READY'
+        if (!volumeBecameAttached) {
+            log.error(String.format("[Volume ID] %s attachment is called, but 
not yet became attached", volumeId));
+        }
+
+        log.info(String.format("Volume [id]: %s attachment for instance [id]: 
%s was successful [status]: Attaching." +
+                " of Iaas : %s", volumeId, instanceId, iaasInfo));
+
+        return "Attaching";
+
+    }
+
+    @Override
+    public void detachVolume(String instanceId, String volumeId) {
+
+
+        IaasProvider iaasInfo = getIaasProvider();
+
+        ComputeServiceContext context = iaasInfo.getComputeService()
+                .getContext();
+
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Starting to detach volume %s from the 
instance %s", volumeId, instanceId));
+        }
+
+        CloudStackApi cloudStackApi = context.unwrapApi(CloudStackApi.class);
+
+        cloudStackApi.getVolumeApi().detachVolume(volumeId);
+
+        try {
+            //TODO this is true only for newly created volumes
+            if (waitForStatus(volumeId, Volume.State.ALLOCATED, 5)) {
+                log.info(String.format("Detachment of Volume [id]: %s from 
instance [id]: %s was successful of Iaas : %s", volumeId, instanceId, 
iaasInfo));
+            }
+        } catch (TimeoutException e) {
+            log.error(String.format("Detachment of Volume [id]: %s from 
instance [id]: %s was unsuccessful. [volume Status] : %s", volumeId, 
instanceId, iaasInfo));
+        }
+
+    }
+
+    @Override
+    public void deleteVolume(String volumeId) {
+        IaasProvider iaasInfo = getIaasProvider();
+        ComputeServiceContext context = iaasInfo.getComputeService()
+                .getContext();
+        CloudStackApi cloudStackApi = context.unwrapApi(CloudStackApi.class);
+        cloudStackApi.getVolumeApi().deleteVolume(volumeId);
+        log.info("Deletion of Volume [id]: " + volumeId + " was successful. "
+                + " of Iaas : " + iaasInfo);
+    }
+
+    @Override
+    public String getIaasDevice(String device) {//todo implement this 
method(auto generated method)
+        return null;
+    }
+
+    private boolean waitForStatus(String volumeId, Volume.State 
expectedStatus, int timeoutInMilliseconds) throws TimeoutException {
+        int timeout = 1000 * 60 * timeoutInMilliseconds;
+        long timout = System.currentTimeMillis() + timeout;
+
+        IaasProvider iaasInfo = getIaasProvider();
+        ComputeServiceContext context = 
iaasInfo.getComputeService().getContext();
+        CloudStackApi cloudStackApi = context.unwrapApi(CloudStackApi.class);
+
+        //get volume
+        org.jclouds.cloudstack.domain.Volume volume = 
cloudStackApi.getVolumeApi().getVolume(volumeId);
+
+        Volume.State volumeState = volume.getState();
+
+        while (volumeState != expectedStatus) {
+            try {
+                if (log.isDebugEnabled()) {
+                    log.debug(String.format("Volume %s is still NOT in %s. 
Current State=%s", volumeId, expectedStatus, volumeState));
+                }
+                if (volumeState == Volume.State.FAILED || volumeState == 
Volume.State.DESTROYED || volumeState == Volume.State.UNRECOGNIZED) {
+                    log.error("Volume " + volumeId + " is in state" + 
volumeState);
+                    return false;
+                }
+
+                Thread.sleep(1000);
+                volumeState = volume.getState();
+                if (System.currentTimeMillis() > timout) {
+                    throw new TimeoutException();
+                }
+            } catch (InterruptedException e) {
+                // Ignoring the exception
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Volume %s status became %s", volumeId, 
expectedStatus));
+        }
+
+        return true;
+    }
+
+    private Map<String, String> convertByteArrayToHashMap(byte[] byteArray) {
+
+        Map<String, String> map = new HashMap<String, String>();
+
+        String stringFromByteArray = new String(byteArray);
+        String[] keyValuePairs = stringFromByteArray.split(",");
+
+        for (String keyValuePair : keyValuePairs) {
+            String[] keyValue = keyValuePair.split("=");
+            if (keyValue.length > 1) {
+                map.put(keyValue[0], keyValue[1]);
+            }
+        }
+
+        return map;
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/ddf44967/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java
 
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java
index 3b81dc8..8df2767 100644
--- 
a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java
+++ 
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java
@@ -258,4 +258,10 @@ public final class CloudControllerConstants {
     public static final String NETWORK_FIXED_IP = "fixedIp";
     public static final String NETWORK_PORT = "portUuid";
     public static final String NETWORK_UUID = "networkUuid";
+
+    // CloudStack specific
+    public static final String USER_NAME = "username";
+    public static final String DOMAIN_ID = "domainId";
+    public static final String DISK_OFFERING = "diskOffering";
+    public static final String NETWORK_IDS= "networkIds";
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/ddf44967/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/CloudstackPartitionValidator.java
----------------------------------------------------------------------
diff --git 
a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/CloudstackPartitionValidator.java
 
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/CloudstackPartitionValidator.java
new file mode 100644
index 0000000..4f3fbce
--- /dev/null
+++ 
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/CloudstackPartitionValidator.java
@@ -0,0 +1,53 @@
+package org.apache.stratos.cloud.controller.validate;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.exception.InvalidPartitionException;
+import org.apache.stratos.cloud.controller.interfaces.Iaas;
+import org.apache.stratos.cloud.controller.pojo.IaasProvider;
+import org.apache.stratos.cloud.controller.util.CloudControllerConstants;
+import org.apache.stratos.cloud.controller.util.CloudControllerUtil;
+import 
org.apache.stratos.cloud.controller.validate.interfaces.PartitionValidator;
+import org.apache.stratos.messaging.domain.topology.Scope;
+
+import java.util.Properties;
+
+
+public class CloudStackPartitionValidator implements PartitionValidator {
+
+
+    private static final Log log = 
LogFactory.getLog(AWSEC2PartitionValidator.class);
+    private IaasProvider iaasProvider;
+    private Iaas iaas;
+
+
+    @Override
+    public void setIaasProvider(IaasProvider iaas) {
+        this.iaasProvider = iaas;
+        this.iaas = iaas.getIaas();
+    }
+
+    @Override
+    public IaasProvider validate(String partitionId, Properties properties) 
throws InvalidPartitionException {
+
+        try {
+            IaasProvider updatedIaasProvider = new IaasProvider(iaasProvider);
+            Iaas updatedIaas = 
CloudControllerUtil.getIaas(updatedIaasProvider);
+            updatedIaas.setIaasProvider(updatedIaasProvider);
+
+            if (properties.containsKey(Scope.zone.toString())) {
+                String zone = properties.getProperty(Scope.zone.toString());
+                iaas.isValidZone(null, zone);
+                
updatedIaasProvider.setProperty(CloudControllerConstants.AVAILABILITY_ZONE, 
zone);
+                updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider);
+                updatedIaas.setIaasProvider(updatedIaasProvider);
+            }
+
+    } catch (Exception ex) {
+        String msg = "Invalid Partition Detected : "+partitionId+". Cause: 
"+ex.getMessage();
+        log.error(msg, ex);
+        throw new InvalidPartitionException(msg, ex);
+    }
+        return iaasProvider;
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/ddf44967/features/cloud-controller/org.apache.stratos.cloud.controller.feature/pom.xml
----------------------------------------------------------------------
diff --git 
a/features/cloud-controller/org.apache.stratos.cloud.controller.feature/pom.xml 
b/features/cloud-controller/org.apache.stratos.cloud.controller.feature/pom.xml
index 40d9775..208daff 100644
--- 
a/features/cloud-controller/org.apache.stratos.cloud.controller.feature/pom.xml
+++ 
b/features/cloud-controller/org.apache.stratos.cloud.controller.feature/pom.xml
@@ -88,7 +88,11 @@
            <artifactId>openstack-nova</artifactId>
            <version>1.7.1-stratos</version>
          </dependency>
-         
+         <dependency>
+            <groupId>org.apache.jclouds.api</groupId>
+            <artifactId>cloudstack</artifactId>
+            <version>${jclouds.version}</version>
+         </dependency>
          <dependency>
            <groupId>org.apache.jclouds.api</groupId>
            <artifactId>openstack-keystone</artifactId>
@@ -232,6 +236,7 @@
                                 
<bundleDef>org.apache.stratos:ec2:1.7.1-stratos</bundleDef>
                                 
<bundleDef>org.apache.stratos:openstack-nova:1.7.1-stratos</bundleDef>
                                 
<bundleDef>org.apache.stratos:vcloud:1.7.1-stratos</bundleDef>
+                                
<bundleDef>org.apache.jclouds.api:cloudstack:${jclouds.version}</bundleDef>
                                 
<bundleDef>com.jamesmurty.utils.wso2:java-xmlbuilder:0.4.wso2v1</bundleDef>
                                 
<bundleDef>org.apache.jclouds.common:openstack-common:${jclouds.version}</bundleDef>
                                 
<bundleDef>org.apache.jclouds.api:openstack-keystone:${jclouds.version}</bundleDef>

http://git-wip-us.apache.org/repos/asf/stratos/blob/ddf44967/features/cloud-controller/org.apache.stratos.cloud.controller.feature/src/main/resources/conf/cloud-controller.xml
----------------------------------------------------------------------
diff --git 
a/features/cloud-controller/org.apache.stratos.cloud.controller.feature/src/main/resources/conf/cloud-controller.xml
 
b/features/cloud-controller/org.apache.stratos.cloud.controller.feature/src/main/resources/conf/cloud-controller.xml
index 24ff621..e6ab96a 100644
--- 
a/features/cloud-controller/org.apache.stratos.cloud.controller.feature/src/main/resources/conf/cloud-controller.xml
+++ 
b/features/cloud-controller/org.apache.stratos.cloud.controller.feature/src/main/resources/conf/cloud-controller.xml
@@ -16,62 +16,79 @@
   #  KIND, either express or implied.  See the License for the
   #  specific language governing permissions and limitations
   #  under the License.
-  --> 
+  -->
 <cloudController xmlns:svns="http://org.wso2.securevault/configuration";>
 
-       <svns:secureVault
-               
provider="org.wso2.securevault.secret.handler.SecretManagerSecretCallbackHandler"
 />
+    <svns:secureVault
+            
provider="org.wso2.securevault.secret.handler.SecretManagerSecretCallbackHandler"/>
 
-       <dataPublisher enable="false">
-               <!-- BAM Server Info - default values are 'admin' and 'admin' 
-                        Optional element. -->
-               <bamServer>
-               <!-- BAM server URL should be specified in carbon.xml -->
-                       <adminUserName>admin</adminUserName>
-                       <adminPassword 
svns:secretAlias="cloud.controller.bam.server.admin.password">admin</adminPassword>
-               </bamServer>
-               <!-- Default cron expression is '1 * * * * ? *' meaning 'first 
second of every minute'.
-                        Optional element. -->
-               <cron>1 * * * * ? *</cron>
-               <!-- Cassandra cluster related info -->
-               <!--cassandraInfo>
-                       <connectionUrl>localhost:9160</connectionUrl>
-                       <userName>admin</userName>
-                       <password 
svns:secretAlias="cloud.controller.cassandra.server.password">admin</password>
-               </cassandraInfo-->
-       </dataPublisher>
+    <dataPublisher enable="false">
+        <!-- BAM Server Info - default values are 'admin' and 'admin'
+             Optional element. -->
+        <bamServer>
+            <!-- BAM server URL should be specified in carbon.xml -->
+            <adminUserName>admin</adminUserName>
+            <adminPassword 
svns:secretAlias="cloud.controller.bam.server.admin.password">admin</adminPassword>
+        </bamServer>
+        <!-- Default cron expression is '1 * * * * ? *' meaning 'first second 
of every minute'.
+             Optional element. -->
+        <cron>1 * * * * ? *</cron>
+        <!-- Cassandra cluster related info -->
+        <!--cassandraInfo>
+            <connectionUrl>localhost:9160</connectionUrl>
+            <userName>admin</userName>
+            <password 
svns:secretAlias="cloud.controller.cassandra.server.password">admin</password>
+        </cassandraInfo-->
+    </dataPublisher>
 
-       <topologySync enable="true">
-               <property name="cron" value="1 * * * * ? *" />
-       </topologySync> 
+    <topologySync enable="true">
+        <property name="cron" value="1 * * * * ? *"/>
+    </topologySync>
 
-       <!-- Specify the properties that are common to an IaaS here. This 
element 
-               is not necessary [0..1]. But you can use this section to avoid 
specifying 
-               same property over and over again. -->
-       <iaasProviders>
-               <!--iaasProvider type="ec2" name="ec2 specific details">
-                       
<className>org.apache.stratos.cloud.controller.iaases.AWSEC2Iaas</className>
-                       <provider>aws-ec2</provider>
-                       <identity 
svns:secretAlias="cloud.controller.ec2.identity">dhsaghfdal</identity>
-                       <credential 
svns:secretAlias="cloud.controller.ec2.credential">jdkjaskd</credential>
-                       <scaleUpOrder>1</scaleUpOrder>
-                       <scaleDownOrder>2</scaleDownOrder>
-                       <property name="jclouds.ec2.ami-query" 
value="owner-id=XX-XX-XX;state=available;image-type=machine"/>
-                       <property name="availabilityZone" value="us-east-1c"/>
-                       <property name="securityGroups" 
value="manager,cep,mb,default"/>
-                       <property name="instanceType" value="m1.large"/>
-                       <property name="keyPair" value="nirmal-key"/>
-               </iaasProvider-->
-               <iaasProvider type="openstack" name="openstack specific 
details">
-                       
<className>org.apache.stratos.cloud.controller.iaases.OpenstackNovaIaas</className>
-                       <provider>openstack-nova</provider>
-                       <identity 
svns:secretAlias="cloud.controller.openstack.identity">demo:demo</identity>
-                       <credential 
svns:secretAlias="cloud.controller.openstack.credential">openstack</credential>
-                       <property name="jclouds.endpoint" 
value="http://192.168.16.20:5000/"; />
-                       <property 
name="jclouds.openstack-nova.auto-create-floating-ips" value="false"/>
-                       <property name="jclouds.api-version" value="2.0/" />
-                       <property name="X" value="x" />
-                       <property name="Y" value="y" />
-               </iaasProvider>
-       </iaasProviders>
+    <!-- Specify the properties that are common to an IaaS here. This element
+        is not necessary [0..1]. But you can use this section to avoid 
specifying
+        same property over and over again. -->
+    <iaasProviders>
+        <!--iaasProvider type="ec2" name="ec2 specific details">
+                
<className>org.apache.stratos.cloud.controller.iaases.AWSEC2Iaas</className>
+        <provider>aws-ec2</provider>
+        <identity 
svns:secretAlias="cloud.controller.ec2.identity">dhsaghfdal</identity>
+        <credential 
svns:secretAlias="cloud.controller.ec2.credential">jdkjaskd</credential>
+        <scaleUpOrder>1</scaleUpOrder>
+        <scaleDownOrder>2</scaleDownOrder>
+        <property name="jclouds.ec2.ami-query" 
value="owner-id=XX-XX-XX;state=available;image-type=machine"/>
+                <property name="availabilityZone" value="us-east-1c"/>
+        <property name="securityGroups" value="manager,cep,mb,default"/>
+                <property name="instanceType" value="m1.large"/>
+                <property name="keyPair" value="nirmal-key"/>
+    </iaasProvider-->
+        <iaasProvider type="openstack" name="openstack specific details">
+            
<className>org.apache.stratos.cloud.controller.iaases.OpenstackNovaIaas</className>
+            <provider>openstack-nova</provider>
+            <identity 
svns:secretAlias="cloud.controller.openstack.identity">demo:demo</identity>
+            <credential 
svns:secretAlias="cloud.controller.openstack.credential">openstack</credential>
+            <property name="jclouds.endpoint" 
value="http://192.168.16.20:5000/"/>
+            <property name="jclouds.openstack-nova.auto-create-floating-ips" 
value="false"/>
+            <property name="jclouds.api-version" value="2.0/"/>
+            <property name="X" value="x"/>
+            <property name="Y" value="y"/>
+        </iaasProvider>
+        <!-- iaasProvider type="cloudstack" name="cloudstack specific details">
+            
<className>org.apache.stratos.cloud.controller.iaases.CloudstackIaas</className>
+            <provider>cloudstack</provider>
+            <identity 
svns:secretAlias="cloud.controller.cloudstack.identity">api-key</identity>
+            <credential 
svns:secretAlias="cloud.controller.cloudstack.credential">secret-key</credential>
+            <property name="jclouds.endpoint" value="ip:port"/>
+            <property name="availabilityZone" value="zone_Id"/>
+            <property name="instanceType" value="instance_type_Id"/>
+            <property name="securityGroupIds" 
value="security_group_Id1,security_group_id2"/>
+            <property name="networkIds" value="network_Id1,network_Id2"/>
+            <property name="diskOffering" value="disk_offering_Id"/>
+            <property name="username" value="username"/>
+            <property name="domainId" value="domainId"/>
+            <property name="keyPair" value="asanka-key"/>
+            <property name="tags" value="tag1,tag2,tag3"/>
+            <property name="autoAssignIp" value="false"/>
+        </iaasProvider -->
+    </iaasProviders>
 </cloudController>

Reply via email to