http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/OpenstackNovaIaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/OpenstackNovaIaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/OpenstackNovaIaas.java deleted file mode 100644 index e02f693..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/OpenstackNovaIaas.java +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.stratos.cloud.controller.iaas; - -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; - -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.util.ComputeServiceBuilderUtil; -import org.apache.stratos.cloud.controller.domain.IaasProvider; -import org.apache.stratos.cloud.controller.domain.NetworkInterface; -import org.apache.stratos.cloud.controller.util.CloudControllerConstants; -import org.apache.stratos.cloud.controller.util.CloudControllerUtil; -import org.apache.stratos.cloud.controller.iaas.validators.OpenstackNovaPartitionValidator; -import org.apache.stratos.cloud.controller.iaas.validators.PartitionValidator; -import org.jclouds.compute.ComputeServiceContext; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.NodeMetadataBuilder; -import org.jclouds.compute.domain.Template; -import org.jclouds.compute.domain.TemplateBuilder; -import org.jclouds.compute.options.TemplateOptions; -import org.jclouds.openstack.nova.v2_0.NovaApi; -import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions; -import org.jclouds.openstack.nova.v2_0.domain.FloatingIP; -import org.jclouds.openstack.nova.v2_0.domain.HostAggregate; -import org.jclouds.openstack.nova.v2_0.domain.KeyPair; -import org.jclouds.openstack.nova.v2_0.domain.Network; -import org.jclouds.openstack.nova.v2_0.domain.Volume; -import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment; -import org.jclouds.openstack.nova.v2_0.domain.zonescoped.AvailabilityZone; -import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneApi; -import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi; -import org.jclouds.openstack.nova.v2_0.extensions.HostAggregateApi; -import org.jclouds.openstack.nova.v2_0.extensions.KeyPairApi; -import org.jclouds.openstack.nova.v2_0.extensions.VolumeApi; -import org.jclouds.openstack.nova.v2_0.extensions.VolumeAttachmentApi; -import org.jclouds.openstack.nova.v2_0.options.CreateVolumeOptions; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.concurrent.TimeoutException; - -public class OpenstackNovaIaas extends Iaas { - - private static final Log log = LogFactory.getLog(OpenstackNovaIaas.class); - private static final String SUCCESSFUL_LOG_LINE = "A key-pair is created successfully in "; - private static final String FAILED_LOG_LINE = "Key-pair is unable to create in "; - - public OpenstackNovaIaas(IaasProvider iaasProvider) { - super(iaasProvider); - } - - @Override - public void buildComputeServiceAndTemplate() { - - IaasProvider iaasInfo = getIaasProvider(); - - // builds and sets Compute Service - ComputeServiceBuilderUtil.buildDefaultComputeService(iaasInfo); - - // builds and sets Template - buildTemplate(); - - } - - public void buildTemplate() { - IaasProvider iaasInfo = getIaasProvider(); - - if (iaasInfo.getComputeService() == null) { - throw new CloudControllerException( - "Compute service is null for IaaS provider: " - + iaasInfo.getName()); - } - - TemplateBuilder templateBuilder = iaasInfo.getComputeService() - .templateBuilder(); - templateBuilder.imageId(iaasInfo.getImage()); - if(!(iaasInfo instanceof IaasProvider)) { - templateBuilder.locationId(iaasInfo.getType()); - } - - // to avoid creation of template objects in each and every time, we - // create all at once! - - String instanceType; - - // set instance type - if (((instanceType = iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE)) != null)) { - - templateBuilder.hardwareId(instanceType); - } - - Template template = templateBuilder.build(); - - // In Openstack the call to IaaS should be blocking, in order to retrieve - // IP addresses. - boolean blockUntilRunning = true; - if(iaasInfo.getProperty(CloudControllerConstants.BLOCK_UNTIL_RUNNING) != null) { - blockUntilRunning = Boolean.parseBoolean(iaasInfo.getProperty( - CloudControllerConstants.BLOCK_UNTIL_RUNNING)); - } - 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[] {}); - - if (iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUPS) != null) { - template.getOptions() - .as(NovaTemplateOptions.class) - .securityGroupNames( - iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUPS).split( - CloudControllerConstants.ENTRY_SEPARATOR)); - } - - if (iaasInfo.getProperty(CloudControllerConstants.KEY_PAIR) != null) { - template.getOptions().as(NovaTemplateOptions.class) - .keyPairName(iaasInfo.getProperty(CloudControllerConstants.KEY_PAIR)); - } - - if (iaasInfo.getNetworkInterfaces() != null) { - Set<Network> novaNetworksSet = new LinkedHashSet<Network>(iaasInfo.getNetworkInterfaces().length); - for (NetworkInterface ni:iaasInfo.getNetworkInterfaces()) { - novaNetworksSet.add(Network.builder().networkUuid(ni.getNetworkUuid()).fixedIp(ni.getFixedIp()) - .portUuid(ni.getPortUuid()).build()); - } - template.getOptions().as(NovaTemplateOptions.class).novaNetworks(novaNetworksSet); - } - - if (iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) { - template.getOptions().as(NovaTemplateOptions.class) - .availabilityZone(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE)); - } - - //TODO -// if (iaas.getProperty(CloudControllerConstants.HOST) != null) { -// template.getOptions().as(NovaTemplateOptions.class) -// .(CloudControllerConstants.HOST); -// } - - // set Template - iaasInfo.setTemplate(template); - } - - @Override - public void setDynamicPayload() { - - IaasProvider iaasInfo = getIaasProvider(); - - if (iaasInfo.getTemplate() != null && iaasInfo.getPayload() != null) { - - iaasInfo.getTemplate().getOptions().as(NovaTemplateOptions.class) - .userData(iaasInfo.getPayload()); - } - - } - - @Override - public synchronized boolean createKeyPairFromPublicKey(String region, String keyPairName, - String publicKey) { - - IaasProvider iaasInfo = getIaasProvider(); - - String openstackNovaMsg = " Openstack-nova. Region: " + region - + " - Name: "; - - ComputeServiceContext context = iaasInfo.getComputeService() - .getContext(); - NovaApi novaApi = context.unwrapApi(NovaApi.class); - KeyPairApi api = novaApi.getKeyPairExtensionForZone(region).get(); - - KeyPair keyPair = api.createWithPublicKey(keyPairName, publicKey); - - if (keyPair != null) { - - iaasInfo.getTemplate().getOptions().as(NovaTemplateOptions.class) - .keyPairName(keyPair.getName()); - - log.info(SUCCESSFUL_LOG_LINE + openstackNovaMsg + keyPair.getName()); - return true; - } - - log.error(FAILED_LOG_LINE + openstackNovaMsg); - return false; - - } - - @Override - public synchronized String associateAddress(NodeMetadata node) { - - IaasProvider iaasInfo = getIaasProvider(); - - ComputeServiceContext context = iaasInfo.getComputeService() - .getContext(); - - String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); - - NovaApi novaApi = context.unwrapApi(NovaApi.class); - FloatingIPApi floatingIp = novaApi.getFloatingIPExtensionForZone( - region).get(); - - String ip = null; - // first try to find an unassigned IP. - ArrayList<FloatingIP> unassignedIps = Lists.newArrayList(Iterables - .filter(floatingIp.list(), - new Predicate<FloatingIP>() { - - @Override - public boolean apply(FloatingIP arg0) { - return arg0.getInstanceId() == null; - } - - })); - - if (!unassignedIps.isEmpty()) { - // try to prevent multiple parallel launches from choosing the same - // ip. - Collections.shuffle(unassignedIps); - ip = Iterables.getLast(unassignedIps).getIp(); - } - - // if no unassigned IP is available, we'll try to allocate an IP. - if (ip == null || ip.isEmpty()) { - String defaultFloatingIpPool = iaasInfo.getProperty(CloudControllerConstants.DEFAULT_FLOATING_IP_POOL); - FloatingIP allocatedFloatingIP; - if ((defaultFloatingIpPool == null) || "".equals(defaultFloatingIpPool)) { - allocatedFloatingIP = floatingIp.create(); - } else { - allocatedFloatingIP = floatingIp.allocateFromPool(defaultFloatingIpPool); - } - if (allocatedFloatingIP == null) { - String msg = "Failed to allocate an IP address."; - log.error(msg); - throw new CloudControllerException(msg); - } - ip = allocatedFloatingIP.getIp(); - } - - // wait till the fixed IP address gets assigned - this is needed before - // we associate a public IP - while (node.getPrivateAddresses() == null) { - CloudControllerUtil.sleep(1000); - } - - if (node.getPublicAddresses() != null - && node.getPublicAddresses().iterator().hasNext()) { - log.info("A public IP (" - + node.getPublicAddresses().iterator().next() - + ") is already allocated to the instance [id] : " - + node.getId()); - return null; - } - - int retries = 0; - //TODO make 5 configurable - while (retries < 5 - && !associateIp(floatingIp, ip, node.getProviderId())) { - - // wait for 5s - CloudControllerUtil.sleep(5000); - retries++; - } - - log.info("Successfully associated an IP address " + ip - + " for node with id: " + node.getId()); - - return ip; - } - - @Override - public synchronized String associatePredefinedAddress (NodeMetadata node, String ip) { - if(log.isDebugEnabled()) { - log.debug("OpenstackNovaIaas:associatePredefinedAddress:ip:" + ip); - } - - IaasProvider iaasInfo = getIaasProvider(); - - ComputeServiceContext context = iaasInfo.getComputeService() - .getContext(); - - String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); - - FloatingIPApi floatingIp = context.unwrapApi(NovaApi.class).getFloatingIPExtensionForZone( - region).get(); - - if(log.isDebugEnabled()) { - log.debug("OpenstackNovaIaas:associatePredefinedAddress:floatingip:" + floatingIp); - } - - // get the list of all unassigned IP. - ArrayList<FloatingIP> unassignedIps = Lists.newArrayList(Iterables - .filter(floatingIp.list(), - new Predicate<FloatingIP>() { - - @Override - public boolean apply(FloatingIP arg0) { - // FIXME is this the correct filter? - return arg0.getFixedIp() == null; - } - - })); - - boolean isAvailable = false; - for (FloatingIP fip : unassignedIps) { - if(log.isDebugEnabled()) { - log.debug("OpenstackNovaIaas:associatePredefinedAddress:iterating over available floatingip:" + fip); - } - if (ip.equals(fip.getIp())) { - if(log.isDebugEnabled()) { - log.debug(String.format("OpenstackNovaIaas:associatePredefinedAddress:floating ip in use:%s /ip:%s", fip, ip)); - } - isAvailable = true; - break; - } - } - - if (isAvailable) { - // assign ip - if(log.isDebugEnabled()) { - log.debug("OpenstackNovaIaas:associatePredefinedAddress:assign floating ip:" + ip); - } - // exercise same code as in associateAddress() - // wait till the fixed IP address gets assigned - this is needed before - // we associate a public IP - - while (node.getPrivateAddresses() == null) { - CloudControllerUtil.sleep(1000); - } - - int retries = 0; - while (retries < 5 - && !associateIp(floatingIp, ip, node.getProviderId())) { - - // wait for 5s - CloudControllerUtil.sleep(5000); - retries++; - } - - NodeMetadataBuilder.fromNodeMetadata(node) - .publicAddresses(ImmutableSet.of(ip)).build(); - - log.info("OpenstackNovaIaas:associatePredefinedAddress:Successfully associated an IP address " + ip - + " for node with id: " + node.getId()); - } else { - // unable to allocate predefined ip, - log.info("OpenstackNovaIaas:associatePredefinedAddress:Unable to allocate predefined ip:" - + " for node with id: " + node.getId()); - return ""; - } - - - NodeMetadataBuilder.fromNodeMetadata(node) - .publicAddresses(ImmutableSet.of(ip)).build(); - - log.info("OpenstackNovaIaas:associatePredefinedAddress::Successfully associated an IP address " + ip - + " for node with id: " + node.getId()); - - return ip; - - } - - @Override - public synchronized void releaseAddress(String ip) { - - IaasProvider iaasInfo = getIaasProvider(); - - ComputeServiceContext context = iaasInfo.getComputeService() - .getContext(); - - String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); - - NovaApi novaApi = context.unwrapApi(NovaApi.class); - FloatingIPApi floatingIPApi = novaApi.getFloatingIPExtensionForZone(region).get(); - - for (FloatingIP floatingIP : floatingIPApi.list()) { - if (floatingIP.getIp().equals(ip)) { - floatingIPApi.delete(floatingIP.getId()); - break; - } - } - - } - - private boolean associateIp(FloatingIPApi api, String ip, String id) { - try { - api.addToServer(ip, id); - return true; - } catch (RuntimeException ex) { - return false; - } - } - - @Override - public boolean isValidRegion(String region) throws InvalidRegionException { - IaasProvider iaasInfo = getIaasProvider(); - - // jclouds' zone = region in openstack - if (region == null || iaasInfo == null) { - String msg = - "Region or IaaSProvider is null: region: " + region + " - IaaSProvider: " + - iaasInfo; - log.error(msg); - throw new InvalidRegionException(msg); - } - - ComputeServiceContext context = iaasInfo.getComputeService().getContext(); - NovaApi novaApi = context.unwrapApi(NovaApi.class); - Set<String> zones = novaApi.getConfiguredZones(); - for (String configuredZone : zones) { - if (region.equalsIgnoreCase(configuredZone)) { - if (log.isDebugEnabled()) { - log.debug("Found a matching region: " + region); - } - return true; - } - } - - 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(); - - // jclouds availability zone = stratos zone - if (region == null || zone == null || iaasInfo == null) { - String msg = "Host or Zone or IaaSProvider is null: region: " + region + " - zone: " + - zone + " - IaaSProvider: " + iaasInfo; - log.error(msg); - throw new InvalidZoneException(msg); - } - ComputeServiceContext context = iaasInfo.getComputeService().getContext(); - NovaApi novaApi = context.unwrapApi(NovaApi.class); - Optional<? extends AvailabilityZoneApi> availabilityZoneApi = novaApi.getAvailabilityZoneApi(region); - for (AvailabilityZone z : availabilityZoneApi.get().list()) { - - if (zone.equalsIgnoreCase(z.getName())) { - if (log.isDebugEnabled()) { - log.debug("Found a matching availability zone: " + zone); - } - return true; - } - } - - String msg = "Invalid zone: " + zone +" in the region: "+region+ " and of the iaas: "+iaasInfo.getType(); - log.error(msg); - throw new InvalidZoneException(msg); - - } - - @Override - public boolean isValidHost(String zone, String host) throws InvalidHostException { - IaasProvider iaasInfo = getIaasProvider(); - - if (host == null || zone == null || iaasInfo == null) { - String msg = String.format("Host or Zone or IaaSProvider is null: host: %s - zone: %s - IaaSProvider: %s", host, zone, iaasInfo); - log.error(msg); - throw new InvalidHostException(msg); - } - ComputeServiceContext context = iaasInfo.getComputeService().getContext(); - NovaApi novaApi = context.unwrapApi(NovaApi.class); - HostAggregateApi hostApi = novaApi.getHostAggregateExtensionForZone(zone).get(); - for (HostAggregate hostAggregate : hostApi.list()) { - for (String configuredHost : hostAggregate.getHosts()) { - if (host.equalsIgnoreCase(configuredHost)) { - if (log.isDebugEnabled()) { - log.debug("Found a matching host: " + host); - } - return true; - } - } - } - - String msg = String.format("Invalid host: %s in the zone: %s and of the iaas: %s", host, zone, iaasInfo.getType()); - log.error(msg); - throw new InvalidHostException(msg); - } - - @Override - public PartitionValidator getPartitionValidator() { - return new OpenstackNovaPartitionValidator(); - } - - @Override - public String createVolume(int sizeGB, String snapshotId) { - IaasProvider iaasInfo = getIaasProvider(); - - if (iaasInfo == null) { - log.fatal(String.format("Cannot create a new volume with snapshot ID : %s", snapshotId)); - return null; - } - - String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); - String zone = ComputeServiceBuilderUtil.extractZone(iaasInfo); - - if (region == null) { - log.fatal(String.format("Cannot create a new volume. Extracted region is null for Iaas : %s", iaasInfo)); - return null; - } - ComputeServiceContext context = iaasInfo.getComputeService().getContext(); - - NovaApi novaApi = context.unwrapApi(NovaApi.class); - VolumeApi volumeApi = novaApi.getVolumeExtensionForZone(region).get(); - Volume volume; - if(StringUtils.isEmpty(snapshotId)){ - if(log.isDebugEnabled()){ - log.info("Creating a volume in the zone " + zone); - } - volume = volumeApi.create(sizeGB, CreateVolumeOptions.Builder.availabilityZone(zone)); - }else{ - if(log.isDebugEnabled()){ - log.info("Creating a volume in the zone " + zone + " from the shanpshot " + snapshotId); - } - volume = volumeApi.create(sizeGB, CreateVolumeOptions.Builder.availabilityZone(zone).snapshotId(snapshotId)); - } - - if (volume == null) { - log.fatal(String.format("Volume creation was unsuccessful. [region] : %s [zone] : %s of Iaas : %s", region, zone, iaasInfo)); - return null; - } - - String volumeId = volume.getId(); - /* - Volume.Status volumeStatus = this.getVolumeStatus(volumeApi, volumeId); - - if(!(volumeStatus == Volume.Status.AVAILABLE || volumeStatus == Volume.Status.CREATING)){ - log.error(String.format("Error while creating [volume id] %s. Volume status is %s", volumeId, volumeStatus)); - return volumeId; - } - try { - if(!waitForStatus(volumeApi, volumeId, Volume.Status.AVAILABLE)){ - log.error("Volume did not become AVAILABLE. Current status is " + volume.getStatus()); - } - } catch (TimeoutException e) { - log.error("[Volume ID] " + volumeId + "did not become AVAILABLE within expected timeout"); - return volumeId; - } - */ - log.info(String.format("Successfully created a new volume [id]: %s in [region] : %s [zone] : %s of Iaas : %s [Volume ID]%s", volume.getId(), region, zone, iaasInfo, volume.getId())); - return volumeId; - } - - private boolean waitForStatus(String volumeId, Volume.Status expectedStatus, int timeoutInMins) throws TimeoutException { - int timeout = 1000 * 60 * timeoutInMins; - long timout = System.currentTimeMillis() + timeout; - - IaasProvider iaasInfo = getIaasProvider(); - String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); - ComputeServiceContext context = iaasInfo.getComputeService().getContext();; - NovaApi novaApi = context.unwrapApi(NovaApi.class); - VolumeApi volumeApi = novaApi.getVolumeExtensionForZone(region).get(); - Volume.Status volumeStatus = this.getVolumeStatus(volumeApi, volumeId); - - while(volumeStatus != expectedStatus){ - try { - if(log.isDebugEnabled()){ - log.debug(String.format("Volume %s is still NOT in %s. Current State=%s", volumeId, expectedStatus, volumeStatus)); - } - if(volumeStatus == Volume.Status.ERROR){ - log.error("Volume " + volumeId + " is in state ERROR"); - return false; - } - Thread.sleep(1000); - volumeStatus = this.getVolumeStatus(volumeApi, volumeId); - 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; - } - - @Override - public String attachVolume(String instanceId, String volumeId, String deviceName) { - IaasProvider iaasInfo = getIaasProvider(); - - if (StringUtils.isEmpty(volumeId)) { - log.error("Volume provided to attach can not be null"); - } - - if (StringUtils.isEmpty(instanceId)) { - log.error("Instance provided to attach can not be null"); - } - - ComputeServiceContext context = iaasInfo.getComputeService() - .getContext(); - String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); - String device = deviceName == null ? "/dev/vdc" : deviceName; - - if (region == null) { - log.fatal(String.format("Cannot attach the volume [id]: %s. Extracted region is null for Iaas : %s", volumeId, iaasInfo)); - return null; - } - - NovaApi novaApi = context.unwrapApi(NovaApi.class); - VolumeApi volumeApi = novaApi.getVolumeExtensionForZone(region).get(); - VolumeAttachmentApi volumeAttachmentApi = novaApi.getVolumeAttachmentExtensionForZone(region).get(); - - Volume.Status volumeStatus = this.getVolumeStatus(volumeApi, volumeId); - - if (log.isDebugEnabled()) { - log.debug("Volume " + volumeId + " is in state " + volumeStatus); - } - - if (!(volumeStatus == Volume.Status.AVAILABLE || volumeStatus == Volume.Status.CREATING)) { - log.error(String.format("Volume %s can not be attached. Volume status is %s", volumeId, volumeStatus)); - return null; - } - - boolean volumeBecameAvailable = false, volumeBecameAttached = false; - try { - volumeBecameAvailable = waitForStatus(volumeId, Volume.Status.AVAILABLE, 5); - } catch (TimeoutException e) { - log.error("[Volume ID] " + volumeId + "did not become AVAILABLE within expected timeout"); - } - - VolumeAttachment attachment = null; - if (volumeBecameAvailable) { - attachment = volumeAttachmentApi.attachVolumeToServerAsDevice(volumeId, instanceId, device); - - try { - volumeBecameAttached = waitForStatus(volumeId, Volume.Status.IN_USE, 2); - } catch (TimeoutException e) { - log.error("[Volume ID] " + volumeId + "did not become IN_USE within expected timeout"); - } - } - try { - // waiting 5seconds till volumes are actually attached. - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - if (attachment == null) { - log.fatal(String.format("Volume [id]: %s attachment for instance [id]: %s was unsuccessful. [region] : %s of Iaas : %s", volumeId, instanceId, region, iaasInfo)); - return null; - } - - 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. [region] : %s of Iaas : %s", volumeId, instanceId, region, iaasInfo)); - return "Attaching"; - } - - @Override - public void detachVolume(String instanceId, String volumeId) { - IaasProvider iaasInfo = getIaasProvider(); - - ComputeServiceContext context = iaasInfo.getComputeService() - .getContext(); - - String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); - - if(region == null) { - log.fatal(String.format("Cannot detach the volume [id]: %s from the instance [id]: %s. Extracted region is null for Iaas : %s", volumeId, instanceId, iaasInfo)); - return; - } - if(log.isDebugEnabled()) { - log.debug(String.format("Starting to detach volume %s from the instance %s", volumeId, instanceId)); - } - - NovaApi novaApi = context.unwrapApi(NovaApi.class); - VolumeAttachmentApi api = novaApi.getVolumeAttachmentExtensionForZone(region).get(); - if (api.detachVolumeFromServer(volumeId, instanceId)) { - log.info(String.format("Detachment of Volume [id]: %s from instance [id]: %s was successful. [region] : %s of Iaas : %s", volumeId, instanceId, region, iaasInfo)); - }else{ - log.error(String.format("Detachment of Volume [id]: %s from instance [id]: %s was unsuccessful. [volume Status] : %s", volumeId, instanceId, region, iaasInfo)); - } - - } - - @Override - public void deleteVolume(String volumeId) { - IaasProvider iaasInfo = getIaasProvider(); - - ComputeServiceContext context = iaasInfo.getComputeService() - .getContext(); - - String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); - - if(region == null) { - log.fatal(String.format("Cannot delete the volume [id]: %s. Extracted region is null for Iaas : %s", volumeId, iaasInfo)); - return; - } - - NovaApi novaApi = context.unwrapApi(NovaApi.class); - VolumeApi api = novaApi.getVolumeExtensionForZone(region).get(); - if (api.delete(volumeId)) { - log.info(String.format("Deletion of Volume [id]: %s was successful. [region] : %s of Iaas : %s", volumeId, region, iaasInfo)); - } - } - - @Override - public String getIaasDevice(String device) { - return device; - } - - private Volume.Status getVolumeStatus(VolumeApi volumeApi, String volumeId){ - return volumeApi.get(volumeId).getStatus(); - } -}
http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/VCloudIaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/VCloudIaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/VCloudIaas.java deleted file mode 100644 index c6e8b3f..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/VCloudIaas.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.stratos.cloud.controller.iaas; - -import org.apache.commons.io.FileUtils; -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.util.ComputeServiceBuilderUtil; -import org.apache.stratos.cloud.controller.domain.IaasProvider; -import org.apache.stratos.cloud.controller.iaas.validators.VCloudPartitionValidator; -import org.apache.stratos.cloud.controller.iaas.validators.PartitionValidator; -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.vcloud.compute.options.VCloudTemplateOptions; -import org.jclouds.vcloud.domain.network.IpAddressAllocationMode; -import org.wso2.carbon.utils.CarbonUtils; - -import java.io.File; -import java.io.IOException; - -public class VCloudIaas extends Iaas { - - - private static final Log log = LogFactory.getLog(VCloudIaas.class); - - private static final String SHELL_TYPE = "shellType"; - private static final String SCRIPTS_PATH = "scripts"; - private static final String CUSTOMIZATION_SCRIPT = "customization"; - private static final String PAYLOAD = "PAYLOAD"; - - public VCloudIaas(IaasProvider iaasProvider) { - super(iaasProvider); - } - - @Override - public void buildComputeServiceAndTemplate() { - - IaasProvider iaasInfo = getIaasProvider(); - - // builds and sets Compute Service - ComputeServiceBuilderUtil.buildDefaultComputeService(iaasInfo); - - // builds and sets Template - buildTemplate(); - - } - - public void buildTemplate() { - IaasProvider iaasInfo = getIaasProvider(); - - if (iaasInfo.getComputeService() == null) { - String msg = "Compute service is null for IaaS provider: " - + iaasInfo.getName(); - log.fatal(msg); - throw new CloudControllerException(msg); - } - - TemplateBuilder templateBuilder = iaasInfo.getComputeService() - .templateBuilder(); - - // set image id specified - templateBuilder.imageId(iaasInfo.getImage()); - - // 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? - default mode is - // non-blocking - boolean blockUntilRunning = Boolean.parseBoolean(iaasInfo - .getProperty("autoAssignIp")); - 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(22, 80, 8080, 443, 8243); - - template.getOptions().as(VCloudTemplateOptions.class) - .ipAddressAllocationMode(IpAddressAllocationMode.POOL); - - // set Template - iaasInfo.setTemplate(template); - } - - @Override - public void setDynamicPayload() { - // in vCloud case we need to run a script - IaasProvider iaasInfo = getIaasProvider(); - - if (iaasInfo.getTemplate() == null || iaasInfo.getPayload() == null) { - if (log.isDebugEnabled()) { - log.debug("Payload for vCloud not found"); - } - return; - } - - String shellType = iaasInfo.getProperty(SHELL_TYPE); - - if (shellType == null || shellType.isEmpty()) { - if (log.isDebugEnabled()) { - log.debug("Shell Type for vCloud Customization script not found from properties"); - } - return; - } - - if (log.isDebugEnabled()) { - log.debug(String.format("Shell Type '%s' will be used for vCloud Customization script", shellType)); - } - - // Payload is a String value - String payload = new String(iaasInfo.getPayload()); - - if (log.isDebugEnabled()) { - log.debug(String.format("Payload '%s' will be used for vCloud Customization script", payload)); - } - - Template template = iaasInfo.getTemplate(); - - File scriptPath = new File(CarbonUtils.getCarbonConfigDirPath(), SCRIPTS_PATH); - - File customizationScriptFile = new File(new File(scriptPath, shellType), CUSTOMIZATION_SCRIPT); - - if (!customizationScriptFile.exists()) { - if (log.isWarnEnabled()) { - log.warn(String.format("The vCloud Customization script '%s' does not exist", - customizationScriptFile.getAbsolutePath())); - } - return; - } - - String customizationScript = null; - - try { - customizationScript = FileUtils.readFileToString(customizationScriptFile); - } catch (IOException e) { - if (log.isErrorEnabled()) { - log.error( - String.format("Error reading the vCloud Customization script '%s'", - customizationScriptFile.getAbsolutePath()), e); - } - } - - if (StringUtils.isEmpty(customizationScript)) { - if (log.isDebugEnabled()) { - log.debug("No content vCloud Customization script not found from properties"); - } - return; - } - - // Set payload - customizationScript = customizationScript.replaceAll(PAYLOAD, payload); - - if (log.isDebugEnabled()) { - log.debug(String.format("The vCloud Customization script\n%s", customizationScript)); - } - - // Run the script - template.getOptions().runScript(customizationScript); - } - - @Override - public boolean createKeyPairFromPublicKey(String region, String keyPairName, String publicKey) { - - // TODO - return false; - } - - @Override - public String associateAddress(NodeMetadata node) { - - // TODO - return ""; - - } - - @Override - public String associatePredefinedAddress(NodeMetadata node, String ip) { - return ""; - } - - @Override - public void releaseAddress(String ip) { - // TODO - } - - @Override - public boolean isValidRegion(String region) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean isValidZone(String region, String zone) { - // TODO Auto-generated method stub - return true; - } - - @Override - public boolean isValidHost(String zone, String host) { - // TODO Auto-generated method stub - return true; - } - - @Override - public PartitionValidator getPartitionValidator() { - return new VCloudPartitionValidator(); - } - - @Override - public String createVolume(int sizeGB, String snapshotId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public String attachVolume(String instanceId, String volumeId, String deviceName) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void detachVolume(String instanceId, String volumeId) { - // TODO Auto-generated method stub - - } - - @Override - public void deleteVolume(String volumeId) { - // TODO Auto-generated method stub - - } - - @Override - public String getIaasDevice(String device) { - return device; - } - -} http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/AWSEC2PartitionValidator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/AWSEC2PartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/AWSEC2PartitionValidator.java deleted file mode 100644 index 3a2c0f1..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/AWSEC2PartitionValidator.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.stratos.cloud.controller.iaas.validators; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.stratos.cloud.controller.exception.InvalidIaasProviderException; -import org.apache.stratos.cloud.controller.exception.InvalidPartitionException; -import org.apache.stratos.cloud.controller.iaas.Iaas; -import org.apache.stratos.cloud.controller.domain.IaasProvider; -import org.apache.stratos.cloud.controller.util.CloudControllerConstants; -import org.apache.stratos.cloud.controller.util.CloudControllerUtil; -import org.apache.stratos.messaging.domain.topology.Scope; - -import java.util.Properties; - - -/** - * AWS-EC2 {@link PartitionValidator} implementation. - * - * - */ -public class AWSEC2PartitionValidator implements PartitionValidator { - - private static final Log log = LogFactory.getLog(AWSEC2PartitionValidator.class); - private IaasProvider iaasProvider; - private Iaas iaas; - - @Override - public IaasProvider validate(String partitionId, Properties properties) throws InvalidPartitionException { - // validate the existence of the region and zone properties. - try { - if (properties.containsKey(Scope.region.toString())) { - String region = properties.getProperty(Scope.region.toString()); - - if (iaasProvider.getImage() != null && !iaasProvider.getImage().contains(region)) { - - String msg = - "Invalid Partition Detected : " + partitionId + - " - Cause: Invalid Region: " + region; - log.error(msg); - throw new InvalidPartitionException(msg); - } - - iaas.isValidRegion(region); - - 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(region, zone); - updatedIaasProvider.setProperty(CloudControllerConstants.AVAILABILITY_ZONE, zone); - updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); - updatedIaas.setIaasProvider(updatedIaasProvider); - } - - updateOtherProperties(updatedIaasProvider, properties); - - return updatedIaasProvider; - - } else { - - return iaasProvider; - } - } catch (Exception ex) { - String msg = "Invalid Partition Detected : "+partitionId+". Cause: "+ex.getMessage(); - log.error(msg, ex); - throw new InvalidPartitionException(msg, ex); - } - - } - - private void updateOtherProperties(IaasProvider updatedIaasProvider, - Properties properties) { - Iaas updatedIaas; - try { - updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); - - for (Object property : properties.keySet()) { - if (property instanceof String) { - String key = (String) property; - updatedIaasProvider.setProperty(key, - properties.getProperty(key)); - if (log.isDebugEnabled()) { - log.debug("Added property " + key - + " to the IaasProvider."); - } - } - } - updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); - updatedIaas.setIaasProvider(updatedIaasProvider); - } catch (InvalidIaasProviderException ignore) { - } - - } - - @Override - public void setIaasProvider(IaasProvider iaas) { - this.iaasProvider = iaas; - this.iaas = iaas.getIaas(); - } - -} http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/CloudstackPartitionValidator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/CloudstackPartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/CloudstackPartitionValidator.java deleted file mode 100644 index 81e4bc2..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/CloudstackPartitionValidator.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.apache.stratos.cloud.controller.iaas.validators; - -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.iaas.Iaas; -import org.apache.stratos.cloud.controller.domain.IaasProvider; -import org.apache.stratos.cloud.controller.util.CloudControllerConstants; -import org.apache.stratos.cloud.controller.util.CloudControllerUtil; -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; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/DockerPartitionValidator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/DockerPartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/DockerPartitionValidator.java deleted file mode 100644 index 1551fa6..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/DockerPartitionValidator.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.stratos.cloud.controller.iaas.validators; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.stratos.cloud.controller.exception.InvalidIaasProviderException; -import org.apache.stratos.cloud.controller.exception.InvalidPartitionException; -import org.apache.stratos.cloud.controller.iaas.AWSEC2Iaas; -import org.apache.stratos.cloud.controller.iaas.Iaas; -import org.apache.stratos.cloud.controller.domain.IaasProvider; -import org.apache.stratos.cloud.controller.util.CloudControllerUtil; - -import java.util.Properties; - -/** - * Docker partition validator definition. - */ -public class DockerPartitionValidator implements PartitionValidator { - private static final Log log = LogFactory.getLog(AWSEC2Iaas.class); - - private IaasProvider iaasProvider; - - @Override - public void setIaasProvider(IaasProvider iaasProvider) { - this.iaasProvider = iaasProvider; - } - - @Override - public IaasProvider validate(String partitionId, Properties properties) throws InvalidPartitionException { - // in Docker case currently we only update the custom properties passed via Partitions, and - // no validation done as of now. - IaasProvider updatedIaasProvider = new IaasProvider(iaasProvider); - updateOtherProperties(updatedIaasProvider, properties); - return updatedIaasProvider; - } - - private void updateOtherProperties(IaasProvider updatedIaasProvider, - Properties properties) { - Iaas updatedIaas; - try { - updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); - - for (Object property : properties.keySet()) { - if (property instanceof String) { - String key = (String) property; - updatedIaasProvider.setProperty(key, - properties.getProperty(key)); - if (log.isDebugEnabled()) { - log.debug("Added property " + key - + " to the IaasProvider."); - } - } - } - updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); - updatedIaas.setIaasProvider(updatedIaasProvider); - } catch (InvalidIaasProviderException ignore) { - } - - } -} http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/GCEPartitionValidator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/GCEPartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/GCEPartitionValidator.java deleted file mode 100644 index 29d6523..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/GCEPartitionValidator.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.stratos.cloud.controller.iaas.validators; - -import java.util.Properties; - -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.iaas.Iaas; -import org.apache.stratos.cloud.controller.domain.IaasProvider; - - -/** - * The VCloud {@link PartitionValidator} implementation. - * - */ -public class GCEPartitionValidator implements PartitionValidator { - - private static final Log log = LogFactory.getLog(VCloudPartitionValidator.class); - private IaasProvider iaasProvider; - private Iaas iaas; - - @Override - public IaasProvider validate(String partitionId, Properties properties) throws InvalidPartitionException { - //TODO: implement real validation logic - return iaasProvider; - - } - - @Override - public void setIaasProvider(IaasProvider iaas) { - this.iaasProvider = iaas; - this.iaas = iaas.getIaas(); - } - -} http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/OpenstackNovaPartitionValidator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/OpenstackNovaPartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/OpenstackNovaPartitionValidator.java deleted file mode 100644 index 002c35e..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/OpenstackNovaPartitionValidator.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.stratos.cloud.controller.iaas.validators; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.stratos.cloud.controller.exception.InvalidIaasProviderException; -import org.apache.stratos.cloud.controller.exception.InvalidPartitionException; -import org.apache.stratos.cloud.controller.iaas.Iaas; -import org.apache.stratos.cloud.controller.domain.IaasProvider; -import org.apache.stratos.cloud.controller.util.CloudControllerConstants; -import org.apache.stratos.cloud.controller.util.CloudControllerUtil; -import org.apache.stratos.messaging.domain.topology.Scope; - -import java.util.Properties; - - -/** - * The Openstack Nova {@link PartitionValidator} implementation. - * - * - */ -public class OpenstackNovaPartitionValidator implements PartitionValidator { - - private static final Log log = LogFactory.getLog(OpenstackNovaPartitionValidator.class); - private IaasProvider iaasProvider; - private Iaas iaas; - - @Override - public IaasProvider validate(String partitionId, Properties properties) throws InvalidPartitionException { - try { - // validate the existence of the zone and hosts properties. - if (properties.containsKey(Scope.region.toString())) { - String region = properties.getProperty(Scope.region.toString()); - - if (iaasProvider.getImage() != null && !iaasProvider.getImage().contains(region)) { - - String msg = - "Invalid Partition Detected : " + partitionId + - " - Cause: Invalid Region: " + region; - log.error(msg); - throw new InvalidPartitionException(msg); - } - - iaas.isValidRegion(region); - - 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(region, zone); - - updatedIaasProvider.setProperty(CloudControllerConstants.AVAILABILITY_ZONE, zone); - updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); - updatedIaas.setIaasProvider(updatedIaasProvider); - } - - updateOtherProperties(updatedIaasProvider, properties); - - return updatedIaasProvider; - - } else { - - return iaasProvider; - } - } catch (Exception ex) { - String msg = "Invalid Partition Detected : "+partitionId+". Cause: "+ex.getMessage(); - log.error(msg, ex); - throw new InvalidPartitionException(msg, ex); - } - } - - private void updateOtherProperties(IaasProvider updatedIaasProvider, - Properties properties) { - Iaas updatedIaas; - try { - updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); - - for (Object property : properties.keySet()) { - if (property instanceof String) { - String key = (String) property; - updatedIaasProvider.setProperty(key, - properties.getProperty(key)); - if (log.isDebugEnabled()) { - log.debug("Added property " + key - + " to the IaasProvider."); - } - } - } - updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider); - updatedIaas.setIaasProvider(updatedIaasProvider); - } catch (InvalidIaasProviderException ignore) { - } - - } - - @Override - public void setIaasProvider(IaasProvider iaas) { - this.iaasProvider = iaas; - this.iaas = iaas.getIaas(); - } - -} http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/PartitionValidator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/PartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/PartitionValidator.java deleted file mode 100644 index 228b1de..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/PartitionValidator.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.stratos.cloud.controller.iaas.validators; - -import java.util.Properties; - -import org.apache.stratos.cloud.controller.exception.InvalidPartitionException; -import org.apache.stratos.cloud.controller.domain.IaasProvider; - -/** - * All the Partition Validators should implement this interface. - * - * - */ -public interface PartitionValidator { - - /** - * set the IaasProvider reference. - * @param iaas {@link IaasProvider} - */ - public void setIaasProvider(IaasProvider iaas); - - /** - * Validate the given properties for its existent in this partition. - * @param partitionId partition id. - * @param properties set of properties to be validated. - * @return cloned and modified {@link IaasProvider} which maps to the given partition. - * @throws InvalidPartitionException if at least one property is evaluated to be invalid. - */ - public IaasProvider validate(String partitionId, Properties properties) throws InvalidPartitionException; -} http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/VCloudPartitionValidator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/VCloudPartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/VCloudPartitionValidator.java deleted file mode 100644 index e8eb8cb..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaas/validators/VCloudPartitionValidator.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.stratos.cloud.controller.iaas.validators; - -import java.util.Properties; - -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.iaas.Iaas; -import org.apache.stratos.cloud.controller.domain.IaasProvider; - - -/** - * The VCloud {@link PartitionValidator} implementation. - * - */ -public class VCloudPartitionValidator implements PartitionValidator { - - @SuppressWarnings("unused") - private static final Log log = LogFactory.getLog(VCloudPartitionValidator.class); - private IaasProvider iaasProvider; - @SuppressWarnings("unused") - private Iaas iaas; - - @Override - public IaasProvider validate(String partitionId, Properties properties) throws InvalidPartitionException { - //TODO: implement real validation logic - return iaasProvider; - - } - - @Override - public void setIaasProvider(IaasProvider iaas) { - this.iaasProvider = iaas; - this.iaas = iaas.getIaas(); - } - -} http://git-wip-us.apache.org/repos/asf/stratos/blob/0984bcef/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java new file mode 100644 index 0000000..6519dfb --- /dev/null +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/AWSEC2Iaas.java @@ -0,0 +1,637 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.stratos.cloud.controller.iaases; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +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.util.ComputeServiceBuilderUtil; +import org.apache.stratos.cloud.controller.domain.IaasProvider; +import org.apache.stratos.cloud.controller.domain.NetworkInterface; +import org.apache.stratos.cloud.controller.util.CloudControllerConstants; +import org.apache.stratos.cloud.controller.util.CloudControllerUtil; +import org.apache.stratos.cloud.controller.iaases.validators.AWSEC2PartitionValidator; +import org.apache.stratos.cloud.controller.iaases.validators.PartitionValidator; +import org.jclouds.aws.ec2.AWSEC2Api; +import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions; +import org.jclouds.aws.ec2.features.AWSKeyPairApi; +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 org.jclouds.ec2.domain.Attachment; +import org.jclouds.ec2.domain.AvailabilityZoneInfo; +import org.jclouds.ec2.domain.KeyPair; +import org.jclouds.ec2.domain.PublicIpInstanceIdPair; +import org.jclouds.ec2.domain.Volume; +import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi; +import org.jclouds.ec2.features.ElasticBlockStoreApi; +import org.jclouds.ec2.features.ElasticIPAddressApi; +import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions; +import org.jclouds.ec2.options.DetachVolumeOptions; + +import java.util.*; + +public class AWSEC2Iaas extends Iaas { + + public AWSEC2Iaas(IaasProvider iaasProvider) { + super(iaasProvider); + } + + private static final Log log = LogFactory.getLog(AWSEC2Iaas.class); + private static final String SUCCESSFUL_LOG_LINE = "A key-pair is created successfully in "; + private static final String FAILED_LOG_LINE = "Key-pair is unable to create in "; + + @Override + public void buildComputeServiceAndTemplate() { + + // builds and sets Compute Service + ComputeServiceBuilderUtil.buildDefaultComputeService(getIaasProvider()); + // builds and sets Template + buildTemplate(); + + } + + public void buildTemplate() { + IaasProvider iaasInfo = getIaasProvider(); + if (iaasInfo.getComputeService() == null) { + String msg = "Compute service is null for IaaS provider: " + + iaasInfo.getName(); + log.fatal(msg); + throw new CloudControllerException(msg); + } + + TemplateBuilder templateBuilder = iaasInfo.getComputeService() + .templateBuilder(); + + // set image id specified + templateBuilder.imageId(iaasInfo.getImage()); + + if(!(iaasInfo instanceof IaasProvider)) { + templateBuilder.locationId(iaasInfo.getType()); + } + + if(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) { + Set<? extends Location> locations = iaasInfo.getComputeService().listAssignableLocations(); + for(Location location : locations) { + if(location.getScope().toString().equalsIgnoreCase(CloudControllerConstants.ZONE_ELEMENT) && + location.getId().equals(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE))) { + templateBuilder.locationId(location.getId()); + log.info("ZONE has been set as " + iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) + + " with id: " + location.getId()); + break; + } + } + } + + if (iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE) != null) { + // set instance type eg: m1.large + templateBuilder.hardwareId(iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE)); + } + + // build the Template + Template template = templateBuilder.build(); + + if(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) { + if(!template.getLocation().getId().equals(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE))) { + log.warn("couldn't find assignable ZONE of id :" + + iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) + " in the IaaS. " + + "Hence using the default location as " + template.getLocation().getScope().toString() + + " with the id " + template.getLocation().getId()); + } + } + + // 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 EC2 specific options + + + if (iaasInfo.getProperty(CloudControllerConstants.ASSOCIATE_PUBLIC_IP_ADDRESS) != null) { + boolean associatePublicIp = Boolean.parseBoolean(iaasInfo.getProperty( + CloudControllerConstants.ASSOCIATE_PUBLIC_IP_ADDRESS)); + if(associatePublicIp){ + template.getOptions().as(AWSEC2TemplateOptions.class) + .associatePublicIpAddress(); + } + } + + if (iaasInfo.getProperty(CloudControllerConstants.SUBNET_ID) != null) { + template.getOptions().as(AWSEC2TemplateOptions.class) + .subnetId(iaasInfo.getProperty(CloudControllerConstants.SUBNET_ID)); + } + + if (iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) { + template.getOptions().as(AWSEC2TemplateOptions.class) + .placementGroup(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE)); + } + + // security group names + if (iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUPS) != null) { + template.getOptions() + .as(AWSEC2TemplateOptions.class) + .securityGroups(iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUPS).split( + CloudControllerConstants.ENTRY_SEPARATOR)); + + } + + // ability to define tags + if (iaasInfo.getProperty(CloudControllerConstants.TAGS) != null) { + template.getOptions() + .as(AWSEC2TemplateOptions.class) + .tags(Arrays.asList(iaasInfo.getProperty(CloudControllerConstants.TAGS) + .split(CloudControllerConstants.ENTRY_SEPARATOR))); + + } + + // ability to define tags with Key-value pairs + Map<String, String> keyValuePairTagsMap = new HashMap<String, String>(); + + for (String propertyKey : iaasInfo.getProperties().keySet()){ + if(propertyKey.startsWith(CloudControllerConstants.TAGS_AS_KEY_VALUE_PAIRS_PREFIX)) { + keyValuePairTagsMap.put(propertyKey.substring(CloudControllerConstants.TAGS_AS_KEY_VALUE_PAIRS_PREFIX.length()), + iaasInfo.getProperties().get(propertyKey)); + template.getOptions() + .as(AWSEC2TemplateOptions.class) + .userMetadata(keyValuePairTagsMap); + } + + } + + + if (iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUP_IDS) != null) { + template.getOptions() + .as(AWSEC2TemplateOptions.class) + .securityGroupIds(iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUP_IDS) + .split(CloudControllerConstants.ENTRY_SEPARATOR)); + + } + + + if (iaasInfo.getProperty(CloudControllerConstants.KEY_PAIR) != null) { + template.getOptions().as(AWSEC2TemplateOptions.class) + .keyPair(iaasInfo.getProperty(CloudControllerConstants.KEY_PAIR)); + } + + + + if (iaasInfo.getNetworkInterfaces() != null) { + List<String> networks = new ArrayList<String>(iaasInfo.getNetworkInterfaces().length); + for (NetworkInterface ni:iaasInfo.getNetworkInterfaces()) { + networks.add(ni.getNetworkUuid()); + } + template.getOptions().as(AWSEC2TemplateOptions.class).networks(networks); + } + + // set Template + iaasInfo.setTemplate(template); + } + + @Override + public void setDynamicPayload() { + IaasProvider iaasInfo = getIaasProvider(); + if (iaasInfo.getTemplate() != null && iaasInfo.getPayload() != null) { + + iaasInfo.getTemplate().getOptions().as(AWSEC2TemplateOptions.class) + .userData(iaasInfo.getPayload()); + } + + } + + @Override + public synchronized boolean createKeyPairFromPublicKey(String region, String keyPairName, + String publicKey) { + + IaasProvider iaasInfo = getIaasProvider(); + + String ec2Msg = " ec2. Region: " + region + " - Key Pair Name: "; + + ComputeServiceContext context = iaasInfo.getComputeService() + .getContext(); + + AWSKeyPairApi keyPairApi = context.unwrapApi(AWSEC2Api.class).getKeyPairApiForRegion(region).get(); + + KeyPair keyPair = keyPairApi.importKeyPairInRegion(region, keyPairName, publicKey); + + if (keyPair != null) { + + iaasInfo.getTemplate().getOptions().as(AWSEC2TemplateOptions.class) + .keyPair(keyPair.getKeyName()); + + log.info(SUCCESSFUL_LOG_LINE + ec2Msg + keyPair.getKeyName()); + return true; + } + + log.error(FAILED_LOG_LINE + ec2Msg); + + return false; + } + + @Override + public synchronized String associateAddress(NodeMetadata node) { + + IaasProvider iaasInfo = getIaasProvider(); + + ComputeServiceContext context = iaasInfo.getComputeService() + .getContext(); + + ElasticIPAddressApi elasticIPAddressApi = context.unwrapApi(AWSEC2Api.class).getElasticIPAddressApi().get(); + String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); + + String ip = null; + + // first try to find an unassigned IP. + ArrayList<PublicIpInstanceIdPair> unassignedIps = Lists + .newArrayList(Iterables.filter(elasticIPAddressApi.describeAddressesInRegion(region, new String[0]), + new Predicate<PublicIpInstanceIdPair>() { + + @Override + public boolean apply(PublicIpInstanceIdPair arg0) { + return arg0.getInstanceId() == null; + } + + })); + + if (!unassignedIps.isEmpty()) { + // try to prevent multiple parallel launches from choosing the same + // ip. + Collections.shuffle(unassignedIps); + ip = Iterables.getLast(unassignedIps).getPublicIp(); + } + + // if no unassigned IP is available, we'll try to allocate an IP. + if (ip == null || ip.isEmpty()) { + try { + ip = elasticIPAddressApi + .allocateAddressInRegion(region); + log.info("Allocated ip [" + ip + "]"); + + } catch (Exception e) { + String msg = "Failed to allocate an IP address. All IP addresses are in use."; + log.error(msg, e); + throw new CloudControllerException(msg, e); + } + } + + String id = node.getProviderId(); + + // wait till the fixed IP address gets assigned - this is needed before + // we associate a + // public IP + + while (node.getPrivateAddresses() == null) { + CloudControllerUtil.sleep(1000); + } + + int retries = 0; + while (retries < 12 && !associatePublicIp(elasticIPAddressApi, region, ip, id)) { + + // wait for 5s + CloudControllerUtil.sleep(5000); + retries++; + } + + log.debug("Successfully associated an IP address " + ip + + " for node with id: " + node.getId()); + + return ip; + + } + + @Override + public String associatePredefinedAddress(NodeMetadata node, String ip) { + return ""; + } + + /** + * @param addressApi + * @param region + * @param ip + * @param id + */ + private boolean associatePublicIp(ElasticIPAddressApi addressApi, String region, + String ip, String id) { + try { + addressApi.associateAddressInRegion( + region, ip, id); + log.info("Successfully associated public IP "); + return true; + } catch (Exception e) { + log.debug("Exception in associating public IP " + e.getMessage()); + return false; + } + } + + @Override + public synchronized void releaseAddress(String ip) { + + IaasProvider iaasInfo = getIaasProvider(); + + ComputeServiceContext context = iaasInfo.getComputeService() + .getContext(); + ElasticIPAddressApi elasticIPAddressApi = context.unwrapApi(AWSEC2Api.class).getElasticIPAddressApi().get(); + String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); + + elasticIPAddressApi.disassociateAddressInRegion( + region, ip); + elasticIPAddressApi.releaseAddressInRegion(region, + ip); + } + + @Override + public boolean isValidRegion(String region) throws InvalidRegionException { + + IaasProvider iaasInfo = getIaasProvider(); + + if (region == null || iaasInfo == null) { + String msg = + "Region or IaaSProvider is null: region: " + region + " - IaaSProvider: " + + iaasInfo; + log.error(msg); + throw new InvalidRegionException(msg); + } + + ComputeServiceContext context = iaasInfo.getComputeService().getContext(); + Set<String> regions = context.unwrapApi(AWSEC2Api.class).getConfiguredRegions(); + for (String configuredRegion : regions) { + if (region.equalsIgnoreCase(configuredRegion)) { + if (log.isDebugEnabled()) { + log.debug("Found a matching region: " + region); + } + return true; + } + } + 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(); + + if (zone == null || iaasInfo == null) { + String msg = + "Zone or IaaSProvider is null: zone: " + zone + " - IaaSProvider: " + + iaasInfo; + log.error(msg); + throw new InvalidZoneException(msg); + } + ComputeServiceContext context = iaasInfo.getComputeService().getContext(); + AvailabilityZoneAndRegionApi zoneRegionApi = context.unwrapApi(AWSEC2Api.class). + getAvailabilityZoneAndRegionApiForRegion(region).get(); + + Set<AvailabilityZoneInfo> availabilityZones = + zoneRegionApi.describeAvailabilityZonesInRegion(region, + new DescribeAvailabilityZonesOptions[0]); + for (AvailabilityZoneInfo zoneInfo : availabilityZones) { + String configuredZone = zoneInfo.getZone(); + if (zone.equalsIgnoreCase(configuredZone)) { + if (log.isDebugEnabled()) { + log.debug("Found a matching zone: " + zone); + } + return true; + } + } + + String msg = "Invalid zone: " + zone +" in the region: "+region+ " and of 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 concept in EC2 + 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 AWSEC2PartitionValidator(); + } + + @Override + public String createVolume(int sizeGB, String snapshotId) { + IaasProvider iaasInfo = getIaasProvider(); + + ComputeServiceContext context = iaasInfo.getComputeService() + .getContext(); + + String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); + String zone = ComputeServiceBuilderUtil.extractZone(iaasInfo); + + if(region == null || zone == null) { + log.fatal("Cannot create a new volume in the [region] : "+region + +", [zone] : "+zone+" of Iaas : "+iaasInfo); + return null; + } + + ElasticBlockStoreApi blockStoreApi = context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get(); + + Volume volume; + if(StringUtils.isEmpty(snapshotId)){ + if(log.isDebugEnabled()){ + log.info("Creating a volume in the zone " + zone); + } + volume = blockStoreApi.createVolumeInAvailabilityZone(zone, sizeGB); + }else{ + if(log.isDebugEnabled()){ + log.info("Creating a volume in the zone " + zone + " from the shanpshot " + snapshotId); + } + volume = blockStoreApi.createVolumeFromSnapshotInAvailabilityZone(zone, snapshotId); + } + + + if (volume == null) { + log.fatal("Volume creation was unsuccessful. [region] : " + region + + ", [zone] : " + zone + " of Iaas : " + iaasInfo); + return null; + } + + log.info("Successfully created a new volume [id]: "+volume.getId() + +" in [region] : "+region+", [zone] : "+zone+" of Iaas : "+iaasInfo); + return volume.getId(); + } + + @Override + public String attachVolume(String instanceId, String volumeId, String deviceName) { + IaasProvider iaasInfo = getIaasProvider(); + + ComputeServiceContext context = iaasInfo.getComputeService() + .getContext(); + + String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); + String zone = ComputeServiceBuilderUtil.extractZone(iaasInfo); + String device = deviceName == null ? "/dev/sdh" : deviceName; + + if(region == null || zone == null) { + log.fatal("Cannot attach the volume [id]: "+volumeId+" in the [region] : "+region + +", [zone] : "+zone+" of Iaas : "+iaasInfo); + return null; + } + + ElasticBlockStoreApi blockStoreApi = context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get(); + + Volume.Status volumeStatus = this.getVolumeStatus(blockStoreApi, region, volumeId); + + if(log.isDebugEnabled()){ + log.debug("Volume " + volumeId + " is in state " + volumeStatus); + } + + while(volumeStatus != Volume.Status.AVAILABLE){ + try { + // TODO Use a proper mechanism to wait till volume becomes available. + Thread.sleep(1000); + volumeStatus = this.getVolumeStatus(blockStoreApi, region, volumeId); + if(log.isDebugEnabled()){ + log.debug("Volume " + volumeId + " is still NOT in AVAILABLE. Current State=" + volumeStatus); + } + } catch (InterruptedException e) { + // Ignoring the exception + } + } + if(log.isDebugEnabled()){ + log.debug("Volume " + volumeId + " became AVAILABLE"); + } + + Attachment attachment = blockStoreApi.attachVolumeInRegion(region, volumeId, instanceId, device); + + if (attachment == null) { + log.fatal("Volume [id]: "+volumeId+" attachment for instance [id]: "+instanceId + +" was unsuccessful. [region] : " + region + + ", [zone] : " + zone + " of Iaas : " + iaasInfo); + return null; + } + + log.info("Volume [id]: "+volumeId+" attachment for instance [id]: "+instanceId + +" was successful [status]: "+attachment.getStatus().value()+". [region] : " + region + + ", [zone] : " + zone + " of Iaas : " + iaasInfo); + return attachment.getStatus().value(); + } + + private Volume.Status getVolumeStatus(ElasticBlockStoreApi blockStoreApi, String region, String volumeId){ + Set<Volume> volumeDescriptions = blockStoreApi.describeVolumesInRegion(region, volumeId); + Iterator<Volume> it = volumeDescriptions.iterator(); + return it.next().getStatus(); + } + + @Override + public void detachVolume(String instanceId, String volumeId) { + IaasProvider iaasInfo = getIaasProvider(); + + ComputeServiceContext context = iaasInfo.getComputeService() + .getContext(); + + String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); + + if(region == null) { + log.fatal("Cannot detach the volume [id]: "+volumeId+" from the instance [id]: "+instanceId + +" of the [region] : "+region + +" of Iaas : "+iaasInfo); + return; + } + + ElasticBlockStoreApi blockStoreApi = context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get(); + + Set<Volume> volumeDescriptions = blockStoreApi.describeVolumesInRegion(region, volumeId); + Iterator<Volume> it = volumeDescriptions.iterator(); + + while(it.hasNext()){ + Volume.Status status = it.next().getStatus(); + + if(status == Volume.Status.AVAILABLE){ + log.warn(String.format("Volume %s is already in AVAILABLE state. Volume seems to be detached somehow", volumeId)); + return; + } + } + + blockStoreApi.detachVolumeInRegion(region, volumeId, true, DetachVolumeOptions.Builder.fromInstance(instanceId)); + + log.info("Detachment of Volume [id]: "+volumeId+" from instance [id]: "+instanceId + +" was successful. [region] : " + region + + " of Iaas : " + iaasInfo); + } + + @Override + public void deleteVolume(String volumeId) { + IaasProvider iaasInfo = getIaasProvider(); + + ComputeServiceContext context = iaasInfo.getComputeService() + .getContext(); + + String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); + + if(region == null) { + log.fatal("Cannot delete the volume [id]: "+volumeId+" of the [region] : "+region + +" of Iaas : "+iaasInfo); + return; + } + + ElasticBlockStoreApi blockStoreApi = context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get(); + blockStoreApi.deleteVolumeInRegion(region, volumeId); + + log.info("Deletion of Volume [id]: "+volumeId+" was successful. [region] : " + region + + " of Iaas : " + iaasInfo); + } + + @Override + /* + Converts the user defined volume device to Ec2 specific device. + For example /dev/sdf is converted to /dev/xvdf + */ + public String getIaasDevice(String device) { + String[] split = device.split("/"); + String x = split[split.length-1]; + StringBuilder ec2Device = new StringBuilder(); + ec2Device.append("/" + split[1]); + ec2Device.append("/xvd"); + ec2Device.append(x.charAt(x.length()-1)); + return ec2Device.toString(); + } + + +}
