stratos-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From im...@apache.org
Subject [1/3] stratos git commit: Simplifying cloud controller service implementation
Date Fri, 05 Dec 2014 13:54:19 GMT
Repository: stratos
Updated Branches:
  refs/heads/master 3bd20e5ee -> 24ba6982f


http://git-wip-us.apache.org/repos/asf/stratos/blob/24ba6982/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/CloudControllerServiceUtil.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/CloudControllerServiceUtil.java
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/CloudControllerServiceUtil.java
new file mode 100644
index 0000000..056d991
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/CloudControllerServiceUtil.java
@@ -0,0 +1,144 @@
+/*
+ * 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.services.impl;
+
+import com.google.common.net.InetAddresses;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.context.CloudControllerContext;
+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.Volume;
+import org.apache.stratos.cloud.controller.exception.CloudControllerException;
+import org.apache.stratos.cloud.controller.exception.InvalidIaasProviderException;
+import org.apache.stratos.cloud.controller.iaases.Iaas;
+import org.apache.stratos.cloud.controller.messaging.publisher.CartridgeInstanceDataPublisher;
+import org.apache.stratos.cloud.controller.messaging.topology.TopologyBuilder;
+import org.apache.stratos.cloud.controller.util.CloudControllerUtil;
+import org.apache.stratos.messaging.domain.topology.MemberStatus;
+import org.jclouds.rest.ResourceNotFoundException;
+
+/**
+ * Cloud controller service utility methods.
+ */
+public class CloudControllerServiceUtil {
+
+    private static final Log log = LogFactory.getLog(CloudControllerServiceUtil.class);
+
+    /**
+     * A helper method to terminate an instance.
+     *
+     * @param iaasProvider
+     * @param ctxt
+     * @param nodeId
+     * @return will return the IaaSProvider
+     */
+    public static IaasProvider terminate(IaasProvider iaasProvider,
+                                   String nodeId, MemberContext ctxt) {
+        Iaas iaas = iaasProvider.getIaas();
+        if (iaas == null) {
+
+            try {
+                iaas = CloudControllerUtil.getIaas(iaasProvider);
+            } catch (InvalidIaasProviderException e) {
+                String msg =
+                        "Instance termination failed. " + ctxt.toString() +
+                                ". Cause: Unable to build Iaas of this " + iaasProvider.toString();
+                log.error(msg, e);
+                throw new CloudControllerException(msg, e);
+            }
+
+        }
+
+        //detach volumes if any
+        detachVolume(iaasProvider, ctxt);
+
+        // destroy the node
+        iaasProvider.getComputeService().destroyNode(nodeId);
+
+        // release allocated IP address
+        if (ctxt.getAllocatedIpAddress() != null) {
+            iaas.releaseAddress(ctxt.getAllocatedIpAddress());
+        }
+
+        if (log.isDebugEnabled()) {
+            log.debug("Member is terminated: " + ctxt.toString());
+        } else if (log.isInfoEnabled()) {
+            log.info("Member with id " + ctxt.getMemberId() + " is terminated");
+        }
+        return iaasProvider;
+    }
+
+    private static void detachVolume(IaasProvider iaasProvider, MemberContext ctxt) {
+        String clusterId = ctxt.getClusterId();
+        ClusterContext clusterCtxt = CloudControllerContext.getInstance().getClusterContext(clusterId);
+        if (clusterCtxt.getVolumes() != null) {
+            for (Volume volume : clusterCtxt.getVolumes()) {
+                try {
+                    String volumeId = volume.getId();
+                    if (volumeId == null) {
+                        return;
+                    }
+                    Iaas iaas = iaasProvider.getIaas();
+                    iaas.detachVolume(ctxt.getInstanceId(), volumeId);
+                } catch (ResourceNotFoundException ignore) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(ignore);
+                    }
+                }
+            }
+        }
+    }
+
+    public static void logTermination(MemberContext memberContext) {
+
+        if (memberContext == null) {
+            return;
+        }
+
+        String partitionId = memberContext.getPartition() == null ? null : memberContext.getPartition().getId();
+
+        //updating the topology
+        TopologyBuilder.handleMemberTerminated(memberContext.getCartridgeType(),
+                memberContext.getClusterId(), memberContext.getNetworkPartitionId(),
+                partitionId, memberContext.getMemberId());
+
+        //publishing data
+        CartridgeInstanceDataPublisher.publish(memberContext.getMemberId(),
+                partitionId,
+                memberContext.getNetworkPartitionId(),
+                memberContext.getClusterId(),
+                memberContext.getCartridgeType(),
+                MemberStatus.Terminated.toString(),
+                null);
+
+        // update data holders
+        CloudControllerContext.getInstance().removeMemberContext(memberContext.getMemberId(),
memberContext.getClusterId());
+
+        // persist
+        CloudControllerContext.getInstance().persist();
+    }
+
+    public static boolean isValidIpAddress(String ip) {
+        boolean isValid = InetAddresses.isInetAddress(ip);
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/24ba6982/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/InstanceCreator.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/InstanceCreator.java
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/InstanceCreator.java
new file mode 100644
index 0000000..033dc6f
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/InstanceCreator.java
@@ -0,0 +1,289 @@
+/*
+ * 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.services.impl;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.context.CloudControllerContext;
+import org.apache.stratos.cloud.controller.domain.*;
+import org.apache.stratos.cloud.controller.exception.CloudControllerException;
+import org.apache.stratos.cloud.controller.iaases.Iaas;
+import org.apache.stratos.cloud.controller.messaging.publisher.CartridgeInstanceDataPublisher;
+import org.apache.stratos.cloud.controller.messaging.topology.TopologyBuilder;
+import org.apache.stratos.cloud.controller.util.CloudControllerConstants;
+import org.apache.stratos.messaging.domain.topology.MemberStatus;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.domain.Template;
+
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+
+/**
+ * Instance creator runnable.
+ */
+public class InstanceCreator implements Runnable {
+
+    private static final Log log = LogFactory.getLog(InstanceCreator.class);
+
+    private MemberContext memberContext;
+    private IaasProvider iaasProvider;
+    private String cartridgeType;
+
+    public InstanceCreator(MemberContext memberContext, IaasProvider iaasProvider,
+                           String cartridgeType) {
+        this.memberContext = memberContext;
+        this.iaasProvider = iaasProvider;
+        this.cartridgeType = cartridgeType;
+    }
+
+    @Override
+    public void run() {
+        Lock lock = null;
+        try {
+            lock = CloudControllerContext.getInstance().acquireMemberContextWriteLock();
+
+            String clusterId = memberContext.getClusterId();
+            Partition partition = memberContext.getPartition();
+            ClusterContext ctxt = CloudControllerContext.getInstance().getClusterContext(clusterId);
+            Iaas iaas = iaasProvider.getIaas();
+            String publicIp = null;
+
+            NodeMetadata node = null;
+            // generate the group id from domain name and sub domain name.
+            // Should have lower-case ASCII letters, numbers, or dashes.
+            // Should have a length between 3-15
+            String str = clusterId.length() > 10 ? clusterId.substring(0, 10) : clusterId.substring(0,
clusterId.length());
+            String group = str.replaceAll("[^a-z0-9-]", "");
+
+            try {
+                ComputeService computeService = iaasProvider.getComputeService();
+                Template template = iaasProvider.getTemplate();
+
+                if (log.isDebugEnabled()) {
+                    log.debug("Cloud Controller is delegating request to start an instance
for "
+                            + memberContext + " to Jclouds layer.");
+                }
+                // create and start a node
+                Set<? extends NodeMetadata> nodes = computeService
+                        .createNodesInGroup(group, 1, template);
+                node = nodes.iterator().next();
+                if (log.isDebugEnabled()) {
+                    log.debug("Cloud Controller received a response for the request to start
"
+                            + memberContext + " from Jclouds layer.");
+                }
+
+                if (node == null) {
+                    String msg = "Null response received for instance start-up request to
Jclouds.\n"
+                            + memberContext.toString();
+                    log.error(msg);
+                    throw new IllegalStateException(msg);
+                }
+
+                // node id
+                String nodeId = node.getId();
+                if (nodeId == null) {
+                    String msg = "Node id of the starting instance is null.\n"
+                            + memberContext.toString();
+                    log.fatal(msg);
+                    throw new IllegalStateException(msg);
+                }
+
+                memberContext.setNodeId(nodeId);
+                if (log.isDebugEnabled()) {
+                    log.debug("Node id was set. " + memberContext.toString());
+                }
+
+                // attach volumes
+                if (ctxt.isVolumeRequired()) {
+                    // remove region prefix
+                    String instanceId = nodeId.indexOf('/') != -1 ? nodeId
+                            .substring(nodeId.indexOf('/') + 1, nodeId.length())
+                            : nodeId;
+                    memberContext.setInstanceId(instanceId);
+                    if (ctxt.getVolumes() != null) {
+                        for (Volume volume : ctxt.getVolumes()) {
+                            try {
+                                iaas.attachVolume(instanceId, volume.getId(),
+                                        volume.getDevice());
+                            } catch (Exception e) {
+                                // continue without throwing an exception, since
+                                // there is an instance already running
+                                log.error("Attaching Volume to Instance [ "
+                                        + instanceId + " ] failed!", e);
+                            }
+                        }
+                    }
+                }
+
+            } catch (Exception e) {
+                String msg = "Failed to start an instance. " + memberContext.toString() +
" Cause: " + e.getMessage();
+                log.error(msg, e);
+                throw new IllegalStateException(msg, e);
+            }
+
+            try {
+                if (log.isDebugEnabled()) {
+                    log.debug("IP allocation process started for " + memberContext);
+                }
+                String autoAssignIpProp =
+                        iaasProvider.getProperty(CloudControllerConstants.AUTO_ASSIGN_IP_PROPERTY);
+
+                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")))
{
+
+                    // check if floating ip is well defined in cartridge definition
+                    if (pre_defined_ip != null) {
+                        if (CloudControllerServiceUtil.isValidIpAddress(pre_defined_ip))
{
+                            if (log.isDebugEnabled()) {
+                                log.debug("CloudControllerServiceImpl:IpAllocator:pre_defined_ip:
invoking associatePredefinedAddress" + pre_defined_ip);
+                            }
+                            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
+                                CloudControllerServiceUtil.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
+                            CloudControllerServiceUtil.terminate(iaasProvider,
+                                    node.getId(), memberContext);
+                            throw new CloudControllerException(msg);
+                        }
+
+                    } else {
+                        if (log.isDebugEnabled()) {
+                            log.debug("CloudControllerServiceImpl:IpAllocator:no (valid)
predefined floating ip configured, "
+                                    + "selecting available one from pool");
+                        }
+                        // allocate an IP address - manual IP assigning mode
+                        ip = iaas.associateAddress(node);
+
+                        if (ip != null) {
+                            memberContext.setAllocatedIpAddress(ip);
+                            if (log.isDebugEnabled()) {
+                                log.debug("Allocated an ip address: "
+                                        + memberContext.toString());
+                            } else if (log.isInfoEnabled()) {
+                                log.info("Allocated ip address [ " + memberContext.getAllocatedIpAddress()
+
+                                        " ] to member with id: " + memberContext.getMemberId());
+                            }
+                        }
+                    }
+
+                    if (ip == null) {
+                        String msg = "No IP address found. IP allocation failed for " + memberContext;
+                        log.error(msg);
+                        throw new CloudControllerException(msg);
+                    }
+
+                    // build the node with the new ip
+                    node = NodeMetadataBuilder.fromNodeMetadata(node)
+                            .publicAddresses(ImmutableSet.of(ip)).build();
+                }
+
+
+                // public ip
+                if (node.getPublicAddresses() != null &&
+                        node.getPublicAddresses().iterator().hasNext()) {
+                    ip = node.getPublicAddresses().iterator().next();
+                    publicIp = ip;
+                    memberContext.setPublicIpAddress(ip);
+                    if (log.isDebugEnabled()) {
+                        log.debug("Retrieving Public IP Address : " + memberContext.toString());
+                    } else if (log.isInfoEnabled()) {
+                        log.info("Retrieving Public IP Address: " + memberContext.getPublicIpAddress()
+
+                                ", member id: " + memberContext.getMemberId());
+                    }
+                }
+
+                // private IP
+                if (node.getPrivateAddresses() != null &&
+                        node.getPrivateAddresses().iterator().hasNext()) {
+                    ip = node.getPrivateAddresses().iterator().next();
+                    memberContext.setPrivateIpAddress(ip);
+                    if (log.isDebugEnabled()) {
+                        log.debug("Retrieving Private IP Address. " + memberContext.toString());
+                    } else if (log.isInfoEnabled()) {
+                        log.info("Retrieving Private IP Address: " + memberContext.getPrivateIpAddress()
+
+                                ", member id: " + memberContext.getMemberId());
+                    }
+                }
+
+                CloudControllerContext.getInstance().addMemberContext(memberContext);
+
+                // persist in registry
+                CloudControllerContext.getInstance().persist();
+
+
+                // trigger topology
+                TopologyBuilder.handleMemberSpawned(cartridgeType, clusterId,
+                        partition.getId(), ip, publicIp, memberContext);
+
+                String memberID = memberContext.getMemberId();
+
+                // update the topology with the newly spawned member
+                // publish data
+                CartridgeInstanceDataPublisher.publish(memberID,
+                        memberContext.getPartition().getId(),
+                        memberContext.getNetworkPartitionId(),
+                        memberContext.getClusterId(),
+                        cartridgeType,
+                        MemberStatus.Created.toString(),
+                        node);
+                if (log.isDebugEnabled()) {
+                    log.debug("Node details: " + node.toString());
+                }
+
+                if (log.isDebugEnabled()) {
+                    log.debug("IP allocation process ended for " + memberContext);
+                }
+
+            } catch (Exception e) {
+                String msg = "Error occurred while allocating an ip address. " + memberContext.toString();
+                log.error(msg, e);
+                throw new CloudControllerException(msg, e);
+            }
+        } finally {
+            if(lock != null) {
+                CloudControllerContext.getInstance().releaseWriteLock(lock);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/stratos/blob/24ba6982/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/InstanceTerminator.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/InstanceTerminator.java
b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/InstanceTerminator.java
new file mode 100644
index 0000000..374537d
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/services/impl/InstanceTerminator.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.services.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.context.CloudControllerContext;
+import org.apache.stratos.cloud.controller.domain.Cartridge;
+import org.apache.stratos.cloud.controller.domain.IaasProvider;
+import org.apache.stratos.cloud.controller.domain.MemberContext;
+import org.apache.stratos.cloud.controller.exception.CloudControllerException;
+import org.apache.stratos.cloud.controller.exception.InvalidCartridgeTypeException;
+import org.apache.stratos.cloud.controller.exception.InvalidMemberException;
+
+import java.util.concurrent.locks.Lock;
+
+/**
+ * Instance terminator runnable.
+ */
+public class InstanceTerminator implements Runnable {
+
+    private static final Log log = LogFactory.getLog(InstanceTerminator.class);
+
+    private MemberContext ctxt;
+
+    public InstanceTerminator(MemberContext ctxt) {
+        this.ctxt = ctxt;
+    }
+
+    @Override
+    public void run() {
+        String memberId = ctxt.getMemberId();
+        String clusterId = ctxt.getClusterId();
+        String partitionId = ctxt.getPartition().getId();
+        String cartridgeType = ctxt.getCartridgeType();
+        String nodeId = ctxt.getNodeId();
+
+        Lock lock = null;
+        try {
+            CloudControllerContext.getInstance().acquireMemberContextWriteLock();
+
+            Cartridge cartridge = CloudControllerContext.getInstance().getCartridge(cartridgeType);
+            log.info("Starting to terminate an instance with member id : " + memberId +
+                    " in partition id: " + partitionId + " of cluster id: " + clusterId +
+                    " and of cartridge type: " + cartridgeType);
+
+            if (cartridge == null) {
+                String msg = "Termination of Member Id: " + memberId + " failed. " +
+                        "Cannot find a matching Cartridge for type: " +
+                        cartridgeType;
+                log.error(msg);
+                throw new InvalidCartridgeTypeException(msg);
+            }
+
+            // if no matching node id can be found.
+            if (nodeId == null) {
+                String msg = "Termination failed. Cannot find a node id for Member Id: "
+ memberId;
+
+                // log information
+                CloudControllerServiceUtil.logTermination(ctxt);
+                log.error(msg);
+                throw new InvalidMemberException(msg);
+            }
+
+            IaasProvider iaasProvider = cartridge.getIaasProviderOfPartition(partitionId);
+
+            // terminate it!
+            CloudControllerServiceUtil.terminate(iaasProvider, nodeId, ctxt);
+
+            // log information
+            CloudControllerServiceUtil.logTermination(ctxt);
+        } catch (Exception e) {
+            String msg = "Instance termination failed. " + ctxt.toString();
+            log.error(msg, e);
+            throw new CloudControllerException(msg, e);
+        } finally {
+            if(lock != null) {
+                CloudControllerContext.getInstance().releaseWriteLock(lock);
+            }
+        }
+    }
+}
\ No newline at end of file


Mime
View raw message