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/03/07 13:26:37 UTC

[05/12] git commit: finalizing the refactoring of LB subscription and service deployment

finalizing the refactoring of LB subscription and service deployment


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

Branch: refs/heads/master
Commit: e79a7e2f0285bd523ef2e459801a3076ac866d8a
Parents: 436abf4
Author: Isuru <is...@wso2.com>
Authored: Sun Feb 16 20:08:13 2014 +0530
Committer: Isuru <is...@wso2.com>
Committed: Sun Feb 16 20:08:13 2014 +0530

----------------------------------------------------------------------
 .../behaviour/CartridgeMgtBehaviour.java        | 120 ++-
 .../stratos/manager/deploy/service/Service.java |  64 +-
 .../service/ServiceDeploymentManager.java       | 475 ++++++------
 .../multitenant/lb/MultiTenantLBService.java    |   6 +-
 .../category/DefaultLoadBalancerCategory.java   |   4 -
 .../category/ExistingLoadBalancerCategory.java  |  25 +-
 .../manager/lb/category/LBCategoryContext.java  | 152 ----
 .../lb/category/LoadBalancerCategory.java       | 123 +---
 .../ServiceLevelLoadBalancerCategory.java       |  18 +-
 .../manager/CartridgeSubscriptionManager.java   | 267 ++++---
 .../subscription/LBCartridgeSubscription.java   |  14 +-
 .../manager/subscription/SubscriptionData.java  |   2 -
 .../SubscriptionSingleTenantBehaviour.java      | 124 ----
 .../tenancy/SubscriptionTenancyBehaviour.java   |  27 +-
 .../utils/CartridgeSubscriptionUtils.java       | 104 +--
 .../rest/endpoint/services/ServiceUtils.java    | 731 +++++++++----------
 16 files changed, 1018 insertions(+), 1238 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/behaviour/CartridgeMgtBehaviour.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/behaviour/CartridgeMgtBehaviour.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/behaviour/CartridgeMgtBehaviour.java
index e3ea69b..0e06da6 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/behaviour/CartridgeMgtBehaviour.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/behaviour/CartridgeMgtBehaviour.java
@@ -18,29 +18,135 @@ package org.apache.stratos.manager.behaviour;
  * under the License.
  */
 
+import org.apache.axis2.AxisFault;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
 import org.apache.stratos.cloud.controller.pojo.Properties;
+import org.apache.stratos.cloud.controller.pojo.Property;
+import org.apache.stratos.manager.client.CloudControllerServiceClient;
 import org.apache.stratos.manager.dao.Cluster;
 import org.apache.stratos.manager.exception.ADCException;
 import org.apache.stratos.manager.exception.AlreadySubscribedException;
 import org.apache.stratos.manager.exception.NotSubscribedException;
 import org.apache.stratos.manager.exception.UnregisteredCartridgeException;
+import org.apache.stratos.manager.payload.BasicPayloadData;
 import org.apache.stratos.manager.payload.PayloadData;
+import org.apache.stratos.manager.payload.PayloadFactory;
 import org.apache.stratos.manager.repository.Repository;
 import org.apache.stratos.manager.subscriber.Subscriber;
+import org.apache.stratos.manager.subscription.utils.CartridgeSubscriptionUtils;
+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.Set;
 
-public interface CartridgeMgtBehaviour extends Serializable {
+public abstract class CartridgeMgtBehaviour implements Serializable {
+
+    private static final long serialVersionUID = 6529685098267757690L;
+
+    private static Log log = LogFactory.getLog(CartridgeMgtBehaviour.class);
 
     public PayloadData create (String alias, Cluster cluster, Subscriber subscriber, Repository repository, CartridgeInfo cartridgeInfo,
-                        String subscriptionKey, Map<String, String> customPayloadEntries) throws ADCException, AlreadySubscribedException;
+                               String subscriptionKey, Map<String, String> customPayloadEntries) throws ADCException, AlreadySubscribedException {
+
+
+        String clusterId = alias + "." + cartridgeInfo.getType() + ".domain";
+
+        // limit the cartridge alias to 30 characters in length
+        if (clusterId.length() > 30) {
+            clusterId = CartridgeSubscriptionUtils.limitLengthOfString(clusterId, 30);
+        }
+        cluster.setClusterDomain(clusterId);
+        // set hostname
+        cluster.setHostName(alias + "." + cluster.getHostName());
+
+        return createPayload(cartridgeInfo, subscriptionKey, subscriber, cluster, repository, alias, customPayloadEntries);
+    }
+
+    protected PayloadData createPayload (CartridgeInfo cartridgeInfo, String subscriptionKey, Subscriber subscriber, Cluster cluster,
+                                         Repository repository, String alias, Map<String, String> customPayloadEntries) throws ADCException {
+
+        //Create the payload
+        BasicPayloadData basicPayloadData = CartridgeSubscriptionUtils.createBasicPayload(cartridgeInfo, subscriptionKey, cluster, repository, alias, subscriber);
+        //Populate the basic payload details
+        basicPayloadData.populatePayload();
+
+        PayloadData payloadData = PayloadFactory.getPayloadDataInstance(cartridgeInfo.getProvider(),
+                cartridgeInfo.getType(), basicPayloadData);
+
+        // get the payload parameters defined in the cartridge definition file for this cartridge type
+        if (cartridgeInfo.getProperties() != null && cartridgeInfo.getProperties().length != 0) {
+
+            for (Property property : cartridgeInfo.getProperties()) {
+                // check if a property is related to the payload. Currently this is done by checking if the
+                // property name starts with 'payload_parameter.' suffix. If so the payload param name will
+                // be taken as the substring from the index of '.' to the end of the property name.
+                if (property.getName()
+                        .startsWith(CartridgeConstants.CUSTOM_PAYLOAD_PARAM_NAME_PREFIX)) {
+                    String payloadParamName = property.getName();
+                    payloadData.add(payloadParamName.substring(payloadParamName.indexOf(".") + 1), property.getValue());
+                }
+            }
+        }
+
+        //check if there are any custom payload entries defined
+        if (customPayloadEntries != null) {
+            //add them to the payload
+            Set<Map.Entry<String,String>> entrySet = customPayloadEntries.entrySet();
+            for (Map.Entry<String, String> entry : entrySet) {
+                payloadData.add(entry.getKey(), entry.getValue());
+            }
+        }
+
+        return payloadData;
+    }
+
+    public void register(CartridgeInfo cartridgeInfo, Cluster cluster, PayloadData payloadData, String autoscalePolicyName, String deploymentPolicyName, Properties properties) throws ADCException, UnregisteredCartridgeException {
+
+        log.info("Payload: " + payloadData.getCompletePayloadData().toString());
+
+        ApplicationManagementUtil.registerService(cartridgeInfo.getType(),
+                cluster.getClusterDomain(),
+                cluster.getClusterSubDomain(),
+                payloadData.getCompletePayloadData(),
+                payloadData.getBasicPayloadData().getTenantRange(),
+                cluster.getHostName(),
+                autoscalePolicyName,
+                deploymentPolicyName,
+                properties);
+    }
+
+    public void remove(String clusterId, String alias) throws ADCException, NotSubscribedException {
+
+        try {
+            CloudControllerServiceClient.getServiceClient().terminateAllInstances(clusterId);
+
+        } catch (AxisFault e) {
+            String errorMsg = "Error in terminating cartridge subscription, cluster id: " + clusterId;
+            log.error(errorMsg);
+            throw new ADCException(errorMsg, e);
+
+        } catch (Exception e) {
+            String errorMsg = "Error in terminating cartridge subscription, cluster id: " + clusterId;
+            log.error(errorMsg);
+            throw new ADCException(errorMsg, e);
+        }
+
+        log.info("Terminated all instances of " + clusterId);
+
+        try {
+            CloudControllerServiceClient.getServiceClient().unregisterService(clusterId);
+
+        } catch (Exception e) {
+            String errorMsg = "Error in unregistering service cluster with domain " + clusterId;
+            log.error(errorMsg);
+            throw new ADCException(errorMsg, e);
+        }
 
-    public void register (CartridgeInfo cartridgeInfo, Cluster cluster, PayloadData payloadData, String autoscalePolicyName,
-                          String deploymentPolicyName, Properties properties)
-            throws ADCException, UnregisteredCartridgeException;
+        log.info("Unregistered service cluster, domain " + clusterId + ", sub domain ");
+    }
 
-    public void remove (String clusterId, String alias)
-            throws ADCException, NotSubscribedException;
 }

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/Service.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/Service.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/Service.java
index bfe275c..42405a1 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/Service.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/Service.java
@@ -23,19 +23,15 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
 import org.apache.stratos.cloud.controller.pojo.Properties;
-import org.apache.stratos.cloud.controller.pojo.Property;
+import org.apache.stratos.manager.behaviour.CartridgeMgtBehaviour;
 import org.apache.stratos.manager.client.CloudControllerServiceClient;
+import org.apache.stratos.manager.dao.Cluster;
 import org.apache.stratos.manager.exception.ADCException;
 import org.apache.stratos.manager.exception.UnregisteredCartridgeException;
-import org.apache.stratos.manager.payload.BasicPayloadData;
 import org.apache.stratos.manager.payload.PayloadData;
-import org.apache.stratos.manager.payload.PayloadFactory;
 import org.apache.stratos.manager.subscription.utils.CartridgeSubscriptionUtils;
-import org.apache.stratos.manager.utils.CartridgeConstants;
 
-import java.io.Serializable;
-
-public abstract class Service implements Serializable {
+public abstract class Service extends CartridgeMgtBehaviour {
 
     private static Log log = LogFactory.getLog(Service.class);
 
@@ -43,12 +39,11 @@ public abstract class Service implements Serializable {
     private String autoscalingPolicyName;
     private String deploymentPolicyName;
     private String tenantRange;
-    private String clusterId;
-    private String hostName;
     private int tenantId;
     private String subscriptionKey;
     private CartridgeInfo cartridgeInfo;
     private PayloadData payloadData;
+    private Cluster cluster;
 
     public Service (String type, String autoscalingPolicyName, String deploymentPolicyName, int tenantId, CartridgeInfo cartridgeInfo,
     		String tenantRange) {
@@ -60,6 +55,7 @@ public abstract class Service implements Serializable {
         this.cartridgeInfo = cartridgeInfo;
         this.tenantRange = tenantRange;
         this.subscriptionKey = CartridgeSubscriptionUtils.generateSubscriptionKey();
+        this.setCluster(new Cluster());
     }
 
     public void deploy (Properties properties) throws ADCException, UnregisteredCartridgeException {
@@ -74,36 +70,14 @@ public abstract class Service implements Serializable {
         //host name is the hostname defined in cartridge definition
         setHostName(cartridgeInfo.getHostName());
 
-        //Create payload
-        BasicPayloadData basicPayloadData = CartridgeSubscriptionUtils.createBasicPayload(this);
-        //populate
-        basicPayloadData.populatePayload();
-        PayloadData payloadData = PayloadFactory.getPayloadDataInstance(cartridgeInfo.getProvider(),
-                cartridgeInfo.getType(), basicPayloadData);
-
-        // get the payload parameters defined in the cartridge definition file for this cartridge type
-        if (cartridgeInfo.getProperties() != null && cartridgeInfo.getProperties().length != 0) {
-
-            for (Property property : cartridgeInfo.getProperties()) {
-                // check if a property is related to the payload. Currently this is done by checking if the
-                // property name starts with 'payload_parameter.' suffix. If so the payload param name will
-                // be taken as the substring from the index of '.' to the end of the property name.
-                if (property.getName()
-                        .startsWith(CartridgeConstants.CUSTOM_PAYLOAD_PARAM_NAME_PREFIX)) {
-                    String payloadParamName = property.getName();
-                    payloadData.add(payloadParamName.substring(payloadParamName.indexOf(".") + 1), property.getValue());
-                }
-            }
-        }
-
-        //set PayloadData instance
-        setPayloadData(payloadData);
+        // create and set PayloadData instance
+        setPayloadData(createPayload(cartridgeInfo, subscriptionKey, null, cluster, null, null, null));
     }
 
     public void undeploy () throws ADCException {
 
         try {
-            CloudControllerServiceClient.getServiceClient().terminateAllInstances(clusterId);
+            CloudControllerServiceClient.getServiceClient().terminateAllInstances(cluster.getClusterDomain());
 
         } catch (Exception e) {
             String errorMsg = "Error in undeploying Service with type " + type;
@@ -114,15 +88,15 @@ public abstract class Service implements Serializable {
         log.info("terminated instance with Service Type " + type);
 
         try {
-            CloudControllerServiceClient.getServiceClient().unregisterService(clusterId);
+            CloudControllerServiceClient.getServiceClient().unregisterService(cluster.getClusterDomain());
 
         } catch (Exception e) {
-            String errorMsg = "Error in unregistering service cluster with domain " + clusterId;
+            String errorMsg = "Error in unregistering service cluster with domain " + cluster.getClusterDomain();
             log.error(errorMsg);
             throw new ADCException(errorMsg, e);
         }
 
-        log.info("Unregistered service with domain " + clusterId);
+        log.info("Unregistered service with domain " + cluster.getClusterDomain());
     }
 
     public String getType() {
@@ -158,19 +132,19 @@ public abstract class Service implements Serializable {
     }
 
     public String getClusterId() {
-        return clusterId;
+        return cluster.getClusterDomain();
     }
 
     public void setClusterId(String clusterId) {
-        this.clusterId = clusterId;
+        this.cluster.setClusterDomain(clusterId);
     }
 
     public String getHostName() {
-        return hostName;
+        return cluster.getHostName();
     }
 
     public void setHostName(String hostName) {
-        this.hostName = hostName;
+        this.cluster.setHostName(hostName);
     }
 
     public int getTenantId() {
@@ -204,4 +178,12 @@ public abstract class Service implements Serializable {
     public void setPayloadData(PayloadData payloadData) {
         this.payloadData = payloadData;
     }
+
+    public Cluster getCluster() {
+        return cluster;
+    }
+
+    public void setCluster(Cluster cluster) {
+        this.cluster = cluster;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/ServiceDeploymentManager.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/ServiceDeploymentManager.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/ServiceDeploymentManager.java
index b5e3889..a80aea0 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/ServiceDeploymentManager.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/ServiceDeploymentManager.java
@@ -21,12 +21,10 @@ package org.apache.stratos.manager.deploy.service;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.stratos.autoscaler.deployment.policy.DeploymentPolicy;
 import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
 import org.apache.stratos.cloud.controller.pojo.LoadbalancerConfig;
 import org.apache.stratos.cloud.controller.pojo.Properties;
 import org.apache.stratos.cloud.controller.pojo.Property;
-import org.apache.stratos.manager.client.AutoscalerServiceClient;
 import org.apache.stratos.manager.client.CloudControllerServiceClient;
 import org.apache.stratos.manager.deploy.service.multitenant.MultiTenantService;
 import org.apache.stratos.manager.deploy.service.multitenant.lb.MultiTenantLBService;
@@ -34,13 +32,13 @@ import org.apache.stratos.manager.exception.ADCException;
 import org.apache.stratos.manager.exception.PersistenceManagerException;
 import org.apache.stratos.manager.exception.ServiceAlreadyDeployedException;
 import org.apache.stratos.manager.exception.UnregisteredCartridgeException;
+import org.apache.stratos.manager.lb.category.*;
 import org.apache.stratos.manager.retriever.DataInsertionAndRetrievalManager;
 import org.apache.stratos.manager.subscription.CartridgeSubscription;
+import org.apache.stratos.manager.subscription.utils.CartridgeSubscriptionUtils;
 import org.apache.stratos.messaging.util.Constants;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
 
 public class ServiceDeploymentManager {
 
@@ -91,222 +89,244 @@ public class ServiceDeploymentManager {
             throw new ADCException(errorMsg);
         }
 
-        
-        // TODO - LB cartridge.... ??
 
-        List<Property> lbRefProp = new ArrayList<Property>();
+//        // TODO - LB cartridge.... ??
+//
+//        List<Property> lbRefProp = new ArrayList<Property>();
+//
+//        // get lb config reference
+//        LoadbalancerConfig lbConfig = cartridgeInfo.getLbConfig();
+//
+//        if (lbConfig == null || lbConfig.getProperties() == null) {
+//
+//            if (log.isDebugEnabled()) {
+//                log.debug("This Service does not require a load balancer. " + "[Service Name] " +
+//                          type);
+//            }
+//        } else {
+//
+//            Service lbService;
+//
+//            Properties lbReferenceProperties = lbConfig.getProperties();
+//
+//            Property property = new Property();
+//            property.setName(org.apache.stratos.messaging.util.Constants.LOAD_BALANCER_REF);
+//
+//            for (org.apache.stratos.cloud.controller.pojo.Property prop : lbReferenceProperties.getProperties()) {
+//
+//                String name = prop.getName();
+//                String value = prop.getValue();
+//
+//                // TODO make following a chain of responsibility pattern
+//                if (Constants.NO_LOAD_BALANCER.equals(name)) {
+//                    if ("true".equals(value)) {
+//                        if (log.isDebugEnabled()) {
+//                            log.debug("This cartridge does not require a load balancer. " +
+//                                      "[Type] " + type);
+//                        }
+//                        property.setValue(name);
+//                        lbRefProp.add(property);
+//                        break;
+//                    }
+//                } else if (Constants.EXISTING_LOAD_BALANCERS.equals(name)) {
+//                    String clusterIdsVal = value;
+//                    if (log.isDebugEnabled()) {
+//                        log.debug("This cartridge refers to existing load balancers. " + "[Type] " +
+//                                  type + "[Referenced Cluster Ids] " + clusterIdsVal);
+//                    }
+//
+//                    String[] clusterIds = clusterIdsVal.split(",");
+//
+//                    for (String clusterId : clusterIds) {
+//
+//                            try {
+//                            	AutoscalerServiceClient.getServiceClient().checkLBExistenceAgainstPolicy(clusterId,
+//                            			deploymentPolicyName);
+//                            } catch (Exception ex) {
+//                                // we don't need to throw the error here.
+//                                log.error(ex.getMessage(), ex);
+//                            }
+//
+//                    }
+//
+//                    property.setValue(name);
+//                    lbRefProp.add(property);
+//                    break;
+//
+//                } else if (Constants.DEFAULT_LOAD_BALANCER.equals(name)) {
+//
+//                    if ("true".equals(value)) {
+//
+//                        CartridgeInfo lbCartridgeInfo;
+//                        String lbCartridgeType = lbConfig.getType();
+//                        try {
+//                            // retrieve lb Cartridge info
+//                            lbCartridgeInfo = CloudControllerServiceClient.getServiceClient().getCartridgeInfo(lbCartridgeType);
+//                        } catch (Exception e) {
+//                            String msg = "Cannot get cartridge info: " + type;
+//                            log.error(msg, e);
+//                            throw new ADCException(msg, e);
+//                        }
+//
+//                        property.setValue(name);
+//                        if (log.isDebugEnabled()) {
+//                            log.debug("This cartridge uses default load balancer. " + "[Type] " +
+//                                      type);
+//                        }
+//
+//                            try {
+//                                // get the valid policies for lb cartridge
+//                                DeploymentPolicy[] lbCartridgeDepPolicies =
+//                                	AutoscalerServiceClient.getServiceClient().getDeploymentPolicies(lbCartridgeType);
+//                                // traverse deployment policies of lb cartridge
+//                                for (DeploymentPolicy policy : lbCartridgeDepPolicies) {
+//                                    // check existence of the subscribed policy
+//                                    if (deploymentPolicyName.equals(policy.getId())) {
+//
+//                                        if (!AutoscalerServiceClient.getServiceClient().checkDefaultLBExistenceAgainstPolicy(deploymentPolicyName)) {
+//
+//                                            // if lb cluster doesn't exist
+//                                            lbService = new MultiTenantLBService(lbCartridgeType,
+//                                                    lbCartridgeInfo.getDefaultAutoscalingPolicy(),
+//                                                    deploymentPolicyName, tenantId,
+//                                                    lbCartridgeInfo,
+//                                                    tenantRange);
+//
+//                                            Properties lbDeploymentProperties = new Properties();
+//
+//                                            // check if there are properties in LB cartridge info
+//                                            Property [] cartridgeInfoProps = lbCartridgeInfo.getProperties();
+//                                            if (cartridgeInfoProps != null && cartridgeInfoProps.length > 0) {
+//                                                lbDeploymentProperties.setProperties(combine(lbCartridgeInfo.getProperties(), new Property[]{property}));
+//                                            } else {
+//                                                lbDeploymentProperties.setProperties(new Property[]{property});
+//                                            }
+//
+//                                            lbService.deploy(lbDeploymentProperties);
+//
+//                                            // persist
+//                                            persist(lbService);
+//                                        }
+//                                    }
+//                                }
+//
+//                            } catch (Exception ex) {
+//                                // we don't need to throw the error here.
+//                                log.error(ex.getMessage(), ex);
+//                            }
+//
+//
+//                        lbRefProp.add(property);
+//                        break;
+//                    }
+//                } else if (Constants.SERVICE_AWARE_LOAD_BALANCER.equals(name)) {
+//
+//                    if ("true".equals(value)) {
+//
+//                        CartridgeInfo lbCartridgeInfo;
+//                        String lbCartridgeType = lbConfig.getType();
+//                        try {
+//                            // retrieve lb Cartridge info
+//                            lbCartridgeInfo = CloudControllerServiceClient.getServiceClient().getCartridgeInfo(lbCartridgeType);
+//                        } catch (Exception e) {
+//                            String msg = "Cannot get cartridge info: " + type;
+//                            log.error(msg, e);
+//                            throw new ADCException(msg, e);
+//                        }
+//
+//                        property.setValue(name);
+//                        if (log.isDebugEnabled()) {
+//                            log.debug("This cartridge uses a service aware load balancer. " +
+//                                    "[Type] " + type);
+//                        }
+//
+//                        // add a property for the service type
+//                        Property loadBalancedServiceTypeProperty = new Property();
+//                        loadBalancedServiceTypeProperty.setName(Constants.LOAD_BALANCED_SERVICE_TYPE);
+//                        loadBalancedServiceTypeProperty.setValue(type);
+//
+//                        try {
+//
+//                            // get the valid policies for lb cartridge
+//                            DeploymentPolicy[] lbCartridgeDepPolicies =
+//                                    AutoscalerServiceClient.getServiceClient().getDeploymentPolicies(lbCartridgeType);
+//                            // traverse deployment policies of lb cartridge
+//                            for (DeploymentPolicy policy : lbCartridgeDepPolicies) {
+//
+//                                // check existence of the subscribed policy
+//                                if (deploymentPolicyName.equals(policy.getId())) {
+//
+//                                    if (!AutoscalerServiceClient.getServiceClient().checkServiceLBExistenceAgainstPolicy(type,
+//                                            deploymentPolicyName)) {
+//
+//                                        lbCartridgeInfo.addProperties(property);
+//                                        lbCartridgeInfo.addProperties(loadBalancedServiceTypeProperty);
+//
+//                                        lbService = new MultiTenantLBService(lbCartridgeType,
+//                                                lbCartridgeInfo.getDefaultAutoscalingPolicy(),
+//                                                deploymentPolicyName, tenantId,
+//                                                lbCartridgeInfo,
+//                                                tenantRange);
+//
+//                                        Properties lbDeploymentProperties = new Properties();
+//
+//                                        // check if there are properties in LB cartridge info
+//                                        Property [] cartridgeInfoProps = lbCartridgeInfo.getProperties();
+//                                        if (cartridgeInfoProps != null && cartridgeInfoProps.length > 0) {
+//                                            lbDeploymentProperties.setProperties(combine(lbCartridgeInfo.getProperties(), new Property[]{property, loadBalancedServiceTypeProperty}));
+//                                        } else {
+//                                            lbDeploymentProperties.setProperties(new Property[]{property, loadBalancedServiceTypeProperty});
+//                                        }
+//
+//                                        lbService.deploy(lbDeploymentProperties);
+//
+//                                        // persist
+//                                        persist(lbService);
+//                                    }
+//                                }
+//                            }
+//
+//                        } catch (Exception ex) {
+//                            // we don't need to throw the error here.
+//                            log.error(ex.getMessage(), ex);
+//                        }
+//
+//
+//                        lbRefProp.add(property);
+//                        break;
+//                    }
+//                }
+//            }
+//        }
+
+        LBDataContext lbDataCtxt = null;
 
         // get lb config reference
         LoadbalancerConfig lbConfig = cartridgeInfo.getLbConfig();
-
         if (lbConfig == null || lbConfig.getProperties() == null) {
-
+            // no LB ref
             if (log.isDebugEnabled()) {
-                log.debug("This Service does not require a load balancer. " + "[Service Name] " +
-                          type);
+                log.debug("This Service does not require a load balancer. " + "[Service Name] " + type);
             }
+
         } else {
+            // LB ref found, get relevant LB Context data
+            lbDataCtxt = CartridgeSubscriptionUtils.getLoadBalancerDataContext(-1234, type, deploymentPolicyName, lbConfig);
 
-            Service lbService;
-
-            Properties lbReferenceProperties = lbConfig.getProperties();
-
-            Property property = new Property();
-            property.setName(org.apache.stratos.messaging.util.Constants.LOAD_BALANCER_REF);
-
-            for (org.apache.stratos.cloud.controller.pojo.Property prop : lbReferenceProperties.getProperties()) {
-
-                String name = prop.getName();
-                String value = prop.getValue();
-
-                // TODO make following a chain of responsibility pattern
-                if (Constants.NO_LOAD_BALANCER.equals(name)) {
-                    if ("true".equals(value)) {
-                        if (log.isDebugEnabled()) {
-                            log.debug("This cartridge does not require a load balancer. " +
-                                      "[Type] " + type);
-                        }
-                        property.setValue(name);
-                        lbRefProp.add(property);
-                        break;
-                    }
-                } else if (Constants.EXISTING_LOAD_BALANCERS.equals(name)) {
-                    String clusterIdsVal = value;
-                    if (log.isDebugEnabled()) {
-                        log.debug("This cartridge refers to existing load balancers. " + "[Type] " +
-                                  type + "[Referenced Cluster Ids] " + clusterIdsVal);
-                    }
-
-                    String[] clusterIds = clusterIdsVal.split(",");
-
-                    for (String clusterId : clusterIds) {
-
-                            try {
-                            	AutoscalerServiceClient.getServiceClient().checkLBExistenceAgainstPolicy(clusterId,
-                            			deploymentPolicyName);
-                            } catch (Exception ex) {
-                                // we don't need to throw the error here.
-                                log.error(ex.getMessage(), ex);
-                            }
-
-                    }
-
-                    property.setValue(name);
-                    lbRefProp.add(property);
-                    break;
-
-                } else if (Constants.DEFAULT_LOAD_BALANCER.equals(name)) {
-
-                    if ("true".equals(value)) {
-
-                        CartridgeInfo lbCartridgeInfo;
-                        String lbCartridgeType = lbConfig.getType();
-                        try {
-                            // retrieve lb Cartridge info
-                            lbCartridgeInfo = CloudControllerServiceClient.getServiceClient().getCartridgeInfo(lbCartridgeType);
-                        } catch (Exception e) {
-                            String msg = "Cannot get cartridge info: " + type;
-                            log.error(msg, e);
-                            throw new ADCException(msg, e);
-                        }
-
-                        property.setValue(name);
-                        if (log.isDebugEnabled()) {
-                            log.debug("This cartridge uses default load balancer. " + "[Type] " +
-                                      type);
-                        }
-
-                            try {
-                                // get the valid policies for lb cartridge
-                                DeploymentPolicy[] lbCartridgeDepPolicies =
-                                	AutoscalerServiceClient.getServiceClient().getDeploymentPolicies(lbCartridgeType);
-                                // traverse deployment policies of lb cartridge
-                                for (DeploymentPolicy policy : lbCartridgeDepPolicies) {
-                                    // check existence of the subscribed policy
-                                    if (deploymentPolicyName.equals(policy.getId())) {
-
-                                        if (!AutoscalerServiceClient.getServiceClient().checkDefaultLBExistenceAgainstPolicy(deploymentPolicyName)) {
-
-                                            // if lb cluster doesn't exist
-                                            lbService = new MultiTenantLBService(lbCartridgeType,
-                                                    lbCartridgeInfo.getDefaultAutoscalingPolicy(),
-                                                    deploymentPolicyName, tenantId,
-                                                    lbCartridgeInfo,
-                                                    tenantRange);
-
-                                            Properties lbDeploymentProperties = new Properties();
-
-                                            // check if there are properties in LB cartridge info
-                                            Property [] cartridgeInfoProps = lbCartridgeInfo.getProperties();
-                                            if (cartridgeInfoProps != null && cartridgeInfoProps.length > 0) {
-                                                lbDeploymentProperties.setProperties(combine(lbCartridgeInfo.getProperties(), new Property[]{property}));
-                                            } else {
-                                                lbDeploymentProperties.setProperties(new Property[]{property});
-                                            }
-
-                                            lbService.deploy(lbDeploymentProperties);
-
-                                            // persist
-                                            persist(lbService);
-                                        }
-                                    }
-                                }
-
-                            } catch (Exception ex) {
-                                // we don't need to throw the error here.
-                                log.error(ex.getMessage(), ex);
-                            }
-
-
-                        lbRefProp.add(property);
-                        break;
-                    }
-                } else if (Constants.SERVICE_AWARE_LOAD_BALANCER.equals(name)) {
-
-                    if ("true".equals(value)) {
-
-                        CartridgeInfo lbCartridgeInfo;
-                        String lbCartridgeType = lbConfig.getType();
-                        try {
-                            // retrieve lb Cartridge info
-                            lbCartridgeInfo = CloudControllerServiceClient.getServiceClient().getCartridgeInfo(lbCartridgeType);
-                        } catch (Exception e) {
-                            String msg = "Cannot get cartridge info: " + type;
-                            log.error(msg, e);
-                            throw new ADCException(msg, e);
-                        }
-
-                        property.setValue(name);
-                        if (log.isDebugEnabled()) {
-                            log.debug("This cartridge uses a service aware load balancer. " +
-                                    "[Type] " + type);
-                        }
-
-                        // add a property for the service type
-                        Property loadBalancedServiceTypeProperty = new Property();
-                        loadBalancedServiceTypeProperty.setName(Constants.LOAD_BALANCED_SERVICE_TYPE);
-                        loadBalancedServiceTypeProperty.setValue(type);
-
-                        try {
-
-                            // get the valid policies for lb cartridge
-                            DeploymentPolicy[] lbCartridgeDepPolicies =
-                                    AutoscalerServiceClient.getServiceClient().getDeploymentPolicies(lbCartridgeType);
-                            // traverse deployment policies of lb cartridge
-                            for (DeploymentPolicy policy : lbCartridgeDepPolicies) {
-
-                                // check existence of the subscribed policy
-                                if (deploymentPolicyName.equals(policy.getId())) {
-
-                                    if (!AutoscalerServiceClient.getServiceClient().checkServiceLBExistenceAgainstPolicy(type,
-                                            deploymentPolicyName)) {
-
-                                        lbCartridgeInfo.addProperties(property);
-                                        lbCartridgeInfo.addProperties(loadBalancedServiceTypeProperty);
-
-                                        lbService = new MultiTenantLBService(lbCartridgeType,
-                                                lbCartridgeInfo.getDefaultAutoscalingPolicy(),
-                                                deploymentPolicyName, tenantId,
-                                                lbCartridgeInfo,
-                                                tenantRange);
-
-                                        Properties lbDeploymentProperties = new Properties();
-
-                                        // check if there are properties in LB cartridge info
-                                        Property [] cartridgeInfoProps = lbCartridgeInfo.getProperties();
-                                        if (cartridgeInfoProps != null && cartridgeInfoProps.length > 0) {
-                                            lbDeploymentProperties.setProperties(combine(lbCartridgeInfo.getProperties(), new Property[]{property, loadBalancedServiceTypeProperty}));
-                                        } else {
-                                            lbDeploymentProperties.setProperties(new Property[]{property, loadBalancedServiceTypeProperty});
-                                        }
-
-                                        lbService.deploy(lbDeploymentProperties);
-
-                                        // persist
-                                        persist(lbService);
-                                    }
-                                }
-                            }
-
-                        } catch (Exception ex) {
-                            // we don't need to throw the error here.
-                            log.error(ex.getMessage(), ex);
-                        }
-
-
-                        lbRefProp.add(property);
-                        break;
-                    }
-                }
-            }
+            // deploy LB service cluster
+            deployLBCluster(type, lbDataCtxt, tenantRange);
         }
 
         Service service = new MultiTenantService(type, autoscalingPolicyName, deploymentPolicyName, tenantId, cartridgeInfo, tenantRange);
 
+        Properties serviceClusterProperties = null;
+        if (lbDataCtxt.getLoadBalancedServiceProperties() != null && !lbDataCtxt.getLoadBalancedServiceProperties().isEmpty()) {
+            serviceClusterProperties = new Properties();
+            serviceClusterProperties.setProperties(lbDataCtxt.getLoadBalancedServiceProperties().toArray(new Property[0]));
+        }
+
         //deploy the service
-        Properties serviceDeploymentProperties = new Properties();
-        serviceDeploymentProperties.setProperties(lbRefProp.toArray(new Property[0]));
-        service.deploy(serviceDeploymentProperties);
+        service.deploy(serviceClusterProperties);
 
         // persist
         persist(service);
@@ -314,6 +334,49 @@ public class ServiceDeploymentManager {
         return service;
     }
 
+    private void deployLBCluster (String loadBalancedService, LBDataContext lbDataCtxt, String tenantRange) throws ADCException, UnregisteredCartridgeException {
+
+        if (lbDataCtxt.getLbCategory().equals(Constants.NO_LOAD_BALANCER)) {
+            // no load balancer required
+            return;
+        }
+
+        LoadBalancerCategory loadBalancerCategory = null;
+
+        if (lbDataCtxt.getLbCategory().equals(Constants.EXISTING_LOAD_BALANCERS)) {
+            loadBalancerCategory = new ExistingLoadBalancerCategory();
+
+        } else if (lbDataCtxt.getLbCategory().equals(Constants.DEFAULT_LOAD_BALANCER)) {
+            loadBalancerCategory = new DefaultLoadBalancerCategory();
+
+        } else if (lbDataCtxt.getLbCategory().equals(Constants.SERVICE_AWARE_LOAD_BALANCER)) {
+            loadBalancerCategory = new ServiceLevelLoadBalancerCategory();
+        }
+
+        if (loadBalancerCategory == null) {
+            throw new ADCException("The given Load Balancer category " + lbDataCtxt.getLbCategory() + " not found");
+        }
+
+        // Set the load balanced service type
+        loadBalancerCategory.setLoadBalancedServiceType(loadBalancedService);
+
+        Service lbService = new MultiTenantLBService(lbDataCtxt.getLbCartridgeInfo().getType(), lbDataCtxt.getAutoscalePolicy(),
+                lbDataCtxt.getDeploymentPolicy(), -1234, lbDataCtxt.getLbCartridgeInfo(),
+                tenantRange, loadBalancerCategory);
+
+        Properties lbProperties = null;
+        if (lbDataCtxt.getLbProperperties() != null && !lbDataCtxt.getLbProperperties().isEmpty())  {
+            lbProperties = new Properties();
+            lbProperties.setProperties(lbDataCtxt.getLbProperperties().toArray(new Property[0]));
+        }
+
+        // delpoy
+        lbService.deploy(lbProperties);
+
+        // persist
+        persist(lbService);
+    }
+
     private void persist (Service service) throws ADCException {
 
         DataInsertionAndRetrievalManager dataInsertionAndRetrievalManager = new DataInsertionAndRetrievalManager();

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/MultiTenantLBService.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/MultiTenantLBService.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/MultiTenantLBService.java
index 3d8caa8..2fe829d 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/MultiTenantLBService.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/MultiTenantLBService.java
@@ -47,9 +47,7 @@ public class MultiTenantLBService extends Service {
         super.deploy(properties);
 
         //register the service
-        loadBalancerCategory.register();
-//        ApplicationManagementUtil.registerService(getType(), getClusterId(), CartridgeConstants.DEFAULT_SUBDOMAIN,
-//                getPayloadData().getCompletePayloadData(), getTenantRange(), getHostName(), getAutoscalingPolicyName(),
-//                getDeploymentPolicyName(), properties);
+        loadBalancerCategory.register(getCartridgeInfo(), getCluster(), getPayloadData(), getAutoscalingPolicyName(), getDeploymentPolicyName(),
+                properties);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/DefaultLoadBalancerCategory.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/DefaultLoadBalancerCategory.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/DefaultLoadBalancerCategory.java
index a346bbd..0df3589 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/DefaultLoadBalancerCategory.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/DefaultLoadBalancerCategory.java
@@ -21,8 +21,4 @@ package org.apache.stratos.manager.lb.category;
 
 public class DefaultLoadBalancerCategory extends LoadBalancerCategory {
 
-    public DefaultLoadBalancerCategory(LBCategoryContext lbCategoryContext) {
-        super(lbCategoryContext);
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ExistingLoadBalancerCategory.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ExistingLoadBalancerCategory.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ExistingLoadBalancerCategory.java
index 6523df8..15450bf 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ExistingLoadBalancerCategory.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ExistingLoadBalancerCategory.java
@@ -19,26 +19,35 @@
 
 package org.apache.stratos.manager.lb.category;
 
+import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
+import org.apache.stratos.cloud.controller.pojo.Properties;
+import org.apache.stratos.manager.dao.Cluster;
 import org.apache.stratos.manager.exception.ADCException;
+import org.apache.stratos.manager.exception.AlreadySubscribedException;
+import org.apache.stratos.manager.exception.NotSubscribedException;
 import org.apache.stratos.manager.exception.UnregisteredCartridgeException;
 import org.apache.stratos.manager.payload.PayloadData;
+import org.apache.stratos.manager.repository.Repository;
+import org.apache.stratos.manager.subscriber.Subscriber;
+
+import java.util.Map;
 
 public class ExistingLoadBalancerCategory extends LoadBalancerCategory {
 
-    public ExistingLoadBalancerCategory(LBCategoryContext lbCategoryContext) {
-        super(lbCategoryContext);
+    public PayloadData create (String alias, Cluster cluster, Subscriber subscriber, Repository repository, CartridgeInfo cartridgeInfo,
+                               String subscriptionKey, Map<String, String> customPayloadEntries) throws ADCException, AlreadySubscribedException {
+
+        // TODO
+        return null;
     }
 
-    public void register () throws ADCException, UnregisteredCartridgeException {
+    public void register (CartridgeInfo cartridgeInfo, Cluster cluster, PayloadData payloadData, String autoscalePolicyName, String deploymentPolicyName, Properties properties) throws ADCException, UnregisteredCartridgeException {
+
         //TODO
     }
 
-    public PayloadData createPayload() throws ADCException {
-        //TODO;
-        return null;
-    }
+    public void remove(String clusterId, String alias) throws ADCException, NotSubscribedException {
 
-    public void unregister () throws ADCException {
         //TODO
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LBCategoryContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LBCategoryContext.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LBCategoryContext.java
deleted file mode 100644
index e6420a9..0000000
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LBCategoryContext.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.stratos.manager.lb.category;
-
-import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
-import org.apache.stratos.cloud.controller.pojo.Properties;
-import org.apache.stratos.manager.dao.Cluster;
-import org.apache.stratos.manager.payload.PayloadData;
-import org.apache.stratos.manager.subscriber.Subscriber;
-
-import java.util.Map;
-
-public class LBCategoryContext {
-
-    private String lbType;
-    private PayloadData payloadData;
-    private Properties properties;
-    private Cluster cluster;
-    private String autoscalingPolicyName;
-    private String deploymentPolicyName;
-    private Map<String, String> customPayloadEntries;
-    private CartridgeInfo cartridgeInfo;
-    private String key;
-    private String loadbalancedServiceType;
-    private String subscriptionAlias;
-    private Subscriber subscriber;
-
-    public LBCategoryContext (String lbType, Cluster cluster, String autoscalingPolicyName, String deploymentPolicyName,
-                              CartridgeInfo cartridgeInfo, PayloadData payloadData, String key) {
-
-        this.lbType = lbType;
-        this.cluster = cluster;
-        this.autoscalingPolicyName = autoscalingPolicyName;
-        this.deploymentPolicyName = deploymentPolicyName;
-        this.cartridgeInfo = cartridgeInfo;
-        this.payloadData = payloadData;
-        this.key = key;
-    }
-
-    public PayloadData getPayloadData() {
-        return payloadData;
-    }
-
-    public void setPayloadData(PayloadData payloadData) {
-        this.payloadData = payloadData;
-    }
-
-    public Properties getProperties() {
-        return properties;
-    }
-
-    public void setProperties(Properties properties) {
-        this.properties = properties;
-    }
-
-    public Cluster getCluster() {
-        return cluster;
-    }
-
-    public void setCluster(Cluster cluster) {
-        this.cluster = cluster;
-    }
-
-    public String getAutoscalingPolicyName() {
-        return autoscalingPolicyName;
-    }
-
-    public void setAutoscalingPolicyName(String autoscalingPolicyName) {
-        this.autoscalingPolicyName = autoscalingPolicyName;
-    }
-
-    public String getDeploymentPolicyName() {
-        return deploymentPolicyName;
-    }
-
-    public void setDeploymentPolicyName(String deploymentPolicyName) {
-        this.deploymentPolicyName = deploymentPolicyName;
-    }
-
-    public Map<String, String> getCustomPayloadEntries() {
-        return customPayloadEntries;
-    }
-
-    public void setCustomPayloadEntries(Map<String, String> customPayloadEntries) {
-        this.customPayloadEntries = customPayloadEntries;
-    }
-
-    public CartridgeInfo getCartridgeInfo() {
-        return cartridgeInfo;
-    }
-
-    public void setCartridgeInfo(CartridgeInfo cartridgeInfo) {
-        this.cartridgeInfo = cartridgeInfo;
-    }
-
-    public String getLbType() {
-        return lbType;
-    }
-
-    public void setLbType(String lbType) {
-        this.lbType = lbType;
-    }
-
-    public String getLoadbalancedServiceType() {
-        return loadbalancedServiceType;
-    }
-
-    public void setLoadbalancedServiceType(String loadbalancedServiceType) {
-        this.loadbalancedServiceType = loadbalancedServiceType;
-    }
-
-    public String getKey() {
-        return key;
-    }
-
-    public void setKey(String key) {
-        this.key = key;
-    }
-
-    public String getSubscriptionAlias() {
-        return subscriptionAlias;
-    }
-
-    public void setSubscriptionAlias(String subscriptionAlias) {
-        this.subscriptionAlias = subscriptionAlias;
-    }
-
-    public Subscriber getSubscriber() {
-        return subscriber;
-    }
-
-    public void setSubscriber(Subscriber subscriber) {
-        this.subscriber = subscriber;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LoadBalancerCategory.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LoadBalancerCategory.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LoadBalancerCategory.java
index b2fca7b..906d2a9 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LoadBalancerCategory.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/LoadBalancerCategory.java
@@ -19,126 +19,17 @@
 
 package org.apache.stratos.manager.lb.category;
 
-import org.apache.axis2.AxisFault;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
-import org.apache.stratos.cloud.controller.pojo.Property;
-import org.apache.stratos.manager.client.CloudControllerServiceClient;
-import org.apache.stratos.manager.exception.ADCException;
-import org.apache.stratos.manager.exception.UnregisteredCartridgeException;
-import org.apache.stratos.manager.payload.BasicPayloadData;
-import org.apache.stratos.manager.payload.PayloadData;
-import org.apache.stratos.manager.payload.PayloadFactory;
-import org.apache.stratos.manager.subscription.utils.CartridgeSubscriptionUtils;
-import org.apache.stratos.manager.utils.ApplicationManagementUtil;
-import org.apache.stratos.manager.utils.CartridgeConstants;
+import org.apache.stratos.manager.behaviour.CartridgeMgtBehaviour;
 
-import java.util.Map;
-import java.util.Set;
+public abstract class LoadBalancerCategory extends CartridgeMgtBehaviour {
 
-public abstract class LoadBalancerCategory {
+    private String loadBalancedServiceType;
 
-    private static Log log = LogFactory.getLog(LoadBalancerCategory.class);
-
-    private LBCategoryContext lbCategoryContext;
-
-    public LoadBalancerCategory (LBCategoryContext lbCategoryContext) {
-        this.setLbCategoryContext(lbCategoryContext);
-    }
-
-    public void register () throws ADCException, UnregisteredCartridgeException {
-
-        log.info("Payload: " + getLbCategoryContext().getPayloadData().getCompletePayloadData().toString());
-
-        ApplicationManagementUtil.registerService(getLbCategoryContext().getLbType(),
-                getLbCategoryContext().getCluster().getClusterDomain(),
-                getLbCategoryContext().getCluster().getClusterSubDomain(),
-                getLbCategoryContext().getPayloadData().getCompletePayloadData(),
-                getLbCategoryContext().getPayloadData().getBasicPayloadData().getTenantRange(),
-                getLbCategoryContext().getCluster().getHostName(),
-                getLbCategoryContext().getAutoscalingPolicyName(),
-                getLbCategoryContext().getDeploymentPolicyName(),
-                getLbCategoryContext().getProperties());
-    }
-
-    public PayloadData createPayload() throws ADCException {
-
-        //Create the payload
-        BasicPayloadData basicPayloadData = CartridgeSubscriptionUtils.createBasicPayload(lbCategoryContext);
-        //Populate the basic payload details
-        basicPayloadData.populatePayload();
-
-        CartridgeInfo cartridgeInfo = getLbCategoryContext().getCartridgeInfo();
-        PayloadData payloadData = PayloadFactory.getPayloadDataInstance(cartridgeInfo.getProvider(),
-                cartridgeInfo.getType(), basicPayloadData);
-
-        // get the payload parameters defined in the cartridge definition file for this cartridge type
-        if (cartridgeInfo.getProperties() != null && cartridgeInfo.getProperties().length != 0) {
-
-            for (Property property : cartridgeInfo.getProperties()) {
-                // check if a property is related to the payload. Currently this is done by checking if the
-                // property name starts with 'payload_parameter.' suffix. If so the payload param name will
-                // be taken as the substring from the index of '.' to the end of the property name.
-                if (property.getName()
-                        .startsWith(CartridgeConstants.CUSTOM_PAYLOAD_PARAM_NAME_PREFIX)) {
-                    String payloadParamName = property.getName();
-                    payloadData.add(payloadParamName.substring(payloadParamName.indexOf(".") + 1), property.getValue());
-                }
-            }
-        }
-
-        //check if there are any custom payload entries defined
-        if (getLbCategoryContext().getCustomPayloadEntries() != null) {
-            //add them to the payload
-            Map<String, String> customPayloadEntries = getLbCategoryContext().getCustomPayloadEntries();
-            Set<Map.Entry<String,String>> entrySet = customPayloadEntries.entrySet();
-            for (Map.Entry<String, String> entry : entrySet) {
-                payloadData.add(entry.getKey(), entry.getValue());
-            }
-        }
-
-        return payloadData;
-    }
-
-    public void unregister () throws ADCException {
-
-        try {
-            CloudControllerServiceClient.getServiceClient().terminateAllInstances(getLbCategoryContext().getCluster().getClusterDomain());
-
-        } catch (AxisFault e) {
-            String errorMsg = "Error in terminating cartridge subscription, cluster id: " + getLbCategoryContext().getCluster().getClusterDomain();
-            log.error(errorMsg);
-            throw new ADCException(errorMsg, e);
-
-        } catch (Exception e) {
-            String errorMsg = "Error in terminating cartridge subscription, cluster id: " + getLbCategoryContext().getCluster().getClusterDomain();
-            log.error(errorMsg);
-            throw new ADCException(errorMsg, e);
-        }
-
-        log.info("Terminated all instances of " + getLbCategoryContext().getCluster().getClusterDomain() + " " +
-                getLbCategoryContext().getCluster().getClusterSubDomain());
-
-        try {
-            CloudControllerServiceClient.getServiceClient().unregisterService(getLbCategoryContext().getCluster().getClusterDomain());
-
-        } catch (Exception e) {
-            String errorMsg = "Error in unregistering service cluster with domain " + getLbCategoryContext().getCluster().getClusterDomain() +
-                    ", sub domain " + getLbCategoryContext().getCluster().getClusterSubDomain();
-            log.error(errorMsg);
-            throw new ADCException(errorMsg, e);
-        }
-
-        log.info("Unregistered service cluster, domain " + getLbCategoryContext().getCluster().getClusterDomain() + ", sub domain " +
-                getLbCategoryContext().getCluster().getClusterSubDomain());
-    }
-
-    public LBCategoryContext getLbCategoryContext() {
-        return lbCategoryContext;
+    public String getLoadBalancedServiceType() {
+        return loadBalancedServiceType;
     }
 
-    public void setLbCategoryContext(LBCategoryContext lbCategoryContext) {
-        this.lbCategoryContext = lbCategoryContext;
+    public void setLoadBalancedServiceType(String loadBalancedServiceType) {
+        this.loadBalancedServiceType = loadBalancedServiceType;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ServiceLevelLoadBalancerCategory.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ServiceLevelLoadBalancerCategory.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ServiceLevelLoadBalancerCategory.java
index 0bb979b..5e94047 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ServiceLevelLoadBalancerCategory.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/lb/category/ServiceLevelLoadBalancerCategory.java
@@ -19,20 +19,26 @@
 
 package org.apache.stratos.manager.lb.category;
 
+import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
+import org.apache.stratos.manager.dao.Cluster;
 import org.apache.stratos.manager.exception.ADCException;
+import org.apache.stratos.manager.exception.AlreadySubscribedException;
 import org.apache.stratos.manager.payload.PayloadData;
+import org.apache.stratos.manager.repository.Repository;
+import org.apache.stratos.manager.subscriber.Subscriber;
+
+import java.util.Map;
 
 public class ServiceLevelLoadBalancerCategory extends LoadBalancerCategory {
 
-    public ServiceLevelLoadBalancerCategory(LBCategoryContext lbCategoryContext) {
-        super(lbCategoryContext);
-    }
+    public PayloadData create (String alias, Cluster cluster, Subscriber subscriber, Repository repository, CartridgeInfo cartridgeInfo,
+                               String subscriptionKey, Map<String, String> customPayloadEntries) throws ADCException, AlreadySubscribedException {
 
-    public PayloadData createPayload() throws ADCException {
 
         // add payload entry for load balanced service type
-        PayloadData serviceLevelLbPayloadData = super.createPayload();
-        serviceLevelLbPayloadData.add("LOAD_BALANCED_SERVICE_TYPE", getLbCategoryContext().getLoadbalancedServiceType());
+        PayloadData serviceLevelLbPayloadData = super.create(alias, cluster, subscriber, repository, cartridgeInfo, subscriptionKey,
+                customPayloadEntries);
+        serviceLevelLbPayloadData.add("LOAD_BALANCED_SERVICE_TYPE", getLoadBalancedServiceType());
         return serviceLevelLbPayloadData;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/e79a7e2f/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 4e603c5..69574e1 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
@@ -21,12 +21,9 @@ package org.apache.stratos.manager.manager;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
-import org.apache.stratos.cloud.controller.pojo.Properties;
-import org.apache.stratos.cloud.controller.pojo.Property;
+import org.apache.stratos.cloud.controller.pojo.*;
 import org.apache.stratos.manager.client.CloudControllerServiceClient;
 import org.apache.stratos.manager.dao.CartridgeSubscriptionInfo;
-import org.apache.stratos.manager.dao.Cluster;
 import org.apache.stratos.manager.dto.SubscriptionInfo;
 import org.apache.stratos.manager.exception.*;
 import org.apache.stratos.manager.lb.category.*;
@@ -43,7 +40,6 @@ import org.apache.stratos.manager.subscription.utils.CartridgeSubscriptionUtils;
 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.util.Constants;
 import org.wso2.carbon.context.CarbonContext;
 
@@ -58,7 +54,7 @@ public class CartridgeSubscriptionManager {
     private static Log log = LogFactory.getLog(CartridgeSubscriptionManager.class);
     //private static DataInsertionAndRetrievalManager dataInsertionAndRetrievalManager = new DataInsertionAndRetrievalManager();
     
-    public CartridgeSubscription subscribeToCartridgeWithProperties(SubscriptionData subscriptionData)  throws ADCException,
+    public SubscriptionInfo subscribeToCartridgeWithProperties(SubscriptionData subscriptionData)  throws ADCException,
                                                                                             InvalidCartridgeAliasException,
                                                                                             DuplicateCartridgeAliasException,
                                                                                             PolicyException,
@@ -69,111 +65,81 @@ public class CartridgeSubscriptionManager {
                                                                                             AlreadySubscribedException,
                                                                                             InvalidRepositoryException {
 
-        int tenantId = subscriptionData.getTenantId();
-        String cartridgeType = subscriptionData.getCartridgeType();
-        String cartridgeAlias =  subscriptionData.getCartridgeAlias();
-        Property [] props = subscriptionData.getProperties();
-        String repositoryPassword = subscriptionData.getRepositoryPassword();
-        String repositoryUsername = subscriptionData.getRepositoryUsername();
-        boolean isPrivateRepository = subscriptionData.isPrivateRepository();
-        String repositoryURL = subscriptionData.getRepositoryURL();
-        String tenantDomain = subscriptionData.getTenantDomain();
-        String tenantAdminUsername = subscriptionData.getTenantAdminUsername();
-        String autoscalingPolicyName = subscriptionData.getAutoscalingPolicyName();
-        String deploymentPolicyName = subscriptionData.getDeploymentPolicyName();
-        String lbClusterId = subscriptionData.getLbClusterId();
-
         // validate cartridge alias
-        CartridgeSubscriptionUtils.validateCartridgeAlias(tenantId, cartridgeType, cartridgeAlias);
+        CartridgeSubscriptionUtils.validateCartridgeAlias(subscriptionData.getTenantId(), subscriptionData.getCartridgeType(), subscriptionData.getCartridgeAlias());
 
         CartridgeInfo cartridgeInfo;
         try {
-            cartridgeInfo =
-                            CloudControllerServiceClient.getServiceClient().getCartridgeInfo(cartridgeType);
-            /*
-            if (props != null) {
-                // TODO: temp fix, need to do a proper fix
-                Property[] cartridgeInfoProperties = cartridgeInfo.getProperties();
-                if(cartridgeInfoProperties != null) {
-                     int length = cartridgeInfoProperties.length + props.length;
-                    Property[] combined = new Property[length];
-                    System.arraycopy(cartridgeInfoProperties, 0, combined, 0, cartridgeInfoProperties.length);
-                    System.arraycopy(props, 0, combined, cartridgeInfoProperties.length, props.length);
-                    cartridgeInfo.setProperties(combined);
-                } else {
-                    cartridgeInfo.setProperties(props);
-                }
+            cartridgeInfo = CloudControllerServiceClient.getServiceClient().getCartridgeInfo(subscriptionData.getCartridgeType());
 
-            }
-            */
         } catch (UnregisteredCartridgeException e) {
             String message =
-                             cartridgeType +
-                                     " is not a valid cartridgeSubscription type. Please try again with a valid cartridgeSubscription type.";
+                    subscriptionData.getCartridgeType() + " is not a valid cartridgeSubscription type. Please try again with a valid cartridgeSubscription type.";
             log.error(message);
             throw e;
 
         } catch (Exception e) {
-            String message = "Error getting info for " + cartridgeType;
+            String message = "Error getting info for " + subscriptionData.getCartridgeType();
             log.error(message, e);
             throw new ADCException(message, e);
         }
 
-        //Decide tenancy behaviour
-        SubscriptionTenancyBehaviour tenancyBehaviour;
-        if(cartridgeInfo.getMultiTenant()) {
-            tenancyBehaviour = new SubscriptionMultiTenantBehaviour();
-        } else {
-            tenancyBehaviour = new SubscriptionSingleTenantBehaviour();
+        // check if this subscription requires Persistence Mapping, and its supported by the cartridge definition
+        Properties persistenceMappingProperties = null;
+        if (subscriptionData.getPersistanceMapping() != null) {
+            persistenceMappingProperties = getPersistenceMappingProperties(subscriptionData.getPersistanceMapping(), cartridgeInfo);
         }
 
-        //Create the CartridgeSubscription instance
-        CartridgeSubscription cartridgeSubscription = CartridgeSubscriptionFactory.
-                getCartridgeSubscriptionInstance(cartridgeInfo, tenancyBehaviour);
-
+        Properties serviceCartridgeSubscriptionProperties = null;
+        LBDataContext lbDataCtxt = null;
 
-        String subscriptionKey = CartridgeSubscriptionUtils.generateSubscriptionKey();
-
-        String encryptedRepoPassword = repositoryPassword != null && !repositoryPassword.isEmpty() ?
-                RepoPasswordMgtUtil.encryptPassword(repositoryPassword, subscriptionKey) : "";
-        
-        //Create repository
-        Repository repository = cartridgeSubscription.manageRepository(repositoryURL,
-                                                                       repositoryUsername,
-                                                                       encryptedRepoPassword,
-                                                                       isPrivateRepository,
-                                                                       cartridgeAlias,
-                                                                       cartridgeInfo, tenantDomain);
-
-        //Create subscriber
-        Subscriber subscriber = new Subscriber(tenantAdminUsername, tenantId, tenantDomain);
-
-        //Set the key
-        cartridgeSubscription.setSubscriptionKey(subscriptionKey);
-
-        // Set persistance mappings
-        cartridgeSubscription.setPersistanceMapping(subscriptionData.getPersistanceMapping());
+        // get lb config reference
+        LoadbalancerConfig lbConfig = cartridgeInfo.getLbConfig();
+        if (lbConfig == null || lbConfig.getProperties() == null) {
+            // no LB ref
+            if (log.isDebugEnabled()) {
+                log.debug("This Service does not require a load balancer. " + "[Service Name] " +
+                        subscriptionData.getCartridgeType());
+            }
 
-        //create subscription
-        cartridgeSubscription.createSubscription(subscriber, cartridgeAlias, autoscalingPolicyName,
-                                                deploymentPolicyName, repository);
+        } else {
+            // LB ref found, get relevant LB Context data
+            lbDataCtxt = CartridgeSubscriptionUtils.getLoadBalancerDataContext(subscriptionData.getTenantId(), subscriptionData.getCartridgeType(),
+                    subscriptionData.getDeploymentPolicyName(), lbConfig);
+
+            // subscribe to LB
+            CartridgeSubscription lbCartridgeSubscription = subscribeToLB (subscriptionData, lbDataCtxt);
+
+            if (lbCartridgeSubscription != null) {
+                // register LB cartridge subscription
+                Properties lbCartridgeSubscriptionProperties =  new Properties();
+                if (lbDataCtxt.getLbProperperties() != null && !lbDataCtxt.getLbProperperties().isEmpty()) {
+                    lbCartridgeSubscriptionProperties.setProperties(lbDataCtxt.getLbProperperties().toArray(new Property[0]));
+                }
 
-        // set the lb cluster id if its available
-        if (lbClusterId != null && !lbClusterId.isEmpty()) {
-            cartridgeSubscription.setLbClusterId(lbClusterId);
+                registerCartridgeSubscription(lbCartridgeSubscription, lbCartridgeSubscriptionProperties);
+            }
         }
 
-        log.info("Tenant [" + tenantId + "] with username [" + tenantAdminUsername +
-                 " subscribed to " + "] Cartridge Alias " + cartridgeAlias + ", Cartridge Type: " +
-                 cartridgeType + ", Repo URL: " + repositoryURL + ", Policy: " +
-                 autoscalingPolicyName);
+        // subscribe to relevant service cartridge
+        CartridgeSubscription serviceCartridgeSubscription = subscribe (subscriptionData, cartridgeInfo);
+        serviceCartridgeSubscriptionProperties = new Properties();
 
+        // lb related properties
+        if (lbDataCtxt.getLoadBalancedServiceProperties() != null && !lbDataCtxt.getLoadBalancedServiceProperties().isEmpty()) {
+            serviceCartridgeSubscriptionProperties.setProperties(lbDataCtxt.getLoadBalancedServiceProperties().toArray(new Property[0]));
+        }
 
-        // Publish tenant subscribed envent to message broker
-        CartridgeSubscriptionUtils.publishTenantSubscribedEvent(cartridgeSubscription.getSubscriber().getTenantId(),
-                cartridgeSubscription.getCartridgeInfo().getType());
+        // Persistence Mapping related properties
+        if (persistenceMappingProperties != null && persistenceMappingProperties.getProperties().length > 0) {
+            // add the properties to send to CC via register method
+            for (Property persistenceMappingProperty : persistenceMappingProperties.getProperties()) {
+                serviceCartridgeSubscriptionProperties.addProperties(persistenceMappingProperty);
+            }
+        }
 
-        return cartridgeSubscription;
+        // register service cartridge subscription
+        return registerCartridgeSubscription(serviceCartridgeSubscription, serviceCartridgeSubscriptionProperties);
     }
 
     private CartridgeSubscription subscribeToLB (SubscriptionData subscriptionData, LBDataContext lbDataContext)
@@ -182,33 +148,18 @@ public class CartridgeSubscriptionManager {
             DuplicateCartridgeAliasException, PolicyException, UnregisteredCartridgeException, RepositoryRequiredException, RepositoryCredentialsRequiredException,
             RepositoryTransportException, AlreadySubscribedException, InvalidRepositoryException {
 
-        LoadBalancerCategory loadBalancerCategory = null;
-
         if (lbDataContext.getLbCategory().equals(Constants.NO_LOAD_BALANCER)) {
             // no load balancer subscription required
+            log.info("No LB subscription required for the Subscription with alias: " + subscriptionData.getCartridgeAlias() + ", type: " +
+                    subscriptionData.getCartridgeType());
             return null;
-
-        }
-
-        String lbAlias = "lb" + lbDataContext.getLbCartridgeInfo().getType() + new Random().nextInt();
-
-        String lbClusterId = lbAlias + "." + lbDataContext.getLbCartridgeInfo().getType() + ".domain";
-
-        // limit the cartridge alias to 30 characters in length
-        if (lbClusterId.length() > 30) {
-            lbClusterId = CartridgeSubscriptionUtils.limitLengthOfString(lbClusterId, 30);
         }
 
-        Cluster lbCluster = new Cluster();
-        lbCluster.setClusterDomain(lbClusterId);
-        // set hostname
-        lbCluster.setHostName(lbAlias + "." + lbDataContext.getLbCartridgeInfo().getHostName());
+        LoadBalancerCategory loadBalancerCategory = null;
 
-        LBCategoryContext lbCategoryContext = new LBCategoryContext(lbDataContext.getLbCartridgeInfo().getType(), lbCluster, lbDataContext.getAutoscalePolicy(),
-                lbDataContext.getDeploymentPolicy(), lbDataContext.getLbCartridgeInfo(), );
+        String lbAlias = "lb" + lbDataContext.getLbCartridgeInfo().getType() + new Random().nextInt();
 
         if (lbDataContext.getLbCategory().equals(Constants.EXISTING_LOAD_BALANCERS)) {
-
             loadBalancerCategory = new ExistingLoadBalancerCategory();
 
         } else if (lbDataContext.getLbCategory().equals(Constants.DEFAULT_LOAD_BALANCER)) {
@@ -226,6 +177,9 @@ public class CartridgeSubscriptionManager {
             throw new ADCException("LB Cartridge must be single tenant");
         }
 
+        // Set the load balanced service type
+        loadBalancerCategory.setLoadBalancedServiceType(subscriptionData.getCartridgeType());
+
         // Create the CartridgeSubscription instance
         CartridgeSubscription cartridgeSubscription = CartridgeSubscriptionFactory.getLBCartridgeSubscriptionInstance(lbDataContext, loadBalancerCategory);
 
@@ -234,12 +188,7 @@ public class CartridgeSubscriptionManager {
         cartridgeSubscription.setSubscriptionKey(subscriptionKey);
 
         // Create repository
-        Repository repository = cartridgeSubscription.manageRepository(null,
-                "",
-                "",
-                false,
-                lbAlias,
-                lbDataContext.getLbCartridgeInfo(),
+        Repository repository = cartridgeSubscription.manageRepository(null, "",  "", false, lbAlias, lbDataContext.getLbCartridgeInfo(),
                 subscriptionData.getTenantDomain());
 
         // Create subscriber
@@ -251,9 +200,60 @@ public class CartridgeSubscriptionManager {
 
 
         log.info("Tenant [" + subscriptionData.getTenantId() + "] with username [" + subscriptionData.getTenantAdminUsername() +
-                " subscribed to " + "] Cartridge with Alias " + lbAlias + ", Cartridge Type: " +
-                lbCategoryContext.getLbType() + ", Autoscale Policy: " +
-                lbDataContext.getAutoscalePolicy() + ", Deployment Policy: " + lbDataContext.getDeploymentPolicy());
+                " subscribed to " + "] Cartridge with Alias " + lbAlias + ", Cartridge Type: " + lbDataContext.getLbCartridgeInfo().getType() +
+                ", Autoscale Policy: " + lbDataContext.getAutoscalePolicy() + ", Deployment Policy: " + lbDataContext.getDeploymentPolicy());
+
+        // Publish tenant subscribed event to message broker
+        CartridgeSubscriptionUtils.publishTenantSubscribedEvent(cartridgeSubscription.getSubscriber().getTenantId(),
+                cartridgeSubscription.getCartridgeInfo().getType());
+
+        return cartridgeSubscription;
+    }
+
+    private CartridgeSubscription subscribe (SubscriptionData subscriptionData, CartridgeInfo cartridgeInfo)
+
+            throws ADCException, InvalidCartridgeAliasException,
+            DuplicateCartridgeAliasException, PolicyException, UnregisteredCartridgeException, RepositoryRequiredException, RepositoryCredentialsRequiredException,
+            RepositoryTransportException, AlreadySubscribedException, InvalidRepositoryException {
+
+
+        // Decide tenancy behaviour
+        SubscriptionTenancyBehaviour tenancyBehaviour;
+        if(cartridgeInfo.getMultiTenant()) {
+            tenancyBehaviour = new SubscriptionMultiTenantBehaviour();
+        } else {
+            tenancyBehaviour = new SubscriptionSingleTenantBehaviour();
+        }
+
+        // Create the CartridgeSubscription instance
+        CartridgeSubscription cartridgeSubscription = CartridgeSubscriptionFactory.
+                getCartridgeSubscriptionInstance(cartridgeInfo, tenancyBehaviour);
+
+        // Generate and set the key
+        String subscriptionKey = CartridgeSubscriptionUtils.generateSubscriptionKey();
+        cartridgeSubscription.setSubscriptionKey(subscriptionKey);
+
+        // Create repository
+        Repository repository = cartridgeSubscription.manageRepository(subscriptionData.getRepositoryURL(),
+                subscriptionData.getRepositoryUsername(),
+                subscriptionData.getRepositoryPassword(),
+                subscriptionData.isPrivateRepository(),
+                subscriptionData.getCartridgeAlias(),
+                cartridgeInfo,
+                subscriptionData.getTenantDomain());
+
+        // Create subscriber
+        Subscriber subscriber = new Subscriber(subscriptionData.getTenantAdminUsername(), subscriptionData.getTenantId(), subscriptionData.getTenantDomain());
+
+        // create subscription
+        cartridgeSubscription.createSubscription(subscriber, subscriptionData.getCartridgeAlias(), subscriptionData.getAutoscalingPolicyName(),
+                subscriptionData.getDeploymentPolicyName(), repository);
+
+
+        log.info("Tenant [" + subscriptionData.getTenantId() + "] with username [" + subscriptionData.getTenantAdminUsername() +
+                " subscribed to " + "] Cartridge with Alias " + subscriptionData.getCartridgeAlias() + ", Cartridge Type: " +
+                subscriptionData.getCartridgeType() + ", Repo URL: " + subscriptionData.getRepositoryURL() + ", Autoscale Policy: " +
+                subscriptionData.getAutoscalingPolicyName() + ", Deployment Policy: " + subscriptionData.getDeploymentPolicyName());
 
 
         // Publish tenant subscribed event to message broker
@@ -272,7 +272,7 @@ public class CartridgeSubscriptionManager {
      * @throws ADCException
      * @throws UnregisteredCartridgeException
      */
-    public SubscriptionInfo registerCartridgeSubscription(CartridgeSubscription cartridgeSubscription, Properties properties)
+    private SubscriptionInfo registerCartridgeSubscription(CartridgeSubscription cartridgeSubscription, Properties properties)
             throws ADCException, UnregisteredCartridgeException {
 
         CartridgeSubscriptionInfo cartridgeSubscriptionInfo = cartridgeSubscription.registerSubscription(properties);
@@ -351,7 +351,42 @@ public class CartridgeSubscriptionManager {
             throw new NotSubscribedException(errorMsg, alias);
         }
     }
-    
+
+    private Properties getPersistenceMappingProperties (PersistanceMapping persistanceMapping, CartridgeInfo cartridgeInfo) throws ADCException {
+
+        if (!persistanceMapping.getPersistanceRequired()) {
+            // Persistence Mapping not required for this subscription
+            return null;
+        }
+
+        if (persistanceMapping.getPersistanceRequired() && !cartridgeInfo.isPeristanceMappingsSpecified()) {
+            // Persistence Mapping not supported in the cartridge definition - error
+            String errorMsg = "Persistence Mapping not supported by the cartridge type " + cartridgeInfo.getType();
+            log.error(errorMsg);
+            throw new ADCException(errorMsg);
+        }
+
+        Property persistanceRequiredProperty = new Property();
+        persistanceRequiredProperty.setName(Constants.IS_VOLUME_REQUIRED);
+        persistanceRequiredProperty.setValue(String.valueOf(persistanceMapping.getPersistanceRequired()));
+
+        Property sizeProperty = new Property();
+        sizeProperty.setName(Constants.VOLUME_SIZE);
+        sizeProperty.setValue(Integer.toString(persistanceMapping.getSize()));
+
+        Property deviceProperty = new Property();
+        deviceProperty.setName(Constants.DEVICE_NAME);
+        deviceProperty.setValue(String.valueOf(persistanceMapping.getDevice()));
+
+        Property deleteOnTerminationProperty = new Property();
+        deleteOnTerminationProperty.setName(Constants.SHOULD_DELETE_VOLUME);
+        deleteOnTerminationProperty.setValue(String.valueOf(persistanceMapping.getRemoveOntermination()));
+
+        Properties persistenceMappingProperties = new Properties();
+        persistenceMappingProperties.setProperties(new Property[]{persistanceRequiredProperty, sizeProperty, deviceProperty, deleteOnTerminationProperty});
+
+        return persistenceMappingProperties;
+    }
     
     /**
      *