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 2014/08/28 11:01:00 UTC

[1/2] merging messaging component

Repository: stratos
Updated Branches:
  refs/heads/4.0.0-grouping c9e3e7273 -> 8c14177f4


http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainRemovedMessageProcessor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainRemovedMessageProcessor.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainRemovedMessageProcessor.java
new file mode 100644
index 0000000..88b3690
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainRemovedMessageProcessor.java
@@ -0,0 +1,97 @@
+/*
+ * 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.messaging.message.processor.tenant;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.messaging.domain.tenant.Subscription;
+import org.apache.stratos.messaging.domain.tenant.Tenant;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainRemovedEvent;
+import org.apache.stratos.messaging.message.processor.MessageProcessor;
+import org.apache.stratos.messaging.message.receiver.tenant.TenantManager;
+import org.apache.stratos.messaging.util.Util;
+
+/**
+ * Subscription domain removed message processor for removing domains from tenant subscriptions.
+ */
+public class SubscriptionDomainRemovedMessageProcessor extends MessageProcessor {
+
+    private static final Log log = LogFactory.getLog(SubscriptionDomainRemovedMessageProcessor.class);
+
+    private MessageProcessor nextProcessor;
+
+    @Override
+    public void setNext(MessageProcessor nextProcessor) {
+        this.nextProcessor = nextProcessor;
+    }
+
+    @Override
+    public boolean process(String type, String message, Object object) {
+        if (SubscriptionDomainRemovedEvent.class.getName().equals(type)) {
+            // Return if tenant manager has not initialized
+            if (!TenantManager.getInstance().isInitialized()) {
+                return false;
+            }
+
+            // Parse complete message and build event
+            SubscriptionDomainRemovedEvent event = (SubscriptionDomainRemovedEvent) Util.jsonToObject(message, SubscriptionDomainRemovedEvent.class);
+
+            try {
+                TenantManager.acquireWriteLock();
+                Tenant tenant = TenantManager.getInstance().getTenant(event.getTenantId());
+                if(tenant == null) {
+                    if(log.isWarnEnabled()) {
+                        log.warn(String.format("Tenant not found: [tenant-id] %d", event.getTenantId()));
+                    }
+                    return false;
+                }
+                Subscription subscription = tenant.getSubscription(event.getServiceName());
+
+                if (subscription == null) {
+                    if (log.isWarnEnabled()) {
+                        log.warn(String.format("Subscription not found: [tenant-id] %d", event.getTenantId()));
+                    }
+                    return false;
+                }
+                subscription.removeSubscriptionDomain(event.getDomainName());
+                if(log.isInfoEnabled()) {
+                    log.info(String.format("Domain removed from tenant subscription: [tenant-id] %d [tenant-domain] %s " +
+                            "[service] %s [domain-name] %s", tenant.getTenantId(), tenant.getTenantDomain(),
+                            event.getServiceName(), event.getDomainName()));
+
+                }
+
+                // Notify event listeners
+                notifyEventListeners(event);
+                return true;
+            }
+            finally {
+                TenantManager.releaseWriteLock();
+            }
+        }
+        else {
+            if (nextProcessor != null) {
+                return nextProcessor.process(type, message, object);
+            } else {
+                throw new RuntimeException(String.format("Failed to process tenant message using available message processors: [type] %s [body] %s", type, message));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantSubscribedMessageProcessor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantSubscribedMessageProcessor.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantSubscribedMessageProcessor.java
index aae074b..196bc22 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantSubscribedMessageProcessor.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantSubscribedMessageProcessor.java
@@ -21,6 +21,8 @@ package org.apache.stratos.messaging.message.processor.tenant;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.messaging.domain.tenant.Subscription;
+import org.apache.stratos.messaging.domain.tenant.SubscriptionDomain;
 import org.apache.stratos.messaging.domain.tenant.Tenant;
 import org.apache.stratos.messaging.event.tenant.TenantSubscribedEvent;
 import org.apache.stratos.messaging.message.processor.MessageProcessor;
@@ -62,7 +64,8 @@ public class TenantSubscribedMessageProcessor extends MessageProcessor {
                     }
                     return false;
                 }
-                tenant.addServiceSubscription(event.getServiceName());
+                Subscription subscription = new Subscription(event.getServiceName(), event.getClusterIds());
+                tenant.addSubscription(subscription);
                 if(log.isInfoEnabled()) {
                     log.info(String.format("Tenant subscribed to service: [tenant-id] %d [tenant-domain] %s [service] %s",
                              tenant.getTenantId(), tenant.getTenantDomain(), event.getServiceName()));

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantUnSubscribedMessageProcessor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantUnSubscribedMessageProcessor.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantUnSubscribedMessageProcessor.java
index 6c4157c..ee929a3 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantUnSubscribedMessageProcessor.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantUnSubscribedMessageProcessor.java
@@ -62,7 +62,7 @@ public class TenantUnSubscribedMessageProcessor extends MessageProcessor {
                     }
                     return false;
                 }
-                tenant.removeServiceSubscription(event.getServiceName());
+                tenant.removeSubscription(event.getServiceName());
                 if(log.isInfoEnabled()) {
                     log.info(String.format("Tenant un-subscribed from service: [tenant-id] %d [tenant-domain] %s [service] %s",
                             tenant.getTenantId(), tenant.getTenantDomain(), event.getServiceName()));

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/ClusterMaintenanceModeMessageProcessor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/ClusterMaintenanceModeMessageProcessor.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/ClusterMaintenanceModeMessageProcessor.java
new file mode 100644
index 0000000..0300b24
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/ClusterMaintenanceModeMessageProcessor.java
@@ -0,0 +1,115 @@
+/*
+ * 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.messaging.message.processor.topology;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.messaging.domain.topology.Cluster;
+import org.apache.stratos.messaging.domain.topology.ClusterStatus;
+import org.apache.stratos.messaging.domain.topology.Service;
+import org.apache.stratos.messaging.domain.topology.Topology;
+import org.apache.stratos.messaging.event.topology.ClusterMaintenanceModeEvent;
+import org.apache.stratos.messaging.message.filter.topology.TopologyClusterFilter;
+import org.apache.stratos.messaging.message.filter.topology.TopologyServiceFilter;
+import org.apache.stratos.messaging.message.processor.MessageProcessor;
+import org.apache.stratos.messaging.util.Util;
+
+public class ClusterMaintenanceModeMessageProcessor extends MessageProcessor {
+    private static final Log log = LogFactory.getLog(ClusterMaintenanceModeMessageProcessor.class);
+    private MessageProcessor nextProcessor;
+
+    @Override
+    public void setNext(MessageProcessor nextProcessor) {
+        this.nextProcessor = nextProcessor;
+    }
+
+    @Override
+    public boolean process(String type, String message, Object object) {
+        Topology topology = (Topology) object;
+
+        if (ClusterMaintenanceModeEvent.class.getName().equals(type)) {
+            // Return if topology has not been initialized
+            if (!topology.isInitialized())
+                return false;
+
+            // Parse complete message and build event
+            ClusterMaintenanceModeEvent event = (ClusterMaintenanceModeEvent) Util.
+                                jsonToObject(message, ClusterMaintenanceModeEvent.class);
+
+            // Apply service filter
+            if (TopologyServiceFilter.getInstance().isActive()) {
+                if (TopologyServiceFilter.getInstance().serviceNameExcluded(event.getServiceName())) {
+                    // Service is excluded, do not update topology or fire event
+                    if (log.isDebugEnabled()) {
+                        log.debug(String.format("Service is excluded: [service] %s", event.getServiceName()));
+                    }
+                    return false;
+                }
+            }
+
+            // Apply cluster filter
+            if (TopologyClusterFilter.getInstance().isActive()) {
+                if (TopologyClusterFilter.getInstance().clusterIdExcluded(event.getClusterId())) {
+                    // Cluster is excluded, do not update topology or fire event
+                    if (log.isDebugEnabled()) {
+                        log.debug(String.format("Cluster is excluded: [cluster] %s", event.getClusterId()));
+                    }
+                    return false;
+                }
+            }
+
+            // Validate event against the existing topology
+            Service service = topology.getService(event.getServiceName());
+            if (service == null) {
+                if (log.isWarnEnabled()) {
+                    log.warn(String.format("Service does not exist: [service] %s",
+                            event.getServiceName()));
+                }
+                return false;
+            }
+            Cluster cluster = service.getCluster(event.getClusterId());
+
+            if (cluster == null) {
+                if (log.isWarnEnabled()) {
+                    log.warn(String.format("Cluster not exists in service: [service] %s [cluster] %s", event.getServiceName(),
+                            event.getClusterId()));
+                }
+			} else {
+			    // Apply changes to the topology
+                cluster.setStatus(ClusterStatus.In_Maintenance);
+				if (log.isInfoEnabled()) {
+					log.info(String.format("Cluster updated as maintenance mode: %s",
+							cluster.toString()));
+				}
+			}
+
+            // Notify event listeners
+            notifyEventListeners(event);
+            return true;
+
+        } else {
+            if (nextProcessor != null) {
+                // ask the next processor to take care of the message.
+                return nextProcessor.process(type, message, topology);
+            } else {
+                throw new RuntimeException(String.format("Failed to process message using available message processors: [type] %s [body] %s", type, message));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java
index 98b3725..8303bee 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/StratosAdmin.java
@@ -18,6 +18,7 @@
  */
 package org.apache.stratos.rest.endpoint.services;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.common.beans.TenantInfoBean;
@@ -27,14 +28,18 @@ import org.apache.stratos.common.util.CommonUtil;
 import org.apache.stratos.manager.composite.application.beans.CompositeAppDefinition;
 import org.apache.stratos.manager.dto.Cartridge;
 import org.apache.stratos.manager.dto.SubscriptionInfo;
+import org.apache.stratos.manager.exception.DomainMappingExistsException;
+import org.apache.stratos.manager.exception.ServiceDoesNotExistException;
 import org.apache.stratos.manager.grouping.definitions.ServiceGroupDefinition;
 import org.apache.stratos.manager.subscription.CartridgeSubscription;
+import org.apache.stratos.manager.subscription.SubscriptionDomain;
 import org.apache.stratos.rest.endpoint.ServiceHolder;
 import org.apache.stratos.rest.endpoint.Utils;
 import org.apache.stratos.rest.endpoint.annotation.AuthorizationAction;
 import org.apache.stratos.rest.endpoint.annotation.SuperTenantService;
 import org.apache.stratos.rest.endpoint.bean.CartridgeInfoBean;
 import org.apache.stratos.rest.endpoint.bean.StratosAdminResponse;
+import org.apache.stratos.rest.endpoint.bean.SubscriptionDomainRequest;
 import org.apache.stratos.rest.endpoint.bean.autoscaler.partition.Partition;
 import org.apache.stratos.rest.endpoint.bean.autoscaler.partition.PartitionGroup;
 import org.apache.stratos.rest.endpoint.bean.autoscaler.policy.autoscale.AutoscalePolicy;
@@ -42,8 +47,11 @@ import org.apache.stratos.rest.endpoint.bean.autoscaler.policy.deployment.Deploy
 import org.apache.stratos.rest.endpoint.bean.cartridge.definition.CartridgeDefinitionBean;
 import org.apache.stratos.rest.endpoint.bean.cartridge.definition.ServiceDefinitionBean;
 import org.apache.stratos.rest.endpoint.bean.repositoryNotificationInfoBean.Payload;
+import org.apache.stratos.rest.endpoint.bean.repositoryNotificationInfoBean.Repository;
+import org.apache.stratos.rest.endpoint.bean.subscription.domain.SubscriptionDomainBean;
 import org.apache.stratos.rest.endpoint.bean.topology.Cluster;
 import org.apache.stratos.rest.endpoint.exception.RestAPIException;
+import org.apache.stratos.rest.endpoint.exception.TenantNotFoundException;
 import org.apache.stratos.tenant.mgt.core.TenantPersistor;
 import org.apache.stratos.tenant.mgt.util.TenantMgtUtil;
 import org.wso2.carbon.context.PrivilegedCarbonContext;
@@ -70,6 +78,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
+import static javax.ws.rs.core.Response.ResponseBuilder;
+
 @Path("/admin/")
 public class StratosAdmin extends AbstractAdmin {
     private static Log log = LogFactory.getLog(StratosAdmin.class);
@@ -78,12 +88,14 @@ public class StratosAdmin extends AbstractAdmin {
     @Context
     UriInfo uriInfo;
 
+
     @POST
     @Path("/init")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     public StratosAdminResponse initialize ()
             throws RestAPIException {
 
+
         StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
         stratosAdminResponse.setMessage("Successfully logged in");
         return stratosAdminResponse;
@@ -229,9 +241,10 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse unDeployCartridgeDefinition (@PathParam("cartridgeType") String cartridgeType) throws RestAPIException {
+    public Response unDeployCartridgeDefinition (@PathParam("cartridgeType") String cartridgeType) throws RestAPIException {
 
-        return ServiceUtils.undeployCartridge(cartridgeType);
+        ServiceUtils.undeployCartridge(cartridgeType);
+        return Response.noContent().build();
     }
 
     @POST
@@ -278,10 +291,12 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse deployPartition (Partition partition)
+    public Response deployPartition (Partition partition)
             throws RestAPIException {
 
-            return ServiceUtils.deployPartition(partition);
+        ServiceUtils.deployPartition(partition);
+        URI url =  uriInfo.getAbsolutePathBuilder().path(partition.id).build();
+        return Response.created(url).build();
     }
 
     @POST
@@ -290,10 +305,12 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse deployAutoscalingPolicyDefintion (AutoscalePolicy autoscalePolicy)
+    public Response deployAutoscalingPolicyDefintion (AutoscalePolicy autoscalePolicy)
             throws RestAPIException {
 
-        return ServiceUtils.deployAutoscalingPolicy(autoscalePolicy);
+        ServiceUtils.deployAutoscalingPolicy(autoscalePolicy);
+        URI url =  uriInfo.getAbsolutePathBuilder().path(autoscalePolicy.getId()).build();
+        return Response.created(url).build();
     }
 
     @POST
@@ -302,10 +319,12 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse deployDeploymentPolicyDefinition (DeploymentPolicy deploymentPolicy)
+    public Response deployDeploymentPolicyDefinition (DeploymentPolicy deploymentPolicy)
             throws RestAPIException {
 
-        return ServiceUtils.deployDeploymentPolicy(deploymentPolicy);
+        ServiceUtils.deployDeploymentPolicy(deploymentPolicy);
+        URI url =  uriInfo.getAbsolutePathBuilder().path(deploymentPolicy.id).build();
+        return Response.created(url).build();
     }
 
     @GET
@@ -313,9 +332,8 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Partition[] getPartitions () throws RestAPIException {
-
-        return ServiceUtils.getAvailablePartitions();
+    public Response getPartitions () throws RestAPIException {
+        return Response.ok().entity(ServiceUtils.getAvailablePartitions()).build();
     }
 
     @GET
@@ -323,9 +341,8 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Partition getPartition (@PathParam("partitionId") String partitionId) throws RestAPIException {
-
-        return ServiceUtils.getPartition(partitionId);
+    public Response getPartition (@PathParam("partitionId") String partitionId) throws RestAPIException {
+        return Response.ok().entity(ServiceUtils.getPartition(partitionId)).build();
     }
 
     @GET
@@ -333,10 +350,9 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public PartitionGroup[] getPartitionGroups (@PathParam("deploymentPolicyId") String deploymentPolicyId)
+    public Response getPartitionGroups (@PathParam("deploymentPolicyId") String deploymentPolicyId)
             throws RestAPIException {
-
-        return ServiceUtils.getPartitionGroups(deploymentPolicyId);
+        return Response.ok().entity(ServiceUtils.getPartitionGroups(deploymentPolicyId)).build();
     }
 
     @GET
@@ -344,10 +360,9 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Partition [] getPartitions (@PathParam("deploymentPolicyId") String deploymentPolicyId,
+    public Response getPartitions (@PathParam("deploymentPolicyId") String deploymentPolicyId,
                                        @PathParam("partitionGroupId") String partitionGroupId) throws RestAPIException {
-
-        return ServiceUtils.getPartitionsOfGroup(deploymentPolicyId, partitionGroupId);
+        return Response.ok().entity(ServiceUtils.getPartitionsOfGroup(deploymentPolicyId, partitionGroupId)).build();
     }
     
     @GET
@@ -355,10 +370,10 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Partition [] getPartitionsOfPolicy (@PathParam("deploymentPolicyId") String deploymentPolicyId)
+    public Response getPartitionsOfPolicy (@PathParam("deploymentPolicyId") String deploymentPolicyId)
             throws RestAPIException {
 
-        return ServiceUtils.getPartitionsOfDeploymentPolicy(deploymentPolicyId);
+        return Response.ok().entity(ServiceUtils.getPartitionsOfDeploymentPolicy(deploymentPolicyId)).build();
     }
 
     @GET
@@ -366,9 +381,8 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public AutoscalePolicy[] getAutoscalePolicies () throws RestAPIException {
-
-        return ServiceUtils.getAutoScalePolicies();
+    public Response getAutoscalePolicies () throws RestAPIException {
+        return Response.ok().entity(ServiceUtils.getAutoScalePolicies()).build();
     }
 
     @GET
@@ -376,10 +390,9 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public AutoscalePolicy getAutoscalePolicies (@PathParam("autoscalePolicyId") String autoscalePolicyId)
+    public Response getAutoscalePolicies (@PathParam("autoscalePolicyId") String autoscalePolicyId)
             throws RestAPIException {
-
-        return ServiceUtils.getAutoScalePolicy(autoscalePolicyId);
+        return Response.ok().entity(ServiceUtils.getAutoScalePolicy(autoscalePolicyId)).build();
     }
 
     @GET
@@ -387,9 +400,8 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public DeploymentPolicy[] getDeploymentPolicies () throws RestAPIException {
-
-        return ServiceUtils.getDeploymentPolicies();
+    public Response getDeploymentPolicies () throws RestAPIException {
+        return Response.ok().entity(ServiceUtils.getDeploymentPolicies()).build();
     }
 
     @GET
@@ -397,10 +409,9 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public DeploymentPolicy getDeploymentPolicies (@PathParam("deploymentPolicyId") String deploymentPolicyId)
+    public Response getDeploymentPolicies (@PathParam("deploymentPolicyId") String deploymentPolicyId)
             throws RestAPIException {
-
-        return ServiceUtils.getDeploymentPolicy(deploymentPolicyId);
+        return Response.ok().entity(ServiceUtils.getDeploymentPolicy(deploymentPolicyId)).build();
     }
 
     @GET
@@ -408,10 +419,9 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public DeploymentPolicy[] getValidDeploymentPolicies (@PathParam("cartridgeType") String cartridgeType)
+    public Response getValidDeploymentPolicies (@PathParam("cartridgeType") String cartridgeType)
             throws RestAPIException {
-
-        return ServiceUtils.getDeploymentPolicies(cartridgeType);
+        return Response.ok().entity(ServiceUtils.getDeploymentPolicies(cartridgeType)).build();
     }
 
     @GET
@@ -419,9 +429,11 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cartridge[] getAvailableMultiTenantCartridges() throws RestAPIException {
+    public Response getAvailableMultiTenantCartridges() throws RestAPIException {
         List<Cartridge> cartridges = ServiceUtils.getAvailableCartridges(null, true, getConfigContext());
-        return cartridges.isEmpty() ? new Cartridge[0] : cartridges.toArray(new Cartridge[cartridges.size()]);
+        ResponseBuilder rb = Response.ok();
+        rb.entity(cartridges.isEmpty() ? new Cartridge[0] : cartridges.toArray(new Cartridge[cartridges.size()]));
+        return rb.build();
     }
 
     @GET
@@ -429,9 +441,11 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cartridge[] getAvailableSingleTenantCartridges() throws RestAPIException {
+    public Response getAvailableSingleTenantCartridges() throws RestAPIException {
         List<Cartridge> cartridges = ServiceUtils.getAvailableCartridges(null, false, getConfigContext());
-        return cartridges.isEmpty() ? new Cartridge[0] : cartridges.toArray(new Cartridge[cartridges.size()]);
+        ResponseBuilder rb = Response.ok();
+        rb.entity(cartridges.isEmpty() ? new Cartridge[0] : cartridges.toArray(new Cartridge[cartridges.size()]));
+        return rb.build();
     }
 
     @GET
@@ -439,9 +453,11 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cartridge[] getAvailableCartridges() throws RestAPIException {
+    public Response getAvailableCartridges() throws RestAPIException {
         List<Cartridge> cartridges = ServiceUtils.getAvailableCartridges(null, null, getConfigContext());
-        return cartridges.isEmpty() ? new Cartridge[0] : cartridges.toArray(new Cartridge[cartridges.size()]);
+        ResponseBuilder rb = Response.ok();
+        rb.entity(cartridges.isEmpty() ? new Cartridge[0] : cartridges.toArray(new Cartridge[cartridges.size()]));
+        return rb.build();
     }
 
     @GET
@@ -449,10 +465,25 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cartridge[] getSubscribedCartridges() throws RestAPIException {
-        List<Cartridge> cartridgeList = ServiceUtils.getSubscriptions(null, getConfigContext());
+    public Response getSubscribedCartridges() throws RestAPIException {
+        List<Cartridge> cartridgeList = ServiceUtils.getSubscriptions(null,null, getConfigContext());
+        // Following is very important when working with axis2
+        ResponseBuilder rb = Response.ok();
+        rb.entity(cartridgeList.isEmpty() ? new Cartridge[0] : cartridgeList.toArray(new Cartridge[cartridgeList.size()]));
+        return rb.build();
+    }
+
+    @GET
+    @Path("/cartridge/list/subscribed/group/{serviceGroup}")
+    @Produces("application/json")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Response getSubscribedCartridgesForServiceGroup(@PathParam("serviceGroup") String serviceGroup) throws RestAPIException {
+        List<Cartridge> cartridgeList = ServiceUtils.getSubscriptions(null, serviceGroup, getConfigContext());
         // Following is very important when working with axis2
-        return cartridgeList.isEmpty() ? new Cartridge[0] : cartridgeList.toArray(new Cartridge[cartridgeList.size()]);
+        ResponseBuilder rb = Response.ok();
+        rb.entity(cartridgeList.isEmpty() ? new Cartridge[0] : cartridgeList.toArray(new Cartridge[cartridgeList.size()]));
+        return rb.build();
     }
     
     @GET
@@ -460,8 +491,10 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cartridge getCartridgeInfo(@PathParam("subscriptionAlias") String subscriptionAlias) throws RestAPIException {
-        return ServiceUtils.getSubscription(subscriptionAlias, getConfigContext());
+    public Response getCartridgeInfo(@PathParam("subscriptionAlias") String subscriptionAlias) throws RestAPIException {
+        ResponseBuilder rb = Response.ok();
+        rb.entity(ServiceUtils.getSubscription(subscriptionAlias, getConfigContext()));
+        return rb.build();
     }
 
     @GET
@@ -469,9 +502,11 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cartridge getAvailableSingleTenantCartridgeInfo(@PathParam("cartridgeType") String cartridgeType)
+    public Response getAvailableSingleTenantCartridgeInfo(@PathParam("cartridgeType") String cartridgeType)
                                             throws RestAPIException {
-        return ServiceUtils.getAvailableCartridgeInfo(cartridgeType, null, getConfigContext());
+        ResponseBuilder rb = Response.ok();
+        rb.entity(ServiceUtils.getAvailableCartridgeInfo(cartridgeType, null, getConfigContext()));
+        return rb.build();
     }
 
     @GET
@@ -479,9 +514,8 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public List<Cartridge> getAvailableLbCartridges()
-                                            throws RestAPIException {
-        return ServiceUtils.getAvailableLbCartridges(false, getConfigContext());
+    public Response getAvailableLbCartridges() throws RestAPIException {
+        return Response.ok().entity(ServiceUtils.getAvailableLbCartridges(false, getConfigContext())).build();
     }
 
     @GET
@@ -489,9 +523,11 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public int getActiveInstances(@PathParam("cartridgeType") String cartridgeType,
+    public Response getActiveInstances(@PathParam("cartridgeType") String cartridgeType,
                               @PathParam("subscriptionAlias") String subscriptionAlias) throws RestAPIException {
-        return ServiceUtils.getActiveInstances(cartridgeType, subscriptionAlias, getConfigContext());
+        ResponseBuilder rb = Response.ok();
+        rb.entity(ServiceUtils.getActiveInstances(cartridgeType, subscriptionAlias, getConfigContext()));
+        return rb.build();
     }
 
     @POST
@@ -499,12 +535,13 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public SubscriptionInfo subscribe(CartridgeInfoBean cartridgeInfoBean) throws RestAPIException {
+    public Response subscribe(CartridgeInfoBean cartridgeInfoBean) throws RestAPIException {
 
-        return ServiceUtils.subscribeToCartridge(cartridgeInfoBean,
+        SubscriptionInfo subscriptionInfo= ServiceUtils.subscribe(cartridgeInfoBean,
                 getConfigContext(),
                 getUsername(),
                 getTenantDomain());
+        return Response.ok(subscriptionInfo).build();
     }
 
     @GET
@@ -512,9 +549,8 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cluster[] getClustersForTenant() throws RestAPIException {
-
-        return ServiceUtils.getClustersForTenant(getConfigContext());
+    public Response getClustersForTenant() throws RestAPIException {
+        return Response.ok().entity(ServiceUtils.getClustersForTenant(getConfigContext())).build();
     }
 
     @GET
@@ -522,9 +558,22 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cluster[] getClusters(@PathParam("cartridgeType") String cartridgeType) throws RestAPIException {
+    public Response getClusters(@PathParam("cartridgeType") String cartridgeType) throws RestAPIException {
 
-        return ServiceUtils.getClustersForTenantAndCartridgeType(getConfigContext(), cartridgeType);
+        ResponseBuilder rb = Response.ok();
+        rb.entity(ServiceUtils.getClustersForTenantAndCartridgeType(getConfigContext(), cartridgeType));
+        return rb.build();
+    }
+    
+    @GET
+    @Path("/cluster/service/{cartridgeType}/")
+    @Produces("application/json")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Response getServiceClusters(@PathParam("cartridgeType") String cartridgeType) throws RestAPIException {
+        ResponseBuilder rb = Response.ok();
+        rb.entity(ServiceUtils.getClustersForTenantAndCartridgeType(getConfigContext(), cartridgeType));
+        return rb.build();
     }
 
     @GET
@@ -532,10 +581,11 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cluster getCluster(@PathParam("cartridgeType") String cartridgeType,
+    public Response getCluster(@PathParam("cartridgeType") String cartridgeType,
                               @PathParam("subscriptionAlias") String subscriptionAlias) throws RestAPIException, RestAPIException {
-
-        return ServiceUtils.getCluster(cartridgeType, subscriptionAlias, getConfigContext());
+        ResponseBuilder rb = Response.ok();
+        rb.entity(ServiceUtils.getCluster(cartridgeType, subscriptionAlias, getConfigContext()));
+        return rb.build();
     }
     
     @GET
@@ -543,10 +593,10 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public Cluster getCluster(@PathParam("clusterId") String clusterId) throws RestAPIException {
+    public Response getCluster(@PathParam("clusterId") String clusterId) throws RestAPIException {
     	Cluster cluster = null;
     	if(log.isDebugEnabled()) {
-    		log.debug("Finding the Cluster for [id]: "+clusterId);
+    		log.debug("Finding cluster for [id]: "+clusterId);
     	}
         Cluster[] clusters = ServiceUtils.getClustersForTenant(getConfigContext());
         if(log.isDebugEnabled()) {
@@ -561,17 +611,16 @@ public class StratosAdmin extends AbstractAdmin {
 				break;
 			}
 		}
-        return cluster;
+        return Response.ok().entity(cluster).build();
     }
 
     @POST
     @Path("/cartridge/unsubscribe")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public StratosAdminResponse unsubscribe(String alias) throws RestAPIException {
-
-        return ServiceUtils.unsubscribe(alias, getTenantDomain());
-
+    public Response unsubscribe(String alias) throws RestAPIException {
+        ServiceUtils.unsubscribe(alias, getTenantDomain());
+        return Response.noContent().build();
     }
 
     @POST
@@ -580,7 +629,7 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse addTenant(TenantInfoBean tenantInfoBean) throws RestAPIException {
+    public Response addTenant(TenantInfoBean tenantInfoBean) throws RestAPIException {
         try {
             CommonUtil.validateEmail(tenantInfoBean.getEmail());
         } catch (Exception e) {
@@ -655,9 +704,8 @@ public class StratosAdmin extends AbstractAdmin {
             throw new RestAPIException(msg);
         }
 
-        StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
-        stratosAdminResponse.setMessage("Successfully added new tenant with domain " + tenantInfoBean.getTenantDomain());
-        return stratosAdminResponse;
+        URI url =  uriInfo.getAbsolutePathBuilder().path(tenant.getDomain()).build();
+        return Response.created(url).build();
     }
 
     @PUT
@@ -665,18 +713,23 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse updateTenant(TenantInfoBean tenantInfoBean) throws RestAPIException {
+    public Response updateTenant(TenantInfoBean tenantInfoBean) throws RestAPIException {
 
         try {
-            return updateExistingTenant(tenantInfoBean);
-        } catch (Exception e) {
+            updateExistingTenant(tenantInfoBean);
+
+        } catch(TenantNotFoundException ex){
+            Response.status(Response.Status.NOT_FOUND).build();
+        }catch (Exception e) {
             String msg = "Error in updating tenant " + tenantInfoBean.getTenantDomain();
             log.error(msg, e);
             throw new RestAPIException(msg);
         }
+
+        return Response.noContent().build();
     }
 
-    private StratosAdminResponse updateExistingTenant(TenantInfoBean tenantInfoBean) throws Exception {
+    private void updateExistingTenant(TenantInfoBean tenantInfoBean) throws Exception {
 
         TenantManager tenantManager = ServiceHolder.getTenantManager();
         UserStoreManager userStoreManager;
@@ -704,7 +757,7 @@ public class StratosAdmin extends AbstractAdmin {
             String msg = "Error in retrieving the tenant id for the tenant domain: " +
                     tenantDomain + ".";
             log.error(msg, e);
-            throw new Exception(msg, e);
+            throw new TenantNotFoundException(msg,e);
         }
 
         // filling the first and last name values
@@ -795,10 +848,6 @@ public class StratosAdmin extends AbstractAdmin {
             log.error(msg, e);
             throw new Exception(msg, e);
         }
-
-        StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
-        stratosAdminResponse.setMessage("Successfully updated the tenant " + tenantDomain);
-        return stratosAdminResponse;
     }
 
     @GET
@@ -867,7 +916,7 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse deleteTenant(@PathParam("tenantDomain") String tenantDomain) throws RestAPIException {
+    public Response deleteTenant(@PathParam("tenantDomain") String tenantDomain) throws RestAPIException {
         TenantManager tenantManager = ServiceHolder.getTenantManager();
         int tenantId = 0;
         try {
@@ -875,7 +924,8 @@ public class StratosAdmin extends AbstractAdmin {
         } catch (org.wso2.carbon.user.api.UserStoreException e) {
             String msg = "Error in deleting tenant " + tenantDomain;
             log.error(msg, e);
-            throw new RestAPIException(msg);
+            //throw new RestAPIException(msg);
+            return Response.status(Response.Status.NOT_FOUND).build();
         }
         try {
             //TODO: billing related info cleanup
@@ -891,9 +941,7 @@ public class StratosAdmin extends AbstractAdmin {
             throw new RestAPIException(msg);
         }
 
-        StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
-        stratosAdminResponse.setMessage("Successfully deleted tenant " + tenantDomain);
-        return stratosAdminResponse;
+        return Response.noContent().build();
     }
 
     @GET
@@ -936,7 +984,7 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse activateTenant(@PathParam("tenantDomain") String tenantDomain) throws RestAPIException {
+    public Response activateTenant(@PathParam("tenantDomain") String tenantDomain) throws RestAPIException {
         TenantManager tenantManager = ServiceHolder.getTenantManager();
         int tenantId;
         try {
@@ -952,8 +1000,6 @@ public class StratosAdmin extends AbstractAdmin {
             throw new RestAPIException( e);
         }
 
-        StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
-
         try {
             TenantMgtUtil.activateTenant(tenantDomain, tenantManager, tenantId);
 
@@ -970,8 +1016,7 @@ public class StratosAdmin extends AbstractAdmin {
             throw new RestAPIException(msg, e);
         }
 
-        stratosAdminResponse.setMessage("Successfully activated tenant " + tenantDomain);
-        return stratosAdminResponse;
+        return Response.noContent().build();
     }
 
     @POST
@@ -979,15 +1024,16 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public boolean isDomainAvailable(@PathParam("tenantDomain") String tenantDomain) throws RestAPIException {
+    public Response isDomainAvailable(@PathParam("tenantDomain") String tenantDomain) throws RestAPIException {
+        boolean available;
         try {
-            return CommonUtil.isDomainNameAvailable(tenantDomain);
+            available = CommonUtil.isDomainNameAvailable(tenantDomain);
         } catch (Exception e) {
             String msg = "Error in checking domain " + tenantDomain + " is available";
             log.error(msg, e);
             throw new RestAPIException(msg);
         }
-
+        return Response.ok(available).build();
     }
 
     @POST
@@ -995,7 +1041,7 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse deactivateTenant(@PathParam("tenantDomain") String tenantDomain) throws RestAPIException {
+    public Response deactivateTenant(@PathParam("tenantDomain") String tenantDomain) throws RestAPIException {
 
         TenantManager tenantManager = ServiceHolder.getTenantManager();
         int tenantId;
@@ -1013,8 +1059,6 @@ public class StratosAdmin extends AbstractAdmin {
             throw new RestAPIException( e);
         }
 
-        StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
-
         try {
             TenantMgtUtil.deactivateTenant(tenantDomain, tenantManager, tenantId);
         } catch (Exception e) {
@@ -1030,8 +1074,7 @@ public class StratosAdmin extends AbstractAdmin {
             throw new RestAPIException(msg, e);
         }
 
-        stratosAdminResponse.setMessage("Successfully deactivated tenant " + tenantDomain);
-        return stratosAdminResponse;
+        return Response.noContent().build();
     }
 
     @POST
@@ -1040,16 +1083,19 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse deployService (ServiceDefinitionBean serviceDefinitionBean)
+    public Response deployService (ServiceDefinitionBean serviceDefinitionBean)
             throws RestAPIException {
 
     	log.info("Service definition request.. : " + serviceDefinitionBean.getServiceName());
     	// super tenant Deploying service (MT) 
     	// here an alias is generated
-       return ServiceUtils.deployService(serviceDefinitionBean.getCartridgeType(), UUID.randomUUID().toString(), serviceDefinitionBean.getAutoscalingPolicyName(),
+       ServiceUtils.deployService(serviceDefinitionBean.getCartridgeType(), UUID.randomUUID().toString(), serviceDefinitionBean.getAutoscalingPolicyName(),
                serviceDefinitionBean.getDeploymentPolicyName(), getTenantDomain(), getUsername(), getTenantId(),
                serviceDefinitionBean.getClusterDomain(), serviceDefinitionBean.getClusterSubDomain(),
                serviceDefinitionBean.getTenantRange());
+
+        URI url =  uriInfo.getAbsolutePathBuilder().path(serviceDefinitionBean.getServiceName()).build();
+        return Response.created(url).build();
     }
 
     @GET
@@ -1068,9 +1114,15 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public ServiceDefinitionBean getService(@PathParam("serviceType") String serviceType)throws RestAPIException {
-
-        return ServiceUtils.getDeployedServiceInformation(serviceType);
+    public Response getService(@PathParam("serviceType") String serviceType)throws RestAPIException {
+        ResponseBuilder rb;
+        ServiceDefinitionBean serviceDefinitionBean = ServiceUtils.getDeployedServiceInformation(serviceType);
+        if(serviceDefinitionBean == null){
+            rb = Response.status(Response.Status.NOT_FOUND);
+        }else{
+            rb = Response.ok(serviceDefinitionBean);
+        }
+        return rb.build();
     }
 
     @GET
@@ -1089,10 +1141,13 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     @SuperTenantService(true)
-    public StratosAdminResponse unDeployService (@PathParam("serviceType") String serviceType)
-            throws RestAPIException {
-
-        return ServiceUtils.undeployService(serviceType);
+    public Response unDeployService (@PathParam("serviceType") String serviceType) throws RestAPIException {
+        try {
+            ServiceUtils.undeployService(serviceType);
+        } catch (ServiceDoesNotExistException e) {
+           return Response.status(Response.Status.NOT_FOUND).build();
+        }
+        return Response.noContent().build();
     }
 
     @POST
@@ -1100,16 +1155,17 @@ public class StratosAdmin extends AbstractAdmin {
     @Produces("application/json")
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
-    public void getRepoNotification(Payload payload) throws RestAPIException {
+    public Response getRepoNotification(Payload payload) throws RestAPIException {
 
         ServiceUtils.getGitRepositoryNotification(payload);
+        return Response.noContent().build();
     }
     
 	@POST
 	@Path("/cartridge/sync")
 	@Consumes("application/json")
 	@AuthorizationAction("/permission/protected/manage/monitor/tenants")
-	public StratosAdminResponse synchronizeRepository(String alias) throws RestAPIException {
+	public Response synchronizeRepository(String alias) throws RestAPIException {
 		if (log.isDebugEnabled()) {
 			log.debug(String.format("Synchronizing Git repository for alias '%s'", alias));
 		}
@@ -1118,7 +1174,8 @@ public class StratosAdmin extends AbstractAdmin {
 			log.debug(String.format("Found subscription for '%s'. Git repository: %s", alias, cartridgeSubscription
 					.getRepository().getUrl()));
 		}
-		return ServiceUtils.synchronizeRepository(cartridgeSubscription);
+		ServiceUtils.synchronizeRepository(cartridgeSubscription);
+        return Response.noContent().build();
 	}
 
     private List<TenantInfoBean> getAllTenants() throws RestAPIException {
@@ -1159,4 +1216,80 @@ public class StratosAdmin extends AbstractAdmin {
         }
         return tenantList;
     }
+
+    @POST
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/domains")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Response addSubscriptionDomains(@PathParam("cartridgeType") String cartridgeType,
+
+                                                       @PathParam("subscriptionAlias") String subscriptionAlias,
+                                                       SubscriptionDomainRequest request) throws RestAPIException {
+        ServiceUtils.addSubscriptionDomains(getConfigContext(), cartridgeType, subscriptionAlias, request);
+        return Response.noContent().build();
+    }
+
+    @GET
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/domains")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Response getSubscriptionDomains(@PathParam("cartridgeType") String cartridgeType,@PathParam("subscriptionAlias") String subscriptionAlias) throws RestAPIException {
+
+        SubscriptionDomainBean[] subscriptionDomainBean = ServiceUtils.getSubscriptionDomains(getConfigContext(), cartridgeType, subscriptionAlias).toArray(new SubscriptionDomainBean[0]);
+
+        if(subscriptionDomainBean.length == 0){
+            return Response.status(Response.Status.NOT_FOUND).build();
+        }else{
+            return Response.ok().entity(subscriptionDomainBean).build();
+        }
+    }
+
+    @GET
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/domains/{domainName}")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Response getSubscriptionDomain(@PathParam("cartridgeType") String cartridgeType, @PathParam("subscriptionAlias") String subscriptionAlias, @PathParam("domainName") String domainName) throws RestAPIException {
+
+        SubscriptionDomainBean subscriptionDomainBean = ServiceUtils.getSubscriptionDomain(getConfigContext(), cartridgeType, subscriptionAlias, domainName);
+        if(subscriptionDomainBean.domainName == null){
+            return Response.status(Response.Status.NOT_FOUND).build();
+        }else{
+            return Response.ok().entity(subscriptionDomainBean).build();
+        }
+    }
+
+    @DELETE
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/domains/{domainName}")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Response removeSubscriptionDomain(@PathParam("cartridgeType") String cartridgeType,
+                                                         @PathParam("subscriptionAlias") String subscriptionAlias,
+                                                         @PathParam("domainName") String domainName) throws RestAPIException {
+        try {
+            ServiceUtils.removeSubscriptionDomain(getConfigContext(), cartridgeType, subscriptionAlias, domainName);
+        } catch (DomainMappingExistsException e) {
+            return Response.status(Response.Status.NOT_FOUND).build();
+        }
+        return Response.noContent().build();
+    }
+
+    @GET
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/load-balancer-cluster")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Response getLoadBalancerCluster(@PathParam("cartridgeType") String cartridgeType,
+                                           @PathParam("subscriptionAlias") String subscriptionAlias) throws RestAPIException {
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("GET /cartridge/%s/subscription/%s/load-balancer-cluster", cartridgeType, subscriptionAlias));
+        }
+        Cartridge subscription = ServiceUtils.getSubscription(subscriptionAlias, getConfigContext());
+        String lbClusterId = subscription.getLbClusterId();
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Load balancer cluster-id found: %s", lbClusterId));
+        }
+        if (StringUtils.isNotBlank(lbClusterId)) {
+            Response.fromResponse(getCluster(lbClusterId));
+        }
+        return Response.status(Response.Status.NOT_FOUND).build();
+    }
 }


[2/2] git commit: merging messaging component

Posted by is...@apache.org.
merging messaging component


Project: http://git-wip-us.apache.org/repos/asf/stratos/repo
Commit: http://git-wip-us.apache.org/repos/asf/stratos/commit/8c14177f
Tree: http://git-wip-us.apache.org/repos/asf/stratos/tree/8c14177f
Diff: http://git-wip-us.apache.org/repos/asf/stratos/diff/8c14177f

Branch: refs/heads/4.0.0-grouping
Commit: 8c14177f4f625c1f16c1b20a455f67dccbeb1f18
Parents: c9e3e72
Author: Isuru Haththotuwa <is...@apache.org>
Authored: Thu Aug 28 14:30:23 2014 +0530
Committer: Isuru Haththotuwa <is...@apache.org>
Committed: Thu Aug 28 14:30:23 2014 +0530

----------------------------------------------------------------------
 .../manager/CartridgeSubscriptionManager.java   | 242 +++++++++++--
 .../manager/payload/BasicPayloadData.java       |  17 +-
 .../stratos/manager/repository/Repository.java  |   9 +
 .../subscription/CartridgeSubscription.java     |  34 +-
 .../subscription/LBCartridgeSubscription.java   |  37 +-
 .../manager/subscription/SubscriptionData.java  |  39 +-
 .../utils/CartridgeSubscriptionUtils.java       |  34 +-
 .../manager/utils/CartridgeConstants.java       |   1 +
 .../messaging/domain/tenant/Subscription.java   |  77 ++++
 .../domain/tenant/SubscriptionDomain.java       |  41 +++
 .../stratos/messaging/domain/tenant/Tenant.java |  29 +-
 .../messaging/domain/topology/Cluster.java      |  10 +
 .../domain/topology/ClusterStatus.java          |  36 ++
 .../tenant/SubscriptionDomainAddedEvent.java    |  67 ++++
 .../tenant/SubscriptionDomainRemovedEvent.java  |  60 +++
 .../tenant/SubscriptionDomainsAddedEvent.java   |  60 +++
 .../tenant/SubscriptionDomainsRemovedEvent.java |  60 +++
 .../event/tenant/TenantSubscribedEvent.java     |   9 +-
 .../topology/ClusterMaintenanceModeEvent.java   |  58 +++
 .../event/topology/MemberActivatedEvent.java    |  49 ++-
 .../event/topology/MemberTerminatedEvent.java   |  10 +
 .../SubscriptionDomainsAddedEventListener.java  |  28 ++
 ...SubscriptionDomainsRemovedEventListener.java |  28 ++
 .../ClusterMaintenanceModeEventListener.java    |  25 ++
 ...SubscriptionDomainAddedMessageProcessor.java | 100 +++++
 ...bscriptionDomainRemovedMessageProcessor.java |  97 +++++
 .../TenantSubscribedMessageProcessor.java       |   5 +-
 .../TenantUnSubscribedMessageProcessor.java     |   2 +-
 .../ClusterMaintenanceModeMessageProcessor.java | 115 ++++++
 .../rest/endpoint/services/StratosAdmin.java    | 363 +++++++++++++------
 30 files changed, 1520 insertions(+), 222 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/manager/CartridgeSubscriptionManager.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/manager/CartridgeSubscriptionManager.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/manager/CartridgeSubscriptionManager.java
index 7d6be7c..989fed4 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/manager/CartridgeSubscriptionManager.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/manager/CartridgeSubscriptionManager.java
@@ -23,10 +23,13 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cloud.controller.stub.CloudControllerServiceUnregisteredCartridgeExceptionException;
 import org.apache.stratos.cloud.controller.stub.pojo.*;
+import org.apache.stratos.cloud.controller.stub.pojo.Properties;
 import org.apache.stratos.manager.client.CloudControllerServiceClient;
 import org.apache.stratos.manager.dao.CartridgeSubscriptionInfo;
+import org.apache.stratos.manager.deploy.service.Service;
 import org.apache.stratos.manager.dto.SubscriptionInfo;
 import org.apache.stratos.manager.exception.*;
+import org.apache.stratos.manager.internal.DataHolder;
 import org.apache.stratos.manager.lb.category.*;
 import org.apache.stratos.manager.repository.Repository;
 import org.apache.stratos.manager.retriever.DataInsertionAndRetrievalManager;
@@ -41,14 +44,17 @@ import org.apache.stratos.manager.topology.model.TopologyClusterInformationModel
 import org.apache.stratos.manager.utils.ApplicationManagementUtil;
 import org.apache.stratos.manager.utils.CartridgeConstants;
 import org.apache.stratos.manager.utils.RepoPasswordMgtUtil;
+import org.apache.stratos.messaging.broker.publish.EventPublisher;
+import org.apache.stratos.messaging.broker.publish.EventPublisherPool;
 import org.apache.stratos.messaging.domain.topology.Cluster;
 import org.apache.stratos.messaging.domain.topology.Member;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainAddedEvent;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainRemovedEvent;
 import org.apache.stratos.messaging.util.Constants;
 import org.wso2.carbon.context.CarbonContext;
 import org.apache.stratos.manager.publisher.CartridgeSubscriptionDataPublisher;
 
-import java.util.Collection;
-import java.util.Random;
+import java.util.*;
 
 /**
  * Manager class for the purpose of managing CartridgeSubscriptionInfo subscriptions, groupings, etc.
@@ -143,8 +149,10 @@ public class CartridgeSubscriptionManager {
         log.info("Successful Subscription: " + cartridgeSubscription.toString());
 
         // Publish tenant subscribed event to message broker
+        Set<String> clusterIds = new HashSet<String>();
+        clusterIds.add(cartridgeSubscription.getCluster().getClusterDomain());
         CartridgeSubscriptionUtils.publishTenantSubscribedEvent(cartridgeSubscription.getSubscriber().getTenantId(),
-                cartridgeSubscription.getCartridgeInfo().getType());
+                cartridgeSubscription.getCartridgeInfo().getType(), clusterIds);
     }
 
     public void persistGroupSubscription (GroupSubscription groupSubscription) throws ADCException {
@@ -280,14 +288,17 @@ public class CartridgeSubscriptionManager {
           Collection<Member> members = cluster.getMembers();
           for (Member member : members) {
   			if(member.isActive()) {
-  				activeMemberCount++;
+                if(log.isDebugEnabled()) {
+                    log.debug("Active member found for cluster  [" + cluster +"]");
+                }
+  				return true;
   			}
   		} 
       }
       if(log.isDebugEnabled()) {
-    	  log.debug("Active member count for cluster  [" + cluster +"] is : "+ activeMemberCount);
+    	  log.debug("Active member not found for cluster  [" + cluster +"]");
       }
-	  return activeMemberCount > 0; 	
+	  return false;
 	}
 
 	private CartridgeSubscription subscribeToLB (SubscriptionData subscriptionData, LBDataContext lbDataContext,
@@ -299,7 +310,7 @@ public class CartridgeSubscriptionManager {
 
         
         if (lbDataContext.getLbCategory() == null || lbDataContext.getLbCategory().equals(Constants.NO_LOAD_BALANCER)) {
-            // no load balancer subscription requiredgenerateSubscriptionKey
+            // no load balancer subscription required generate SubscriptionKey
             log.info("No LB subscription required for the Subscription with alias: " + subscriptionData.getCartridgeAlias() + ", type: " +
                     subscriptionData.getCartridgeType());
             return null;
@@ -394,25 +405,64 @@ public class CartridgeSubscriptionManager {
         // Create the CartridgeSubscription instance
         CartridgeSubscription cartridgeSubscription = CartridgeSubscriptionFactory.getCartridgeSubscriptionInstance(cartridgeInfo, tenancyBehaviour);
 
-        // Generate and set the key
-        String subscriptionKey = CartridgeSubscriptionUtils.generateSubscriptionKey();
-        cartridgeSubscription.setSubscriptionKey(subscriptionKey);
         
-        String encryptedRepoPassword;
-        String repositoryPassword = subscriptionData.getRepositoryPassword();
-        if(repositoryPassword != null && !repositoryPassword.isEmpty()) {
-        	encryptedRepoPassword = RepoPasswordMgtUtil.encryptPassword(repositoryPassword, subscriptionKey);
-        } else {
-        	encryptedRepoPassword = "";
+        // For MT cartridges subscription key should not be generated for every subscription,
+        // instead use the already generated key at the time of service deployment
+        String subscriptionKey = null;
+        if(cartridgeInfo.getMultiTenant()) {
+        	try {
+				Service service = new DataInsertionAndRetrievalManager().getService(subscriptionData.getCartridgeType());
+				if(service != null) {
+					subscriptionKey = service.getSubscriptionKey();
+				}else {
+					String msg = "Could not find service for cartridge type [" + subscriptionData.getCartridgeType() + "] " ;
+					log.error(msg);				
+					throw new ADCException(msg);
+				}
+			} catch (Exception e) {
+				String msg = "Exception has occurred in get service for cartridge type [" + subscriptionData.getCartridgeType() + "] " ;
+				log.error(msg);				
+				throw new ADCException(msg, e);
+			}
+        }else {
+        	// Generate and set the key
+            subscriptionKey = CartridgeSubscriptionUtils.generateSubscriptionKey();
         }
+        
+        cartridgeSubscription.setSubscriptionKey(subscriptionKey);
+
+        if(log.isDebugEnabled()) {
+            log.debug("Repository with url: " + subscriptionData.getRepositoryURL() +
+                    " username: " + subscriptionData.getRepositoryUsername() +
+                    " Type: " + subscriptionData.getRepositoryType());
+        }
+        
+        // Create subscriber
+        Subscriber subscriber = new Subscriber(subscriptionData.getTenantAdminUsername(), subscriptionData.getTenantId(), subscriptionData.getTenantDomain());
+        cartridgeSubscription.setSubscriber(subscriber);
+        cartridgeSubscription.setAlias(subscriptionData.getCartridgeAlias());
 
         // Create repository
         Repository repository = cartridgeSubscription.manageRepository(subscriptionData.getRepositoryURL(), subscriptionData.getRepositoryUsername(),
-                encryptedRepoPassword,
+        		subscriptionData.getRepositoryPassword(),
                 subscriptionData.isPrivateRepository());
 
-        // Create subscriber
-        Subscriber subscriber = new Subscriber(subscriptionData.getTenantAdminUsername(), subscriptionData.getTenantId(), subscriptionData.getTenantDomain());
+        // Update repository attributes
+        if(repository != null) {
+        	
+            repository.setCommitEnabled(subscriptionData.isCommitsEnabled());
+            
+            // Encrypt repository password
+            String encryptedRepoPassword;
+            String repositoryPassword = repository.getPassword();
+            if(repositoryPassword != null && !repositoryPassword.isEmpty()) {
+            	encryptedRepoPassword = RepoPasswordMgtUtil.encryptPassword(repositoryPassword, subscriptionKey);
+            } else {
+            	encryptedRepoPassword = "";
+            }
+            repository.setPassword(encryptedRepoPassword);
+            
+        }
 
         // set the LB cluster id relevant to this service cluster
         cartridgeSubscription.setLbClusterId(lbClusterId);
@@ -488,13 +538,155 @@ public class CartridgeSubscriptionManager {
         log.info("Successful Subscription: " + cartridgeSubscription.toString());
 
         // Publish tenant subscribed event to message broker
-        CartridgeSubscriptionUtils.publishTenantSubscribedEvent(cartridgeSubscription.getSubscriber().getTenantId(),
-                cartridgeSubscription.getCartridgeInfo().getType());
+        Set<String> clusterIds = new HashSet<String>();
+        clusterIds.add(cartridgeSubscription.getCluster().getClusterDomain());
+        CartridgeSubscriptionUtils.publishTenantSubscribedEvent(cartridgeSubscription.getSubscriber().getTenantId(), cartridgeSubscription.getCartridgeInfo().getType(), clusterIds);
 
         return ApplicationManagementUtil.
                 createSubscriptionResponse(cartridgeSubscriptionInfo, cartridgeSubscription.getRepository());
     }
 
+    public void addSubscriptionDomain(int tenantId, String subscriptionAlias, String domainName, String applicationContext)
+            throws ADCException {
+
+        CartridgeSubscription cartridgeSubscription;
+        try {
+            cartridgeSubscription = getCartridgeSubscription(tenantId, subscriptionAlias);
+            if(cartridgeSubscription == null) {
+                throw new ADCException("Cartridge subscription not found");
+            }
+
+                if(!isSubscriptionDomainValid(domainName)) {
+                    throw new ADCException(String.format("Domain name %s already registered", domainName));
+                }
+
+            cartridgeSubscription.addSubscriptionDomain(new SubscriptionDomain(domainName, applicationContext));
+            new DataInsertionAndRetrievalManager().cacheAndPersistSubcription(cartridgeSubscription);
+        } catch (PersistenceManagerException e) {
+            String errorMsg = "Could not add domain to cartridge subscription: [tenant-id] " + tenantId + " [subscription-alias] " + subscriptionAlias +
+            " [domain-name] " + domainName + " [application-context] " + applicationContext;
+            log.error(errorMsg);
+            throw new ADCException(errorMsg, e);
+        }
+
+        log.info("Successfully added domains to cartridge subscription: [tenant-id] " + tenantId + " [subscription-alias] " + subscriptionAlias +
+                " [domain-name] " + domainName + " [application-context] " +applicationContext);
+
+        EventPublisher eventPublisher = EventPublisherPool.getPublisher(Constants.TENANT_TOPIC);
+
+        Set<String> clusterIds = new HashSet<String>();
+        clusterIds.add(cartridgeSubscription.getCluster().getClusterDomain());
+        SubscriptionDomainAddedEvent event = new SubscriptionDomainAddedEvent(tenantId, cartridgeSubscription.getType(),
+                clusterIds, domainName, applicationContext);
+
+        eventPublisher.publish(event);
+    }
+
+    public void removeSubscriptionDomain(int tenantId, String subscriptionAlias, String domainName) throws ADCException, DomainSubscriptionDoesNotExist {
+
+        CartridgeSubscription cartridgeSubscription;
+        try {
+            cartridgeSubscription = getCartridgeSubscription(tenantId, subscriptionAlias);
+            if(cartridgeSubscription == null) {
+                throw new DomainSubscriptionDoesNotExist("Cartridge subscription not found", domainName);
+            }
+            cartridgeSubscription.removeSubscriptionDomain(domainName);
+            new DataInsertionAndRetrievalManager().cacheAndPersistSubcription(cartridgeSubscription);
+        } catch (PersistenceManagerException e) {
+            String errorMsg = "Could not remove domain from cartridge subscription: [tenant-id] " + tenantId + " [subscription-alias] " + subscriptionAlias +
+                    " [domain-name] " + domainName;
+            log.error(errorMsg);
+            throw new ADCException(errorMsg, e);
+        }
+
+        log.info("Successfully removed domain from cartridge subscription: [tenant-id] " + tenantId + " [subscription-alias] " + subscriptionAlias +
+                " [domain-name] " + domainName);
+
+        EventPublisher eventPublisher = EventPublisherPool.getPublisher(Constants.TENANT_TOPIC);
+
+        Set<String> clusterIds = new HashSet<String>();
+        clusterIds.add(cartridgeSubscription.getCluster().getClusterDomain());
+        SubscriptionDomainRemovedEvent event = new SubscriptionDomainRemovedEvent(tenantId, cartridgeSubscription.getType(),
+                clusterIds, domainName);
+        eventPublisher.publish(event);
+    }
+
+    public List<SubscriptionDomain> getSubscriptionDomains(int tenantId, String subscriptionAlias)
+            throws ADCException {
+
+        try {
+            CartridgeSubscription cartridgeSubscription = getCartridgeSubscription(tenantId, subscriptionAlias);
+            if(cartridgeSubscription == null) {
+                throw new ADCException("Cartridge subscription not found");
+            }
+            
+            //return (List<SubscriptionDomain>) cartridgeSubscription.getSubscriptionDomains();
+            return new ArrayList<SubscriptionDomain>(cartridgeSubscription.getSubscriptionDomains());
+        } catch (Exception e) {
+            String errorMsg = "Could not get domains of cartridge subscription: [tenant-id] " + tenantId + " [subscription-alias] " + subscriptionAlias;
+            log.error(errorMsg);
+            throw new ADCException(errorMsg, e);
+        }
+    }
+    
+    public SubscriptionDomain getSubscriptionDomain(int tenantId, String subscriptionAlias, String domain)
+            throws ADCException {
+
+        try {
+            CartridgeSubscription cartridgeSubscription = getCartridgeSubscription(tenantId, subscriptionAlias);
+            if(cartridgeSubscription == null) {
+                throw new ADCException("Cartridge subscription not found");
+            }
+            
+            return cartridgeSubscription.getSubscriptionDomain(domain);
+        } catch (Exception e) {
+            String errorMsg = "Could not check [domain] "+domain+" against cartridge subscription: [tenant-id] " 
+            					+ tenantId + " [subscription-alias] " + subscriptionAlias;
+            log.error(errorMsg);
+            throw new ADCException(errorMsg, e);
+        }
+    }
+
+    public boolean isSubscriptionDomainValid(String domainName) throws ADCException {
+        try {
+            if(log.isDebugEnabled()) {
+                log.debug(String.format("Validating domain: %s", domainName));
+            }
+            org.wso2.carbon.user.core.tenant.TenantManager tenantManager = DataHolder.getRealmService().getTenantManager();
+            org.wso2.carbon.user.api.Tenant[] tenants = tenantManager.getAllTenants();
+            if((tenants != null) && (tenants.length > 0)) {
+                DataInsertionAndRetrievalManager manager = new DataInsertionAndRetrievalManager();
+                for (org.wso2.carbon.user.api.Tenant tenant : tenants) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(String.format("Reading subscriptions for tenant: [tenant-id] %d [tenant-domain] %s",
+                                tenant.getId(), tenant.getDomain()));
+                    }
+                    Collection<CartridgeSubscription> subscriptions = manager.getCartridgeSubscriptions(tenant.getId());
+                    if (subscriptions == null) {
+                        continue;
+                    }
+                    for (CartridgeSubscription subscription : subscriptions) {
+                        if (log.isDebugEnabled()) {
+                            log.debug(String.format("Reading domain names in subscription: [alias] %s [domain-names] %s",
+                                    subscription.getAlias(), subscription.getSubscriptionDomains()));
+                        }
+                        if (subscription.subscriptionDomainExists(domainName)) {
+                            return false;
+                        }
+                    }
+                }
+            }
+            if(log.isDebugEnabled()) {
+                log.debug(String.format("Domain name %s is valid", domainName));
+            }
+            return true;
+        } catch (Exception e) {
+            String errorMsg = "Could not validate domain:  " + domainName;
+            log.error(errorMsg);
+            throw new ADCException(errorMsg, e);
+        }
+    }
+
     public Collection<CartridgeSubscription> getCartridgeSubscriptions (int tenantId, String type) throws ADCException {
 
         if (type == null || type.isEmpty()) {
@@ -543,8 +735,12 @@ public class CartridgeSubscriptionManager {
             }
 
             // Publish tenant un-subscribed event to message broker
-            CartridgeSubscriptionUtils.publishTenantUnSubscribedEvent(cartridgeSubscription.getSubscriber().getTenantId(),
-                    cartridgeSubscription.getCartridgeInfo().getType());
+
+            Set<String> clusterIds = new HashSet<String>();
+            clusterIds.add(cartridgeSubscription.getCluster().getClusterDomain());
+            CartridgeSubscriptionUtils.publishTenantUnSubscribedEvent(
+                    cartridgeSubscription.getSubscriber().getTenantId(),
+                    cartridgeSubscription.getCartridgeInfo().getType(), clusterIds);
             
 			// publishing to the unsubscribed event details to bam
 			CartridgeSubscriptionDataPublisher.publish(cartridgeSubscription

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/payload/BasicPayloadData.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/payload/BasicPayloadData.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/payload/BasicPayloadData.java
index 0d27b1b..234dac1 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/payload/BasicPayloadData.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/payload/BasicPayloadData.java
@@ -47,6 +47,7 @@ public class BasicPayloadData implements Serializable {
     private String gitRepositoryUrl;
     private String portMappings;
     private String multitenant;
+    private String provider;
 
     protected StringBuilder payloadBuilder;
 
@@ -74,13 +75,15 @@ public class BasicPayloadData implements Serializable {
         payloadBuilder.append(",");
         payloadBuilder.append("CARTRIDGE_KEY=" + getSubscriptionKey());
         payloadBuilder.append(",");
-        payloadBuilder.append("DEPLOYMENT=" + getDeployment());
-        payloadBuilder.append(",");
+        //payloadBuilder.append("DEPLOYMENT=" + getDeployment());
+        //payloadBuilder.append(",");
         //payloadBuilder.append("APP_PATH=" + getApplicationPath());
         //payloadBuilder.append(",");
         payloadBuilder.append("REPO_URL=" + getGitRepositoryUrl());
         payloadBuilder.append(",");
         payloadBuilder.append("PORTS=" + getPortMappings());
+        payloadBuilder.append(",");
+        payloadBuilder.append("PROVIDER=" + getProvider());
 
         //Payload Data exposed as system variables
         payloadBuilder.append(",");
@@ -88,6 +91,8 @@ public class BasicPayloadData implements Serializable {
         payloadBuilder.append(",");
         payloadBuilder.append("PUPPET_HOSTNAME=" + System.getProperty(CartridgeConstants.PUPPET_HOSTNAME));
         payloadBuilder.append(",");
+        payloadBuilder.append("PUPPET_DNS_AVAILABLE=" + System.getProperty(CartridgeConstants.PUPPET_DNS_AVAILABLE));
+        payloadBuilder.append(",");
         payloadBuilder.append("PUPPET_ENV=" + System.getProperty(CartridgeConstants.PUPPET_ENVIRONMENT));
 
     }
@@ -216,4 +221,12 @@ public class BasicPayloadData implements Serializable {
     public void setPuppetEnvironment(String puppetEnvironment) {
         this.puppetEnvironment = puppetEnvironment;
     }
+
+    public String getProvider() {
+        return provider;
+    }
+
+    public void setProvider(String provider) {
+        this.provider = provider;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/Repository.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/Repository.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/Repository.java
index 16cc2c4..ab95ae3 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/Repository.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/Repository.java
@@ -29,6 +29,7 @@ public class Repository implements Serializable {
     private String userName;
     private String password;
     private boolean isPrivateRepository;
+    private boolean commitEnabled;
 
     public String getUserName() {
         return userName;
@@ -75,4 +76,12 @@ public class Repository implements Serializable {
         return "Repository [id=" + id + ", url=" + url + ", userName=" + userName +
                ", isPrivateRepository=" + isPrivateRepository + "]";
     }
+
+    public boolean isCommitEnabled() {
+        return commitEnabled;
+    }
+
+    public void setCommitEnabled(boolean commitEnabled) {
+        this.commitEnabled = commitEnabled;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/CartridgeSubscription.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/CartridgeSubscription.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/CartridgeSubscription.java
index b974f54..a5d901d 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/CartridgeSubscription.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/CartridgeSubscription.java
@@ -35,7 +35,7 @@ import org.apache.stratos.manager.utils.ApplicationManagementUtil;
 import org.apache.stratos.manager.utils.CartridgeConstants;
 
 import java.io.Serializable;
-import java.util.Map;
+import java.util.*;
 
 public abstract class CartridgeSubscription implements Serializable {
 
@@ -59,7 +59,7 @@ public abstract class CartridgeSubscription implements Serializable {
     //private List<String> connectedSubscriptionAliases;
     private String subscriptionKey;
     private SubscriptionTenancyBehaviour subscriptionTenancyBehaviour;
-
+    private Map<String, SubscriptionDomain> subscriptionDomainMap;
     
     /**
      * Constructor
@@ -80,6 +80,7 @@ public abstract class CartridgeSubscription implements Serializable {
         //this.setSubscriptionStatus(CartridgeConstants.SUBSCRIBED);
         //this.connectedSubscriptionAliases = new ArrayList<String>();
         this.setSubscriptionTenancyBehaviour(subscriptionTenancyBehaviour);
+        this.subscriptionDomainMap = new HashMap<String, SubscriptionDomain>();
     }
 
     /**
@@ -118,6 +119,33 @@ public abstract class CartridgeSubscription implements Serializable {
                 getSubscriptionKey(), getCustomPayloadEntries()));
     }
 
+    public void addSubscriptionDomain(SubscriptionDomain subscriptionDomain) {
+        subscriptionDomainMap.put(subscriptionDomain.getDomainName(), subscriptionDomain);
+    }
+
+    public void removeSubscriptionDomain(String domainName) {
+        if(subscriptionDomainExists(domainName)) {
+            subscriptionDomainMap.remove(domainName);
+        }
+        else {
+            if(log.isWarnEnabled()) {
+                log.warn("Subscription domain does not exist: " + domainName);
+            }
+        }
+    }
+
+    public boolean subscriptionDomainExists(String domainName) {
+        return subscriptionDomainMap.containsKey(domainName);
+    }
+    
+    public SubscriptionDomain getSubscriptionDomain(String domainName) {
+        return subscriptionDomainMap.get(domainName);
+    }
+
+    public Collection<SubscriptionDomain> getSubscriptionDomains() {
+        return Collections.unmodifiableCollection(subscriptionDomainMap.values());
+    }
+
     /**
      * Unsubscribe from this cartridge subscription
      *
@@ -389,7 +417,7 @@ public abstract class CartridgeSubscription implements Serializable {
                ", alias=" + alias + ", autoscalingPolicyName=" + autoscalingPolicyName +
                ", deploymentPolicyName=" + deploymentPolicyName + ", subscriber=" + subscriber +
                ", repository=" + repository + ", cartridgeInfo=" + cartridgeInfo + ", payload=" +
-               payloadData + ", cluster=" + cluster + "]";
+               payloadData + ", cluster=" + cluster + "]" + ", subscriptionDomainMap=" + subscriptionDomainMap.toString();
     }
 
     public String getLbClusterId() {

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/LBCartridgeSubscription.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/LBCartridgeSubscription.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/LBCartridgeSubscription.java
index f6555f8..c0bd321 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/LBCartridgeSubscription.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/LBCartridgeSubscription.java
@@ -25,23 +25,15 @@ import org.apache.stratos.cloud.controller.stub.pojo.CartridgeInfo;
 import org.apache.stratos.cloud.controller.stub.pojo.Persistence;
 import org.apache.stratos.cloud.controller.stub.pojo.Properties;
 import org.apache.stratos.manager.dao.CartridgeSubscriptionInfo;
-import org.apache.stratos.manager.exception.ADCException;
-import org.apache.stratos.manager.exception.AlreadySubscribedException;
-import org.apache.stratos.manager.exception.DuplicateCartridgeAliasException;
-import org.apache.stratos.manager.exception.InvalidCartridgeAliasException;
-import org.apache.stratos.manager.exception.InvalidRepositoryException;
-import org.apache.stratos.manager.exception.NotSubscribedException;
-import org.apache.stratos.manager.exception.PolicyException;
-import org.apache.stratos.manager.exception.RepositoryCredentialsRequiredException;
-import org.apache.stratos.manager.exception.RepositoryRequiredException;
-import org.apache.stratos.manager.exception.RepositoryTransportException;
-import org.apache.stratos.manager.exception.UnregisteredCartridgeException;
+import org.apache.stratos.manager.exception.*;
 import org.apache.stratos.manager.lb.category.LoadBalancerCategory;
 import org.apache.stratos.manager.repository.Repository;
 import org.apache.stratos.manager.subscriber.Subscriber;
 import org.apache.stratos.manager.subscription.tenancy.SubscriptionTenancyBehaviour;
 import org.apache.stratos.manager.utils.ApplicationManagementUtil;
 
+import java.util.Set;
+
 public class LBCartridgeSubscription extends CartridgeSubscription {
 
     private LoadBalancerCategory loadBalancerCategory;
@@ -72,24 +64,25 @@ public class LBCartridgeSubscription extends CartridgeSubscription {
         setAutoscalingPolicyName(autoscalingPolicy);
         setDeploymentPolicyName(deploymentPolicyName);
         setRepository(repository);
+        setPayloadData(getLoadBalancerCategory().create(getAlias(), getCluster(), getSubscriber(), getRepository(), getCartridgeInfo(),
+                getSubscriptionKey(), getCustomPayloadEntries()));
         // If LB subscription is for MT service, payload data should not be set
-        if(!loadBalancerCategory.isLoadBalancedServiceMultiTenant()) {        	
-        	setPayloadData(getLoadBalancerCategory().create(getAlias(), getCluster(), getSubscriber(), getRepository(), getCartridgeInfo(),
-                    getSubscriptionKey(), getCustomPayloadEntries()));	
-        }        
+//        if(!loadBalancerCategory.isLoadBalancedServiceMultiTenant()) {
+//        	setPayloadData(getLoadBalancerCategory().create(getAlias(), getCluster(), getSubscriber(), getRepository(), getCartridgeInfo(),
+//                    getSubscriptionKey(), getCustomPayloadEntries()));
+//        }
     }
 
     
     @Override
     public CartridgeSubscriptionInfo registerSubscription(Properties properties, Persistence persistence) throws ADCException, UnregisteredCartridgeException {
-    	if(!loadBalancerCategory.isLoadBalancedServiceMultiTenant()) {
-    		if(log.isDebugEnabled()) {
-    		 log.debug("Loadbalanced service is single tenant.");
-    		}
+    	//if(!loadBalancerCategory.isLoadBalancedServiceMultiTenant()) {
+    		//if(log.isDebugEnabled()) {
+    		 //log.debug("Loadbalanced service is single tenant.");
+    		//}
     		getLoadBalancerCategory().register (getCartridgeInfo(), getCluster(), getPayloadData(), getAutoscalingPolicyName(),
-    	                getDeploymentPolicyName(), properties, persistence);
-    	}
-       
+    	                getDeploymentPolicyName(), properties, null);
+    	//}
 
         return ApplicationManagementUtil.createCartridgeSubscription(getCartridgeInfo(), getAutoscalingPolicyName(),
                 getType(), getAlias(), getSubscriber().getTenantId(), getSubscriber().getTenantDomain(),

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionData.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionData.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionData.java
index 0b257d5..56829e0 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionData.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionData.java
@@ -22,12 +22,15 @@ import org.apache.stratos.cloud.controller.stub.pojo.Persistence;
 import org.apache.stratos.cloud.controller.stub.pojo.Properties;
 import org.apache.stratos.cloud.controller.stub.pojo.Property;
 
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * This holds the data that are gathered at the time of subscription. This is usefull when passing subscription details to the method calls.
  */
 public class SubscriptionData {
 
-
     private String cartridgeType;
     private String cartridgeAlias;
     private String autoscalingPolicyName;
@@ -43,8 +46,14 @@ public class SubscriptionData {
     private PersistenceContext persistanceCtxt;
     private boolean isCommitsEnabled;
     private String serviceGroup;
+    private Set<String> domains;
     private Persistence persistence;
     private Properties properties;
+    private String serviceName;
+
+    public SubscriptionData() {
+        this.domains = new HashSet<String>();
+    }
 
     public String getCartridgeType() {
         return cartridgeType;
@@ -166,13 +175,29 @@ public class SubscriptionData {
 		this.serviceGroup = serviceGroup;
 	}
 
+    public void addDomains(Set<String> domains) {
+        domains.addAll(domains);
+    }
+
+    public void removeDomain(String domain) {
+        domains.remove(domain);
+    }
+
+    public void removeDomains(Set<String> domains) {
+        domains.removeAll(domains);
+    }
+
+    public Set<String> getDomains() {
+        return Collections.unmodifiableSet(domains);
+    }
+
     public Persistence getPersistence() {
         return persistence;
     }
 
-    public void setPersistence(Persistence persistence) {
+     public void setPersistence(Persistence persistence) {
         this.persistence = persistence;
-    }
+     }
 
     public Properties getProperties() {
         return properties;
@@ -181,4 +206,12 @@ public class SubscriptionData {
     public void setProperties(Properties properties) {
         this.properties = properties;
     }
+	public String getServiceName() {
+		return serviceName;
+	}
+
+	public void setServiceName(String serviceName) {
+		this.serviceName = serviceName;
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/utils/CartridgeSubscriptionUtils.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/utils/CartridgeSubscriptionUtils.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/utils/CartridgeSubscriptionUtils.java
index deb9475..4e54f21 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/utils/CartridgeSubscriptionUtils.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/utils/CartridgeSubscriptionUtils.java
@@ -45,6 +45,7 @@ import org.apache.stratos.messaging.event.tenant.TenantSubscribedEvent;
 import org.apache.stratos.messaging.event.tenant.TenantUnSubscribedEvent;
 import org.apache.stratos.messaging.util.Constants;
 
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.regex.Pattern;
 
@@ -58,10 +59,11 @@ public class CartridgeSubscriptionUtils {
         BasicPayloadData basicPayloadData = new BasicPayloadData();
         basicPayloadData.setApplicationPath(cartridgeInfo.getBaseDir());
         basicPayloadData.setSubscriptionKey(subscriptionKey);
-        basicPayloadData.setDeployment("default");//currently hard coded to default
+        //basicPayloadData.setDeployment("default");//currently hard coded to default
         basicPayloadData.setMultitenant(String.valueOf(cartridgeInfo.getMultiTenant()));
         basicPayloadData.setPortMappings(createPortMappingPayloadString(cartridgeInfo));
         basicPayloadData.setServiceName(cartridgeInfo.getType());
+        basicPayloadData.setProvider(cartridgeInfo.getProvider());
 
         if(repository != null) {
             basicPayloadData.setGitRepositoryUrl(repository.getUrl());
@@ -96,7 +98,7 @@ public class CartridgeSubscriptionUtils {
         basicPayloadData.setApplicationPath(service.getCartridgeInfo().getBaseDir());
         basicPayloadData.setSubscriptionKey(service.getSubscriptionKey());
         basicPayloadData.setClusterId(service.getClusterId());
-        basicPayloadData.setDeployment("default");//currently hard coded to default
+        //basicPayloadData.setDeployment("default");//currently hard coded to default
         basicPayloadData.setHostName(service.getHostName());
         basicPayloadData.setMultitenant(String.valueOf(service.getCartridgeInfo().getMultiTenant()));
         basicPayloadData.setPortMappings(createPortMappingPayloadString(service.getCartridgeInfo()));
@@ -147,19 +149,19 @@ public class CartridgeSubscriptionUtils {
     }
 
     public static String generateSubscriptionKey() {
-        String key = RandomStringUtils.randomAlphanumeric(16);
-        log.info("Generated key  : " + key); // TODO -- remove the log
-        return key;
+        return RandomStringUtils.randomAlphanumeric(16);
     }
 
     static class TenantSubscribedEventPublisher implements Runnable {
     	
-    	int tenantId;
-    	String serviceName;
+    	private int tenantId;
+    	private String serviceName;
+        private Set<String> clusterIds;
 
-    	public TenantSubscribedEventPublisher(int tenantId, String service) {
+        public TenantSubscribedEventPublisher(int tenantId, String service, Set<String> clusterIds) {
     		this.tenantId = tenantId;
     		this.serviceName = service;
+            this.clusterIds = clusterIds;
 		}
 		@Override
 		public void run() {
@@ -167,7 +169,7 @@ public class CartridgeSubscriptionUtils {
 				if(log.isInfoEnabled()) {
 					log.info(String.format("Publishing tenant subscribed event: [tenant-id] %d [service] %s", tenantId, serviceName));
 				}
-				TenantSubscribedEvent subscribedEvent = new TenantSubscribedEvent(tenantId, serviceName);
+				TenantSubscribedEvent subscribedEvent = new TenantSubscribedEvent(tenantId, serviceName, clusterIds);
 				EventPublisher eventPublisher = EventPublisherPool.getPublisher(Constants.TENANT_TOPIC);
 				eventPublisher.publish(subscribedEvent);
 			} catch (Exception e) {
@@ -179,7 +181,7 @@ public class CartridgeSubscriptionUtils {
 		}
     	
     }
-    public static void publishTenantSubscribedEvent(int tenantId, String serviceName) {
+    public static void publishTenantSubscribedEvent(int tenantId, String serviceName, Set<String> clusterIds) {
     	
     	
     	Executor exec = new Executor() {
@@ -189,15 +191,15 @@ public class CartridgeSubscriptionUtils {
 			}
 		};
 		
-		exec.execute(new TenantSubscribedEventPublisher(tenantId, serviceName));
+		exec.execute(new TenantSubscribedEventPublisher(tenantId, serviceName, clusterIds));
     }
 
-    public static void publishTenantUnSubscribedEvent(int tenantId, String serviceName) {
+    public static void publishTenantUnSubscribedEvent(int tenantId, String serviceName, Set<String> clusterIds) {
         try {
             if(log.isInfoEnabled()) {
                 log.info(String.format("Publishing tenant un-subscribed event: [tenant-id] %d [service] %s", tenantId, serviceName));
             }
-            TenantUnSubscribedEvent event = new TenantUnSubscribedEvent(tenantId, serviceName);
+            TenantUnSubscribedEvent event = new TenantUnSubscribedEvent(tenantId, serviceName, clusterIds);
             EventPublisher eventPublisher = EventPublisherPool.getPublisher(Constants.TENANT_TOPIC);
             eventPublisher.publish(event);
         } catch (Exception e) {
@@ -209,8 +211,10 @@ public class CartridgeSubscriptionUtils {
 
     public static void validateCartridgeAlias (int tenantId, String cartridgeType, String alias) throws InvalidCartridgeAliasException, DuplicateCartridgeAliasException, ADCException {
 
-        boolean validAlias = ApplicationUtils.isAliasValid(alias);
-        if (!validAlias) {
+        String patternString = "([a-z0-9]+([-][a-z0-9])*)+";
+        Pattern pattern = Pattern.compile(patternString);
+
+        if (!pattern.matcher(alias).matches()) {
             String msg = "The alias " + alias + " can contain only alpha-numeric lowercase characters. Please enter a valid alias.";
             log.error(msg);
             throw new InvalidCartridgeAliasException(msg, tenantId, cartridgeType, alias);

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java
index 6ed5564..ab78bd6 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/CartridgeConstants.java
@@ -33,6 +33,7 @@ public class CartridgeConstants {
     public static final String UNSUBSCRIBED = "UNSUBSCRIBED";
     public static final String PUPPET_IP = "puppet.ip";
     public static final String PUPPET_HOSTNAME = "puppet.hostname";
+    public static final String PUPPET_DNS_AVAILABLE = "puppet.dns.available";
     public static final String PUPPET_ENVIRONMENT = "puppet.environment";
 
 	public static final String SUDO_SH = "sudo sh";

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Subscription.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Subscription.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Subscription.java
new file mode 100644
index 0000000..caab423
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Subscription.java
@@ -0,0 +1,77 @@
+/*
+ * 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.messaging.domain.tenant;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.*;
+
+/**
+ * Tenant's service subscription.
+ */
+public class Subscription {
+    private static final Log log = LogFactory.getLog(Subscription.class);
+
+    private final String serviceName;
+    private final Set<String> clusterIds;
+    private final Map<String, SubscriptionDomain> subscriptionDomainMap;
+
+    public Subscription(String serviceName, Set<String> clusterIds) {
+        this.serviceName = serviceName;
+        this.clusterIds = clusterIds;
+        this.subscriptionDomainMap = new HashMap<String, SubscriptionDomain>();
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public Set<String> getClusterIds() {
+        return Collections.unmodifiableSet(clusterIds);
+    }
+
+    public void addSubscriptionDomain(SubscriptionDomain subscriptionDomain) {
+        subscriptionDomainMap.put(subscriptionDomain.getDomainName(), subscriptionDomain);
+    }
+
+    public void addSubscriptionDomain(String domainName, String applicationContext) {
+        addSubscriptionDomain(new SubscriptionDomain(domainName, applicationContext));
+    }
+
+    public void removeSubscriptionDomain(String domainName) {
+        if(subscriptionDomainExists(domainName)) {
+            subscriptionDomainMap.remove(domainName);
+        }
+        else {
+            if(log.isWarnEnabled()) {
+                log.warn("Subscription domain does not exist: " + domainName);
+            }
+        }
+    }
+
+    public boolean subscriptionDomainExists(String domainName) {
+        return subscriptionDomainMap.containsKey(domainName);
+    }
+
+    public Collection<SubscriptionDomain> getSubscriptionDomains() {
+        return Collections.unmodifiableCollection(subscriptionDomainMap.values());
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/SubscriptionDomain.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/SubscriptionDomain.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/SubscriptionDomain.java
new file mode 100644
index 0000000..84df4c8
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/SubscriptionDomain.java
@@ -0,0 +1,41 @@
+/*
+ * 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.messaging.domain.tenant;
+
+/**
+ * Subscription domain definition.
+ */
+public class SubscriptionDomain {
+    private final String domainName;
+    private final String applicationContext;
+
+    public SubscriptionDomain(String domainName, String applicationContext) {
+        this.domainName = domainName;
+        this.applicationContext = applicationContext;
+    }
+
+    public String getDomainName() {
+        return domainName;
+    }
+
+    public String getApplicationContext() {
+        return applicationContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Tenant.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Tenant.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Tenant.java
index bc4244a..ed20bd0 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Tenant.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/tenant/Tenant.java
@@ -32,13 +32,13 @@ public class Tenant implements Serializable{
 
     private int tenantId;
     private String tenantDomain;
-    // Map<ServiceName, Subscribed>
-    private Map<String, Boolean> serviceNameMap;
+    // Map<ServiceName, Subscription>
+    private Map<String, Subscription> serviceNameSubscriptionMap;
 
     public Tenant(int tenantId, String tenantDomain) {
         this.tenantId = tenantId;
         this.tenantDomain = tenantDomain;
-        this.serviceNameMap = new HashMap<String, Boolean>();
+        this.serviceNameSubscriptionMap = new HashMap<String, Subscription>();
     }
 
     public int getTenantId() {
@@ -53,19 +53,26 @@ public class Tenant implements Serializable{
         this.tenantDomain = tenantDomain;
     }
 
-    public Collection<String> getServiceSubscriptions() {
-        return serviceNameMap.keySet();
+    public Subscription getSubscription(String serviceName) {
+        if(serviceNameSubscriptionMap.containsKey(serviceName)) {
+            return serviceNameSubscriptionMap.get(serviceName);
+        }
+        return null;
     }
 
-    public boolean isServiceSubscribed(String serviceName) {
-        return serviceNameMap.containsKey(serviceName);
+    public Collection<Subscription> getSubscriptions() {
+        return serviceNameSubscriptionMap.values();
     }
 
-    public void addServiceSubscription(String serviceName) {
-        serviceNameMap.put(serviceName, true);
+    public boolean isSubscribed(String serviceName) {
+        return serviceNameSubscriptionMap.containsKey(serviceName);
     }
 
-    public void removeServiceSubscription(String serviceName) {
-        serviceNameMap.remove(serviceName);
+    public void addSubscription(Subscription subscription) {
+        serviceNameSubscriptionMap.put(subscription.getServiceName(), subscription);
+    }
+
+    public void removeSubscription(String serviceName) {
+        serviceNameSubscriptionMap.remove(serviceName);
     }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Cluster.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Cluster.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Cluster.java
index dddb869..08bd262 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Cluster.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Cluster.java
@@ -49,6 +49,8 @@ public class Cluster implements Serializable {
     @XmlJavaTypeAdapter(MapAdapter.class)
     private Map<String, Member> memberMap;
 
+    private ClusterStatus status;
+
     private String loadBalanceAlgorithmName;
     @XmlJavaTypeAdapter(MapAdapter.class)
     private Properties properties;
@@ -200,5 +202,13 @@ public class Cluster implements Serializable {
         }
         return partitionIds.keySet();
     }
+
+    public ClusterStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(ClusterStatus status) {
+        this.status = status;
+    }
 }
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/ClusterStatus.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/ClusterStatus.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/ClusterStatus.java
new file mode 100644
index 0000000..b3301c8
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/ClusterStatus.java
@@ -0,0 +1,36 @@
+/*
+ * 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.messaging.domain.topology;
+public enum ClusterStatus {
+    Created(1),
+    In_Maintenance(2),
+    Removed(3);
+
+    private int code;
+
+    private ClusterStatus(int code) {
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainAddedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainAddedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainAddedEvent.java
new file mode 100644
index 0000000..e2b87d4
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainAddedEvent.java
@@ -0,0 +1,67 @@
+/*
+ * 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.messaging.event.tenant;
+
+import org.apache.stratos.messaging.event.Event;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * This event is fired when domains are added to a tenant subscription.
+ */
+public class SubscriptionDomainAddedEvent extends Event implements Serializable {
+    private static final long serialVersionUID = 3457484382856403382L;
+
+    private final int tenantId;
+    private final String serviceName;
+    private final Set<String> clusterIds;
+    private final String domainName;
+    private final String applicationContext;
+
+    public SubscriptionDomainAddedEvent(int tenantId, String serviceName, Set<String> clusterIds, String domainName,
+                                        String applicationContext) {
+        this.tenantId = tenantId;
+        this.serviceName = serviceName;
+        this.clusterIds = clusterIds;
+        this.domainName = domainName;
+        this.applicationContext = applicationContext;
+    }
+
+    public int getTenantId() {
+        return tenantId;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public Set<String> getClusterIds() {
+        return Collections.unmodifiableSet(clusterIds);
+    }
+
+    public String getDomainName() {
+        return domainName;
+    }
+
+    public String getApplicationContext() {
+        return applicationContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainRemovedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainRemovedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainRemovedEvent.java
new file mode 100644
index 0000000..b3d9578
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainRemovedEvent.java
@@ -0,0 +1,60 @@
+/*
+ * 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.messaging.event.tenant;
+
+import org.apache.stratos.messaging.event.Event;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * This event is fired when domains are removed from a tenant subscription.
+ */
+public class SubscriptionDomainRemovedEvent extends Event implements Serializable {
+    private static final long serialVersionUID = -8837521344795740210L;
+
+    private final int tenantId;
+    private final String serviceName;
+    private final Set<String> clusterIds;
+    private final String domainName;
+
+    public SubscriptionDomainRemovedEvent(int tenantId, String serviceName, Set<String> clusterIds, String domainName) {
+        this.tenantId = tenantId;
+        this.serviceName = serviceName;
+        this.clusterIds = clusterIds;
+        this.domainName = domainName;
+    }
+
+    public int getTenantId() {
+        return tenantId;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public Set<String> getClusterIds() {
+        return Collections.unmodifiableSet(clusterIds);
+    }
+
+    public String getDomainName() {
+        return domainName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainsAddedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainsAddedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainsAddedEvent.java
new file mode 100644
index 0000000..312571a
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainsAddedEvent.java
@@ -0,0 +1,60 @@
+/*
+ * 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.messaging.event.tenant;
+
+import org.apache.stratos.messaging.event.Event;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * This event is fired when domains are added to a tenant subscription.
+ */
+public class SubscriptionDomainsAddedEvent extends Event implements Serializable {
+    private static final long serialVersionUID = 3457484382856403382L;
+
+    private final int tenantId;
+    private final String serviceName;
+    private final Set<String> clusterIds;
+    private final Set<String> domains;
+
+    public SubscriptionDomainsAddedEvent(int tenantId, String serviceName, Set<String> clusterIds, Set<String> domains) {
+        this.tenantId = tenantId;
+        this.serviceName = serviceName;
+        this.clusterIds = clusterIds;
+        this.domains = (domains != null) ? domains : new HashSet<String>();
+    }
+
+    public int getTenantId() {
+        return tenantId;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public Set<String> getClusterIds() {
+        return Collections.unmodifiableSet(clusterIds);
+    }
+
+    public Set<String> getDomains() {
+        return Collections.unmodifiableSet(domains);
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainsRemovedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainsRemovedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainsRemovedEvent.java
new file mode 100644
index 0000000..3cc5664
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/SubscriptionDomainsRemovedEvent.java
@@ -0,0 +1,60 @@
+/*
+ * 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.messaging.event.tenant;
+
+import org.apache.stratos.messaging.event.Event;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * This event is fired when domains are removed from a tenant subscription.
+ */
+public class SubscriptionDomainsRemovedEvent extends Event implements Serializable {
+    private static final long serialVersionUID = -8837521344795740210L;
+
+    private final int tenantId;
+    private final String serviceName;
+    private final Set<String> clusterIds;
+    private Set<String> domains;
+
+    public SubscriptionDomainsRemovedEvent(int tenantId, String serviceName, Set<String> clusterIds, Set<String> domains) {
+        this.tenantId = tenantId;
+        this.serviceName = serviceName;
+        this.clusterIds = clusterIds;
+        this.domains = (domains != null) ? domains : new HashSet<String>();
+    }
+
+    public int getTenantId() {
+        return tenantId;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public Set<String> getClusterIds() {
+        return Collections.unmodifiableSet(clusterIds);
+    }
+
+    public Set<String> getDomains() {
+        return Collections.unmodifiableSet(domains);
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantSubscribedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantSubscribedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantSubscribedEvent.java
index 2be1ad3..d89de12 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantSubscribedEvent.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantSubscribedEvent.java
@@ -20,6 +20,7 @@
 package org.apache.stratos.messaging.event.tenant;
 
 import java.io.Serializable;
+import java.util.*;
 
 /**
  * This event is fired when a tenant is subscribed to a service.
@@ -29,10 +30,12 @@ public class TenantSubscribedEvent extends TenantEvent implements Serializable {
 
     private final int tenantId;
     private final String serviceName;
+    private final Set<String> clusterIds;
 
-    public TenantSubscribedEvent(int tenantId, String serviceName) {
+    public TenantSubscribedEvent(int tenantId, String serviceName, Set<String> clusterIds) {
         this.tenantId = tenantId;
         this.serviceName = serviceName;
+        this.clusterIds = clusterIds;
     }
 
     public int getTenantId() {
@@ -42,4 +45,8 @@ public class TenantSubscribedEvent extends TenantEvent implements Serializable {
     public String getServiceName() {
         return serviceName;
     }
+
+    public Set<String> getClusterIds() {
+        return Collections.unmodifiableSet(clusterIds);
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ClusterMaintenanceModeEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ClusterMaintenanceModeEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ClusterMaintenanceModeEvent.java
new file mode 100644
index 0000000..76e5820
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ClusterMaintenanceModeEvent.java
@@ -0,0 +1,58 @@
+/*
+ * 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.messaging.event.topology;
+
+import org.apache.stratos.messaging.domain.topology.ClusterStatus;
+
+import java.io.Serializable;
+
+public class ClusterMaintenanceModeEvent extends TopologyEvent implements Serializable {
+
+	private final String serviceName;
+	private final String clusterId;
+    private ClusterStatus status;
+
+    public ClusterMaintenanceModeEvent(String serviceName, String clusterId) {
+        this.serviceName = serviceName;
+        this.clusterId = clusterId;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    @Override
+    public String toString() {
+        return "ClusterMaintenanceModeEvent [serviceName=" + serviceName + ", clusterStatus=" +
+                status.toString() + "]";
+    }
+
+    public String getClusterId() {
+        return clusterId;
+    }
+
+    public ClusterStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(ClusterStatus status) {
+        this.status = status;
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberActivatedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberActivatedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberActivatedEvent.java
index 38d4f92..3e0d355 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberActivatedEvent.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberActivatedEvent.java
@@ -19,6 +19,9 @@
 
 package org.apache.stratos.messaging.event.topology;
 
+import java.io.Serializable;
+import java.util.*;
+
 import org.apache.stratos.messaging.domain.topology.Port;
 
 import java.io.Serializable;
@@ -38,8 +41,8 @@ public class MemberActivatedEvent extends TopologyEvent implements Serializable
     private final String networkPartitionId;
     private final String partitionId;
     private final String memberId;
-    private Map<String, Port> portMap;
-    private String memberPublicIp;
+    // Key: Port.proxy
+    private Map<Integer, Port> portMap;
     private String memberIp;
     private String groupId;
     private String applicationId;
@@ -50,7 +53,7 @@ public class MemberActivatedEvent extends TopologyEvent implements Serializable
         this.networkPartitionId = networkPartitionId;
         this.partitionId = partitionId;
         this.memberId = memberId;
-    	this.portMap = new HashMap<String, Port>();
+    	this.portMap = new HashMap<Integer, Port>();
     }
     
     public String getServiceName() {
@@ -72,32 +75,37 @@ public class MemberActivatedEvent extends TopologyEvent implements Serializable
     public String getMemberId() {
         return memberId;
     }
-    
+
     public Collection<Port> getPorts() {
-        return portMap.values();
+        return Collections.unmodifiableCollection(portMap.values());
     }
 
-    public void addPort(Port port) {
-        this.portMap.put(port.getProtocol(), port);
+    public Port getPort(int proxy) {
+        if(portMap.containsKey(proxy)) {
+            return portMap.get(proxy);
+        }
+        return null;
     }
 
-    public void removePort(Port port) {
-        this.portMap.remove(port.getProtocol());
+    public void addPort(Port port) {
+        this.portMap.put(port.getProxy(), port);
     }
 
-    public void removePort(String portName) {
-        this.portMap.remove(portName);
+    public void addPorts(Collection<Port> ports) {
+        for(Port port : ports) {
+            addPort(port);
+        }
     }
 
-    public boolean portExists(Port port) {
-        return this.portMap.containsKey(port.getProtocol());
+    public void removePort(Port port) {
+        this.portMap.remove(port.getProxy());
     }
 
-    public Port getPort(String portName) {
-        return this.portMap.get(portName);
+    public boolean portExists(Port port) {
+        return this.portMap.containsKey(port.getProxy());
     }
 
-	public String getMemberIp() {
+    public String getMemberIp() {
 	    return memberIp;
     }
 
@@ -105,15 +113,6 @@ public class MemberActivatedEvent extends TopologyEvent implements Serializable
 	    this.memberIp = memberIp;
     }
 
-       public String getMemberPublicIp() {
-           return memberPublicIp;
-    }
-
-       public void setMemberPublicIp(String memberPublicIp) {
-           this.memberPublicIp = memberPublicIp;
-    }
-
-
 	public String getGroupId() {
 		return groupId;
 	}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberTerminatedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberTerminatedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberTerminatedEvent.java
index c35f80c..d8fd990 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberTerminatedEvent.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/MemberTerminatedEvent.java
@@ -20,6 +20,7 @@
 package org.apache.stratos.messaging.event.topology;
 
 import java.io.Serializable;
+import java.util.Properties;
 
 /**
  * This event is fired by Cloud Controller when a member is terminated.
@@ -34,6 +35,8 @@ public class
     private final String partitionId;
     private final String memberId;
     private String groupId;
+    private Properties properties;
+
 
     public MemberTerminatedEvent(String serviceName, String clusterId, String networkPartitionId, String partitionId, String memberId) {
         this.serviceName = serviceName;
@@ -70,4 +73,11 @@ public class
 	public void setGroupId(String groupId) {
 		this.groupId = groupId;
 	}
+    public Properties getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Properties properties) {
+        this.properties = properties;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/tenant/SubscriptionDomainsAddedEventListener.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/tenant/SubscriptionDomainsAddedEventListener.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/tenant/SubscriptionDomainsAddedEventListener.java
new file mode 100644
index 0000000..3f169b7
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/tenant/SubscriptionDomainsAddedEventListener.java
@@ -0,0 +1,28 @@
+/*
+ * 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.messaging.listener.tenant;
+
+import org.apache.stratos.messaging.listener.EventListener;
+
+/**
+ * Tenant subscription domains added event listener.
+ */
+public abstract class SubscriptionDomainsAddedEventListener extends EventListener {
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/tenant/SubscriptionDomainsRemovedEventListener.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/tenant/SubscriptionDomainsRemovedEventListener.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/tenant/SubscriptionDomainsRemovedEventListener.java
new file mode 100644
index 0000000..5c81ad6
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/tenant/SubscriptionDomainsRemovedEventListener.java
@@ -0,0 +1,28 @@
+/*
+ * 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.messaging.listener.tenant;
+
+import org.apache.stratos.messaging.listener.EventListener;
+
+/**
+ * Tenant subscription domains removed event listener.
+ */
+public abstract class SubscriptionDomainsRemovedEventListener extends EventListener {
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/topology/ClusterMaintenanceModeEventListener.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/topology/ClusterMaintenanceModeEventListener.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/topology/ClusterMaintenanceModeEventListener.java
new file mode 100644
index 0000000..3bd2a19
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/listener/topology/ClusterMaintenanceModeEventListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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.messaging.listener.topology;
+
+import org.apache.stratos.messaging.listener.EventListener;
+
+public abstract class ClusterMaintenanceModeEventListener extends EventListener {
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/8c14177f/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainAddedMessageProcessor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainAddedMessageProcessor.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainAddedMessageProcessor.java
new file mode 100644
index 0000000..a185cd2
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainAddedMessageProcessor.java
@@ -0,0 +1,100 @@
+/*
+ * 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.messaging.message.processor.tenant;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.messaging.domain.tenant.Subscription;
+import org.apache.stratos.messaging.domain.tenant.SubscriptionDomain;
+import org.apache.stratos.messaging.domain.tenant.Tenant;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainAddedEvent;
+import org.apache.stratos.messaging.message.processor.MessageProcessor;
+import org.apache.stratos.messaging.message.receiver.tenant.TenantManager;
+import org.apache.stratos.messaging.util.Util;
+
+/**
+ * Subscription domain added message processor for adding domains to tenant subscriptions.
+ */
+public class SubscriptionDomainAddedMessageProcessor extends MessageProcessor {
+
+    private static final Log log = LogFactory.getLog(SubscriptionDomainAddedMessageProcessor.class);
+
+    private MessageProcessor nextProcessor;
+
+    @Override
+    public void setNext(MessageProcessor nextProcessor) {
+        this.nextProcessor = nextProcessor;
+    }
+
+    @Override
+    public boolean process(String type, String message, Object object) {
+        if (SubscriptionDomainAddedEvent.class.getName().equals(type)) {
+            // Return if tenant manager has not initialized
+
+            if (!TenantManager.getInstance().isInitialized()) {
+                return false;
+            }
+
+            // Parse complete message and build event
+            SubscriptionDomainAddedEvent event = (SubscriptionDomainAddedEvent) Util.jsonToObject(message, SubscriptionDomainAddedEvent.class);
+
+            try {
+                TenantManager.acquireWriteLock();
+                Tenant tenant = TenantManager.getInstance().getTenant(event.getTenantId());
+
+                if (tenant == null) {
+                    if (log.isWarnEnabled()) {
+                        log.warn(String.format("Tenant not found: [tenant-id] %d", event.getTenantId()));
+                    }
+                    return false;
+                }
+                Subscription subscription = tenant.getSubscription(event.getServiceName());
+                if (subscription == null) {
+                    if (log.isWarnEnabled()) {
+                        log.warn(String.format("Subscription not found: [tenant-id] %d", event.getTenantId()));
+                    }
+                    return false;
+                }
+                subscription.addSubscriptionDomain(new SubscriptionDomain(event.getDomainName(), event.getApplicationContext()));
+
+                if (log.isInfoEnabled()) {
+                    log.info(String.format("Domain added to tenant subscription: [tenant-id] %d [tenant-domain] %s " +
+                                    "[service] %s [domain-name] %s [application-context] %s", tenant.getTenantId(),
+                            tenant.getTenantDomain(), event.getServiceName(), event.getDomainName(), event.getApplicationContext()
+                    ));
+                }
+
+                // Notify event listeners
+                notifyEventListeners(event);
+                return true;
+            }
+            finally {
+                TenantManager.releaseWriteLock();
+            }
+        }
+        else {
+            if (nextProcessor != null) {
+                return nextProcessor.process(type, message, object);
+            } else {
+                throw new RuntimeException(String.format("Failed to process tenant message using available message processors: [type] %s [body] %s", type, message));
+            }
+        }
+    }
+}