Repository: incubator-stratos Updated Branches: refs/heads/master a3fae8e90 -> cbf7c38f0
fixing https://issues.apache.org/jira/browse/STRATOS-493 - patch from Martin Eppel Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/cbf7c38f Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/cbf7c38f Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/cbf7c38f Branch: refs/heads/master Commit: cbf7c38f05399af1fe611be337d2c989d4f04b10 Parents: a3fae8e Author: Martin Eppel <[email protected]> Authored: Wed Mar 26 15:45:37 2014 +0530 Committer: Nirmal Fernando <[email protected]> Committed: Wed Mar 26 15:45:37 2014 +0530 ---------------------------------------------------------------------- .../cloud/controller/iaases/AWSEC2Iaas.java | 5 ++ .../controller/iaases/OpenstackNovaIaas.java | 94 ++++++++++++++++++++ .../cloud/controller/iaases/VCloudIaas.java | 5 ++ .../impl/CloudControllerServiceImpl.java | 86 ++++++++++++++---- .../cloud/controller/interfaces/Iaas.java | 10 +++ .../util/CloudControllerConstants.java | 2 + 6 files changed, 186 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cbf7c38f/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 index d536672..0702ace 100644 --- 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 @@ -309,6 +309,11 @@ public class AWSEC2Iaas extends Iaas { return ip; } + + @Override + public String associatePredefinedAddress(NodeMetadata node, String ip) { + return ""; + } /** * @param addressApi http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cbf7c38f/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 index e7ee43f..6a5d221 100644 --- 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 @@ -297,6 +297,100 @@ public class OpenstackNovaIaas extends Iaas { 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(); + + @SuppressWarnings("deprecation") + NovaApi novaClient = context.unwrap(NovaApiMetadata.CONTEXT_TOKEN).getApi(); + String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo); + + FloatingIPApi floatingIp = novaClient.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("penstackNovaIaas:associatePredefinedAddress:iterating over available floatingip:" + fip); + } + if (ip.equals(fip.getIp())) { + if(log.isDebugEnabled()) { + log.debug("OpenstackNovaIaas:associatePredefinedAddress:floating ip in use:" + fip + " /ip:" + 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) { http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cbf7c38f/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 index 56618b7..9332d7f 100644 --- 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 @@ -198,6 +198,11 @@ public class VCloudIaas extends Iaas { } @Override + public String associatePredefinedAddress(NodeMetadata node, String ip) { + return ""; + } + + @Override public void releaseAddress(String ip) { // TODO } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cbf7c38f/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java index 61187d6..adff085 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java @@ -48,6 +48,8 @@ import java.util.*; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; +import com.google.common.net.InetAddresses; + /** * Cloud Controller Service is responsible for starting up new server instances, * terminating already started instances, providing pending instance count etc. @@ -208,7 +210,11 @@ public class CloudControllerServiceImpl implements CloudControllerService { @Override public MemberContext startInstance(MemberContext memberContext) throws IllegalArgumentException, - UnregisteredCartridgeException, InvalidIaasProviderException, IllegalStateException { + UnregisteredCartridgeException, InvalidIaasProviderException { + + if(log.isDebugEnabled()) { + log.debug("CloudControllerServiceImpl:startInstance"); + } if (memberContext == null) { String msg = "Instance start-up failed. Member is null."; @@ -219,7 +225,9 @@ public class CloudControllerServiceImpl implements CloudControllerService { String clusterId = memberContext.getClusterId(); Partition partition = memberContext.getPartition(); - log.debug("Received an instance spawn request : " + memberContext.toString()); + if(log.isDebugEnabled()) { + log.debug("Received an instance spawn request : " + memberContext.toString()); + } ComputeService computeService = null; Template template = null; @@ -571,23 +579,64 @@ public class CloudControllerServiceImpl implements CloudControllerService { String autoAssignIpProp = iaasProvider.getProperty(CloudControllerConstants.AUTO_ASSIGN_IP_PROPERTY); - - // reset ip - String ip = ""; + + String pre_defined_ip = + iaasProvider.getProperty(CloudControllerConstants.FLOATING_IP_PROPERTY); + + // reset ip + String ip = ""; + // default behavior is autoIpAssign=false if (autoAssignIpProp == null || (autoAssignIpProp != null && autoAssignIpProp.equals("false"))) { - - Iaas iaas = iaasProvider.getIaas(); - // allocate an IP address - manual IP assigning mode - ip = iaas.associateAddress(node); - - if (ip != null) { - memberContext.setAllocatedIpAddress(ip); - log.info("Allocated an ip address: " - + memberContext.toString()); - } - } + + // check if floating ip is well defined in cartridge definition + if (pre_defined_ip != null) { + if (isValidIpAddress(pre_defined_ip)) { + if(log.isDebugEnabled()) { + log.debug("CloudControllerServiceImpl:IpAllocator:pre_defined_ip: invoking associatePredefinedAddress" + pre_defined_ip); + } + Iaas iaas = iaasProvider.getIaas(); + ip = iaas.associatePredefinedAddress(node, pre_defined_ip); + + if (ip == null || "".equals(ip) || !pre_defined_ip.equals(ip)) { + // throw exception and stop instance creation + String msg = "Error occurred while allocating predefined floating ip address: " + pre_defined_ip + + " / allocated ip:" + ip + + " - terminating node:" + memberContext.toString(); + log.error(msg); + // terminate instance + terminate(iaasProvider, + node.getId(), memberContext); + throw new CloudControllerException(msg); + } + } else { + String msg = "Invalid floating ip address configured: " + pre_defined_ip + + " - terminating node:" + memberContext.toString(); + log.error(msg); + // terminate instance + terminate(iaasProvider, + node.getId(), memberContext); + throw new CloudControllerException(msg); + } + + } else { + if(log.isDebugEnabled()) { + log.debug("CloudControllerServiceImpl:IpAllocator:no (valid) predefined floating ip configured, " + pre_defined_ip + + ", selecting available one from pool"); + } + Iaas iaas = iaasProvider.getIaas(); + // allocate an IP address - manual IP assigning mode + ip = iaas.associateAddress(node); + + if (ip != null) { + memberContext.setAllocatedIpAddress(ip); + log.info("Allocated an ip address: " + + memberContext.toString()); + } + } + } + // public ip if (node.getPublicAddresses() != null && @@ -639,6 +688,11 @@ public class CloudControllerServiceImpl implements CloudControllerService { } } + + private boolean isValidIpAddress (String ip) { + boolean isValid = InetAddresses.isInetAddress(ip); + return isValid; + } @Override public void terminateAllInstances(String clusterId) throws IllegalArgumentException, InvalidClusterException { http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cbf7c38f/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/Iaas.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/Iaas.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/Iaas.java index f45d32e..56be59c 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/Iaas.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/Iaas.java @@ -71,6 +71,16 @@ public abstract class Iaas { public abstract String associateAddress(NodeMetadata node); /** + * This will obtain a predefined IP address and associate that IP with this node, if ip is already in use allocate ip from pool + * (through associateAddress()) + * @param node Node to be associated with an IP. + * @ip preallocated floating Ip + * @return associated public IP. + */ + + abstract public String associatePredefinedAddress(NodeMetadata node, String ip); + + /** * This will deallocate/release the given IP address back to pool. * @param iaasInfo corresponding {@link IaasProvider} * @param ip public IP address to be released. http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/cbf7c38f/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java index 42c30d9..0418078 100644 --- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java +++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerConstants.java @@ -140,6 +140,8 @@ public final class CloudControllerConstants { public static final String AMQP_INITIAL_CONTEXT_FACTORY_PROPERTY = "amqpInitialContextFactory"; public static final String AMQP_TOPIC_CONNECTION_FACTORY_PROPERTY = "amqpTopicConnectionFactory"; public static final String INSTANCE_TOPIC = "instance-status"; + // pre define a floating ip + public static final String FLOATING_IP_PROPERTY = "floatingIp"; /**
