You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by is...@apache.org on 2013/07/10 13:12:18 UTC

[03/14] versions of components are set to 3.0.0-SNAPSHOT

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e8c32dac/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
new file mode 100644
index 0000000..b33d7b6
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java
@@ -0,0 +1,1123 @@
+/*
+ * Copyright (c) 2005-2011, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ * 
+ * WSO2 Inc. 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.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.stratos.cloud.controller.consumers.TopologyBuilder;
+import org.apache.stratos.cloud.controller.exception.CloudControllerException;
+import org.apache.stratos.cloud.controller.exception.UnregisteredServiceException;
+import org.apache.stratos.cloud.controller.publisher.CartridgeInstanceDataPublisherTask;
+import org.apache.stratos.cloud.controller.runtime.FasterLookUpDataHolder;
+import org.apache.stratos.cloud.controller.util.Cartridge;
+import org.apache.stratos.cloud.controller.util.CartridgeInfo;
+import org.apache.stratos.cloud.controller.util.Properties;
+import org.apache.stratos.cloud.controller.util.Property;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.ComputeMetadata;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadata.Status;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.internal.NodeMetadataImpl;
+import org.apache.stratos.lb.common.conf.util.Constants;
+import org.wso2.carbon.ntask.common.TaskException;
+import org.wso2.carbon.ntask.core.TaskInfo;
+import org.wso2.carbon.ntask.core.TaskInfo.TriggerInfo;
+import org.wso2.carbon.ntask.core.TaskManager;
+import org.wso2.carbon.ntask.core.service.TaskService;
+import org.wso2.carbon.registry.core.exceptions.RegistryException;
+import org.apache.stratos.cloud.controller.exception.UnregisteredCartridgeException;
+import org.apache.stratos.cloud.controller.interfaces.CloudControllerService;
+import org.apache.stratos.cloud.controller.jcloud.ComputeServiceBuilderUtil;
+import org.apache.stratos.cloud.controller.persist.Deserializer;
+import org.apache.stratos.cloud.controller.registry.RegistryManager;
+import org.apache.stratos.cloud.controller.topic.TopologySynchronizerTask;
+import org.apache.stratos.cloud.controller.util.CloudControllerConstants;
+import org.apache.stratos.cloud.controller.util.DeclarativeServiceReferenceHolder;
+import org.apache.stratos.cloud.controller.util.CloudControllerUtil;
+import org.apache.stratos.cloud.controller.util.IaasContext;
+import org.apache.stratos.cloud.controller.util.IaasProvider;
+import org.apache.stratos.cloud.controller.util.ServiceContext;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Cloud Controller Service is responsible for starting up new server instances,
+ * terminating already started instances, providing pending instance count etc.
+ * 
+ */
+public class CloudControllerServiceImpl implements CloudControllerService {
+
+	private static final Log log = LogFactory.getLog(CloudControllerServiceImpl.class);
+	private FasterLookUpDataHolder dataHolder = FasterLookUpDataHolder.getInstance();
+
+	public CloudControllerServiceImpl() {
+
+		// acquire serialized data from registry
+		acquireData();
+
+		// gets the task service
+		TaskService taskService =
+		                          DeclarativeServiceReferenceHolder.getInstance()
+		                                                               .getTaskService();
+
+		if (dataHolder.getEnableBAMDataPublisher()) {
+
+			// register and schedule, BAM data publisher task 
+			registerAndScheduleDataPublisherTask(taskService);
+		}
+
+		if (dataHolder.getEnableTopologySync()) {
+
+			// start the topology builder thread
+			startTopologyBuilder();
+
+			// register and schedule, topology synchronizer task
+			registerAndScheduleTopologySyncerTask(taskService);
+		}
+	}
+
+    private void registerAndScheduleTopologySyncerTask(TaskService taskService) {
+	    TaskInfo taskInfo;
+	    TaskManager tm = null;
+	    try {
+
+	    	if (!taskService.getRegisteredTaskTypes()
+	    	                .contains(CloudControllerConstants.TOPOLOGY_SYNC_TASK_TYPE)) {
+
+	    		// topology sync
+	    		taskService.registerTaskType(CloudControllerConstants.TOPOLOGY_SYNC_TASK_TYPE);
+
+	    		tm =
+	    		     taskService.getTaskManager(CloudControllerConstants.TOPOLOGY_SYNC_TASK_TYPE);
+
+	    		TriggerInfo triggerInfo =
+	    		                          new TriggerInfo(
+	    		                                          dataHolder.getTopologySynchronizerCron());
+	    		taskInfo =
+	    		           new TaskInfo(CloudControllerConstants.TOPOLOGY_SYNC_TASK_NAME,
+	    		                        TopologySynchronizerTask.class.getName(),
+	    		                        new HashMap<String, String>(), triggerInfo);
+	    		tm.registerTask(taskInfo);
+	    	}
+
+	    } catch (Exception e) {
+	    	String msg =
+	    	             "Error scheduling task: " +
+	    	                     CloudControllerConstants.TOPOLOGY_SYNC_TASK_NAME;
+	    	log.error(msg, e);
+	    	if (tm != null) {
+	    		try {
+	    			tm.deleteTask(CloudControllerConstants.TOPOLOGY_SYNC_TASK_NAME);
+	    		} catch (TaskException e1) {
+	    			log.error(e1);
+	    		}
+	    	}
+	    	throw new CloudControllerException(msg, e);
+	    }
+    }
+
+    private void startTopologyBuilder() {
+	    // initialize TopologyBuilder Consumer
+	    Thread topologyBuilder =
+	                              new Thread(
+	                                         new TopologyBuilder(
+	                                                             dataHolder.getSharedTopologyDiffQueue()));
+	    // start consumer
+	    topologyBuilder.start();
+    }
+
+    private TaskManager registerAndScheduleDataPublisherTask(TaskService taskService) {
+	    TaskInfo taskInfo;
+	    TaskManager tm = null;
+	    // initialize and schedule the data publisher task
+	    try {
+
+	    	if (!taskService.getRegisteredTaskTypes()
+	    	                .contains(CloudControllerConstants.DATA_PUB_TASK_TYPE)) {
+
+	    		taskService.registerTaskType(CloudControllerConstants.DATA_PUB_TASK_TYPE);
+
+	    		tm = taskService.getTaskManager(CloudControllerConstants.DATA_PUB_TASK_TYPE);
+
+	    		if (!tm.isTaskScheduled(CloudControllerConstants.DATA_PUB_TASK_NAME)) {
+
+	    			TriggerInfo triggerInfo =
+	    			                          new TriggerInfo(
+	    			                                          FasterLookUpDataHolder.getInstance()
+	    			                                                                .getDataPublisherCron());
+	    			taskInfo =
+	    			           new TaskInfo(CloudControllerConstants.DATA_PUB_TASK_NAME,
+	    			                        CartridgeInstanceDataPublisherTask.class.getName(),
+	    			                        new HashMap<String, String>(), triggerInfo);
+	    			tm.registerTask(taskInfo);
+
+	    			// Following code is currently not required, due to an issue in TS API.
+	    			// tm.scheduleTask(taskInfo.getName());
+	    		}
+	    	}
+
+	    } catch (Exception e) {
+	    	String msg =
+	    	             "Error scheduling task: " +
+	    	                     CloudControllerConstants.DATA_PUB_TASK_NAME;
+	    	log.error(msg, e);
+	    	if (tm != null) {
+	    		try {
+	    			tm.deleteTask(CloudControllerConstants.DATA_PUB_TASK_NAME);
+	    		} catch (TaskException e1) {
+	    			log.error(e1);
+	    		}
+	    	}
+	    	throw new CloudControllerException(msg, e);
+	    }
+	    return tm;
+    }
+
+	private void acquireData() {
+
+		Object obj = RegistryManager.getInstance().retrieve();
+		if (obj != null) {
+			try {
+				Object dataObj = Deserializer.deserializeFromByteArray((byte[]) obj);
+				if (dataObj instanceof FasterLookUpDataHolder) {
+					FasterLookUpDataHolder serializedObj = (FasterLookUpDataHolder) dataObj;
+					FasterLookUpDataHolder currentData = FasterLookUpDataHolder.getInstance();
+					
+					// assign necessary data
+					currentData.setNodeIdToServiceContextMap(serializedObj.getNodeIdToServiceContextMap());
+					
+					// traverse through current Service Contexts
+					for (ServiceContext ctxt : currentData.getServiceCtxtList()) {
+						// traverse through serialized Service Contexts
+	                    for (ServiceContext serializedCtxt : serializedObj.getServiceCtxtList()) {
+	                    	// if a matching Service Context found
+	                        if(ctxt.equals(serializedCtxt)){
+	                        	// persisted node ids of this Service Context
+	                        	List<Object> nodeIds = serializedObj.getNodeIdsOfServiceCtxt(serializedCtxt);
+	                        	for (Object nodeIdObj : nodeIds) {
+	                                String nodeId = (String) nodeIdObj;
+	                                
+	                                // assign persisted data
+	                                currentData.addNodeId(nodeId, ctxt);
+	                                
+                                }
+	                        	
+	                        	ctxt.setIaasContextMap(serializedCtxt.getIaasCtxts());
+	                        	appendToPublicIpProperty(serializedCtxt.getProperty(CloudControllerConstants.PUBLIC_IP_PROPERTY), ctxt);
+	                        	
+	                        	// assign lastly used IaaS
+	                        	if(serializedCtxt.getCartridge() != null && serializedCtxt.getCartridge().getLastlyUsedIaas() != null){
+	                        		
+	                        		if(ctxt.getCartridge() == null){
+	                        			// load Cartridge
+	                        			ctxt.setCartridge(loadCartridge(ctxt.getCartridgeType(), ctxt.getPayload(), serializedObj.getCartridges()));
+	                        		}
+	                        		
+	                        		IaasProvider serializedIaas = serializedCtxt.getCartridge().getLastlyUsedIaas();
+	                        		ctxt.getCartridge().setLastlyUsedIaas(serializedIaas);
+	                        		
+	                        	}
+	                        }
+                        }
+                    }
+					
+					log.debug("Data is retrieved from registry.");
+				} else {
+					log.debug("No data is persisted in registry.");
+				}
+			} catch (Exception e) {
+
+				String msg =
+				             "Unable to acquire data from Registry. Hence, any historical data will not get reflected.";
+				log.warn(msg, e);
+			}
+
+		}
+	}
+
+	@Override
+	public String startInstance(String domainName, String subDomainName) {
+
+		ComputeService computeService;
+		Template template;
+		String ip = "";
+		final Lock lock = new ReentrantLock();
+
+		// check for sub domain
+		subDomainName = checkSubDomain(subDomainName);
+
+		log.info("Starting new instance of domain : " + domainName + " and sub domain : " +
+		         subDomainName);
+
+		// get the subjected ServiceContext
+		ServiceContext serviceCtxt =
+		                             FasterLookUpDataHolder.getInstance()
+		                                                   .getServiceContext(domainName,
+		                                                                      subDomainName);
+
+		if (serviceCtxt == null) {
+			String msg =
+			             "Not a registered service: domain - " + domainName + ", sub domain - " +
+			                     subDomainName;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		// load Cartridge
+		serviceCtxt.setCartridge(loadCartridge(serviceCtxt.getCartridgeType(),
+		                                       serviceCtxt.getPayload(),
+		                                       FasterLookUpDataHolder.getInstance().getCartridges()));
+
+		if (serviceCtxt.getCartridge() == null) {
+			String msg =
+			             "There's no registered Cartridge found. Domain - " + domainName +
+			                     ", sub domain - " + subDomainName;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		if (serviceCtxt.getCartridge().getIaases().isEmpty()) {
+			String msg =
+			             "There's no registered IaaSes found for Cartridge type: " +
+			                     serviceCtxt.getCartridge().getType();
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		// sort the IaasProviders according to scale up order
+		Collections.sort(serviceCtxt.getCartridge().getIaases(),
+		                 IaasProviderComparator.ascending(IaasProviderComparator.getComparator(IaasProviderComparator.SCALE_UP_SORT)));
+
+		for (IaasProvider iaas : serviceCtxt.getCartridge().getIaases()) {
+
+			IaasContext ctxt = null;
+			if ((ctxt = serviceCtxt.getIaasContext(iaas.getType())) == null) {
+				ctxt = serviceCtxt.addIaasContext(iaas.getType());
+			}
+
+			if (iaas.getMaxInstanceLimit() > ctxt.getCurrentInstanceCount()) {
+				try {
+
+					iaas.getIaas().setDynamicPayload(iaas);
+
+					// get the ComputeService
+					computeService = iaas.getComputeService();
+
+					// corresponding Template
+					template = iaas.getTemplate();
+
+					if (template == null) {
+						String msg =
+						             "Failed to start an instance in " +
+						                     iaas.getType() +
+						                     ". Reason : Template is null. You have not specify a matching service " +
+						                     "element in the configuration file of Autoscaler.\n Hence, will try to " +
+						                     "start in another IaaS if available.";
+						log.error(msg);
+						continue;
+					}
+
+					// set instance name as the host name
+					// template.getOptions().userMetadata("Name",
+					// serviceCtxt.getHostName());
+					// template.getOptions().as(TemplateOptions.class).userMetadata("Name",
+					// serviceCtxt.getHostName());
+
+					// 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 = domainName.concat("-" + subDomainName).substring(0, 10);
+					String group = str.replaceAll("[^a-z0-9-]", "");
+
+					NodeMetadata node;
+
+					// create and start a node
+					Set<? extends NodeMetadata> nodes =
+					                                    computeService.createNodesInGroup(group, 1,
+					                                                                      template);
+
+					node = nodes.iterator().next();
+
+					String autoAssignIpProp =
+					                          iaas.getProperty(CloudControllerConstants.AUTO_ASSIGN_IP_PROPERTY);
+
+					// acquire the lock
+					lock.tryLock();
+
+					try {
+						// reset ip
+						ip = "";
+						// default behavior is autoIpAssign=false
+						if (autoAssignIpProp == null ||
+						    (autoAssignIpProp != null && autoAssignIpProp.equals("false"))) {
+							// allocate an IP address - manual IP assigning mode
+							ip = iaas.getIaas().associateAddress(iaas, node);
+						}
+
+						if (ip.isEmpty() && node.getPublicAddresses() != null &&
+						    node.getPublicAddresses().iterator().hasNext()) {
+							ip = node.getPublicAddresses().iterator().next();
+						}
+
+						// if not public IP is assigned, we're using private IP
+						if (ip.isEmpty() && node.getPrivateAddresses() != null &&
+						    node.getPrivateAddresses().iterator().hasNext()) {
+							ip = node.getPrivateAddresses().iterator().next();
+						}
+
+						if (node.getId() == null) {
+							String msg =
+							             "Node id of the starting instance is null.\n" +
+							                     node.toString();
+							log.fatal(msg);
+							throw new CloudControllerException(msg);
+						}
+
+						// add node ID
+						ctxt.addNodeId(node.getId());
+						ctxt.addNodeToPublicIp(node.getId(), ip);
+
+						// to faster look up
+						FasterLookUpDataHolder.getInstance().addNodeId(node.getId(), serviceCtxt);
+
+						serviceCtxt.getCartridge().setLastlyUsedIaas(iaas);
+
+						// add this ip to the topology
+						appendToPublicIpProperty(ip, serviceCtxt);
+
+						ctxt.incrementCurrentInstanceCountByOne();
+						
+						// persist in registry
+						persist();
+
+						// trigger topology consumers
+						List<ServiceContext> list = new ArrayList<ServiceContext>();
+						list.add(serviceCtxt);
+						try {
+							dataHolder.getSharedTopologyDiffQueue().put(list);
+							
+							// publish data
+							CartridgeInstanceDataPublisherTask.publish();
+						} catch (InterruptedException ignore) {
+						}
+
+						if (log.isDebugEnabled()) {
+							log.debug("Node details: \n" + node.toString() + "\n***************\n");
+						}
+
+						log.info("Instance is successfully starting up in IaaS " + iaas.getType() +
+						         ".\tIP Address(public/private): " + ip + "\tNode Id: " +
+						         node.getId());
+
+						return ip;
+
+					} finally {
+						// release the lock
+						lock.unlock();
+					}
+
+				} catch (Exception e) {
+					log.warn("Failed to start an instance in " + iaas.getType() +
+					         ". Hence, will try to start in another IaaS if available.", e);
+					continue;
+				}
+			} else {
+				log.warn("Max instance limit is reached in the IaaS " + iaas.getType() +
+				          " : Max instance limit: " + iaas.getMaxInstanceLimit());
+			}
+
+		}
+
+		log.error("Failed to start an instance, in any available IaaS: " + domainName +
+		          " and sub domain : " + subDomainName);
+
+		return null;
+
+	}
+
+	/**
+	 * Appends this ip to the Service Context's {@link CloudControllerConstants#PUBLIC_IP_PROPERTY}
+     * @param ip
+     * @param serviceCtxt
+     */
+	private void appendToPublicIpProperty(String ip, ServiceContext serviceCtxt) {
+		String ipStr = serviceCtxt.getProperty(CloudControllerConstants.PUBLIC_IP_PROPERTY);
+		if (ip != null && !"".equals(ip)) {
+			serviceCtxt.setProperty(CloudControllerConstants.PUBLIC_IP_PROPERTY,
+			                        ("".equals(ipStr) ? ""
+			                                         : ipStr +
+			                                           CloudControllerConstants.ENTRY_SEPARATOR) +
+			                                ip);
+		}
+	}
+
+	/**
+     * Persist data in registry.
+     */
+    private void persist() {
+	    try {
+	        RegistryManager.getInstance().persist(FasterLookUpDataHolder.getInstance());
+	    } catch (RegistryException e) {
+
+	    	String msg = "Failed to persist the Cloud Controller data in registry. Further, transaction roll back also failed.";
+	    	log.fatal(msg);
+	    	throw new CloudControllerException(msg, e);
+	    }
+    }
+
+	private Cartridge loadCartridge(String cartridgeType, byte[] payload, List<Cartridge> cartridges) {
+
+		for (Cartridge cartridge : cartridges) {
+			if (cartridge.getType().equals(cartridgeType)) {
+				for (IaasProvider iaas : cartridge.getIaases()) {
+					iaas.setPayload(payload);
+				}
+				return cartridge;
+			}
+		}
+
+		return null;
+	}
+
+	@Override
+	public boolean terminateInstance(String domainName, String subDomainName) {
+
+		subDomainName = checkSubDomain(subDomainName);
+
+		log.info("Starting to terminate an instance of domain : " + domainName +
+		         " and sub domain : " + subDomainName);
+
+		ServiceContext serviceCtxt =
+		                             FasterLookUpDataHolder.getInstance()
+		                                                   .getServiceContext(domainName,
+		                                                                      subDomainName);
+
+		if (serviceCtxt == null) {
+			String msg =
+			             "Not a registered service: domain - " + domainName + ", sub domain - " +
+			                     subDomainName;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		// load Cartridge, if null
+		if (serviceCtxt.getCartridge() == null) {
+			serviceCtxt.setCartridge(loadCartridge(serviceCtxt.getCartridgeType(),
+			                                       serviceCtxt.getPayload(),
+			                                       FasterLookUpDataHolder.getInstance()
+			                                                             .getCartridges()));
+		}
+		
+		// if still, Cartridge is null
+		if (serviceCtxt.getCartridge() == null) {
+			String msg =
+			             "There's no registered Cartridge found. Domain - " + domainName +
+			                     ", sub domain - " + subDomainName;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		// sort the IaasProviders according to scale down order
+		Collections.sort(serviceCtxt.getCartridge().getIaases(),
+		                 IaasProviderComparator.ascending(IaasProviderComparator.getComparator(IaasProviderComparator.SCALE_DOWN_SORT)));
+
+		// traverse in scale down order
+		for (IaasProvider iaas : serviceCtxt.getCartridge().getIaases()) {
+
+			String msg =
+			             "Failed to terminate an instance in " + iaas.getType() +
+			                     ". Hence, will try to terminate an instance in another IaaS if possible.";
+
+			String nodeId = null;
+
+			IaasContext ctxt = serviceCtxt.getIaasContext(iaas.getType());
+
+			// terminate the last instance first
+			for (String id : Lists.reverse(ctxt.getNodeIds())) {
+				if (id != null) {
+					nodeId = id;
+					break;
+				}
+			}
+
+			// if no matching node id can be found.
+			if (nodeId == null) {
+
+				log.warn(msg + " : Reason- No matching instance found for domain: " + domainName +
+				         " and sub domain: " + subDomainName + ".");
+				continue;
+			}
+
+			// terminate it!
+			terminate(iaas, ctxt, nodeId);
+			
+			// log information
+			logTermination(nodeId, ctxt, serviceCtxt);
+
+			return true;
+
+		}
+
+		log.info("Termination of an instance which is belong to domain '" + domainName +
+		         "' and sub domain '" + subDomainName + "' , failed! Reason: No matching " +
+		         "running instance found in any available IaaS.");
+
+		return false;
+
+	}
+
+	@Override
+	public boolean terminateLastlySpawnedInstance(String domainName, String subDomainName) {
+
+		subDomainName = checkSubDomain(subDomainName);
+
+		log.info("Starting to terminate the last instance spawned, of domain : " + domainName +
+		         " and sub domain : " + subDomainName);
+
+		ServiceContext serviceCtxt =
+		                             FasterLookUpDataHolder.getInstance()
+		                                                   .getServiceContext(domainName,
+		                                                                      subDomainName);
+
+		if (serviceCtxt == null) {
+			String msg =
+			             "Not a registered service: domain - " + domainName + ", sub domain - " +
+			                     subDomainName;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		// load Cartridge, if null
+		if (serviceCtxt.getCartridge() == null) {
+			serviceCtxt.setCartridge(loadCartridge(serviceCtxt.getCartridgeType(),
+			                                       serviceCtxt.getPayload(),
+			                                       FasterLookUpDataHolder.getInstance()
+			                                                             .getCartridges()));
+		}
+		
+		if (serviceCtxt.getCartridge() == null) {
+			String msg =
+			             "There's no registered Cartridge found. Domain - " + domainName +
+			                     ", sub domain - " + subDomainName;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		IaasProvider iaas = serviceCtxt.getCartridge().getLastlyUsedIaas();
+		// this is required since, we need to find the correct reference.
+		// caz if the lastly used iaas retrieved from registry, it is not a reference.
+		iaas = serviceCtxt.getCartridge().getIaasProvider(iaas.getType());
+
+		if (iaas != null) {
+
+			String nodeId = null;
+			IaasContext ctxt = serviceCtxt.getIaasContext(iaas.getType());
+
+			int i=0;
+			for (i = ctxt.getNodeIds().size()-1; i >= 0 ; i--) {
+	            String id = ctxt.getNodeIds().get(i);
+				if (id != null) {
+					nodeId = id;
+					break;
+				}
+            }
+
+			if (nodeId != null) {
+
+				// terminate it!
+				iaas = terminate(iaas, ctxt, nodeId);
+				
+				// log information
+				logTermination(nodeId, ctxt, serviceCtxt);
+
+				return true;
+			}
+
+		}
+
+		log.info("Termination of an instance which is belong to domain '" + domainName +
+		          "' and sub domain '" + subDomainName + "' , failed! Reason: No matching " +
+		          "running instance found in lastly used IaaS.");
+
+		return false;
+
+	}
+
+	@Override
+	public boolean terminateAllInstances(String domainName, String subDomainName) {
+
+		boolean isAtLeastOneTerminated = false;
+		
+		subDomainName = checkSubDomain(subDomainName);
+
+		log.info("Starting to terminate all instances of domain : " + domainName +
+		         " and sub domain : " + subDomainName);
+
+		ServiceContext serviceCtxt =
+		                             FasterLookUpDataHolder.getInstance()
+		                                                   .getServiceContext(domainName,
+		                                                                      subDomainName);
+
+		if (serviceCtxt == null) {
+			String msg =
+			             "Not a registered service: domain - " + domainName + ", sub domain - " +
+			                     subDomainName;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		// load Cartridge, if null
+		if (serviceCtxt.getCartridge() == null) {
+			serviceCtxt.setCartridge(loadCartridge(serviceCtxt.getCartridgeType(),
+			                                       serviceCtxt.getPayload(),
+			                                       FasterLookUpDataHolder.getInstance()
+			                                                             .getCartridges()));
+		}
+		
+		if (serviceCtxt.getCartridge() == null) {
+			String msg =
+			             "There's no registered Cartridge found. Domain - " + domainName +
+			                     ", sub domain - " + subDomainName;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		// sort the IaasProviders according to scale down order
+		Collections.sort(serviceCtxt.getCartridge().getIaases(),
+		                 IaasProviderComparator.ascending(IaasProviderComparator.getComparator(IaasProviderComparator.SCALE_DOWN_SORT)));
+
+		// traverse in scale down order
+		for (IaasProvider iaas : serviceCtxt.getCartridge().getIaases()) {
+
+			IaasContext ctxt = serviceCtxt.getIaasContext(iaas.getType());
+			
+			if (ctxt == null) {
+				log.error("Iaas Context for " + iaas.getType() + " not found. Cannot terminate instances");
+				continue;
+			}
+
+			ArrayList<String> temp = new ArrayList<String>(ctxt.getNodeIds());
+			for (String id : temp) {
+				if (id != null) {
+					// terminate it!
+					terminate(iaas, ctxt, id);
+					
+					// log information
+					logTermination(id, ctxt, serviceCtxt);
+					
+					isAtLeastOneTerminated = true;
+				}
+			}
+		}
+		
+		if(isAtLeastOneTerminated){
+			return true;
+		}
+		
+		log.info("Termination of an instance which is belong to domain '" + domainName +
+		          "' and sub domain '" + subDomainName + "' , failed! Reason: No matching " +
+		          "running instance found in lastly used IaaS.");
+
+		return false;
+
+	}
+	
+	public int getPendingInstanceCount(String domainName, String subDomainName) {
+
+		subDomainName = checkSubDomain(subDomainName);
+
+		int pendingInstanceCount = 0;
+
+		ServiceContext subjectedSerCtxt =
+		                                  FasterLookUpDataHolder.getInstance()
+		                                                        .getServiceContext(domainName,
+		                                                                           subDomainName);
+
+		if (subjectedSerCtxt != null && subjectedSerCtxt.getCartridgeType() != null) {
+			
+			// load cartridge
+			subjectedSerCtxt.setCartridge(loadCartridge(subjectedSerCtxt.getCartridgeType(),
+			                                            subjectedSerCtxt.getPayload(),
+			                                            FasterLookUpDataHolder.getInstance()
+			                                                                  .getCartridges()));
+			
+			if(subjectedSerCtxt.getCartridge() == null){
+				return pendingInstanceCount;
+			}
+			
+			List<IaasProvider> iaases = subjectedSerCtxt.getCartridge().getIaases();
+			
+			for (IaasProvider iaas : iaases) {
+
+				ComputeService computeService = iaas.getComputeService();
+
+				IaasContext ctxt = null;
+				if ((ctxt = subjectedSerCtxt.getIaasContext(iaas.getType())) == null) {
+					ctxt = subjectedSerCtxt.addIaasContext(iaas.getType());
+				}
+
+				// get list of node Ids which are belong to this domain- sub
+				// domain
+				List<String> nodeIds = ctxt.getNodeIds();
+
+				if (nodeIds.isEmpty()) {
+					log.debug("Zero nodes spawned in the IaaS " + iaas.getType() + " of domain: " +
+					          domainName + " and sub domain: " + subDomainName);
+					continue;
+				}
+
+				// get all the nodes spawned by this IaasContext
+				Set<? extends ComputeMetadata> set = computeService.listNodes();
+
+				Iterator<? extends ComputeMetadata> iterator = set.iterator();
+
+				// traverse through all nodes of this ComputeService object
+				while (iterator.hasNext()) {
+					NodeMetadataImpl nodeMetadata = (NodeMetadataImpl) iterator.next();
+
+					// if this node belongs to the requested domain
+					if (nodeIds.contains(nodeMetadata.getId())) {
+
+						// get the status of the node
+						Status nodeStatus = nodeMetadata.getStatus();
+
+						// count nodes that are in pending state
+						if (nodeStatus.equals(Status.PENDING)) {
+							pendingInstanceCount++;
+						}
+					}
+
+				}
+			}
+		}
+
+		log.debug("Pending instance count of domain '" + domainName + "' and sub domain '" +
+		          subDomainName + "' is " + pendingInstanceCount);
+
+		return pendingInstanceCount;
+
+	}
+
+	
+	/**
+	 * A helper method to terminate an instance.
+	 */
+	private IaasProvider terminate(IaasProvider iaasTemp, IaasContext ctxt, String nodeId) {
+
+		// this is just to be safe
+		if (iaasTemp.getComputeService() == null) {
+			String msg = "Unexpeced error occured! IaasContext's ComputeService is null!";
+			log.error(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		// destroy the node
+		iaasTemp.getComputeService().destroyNode(nodeId);
+		
+		
+		String autoAssignIpProp =
+			iaasTemp.getProperty(CloudControllerConstants.AUTO_ASSIGN_IP_PROPERTY);
+		
+		// release allocated IP address
+		if (autoAssignIpProp == null ||
+			    (autoAssignIpProp != null && autoAssignIpProp.equals("false"))) {
+				// allocate an IP address - manual IP assigning mode
+			iaasTemp.getIaas().releaseAddress(iaasTemp, ctxt.getPublicIp(nodeId));
+		}		
+
+		// remove the node id
+		ctxt.removeNodeId(nodeId);
+		
+		ctxt.decrementCurrentInstanceCountByOne();
+		
+		// publish data to BAM
+		CartridgeInstanceDataPublisherTask.publish();
+
+		log.info("Node with Id: '" + nodeId + "' is terminated!");
+		return iaasTemp;
+	}
+	
+	private void logTermination(String nodeId, IaasContext ctxt, ServiceContext serviceCtxt) {
+
+		// get the ip of the terminated node
+		String ip = ctxt.getPublicIp(nodeId);
+		String ipProp = CloudControllerConstants.PUBLIC_IP_PROPERTY;
+		String ipStr = serviceCtxt.getProperty(ipProp);
+		StringBuilder newIpStr = new StringBuilder("");
+
+		for (String str : ipStr.split(CloudControllerConstants.ENTRY_SEPARATOR)) {
+			if (!str.equals(ip)) {
+				newIpStr.append(str + CloudControllerConstants.ENTRY_SEPARATOR);
+			}
+		}
+
+		// add this ip to the topology
+		serviceCtxt.setProperty(ipProp,
+		                        newIpStr.length() == 0
+		                                              ? ""
+		                                              : newIpStr.substring(0, newIpStr.length() - 1)
+		                                                        .toString());
+
+		// remove the reference
+		ctxt.removeNodeIdToPublicIp(nodeId);
+
+		// persist
+		persist();
+		
+		// trigger topology consumers
+		List<ServiceContext> list = new ArrayList<ServiceContext>();
+		list.add(serviceCtxt);
+		try {
+			dataHolder.getSharedTopologyDiffQueue().put(list);
+		} catch (InterruptedException ignore) {
+		}
+
+	}
+
+	/**
+	 * Comparator to compare {@link IaasProvider} on different attributes.
+	 */
+	public enum IaasProviderComparator implements Comparator<IaasProvider> {
+		SCALE_UP_SORT {
+			public int compare(IaasProvider o1, IaasProvider o2) {
+				return Integer.valueOf(o1.getScaleUpOrder()).compareTo(o2.getScaleUpOrder());
+			}
+		},
+		SCALE_DOWN_SORT {
+			public int compare(IaasProvider o1, IaasProvider o2) {
+				return Integer.valueOf(o1.getScaleDownOrder()).compareTo(o2.getScaleDownOrder());
+			}
+		};
+
+		public static Comparator<IaasProvider> ascending(final Comparator<IaasProvider> other) {
+			return new Comparator<IaasProvider>() {
+				public int compare(IaasProvider o1, IaasProvider o2) {
+					return other.compare(o1, o2);
+				}
+			};
+		}
+
+		public static Comparator<IaasProvider> getComparator(final IaasProviderComparator... multipleOptions) {
+			return new Comparator<IaasProvider>() {
+				public int compare(IaasProvider o1, IaasProvider o2) {
+					for (IaasProviderComparator option : multipleOptions) {
+						int result = option.compare(o1, o2);
+						if (result != 0) {
+							return result;
+						}
+					}
+					return 0;
+				}
+			};
+		}
+	}
+
+	@Override
+	public boolean registerService(String domain, String subDomain, String tenantRange,
+	                               String cartridgeType, String hostName, Properties properties, byte[] payload)
+	                                                                                     throws UnregisteredCartridgeException {
+
+		// create a ServiceContext dynamically
+		ServiceContext newServiceCtxt = new ServiceContext();
+		newServiceCtxt.setDomainName(domain);
+		newServiceCtxt.setSubDomainName(subDomain);
+		newServiceCtxt.setTenantRange(tenantRange);
+		newServiceCtxt.setHostName(hostName);
+		
+		if (properties != null && properties.getProperties() != null ) {
+			// add properties
+			for (Property property : properties.getProperties()) {
+				if (property != null && property.getName() != null) {
+					newServiceCtxt.setProperty(property.getName(), property.getValue());
+				}
+			}
+		}
+		
+		newServiceCtxt.setCartridgeType(cartridgeType);
+
+		for (Cartridge cartridge : FasterLookUpDataHolder.getInstance().getCartridges()) {
+			if (cartridge.getType().equals(cartridgeType)) {
+				newServiceCtxt.setCartridge(cartridge);
+				break;
+			}
+		}
+
+		if (newServiceCtxt.getCartridge() == null) {
+			String msg = "Registration failed - Unregistered Cartridge type: " + cartridgeType;
+			log.error(msg);
+			throw new UnregisteredCartridgeException(msg);
+		}
+
+		if (payload != null && payload.length != 0) {
+
+			// write payload file
+			try {
+				String uniqueName = domain + "-" + subDomain + ".txt";
+				FileUtils.forceMkdir(new File(CloudControllerConstants.PAYLOAD_DIR));
+				File payloadFile = new File(CloudControllerConstants.PAYLOAD_DIR + uniqueName);
+				FileUtils.writeByteArrayToFile(payloadFile, payload);
+				newServiceCtxt.setPayloadFile(payloadFile.getPath());
+
+			} catch (IOException e) {
+				String msg =
+				             "Failed while persisting the payload of domain : " + domain +
+				                     ", sub domain : " + subDomain;
+				log.error(msg, e);
+				throw new CloudControllerException(msg, e);
+			}
+
+		} else {
+			log.debug("Payload is null or empty for :\n "+newServiceCtxt.toNode().toString());
+		}
+
+		// persist
+		try {
+			String uniqueName = domain + "-" + subDomain + "-" + UUID.randomUUID() + ".xml";
+			FileUtils.writeStringToFile(new File(CloudControllerConstants.SERVICES_DIR + uniqueName),
+			                            newServiceCtxt.toXml());
+		} catch (IOException e) {
+			String msg =
+			             "Failed while persisting the service configuration - domain : " + domain +
+			                     ", sub domain : " + subDomain + ", tenant range: " + tenantRange +
+			                     ", cartridge type: " + cartridgeType;
+			log.error(msg, e);
+			throw new CloudControllerException(msg, e);
+		}
+
+		log.info("Service successfully registered! Domain - " + domain + ", Sub domain - " +
+		         newServiceCtxt.getSubDomainName() + ", Cartridge type - " + cartridgeType);
+
+		return true;
+	}
+
+	@Override
+	public String[] getRegisteredCartridges() {
+		// get the list of cartridges registered
+		List<Cartridge> cartridges = FasterLookUpDataHolder.getInstance().getCartridges();
+
+		if (cartridges == null) {
+			return new String[0];
+		}
+
+		String[] cartridgeTypes = new String[cartridges.size()];
+		int i = 0;
+
+		for (Cartridge cartridge : cartridges) {
+			cartridgeTypes[i] = cartridge.getType();
+			i++;
+		}
+
+		return cartridgeTypes;
+	}
+
+	@Override
+	public boolean createKeyPairFromPublicKey(String cartridgeType, String keyPairName,
+	                                          String publicKey) {
+
+		Cartridge cartridge = FasterLookUpDataHolder.getInstance().getCartridge(cartridgeType);
+
+		if (cartridge == null) {
+			String msg = "Invalid Cartridge type specified : " + cartridgeType;
+			log.fatal(msg);
+			throw new CloudControllerException(msg);
+		}
+
+		for (IaasProvider iaas : cartridge.getIaases()) {
+			String region = ComputeServiceBuilderUtil.extractRegion(iaas);
+
+			if (region == null) {
+				String msg =
+				             "Cannot find a region to create the key pair. Please add a property called 'region' under IaaS '" +
+				                     iaas.getType() + "' of Cartridge - " + cartridgeType;
+				log.fatal(msg);
+				throw new CloudControllerException(msg);
+			}
+
+			return iaas.getIaas().createKeyPairFromPublicKey(iaas, region, keyPairName, publicKey);
+		}
+
+		return false;
+	}
+
+	private String checkSubDomain(String subDomainName) {
+		// if sub domain is null, we assume it as default one.
+		if (subDomainName == null || "null".equalsIgnoreCase(subDomainName)) {
+			subDomainName = Constants.DEFAULT_SUB_DOMAIN;
+			log.debug("Sub domain is null, hence using the default value : " + subDomainName);
+		}
+
+		return subDomainName;
+	}
+
+	@Override
+	public CartridgeInfo getCartridgeInfo(String cartridgeType)
+	                                                           throws UnregisteredCartridgeException {
+		Cartridge cartridge = FasterLookUpDataHolder.getInstance().getCartridge(cartridgeType);
+
+		if (cartridge != null) {
+
+			return CloudControllerUtil.toCartridgeInfo(cartridge);
+
+		}
+
+		String msg =
+		             "Cannot find a Cartridge having a type of " + cartridgeType +
+		                     ". Hence unable to find information.";
+		log.error(msg);
+		throw new UnregisteredCartridgeException(msg);
+	}
+
+	@Override
+    public boolean unregisterService(String domain, String subDomain) throws UnregisteredServiceException {
+		
+		subDomain = checkSubDomain(subDomain);
+
+		// find the service context
+		ServiceContext subjectedSerCtxt =
+		                                  FasterLookUpDataHolder.getInstance()
+		                                                        .getServiceContext(domain,
+		                                                                           subDomain);
+		
+		if(subjectedSerCtxt == null){
+			throw new UnregisteredServiceException("No registered service found for domain: "+domain+" - sub domain: "+subDomain);
+		}
+		
+		// get the service definition file.
+		File serviceDefFile = subjectedSerCtxt.getFile();
+		
+		// delete that file, so that it gets automatically undeployed.
+	    return serviceDefFile.delete();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e8c32dac/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/CloudControllerService.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/CloudControllerService.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/CloudControllerService.java
new file mode 100644
index 0000000..462afd9
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/CloudControllerService.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2005-2011, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ * 
+ * WSO2 Inc. 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.interfaces;
+
+import org.apache.stratos.cloud.controller.exception.UnregisteredServiceException;
+import org.apache.stratos.cloud.controller.util.CartridgeInfo;
+import org.apache.stratos.cloud.controller.util.Properties;
+import org.apache.stratos.lb.common.conf.util.Constants;
+import org.apache.stratos.cloud.controller.exception.UnregisteredCartridgeException;
+
+/**
+ * This Interface provides a way to communicate with underline
+ * Infrastructure which are supported by <i>JClouds</i>.
+ * 
+ */
+public interface CloudControllerService {
+
+    /**
+     * Creates a key pair in all IaaSes that are configured for the given cartridge,
+     * having the given name and public key.
+     * 
+     * <p/>
+     * <h4>Supported Formats</h4>
+     * <ul>
+     * <li>OpenSSH public key format (e.g., the format in ~/.ssh/authorized_keys)</li>
+     * <li>Base64 encoded DER format</li>
+     * <li>SSH public key file format as specified in RFC4716</li>
+     * </ul>
+     * DSA keys are not supported. Make sure your key generator is set up to create RSA keys.
+     * <p/>
+     * Supported lengths: 1024, 2048, and 4096.
+     * <p/>
+     * 
+     * @param cartridgeType
+     *            type of the cartridge. Note this cartridge type should be already
+     *            registered one.
+     * @param keyPairName
+     *            name of the key pair which is going to get created in IaaSes.
+     * @param publicKey
+     *            The public key.
+     * 
+     */
+	@Deprecated
+    public boolean createKeyPairFromPublicKey(String cartridgeType, String keyPairName,
+        String publicKey);
+
+    /**
+     * This method will return the information regarding the given cartridge, if present.
+     * Else this will return <code>null</code>.
+     * 
+     * @param cartridgeType
+     *            type of the cartridge.
+     * @return {@link org.apache.stratos.cloud.controller.util.CartridgeInfo} of the given cartridge type or <code>null</code>.
+     * @throws UnregisteredCartridgeException if there is no registered cartridge with this type.
+     */
+    public CartridgeInfo getCartridgeInfo(String cartridgeType) throws UnregisteredCartridgeException;
+
+    /**
+     * Calling this method will result in returning the pending instances
+     * count of a particular domain.
+     * 
+     * @param domainName
+     *            service cluster domain
+     * @param sudDomainName
+     *            service clustering sub domain of the instance to be started up.
+     *            If this is null, the default value will be used. Default value is
+     *            {@link Constants}.DEFAULT_SUB_DOMAIN.
+     * @return number of pending instances for this domain. If no instances of this
+     *         domain is present, this will return zero.
+     */
+    public int getPendingInstanceCount(String domainName, String subDomainName);
+
+    /**
+     * Calling this method will result in returning the types of {@link org.apache.stratos.cloud.controller.util.Cartridge}s
+     * registered in Cloud Controller.
+     * 
+     * @return String array containing types of registered {@link org.apache.stratos.cloud.controller.util.Cartridge}s.
+     */
+    public String[] getRegisteredCartridges();
+    
+    /**
+     * <p>
+     * Registers the details of a newly created service cluster. This will override an already
+     * present service cluster, if there is any. A service cluster is uniquely identified by its
+     * domain and sub domain combination.
+     * </p>
+     * @param domain
+     *            service cluster domain
+     * @param subDomain
+     *            service cluster sub domain
+     * @param tenantRange 
+     * 			  tenant range eg: '1-10' or '2'
+     * @param cartridgeType
+     *            cartridge type of the new service. This should be an already registered cartridge
+     *            type.
+     * @param hostName
+     * 			  host name of this service instance
+     * @param properties
+     * 			  Set of properties related to this service definition.
+     * @param payload
+     *            payload which will be passed to instance to be started. Payload shouldn't contain 
+     *            xml tags.
+     * @return whether the registration is successful or not.
+     * 
+     * @throws UnregisteredCartridgeException
+     *             when the cartridge type requested by this service is
+     *             not a registered one.
+     */
+    public boolean registerService(String domain, String subDomain, String tenantRange, String cartridgeType,
+        String hostName, Properties properties, byte[] payload) throws UnregisteredCartridgeException;
+
+    /**
+     * Calling this method will result in an instance startup, which is belong
+     * to the provided service domain. Also note that the instance that is starting up
+     * belongs to the group whose name is derived from its service domain, replacing <i>.</i>
+     * by a hyphen (<i>-</i>).
+     * 
+     * @param domainName
+     *            service clustering domain of the instance to be started up.
+     * @param subDomainName
+     *            service clustering sub domain of the instance to be started up.
+     *            If this is null, the default value will be used. Default value is
+     *            {@link Constants}.DEFAULT_SUB_DOMAIN.
+     * @return public IP which is associated with the newly started instance.
+     */
+    public String startInstance(String domainName, String subDomainName);
+
+    /**
+     * Calling this method will result in termination of all instances belong
+     * to the provided service domain and sub domain.
+     * 
+     * @param domainName
+     *            service domain of the instance to be terminated.
+     * @param sudDomainName
+     *            service clustering sub domain of the instances to be terminated.
+     *            If this is null, the default value will be used. Default value is
+     *            {@link Constants}.DEFAULT_SUB_DOMAIN.
+     * @return whether an instance terminated successfully or not.
+     */
+    public boolean terminateAllInstances(String domainName, String subDomainName);
+
+    /**
+     * Calling this method will result in termination of an instance which is belong
+     * to the provided service domain and sub domain.
+     * 
+     * @param domainName
+     *            service domain of the instance to be terminated.
+     * @param sudDomainName
+     *            service clustering sub domain of the instance to be terminated.
+     *            If this is null, the default value will be used. Default value is
+     *            {@link Constants}.DEFAULT_SUB_DOMAIN.
+     * @return whether an instance terminated successfully or not.
+     */
+    public boolean terminateInstance(String domainName, String subDomainName);
+    
+    /**
+     * Calling this method will result in termination of the lastly spawned instance which is
+     * belong to the provided service domain and sub domain.
+     * 
+     * @param domainName
+     *            service domain of the instance to be terminated.
+     * @param sudDomainName
+     *            service clustering sub domain of the instance to be terminated.
+     *            If this is null, the default value will be used. Default value is
+     *            {@link Constants}.DEFAULT_SUB_DOMAIN.
+     * @return whether the termination is successful or not.
+     */
+    public boolean terminateLastlySpawnedInstance(String domainName, String subDomainName);
+
+    /**
+     * Unregister the service cluster which represents by this domain and sub domain.
+     * @param domain service cluster domain
+     * @param subDomain service cluster sub domain
+     * @return whether the unregistration was successful or not.
+     * @throws org.apache.stratos.cloud.controller.exception.UnregisteredServiceException if the service cluster requested is not a registered one.
+     */
+    public boolean unregisterService(String domain, String subDomain) throws UnregisteredServiceException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e8c32dac/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
new file mode 100644
index 0000000..ceb1bcb
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/interfaces/Iaas.java
@@ -0,0 +1,73 @@
+/*
+*  Copyright (c) 2005-2011, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+*
+*  WSO2 Inc. 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.interfaces;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.apache.stratos.cloud.controller.util.IaasProvider;
+
+/**
+ * All IaaSes that are going to support by Cloud Controller, should extend this abstract class.
+ */
+public abstract class Iaas {
+    
+    /**
+     * This should build the {@link ComputeService} object and the {@link Template} object,
+     * using the information from {@link IaasProvider} and should set the built 
+     * {@link ComputeService} object in the {@link IaasProvider#setComputeService(ComputeService)}
+     * and also should set the built {@link Template} object in the 
+     * {@link IaasProvider#setTemplate(Template)}.
+     * @param iaasInfo corresponding {@link IaasProvider}
+     */
+    public abstract void buildComputeServiceAndTemplate(IaasProvider iaasInfo);
+    
+    /**
+     * This method provides a way to set payload that can be obtained from {@link IaasProvider#getPayload()}
+     * in the {@link Template} of this IaaS.
+     * @param iaasInfo corresponding {@link IaasProvider}
+     */
+    public abstract void setDynamicPayload(IaasProvider iaasInfo);
+    
+    /**
+     * This will obtain an IP address from the allocated list and associate that IP with this node.
+     * @param iaasInfo corresponding {@link IaasProvider}
+     * @param node Node to be associated with an IP.
+     * @return associated public IP.
+     */
+    public abstract String associateAddress(IaasProvider iaasInfo, NodeMetadata node);
+    
+    /**
+     * This will deallocate/release the given IP address back to pool.
+     * @param iaasInfo corresponding {@link IaasProvider}
+     * @param ip public IP address to be released.
+     */
+    public abstract void releaseAddress(IaasProvider iaasInfo, String ip);
+    
+    /**
+     * This method should create a Key Pair corresponds to a given public key in the respective region having the name given.
+     * Also should override the value of the key pair in the {@link Template} of this IaaS.
+     * @param iaasInfo {@link IaasProvider} 
+     * @param region region that the key pair will get created.
+     * @param keyPairName name of the key pair. NOTE: Jclouds adds a prefix : <code>jclouds#</code>
+     * @param publicKey public key, from which the key pair will be created.
+     * @return whether the key pair creation is successful or not.
+     */
+    public abstract boolean createKeyPairFromPublicKey(IaasProvider iaasInfo, String region, String keyPairName, String publicKey);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e8c32dac/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/internal/CloudControllerDSComponent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/internal/CloudControllerDSComponent.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/internal/CloudControllerDSComponent.java
new file mode 100644
index 0000000..0152a75
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/internal/CloudControllerDSComponent.java
@@ -0,0 +1,85 @@
+package org.apache.stratos.cloud.controller.internal;
+
+import org.apache.stratos.cloud.controller.exception.CloudControllerException;
+import org.apache.stratos.cloud.controller.impl.CloudControllerServiceImpl;
+import org.apache.stratos.cloud.controller.interfaces.CloudControllerService;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.wso2.carbon.ntask.core.service.TaskService;
+import org.wso2.carbon.registry.core.exceptions.RegistryException;
+import org.wso2.carbon.registry.core.service.RegistryService;
+import org.apache.stratos.cloud.controller.topic.ConfigurationPublisher;
+import org.apache.stratos.cloud.controller.util.DeclarativeServiceReferenceHolder;
+
+/**
+ * Registering Cloud Controller Service.
+ * 
+ * @scr.component name="org.wso2.carbon.stratos.cloud.controller" immediate="true"
+ * @scr.reference name="ntask.component" interface="org.wso2.carbon.ntask.core.service.TaskService"
+ *                cardinality="1..1" policy="dynamic" bind="setTaskService"
+ *                unbind="unsetTaskService"
+ * @scr.reference name="registry.service"
+ *                interface=
+ *                "org.wso2.carbon.registry.core.service.RegistryService"
+ *                cardinality="1..1" policy="dynamic" bind="setRegistryService"
+ *                unbind="unsetRegistryService"
+ */
+public class CloudControllerDSComponent {
+
+    private static final Log log = LogFactory.getLog(CloudControllerDSComponent.class);
+
+    protected void activate(ComponentContext context) {
+        try {
+        	if (DeclarativeServiceReferenceHolder.getInstance().getConfigPub() == null) {
+        		DeclarativeServiceReferenceHolder.getInstance()
+        		.setConfigPub(new ConfigurationPublisher());
+        	}
+            
+            BundleContext bundleContext = context.getBundleContext();
+            bundleContext.registerService(CloudControllerService.class.getName(),
+                                          new CloudControllerServiceImpl(), null);
+            
+
+            log.debug("******* Cloud Controller Service bundle is activated ******* ");
+        } catch (Throwable e) {
+            log.error("******* Cloud Controller Service bundle is failed to activate ****", e);
+        }
+    }
+    
+    protected void setTaskService(TaskService taskService) {
+        if (log.isDebugEnabled()) {
+            log.debug("Setting the Task Service");
+        }
+        DeclarativeServiceReferenceHolder.getInstance().setTaskService(taskService);
+    }
+
+    protected void unsetTaskService(TaskService taskService) {
+        if (log.isDebugEnabled()) {
+            log.debug("Unsetting the Task Service");
+        }
+        DeclarativeServiceReferenceHolder.getInstance().setTaskService(null);
+    }
+    
+	protected void setRegistryService(RegistryService registryService) {
+		if (log.isDebugEnabled()) {
+			log.debug("Setting the Registry Service");
+		}
+		try {
+	        DeclarativeServiceReferenceHolder.getInstance()
+	                                             .setRegistry(registryService.getGovernanceSystemRegistry());
+        } catch (RegistryException e) {
+        	String msg = "Failed when retrieving Governance System Registry.";
+        	log.error(msg, e);
+        	throw new CloudControllerException(msg, e);
+        }
+	}
+
+	protected void unsetRegistryService(RegistryService registryService) {
+		if (log.isDebugEnabled()) {
+            log.debug("Unsetting the Registry Service");
+        }
+        DeclarativeServiceReferenceHolder.getInstance().setRegistry(null);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e8c32dac/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/jcloud/ComputeServiceBuilderUtil.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/jcloud/ComputeServiceBuilderUtil.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/jcloud/ComputeServiceBuilderUtil.java
new file mode 100644
index 0000000..e80f949
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/jcloud/ComputeServiceBuilderUtil.java
@@ -0,0 +1,182 @@
+/*
+*  Copyright (c) 2005-2011, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+*
+*  WSO2 Inc. 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.jcloud;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.stratos.cloud.controller.util.CloudControllerConstants;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.synapse.SynapseException;
+import org.jclouds.ContextBuilder;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.apache.stratos.cloud.controller.util.IaasProvider;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * This class is responsible for creating a JClouds specific ComputeService object.
+ */
+public class ComputeServiceBuilderUtil {
+    
+    private static final Log log = LogFactory.getLog(ComputeServiceBuilderUtil.class);
+    
+    public static byte[] getUserData(String payloadFileName) {
+        // String userData = null;
+        byte[] bytes = null;
+        try {
+            File file = new File(payloadFileName);
+            if (!file.exists()) {
+                handleException("Payload file " + payloadFileName + " does not exist");
+            }
+            if (!file.canRead()) {
+                handleException("Payload file " + payloadFileName + " does cannot be read");
+            }
+            bytes = getBytesFromFile(file);
+
+        } catch (IOException e) {
+            handleException("Cannot read data from payload file " + payloadFileName, e);
+        }
+        return bytes;
+    }
+
+    
+    public static void buildDefaultComputeService(IaasProvider iaas) {
+
+        Properties properties = new Properties();
+
+        // load properties
+        for (Map.Entry<String, String> entry : iaas.getProperties().entrySet()) {
+            properties.put(entry.getKey(), entry.getValue());
+        }
+
+        // set modules
+        Iterable<Module> modules =
+            ImmutableSet.<Module> of(new SshjSshClientModule(), new SLF4JLoggingModule(),
+                                     new EnterpriseConfigurationModule());
+
+        // build context
+        ContextBuilder builder =
+            ContextBuilder.newBuilder(iaas.getProvider())
+                          .credentials(iaas.getIdentity(), iaas.getCredential()).modules(modules)
+                          .overrides(properties);
+
+        // set the compute service object
+        iaas.setComputeService(builder.buildView(ComputeServiceContext.class).getComputeService());
+    }
+    
+    public static String extractRegion(IaasProvider iaas) {
+        String region;
+        // try to find region
+        if ((region = iaas.getProperty(CloudControllerConstants.REGION_PROPERTY)) == null) {
+            // if the property, isn't specified, try to obtain from the image id
+            // image id can be in following format - {region}/{UUID}
+            region = iaas.getImage().contains("/") ? iaas.getImage().split("/")[0] : null;
+        }
+
+        return region;
+    }
+    
+    /** Returns the contents of the file in a byte array
+     *
+     * @param file
+     *            - Input File
+     * @return Bytes from the file
+     * @throws java.io.IOException
+     *             , if retrieving the file contents failed.
+     */
+    public static byte[] getBytesFromFile(File file) throws IOException {
+        if (!file.exists()) {
+            log.error("Payload file " + file.getAbsolutePath() + " does not exist");
+            return null;
+        }
+        InputStream is = new FileInputStream(file);
+        byte[] bytes;
+
+        try {
+            // Get the size of the file
+            long length = file.length();
+            
+            // You cannot create an array using a long type.
+            // It needs to be an int type.
+            // Before converting to an int type, check
+            // to ensure that file is not larger than Integer.MAX_VALUE.
+            if (length > Integer.MAX_VALUE) {
+                if (log.isDebugEnabled()) {
+                    log.debug("File is too large");
+                }
+            }
+
+            // Create the byte array to hold the data
+            bytes = new byte[(int) length];
+
+            // Read in the bytes
+            int offset = 0;
+            int numRead;
+            while (offset < bytes.length &&
+                (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
+                offset += numRead;
+            }
+
+            // Ensure all the bytes have been read in
+            if (offset < bytes.length) {
+                throw new IOException("Could not completely read file " + file.getName());
+            }
+        } finally {
+            // Close the input stream and return bytes
+            is.close();
+         }
+        
+        return bytes;
+    }
+    
+    /**
+     * handles the exception
+     * 
+     * @param msg
+     *            exception message
+     */
+    private static void handleException(String msg) {
+        log.error(msg);
+        throw new SynapseException(msg);
+    }
+
+    /**
+     * handles the exception
+     * 
+     * @param msg
+     *            exception message
+     * @param e
+     *            exception
+     */
+    private static void handleException(String msg, Exception e) {
+        log.error(msg, e);
+        throw new SynapseException(msg, e);
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e8c32dac/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/persist/Deserializer.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/persist/Deserializer.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/persist/Deserializer.java
new file mode 100644
index 0000000..bafddb7
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/persist/Deserializer.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2005-2011, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ * 
+ * WSO2 Inc. 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.persist;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class Deserializer {
+    
+    private static final Log log = LogFactory.getLog(Deserializer.class);
+
+    /**
+     * We deserialize only if the path to the serialized object file is exists.
+     * @param filePath path to the serialized object file
+     * @return the object obtained after deserialization or null if file isn't valid.
+     * @throws Exception
+     */
+    public static Object deserialize(String filePath) throws Exception {
+
+        ObjectInputStream objIn = null; 
+        Object obj = null;
+        
+        if(!new File(filePath).isFile()){
+            return obj;
+        }
+        
+        try {
+
+            objIn = new ObjectInputStream(new FileInputStream(filePath));
+            obj = objIn.readObject();
+
+        } catch (IOException e) {
+            log.error("Failed to deserialize the file at "+filePath , e);
+            throw e;
+            
+        } catch (ClassNotFoundException e) {
+            log.error("Failed to deserialize the file at "+filePath , e);
+            throw e;
+            
+        } finally{
+            objIn.close();
+        }
+        
+        return obj;
+
+    }
+    
+    /**
+     * Deserialize a byte array and retrieve the object.
+     * @param bytes bytes to be deserialized
+     * @return the deserialized {@link Object}
+     * @throws Exception if the deserialization is failed.
+     */
+    public static Object deserializeFromByteArray(byte[] bytes) throws Exception {
+
+    	ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
+    	ObjectInput in = null;
+    	try {
+    	  in = new ObjectInputStream(bis);
+    	  Object o = in.readObject(); 
+    	  
+    	  return o;
+    	  
+    	} finally {
+    	  bis.close();
+    	  in.close();
+    	}
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e8c32dac/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/persist/Serializer.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/persist/Serializer.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/persist/Serializer.java
new file mode 100644
index 0000000..9ce69cb
--- /dev/null
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/persist/Serializer.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2005-2011, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ * 
+ * WSO2 Inc. 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.persist;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+
+import org.apache.stratos.cloud.controller.runtime.FasterLookUpDataHolder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class Serializer {
+    
+    private static final Log log = LogFactory.getLog(Serializer.class);
+
+    public static void serializeToFile(Object serializableObj, String filePath) throws IOException {
+
+        File outFile = new File(filePath);
+        ObjectOutput ObjOut = null;
+        
+        try {
+
+            if(outFile.createNewFile()){
+                log.debug("Serialization file is created at "+filePath);
+            } else{
+                log.debug("Serialization file is already existing at "+filePath);
+            }
+            
+            ObjOut = new ObjectOutputStream(new FileOutputStream(outFile));
+            ObjOut.writeObject(serializableObj);
+
+        } catch (IOException e) {
+            log.error("Failed to serialize the object "+serializableObj.toString()
+                      + " to file "+filePath , e);
+            throw e;
+            
+        } finally{
+            ObjOut.close();
+        }
+
+    }
+    
+    /**
+     * Serialize a {@link org.apache.stratos.cloud.controller.runtime.FasterLookUpDataHolder} to a byte array.
+     * @param serializableObj
+     * @return byte[] 
+     * @throws IOException
+     */
+    public static byte[] serializeToByteArray(FasterLookUpDataHolder serializableObj) throws IOException {
+
+    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
+    	ObjectOutput out = null;
+    	try {
+    	  out = new ObjectOutputStream(bos);   
+    	  out.writeObject(serializableObj);
+    	  
+    	  return bos.toByteArray();
+    	  
+    	} finally {
+    	  out.close();
+    	  bos.close();
+    	}
+
+    }
+
+}