http://git-wip-us.apache.org/repos/asf/stratos/blob/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsIaasUtil.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsIaasUtil.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsIaasUtil.java new file mode 100644 index 0000000..b361f5c --- /dev/null +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsIaasUtil.java @@ -0,0 +1,90 @@ +/* + * 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 org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.stratos.cloud.controller.domain.IaasProvider; +import org.apache.stratos.cloud.controller.exception.InvalidIaasProviderException; +import org.apache.stratos.cloud.controller.util.ComputeServiceBuilderUtil; +import org.jclouds.compute.ComputeService; + +import java.lang.reflect.Constructor; + +/** + * jclouds IaaS utility methods. + */ +public class JcloudsIaasUtil { + private static final Log log = LogFactory.getLog(JcloudsIaasUtil.class); + + public static void buildComputeServiceAndTemplate(IaasProvider iaasProvider) throws InvalidIaasProviderException { + if(iaasProvider.getImage() != null) { + buildComputeServiceAndTemplateFromImage(iaasProvider); + } else { + buildDefaultComputeService(iaasProvider); + } + } + + private static void buildComputeServiceAndTemplateFromImage(IaasProvider iaasProvider) throws InvalidIaasProviderException { + try { + JcloudsIaas iaas = (JcloudsIaas) iaasProvider.getIaas(); + iaas.buildComputeServiceAndTemplate(); + } catch (Exception e) { + String msg = "Could not build iaas of type: " + iaasProvider.getType(); + log.error(msg, e); + throw new InvalidIaasProviderException(msg, e); + } + } + + private static void buildDefaultComputeService(IaasProvider iaasProvider) throws InvalidIaasProviderException { + try { + ComputeService computeService = ComputeServiceBuilderUtil.buildDefaultComputeService(iaasProvider); + iaasProvider.setComputeService(computeService); + } catch (Exception e) { + String msg = "Unable to build the jclouds object for iaas " + + "of type: " + iaasProvider.getType(); + log.error(msg, e); + throw new InvalidIaasProviderException(msg, e); + } + } + + public static Iaas createIaasInstance(IaasProvider iaasProvider) + throws InvalidIaasProviderException { + try { + + if(iaasProvider.getClassName() == null) { + String msg = "You have not specified a class which represents the iaas of type: [" + + iaasProvider.getType() + "]."; + log.error(msg); + throw new InvalidIaasProviderException(msg); + } + + Constructor<?> c = Class.forName(iaasProvider.getClassName()).getConstructor(IaasProvider.class); + Iaas iaas = (Iaas) c.newInstance(iaasProvider); + return iaas; + } catch (Exception e) { + String msg = "Class [" + iaasProvider.getClassName() + + "] which represents the iaas of type: [" + + iaasProvider.getType() + "] has failed to instantiate."; + log.error(msg, e); + throw new InvalidIaasProviderException(msg, e); + } + } +}
http://git-wip-us.apache.org/repos/asf/stratos/blob/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsOpenstackIaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsOpenstackIaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsOpenstackIaas.java new file mode 100644 index 0000000..e16a074 --- /dev/null +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsOpenstackIaas.java @@ -0,0 +1,559 @@ +/* + * 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 java.util.LinkedHashSet; +import java.util.Set; +import java.util.concurrent.TimeoutException; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.stratos.cloud.controller.domain.IaasProvider; +import org.apache.stratos.cloud.controller.domain.NetworkInterface; +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.iaases.openstack.networking.NeutronNetworkingApi; +import org.apache.stratos.cloud.controller.iaases.openstack.networking.NovaNetworkingApi; +import org.apache.stratos.cloud.controller.iaases.openstack.networking.OpenstackNetworkingApi; +import org.apache.stratos.cloud.controller.iaases.validators.OpenstackNovaPartitionValidator; +import org.apache.stratos.cloud.controller.iaases.validators.PartitionValidator; +import org.apache.stratos.cloud.controller.util.CloudControllerConstants; +import org.apache.stratos.cloud.controller.util.ComputeServiceBuilderUtil; +import org.jclouds.compute.ComputeService; +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.openstack.nova.v2_0.NovaApi; +import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions; +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.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 com.google.common.base.Optional; + +public class JcloudsOpenstackIaas extends JcloudsIaas { + + private static final Log log = LogFactory.getLog(JcloudsOpenstackIaas.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 "; + + private OpenstackNetworkingApi openstackNetworkingApi; + + public JcloudsOpenstackIaas(IaasProvider iaasProvider) { + super(iaasProvider); + setOpenstackNetworkingApi(iaasProvider); + } + + private void setOpenstackNetworkingApi(IaasProvider iaasProvider) { + String openstackNetworkingProvider = iaasProvider.getProperty(CloudControllerConstants.OPENSTACK_NETWORKING_PROVIDER); + if (openstackNetworkingProvider != null && + openstackNetworkingProvider.equals(CloudControllerConstants.OPENSTACK_NEUTRON_NETWORKING)) { + if (log.isDebugEnabled()) { + String msg = String.format("Openstack networking provider is %s. Trying to instanstiate %s", + openstackNetworkingProvider, NeutronNetworkingApi.class.getName()); + log.debug(msg); + } + openstackNetworkingApi = new NeutronNetworkingApi(iaasProvider); + } else { + if (log.isDebugEnabled()) { + String msg = String.format("Openstack networking provider is %s. Hence trying to instanstiate %s", + openstackNetworkingProvider, NovaNetworkingApi.class.getName()); + log.debug(msg); + } + openstackNetworkingApi = new NovaNetworkingApi(iaasProvider); + } + } + + @Override + public void buildComputeServiceAndTemplate() { + // builds and sets Compute Service + ComputeService computeService = ComputeServiceBuilderUtil.buildDefaultComputeService(getIaasProvider()); + getIaasProvider().setComputeService(computeService); + + // builds and sets Template + buildTemplate(); + } + + public void buildTemplate() { + IaasProvider iaasProvider = getIaasProvider(); + + if (iaasProvider.getComputeService() == null) { + throw new CloudControllerException( + "Compute service is null for IaaS provider: " + + iaasProvider.getName()); + } + + TemplateBuilder templateBuilder = iaasProvider.getComputeService() + .templateBuilder(); + templateBuilder.imageId(iaasProvider.getImage()); + if(!(iaasProvider instanceof IaasProvider)) { + templateBuilder.locationId(iaasProvider.getType()); + } + + // to avoid creation of template objects in each and every time, we + // create all at once! + + String instanceType; + + // set instance type + if (((instanceType = iaasProvider.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(iaasProvider.getProperty(CloudControllerConstants.BLOCK_UNTIL_RUNNING) != null) { + blockUntilRunning = Boolean.parseBoolean(iaasProvider.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 (iaasProvider.getProperty(CloudControllerConstants.SECURITY_GROUPS) != null) { + template.getOptions() + .as(NovaTemplateOptions.class) + .securityGroupNames( + iaasProvider.getProperty(CloudControllerConstants.SECURITY_GROUPS).split( + CloudControllerConstants.ENTRY_SEPARATOR)); + } + + if (iaasProvider.getProperty(CloudControllerConstants.KEY_PAIR) != null) { + template.getOptions().as(NovaTemplateOptions.class) + .keyPairName(iaasProvider.getProperty(CloudControllerConstants.KEY_PAIR)); + } + + if (iaasProvider.getNetworkInterfaces() != null) { + Set<Network> novaNetworksSet = new LinkedHashSet<Network>(iaasProvider.getNetworkInterfaces().length); + for (NetworkInterface ni:iaasProvider.getNetworkInterfaces()) { + novaNetworksSet.add(Network.builder().networkUuid(ni.getNetworkUuid()).fixedIp(ni.getFixedIp()) + .portUuid(ni.getPortUuid()).build()); + } + template.getOptions().as(NovaTemplateOptions.class).novaNetworks(novaNetworksSet); + } + + if (iaasProvider.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) { + template.getOptions().as(NovaTemplateOptions.class) + .availabilityZone(iaasProvider.getProperty(CloudControllerConstants.AVAILABILITY_ZONE)); + } + + //TODO +// if (iaas.getProperty(CloudControllerConstants.HOST) != null) { +// template.getOptions().as(NovaTemplateOptions.class) +// .(CloudControllerConstants.HOST); +// } + + // set Template + iaasProvider.setTemplate(template); + } + + @Override + public void setDynamicPayload(byte[] payload) { + if (getIaasProvider().getTemplate() != null) { + getIaasProvider().getTemplate().getOptions().as(NovaTemplateOptions.class).userData(payload); + } + } + + @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) { + //TODO return the list of IP addresses once the topology changes is done + return openstackNetworkingApi.associateAddresses(node).iterator().next(); + } + + @Override + public synchronized String associatePredefinedAddress (NodeMetadata node, String ip) { + return openstackNetworkingApi.associatePredefinedAddress(node, ip); + } + + @Override + public synchronized void releaseAddress(String ip) { + openstackNetworkingApi.releaseAddress(ip); + } + + @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/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsVCloudIaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsVCloudIaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsVCloudIaas.java new file mode 100644 index 0000000..9f87dd4 --- /dev/null +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/JcloudsVCloudIaas.java @@ -0,0 +1,261 @@ +/* + * 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 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.iaases.validators.PartitionValidator; +import org.apache.stratos.cloud.controller.iaases.validators.VCloudPartitionValidator; +import org.jclouds.compute.ComputeService; +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 JcloudsVCloudIaas extends JcloudsIaas { + + + private static final Log log = LogFactory.getLog(JcloudsVCloudIaas.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 JcloudsVCloudIaas(IaasProvider iaasProvider) { + super(iaasProvider); + } + + @Override + public void buildComputeServiceAndTemplate() { + // builds and sets Compute Service + ComputeService computeService = ComputeServiceBuilderUtil.buildDefaultComputeService(getIaasProvider()); + getIaasProvider().setComputeService(computeService); + + // 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(byte[] payload) { + // in vCloud case we need to run a script + IaasProvider iaasProvider = getIaasProvider(); + + if (iaasProvider.getTemplate() == null) { + if (log.isDebugEnabled()) { + log.debug("Payload for vCloud not found"); + } + return; + } + + String shellType = iaasProvider.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 payloadStr = new String(payload); + + if (log.isDebugEnabled()) { + log.debug(String.format("Payload '%s' will be used for vCloud Customization script", payload)); + } + + Template template = iaasProvider.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, payloadStr); + + 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/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java deleted file mode 100644 index 2740397..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/OpenstackNovaIaas.java +++ /dev/null @@ -1,567 +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.iaases; - -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.concurrent.TimeoutException; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.stratos.cloud.controller.domain.IaasProvider; -import org.apache.stratos.cloud.controller.domain.NetworkInterface; -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.iaases.openstack.networking.NeutronNetworkingApi; -import org.apache.stratos.cloud.controller.iaases.openstack.networking.NovaNetworkingApi; -import org.apache.stratos.cloud.controller.iaases.openstack.networking.OpenstackNetworkingApi; -import org.apache.stratos.cloud.controller.iaases.validators.OpenstackNovaPartitionValidator; -import org.apache.stratos.cloud.controller.iaases.validators.PartitionValidator; -import org.apache.stratos.cloud.controller.util.CloudControllerConstants; -import org.apache.stratos.cloud.controller.util.ComputeServiceBuilderUtil; -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.openstack.nova.v2_0.NovaApi; -import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions; -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.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 com.google.common.base.Optional; - -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 "; - - private OpenstackNetworkingApi openstackNetworkingApi; - - public OpenstackNovaIaas(IaasProvider iaasProvider) { - super(iaasProvider); - setOpenstackNetworkingApi(iaasProvider); - } - - private void setOpenstackNetworkingApi(IaasProvider iaasProvider) { - String openstackNetworkingProvider = iaasProvider.getProperty(CloudControllerConstants.OPENSTACK_NETWORKING_PROVIDER); - if (openstackNetworkingProvider != null && - openstackNetworkingProvider.equals(CloudControllerConstants.OPENSTACK_NEUTRON_NETWORKING)) { - if (log.isDebugEnabled()) { - String msg = String.format("Openstack networking provider is %s. Trying to instanstiate %s", - openstackNetworkingProvider, NeutronNetworkingApi.class.getName()); - log.debug(msg); - } - openstackNetworkingApi = new NeutronNetworkingApi(iaasProvider); - } else { - if (log.isDebugEnabled()) { - String msg = String.format("Openstack networking provider is %s. Hence trying to instanstiate %s", - openstackNetworkingProvider, NovaNetworkingApi.class.getName()); - log.debug(msg); - } - openstackNetworkingApi = new NovaNetworkingApi(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) { - //TODO return the list of IP addresses once the topology changes is done - return openstackNetworkingApi.associateAddresses(node).iterator().next(); - } - - @Override - public synchronized String associatePredefinedAddress (NodeMetadata node, String ip) { - return openstackNetworkingApi.associatePredefinedAddress(node, ip); - } - - @Override - public synchronized void releaseAddress(String ip) { - openstackNetworkingApi.releaseAddress(ip); - } - - @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/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/VCloudIaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/VCloudIaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/VCloudIaas.java deleted file mode 100644 index 6e10628..0000000 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/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.iaases; - -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.iaases.validators.PartitionValidator; -import org.apache.stratos.cloud.controller.iaases.validators.VCloudPartitionValidator; -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/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockIPAddressPool.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockIPAddressPool.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockIPAddressPool.java new file mode 100644 index 0000000..610c00b --- /dev/null +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockIPAddressPool.java @@ -0,0 +1,99 @@ +/* + * 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.mock; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.stratos.cloud.controller.registry.RegistryManager; +import org.wso2.carbon.registry.core.exceptions.RegistryException; + +import java.io.Serializable; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Mock IP address pool is a singleton class for managing private and public IP addresses. + */ +public class MockIPAddressPool { + private static final Log log = LogFactory.getLog(MockIPAddressPool.class); + private static final String MOCK_IAAS_PRIVATE_IP_SEQUENCE = "/mock/iaas/private-ip-sequence"; + private static final String MOCK_IAAS_PUBLIC_IP_SEQUENCE = "/mock/iaas/public-ip-sequence"; + private static final String PRIVATE_IP_PREFIX = "10.0.0."; + private static final String PUBLIC_IP_PREFIX = "20.0.0."; + + private static volatile MockIPAddressPool instance; + + private AtomicInteger privateIpSequence; + private AtomicInteger publicIpSequence; + + private MockIPAddressPool() { + privateIpSequence = readFromRegistry(MOCK_IAAS_PRIVATE_IP_SEQUENCE); + if (privateIpSequence == null) { + privateIpSequence = new AtomicInteger(); + } + + publicIpSequence = readFromRegistry(MOCK_IAAS_PUBLIC_IP_SEQUENCE); + if (publicIpSequence == null) { + publicIpSequence = new AtomicInteger(); + } + } + + public static MockIPAddressPool getInstance() { + if (instance == null) { + synchronized (MockIPAddressPool.class) { + if (instance == null) { + instance = new MockIPAddressPool(); + } + } + } + return instance; + } + + public String getNextPrivateIpAddress() { + int nextSequence = privateIpSequence.incrementAndGet(); + String ipAddress = PRIVATE_IP_PREFIX + nextSequence; + persistInRegistry(MOCK_IAAS_PRIVATE_IP_SEQUENCE, privateIpSequence); + if (log.isInfoEnabled()) { + log.info("Mock private IP address allocated: " + ipAddress); + } + return ipAddress; + } + + public String getNextPublicIpAddress() { + int nextSequence = publicIpSequence.incrementAndGet(); + String ipAddress = PUBLIC_IP_PREFIX + nextSequence; + persistInRegistry(MOCK_IAAS_PRIVATE_IP_SEQUENCE, publicIpSequence); + if (log.isInfoEnabled()) { + log.info("Mock public IP address allocated: " + ipAddress); + } + return ipAddress; + } + + private void persistInRegistry(String resourcePath, Serializable serializable) { + try { + RegistryManager.getInstance().persist(resourcePath, serializable); + } catch (RegistryException e) { + log.error(String.format("Could not persist mock iaas ip sequence [%s] in registry", resourcePath), e); + } + } + + private AtomicInteger readFromRegistry(String resourcePath) { + return (AtomicInteger) RegistryManager.getInstance().read(resourcePath); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockIaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockIaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockIaas.java new file mode 100644 index 0000000..82d6c59 --- /dev/null +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockIaas.java @@ -0,0 +1,176 @@ +/* + * 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.mock; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.stratos.cloud.controller.domain.ClusterContext; +import org.apache.stratos.cloud.controller.domain.IaasProvider; +import org.apache.stratos.cloud.controller.domain.MemberContext; +import org.apache.stratos.cloud.controller.domain.Partition; +import org.apache.stratos.cloud.controller.exception.*; +import org.apache.stratos.cloud.controller.iaases.Iaas; +import org.apache.stratos.cloud.controller.iaases.validators.PartitionValidator; +import org.apache.stratos.cloud.controller.registry.RegistryManager; +import org.apache.stratos.common.threading.StratosThreadPool; +import org.jclouds.compute.domain.NodeMetadata; +import org.wso2.carbon.registry.core.exceptions.RegistryException; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; + +/** + * Created by imesh on 12/6/14. + */ +public class MockIaas extends Iaas { + + private static final Log log = LogFactory.getLog(MockIaas.class); + private static final String MOCK_IAAS_MEMBERS = "/mock/iaas/members"; + + private ExecutorService executorService; + private MockPartitionValidator partitionValidator; + private ConcurrentHashMap<String, MockMember> membersMap; + + public MockIaas(IaasProvider iaasProvider) { + super(iaasProvider); + executorService = StratosThreadPool.getExecutorService("MOCK_IAAS_THREAD_EXECUTOR", 100); + partitionValidator = new MockPartitionValidator(); + membersMap = readFromRegistry(); + if(membersMap != null) { + // Start existing members + for(MockMember mockMember : membersMap.values()) { + executorService.submit(mockMember); + } + } else { + // No members found in registry, create new map + membersMap = new ConcurrentHashMap<String, MockMember>(); + } + } + + @Override + public void initialize() { + } + + @Override + public NodeMetadata createInstance(ClusterContext clusterContext, MemberContext memberContext) { + // Create mock member instance + MockMemberContext mockMemberContext = new MockMemberContext(clusterContext.getCartridgeType(), + clusterContext.getClusterId(), memberContext.getMemberId(), memberContext.getNetworkPartitionId(), + memberContext.getPartition().getId(), memberContext.getInstanceId()); + MockMember mockMember = new MockMember(mockMemberContext); + membersMap.put(mockMember.getMockMemberContext().getMemberId(), mockMember); + executorService.submit(mockMember); + + // Prepare node metadata + MockNodeMetadata nodeMetadata = new MockNodeMetadata(); + nodeMetadata.setId(UUID.randomUUID().toString()); + + // Persist changes + persistInRegistry(); + + return nodeMetadata; + } + + private void persistInRegistry() { + try { + RegistryManager.getInstance().persist(MOCK_IAAS_MEMBERS, membersMap); + } catch (RegistryException e) { + log.error("Could not persist mock iaas members in registry", e); + }; + } + + private ConcurrentHashMap<String, MockMember> readFromRegistry() { + return (ConcurrentHashMap<String, MockMember>) RegistryManager.getInstance().read(MOCK_IAAS_MEMBERS); + } + + @Override + public void allocateIpAddress(String clusterId, MemberContext memberContext, Partition partition, + String cartridgeType, NodeMetadata node) { + // Allocate mock ip addresses + memberContext.setPrivateIpAddress(MockIPAddressPool.getInstance().getNextPrivateIpAddress()); + memberContext.setPublicIpAddress(MockIPAddressPool.getInstance().getNextPublicIpAddress()); + } + + @Override + public void releaseAddress(String ip) { + + } + + @Override + public boolean isValidRegion(String region) throws InvalidRegionException { + return true; + } + + @Override + public boolean isValidZone(String region, String zone) throws InvalidZoneException, InvalidRegionException { + return true; + } + + @Override + public boolean isValidHost(String zone, String host) throws InvalidHostException { + return true; + } + + @Override + public PartitionValidator getPartitionValidator() { + return partitionValidator; + } + + @Override + public String createVolume(int sizeGB, String snapshotId) { + return null; + } + + @Override + public String attachVolume(String instanceId, String volumeId, String deviceName) { + return null; + } + + @Override + public void detachVolume(String instanceId, String volumeId) { + + } + + @Override + public void deleteVolume(String volumeId) { + + } + + @Override + public String getIaasDevice(String device) { + return null; + } + + @Override + public void setDynamicPayload(byte[] payload) { + + } + + @Override + public void terminateInstance(MemberContext memberContext) throws InvalidCartridgeTypeException, InvalidMemberException { + MockMember mockMember = membersMap.get(memberContext.getMemberId()); + if(mockMember != null) { + mockMember.terminate(); + membersMap.remove(memberContext.getMemberId()); + } + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockMember.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockMember.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockMember.java new file mode 100644 index 0000000..898de35 --- /dev/null +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockMember.java @@ -0,0 +1,85 @@ +/* + * 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.mock; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.stratos.cloud.controller.iaases.mock.statistics.MockHealthStatisticsNotifier; + +import java.io.Serializable; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +/** + * Mock member definition. + */ +public class MockMember implements Runnable, Serializable { + + private static final Log log = LogFactory.getLog(MockMember.class); + private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + private MockMemberContext mockMemberContext; + private boolean terminated; + + public MockMember(MockMemberContext mockMemberContext) { + this.mockMemberContext = mockMemberContext; + } + + @Override + public void run() { + MockMemberEventPublisher.publishInstanceStartedEvent(mockMemberContext); + sleep(5000); + MockMemberEventPublisher.publishInstanceActivatedEvent(mockMemberContext); + + + if (log.isInfoEnabled()) { + log.info("Starting health statistics notifier"); + } + final ScheduledFuture<?> scheduledFuture = scheduler.scheduleAtFixedRate( + new MockHealthStatisticsNotifier(mockMemberContext), 15, 15, TimeUnit.SECONDS); + + if (log.isInfoEnabled()) { + log.info("Health statistics notifier started"); + } + + while(!terminated) { + sleep(1000); + } + } + + private void sleep(long time) { + try { + Thread.sleep(time); + } catch (InterruptedException ignore) { + terminate(); + } + } + + public MockMemberContext getMockMemberContext() { + return mockMemberContext; + } + + public void terminate() { + terminated = true; + scheduler.shutdownNow(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/2ec3ff0e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockMemberContext.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockMemberContext.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockMemberContext.java new file mode 100644 index 0000000..7189d11 --- /dev/null +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/mock/MockMemberContext.java @@ -0,0 +1,68 @@ +/* + * 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.mock; + +import java.io.Serializable; + +/** + * Mock member context. + */ +public class MockMemberContext implements Serializable { + private final String serviceName; + private final String clusterId; + private final String memberId; + private final String networkPartitionId; + private final String partitionId; + private final String instanceId; + + public MockMemberContext(String serviceName, String clusterId, String memberId, + String networkPartitionId, String partitionId, String instanceId) { + this.serviceName = serviceName; + this.clusterId = clusterId; + this.memberId = memberId; + this.networkPartitionId = networkPartitionId; + this.partitionId = partitionId; + this.instanceId = instanceId; + } + + public String getServiceName() { + return serviceName; + } + + public String getClusterId() { + return clusterId; + } + + public String getMemberId() { + return memberId; + } + + public String getNetworkPartitionId() { + return networkPartitionId; + } + + public String getPartitionId() { + return partitionId; + } + + public String getInstanceId() { + return instanceId; + } +}
