You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by ma...@apache.org on 2014/07/08 09:41:51 UTC

[01/14] Clustering changes for stratos

Repository: stratos
Updated Branches:
  refs/heads/4.0.0 37372c2e7 -> e1c15c4e9


http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/service-stubs/org.apache.stratos.cloud.controller.service.stub/src/main/resources/CloudControllerService.wsdl
----------------------------------------------------------------------
diff --git a/service-stubs/org.apache.stratos.cloud.controller.service.stub/src/main/resources/CloudControllerService.wsdl b/service-stubs/org.apache.stratos.cloud.controller.service.stub/src/main/resources/CloudControllerService.wsdl
index ac16821..a354310 100644
--- a/service-stubs/org.apache.stratos.cloud.controller.service.stub/src/main/resources/CloudControllerService.wsdl
+++ b/service-stubs/org.apache.stratos.cloud.controller.service.stub/src/main/resources/CloudControllerService.wsdl
@@ -1,960 +1,943 @@
-<!--
-  ~ 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.
-  -->
-
 <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ax220="http://partition.deployment.controller.cloud.stratos.apache.org/xsd" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ax221="http://pojo.controller.cloud.stratos.apache.org/xsd" xmlns:ns="http://impl.controller.cloud.stratos.apache.org" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ax218="http://exception.controller.cloud.stratos.apache.org/xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://impl.controller.cloud.stratos.apache.org">
     <wsdl:documentation>CloudControllerService</wsdl:documentation>
     <wsdl:types>
         <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://exception.controller.cloud.stratos.apache.org/xsd">
-            <xs:complexType name="InvalidPartitionException">
-                <xs:sequence>
-                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
-                </xs:sequence>
-            </xs:complexType>
             <xs:complexType name="UnregisteredClusterException">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="UnregisteredCartridgeException">
+            <xs:complexType name="InvalidPartitionException">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
             <xs:complexType name="InvalidCartridgeDefinitionException">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
             <xs:complexType name="InvalidIaasProviderException">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"></xs:element>
+                </xs:sequence>
+            </xs:complexType>
+            <xs:complexType name="UnregisteredCartridgeException">
+                <xs:sequence>
+                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
             <xs:complexType name="InvalidCartridgeTypeException">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
             <xs:complexType name="InvalidMemberException">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
             <xs:complexType name="InvalidClusterException">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
         </xs:schema>
         <xs:schema xmlns:ax219="http://exception.controller.cloud.stratos.apache.org/xsd" xmlns:ax223="http://partition.deployment.controller.cloud.stratos.apache.org/xsd" xmlns:ax224="http://pojo.controller.cloud.stratos.apache.org/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://impl.controller.cloud.stratos.apache.org">
-            <xs:import namespace="http://exception.controller.cloud.stratos.apache.org/xsd"/>
-            <xs:import namespace="http://partition.deployment.controller.cloud.stratos.apache.org/xsd"/>
-            <xs:import namespace="http://pojo.controller.cloud.stratos.apache.org/xsd"/>
+            <xs:import namespace="http://exception.controller.cloud.stratos.apache.org/xsd"></xs:import>
+            <xs:import namespace="http://partition.deployment.controller.cloud.stratos.apache.org/xsd"></xs:import>
+            <xs:import namespace="http://pojo.controller.cloud.stratos.apache.org/xsd"></xs:import>
+            <xs:element name="CloudControllerServiceUnregisteredClusterException">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element minOccurs="0" name="UnregisteredClusterException" nillable="true" type="ax219:UnregisteredClusterException"></xs:element>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="unregisterService">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"></xs:element>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
             <xs:element name="CloudControllerServiceInvalidPartitionException">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="InvalidPartitionException" nillable="true" type="ax219:InvalidPartitionException"/>
+                        <xs:element minOccurs="0" name="InvalidPartitionException" nillable="true" type="ax219:InvalidPartitionException"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="validatePartition">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="partition" nillable="true" type="ax220:Partition"/>
+                        <xs:element minOccurs="0" name="partition" nillable="true" type="ax220:Partition"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="validatePartitionResponse">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="return" type="xs:boolean"/>
+                        <xs:element minOccurs="0" name="return" type="xs:boolean"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="CloudControllerServiceUnregisteredClusterException">
+            <xs:element name="CloudControllerServiceInvalidCartridgeDefinitionException">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="UnregisteredClusterException" nillable="true" type="ax219:UnregisteredClusterException"/>
+                        <xs:element minOccurs="0" name="InvalidCartridgeDefinitionException" nillable="true" type="ax219:InvalidCartridgeDefinitionException"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="unregisterService">
+            <xs:element name="CloudControllerServiceInvalidIaasProviderException">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"/>
+                        <xs:element minOccurs="0" name="InvalidIaasProviderException" nillable="true" type="ax219:InvalidIaasProviderException"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="CloudControllerServiceUnregisteredCartridgeException">
+            <xs:element name="deployCartridgeDefinition">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="UnregisteredCartridgeException" nillable="true" type="ax219:UnregisteredCartridgeException"/>
+                        <xs:element minOccurs="0" name="cartridgeConfig" nillable="true" type="ax221:CartridgeConfig"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="getCartridgeInfo">
+            <xs:element name="getClusterContext">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"/>
+                        <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="getCartridgeInfoResponse">
+            <xs:element name="getClusterContextResponse">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="return" nillable="true" type="ax221:CartridgeInfo"/>
+                        <xs:element minOccurs="0" name="return" nillable="true" type="ax221:ClusterContext"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="CloudControllerServiceInvalidCartridgeDefinitionException">
+            <xs:element name="CloudControllerServiceUnregisteredCartridgeException">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="InvalidCartridgeDefinitionException" nillable="true" type="ax219:InvalidCartridgeDefinitionException"/>
+                        <xs:element minOccurs="0" name="UnregisteredCartridgeException" nillable="true" type="ax219:UnregisteredCartridgeException"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="CloudControllerServiceInvalidIaasProviderException">
+            <xs:element name="getCartridgeInfo">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="InvalidIaasProviderException" nillable="true" type="ax219:InvalidIaasProviderException"/>
+                        <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="deployCartridgeDefinition">
+            <xs:element name="getCartridgeInfoResponse">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="cartridgeConfig" nillable="true" type="ax221:CartridgeConfig"/>
+                        <xs:element minOccurs="0" name="return" nillable="true" type="ax221:CartridgeInfo"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="CloudControllerServiceInvalidCartridgeTypeException">
+            <xs:element name="startInstance">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="InvalidCartridgeTypeException" nillable="true" type="ax219:InvalidCartridgeTypeException"/>
+                        <xs:element minOccurs="0" name="memberContext" nillable="true" type="ax221:MemberContext"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="validateDeploymentPolicy">
+            <xs:element name="startInstanceResponse">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"/>
-                        <xs:element maxOccurs="unbounded" minOccurs="0" name="partitions" nillable="true" type="ax220:Partition"/>
+                        <xs:element minOccurs="0" name="return" nillable="true" type="ax221:MemberContext"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="validateDeploymentPolicyResponse">
+            <xs:element name="CloudControllerServiceInvalidCartridgeTypeException">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="return" type="xs:boolean"/>
+                        <xs:element minOccurs="0" name="InvalidCartridgeTypeException" nillable="true" type="ax219:InvalidCartridgeTypeException"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="undeployCartridgeDefinition">
+            <xs:element name="validateDeploymentPolicy">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"/>
+                        <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"></xs:element>
+                        <xs:element maxOccurs="unbounded" minOccurs="0" name="partitions" nillable="true" type="ax220:Partition"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="startInstance">
+            <xs:element name="validateDeploymentPolicyResponse">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="memberContext" nillable="true" type="ax221:MemberContext"/>
+                        <xs:element minOccurs="0" name="return" type="xs:boolean"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
-            <xs:element name="startInstanceResponse">
+            <xs:element name="undeployCartridgeDefinition">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="return" nillable="true" type="ax221:MemberContext"/>
+                        <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="CloudControllerServiceInvalidMemberException">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="InvalidMemberException" nillable="true" type="ax219:InvalidMemberException"/>
+                        <xs:element minOccurs="0" name="InvalidMemberException" nillable="true" type="ax219:InvalidMemberException"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="terminateInstance">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="memberId" nillable="true" type="xs:string"/>
+                        <xs:element minOccurs="0" name="memberId" nillable="true" type="xs:string"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="CloudControllerServiceInvalidClusterException">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="InvalidClusterException" nillable="true" type="ax219:InvalidClusterException"/>
+                        <xs:element minOccurs="0" name="InvalidClusterException" nillable="true" type="ax219:InvalidClusterException"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="terminateAllInstances">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"/>
+                        <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="getRegisteredCartridges">
                 <xs:complexType>
-                    <xs:sequence/>
+                    <xs:sequence></xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="getRegisteredCartridgesResponse">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element maxOccurs="unbounded" minOccurs="0" name="return" nillable="true" type="xs:string"/>
-                    </xs:sequence>
-                </xs:complexType>
-            </xs:element>
-            <xs:element name="getClusterContext">
-                <xs:complexType>
-                    <xs:sequence>
-                        <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"/>
-                    </xs:sequence>
-                </xs:complexType>
-            </xs:element>
-            <xs:element name="getClusterContextResponse">
-                <xs:complexType>
-                    <xs:sequence>
-                        <xs:element minOccurs="0" name="return" nillable="true" type="ax221:ClusterContext"/>
+                        <xs:element maxOccurs="unbounded" minOccurs="0" name="return" nillable="true" type="xs:string"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="registerService">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="registrant" nillable="true" type="ax221:Registrant"/>
+                        <xs:element minOccurs="0" name="registrant" nillable="true" type="ax221:Registrant"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
             <xs:element name="registerServiceResponse">
                 <xs:complexType>
                     <xs:sequence>
-                        <xs:element minOccurs="0" name="return" type="xs:boolean"/>
+                        <xs:element minOccurs="0" name="return" type="xs:boolean"></xs:element>
                     </xs:sequence>
                 </xs:complexType>
             </xs:element>
         </xs:schema>
         <xs:schema xmlns:ax225="http://partition.deployment.controller.cloud.stratos.apache.org/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://pojo.controller.cloud.stratos.apache.org/xsd">
-            <xs:import namespace="http://partition.deployment.controller.cloud.stratos.apache.org/xsd"/>
+            <xs:import namespace="http://partition.deployment.controller.cloud.stratos.apache.org/xsd"></xs:import>
             <xs:complexType name="Properties">
                 <xs:sequence>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="properties" nillable="true" type="ax221:Property"/>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="properties" nillable="true" type="ax221:Property"></xs:element>
                 </xs:sequence>
             </xs:complexType>
             <xs:complexType name="Property">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="name" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="value" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="name" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="value" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="CartridgeInfo">
+            <xs:complexType name="CartridgeConfig">
                 <xs:sequence>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="appTypes" nillable="true" type="ax221:AppType"/>
-                    <xs:element minOccurs="0" name="baseDir" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="defaultAutoscalingPolicy" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="defaultDeploymentPolicy" nillable="true" type="xs:string"/>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="deploymentDirs" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="description" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="displayName" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="hostName" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="lbConfig" nillable="true" type="ax221:LoadbalancerConfig"/>
-                    <xs:element minOccurs="0" name="multiTenant" type="xs:boolean"/>
-                    <xs:element minOccurs="0" name="persistence" nillable="true" type="ax221:Persistence"/>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="portMappings" nillable="true" type="ax221:PortMapping"/>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="properties" nillable="true" type="ax221:Property"/>
-                    <xs:element minOccurs="0" name="provider" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="version" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="baseDir" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="defaultAutoscalingPolicy" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="defaultDeploymentPolicy" nillable="true" type="xs:string"></xs:element>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="deploymentDirs" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="description" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="displayName" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="hostName" nillable="true" type="xs:string"></xs:element>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="iaasConfigs" nillable="true" type="ax221:IaasConfig"></xs:element>
+                    <xs:element minOccurs="0" name="lbConfig" nillable="true" type="ax221:LoadbalancerConfig"></xs:element>
+                    <xs:element minOccurs="0" name="multiTenant" type="xs:boolean"></xs:element>
+                    <xs:element minOccurs="0" name="persistence" nillable="true" type="ax221:Persistence"></xs:element>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="portMappings" nillable="true" type="ax221:PortMapping"></xs:element>
+                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"></xs:element>
+                    <xs:element minOccurs="0" name="provider" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="serviceGroup" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="version" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="AppType">
+            <xs:complexType name="IaasConfig">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="appSpecificMapping" type="xs:boolean"/>
-                    <xs:element minOccurs="0" name="name" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="className" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="credential" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="identity" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="imageId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="maxInstanceLimit" type="xs:int"></xs:element>
+                    <xs:element minOccurs="0" name="name" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="networkInterfaces" nillable="true" type="ax221:NetworkInterfaces"></xs:element>
+                    <xs:element minOccurs="0" name="payload" nillable="true" type="xs:base64Binary"></xs:element>
+                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"></xs:element>
+                    <xs:element minOccurs="0" name="provider" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="LoadbalancerConfig">
+            <xs:complexType name="NetworkInterfaces">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"/>
-                    <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"/>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="networkInterfaces" nillable="true" type="ax221:NetworkInterface"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="Persistence">
+            <xs:complexType name="NetworkInterface">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="persistanceRequired" type="xs:boolean"/>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="volumes" nillable="true" type="ax221:Volume"/>
+                    <xs:element minOccurs="0" name="fixedIp" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="networkUuid" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="portUuid" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="Volume">
+            <xs:complexType name="LoadbalancerConfig">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="device" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="iaasType" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="id" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="mappingPath" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="removeOntermination" type="xs:boolean"/>
-                    <xs:element minOccurs="0" name="size" type="xs:int"/>
+                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"></xs:element>
+                    <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="PortMapping">
+            <xs:complexType name="Persistence">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="port" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="protocol" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="proxyPort" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="persistanceRequired" type="xs:boolean"></xs:element>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="volumes" nillable="true" type="ax221:Volume"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="CartridgeConfig">
+            <xs:complexType name="Volume">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="baseDir" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="defaultAutoscalingPolicy" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="defaultDeploymentPolicy" nillable="true" type="xs:string"/>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="deploymentDirs" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="description" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="displayName" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="hostName" nillable="true" type="xs:string"/>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="iaasConfigs" nillable="true" type="ax221:IaasConfig"/>
-                    <xs:element minOccurs="0" name="lbConfig" nillable="true" type="ax221:LoadbalancerConfig"/>
-                    <xs:element minOccurs="0" name="multiTenant" type="xs:boolean"/>
-                    <xs:element minOccurs="0" name="persistence" nillable="true" type="ax221:Persistence"/>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="portMappings" nillable="true" type="ax221:PortMapping"/>
-                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"/>
-                    <xs:element minOccurs="0" name="provider" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="serviceGroup" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="version" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="device" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="iaasType" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="id" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="mappingPath" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="removeOntermination" type="xs:boolean"></xs:element>
+                    <xs:element minOccurs="0" name="size" type="xs:int"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="IaasConfig">
+            <xs:complexType name="PortMapping">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="className" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="credential" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="identity" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="imageId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="maxInstanceLimit" type="xs:int"/>
-                    <xs:element minOccurs="0" name="name" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="networkInterfaces" nillable="true" type="ax221:NetworkInterfaces"/>
-                    <xs:element minOccurs="0" name="payload" nillable="true" type="xs:base64Binary"/>
-                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"/>
-                    <xs:element minOccurs="0" name="provider" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="port" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="protocol" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="proxyPort" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="NetworkInterfaces">
+            <xs:complexType name="ClusterContext">
                 <xs:sequence>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="networkInterfaces" nillable="true" type="ax221:NetworkInterface"/>
+                    <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="hostName" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="lbCluster" type="xs:boolean"></xs:element>
+                    <xs:element minOccurs="0" name="payload" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="timeoutInMillis" type="xs:long"></xs:element>
+                    <xs:element minOccurs="0" name="volumeRequired" type="xs:boolean"></xs:element>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="volumes" nillable="true" type="ax221:Volume"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="NetworkInterface">
+            <xs:complexType name="CartridgeInfo">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="fixedIp" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="networkUuid" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="portUuid" nillable="true" type="xs:string"/>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="appTypes" nillable="true" type="ax221:AppType"></xs:element>
+                    <xs:element minOccurs="0" name="baseDir" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="defaultAutoscalingPolicy" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="defaultDeploymentPolicy" nillable="true" type="xs:string"></xs:element>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="deploymentDirs" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="description" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="displayName" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="hostName" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="lbConfig" nillable="true" type="ax221:LoadbalancerConfig"></xs:element>
+                    <xs:element minOccurs="0" name="multiTenant" type="xs:boolean"></xs:element>
+                    <xs:element minOccurs="0" name="persistence" nillable="true" type="ax221:Persistence"></xs:element>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="portMappings" nillable="true" type="ax221:PortMapping"></xs:element>
+                    <xs:element maxOccurs="unbounded" minOccurs="0" name="properties" nillable="true" type="ax221:Property"></xs:element>
+                    <xs:element minOccurs="0" name="provider" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="serviceGroup" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="type" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="version" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="MemberContext">
+            <xs:complexType name="AppType">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="allocatedIpAddress" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="initTime" type="xs:long"/>
-                    <xs:element minOccurs="0" name="instanceId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="lbClusterId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="memberId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="networkPartitionId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="nodeId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="partition" nillable="true" type="ax220:Partition"/>
-                    <xs:element minOccurs="0" name="privateIpAddress" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="publicIpAddress" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="appSpecificMapping" type="xs:boolean"></xs:element>
+                    <xs:element minOccurs="0" name="name" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
-            <xs:complexType name="ClusterContext">
+            <xs:complexType name="MemberContext">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="hostName" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="lbCluster" type="xs:boolean"/>
-                    <xs:element minOccurs="0" name="payload" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="timeoutInMillis" type="xs:long"/>
-                    <xs:element minOccurs="0" name="volumeRequired" type="xs:boolean"/>
-                    <xs:element maxOccurs="unbounded" minOccurs="0" name="volumes" nillable="true" type="ax221:Volume"/>
+                    <xs:element minOccurs="0" name="allocatedIpAddress" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="initTime" type="xs:long"></xs:element>
+                    <xs:element minOccurs="0" name="instanceId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="lbClusterId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="memberId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="networkPartitionId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="nodeId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="partition" nillable="true" type="ax220:Partition"></xs:element>
+                    <xs:element minOccurs="0" name="privateIpAddress" nillable="true" type="xs:string"></xs:element>
+					<xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"></xs:element>
+                    <xs:element minOccurs="0" name="publicIpAddress" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
             <xs:complexType name="Registrant">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="autoScalerPolicyName" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="deploymentPolicyName" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="hostName" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="payload" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"/>
-                    <xs:element minOccurs="0" name="tenantRange" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="autoScalerPolicyName" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="cartridgeType" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="clusterId" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="deploymentPolicyName" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="hostName" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="payload" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"></xs:element>
+                    <xs:element minOccurs="0" name="tenantRange" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
         </xs:schema>
         <xs:schema xmlns:ax222="http://pojo.controller.cloud.stratos.apache.org/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://partition.deployment.controller.cloud.stratos.apache.org/xsd">
-            <xs:import namespace="http://pojo.controller.cloud.stratos.apache.org/xsd"/>
+            <xs:import namespace="http://pojo.controller.cloud.stratos.apache.org/xsd"></xs:import>
             <xs:complexType name="Partition">
                 <xs:sequence>
-                    <xs:element minOccurs="0" name="id" nillable="true" type="xs:string"/>
-                    <xs:element minOccurs="0" name="partitionMax" type="xs:int"/>
-                    <xs:element minOccurs="0" name="partitionMin" type="xs:int"/>
-                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"/>
-                    <xs:element minOccurs="0" name="provider" nillable="true" type="xs:string"/>
+                    <xs:element minOccurs="0" name="id" nillable="true" type="xs:string"></xs:element>
+                    <xs:element minOccurs="0" name="partitionMax" type="xs:int"></xs:element>
+                    <xs:element minOccurs="0" name="partitionMin" type="xs:int"></xs:element>
+                    <xs:element minOccurs="0" name="properties" nillable="true" type="ax221:Properties"></xs:element>
+                    <xs:element minOccurs="0" name="provider" nillable="true" type="xs:string"></xs:element>
                 </xs:sequence>
             </xs:complexType>
         </xs:schema>
     </wsdl:types>
     <wsdl:message name="validatePartitionRequest">
-        <wsdl:part name="parameters" element="ns:validatePartition"/>
+        <wsdl:part name="parameters" element="ns:validatePartition"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="validatePartitionResponse">
-        <wsdl:part name="parameters" element="ns:validatePartitionResponse"/>
+        <wsdl:part name="parameters" element="ns:validatePartitionResponse"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="CloudControllerServiceInvalidPartitionException">
-        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidPartitionException"/>
+        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidPartitionException"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="validateDeploymentPolicyRequest">
-        <wsdl:part name="parameters" element="ns:validateDeploymentPolicy"/>
+        <wsdl:part name="parameters" element="ns:validateDeploymentPolicy"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="validateDeploymentPolicyResponse">
-        <wsdl:part name="parameters" element="ns:validateDeploymentPolicyResponse"/>
+        <wsdl:part name="parameters" element="ns:validateDeploymentPolicyResponse"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="CloudControllerServiceInvalidCartridgeTypeException">
-        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidCartridgeTypeException"/>
+        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidCartridgeTypeException"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="terminateInstanceRequest">
-        <wsdl:part name="parameters" element="ns:terminateInstance"/>
+        <wsdl:part name="parameters" element="ns:terminateInstance"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="CloudControllerServiceInvalidMemberException">
-        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidMemberException"/>
+        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidMemberException"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="registerServiceRequest">
-        <wsdl:part name="parameters" element="ns:registerService"/>
+        <wsdl:part name="parameters" element="ns:registerService"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="registerServiceResponse">
-        <wsdl:part name="parameters" element="ns:registerServiceResponse"/>
+        <wsdl:part name="parameters" element="ns:registerServiceResponse"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="CloudControllerServiceUnregisteredCartridgeException">
-        <wsdl:part name="parameters" element="ns:CloudControllerServiceUnregisteredCartridgeException"/>
+        <wsdl:part name="parameters" element="ns:CloudControllerServiceUnregisteredCartridgeException"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="deployCartridgeDefinitionRequest">
-        <wsdl:part name="parameters" element="ns:deployCartridgeDefinition"/>
+        <wsdl:part name="parameters" element="ns:deployCartridgeDefinition"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="CloudControllerServiceInvalidCartridgeDefinitionException">
-        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidCartridgeDefinitionException"/>
+        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidCartridgeDefinitionException"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="CloudControllerServiceInvalidIaasProviderException">
-        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidIaasProviderException"/>
+        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidIaasProviderException"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="getCartridgeInfoRequest">
-        <wsdl:part name="parameters" element="ns:getCartridgeInfo"/>
+        <wsdl:part name="parameters" element="ns:getCartridgeInfo"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="getCartridgeInfoResponse">
-        <wsdl:part name="parameters" element="ns:getCartridgeInfoResponse"/>
+        <wsdl:part name="parameters" element="ns:getCartridgeInfoResponse"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="unregisterServiceRequest">
-        <wsdl:part name="parameters" element="ns:unregisterService"/>
+        <wsdl:part name="parameters" element="ns:unregisterService"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="CloudControllerServiceUnregisteredClusterException">
-        <wsdl:part name="parameters" element="ns:CloudControllerServiceUnregisteredClusterException"/>
+        <wsdl:part name="parameters" element="ns:CloudControllerServiceUnregisteredClusterException"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="undeployCartridgeDefinitionRequest">
-        <wsdl:part name="parameters" element="ns:undeployCartridgeDefinition"/>
+        <wsdl:part name="parameters" element="ns:undeployCartridgeDefinition"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="terminateAllInstancesRequest">
-        <wsdl:part name="parameters" element="ns:terminateAllInstances"/>
+        <wsdl:part name="parameters" element="ns:terminateAllInstances"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="CloudControllerServiceInvalidClusterException">
-        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidClusterException"/>
+        <wsdl:part name="parameters" element="ns:CloudControllerServiceInvalidClusterException"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="getRegisteredCartridgesRequest">
-        <wsdl:part name="parameters" element="ns:getRegisteredCartridges"/>
+        <wsdl:part name="parameters" element="ns:getRegisteredCartridges"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="getRegisteredCartridgesResponse">
-        <wsdl:part name="parameters" element="ns:getRegisteredCartridgesResponse"/>
+        <wsdl:part name="parameters" element="ns:getRegisteredCartridgesResponse"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="startInstanceRequest">
-        <wsdl:part name="parameters" element="ns:startInstance"/>
+        <wsdl:part name="parameters" element="ns:startInstance"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="startInstanceResponse">
-        <wsdl:part name="parameters" element="ns:startInstanceResponse"/>
+        <wsdl:part name="parameters" element="ns:startInstanceResponse"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="getClusterContextRequest">
-        <wsdl:part name="parameters" element="ns:getClusterContext"/>
+        <wsdl:part name="parameters" element="ns:getClusterContext"></wsdl:part>
     </wsdl:message>
     <wsdl:message name="getClusterContextResponse">
-        <wsdl:part name="parameters" element="ns:getClusterContextResponse"/>
+        <wsdl:part name="parameters" element="ns:getClusterContextResponse"></wsdl:part>
     </wsdl:message>
     <wsdl:portType name="CloudControllerServicePortType">
         <wsdl:operation name="validatePartition">
-            <wsdl:input message="ns:validatePartitionRequest" wsaw:Action="urn:validatePartition"/>
-            <wsdl:output message="ns:validatePartitionResponse" wsaw:Action="urn:validatePartitionResponse"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidPartitionException" name="CloudControllerServiceInvalidPartitionException" wsaw:Action="urn:validatePartitionCloudControllerServiceInvalidPartitionException"/>
+            <wsdl:input message="ns:validatePartitionRequest" wsaw:Action="urn:validatePartition"></wsdl:input>
+            <wsdl:output message="ns:validatePartitionResponse" wsaw:Action="urn:validatePartitionResponse"></wsdl:output>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidPartitionException" name="CloudControllerServiceInvalidPartitionException" wsaw:Action="urn:validatePartitionCloudControllerServiceInvalidPartitionException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="validateDeploymentPolicy">
-            <wsdl:input message="ns:validateDeploymentPolicyRequest" wsaw:Action="urn:validateDeploymentPolicy"/>
-            <wsdl:output message="ns:validateDeploymentPolicyResponse" wsaw:Action="urn:validateDeploymentPolicyResponse"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidPartitionException" name="CloudControllerServiceInvalidPartitionException" wsaw:Action="urn:validateDeploymentPolicyCloudControllerServiceInvalidPartitionException"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidCartridgeTypeException" name="CloudControllerServiceInvalidCartridgeTypeException" wsaw:Action="urn:validateDeploymentPolicyCloudControllerServiceInvalidCartridgeTypeException"/>
+            <wsdl:input message="ns:validateDeploymentPolicyRequest" wsaw:Action="urn:validateDeploymentPolicy"></wsdl:input>
+            <wsdl:output message="ns:validateDeploymentPolicyResponse" wsaw:Action="urn:validateDeploymentPolicyResponse"></wsdl:output>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidPartitionException" name="CloudControllerServiceInvalidPartitionException" wsaw:Action="urn:validateDeploymentPolicyCloudControllerServiceInvalidPartitionException"></wsdl:fault>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidCartridgeTypeException" name="CloudControllerServiceInvalidCartridgeTypeException" wsaw:Action="urn:validateDeploymentPolicyCloudControllerServiceInvalidCartridgeTypeException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="terminateInstance">
-            <wsdl:input message="ns:terminateInstanceRequest" wsaw:Action="urn:terminateInstance"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidMemberException" name="CloudControllerServiceInvalidMemberException" wsaw:Action="urn:terminateInstanceCloudControllerServiceInvalidMemberException"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidCartridgeTypeException" name="CloudControllerServiceInvalidCartridgeTypeException" wsaw:Action="urn:terminateInstanceCloudControllerServiceInvalidCartridgeTypeException"/>
+            <wsdl:input message="ns:terminateInstanceRequest" wsaw:Action="urn:terminateInstance"></wsdl:input>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidMemberException" name="CloudControllerServiceInvalidMemberException" wsaw:Action="urn:terminateInstanceCloudControllerServiceInvalidMemberException"></wsdl:fault>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidCartridgeTypeException" name="CloudControllerServiceInvalidCartridgeTypeException" wsaw:Action="urn:terminateInstanceCloudControllerServiceInvalidCartridgeTypeException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="registerService">
-            <wsdl:input message="ns:registerServiceRequest" wsaw:Action="urn:registerService"/>
-            <wsdl:output message="ns:registerServiceResponse" wsaw:Action="urn:registerServiceResponse"/>
-            <wsdl:fault message="ns:CloudControllerServiceUnregisteredCartridgeException" name="CloudControllerServiceUnregisteredCartridgeException" wsaw:Action="urn:registerServiceCloudControllerServiceUnregisteredCartridgeException"/>
+            <wsdl:input message="ns:registerServiceRequest" wsaw:Action="urn:registerService"></wsdl:input>
+            <wsdl:output message="ns:registerServiceResponse" wsaw:Action="urn:registerServiceResponse"></wsdl:output>
+            <wsdl:fault message="ns:CloudControllerServiceUnregisteredCartridgeException" name="CloudControllerServiceUnregisteredCartridgeException" wsaw:Action="urn:registerServiceCloudControllerServiceUnregisteredCartridgeException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="deployCartridgeDefinition">
-            <wsdl:input message="ns:deployCartridgeDefinitionRequest" wsaw:Action="urn:deployCartridgeDefinition"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidCartridgeDefinitionException" name="CloudControllerServiceInvalidCartridgeDefinitionException" wsaw:Action="urn:deployCartridgeDefinitionCloudControllerServiceInvalidCartridgeDefinitionException"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidIaasProviderException" name="CloudControllerServiceInvalidIaasProviderException" wsaw:Action="urn:deployCartridgeDefinitionCloudControllerServiceInvalidIaasProviderException"/>
+            <wsdl:input message="ns:deployCartridgeDefinitionRequest" wsaw:Action="urn:deployCartridgeDefinition"></wsdl:input>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidCartridgeDefinitionException" name="CloudControllerServiceInvalidCartridgeDefinitionException" wsaw:Action="urn:deployCartridgeDefinitionCloudControllerServiceInvalidCartridgeDefinitionException"></wsdl:fault>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidIaasProviderException" name="CloudControllerServiceInvalidIaasProviderException" wsaw:Action="urn:deployCartridgeDefinitionCloudControllerServiceInvalidIaasProviderException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getCartridgeInfo">
-            <wsdl:input message="ns:getCartridgeInfoRequest" wsaw:Action="urn:getCartridgeInfo"/>
-            <wsdl:output message="ns:getCartridgeInfoResponse" wsaw:Action="urn:getCartridgeInfoResponse"/>
-            <wsdl:fault message="ns:CloudControllerServiceUnregisteredCartridgeException" name="CloudControllerServiceUnregisteredCartridgeException" wsaw:Action="urn:getCartridgeInfoCloudControllerServiceUnregisteredCartridgeException"/>
+            <wsdl:input message="ns:getCartridgeInfoRequest" wsaw:Action="urn:getCartridgeInfo"></wsdl:input>
+            <wsdl:output message="ns:getCartridgeInfoResponse" wsaw:Action="urn:getCartridgeInfoResponse"></wsdl:output>
+            <wsdl:fault message="ns:CloudControllerServiceUnregisteredCartridgeException" name="CloudControllerServiceUnregisteredCartridgeException" wsaw:Action="urn:getCartridgeInfoCloudControllerServiceUnregisteredCartridgeException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="unregisterService">
-            <wsdl:input message="ns:unregisterServiceRequest" wsaw:Action="urn:unregisterService"/>
-            <wsdl:fault message="ns:CloudControllerServiceUnregisteredClusterException" name="CloudControllerServiceUnregisteredClusterException" wsaw:Action="urn:unregisterServiceCloudControllerServiceUnregisteredClusterException"/>
+            <wsdl:input message="ns:unregisterServiceRequest" wsaw:Action="urn:unregisterService"></wsdl:input>
+            <wsdl:fault message="ns:CloudControllerServiceUnregisteredClusterException" name="CloudControllerServiceUnregisteredClusterException" wsaw:Action="urn:unregisterServiceCloudControllerServiceUnregisteredClusterException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="undeployCartridgeDefinition">
-            <wsdl:input message="ns:undeployCartridgeDefinitionRequest" wsaw:Action="urn:undeployCartridgeDefinition"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidCartridgeTypeException" name="CloudControllerServiceInvalidCartridgeTypeException" wsaw:Action="urn:undeployCartridgeDefinitionCloudControllerServiceInvalidCartridgeTypeException"/>
+            <wsdl:input message="ns:undeployCartridgeDefinitionRequest" wsaw:Action="urn:undeployCartridgeDefinition"></wsdl:input>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidCartridgeTypeException" name="CloudControllerServiceInvalidCartridgeTypeException" wsaw:Action="urn:undeployCartridgeDefinitionCloudControllerServiceInvalidCartridgeTypeException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="terminateAllInstances">
-            <wsdl:input message="ns:terminateAllInstancesRequest" wsaw:Action="urn:terminateAllInstances"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidClusterException" name="CloudControllerServiceInvalidClusterException" wsaw:Action="urn:terminateAllInstancesCloudControllerServiceInvalidClusterException"/>
+            <wsdl:input message="ns:terminateAllInstancesRequest" wsaw:Action="urn:terminateAllInstances"></wsdl:input>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidClusterException" name="CloudControllerServiceInvalidClusterException" wsaw:Action="urn:terminateAllInstancesCloudControllerServiceInvalidClusterException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getRegisteredCartridges">
-            <wsdl:input message="ns:getRegisteredCartridgesRequest" wsaw:Action="urn:getRegisteredCartridges"/>
-            <wsdl:output message="ns:getRegisteredCartridgesResponse" wsaw:Action="urn:getRegisteredCartridgesResponse"/>
+            <wsdl:input message="ns:getRegisteredCartridgesRequest" wsaw:Action="urn:getRegisteredCartridges"></wsdl:input>
+            <wsdl:output message="ns:getRegisteredCartridgesResponse" wsaw:Action="urn:getRegisteredCartridgesResponse"></wsdl:output>
         </wsdl:operation>
         <wsdl:operation name="startInstance">
-            <wsdl:input message="ns:startInstanceRequest" wsaw:Action="urn:startInstance"/>
-            <wsdl:output message="ns:startInstanceResponse" wsaw:Action="urn:startInstanceResponse"/>
-            <wsdl:fault message="ns:CloudControllerServiceUnregisteredCartridgeException" name="CloudControllerServiceUnregisteredCartridgeException" wsaw:Action="urn:startInstanceCloudControllerServiceUnregisteredCartridgeException"/>
-            <wsdl:fault message="ns:CloudControllerServiceInvalidIaasProviderException" name="CloudControllerServiceInvalidIaasProviderException" wsaw:Action="urn:startInstanceCloudControllerServiceInvalidIaasProviderException"/>
+            <wsdl:input message="ns:startInstanceRequest" wsaw:Action="urn:startInstance"></wsdl:input>
+            <wsdl:output message="ns:startInstanceResponse" wsaw:Action="urn:startInstanceResponse"></wsdl:output>
+            <wsdl:fault message="ns:CloudControllerServiceUnregisteredCartridgeException" name="CloudControllerServiceUnregisteredCartridgeException" wsaw:Action="urn:startInstanceCloudControllerServiceUnregisteredCartridgeException"></wsdl:fault>
+            <wsdl:fault message="ns:CloudControllerServiceInvalidIaasProviderException" name="CloudControllerServiceInvalidIaasProviderException" wsaw:Action="urn:startInstanceCloudControllerServiceInvalidIaasProviderException"></wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getClusterContext">
-            <wsdl:input message="ns:getClusterContextRequest" wsaw:Action="urn:getClusterContext"/>
-            <wsdl:output message="ns:getClusterContextResponse" wsaw:Action="urn:getClusterContextResponse"/>
+            <wsdl:input message="ns:getClusterContextRequest" wsaw:Action="urn:getClusterContext"></wsdl:input>
+            <wsdl:output message="ns:getClusterContextResponse" wsaw:Action="urn:getClusterContextResponse"></wsdl:output>
         </wsdl:operation>
     </wsdl:portType>
     <wsdl:binding name="CloudControllerServiceSoap11Binding" type="ns:CloudControllerServicePortType">
-        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
+        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>
         <wsdl:operation name="validatePartition">
-            <soap:operation soapAction="urn:validatePartition" style="document"/>
+            <soap:operation soapAction="urn:validatePartition" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:output>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceInvalidPartitionException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidPartitionException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidPartitionException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="validateDeploymentPolicy">
-            <soap:operation soapAction="urn:validateDeploymentPolicy" style="document"/>
+            <soap:operation soapAction="urn:validateDeploymentPolicy" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:output>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceInvalidPartitionException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidPartitionException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidPartitionException"></soap:fault>
             </wsdl:fault>
             <wsdl:fault name="CloudControllerServiceInvalidCartridgeTypeException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="terminateInstance">
-            <soap:operation soapAction="urn:terminateInstance" style="document"/>
+            <soap:operation soapAction="urn:terminateInstance" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceInvalidMemberException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidMemberException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidMemberException"></soap:fault>
             </wsdl:fault>
             <wsdl:fault name="CloudControllerServiceInvalidCartridgeTypeException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="registerService">
-            <soap:operation soapAction="urn:registerService" style="document"/>
+            <soap:operation soapAction="urn:registerService" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:output>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceUnregisteredCartridgeException">
-                <soap:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"/>
+                <soap:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="deployCartridgeDefinition">
-            <soap:operation soapAction="urn:deployCartridgeDefinition" style="document"/>
+            <soap:operation soapAction="urn:deployCartridgeDefinition" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceInvalidCartridgeDefinitionException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidCartridgeDefinitionException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidCartridgeDefinitionException"></soap:fault>
             </wsdl:fault>
             <wsdl:fault name="CloudControllerServiceInvalidIaasProviderException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidIaasProviderException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidIaasProviderException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getCartridgeInfo">
-            <soap:operation soapAction="urn:getCartridgeInfo" style="document"/>
+            <soap:operation soapAction="urn:getCartridgeInfo" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:output>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceUnregisteredCartridgeException">
-                <soap:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"/>
+                <soap:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="unregisterService">
-            <soap:operation soapAction="urn:unregisterService" style="document"/>
+            <soap:operation soapAction="urn:unregisterService" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceUnregisteredClusterException">
-                <soap:fault use="literal" name="CloudControllerServiceUnregisteredClusterException"/>
+                <soap:fault use="literal" name="CloudControllerServiceUnregisteredClusterException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="undeployCartridgeDefinition">
-            <soap:operation soapAction="urn:undeployCartridgeDefinition" style="document"/>
+            <soap:operation soapAction="urn:undeployCartridgeDefinition" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceInvalidCartridgeTypeException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="terminateAllInstances">
-            <soap:operation soapAction="urn:terminateAllInstances" style="document"/>
+            <soap:operation soapAction="urn:terminateAllInstances" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceInvalidClusterException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidClusterException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidClusterException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getRegisteredCartridges">
-            <soap:operation soapAction="urn:getRegisteredCartridges" style="document"/>
+            <soap:operation soapAction="urn:getRegisteredCartridges" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:output>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:output>
         </wsdl:operation>
         <wsdl:operation name="startInstance">
-            <soap:operation soapAction="urn:startInstance" style="document"/>
+            <soap:operation soapAction="urn:startInstance" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:output>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceInvalidIaasProviderException">
-                <soap:fault use="literal" name="CloudControllerServiceInvalidIaasProviderException"/>
+                <soap:fault use="literal" name="CloudControllerServiceInvalidIaasProviderException"></soap:fault>
             </wsdl:fault>
             <wsdl:fault name="CloudControllerServiceUnregisteredCartridgeException">
-                <soap:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"/>
+                <soap:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"></soap:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getClusterContext">
-            <soap:operation soapAction="urn:getClusterContext" style="document"/>
+            <soap:operation soapAction="urn:getClusterContext" style="document"></soap:operation>
             <wsdl:input>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:input>
             <wsdl:output>
-                <soap:body use="literal"/>
+                <soap:body use="literal"></soap:body>
             </wsdl:output>
         </wsdl:operation>
     </wsdl:binding>
     <wsdl:binding name="CloudControllerServiceSoap12Binding" type="ns:CloudControllerServicePortType">
-        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
+        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap12:binding>
         <wsdl:operation name="validatePartition">
-            <soap12:operation soapAction="urn:validatePartition" style="document"/>
+            <soap12:operation soapAction="urn:validatePartition" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:output>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceInvalidPartitionException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidPartitionException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidPartitionException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="validateDeploymentPolicy">
-            <soap12:operation soapAction="urn:validateDeploymentPolicy" style="document"/>
+            <soap12:operation soapAction="urn:validateDeploymentPolicy" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:output>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceInvalidPartitionException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidPartitionException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidPartitionException"></soap12:fault>
             </wsdl:fault>
             <wsdl:fault name="CloudControllerServiceInvalidCartridgeTypeException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="terminateInstance">
-            <soap12:operation soapAction="urn:terminateInstance" style="document"/>
+            <soap12:operation soapAction="urn:terminateInstance" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceInvalidMemberException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidMemberException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidMemberException"></soap12:fault>
             </wsdl:fault>
             <wsdl:fault name="CloudControllerServiceInvalidCartridgeTypeException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="registerService">
-            <soap12:operation soapAction="urn:registerService" style="document"/>
+            <soap12:operation soapAction="urn:registerService" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:output>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceUnregisteredCartridgeException">
-                <soap12:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="deployCartridgeDefinition">
-            <soap12:operation soapAction="urn:deployCartridgeDefinition" style="document"/>
+            <soap12:operation soapAction="urn:deployCartridgeDefinition" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceInvalidCartridgeDefinitionException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidCartridgeDefinitionException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidCartridgeDefinitionException"></soap12:fault>
             </wsdl:fault>
             <wsdl:fault name="CloudControllerServiceInvalidIaasProviderException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidIaasProviderException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidIaasProviderException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getCartridgeInfo">
-            <soap12:operation soapAction="urn:getCartridgeInfo" style="document"/>
+            <soap12:operation soapAction="urn:getCartridgeInfo" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:output>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceUnregisteredCartridgeException">
-                <soap12:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="unregisterService">
-            <soap12:operation soapAction="urn:unregisterService" style="document"/>
+            <soap12:operation soapAction="urn:unregisterService" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceUnregisteredClusterException">
-                <soap12:fault use="literal" name="CloudControllerServiceUnregisteredClusterException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceUnregisteredClusterException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="undeployCartridgeDefinition">
-            <soap12:operation soapAction="urn:undeployCartridgeDefinition" style="document"/>
+            <soap12:operation soapAction="urn:undeployCartridgeDefinition" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceInvalidCartridgeTypeException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidCartridgeTypeException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="terminateAllInstances">
-            <soap12:operation soapAction="urn:terminateAllInstances" style="document"/>
+            <soap12:operation soapAction="urn:terminateAllInstances" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:fault name="CloudControllerServiceInvalidClusterException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidClusterException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidClusterException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getRegisteredCartridges">
-            <soap12:operation soapAction="urn:getRegisteredCartridges" style="document"/>
+            <soap12:operation soapAction="urn:getRegisteredCartridges" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:output>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:output>
         </wsdl:operation>
         <wsdl:operation name="startInstance">
-            <soap12:operation soapAction="urn:startInstance" style="document"/>
+            <soap12:operation soapAction="urn:startInstance" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:output>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:output>
             <wsdl:fault name="CloudControllerServiceInvalidIaasProviderException">
-                <soap12:fault use="literal" name="CloudControllerServiceInvalidIaasProviderException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceInvalidIaasProviderException"></soap12:fault>
             </wsdl:fault>
             <wsdl:fault name="CloudControllerServiceUnregisteredCartridgeException">
-                <soap12:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"/>
+                <soap12:fault use="literal" name="CloudControllerServiceUnregisteredCartridgeException"></soap12:fault>
             </wsdl:fault>
         </wsdl:operation>
         <wsdl:operation name="getClusterContext">
-            <soap12:operation soapAction="urn:getClusterContext" style="document"/>
+            <soap12:operation soapAction="urn:getClusterContext" style="document"></soap12:operation>
             <wsdl:input>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:input>
             <wsdl:output>
-                <soap12:body use="literal"/>
+                <soap12:body use="literal"></soap12:body>
             </wsdl:output>
         </wsdl:operation>
     </wsdl:binding>
     <wsdl:binding name="CloudControllerServiceHttpBinding" type="ns:CloudControllerServicePortType">
-        <http:binding verb="POST"/>
+        <http:binding verb="POST"></http:binding>
         <wsdl:operation name="validatePartition">
-            <http:operation location="validatePartition"/>
+            <http:operation location="validatePartition"></http:operation>
             <wsdl:input>
-                <mime:content type="text/xml" part="parameters"/>
+                <mime:content type="text/xml" part="parameters"></mime:content>
             </wsdl:input>
             <wsdl:output>
-                <mime:content type="text/xml" part="parameters"/>
+                <mime:content type="text/xml" part="parameters"></mime:content>
             </wsdl:output>
         </wsdl:operation>
         <wsdl:operation name="validateDeploymentPolicy">
-            <http:operation location="validateDeploymentPolicy"/>
+            <http:operation location="validateDeploymentPolicy"></http:operation>
             <wsdl:input>
-                <mime:content type="text/xml" part="parameters"/>
+                <mime:content type="text/xml" part="parameters"></mime:content>
             </wsdl:input>
             <wsdl:output>
-

<TRUNCATED>

[12/14] git commit: Merge branch '4.0.0' of https://git-wip-us.apache.org/repos/asf/stratos into 4.0.0

Posted by ma...@apache.org.
Merge branch '4.0.0' of https://git-wip-us.apache.org/repos/asf/stratos into 4.0.0


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

Branch: refs/heads/4.0.0
Commit: 6b6e509f0743a2869f26bc5f3b49f53c05c28979
Parents: 47f9f25 6a45473
Author: Manula Thantriwatte <ma...@apache.org>
Authored: Thu Jul 3 08:40:33 2014 +0000
Committer: Manula Thantriwatte <ma...@apache.org>
Committed: Thu Jul 3 08:40:33 2014 +0000

----------------------------------------------------------------------
 .../stratos/modules/distribution/src/main/conf/log4j.properties  | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------



[03/14] Clustering changes for stratos

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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/7b35e29e/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/7b35e29e/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..79d1e12
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainAddedMessageProcessor.java
@@ -0,0 +1,95 @@
+/*
+ * 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));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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..ea413cd
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/SubscriptionDomainRemovedMessageProcessor.java
@@ -0,0 +1,94 @@
+/*
+ * 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/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantMessageProcessorChain.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantMessageProcessorChain.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantMessageProcessorChain.java
index d4c008e..b5edfc1 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantMessageProcessorChain.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/tenant/TenantMessageProcessorChain.java
@@ -37,6 +37,8 @@ public class TenantMessageProcessorChain extends MessageProcessorChain {
     private TenantRemovedMessageProcessor tenantRemovedMessageProcessor;
     private TenantSubscribedMessageProcessor tenantSubscribedMessageProcessor;
     private TenantUnSubscribedMessageProcessor tenantUnSubscribedMessageProcessor;
+    private SubscriptionDomainAddedMessageProcessor subscriptionDomainAddedMessageProcessor;
+    private SubscriptionDomainRemovedMessageProcessor subscriptionDomainRemovedMessageProcessor;
 
     public void initialize() {
         // Add tenant event processors
@@ -58,6 +60,12 @@ public class TenantMessageProcessorChain extends MessageProcessorChain {
         tenantUnSubscribedMessageProcessor = new TenantUnSubscribedMessageProcessor();
         add(tenantUnSubscribedMessageProcessor);
 
+        subscriptionDomainAddedMessageProcessor = new SubscriptionDomainAddedMessageProcessor();
+        add(subscriptionDomainAddedMessageProcessor);
+
+        subscriptionDomainRemovedMessageProcessor = new SubscriptionDomainRemovedMessageProcessor();
+        add(subscriptionDomainRemovedMessageProcessor);
+
         if (log.isDebugEnabled()) {
             log.debug("Tenant message processor chain initialized");
         }
@@ -76,6 +84,10 @@ public class TenantMessageProcessorChain extends MessageProcessorChain {
             tenantSubscribedMessageProcessor.addEventListener(eventListener);
         } else if (eventListener instanceof TenantUnSubscribedEventListener) {
             tenantUnSubscribedMessageProcessor.addEventListener(eventListener);
+        } else if (eventListener instanceof SubscriptionDomainsAddedEventListener) {
+            subscriptionDomainAddedMessageProcessor.addEventListener(eventListener);
+        } else if (eventListener instanceof SubscriptionDomainsRemovedEventListener) {
+            subscriptionDomainRemovedMessageProcessor.addEventListener(eventListener);
         }
         else {
             throw new RuntimeException("Unknown event listener");

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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/7b35e29e/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/7b35e29e/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/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/InstanceSpawnedMessageProcessor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/InstanceSpawnedMessageProcessor.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/InstanceSpawnedMessageProcessor.java
index 3bb0532..8e4e1b1 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/InstanceSpawnedMessageProcessor.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/InstanceSpawnedMessageProcessor.java
@@ -114,6 +114,7 @@ public class InstanceSpawnedMessageProcessor extends MessageProcessor {
             	member.setMemberPublicIp(event.getMemberPublicIp());
             	member.setMemberIp(event.getMemberIp());
             	member.setLbClusterId(event.getLbClusterId());
+                member.setProperties(event.getProperties());
             	cluster.addMember(member);
             	
             	if (log.isInfoEnabled()) {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/TopologyMessageProcessorChain.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/TopologyMessageProcessorChain.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/TopologyMessageProcessorChain.java
index 7415c1f..eac7358 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/TopologyMessageProcessorChain.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/processor/topology/TopologyMessageProcessorChain.java
@@ -35,6 +35,7 @@ public class TopologyMessageProcessorChain extends MessageProcessorChain {
     private ServiceCreatedMessageProcessor serviceCreatedMessageProcessor;
     private ServiceRemovedMessageProcessor serviceRemovedMessageProcessor;
     private ClusterCreatedMessageProcessor clusterCreatedMessageProcessor;
+    private ClusterMaintenanceModeMessageProcessor clusterMaintenanceModeMessageProcessor;
     private ClusterRemovedMessageProcessor clusterRemovedMessageProcessor;
     private InstanceSpawnedMessageProcessor instanceSpawnedMessageProcessor;
     private MemberStartedMessageProcessor memberStartedMessageProcessor;
@@ -58,6 +59,9 @@ public class TopologyMessageProcessorChain extends MessageProcessorChain {
         clusterCreatedMessageProcessor = new ClusterCreatedMessageProcessor();
         add(clusterCreatedMessageProcessor);
 
+        clusterMaintenanceModeMessageProcessor = new ClusterMaintenanceModeMessageProcessor();
+        add(clusterMaintenanceModeMessageProcessor);
+
         clusterRemovedMessageProcessor = new ClusterRemovedMessageProcessor();
         add(clusterRemovedMessageProcessor);
 
@@ -93,6 +97,8 @@ public class TopologyMessageProcessorChain extends MessageProcessorChain {
         } else if (eventListener instanceof ClusterCreatedEventListener) {
             clusterCreatedMessageProcessor.addEventListener(eventListener);
             log.info("Messaging: added ClusterCreatedEventListener");
+        } else if (eventListener instanceof ClusterMaintenanceModeEventListener) {
+            clusterMaintenanceModeMessageProcessor.addEventListener(eventListener);
         } else if (eventListener instanceof ClusterRemovedEventListener) {
             clusterRemovedMessageProcessor.addEventListener(eventListener);
         } else if (eventListener instanceof InstanceSpawnedEventListener) {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/receiver/tenant/TenantManager.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/receiver/tenant/TenantManager.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/receiver/tenant/TenantManager.java
index 8133b90..4581889 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/receiver/tenant/TenantManager.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/message/receiver/tenant/TenantManager.java
@@ -22,6 +22,7 @@ package org.apache.stratos.messaging.message.receiver.tenant;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.messaging.domain.tenant.Tenant;
+import org.wso2.carbon.base.MultitenantConstants;
 
 import java.util.HashMap;
 import java.util.List;
@@ -78,6 +79,10 @@ public class TenantManager {
     private TenantManager() {
         this.tenantIdTenantMap = new HashMap<Integer, Tenant>();
         this.tenantDomainTenantMap = new HashMap<String, Tenant>();
+        Tenant superTenant = new Tenant(MultitenantConstants.SUPER_TENANT_ID, 
+        		MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
+        this.tenantIdTenantMap.put(MultitenantConstants.SUPER_TENANT_ID, superTenant);
+        this.tenantDomainTenantMap.put(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, superTenant);
     }
 
     public static TenantManager getInstance() {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/util/Constants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/util/Constants.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/util/Constants.java
index 8b3c814..a44489f 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/util/Constants.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/util/Constants.java
@@ -63,4 +63,6 @@ public class Constants {
     public static final String DEVICE_NAME = "volume.device.name";
 	public static final String GRACEFUL_SHUTDOWN_TIMEOUT = "graceful.shutdown.timeout";
 
+    public static final String IS_PRIMARY = "PRIMARY";
+
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.messaging/src/test/java/org/apache/stratos/messaging/test/TenantDomainTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/test/java/org/apache/stratos/messaging/test/TenantDomainTest.java b/components/org.apache.stratos.messaging/src/test/java/org/apache/stratos/messaging/test/TenantDomainTest.java
new file mode 100644
index 0000000..fae8b79
--- /dev/null
+++ b/components/org.apache.stratos.messaging/src/test/java/org/apache/stratos/messaging/test/TenantDomainTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.test;
+
+import junit.framework.Assert;
+import org.apache.stratos.messaging.domain.tenant.Subscription;
+import org.apache.stratos.messaging.domain.tenant.Tenant;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.HashSet;
+
+/**
+ * Tenant domain model test.
+ */
+@RunWith(JUnit4.class)
+public class TenantDomainTest {
+    @Test
+    public void testSubscriptionModel() {
+        Tenant tenant = new Tenant(1, "domain.org");
+        Subscription subscription = new Subscription("subscription1", new HashSet<String>());
+        tenant.addSubscription(subscription);
+        Assert.assertTrue("Subscription not added", tenant.isSubscribed("subscription1"));
+        tenant.removeSubscription("subscription1");
+        Assert.assertTrue("Subscription not removed", !tenant.isSubscribed("subscription1"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/CartridgeInfoBean.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/CartridgeInfoBean.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/CartridgeInfoBean.java
index e29d028..1bce7fb 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/CartridgeInfoBean.java
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/CartridgeInfoBean.java
@@ -19,6 +19,8 @@
 package org.apache.stratos.rest.endpoint.bean;
 
 import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.List;
 
 @XmlRootElement
 public class CartridgeInfoBean {
@@ -38,6 +40,11 @@ public class CartridgeInfoBean {
     private String size;
     private boolean removeOnTermination;
     private String serviceGroup;
+    private List<String> domains;
+
+    public CartridgeInfoBean() {
+        this.domains = new ArrayList<String>();
+    }
 
     public String getCartridgeType() {
         return cartridgeType;
@@ -159,4 +166,8 @@ public class CartridgeInfoBean {
 		this.serviceGroup = serviceGroup;
 	}
     
+    public List<String> getDomains() { return domains; }
+
+    public void setDomains(List<String> domains) { this.domains = domains; }
+
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/SubscriptionDomainRequest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/SubscriptionDomainRequest.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/SubscriptionDomainRequest.java
new file mode 100644
index 0000000..6e0d6ae
--- /dev/null
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/SubscriptionDomainRequest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.rest.endpoint.bean;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.stratos.rest.endpoint.bean.subscription.domain.SubscriptionDomainBean;
+
+/**
+ * Defines subscription domain post request.
+ */
+@XmlRootElement
+public class SubscriptionDomainRequest {
+    public List<SubscriptionDomainBean> domains;
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/subscription/domain/SubscriptionDomainBean.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/subscription/domain/SubscriptionDomainBean.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/subscription/domain/SubscriptionDomainBean.java
new file mode 100644
index 0000000..1b053bf
--- /dev/null
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/subscription/domain/SubscriptionDomainBean.java
@@ -0,0 +1,29 @@
+/*
+ * 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.rest.endpoint.bean.subscription.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "domains")
+public class SubscriptionDomainBean {
+    public String domainName;
+    public String applicationContext;
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/util/converter/PojoConverter.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/util/converter/PojoConverter.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/util/converter/PojoConverter.java
index 1208967..efb2960 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/util/converter/PojoConverter.java
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/bean/util/converter/PojoConverter.java
@@ -21,12 +21,14 @@ package org.apache.stratos.rest.endpoint.bean.util.converter;
 
 import org.apache.stratos.cloud.controller.stub.pojo.*;
 import org.apache.stratos.manager.deploy.service.Service;
+import org.apache.stratos.manager.subscription.SubscriptionDomain;
 import org.apache.stratos.messaging.domain.topology.Cluster;
 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.*;
 import org.apache.stratos.rest.endpoint.bean.autoscaler.policy.deployment.DeploymentPolicy;
 import org.apache.stratos.rest.endpoint.bean.cartridge.definition.*;
+import org.apache.stratos.rest.endpoint.bean.subscription.domain.SubscriptionDomainBean;
 import org.apache.stratos.rest.endpoint.bean.topology.Member;
 
 import java.util.ArrayList;
@@ -412,6 +414,34 @@ public class PojoConverter {
 
         return partitionBeans;
     }
+    
+	public static List<SubscriptionDomainBean> populateSubscriptionDomainPojos(List<SubscriptionDomain> subscriptionDomains) {
+
+		List<SubscriptionDomainBean> subscriptionDomainBeans = new ArrayList<SubscriptionDomainBean>();
+		
+		if (subscriptionDomains == null) {
+			return subscriptionDomainBeans;
+		}
+		
+		for (SubscriptionDomain subscriptionDomain : subscriptionDomains) {
+			subscriptionDomainBeans.add(populateSubscriptionDomainPojo(subscriptionDomain));
+		}
+
+		return subscriptionDomainBeans;
+	}
+    
+	public static SubscriptionDomainBean populateSubscriptionDomainPojo(SubscriptionDomain subscriptionDomain) {
+
+		SubscriptionDomainBean subscriptionDomainBean = new SubscriptionDomainBean();
+		
+		if (subscriptionDomain == null) {
+			return subscriptionDomainBean;
+		}
+		subscriptionDomainBean.domainName = subscriptionDomain.getDomainName();
+		subscriptionDomainBean.applicationContext = subscriptionDomain.getApplicationContext();
+
+		return subscriptionDomainBean;
+	}
 
     private static List<PropertyBean> getPropertyBeans (Properties properties) {
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CustomThrowableExceptionMapper.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CustomThrowableExceptionMapper.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CustomThrowableExceptionMapper.java
new file mode 100644
index 0000000..0f08728
--- /dev/null
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/CustomThrowableExceptionMapper.java
@@ -0,0 +1,39 @@
+package org.apache.stratos.rest.endpoint.handlers;/*
+ * 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.
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.rest.endpoint.Utils;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+public class CustomThrowableExceptionMapper implements ExceptionMapper<Throwable> {
+    private static Log log = LogFactory.getLog(CustomThrowableExceptionMapper.class);
+
+    public Response toResponse(Throwable throwable) {
+        if(log.isDebugEnabled()){
+            log.debug("Internal server error", throwable);
+        }
+
+        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(MediaType.APPLICATION_JSON).
+                entity(Utils.buildMessage(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Internal server error")).build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/GenericExceptionMapper.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/GenericExceptionMapper.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/GenericExceptionMapper.java
new file mode 100644
index 0000000..684bd2e
--- /dev/null
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/GenericExceptionMapper.java
@@ -0,0 +1,46 @@
+/*
+ * 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.rest.endpoint.handlers;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.rest.endpoint.Utils;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+/*This class maps any exception thrown by the server, which is not mapped by a specifi exception mapper
+* in to an appropriate format
+* */
+public class GenericExceptionMapper implements ExceptionMapper<WebApplicationException> {
+    private static Log log = LogFactory.getLog(GenericExceptionMapper.class);
+
+    public Response toResponse(WebApplicationException webApplicationException) {
+        if(log.isDebugEnabled()){
+            log.debug("Internal erver error", webApplicationException);
+        }
+        // if no specific error message specified, spitting out a generaic error message
+        String errorMessage = (webApplicationException.getMessage() != null)?
+                webApplicationException.getMessage():"Internal server error";
+        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(MediaType.APPLICATION_JSON).
+                entity(Utils.buildMessage(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), errorMessage)).build();
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java
index 7e66e6e..bfa676f 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/handlers/StratosAuthenticationHandler.java
@@ -18,6 +18,10 @@
  */
 package org.apache.stratos.rest.endpoint.handlers;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.cxf.configuration.security.AuthorizationPolicy;
@@ -63,32 +67,45 @@ public class StratosAuthenticationHandler extends AbstractAuthenticationAuthoriz
      * @return
      */
     public Response handle(Message message, ClassResourceInfo classResourceInfo) {
+    	// If Mutual SSL is enabled
+        HttpServletRequest request = (HttpServletRequest) message.get("HTTP.REQUEST");
+        Object certObject = request.getAttribute("javax.servlet.request.X509Certificate");
+        
         AuthorizationPolicy policy = (AuthorizationPolicy) message.get(AuthorizationPolicy.class);
         String username = policy.getUserName().trim();
         String password = policy.getPassword().trim();
 
         //sanity check
-        if ((username == null) || (password == null) || username.equals("")
-                || password.equals("")) {
-            log.error("username or password is seen as null/empty values.");
-            return Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate", "Basic").
-                    type(MediaType.APPLICATION_JSON).entity(Utils.buildMessage("Username/Password cannot be null")).build();
+        if ((username == null) || username.equals("")) {
+            log.error("username is seen as null/empty values.");
+            return Response.status(Response.Status.UNAUTHORIZED)
+                           .header("WWW-Authenticate", "Basic").type(MediaType.APPLICATION_JSON)
+                           .entity(Utils.buildMessage("Username cannot be null")).build();
+        } else if (certObject == null && ((password == null) || password.equals(""))) {
+            log.error("password is seen as null/empty values.");
+            return Response.status(Response.Status.UNAUTHORIZED)
+                           .header("WWW-Authenticate", "Basic").type(MediaType.APPLICATION_JSON)
+                           .entity(Utils.buildMessage("password cannot be null")).build();
         }
+        
         try {
             RealmService realmService = ServiceHolder.getRealmService();
             RegistryService registryService = ServiceHolder.getRegistryService();
             String tenantDomain = MultitenantUtils.getTenantDomain(username);
             int tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
-
-            UserRealm userRealm = AnonymousSessionUtil.getRealmByTenantDomain(registryService, realmService, tenantDomain);
-            if (userRealm == null) {
-                log .error("Invalid domain or unactivated tenant login");
-                // is this the correct HTTP code for this scenario ? (401)
-                return Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate", "Basic").
-                        type(MediaType.APPLICATION_JSON).entity(Utils.buildMessage("Tenant not found")).build();
+            
+            UserRealm userRealm = null;
+            if (certObject == null) {
+                userRealm = AnonymousSessionUtil.getRealmByTenantDomain(registryService, realmService, tenantDomain);
+                if (userRealm == null) {
+                    log .error("Invalid domain or unactivated tenant login");
+                    // is this the correct HTTP code for this scenario ? (401)
+                    return Response.status(Response.Status.UNAUTHORIZED).header("WWW-Authenticate", "Basic").
+                            type(MediaType.APPLICATION_JSON).entity(Utils.buildMessage("Tenant not found")).build();
+                }
             }
             username = MultitenantUtils.getTenantAwareUsername(username);
-            if (userRealm.getUserStoreManager().authenticate(username, password)) {  // if authenticated
+            if (certObject != null || userRealm.getUserStoreManager().authenticate(username, password)) {  // if authenticated
 
                 // setting the correct tenant info for downstream code..
                 PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/MockContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/MockContext.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/MockContext.java
index abd0a59..8ce6f68 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/MockContext.java
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/MockContext.java
@@ -21,21 +21,29 @@ package org.apache.stratos.rest.endpoint.mock;
 import org.apache.stratos.common.beans.TenantInfoBean;
 import org.apache.stratos.manager.dto.Cartridge;
 import org.apache.stratos.manager.dto.SubscriptionInfo;
+import org.apache.stratos.manager.subscription.SubscriptionDomain;
 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;
 import org.apache.stratos.rest.endpoint.bean.autoscaler.policy.deployment.DeploymentPolicy;
 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.subscription.domain.SubscriptionDomainBean;
 import org.apache.stratos.rest.endpoint.bean.topology.Cluster;
+import org.apache.stratos.rest.endpoint.bean.util.converter.PojoConverter;
 import org.apache.stratos.rest.endpoint.exception.RestAPIException;
 
 import java.util.*;
 
+import javax.ws.rs.core.Response.Status;
+
 public class MockContext {
     private static MockContext mockContext = new MockContext(); // singleton
+    private Map<String, List<SubscriptionDomain>> subscriptionAliasToDomainMap = new HashMap<String, List<SubscriptionDomain>>();
+    private Map<Integer, List<String>> tenantIdToAliasesMap = new HashMap<Integer, List<String>>();
     private List<CartridgeDefinitionBean> cartridgeDefinitionBeanList = new LinkedList<CartridgeDefinitionBean>();
     private Map<String,Cartridge> availableSingleTenantCartridges = new HashMap<String,Cartridge>();
     private Map<String,Cartridge> availableMultiTenantCartridges = new HashMap<String,Cartridge>();
@@ -383,4 +391,84 @@ public class MockContext {
         return deploymentPolicyMap.values().toArray(new DeploymentPolicy[0]);
     }
 
+	public StratosAdminResponse addSubscriptionDomains(int tenantId, String alias, SubscriptionDomainRequest request) {
+		// populate new alias
+		List<String> aliasList;
+		if(tenantIdToAliasesMap.containsKey(tenantId)) {
+			aliasList = tenantIdToAliasesMap.get(tenantId);
+		} else {
+			aliasList = new ArrayList<String>();
+		}
+		aliasList.add(alias);
+		tenantIdToAliasesMap.put(tenantId, aliasList);
+		
+		// populate domains
+		List<SubscriptionDomain> list;
+		if(subscriptionAliasToDomainMap.containsKey(alias)) {
+			list = subscriptionAliasToDomainMap.get(alias);
+		} else {
+			list = new ArrayList<SubscriptionDomain>();
+		}
+		for (org.apache.stratos.rest.endpoint.bean.subscription.domain.SubscriptionDomainBean bean : request.domains) {
+			
+			SubscriptionDomain subscriptionDomain = new SubscriptionDomain(bean.domainName, bean.applicationContext);
+			list.add(subscriptionDomain);
+		}
+		
+		subscriptionAliasToDomainMap.put(alias, list);
+		
+		StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
+        stratosAdminResponse.setMessage("Successfully added subscription domain/s.");
+        return stratosAdminResponse;
+	}
+
+	public List<SubscriptionDomainBean> getSubscriptionDomains(int tenantId, String alias) {
+		List<String> tenantAliases = tenantIdToAliasesMap.get(tenantId);
+		if(tenantAliases != null && tenantAliases.contains(alias)) {
+			
+			return PojoConverter.populateSubscriptionDomainPojos(subscriptionAliasToDomainMap.get(alias));
+		}
+        return new ArrayList<SubscriptionDomainBean>();
+	}
+
+	public SubscriptionDomainBean getSubscriptionDomain(int tenantId, String cartridgeType,
+			String subscriptionAlias, String domainName) throws RestAPIException {
+		List<String> tenantAliases = tenantIdToAliasesMap.get(tenantId);
+		if(tenantAliases != null && tenantAliases.contains(subscriptionAlias)) {
+			for (SubscriptionDomain subscriptionDomain : subscriptionAliasToDomainMap.get(subscriptionAlias)) {
+				if(subscriptionDomain.getDomainName().equals(domainName)) {
+					
+					return PojoConverter.populateSubscriptionDomainPojo(subscriptionDomain);
+				}
+			}
+		}
+
+		String message = "Could not find a subscription [domain] " + domainName
+				+ " for Cartridge [type] " + cartridgeType + " and [alias] "
+				+ subscriptionAlias;
+		throw new RestAPIException(Status.NOT_FOUND, message);
+	}
+
+	public StratosAdminResponse removeSubscriptionDomain(int tenantId,
+			String subscriptionAlias, String domainName) {
+		StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
+		
+		List<String> tenantAliases = tenantIdToAliasesMap.get(tenantId);
+		if(tenantAliases != null && tenantAliases.contains(subscriptionAlias)) {
+			for (Iterator<SubscriptionDomain> iterator = subscriptionAliasToDomainMap.get(subscriptionAlias).iterator(); iterator
+					.hasNext();) {
+				SubscriptionDomain subscriptionDomain = (SubscriptionDomain) iterator.next();
+				if (subscriptionDomain.getDomainName().equals(domainName)) {
+					iterator.remove();
+					stratosAdminResponse.setMessage("Successfully removed the subscription domain: "+domainName);
+				}
+			}
+		} else {
+			
+			stratosAdminResponse.setMessage("Failed to remove the subscription domain: "+domainName);
+		}
+		
+        return stratosAdminResponse;
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/StratosTestAdmin.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/StratosTestAdmin.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/StratosTestAdmin.java
index 6880bab..5302dab 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/StratosTestAdmin.java
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/mock/StratosTestAdmin.java
@@ -18,26 +18,30 @@
  */
 package org.apache.stratos.rest.endpoint.mock;
 
-import org.apache.catalina.tribes.membership.McastService;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.common.beans.TenantInfoBean;
 import org.apache.stratos.manager.dto.Cartridge;
 import org.apache.stratos.manager.dto.SubscriptionInfo;
 import org.apache.stratos.manager.exception.ADCException;
+import org.apache.stratos.manager.subscription.SubscriptionDomain;
 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;
 import org.apache.stratos.rest.endpoint.bean.autoscaler.policy.deployment.DeploymentPolicy;
 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.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.services.ServiceUtils;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
@@ -465,6 +469,46 @@ public class StratosTestAdmin {
         return MockContext.getInstance().getDeploymentPoliciesForCartridgeType(cartridgeType);
     }
 
+    @POST
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/domains")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public StratosAdminResponse addSubscriptionDomains(@PathParam("cartridgeType") String cartridgeType,
+                                                      @PathParam("subscriptionAlias") String subscriptionAlias,
+                                                      SubscriptionDomainRequest request) throws RestAPIException {
+
+        return MockContext.getInstance().addSubscriptionDomains(2, subscriptionAlias, request);
+    }
+
+    @GET
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/domains")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public SubscriptionDomainBean[] getSubscriptionDomains(@PathParam("cartridgeType") String cartridgeType,
+                                           @PathParam("subscriptionAlias") String subscriptionAlias) throws RestAPIException {
+
+        return MockContext.getInstance().getSubscriptionDomains(2, subscriptionAlias).toArray(new SubscriptionDomainBean[0]);
+    }
 
+    @GET
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/domains/{domainName}")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public SubscriptionDomainBean getSubscriptionDomain(@PathParam("cartridgeType") String cartridgeType,
+            @PathParam("subscriptionAlias") String subscriptionAlias, @PathParam("domainName") String domainName) throws RestAPIException {
+
+        return MockContext.getInstance().getSubscriptionDomain(2, cartridgeType, subscriptionAlias, domainName);
+    }
+
+    @DELETE
+    @Path("/cartridge/{cartridgeType}/subscription/{subscriptionAlias}/domains/{domainName}")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public StratosAdminResponse removeSubscriptionDomain(@PathParam("cartridgeType") String cartridgeType,
+                                                         @PathParam("subscriptionAlias") String subscriptionAlias,
+                                                         @PathParam("domainName") String domainName) throws RestAPIException {
+
+        return MockContext.getInstance().removeSubscriptionDomain(2, subscriptionAlias, domainName);
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/ServiceUtils.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/ServiceUtils.java b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/ServiceUtils.java
index 44b2c26..7f468d7 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/ServiceUtils.java
+++ b/components/org.apache.stratos.rest.endpoint/src/main/java/org/apache/stratos/rest/endpoint/services/ServiceUtils.java
@@ -20,6 +20,7 @@ package org.apache.stratos.rest.endpoint.services;
 
 import org.apache.axis2.AxisFault;
 import org.apache.axis2.context.ConfigurationContext;
+import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.autoscaler.deployment.policy.DeploymentPolicy;
@@ -44,6 +45,7 @@ import org.apache.stratos.manager.subscription.CartridgeSubscription;
 import org.apache.stratos.manager.subscription.DataCartridgeSubscription;
 import org.apache.stratos.manager.subscription.PersistenceContext;
 import org.apache.stratos.manager.subscription.SubscriptionData;
+import org.apache.stratos.manager.subscription.SubscriptionDomain;
 import org.apache.stratos.manager.topology.model.TopologyClusterInformationModel;
 import org.apache.stratos.manager.utils.ApplicationManagementUtil;
 import org.apache.stratos.manager.utils.CartridgeConstants;
@@ -54,16 +56,19 @@ import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 import org.apache.stratos.messaging.util.Constants;
 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;
 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.subscription.domain.SubscriptionDomainBean;
 import org.apache.stratos.rest.endpoint.bean.util.converter.PojoConverter;
 import org.apache.stratos.rest.endpoint.exception.RestAPIException;
 
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 
 import java.rmi.RemoteException;
 import java.util.*;
@@ -575,6 +580,7 @@ public class ServiceUtils {
                     //cartridge.setStatus(CartridgeConstants.NOT_SUBSCRIBED);
                     cartridge.setCartridgeAlias("-");
                     cartridge.setPersistence(cartridgeInfo.getPersistence());
+                    cartridge.setServiceGroup(cartridgeInfo.getServiceGroup());
 
                     if(cartridgeInfo.getLbConfig() != null && cartridgeInfo.getProperties() != null) {
                         for(Property property: cartridgeInfo.getProperties()) {
@@ -718,7 +724,7 @@ public class ServiceUtils {
         return availableMultitenantCartridges;
     }
 
-	static List<Cartridge> getSubscriptions (String cartridgeSearchString, ConfigurationContext configurationContext) throws RestAPIException {
+	static List<Cartridge> getSubscriptions (String cartridgeSearchString, String serviceGroup, ConfigurationContext configurationContext) throws RestAPIException {
 
         List<Cartridge> cartridges = new ArrayList<Cartridge>();
 
@@ -762,6 +768,10 @@ public class ServiceUtils {
                     // Ignoring the LB cartridges since they are not shown to the user.
                     if(cartridge.isLoadBalancer())
                         continue;
+                    if(StringUtils.isNotEmpty(serviceGroup) && cartridge.getServiceGroup() != null &&
+                    		!cartridge.getServiceGroup().equals(serviceGroup)){
+                        continue;
+                    }
                     cartridges.add(cartridge);
                 }
             } else {
@@ -894,7 +904,9 @@ public class ServiceUtils {
                     }
                 }
             }
-			
+            if(subscription.getCartridgeInfo().getServiceGroup() != null) {
+            	cartridge.setServiceGroup(subscription.getCartridgeInfo().getServiceGroup());
+            }
 			return cartridge;
 			
 		} catch (Exception e) {
@@ -992,6 +1004,7 @@ public class ServiceUtils {
         subscriptionData.setRepositoryPassword(cartridgeInfoBean.getRepoPassword());
         subscriptionData.setCommitsEnabled(cartridgeInfoBean.isCommitsEnabled());
         subscriptionData.setServiceGroup(cartridgeInfoBean.getServiceGroup());
+        //subscriptionData.setServiceName(cartridgeInfoBean.getServiceName()); // For MT cartridges
         
         if (cartridgeInfoBean.isPersistanceRequired()) {
             // Add persistence related properties to PersistenceContext
@@ -1050,6 +1063,22 @@ public class ServiceUtils {
         return arrCluster;
 
     }
+    
+	public static org.apache.stratos.rest.endpoint.bean.topology.Cluster[] getClustersForCartridgeType(String cartridgeType) {
+
+		Set<Cluster> clusterSet = TopologyClusterInformationModel
+				.getInstance()
+				.getClusters(cartridgeType);
+		List<org.apache.stratos.rest.endpoint.bean.topology.Cluster> clusters = new ArrayList<org.apache.stratos.rest.endpoint.bean.topology.Cluster>();
+		for (Cluster cluster : clusterSet) {
+			clusters.add(PojoConverter.populateClusterPojos(cluster));
+		}
+		org.apache.stratos.rest.endpoint.bean.topology.Cluster[] arrCluster = new org.apache.stratos.rest.endpoint.bean.topology.Cluster[clusters
+				.size()];
+		arrCluster = clusters.toArray(arrCluster);
+		return arrCluster;
+
+	}
 
     // return the cluster id for the lb. This is a temp fix.
     /*private static String subscribeToLb(String cartridgeType, String loadBalancedCartridgeType, String lbAlias,
@@ -1187,4 +1216,101 @@ public class ServiceUtils {
         return stratosAdminResponse;
     }
 
+    public static StratosAdminResponse addSubscriptionDomains(ConfigurationContext configurationContext, String cartridgeType,
+                                                             String subscriptionAlias, 
+                                                             SubscriptionDomainRequest request) 
+                                                            		 throws RestAPIException {
+        try {
+            int tenantId = ApplicationManagementUtil.getTenantId(configurationContext);
+
+            for (org.apache.stratos.rest.endpoint.bean.subscription.domain.SubscriptionDomainBean subscriptionDomain : request.domains) {
+                boolean isDomainExists = isSubscriptionDomainExists(configurationContext, cartridgeType, subscriptionAlias, subscriptionDomain.domainName);
+                if (isDomainExists) {
+                    String message = "Subscription domain " + subscriptionDomain.domainName + " exists";
+                    throw new RestAPIException(Status.INTERNAL_SERVER_ERROR, message);
+                }
+            }
+
+            for (org.apache.stratos.rest.endpoint.bean.subscription.domain.SubscriptionDomainBean subscriptionDomain : request.domains) {
+                cartridgeSubsciptionManager.addSubscriptionDomain(tenantId, subscriptionAlias,
+            			subscriptionDomain.domainName, subscriptionDomain.applicationContext);
+			}
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new RestAPIException(e.getMessage(), e);
+        }
+
+        StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
+        stratosAdminResponse.setMessage("Successfully added domains to cartridge subscription");
+        return stratosAdminResponse;
+    }
+
+    public static boolean isSubscriptionDomainExists(ConfigurationContext configurationContext, String cartridgeType,
+                                                     String subscriptionAlias, String domain) throws RestAPIException {
+        try {
+            int tenantId = ApplicationManagementUtil.getTenantId(configurationContext);
+            SubscriptionDomainBean subscriptionDomain = PojoConverter.populateSubscriptionDomainPojo(cartridgeSubsciptionManager.getSubscriptionDomain(tenantId,
+                    subscriptionAlias, domain));
+
+            if (subscriptionDomain.domainName != null) {
+                return true;
+            } else {
+                return false;
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new RestAPIException(e.getMessage(), e);
+        }
+
+    }
+
+    public static List<SubscriptionDomainBean> getSubscriptionDomains(ConfigurationContext configurationContext, String cartridgeType,
+                                                      String subscriptionAlias) throws RestAPIException {
+        try {
+            int tenantId = ApplicationManagementUtil.getTenantId(configurationContext);
+            return PojoConverter.populateSubscriptionDomainPojos(cartridgeSubsciptionManager.getSubscriptionDomains(tenantId, subscriptionAlias));
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new RestAPIException(e.getMessage(), e);
+        }
+    }
+    
+	public static SubscriptionDomainBean getSubscriptionDomain(ConfigurationContext configurationContext, String cartridgeType,
+			String subscriptionAlias, String domain) throws RestAPIException {
+		try {
+			int tenantId = ApplicationManagementUtil
+					.getTenantId(configurationContext);
+			SubscriptionDomainBean subscriptionDomain = PojoConverter.populateSubscriptionDomainPojo(cartridgeSubsciptionManager.getSubscriptionDomain(tenantId,
+					subscriptionAlias, domain));
+			
+			if (subscriptionDomain == null) {
+				String message = "Could not find a subscription [domain] "+domain+ " for Cartridge [type] "
+							+cartridgeType+ " and [alias] "+subscriptionAlias;
+				log.error(message);
+				throw new RestAPIException(Status.NOT_FOUND, message);
+			}
+			
+			return subscriptionDomain;
+			
+		} catch (Exception e) {
+			log.error(e.getMessage(), e);
+			throw new RestAPIException(e.getMessage(), e);
+		}
+	}
+
+    public static StratosAdminResponse removeSubscriptionDomain(ConfigurationContext configurationContext, String cartridgeType,
+                                                                String subscriptionAlias, String domain) throws RestAPIException {
+        try {
+            int tenantId = ApplicationManagementUtil.getTenantId(configurationContext);
+            cartridgeSubsciptionManager.removeSubscriptionDomain(tenantId, subscriptionAlias, domain);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new RestAPIException(e.getMessage(), e);
+        }
+
+        StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
+        stratosAdminResponse.setMessage("Successfully removed domains from cartridge subscription");
+        return stratosAdminResponse;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 7b744a5..63d713f 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,12 +28,14 @@ import org.apache.stratos.common.util.CommonUtil;
 import org.apache.stratos.manager.dto.Cartridge;
 import org.apache.stratos.manager.dto.SubscriptionInfo;
 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;
@@ -41,6 +44,7 @@ import org.apache.stratos.rest.endpoint.bean.cartridge.definition.CartridgeDefin
 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.tenant.mgt.core.TenantPersistor;
@@ -79,6 +83,7 @@ public class StratosAdmin extends AbstractAdmin {
     public StratosAdminResponse initialize ()
             throws RestAPIException {
 
+
         StratosAdminResponse stratosAdminResponse = new StratosAdminResponse();
         stratosAdminResponse.setMessage("Successfully logged in");
         return stratosAdminResponse;
@@ -309,7 +314,18 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     public Cartridge[] getSubscribedCartridges() throws RestAPIException {
-        List<Cartridge> cartridgeList = ServiceUtils.getSubscriptions(null, getConfigContext());
+        List<Cartridge> cartridgeList = ServiceUtils.getSubscriptions(null, null, getConfigContext());
+        // Following is very important when working with axis2
+        return cartridgeList.isEmpty() ? new Cartridge[0] : cartridgeList.toArray(new Cartridge[cartridgeList.size()]);
+    }
+
+    @GET
+    @Path("/cartridge/list/subscribed/group/{serviceGroup}")
+    @Produces("application/json")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Cartridge[] 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()]);
     }
@@ -382,6 +398,15 @@ public class StratosAdmin extends AbstractAdmin {
     @Consumes("application/json")
     @AuthorizationAction("/permission/protected/manage/monitor/tenants")
     public Cluster[] getClusters(@PathParam("cartridgeType") String cartridgeType) throws RestAPIException {
+        return ServiceUtils.getClustersForCartridgeType(cartridgeType);
+    }
+    
+    @GET
+    @Path("/cluster/service/{cartridgeType}/")
+    @Produces("application/json")
+    @Consumes("application/json")
+    @AuthorizationAction("/permission/protected/manage/monitor/tenants")
+    public Cluster[] getServiceClusters(@PathParam("cartridgeType") String cartridgeType) throws RestAPIException {
 
         return ServiceUtils.getClustersForTenantAndCartridgeType(getConfigContext(), cartridgeType);
     }
@@ -405,7 +430,7 @@ public class StratosAdmin extends AbstractAdmin {
     public Cluster 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()) {
@@ -1018,4 +1043,81 @@ 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 {
+
+        StratosAdminResponse stratosAdminResponse = ServiceUtils.addSubscriptionDomains(getConfigContext(), cartridgeType, subscriptionAlias, request);
+        return Response.ok().entity(stratosAdminResponse).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 StratosAdminResponse removeSubscriptionDomain(@PathParam("cartridgeType") String cartridgeType,
+                                                         @PathParam("subscriptionAlias") String subscriptionAlias,
+                                                         @PathParam("domainName") String domainName) throws RestAPIException {
+        return ServiceUtils.removeSubscriptionDomain(getConfigContext(), cartridgeType, subscriptionAlias, domainName);
+    }
+
+    @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)) {
+            Cluster lbCluster = getCluster(lbClusterId);
+            if (lbCluster != null) {
+                if (log.isDebugEnabled()) {
+                    log.debug(String.format("Load balancer cluster found: %s", lbCluster.toString()));
+                }
+                Response.ok().entity(lbCluster).build();
+            }
+        }
+        return Response.status(Response.Status.NOT_FOUND).build();
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos-test/WEB-INF/cxf-servlet.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos-test/WEB-INF/cxf-servlet.xml b/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos-test/WEB-INF/cxf-servlet.xml
index 552cad7..f8b8750 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos-test/WEB-INF/cxf-servlet.xml
+++ b/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos-test/WEB-INF/cxf-servlet.xml
@@ -31,6 +31,7 @@
         </jaxrs:serviceBeans>
 
         <jaxrs:providers>
+			<ref bean="throwableExceptionHandler"/>
             <bean class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
                 <property name="dropRootElement" value="true"/>
                 <property name="supportUnwrapped" value="true"/>
@@ -41,4 +42,5 @@
 
     <bean id="stratosRestEndpointTestBean" class="org.apache.stratos.rest.endpoint.mock.StratosTestAdmin"/>
     <bean id="exceptionHandler" class="org.apache.stratos.rest.endpoint.handlers.CustomExceptionMapper"/>
+    <bean id="throwableExceptionHandler" class="org.apache.stratos.rest.endpoint.handlers.CustomThrowableExceptionMapper"/>
 </beans>


[05/14] Clustering changes for stratos

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/endpoint/TenantAwareLoadBalanceEndpoint.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/endpoint/TenantAwareLoadBalanceEndpoint.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/endpoint/TenantAwareLoadBalanceEndpoint.java
index 3d71a0a..884d5f6 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/endpoint/TenantAwareLoadBalanceEndpoint.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/endpoint/TenantAwareLoadBalanceEndpoint.java
@@ -28,14 +28,17 @@ import org.apache.stratos.load.balancer.algorithm.LoadBalanceAlgorithmFactory;
 import org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration;
 import org.apache.stratos.load.balancer.conf.domain.MemberIpType;
 import org.apache.stratos.load.balancer.conf.domain.TenantIdentifier;
+import org.apache.stratos.load.balancer.context.LoadBalancerContext;
 import org.apache.stratos.load.balancer.statistics.InFlightRequestDecrementCallable;
 import org.apache.stratos.load.balancer.statistics.InFlightRequestIncrementCallable;
 import org.apache.stratos.load.balancer.statistics.LoadBalancerStatisticsExecutor;
 import org.apache.stratos.load.balancer.util.Constants;
 import org.apache.stratos.messaging.domain.tenant.Tenant;
+import org.apache.stratos.messaging.domain.topology.Cluster;
 import org.apache.stratos.messaging.domain.topology.Member;
 import org.apache.stratos.messaging.domain.topology.Port;
 import org.apache.stratos.messaging.message.receiver.tenant.TenantManager;
+import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 import org.apache.synapse.MessageContext;
 import org.apache.synapse.SynapseConstants;
 import org.apache.synapse.SynapseException;
@@ -59,7 +62,7 @@ import java.util.regex.Pattern;
 
 
 public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints.LoadbalanceEndpoint implements Serializable {
-    private static final String PORT_MAPPING_PREFIX = "port.mapping.";
+    private static final long serialVersionUID = -6612900240087164008L;
 
     /* Request delegator identifies the next member */
     private RequestDelegator requestDelegator;
@@ -75,6 +78,8 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
 
     /* Sessions time out interval */
     private long sessionTimeout = -1;
+    
+    private final static Pattern LAST_INT_PATTERN = Pattern.compile("[^0-9]+([0-9]+)$");
 
     @Override
     public void init(SynapseEnvironment synapseEnvironment) {
@@ -118,6 +123,8 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
 
         TenantAwareLoadBalanceFaultHandler faultHandler = new TenantAwareLoadBalanceFaultHandler();
         if (sessionInformation != null && currentMember != null) {
+            // Update axis2 member ports
+            updateAxis2MemberPorts(synCtx, currentMember);
             // Send request to the member with the existing session
             sessionInformation.updateExpiryTime();
             sendToApplicationMember(synCtx, currentMember, faultHandler, false);
@@ -150,8 +157,17 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
     private void setupLoadBalancerContextProperties(MessageContext synCtx, org.apache.axis2.clustering.Member currentMember) {
         String lbHostName = extractTargetHost(synCtx);
         org.apache.axis2.context.MessageContext axis2MsgCtx = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
-        TransportInDescription httpTransportIn = axis2MsgCtx.getConfigurationContext().getAxisConfiguration().getTransportIn("http");
-        TransportInDescription httpsTransportIn = axis2MsgCtx.getConfigurationContext().getAxisConfiguration().getTransportIn("https");
+        
+        String httpTransportName = "http", httpsTransportName = "https";
+        String transportId = getTransportId(extractIncomingTransport(synCtx));
+               
+		if (transportId != null) {
+			httpsTransportName = httpsTransportName.concat(transportId);
+			httpTransportName = httpTransportName.concat(transportId);
+		}
+        
+        TransportInDescription httpTransportIn = axis2MsgCtx.getConfigurationContext().getAxisConfiguration().getTransportIn(httpTransportName);
+        TransportInDescription httpsTransportIn = axis2MsgCtx.getConfigurationContext().getAxisConfiguration().getTransportIn(httpsTransportName);
         String lbHttpPort = (String) httpTransportIn.getParameter("port").getValue();
         String lbHttpsPort = (String) httpsTransportIn.getParameter("port").getValue();
         String clusterId = currentMember.getProperties().getProperty(Constants.CLUSTER_ID);
@@ -161,6 +177,16 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
         synCtx.setProperty(Constants.LB_HTTPS_PORT, lbHttpsPort);
         synCtx.setProperty(Constants.CLUSTER_ID, clusterId);
     }
+    
+	protected String getTransportId(String incomingTransportName) {
+		// pattern match and find the transport id.
+		Matcher matcher = LAST_INT_PATTERN.matcher(incomingTransportName);
+		if (matcher.find()) {
+			return matcher.group(1);
+		}
+
+		return null;
+	}
 
 
     /**
@@ -212,112 +238,255 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
             }
             String url = extractUrl(synCtx);
             int tenantId = scanUrlForTenantId(url);
-            if (tenantExists(tenantId)) {
+            if(tenantId == -1) {
+               // If there is no tenant involves in the URL, Find next member from host name
+               member = requestDelegator.findNextMemberFromHostName(targetHost);
+            } else if (tenantExists(tenantId)) {
+                // Tenant found, find member from hostname and tenant id
                 member = requestDelegator.findNextMemberFromTenantId(targetHost, tenantId);
             } else {
-                // Multi-tenant cluster not found, try single tenant
-                member = requestDelegator.findNextMemberFromHostName(targetHost);
+                // Tenant id not found in the subscription for the URL which has tenant domain.
+                throwSynapseException(synCtx, 403, String.format("You are unauthorized to access"));
             }
         } else {
-            // Find next member from single tenant cluster map
-            member = requestDelegator.findNextMemberFromHostName(targetHost);
+
         }
 
         if (member == null)
             return null;
 
         // Create Axi2 member object
+        org.apache.axis2.clustering.Member axis2Member = new org.apache.axis2.clustering.Member(
+                getMemberIp(synCtx, member), -1);
+        axis2Member.setDomain(member.getClusterId());
+        axis2Member.setActive(member.isActive());
+        // Set cluster id and member id in member properties
+        axis2Member.getProperties().setProperty(Constants.CLUSTER_ID, member.getClusterId());
+        axis2Member.getProperties().setProperty(Constants.MEMBER_ID, member.getMemberId());
+        // Update axis2 member ports
+        updateAxis2MemberPorts(synCtx, axis2Member);
+        return axis2Member;
+    }
+
+    /**
+     * Update http/https port in axis2 member according to incoming request port.
+     *
+     * @param synCtx
+     * @param axis2Member
+     */
+    private void updateAxis2MemberPorts(MessageContext synCtx, org.apache.axis2.clustering.Member axis2Member) {
+        if(log.isDebugEnabled()) {
+            log.debug("Updating axis2 member port");
+        }
+
+        // Find mapping outgoing port for incoming port
+        int incomingPort = findIncomingPort(synCtx);
         String transport = extractTransport(synCtx);
-        Port transportPort = member.getPort(transport);
-        if (transportPort == null) {
+        Port outgoingPort = findOutgoingPort(synCtx, axis2Member, transport, incomingPort);
+        if (outgoingPort == null) {
             if (log.isErrorEnabled()) {
-                log.error(String.format("Port not found for transport %s in member %s", transport, member.getMemberId()));
+                log.error(String.format("Could not find the port for proxy port %d in member %s", incomingPort,
+                        axis2Member.getProperties().getProperty(Constants.MEMBER_ID)));
             }
             throwSynapseException(synCtx, 500, "Internal server error");
         }
+        if (Constants.HTTP.equals(transport)) {
+            axis2Member.setHttpPort(outgoingPort.getValue());
+        } else if (Constants.HTTPS.equals(transport)) {
+            axis2Member.setHttpsPort(outgoingPort.getValue());
+        }
+    }
 
-        int memberPort = transportPort.getValue();
-        org.apache.axis2.clustering.Member axis2Member = new org.apache.axis2.clustering.Member(getMemberIp(synCtx, member), memberPort);
-        axis2Member.setDomain(member.getClusterId());
-        Port httpPort = member.getPort("http");
-        if (httpPort != null)
-            axis2Member.setHttpPort(httpPort.getValue());
-        Port httpsPort = member.getPort("https");
-        if (httpsPort != null)
-            axis2Member.setHttpsPort(httpsPort.getValue());
-        axis2Member.setActive(member.isActive());
-        // Set cluster id and partition id in message context
-        axis2Member.getProperties().setProperty(Constants.CLUSTER_ID, member.getClusterId());
-        return axis2Member;
+    /**
+     * Find incoming port from request URL.
+     *
+     * @param synCtx
+     * @return
+     * @throws MalformedURLException
+     */
+    private int findIncomingPort(MessageContext synCtx) {
+        org.apache.axis2.context.MessageContext msgCtx =
+                ((Axis2MessageContext) synCtx).getAxis2MessageContext();
+        try {
+            String servicePrefix = (String) msgCtx.getProperty(Constants.AXIS2_MSG_CTX_SERVICE_PREFIX);
+            if (servicePrefix == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("%s property not found in axis2 message context", Constants.AXIS2_MSG_CTX_SERVICE_PREFIX));
+                }
+                throwSynapseException(synCtx, 500, "Internal server error");
+            }
+            URL servicePrefixUrl = new URL(servicePrefix);
+            return servicePrefixUrl.getPort();
+        } catch (MalformedURLException e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not find incoming request port");
+            }
+            throwSynapseException(synCtx, 500, "Internal server error");
+        }
+        return -1;
     }
 
+    /**
+     * Find mapping outgoing port for incoming port.
+     *
+     * @param synCtx
+     * @param axis2Member
+     * @param transport
+     * @param incomingPort
+     * @return
+     * @throws MalformedURLException
+     */
+    private Port findOutgoingPort(MessageContext synCtx, org.apache.axis2.clustering.Member axis2Member, String transport, int incomingPort) {
+        Member member = findMemberFromAxis2Member(synCtx, axis2Member);
+        if ((member != null) && (member.getPorts() != null)) {
+            Port outgoingPort = member.getPort(incomingPort);
+            if (outgoingPort != null) {
+                if (!transport.startsWith(outgoingPort.getProtocol())) {
+                    if (log.isErrorEnabled()) {
+                        String message = String.format("Transport %s is not valid for port %d", transport, incomingPort);
+                        if (log.isErrorEnabled()) {
+                            log.error(message);
+                        }
+                        throwSynapseException(synCtx, 500, message);
+                    }
+                }
+                if (log.isDebugEnabled()) {
+                    log.debug("Outgoing request port found: " + outgoingPort.getValue());
+                }
+                return outgoingPort;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find topology member from axis2 member using cluster id and member id defined in axis2 member properties.
+     *
+     * @param synCtx
+     * @param axis2Member
+     * @return
+     */
+    private Member findMemberFromAxis2Member(MessageContext synCtx, org.apache.axis2.clustering.Member axis2Member) {
+        String clusterId = axis2Member.getProperties().getProperty(Constants.CLUSTER_ID);
+        String memberId = axis2Member.getProperties().getProperty(Constants.MEMBER_ID);
+        if (StringUtils.isBlank(clusterId) || StringUtils.isBlank(memberId)) {
+            if (log.isErrorEnabled()) {
+                log.error(String.format("Could not find cluster id and/or member id properties in axis2 member: [cluster-id] %s " +
+                        "[member-id] %s", clusterId, memberId));
+            }
+            throwSynapseException(synCtx, 500, "Internal server error");
+        }
+        try {
+            TopologyManager.acquireReadLock();
+            Cluster cluster = LoadBalancerContext.getInstance().getClusterIdClusterMap().getCluster(clusterId);
+            if (cluster == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("Cluster not found in load balancer context: [cluster-id] %s ", clusterId));
+                }
+                throwSynapseException(synCtx, 500, "Internal server error");
+            }
+            Member member = cluster.getMember(memberId);
+            if (member == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("Member not found in load balancer context: [cluster-id] %s [member-id] %s", clusterId, memberId));
+                }
+                throwSynapseException(synCtx, 500, "Internal server error");
+            }
+            return member;
+        } finally {
+            TopologyManager.releaseReadLock();
+        }
+    }
+
+    /**
+     * Get members private or public ip according to load balancer configuration.
+     *
+     * @param synCtx
+     * @param member
+     * @return
+     */
     private String getMemberIp(MessageContext synCtx, Member member) {
-        if(LoadBalancerConfiguration.getInstance().isTopologyEventListenerEnabled()) {
-            if(LoadBalancerConfiguration.getInstance().getTopologyMemberIpType() == MemberIpType.Public) {
+        if (LoadBalancerConfiguration.getInstance().isTopologyEventListenerEnabled()) {
+            if (LoadBalancerConfiguration.getInstance().getTopologyMemberIpType() == MemberIpType.Public) {
                 // Return member's public IP address
-                if(StringUtils.isBlank(member.getMemberPublicIp())) {
+                if (StringUtils.isBlank(member.getMemberPublicIp())) {
                     if (log.isErrorEnabled()) {
                         log.error(String.format("Member public IP address not found: [member] %s", member.getMemberId()));
                     }
                     throwSynapseException(synCtx, 500, "Internal server error");
                 }
-                if(log.isDebugEnabled()) {
+                if (log.isDebugEnabled()) {
                     log.debug(String.format("Using member public IP address: [member] %s [ip] %s", member.getMemberId(), member.getMemberPublicIp()));
                 }
                 return member.getMemberPublicIp();
             }
         }
         // Return member's private IP address
-        if(StringUtils.isBlank(member.getMemberIp())) {
+        if (StringUtils.isBlank(member.getMemberIp())) {
             if (log.isErrorEnabled()) {
                 log.error(String.format("Member IP address not found: [member] %s", member.getMemberId()));
             }
             throwSynapseException(synCtx, 500, "Internal server error");
         }
-        if(log.isDebugEnabled()) {
+        if (log.isDebugEnabled()) {
             log.debug(String.format("Using member IP address: [member] %s [ip] %s", member.getMemberId(), member.getMemberIp()));
         }
         return member.getMemberIp();
     }
 
+    /**
+     * Extract incoming request URL from message context.
+     *
+     * @param synCtx
+     * @return
+     */
     private String extractUrl(MessageContext synCtx) {
         Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx;
         org.apache.axis2.context.MessageContext axis2MessageCtx = axis2smc.getAxis2MessageContext();
         return (String) axis2MessageCtx.getProperty(Constants.AXIS2_MSG_CTX_TRANSPORT_IN_URL);
     }
 
+    /**
+     * Scan given URL for tenant id.
+     *
+     * @param url
+     * @return
+     */
     private int scanUrlForTenantId(String url) {
         int tenantId = -1;
-        String regex = LoadBalancerConfiguration.getInstance().getTenantIdentifierRegex();
-        if (log.isDebugEnabled()) {
-            log.debug(String.format("Request URL: %s ", url));
-            log.debug(String.format("Tenant identifier regex: %s ", regex));
-        }
-        Pattern pattern = Pattern.compile(regex);
-        Matcher matcher = pattern.matcher(url);
-        if (matcher.find()) {
-            if (LoadBalancerConfiguration.getInstance().getTenantIdentifier() == TenantIdentifier.TenantId) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Identifying tenant using tenant id...");
-                }
-                tenantId = Integer.parseInt(matcher.group(1));
-                if (log.isDebugEnabled()) {
-                    log.debug(String.format("Tenant identifier found: [tenant-id] %d", tenantId));
-                }
-            } else if (LoadBalancerConfiguration.getInstance().getTenantIdentifier() == TenantIdentifier.TenantDomain) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Identifying tenant using tenant domain...");
+        List<String> regexList = LoadBalancerConfiguration.getInstance().getTenantIdentifierRegexList();
+        for(String regex : regexList) {
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Request URL: %s ", url));
+                log.debug(String.format("Tenant identifier regex: %s ", regex));
+            }
+            Pattern pattern = Pattern.compile(regex);
+            Matcher matcher = pattern.matcher(url);
+            if (matcher.find()) {
+                if (LoadBalancerConfiguration.getInstance().getTenantIdentifier() == TenantIdentifier.TenantId) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Identifying tenant using tenant id...");
+                    }
+                    tenantId = Integer.parseInt(matcher.group(1));
+                    if (log.isDebugEnabled()) {
+                        log.debug(String.format("Tenant identifier found: [tenant-id] %d", tenantId));
+                    }
+                } else if (LoadBalancerConfiguration.getInstance().getTenantIdentifier() == TenantIdentifier.TenantDomain) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Identifying tenant using tenant domain...");
+                    }
+                    String tenantDomain = matcher.group(1);
+                    tenantId = findTenantIdFromTenantDomain(tenantDomain);
+                    if (log.isDebugEnabled()) {
+                        log.debug(String.format("Tenant identifier found: [tenant-domain] %s [tenant-id] %d", tenantDomain, tenantId));
+                    }
                 }
-                String tenantDomain = matcher.group(1);
-                tenantId = findTenantIdFromTenantDomain(tenantDomain);
+                break;
+            } else {
                 if (log.isDebugEnabled()) {
-                    log.debug(String.format("Tenant identifier found: [tenant-domain] %s [tenant-id] %d", tenantDomain, tenantId));
+                    log.debug("Tenant identifier not found in URL");
                 }
             }
-        } else {
-            if (log.isDebugEnabled()) {
-                log.debug("Tenant identifier not found in URL");
-            }
         }
         return tenantId;
     }
@@ -386,6 +555,11 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
         org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
         return axis2MessageContext.getTransportIn().getName();
     }
+    
+    private String extractIncomingTransport(MessageContext synCtx) {
+        org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
+        return axis2MessageContext.getIncomingTransportName();
+    }
 
     /**
      * @param to     get an endpoint to send the information
@@ -413,53 +587,71 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
         return endpoint;
     }
 
-    private EndpointReference getEndpointReferenceAfterURLRewrite(org.apache.axis2.clustering.Member currentMember,
-                                                                  String transport,
-                                                                  String address,
-                                                                  int incomingPort) {
+    private EndpointReference getEndpointReferenceAfterURLRewrite(MessageContext synCtx, org.apache.axis2.clustering.Member currentMember,
+                                                                  String transport) {
+        try {
+            if (transport.startsWith(Constants.HTTPS)) {
+                transport = Constants.HTTPS;
+            } else if (transport.startsWith(Constants.HTTP)) {
+                transport = Constants.HTTP;
+            } else {
+                String msg = "Cannot load balance for non-HTTP/S transport " + transport;
+                log.error(msg);
+                throwSynapseException(synCtx, 500, msg);
+            }
 
-        if (transport.startsWith("https")) {
-            transport = "https";
-        } else if (transport.startsWith("http")) {
-            transport = "http";
-        } else {
-            String msg = "Cannot load balance for non-HTTP/S transport " + transport;
-            log.error(msg);
-            throw new SynapseException(msg);
-        }
-        // URL Rewrite
-        if (transport.startsWith("http") || transport.startsWith("https")) {
-            if (address.startsWith("http://") || address.startsWith("https://")) {
+            String address = synCtx.getTo().getAddress();
+            if (address.startsWith(Constants.HTTP + "://") || address.startsWith(Constants.HTTPS + "://")) {
+                // Remove protocol, hostname and port found in address
                 try {
-                    String _address = address.indexOf("?") > 0 ? address.substring(address.indexOf("?"), address.length()) : "";
-                    address = new URL(address).getPath() + _address;
+                    URL addressUrl = new URL(address);
+                    address = addressUrl.getPath() + (StringUtils.isNotBlank(addressUrl.getQuery()) ?
+                            "?" + addressUrl.getQuery() : "");
                 } catch (MalformedURLException e) {
-                    String msg = "URL " + address + " is malformed";
+                    String msg = String.format("URL is malformed: %s", address);
                     log.error(msg, e);
                     throw new SynapseException(msg, e);
                 }
             }
 
-            int port;
-            Properties memberProperties = currentMember.getProperties();
-            String mappedPort = memberProperties.getProperty(PORT_MAPPING_PREFIX + incomingPort);
-            if (mappedPort != null) {
-                port = Integer.parseInt(mappedPort);
-            } else if (transport.startsWith("https")) {
-                port = currentMember.getHttpsPort();
-            } else {
-                port = currentMember.getHttpPort();
+            String hostName = extractTargetHost(synCtx);
+            if (LoadBalancerContext.getInstance().getHostNameAppContextMap().contains(hostName)) {
+                String appContext = LoadBalancerContext.getInstance().getHostNameAppContextMap().getAppContext(hostName);
+                if (StringUtils.isNotBlank(appContext)) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(String.format("Domain mapping found with application context: [domain-name] %s [app-context] %s", hostName, appContext));
+                        log.debug(String.format("Incoming request address: %s", address));
+                    }
+                    address = "/" + cleanURLPath(appContext) + "/" + cleanURLPath(address);
+                    if (log.isDebugEnabled()) {
+                        log.debug(String.format("Outgoing request address: %s", address));
+                    }
+                }
             }
 
-            String remoteHost = memberProperties.getProperty("remoteHost");
-            String hostName = (remoteHost == null) ? currentMember.getHostName() : remoteHost;
-            return new EndpointReference(transport + "://" + hostName +
-                    ":" + port + address);
-        } else {
-            String msg = "Cannot load balance for non-HTTP/S transport " + transport;
-            log.error(msg);
-            throw new SynapseException(msg);
+            String memberHostName = currentMember.getHostName();
+            int memberPort = (transport.startsWith(Constants.HTTPS)) ? currentMember.getHttpsPort() : currentMember.getHttpPort();
+            return new EndpointReference(new URL(transport, memberHostName, memberPort, address).toString());
+
+        } catch (MalformedURLException e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not create endpoint reference", e);
+            }
+            throwSynapseException(synCtx, 500, "Internal server error");
+            return null;
+        }
+    }
+
+    private String cleanURLPath(String path) {
+        if (StringUtils.isNotBlank(path)) {
+            if (path.startsWith("/")) {
+                path = path.replaceFirst("/", "");
+            }
+            if (path.endsWith("/")) {
+                path = path.substring(0, path.length() - 2);
+            }
         }
+        return path;
     }
 
     /*
@@ -507,9 +699,7 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
         axis2MsgCtx.removeProperty(NhttpConstants.REST_URL_POSTFIX);
 
         String transport = axis2MsgCtx.getTransportIn().getName();
-        String address = synCtx.getTo().getAddress();
-        int incomingPort = extractPort(synCtx, transport);
-        EndpointReference to = getEndpointReferenceAfterURLRewrite(currentMember, transport, address, incomingPort);
+        EndpointReference to = getEndpointReferenceAfterURLRewrite(synCtx, currentMember, transport);
         synCtx.setTo(to);
 
         Endpoint endpoint = getEndpoint(to, currentMember, synCtx);
@@ -565,14 +755,13 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
     private void incrementInFlightRequestCount(MessageContext messageContext) {
         try {
             String clusterId = (String) messageContext.getProperty(Constants.CLUSTER_ID);
-            if(StringUtils.isBlank(clusterId)) {
+            if (StringUtils.isBlank(clusterId)) {
                 throw new RuntimeException("Cluster id not found in message context");
             }
             FutureTask<Object> task = new FutureTask<Object>(new InFlightRequestIncrementCallable(clusterId));
             LoadBalancerStatisticsExecutor.getInstance().getService().submit(task);
-        }
-        catch (Exception e) {
-            if(log.isDebugEnabled()) {
+        } catch (Exception e) {
+            if (log.isDebugEnabled()) {
                 log.debug("Could not increment in-flight request count", e);
             }
         }
@@ -581,14 +770,13 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
     private void decrementInFlightRequestCount(MessageContext messageContext) {
         try {
             String clusterId = (String) messageContext.getProperty(Constants.CLUSTER_ID);
-            if(StringUtils.isBlank(clusterId)) {
+            if (StringUtils.isBlank(clusterId)) {
                 throw new RuntimeException("Cluster id not found in message context");
             }
             FutureTask<Object> task = new FutureTask<Object>(new InFlightRequestDecrementCallable(clusterId));
             LoadBalancerStatisticsExecutor.getInstance().getService().submit(task);
-        }
-        catch (Exception e) {
-            if(log.isDebugEnabled()) {
+        } catch (Exception e) {
+            if (log.isDebugEnabled()) {
                 log.debug("Could not decrement in-flight request count", e);
             }
         }
@@ -661,7 +849,7 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
             decrementInFlightRequestCount(synCtx);
 
             if (isFailover()) {
-                if(log.isDebugEnabled()) {
+                if (log.isDebugEnabled()) {
                     log.debug("Fail-over enabled, trying to send the message to the next available member");
                 }
 
@@ -670,7 +858,7 @@ public class TenantAwareLoadBalanceEndpoint extends org.apache.synapse.endpoints
                     currentEp.destroy();
                 }
                 if (currentMember == null) {
-                    if(log.isErrorEnabled()) {
+                    if (log.isErrorEnabled()) {
                         log.error("Current member is null, could not fail-over");
                     }
                     return;

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/util/Constants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/util/Constants.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/util/Constants.java
index ff64d20..a29b980 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/util/Constants.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/util/Constants.java
@@ -22,12 +22,17 @@ package org.apache.stratos.load.balancer.util;
 public class Constants {
 
     public static final String CLUSTER_ID = "cluster_id";
+    public static final String MEMBER_ID = "member_id";
+
+    public static final String HTTP = "http";
+    public static final String HTTPS = "https";
+
+    public static final String AXIS2_MSG_CTX_TRANSPORT_IN_URL = "TransportInURL";
+    public static final String AXIS2_MSG_CTX_SERVICE_PREFIX = "SERVICE_PREFIX";
 
     public static final String LB_HOST_NAME = "LB_HOST_NAME";
     public static final String LB_HTTP_PORT = "LB_HTTP_PORT";
     public static final String LB_HTTPS_PORT = "LB_HTTPS_PORT";
 
     public static final String ALGORITHM_CONTEXT_CACHE = "algorithm.context.cache";
-
-    public static final String AXIS2_MSG_CTX_TRANSPORT_IN_URL = "TransportInURL";
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java
index 8256b80..6b5b97f 100755
--- a/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java
+++ b/components/org.apache.stratos.load.balancer/src/test/java/org/apache/stratos/load/balancer/test/LoadBalancerConfigurationTest.java
@@ -18,18 +18,18 @@
  */
 package org.apache.stratos.load.balancer.test;
 
-import java.io.File;
-import java.net.URL;
-
+import org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration;
 import org.apache.stratos.load.balancer.conf.domain.TenantIdentifier;
 import org.apache.stratos.messaging.domain.topology.*;
+import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 import org.apache.stratos.load.balancer.conf.LoadBalancerConfiguration;
 
-import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
+import java.io.File;
+import java.net.URL;
 
 /**
  * Test sample load balancer configurations.
@@ -84,7 +84,7 @@ public class LoadBalancerConfigurationTest {
             Assert.assertEquals(String.format("%s, network partition id is not valid", validationError), "network-partition-1", configuration.getNetworkPartitionId());
             Assert.assertTrue(String.format("%s, multi-tenancy is not true", validationError), configuration.isMultiTenancyEnabled());
             Assert.assertEquals(String.format("%s, tenant-identifier is not valid", validationError), TenantIdentifier.TenantDomain, configuration.getTenantIdentifier());
-            Assert.assertEquals(String.format("%s, tenant-identifier-regex is not valid", validationError), "t/([^/]*)/", configuration.getTenantIdentifierRegex());
+            Assert.assertEquals(String.format("%s, tenant-identifier-regex is not valid", validationError), "t/([^/]*)/", configuration.getTenantIdentifierRegexList().get(0));
         } finally {
             LoadBalancerConfiguration.clear();
         }
@@ -131,11 +131,11 @@ public class LoadBalancerConfigurationTest {
             Assert.assertNotNull(String.format("%s, member not found: [member] %s", validationError, memberId), m1);
             Assert.assertEquals(String.format("%s, member ip not valid", validationError), "10.0.0.10", m1.getMemberIp());
 
-            String portName = "http";
-            Port m1Http = m1.getPort(portName);
-            Assert.assertNotNull(String.format("%s, port not found: [member] %s [port] %s", validationError, memberId, portName), m1Http);
-            Assert.assertEquals(String.format("%s, port value not valid: [member] %s [port] %s", validationError, memberId, portName), 8080, m1Http.getValue());
-            Assert.assertEquals(String.format("%s, port proxy not valid: [member] %s [port] %s", validationError, memberId, portName), 80, m1Http.getProxy());
+            int proxyPort = 80;
+            Port m1Http = m1.getPort(proxyPort);
+            Assert.assertNotNull(String.format("%s, port not found: [member] %s [proxy-port] %d", validationError, memberId, proxyPort), m1Http);
+            Assert.assertEquals(String.format("%s, port value not valid: [member] %s [proxy-port] %d", validationError, memberId, proxyPort), 8080, m1Http.getValue());
+            Assert.assertEquals(String.format("%s, port proxy not valid: [member] %s [proxy-port] %d", validationError, memberId, proxyPort), 80, m1Http.getProxy());
 
         } finally {
             TopologyManager.releaseReadLock();

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 56f7e10..352c5b0 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
@@ -87,6 +87,7 @@ public abstract class CartridgeMgtBehaviour implements Serializable {
         PayloadData payloadData = PayloadFactory.getPayloadDataInstance(cartridgeInfo.getProvider(),
                 cartridgeInfo.getType(), basicPayloadData);
 
+        boolean isDeploymentParam = false;
         // get the payload parameters defined in the cartridge definition file for this cartridge type
         if (cartridgeInfo.getProperties() != null && cartridgeInfo.getProperties().length != 0) {
 
@@ -97,11 +98,21 @@ public abstract class CartridgeMgtBehaviour implements Serializable {
                 if (property.getName()
                         .startsWith(CartridgeConstants.CUSTOM_PAYLOAD_PARAM_NAME_PREFIX)) {
                     String payloadParamName = property.getName();
-                    payloadData.add(payloadParamName.substring(payloadParamName.indexOf(".") + 1), property.getValue());
+                    String payloadParamSubstring = payloadParamName.substring(payloadParamName.indexOf(".") + 1);
+                    if("DEPLOYMENT".equals(payloadParamSubstring)) {
+                    	isDeploymentParam = true;
+                    }
+                    payloadData.add(payloadParamSubstring, property.getValue());
                 }
             }
         }
 
+        // DEPLOYMENT payload param must be set because its used by puppet agent 
+        // to generate the hostname. Therefore, if DEPLOYMENT is not set in cartridge properties, 
+        // adding the DEPLOYMENT="default" param
+        if(!isDeploymentParam) {
+        	payloadData.add("DEPLOYMENT", "default");
+        }
         //check if there are any custom payload entries defined
         if (customPayloadEntries != null) {
             //add them to the payload

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/dao/Cluster.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/dao/Cluster.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/dao/Cluster.java
index bacb4d8..c515461 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/dao/Cluster.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/dao/Cluster.java
@@ -75,9 +75,9 @@ public class Cluster implements Serializable {
         this.hostName = hostName;
     }
 
-    public int getId() {
-        return id;
-    }
+    //public int getId() {
+    //    return id;
+    //}
 
     public void setId(int id) {
         this.id = id;

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 adfe60f..6281ec3 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
@@ -62,7 +62,7 @@ public abstract class Service extends CartridgeMgtBehaviour {
 
         setClusterId(generateClusterId(null, type));
         //host name is the hostname defined in cartridge definition
-        setHostName(cartridgeInfo.getHostName());
+        setHostName(generateHostName(null, cartridgeInfo.getHostName()));
 
         // create and set PayloadData instance
         setPayloadData(createPayload(cartridgeInfo, subscriptionKey, null, cluster, null, null, null));
@@ -70,7 +70,7 @@ public abstract class Service extends CartridgeMgtBehaviour {
 
     protected String generateClusterId (String alias, String cartridgeType) {
 
-        String clusterId = cartridgeType + cartridgeInfo.getHostName() + ".domain";
+        String clusterId = cartridgeType + "." + cartridgeInfo.getHostName() + ".domain";
         // limit the cartridge alias to 30 characters in length
         if (clusterId.length() > 30) {
             clusterId = CartridgeSubscriptionUtils.limitLengthOfString(clusterId, 30);
@@ -79,6 +79,11 @@ public abstract class Service extends CartridgeMgtBehaviour {
         return clusterId;
     }
 
+    protected String generateHostName (String alias, String cartridgeDefinitionHostName) {
+
+        return cartridgeDefinitionHostName;
+    }
+
     public void deploy (Properties properties) throws ADCException, UnregisteredCartridgeException {
 
         register(getCartridgeInfo(), getCluster(), getPayloadData(), getAutoscalingPolicyName(), getDeploymentPolicyName(), properties);

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 2c3045e..ed99d14 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
@@ -28,7 +28,10 @@ import org.apache.stratos.cloud.controller.stub.pojo.Properties;
 import org.apache.stratos.cloud.controller.stub.pojo.Property;
 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;
+import org.apache.stratos.manager.deploy.service.multitenant.lb.DefaultLBService;
+import org.apache.stratos.manager.deploy.service.multitenant.lb.ExistingLBService;
+import org.apache.stratos.manager.deploy.service.multitenant.lb.LBService;
+import org.apache.stratos.manager.deploy.service.multitenant.lb.ServiceAwareLBService;
 import org.apache.stratos.manager.exception.*;
 import org.apache.stratos.manager.lb.category.*;
 import org.apache.stratos.manager.retriever.DataInsertionAndRetrievalManager;
@@ -185,7 +188,7 @@ public class ServiceDeploymentManager {
 //                                        if (!AutoscalerServiceClient.getServiceClient().checkDefaultLBExistenceAgainstPolicy(deploymentPolicyName)) {
 //
 //                                            // if lb cluster doesn't exist
-//                                            lbService = new MultiTenantLBService(lbCartridgeType,
+//                                            lbService = new LBService(lbCartridgeType,
 //                                                    lbCartridgeInfo.getDefaultAutoscalingPolicy(),
 //                                                    deploymentPolicyName, tenantId,
 //                                                    lbCartridgeInfo,
@@ -261,7 +264,7 @@ public class ServiceDeploymentManager {
 //                                        lbCartridgeInfo.addProperties(property);
 //                                        lbCartridgeInfo.addProperties(loadBalancedServiceTypeProperty);
 //
-//                                        lbService = new MultiTenantLBService(lbCartridgeType,
+//                                        lbService = new LBService(lbCartridgeType,
 //                                                lbCartridgeInfo.getDefaultAutoscalingPolicy(),
 //                                                deploymentPolicyName, tenantId,
 //                                                lbCartridgeInfo,
@@ -319,9 +322,11 @@ public class ServiceDeploymentManager {
         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]));
+        if (lbDataCtxt != null) {
+            if (lbDataCtxt.getLoadBalancedServiceProperties() != null && !lbDataCtxt.getLoadBalancedServiceProperties().isEmpty()) {
+                serviceClusterProperties = new Properties();
+                serviceClusterProperties.setProperties(lbDataCtxt.getLoadBalancedServiceProperties().toArray(new Property[0]));
+            }
         }
 
         // create
@@ -343,35 +348,37 @@ public class ServiceDeploymentManager {
             return;
         }
 
-        LoadBalancerCategory loadBalancerCategory = null;
+        LBService lbService = null;
 
         if (lbDataCtxt.getLbCategory().equals(Constants.EXISTING_LOAD_BALANCERS)) {
-            loadBalancerCategory = new ExistingLoadBalancerCategory();
+            lbService = new ExistingLBService(lbDataCtxt.getLbCartridgeInfo().getType(), lbDataCtxt.getAutoscalePolicy(),
+                    lbDataCtxt.getDeploymentPolicy(), -1234, lbDataCtxt.getLbCartridgeInfo(),
+                    tenantRange);
 
         } else if (lbDataCtxt.getLbCategory().equals(Constants.DEFAULT_LOAD_BALANCER)) {
-            loadBalancerCategory = new DefaultLoadBalancerCategory();
+            lbService = new DefaultLBService(lbDataCtxt.getLbCartridgeInfo().getType(), lbDataCtxt.getAutoscalePolicy(),
+                    lbDataCtxt.getDeploymentPolicy(), -1234, lbDataCtxt.getLbCartridgeInfo(),
+                    tenantRange);
 
         } else if (lbDataCtxt.getLbCategory().equals(Constants.SERVICE_AWARE_LOAD_BALANCER)) {
-            loadBalancerCategory = new ServiceLevelLoadBalancerCategory();
+            lbService = new ServiceAwareLBService(lbDataCtxt.getLbCartridgeInfo().getType(), lbDataCtxt.getAutoscalePolicy(),
+                    lbDataCtxt.getDeploymentPolicy(), -1234, lbDataCtxt.getLbCartridgeInfo(),
+                    tenantRange);
         }
 
-        if (loadBalancerCategory == null) {
+        if (lbService == null) {
             throw new ADCException("The given Load Balancer category " + lbDataCtxt.getLbCategory() + " not found");
         }
 
         // Set the load balanced service type
-        loadBalancerCategory.setLoadBalancedServiceType(loadBalancedService);
+        lbService.setLoadBalancedServiceType(loadBalancedService);
 
         // Set if the load balanced service is multi tenant or not
-        loadBalancerCategory.setLoadBalancedServiceMultiTenant(true); // TODO --- temp hack
+        //lbService.setLoadBalancedServiceMultiTenant(true); // TODO --- temp hack
 
         // set the relevant deployment policy
-        log.info(" ******* Setting Deployment Policy name : ------>  " + lbDataCtxt.getDeploymentPolicy());
-        loadBalancerCategory.setDeploymentPolicyName(lbDataCtxt.getDeploymentPolicy());
-
-        Service lbService = new MultiTenantLBService(lbDataCtxt.getLbCartridgeInfo().getType(), lbDataCtxt.getAutoscalePolicy(),
-                lbDataCtxt.getDeploymentPolicy(), -1234, lbDataCtxt.getLbCartridgeInfo(),
-                tenantRange, loadBalancerCategory);
+        //log.info(" ******* Setting Deployment Policy name : ------>  " + lbDataCtxt.getDeploymentPolicy());
+        //loadBalancerCategory.setDeploymentPolicyName(lbDataCtxt.getDeploymentPolicy());
 
         Properties lbProperties = null;
         if (lbDataCtxt.getLbProperperties() != null && !lbDataCtxt.getLbProperperties().isEmpty())  {
@@ -383,7 +390,9 @@ public class ServiceDeploymentManager {
         lbService.create();
 
         // add LB category to the payload
-        lbService.getPayloadData().add(CartridgeConstants.LB_CATEGORY, lbDataCtxt.getLbCategory());
+        if (lbService.getPayloadData() != null) {
+            lbService.getPayloadData().add(CartridgeConstants.LB_CATEGORY, lbDataCtxt.getLbCategory());
+        }
 
         // delpoy
         lbService.deploy(lbProperties);

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/DefaultLBService.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/DefaultLBService.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/DefaultLBService.java
new file mode 100644
index 0000000..580186e
--- /dev/null
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/DefaultLBService.java
@@ -0,0 +1,110 @@
+/*
+ * 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.deploy.service.multitenant.lb;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.stub.pojo.CartridgeInfo;
+import org.apache.stratos.cloud.controller.stub.pojo.ClusterContext;
+import org.apache.stratos.cloud.controller.stub.pojo.Properties;
+import org.apache.stratos.manager.client.AutoscalerServiceClient;
+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.UnregisteredCartridgeException;
+import org.apache.stratos.manager.payload.PayloadData;
+import org.apache.stratos.manager.repository.Repository;
+import org.apache.stratos.manager.subscriber.Subscriber;
+
+import java.rmi.RemoteException;
+import java.util.Map;
+
+public class DefaultLBService extends LBService {
+
+    private static Log log = LogFactory.getLog(DefaultLBService.class);
+    private boolean defaultLBServiceExists = false;
+
+    public DefaultLBService (String type, String autoscalingPolicyName, String deploymentPolicyName, int tenantId,
+                            CartridgeInfo cartridgeInfo, String tenantRange) {
+
+        super(type, autoscalingPolicyName, deploymentPolicyName, tenantId, cartridgeInfo, tenantRange);
+    }
+
+    public PayloadData create(String alias, Cluster cluster, Subscriber subscriber, Repository repository, CartridgeInfo cartridgeInfo,
+                              String subscriptionKey, Map<String, String> customPayloadEntries)
+            throws ADCException, AlreadySubscribedException {
+
+        // call the relevant method to get the cluster id, using deployment policy
+        String clusterId = null;
+        try {
+            clusterId = AutoscalerServiceClient.getServiceClient().getDefaultLBClusterId(getDeploymentPolicyName());
+        } catch (Exception e) {
+            log.error("Error occurred in retrieving default LB cluster id" + e.getMessage());
+            throw new ADCException(e);
+        }
+
+        if (clusterId != null) {
+            //set the cluster id to Cluster object
+            cluster.setClusterDomain(clusterId);
+            if (log.isDebugEnabled()) {
+                log.debug("Set existing default LB cluster id " + clusterId);
+            }
+            defaultLBServiceExists = true;
+
+            //get the hostname for this cluster and set it
+            ClusterContext clusterContext;
+            try {
+                clusterContext = CloudControllerServiceClient.getServiceClient().getClusterContext(clusterId);
+
+            } catch (RemoteException e) {
+                log.error("Error occurred in retrieving Cluster Context for default LB ", e);
+                throw new ADCException(e);
+            }
+
+            if (clusterContext != null) {
+                cluster.setHostName(clusterContext.getHostName());
+                if (log.isDebugEnabled()) {
+                    log.debug("Set existing default LB hostname " + clusterContext.getHostName());
+                }
+            }
+
+            return null;
+
+        } else {
+            // set cluster domain
+            cluster.setClusterDomain(generateClusterId(null, cartridgeInfo.getType()));
+            // set hostname
+            cluster.setHostName(generateHostName(null, cartridgeInfo.getHostName()));
+
+            return createPayload(cartridgeInfo, subscriptionKey, subscriber, cluster, repository, alias, customPayloadEntries);
+        }
+    }
+
+    public void register(CartridgeInfo cartridgeInfo, Cluster cluster, PayloadData payloadData, String autoscalePolicyName, String deploymentPolicyName, Properties properties) throws ADCException, UnregisteredCartridgeException {
+
+        //log.info("Register service with payload data ["+payloadData+"] ");
+        if (!defaultLBServiceExists) {
+            super.register(cartridgeInfo, cluster, payloadData, autoscalePolicyName, deploymentPolicyName, properties);
+        }else {
+            log.info("Default LB already exists for deployment policy: " + getDeploymentPolicyName());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/ExistingLBService.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/ExistingLBService.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/ExistingLBService.java
new file mode 100644
index 0000000..5475e42
--- /dev/null
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/ExistingLBService.java
@@ -0,0 +1,52 @@
+/*
+ * 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.deploy.service.multitenant.lb;
+
+import org.apache.stratos.cloud.controller.stub.pojo.CartridgeInfo;
+import org.apache.stratos.cloud.controller.stub.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.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 ExistingLBService extends LBService {
+
+    public ExistingLBService(String type, String autoscalingPolicyName, String deploymentPolicyName, int tenantId, CartridgeInfo cartridgeInfo, String tenantRange) {
+        super(type, autoscalingPolicyName, deploymentPolicyName, tenantId, cartridgeInfo, tenantRange);
+    }
+
+    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(CartridgeInfo cartridgeInfo, Cluster cluster, PayloadData payloadData, String autoscalePolicyName, String deploymentPolicyName, Properties properties) throws ADCException, UnregisteredCartridgeException {
+
+        // TODO
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/LBService.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/LBService.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/LBService.java
new file mode 100644
index 0000000..52c33d3
--- /dev/null
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/LBService.java
@@ -0,0 +1,69 @@
+/*
+ * 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.deploy.service.multitenant.lb;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.stub.pojo.CartridgeInfo;
+import org.apache.stratos.cloud.controller.stub.pojo.Properties;
+import org.apache.stratos.manager.deploy.service.Service;
+import org.apache.stratos.manager.exception.ADCException;
+import org.apache.stratos.manager.exception.AlreadySubscribedException;
+import org.apache.stratos.manager.exception.UnregisteredCartridgeException;
+import org.apache.stratos.manager.lb.category.LoadBalancerCategory;
+
+public class LBService extends Service {
+
+    private static Log log = LogFactory.getLog(LBService.class);
+
+    private String loadBalancedServiceType;
+
+    public LBService(String type, String autoscalingPolicyName, String deploymentPolicyName, int tenantId,
+                     CartridgeInfo cartridgeInfo, String tenantRange) {
+
+        super(type, autoscalingPolicyName, deploymentPolicyName, tenantId, cartridgeInfo, tenantRange);
+    }
+
+    public void create () throws ADCException {
+
+        try {
+            setPayloadData(create(null, getCluster(), null, null, getCartridgeInfo(), getSubscriptionKey(), null));
+
+        } catch (AlreadySubscribedException e) {
+            throw new ADCException(e);
+        }
+    }
+
+    @Override
+    public void deploy(Properties properties) throws ADCException, UnregisteredCartridgeException {
+
+        //register the service
+        register(getCartridgeInfo(), getCluster(), getPayloadData(), getAutoscalingPolicyName(), getDeploymentPolicyName(),
+                properties);
+    }
+
+    public String getLoadBalancedServiceType() {
+        return loadBalancedServiceType;
+    }
+
+    public void setLoadBalancedServiceType(String loadBalancedServiceType) {
+        this.loadBalancedServiceType = loadBalancedServiceType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/ServiceAwareLBService.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/ServiceAwareLBService.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/ServiceAwareLBService.java
new file mode 100644
index 0000000..282cbf3
--- /dev/null
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/deploy/service/multitenant/lb/ServiceAwareLBService.java
@@ -0,0 +1,137 @@
+/*
+ * 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.deploy.service.multitenant.lb;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.stub.pojo.CartridgeInfo;
+import org.apache.stratos.cloud.controller.stub.pojo.ClusterContext;
+import org.apache.stratos.cloud.controller.stub.pojo.Properties;
+import org.apache.stratos.manager.client.AutoscalerServiceClient;
+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.UnregisteredCartridgeException;
+import org.apache.stratos.manager.payload.PayloadData;
+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.CartridgeConstants;
+
+import java.rmi.RemoteException;
+import java.util.Map;
+
+public class ServiceAwareLBService extends LBService {
+
+    public ServiceAwareLBService(String type, String autoscalingPolicyName, String deploymentPolicyName, int tenantId,
+                                 CartridgeInfo cartridgeInfo, String tenantRange) {
+
+        super(type, autoscalingPolicyName, deploymentPolicyName, tenantId, cartridgeInfo, tenantRange);
+    }
+
+    private static Log log = LogFactory.getLog(ServiceAwareLBService.class);
+
+    private boolean serviceAwareLBExists;
+
+    public PayloadData create (String alias, Cluster cluster, Subscriber subscriber, Repository repository, CartridgeInfo cartridgeInfo,
+                               String subscriptionKey, Map<String, String> customPayloadEntries) throws ADCException, AlreadySubscribedException {
+
+        // call the relevant method to get the cluster id, using deployment policy and type
+        String clusterId = null;
+
+        try {
+            clusterId = AutoscalerServiceClient.getServiceClient().getServiceLBClusterId(getLoadBalancedServiceType(), getDeploymentPolicyName());
+
+        } catch (Exception e) {
+            log.error("Error occurred in retrieving Service LB cluster id" + e.getMessage());
+            throw new ADCException(e);
+        }
+
+        if (clusterId != null) {
+
+            //set the cluster id to Cluster object
+            cluster.setClusterDomain(clusterId);
+            if (log.isDebugEnabled()) {
+                log.debug("Set existing Service LB cluster id " + clusterId);
+            }
+            serviceAwareLBExists = true;
+
+            //get the hostname for this cluster and set it
+            ClusterContext clusterContext;
+            try {
+                clusterContext = CloudControllerServiceClient.getServiceClient().getClusterContext(clusterId);
+
+            } catch (RemoteException e) {
+                log.error("Error occurred in retrieving Cluster Context for Service LB ", e);
+                throw new ADCException(e);
+            }
+
+            if (clusterContext != null) {
+                cluster.setHostName(clusterContext.getHostName());
+                if (log.isDebugEnabled()) {
+                    log.debug("Set existing Service LB hostname " + clusterContext.getHostName());
+                }
+            }
+
+            return null;
+
+        } else {
+
+            // set cluster domain
+            cluster.setClusterDomain(generateClusterId(getLoadBalancedServiceType(), cartridgeInfo.getType()));
+            // set hostname
+            cluster.setHostName(generateHostName(getLoadBalancedServiceType(), cartridgeInfo.getHostName()));
+
+            PayloadData serviceLevelLbPayloadData = createPayload(cartridgeInfo, subscriptionKey, subscriber, cluster,
+                    repository, alias, customPayloadEntries);
+
+            // add payload entry for load balanced service type
+            serviceLevelLbPayloadData.add(CartridgeConstants.LOAD_BALANCED_SERVICE_TYPE, getLoadBalancedServiceType());
+            return serviceLevelLbPayloadData;
+        }
+    }
+
+    protected String generateClusterId (String loadBalancedServiceType, String cartridgeType) {
+
+        String clusterId = cartridgeType + "." + loadBalancedServiceType + "." + getCartridgeInfo().getHostName() + ".domain";
+        // limit the cartridge alias to 30 characters in length
+        if (clusterId.length() > 30) {
+            clusterId = CartridgeSubscriptionUtils.limitLengthOfString(clusterId, 30);
+        }
+
+        return clusterId;
+    }
+
+    protected String generateHostName (String loadBalancedServiceType, String cartridgeDefinitionHostName) {
+
+        return getCartridgeInfo().getType() + "." + loadBalancedServiceType + "." + cartridgeDefinitionHostName;
+    }
+
+    public void register(CartridgeInfo cartridgeInfo, Cluster cluster, PayloadData payloadData, String autoscalePolicyName, String deploymentPolicyName, Properties properties) throws ADCException, UnregisteredCartridgeException {
+
+        if (!serviceAwareLBExists) {
+            super.register(cartridgeInfo, cluster, payloadData, autoscalePolicyName, deploymentPolicyName, properties);
+
+        }else {
+            log.info("Service Aware LB already exists for cartridge type: " + getLoadBalancedServiceType() + ", deployment policy: " + getDeploymentPolicyName());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 e49dbde..8470cb5 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
@@ -89,20 +89,19 @@ public class DefaultLoadBalancerCategory extends LoadBalancerCategory {
             // set hostname
             cluster.setHostName(generateHostName(alias, cartridgeInfo.getHostName()));
         
-        return createPayload(cartridgeInfo, subscriptionKey, subscriber,
-                cluster, repository, alias, customPayloadEntries);
+            return createPayload(cartridgeInfo, subscriptionKey, subscriber, cluster, repository, alias, customPayloadEntries);
         }
     }
 
     public void register(CartridgeInfo cartridgeInfo, Cluster cluster, PayloadData payloadData, String autoscalePolicyName, String deploymentPolicyName, Properties properties) throws ADCException, UnregisteredCartridgeException {
-    	log.info("Register service with payload data ["+payloadData+"] ");
+    	//log.info("Register service with payload data ["+payloadData+"] ");
         if (!isDefaultLBExists()) {
-        	if(payloadData != null) {
-        		log.info("Payload: " + payloadData.getCompletePayloadData().toString());
-        	}
+        	//if(payloadData != null) {
+        		//log.info("Payload: " + payloadData.getCompletePayloadData().toString());
+        	//}
             super.register(cartridgeInfo, cluster, payloadData, autoscalePolicyName, deploymentPolicyName, properties);
         }else {
-        	log.info(" Default LB exists... Not registering...");
+            log.info("Default LB already exists for deployment policy: " + getDeploymentPolicyName());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 fc47261..131b4dc 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
@@ -106,9 +106,9 @@ public class ServiceLevelLoadBalancerCategory extends LoadBalancerCategory {
 
         if (!serviceLbExists) {
 
-            if(payloadData != null) {
-                log.info("Payload: " + payloadData.getCompletePayloadData().toString());
-            }
+           // if(payloadData != null) {
+              //  log.info("Payload: " + payloadData.getCompletePayloadData().toString());
+           // }
 
             super.register(cartridgeInfo, cluster, payloadData, autoscalePolicyName, deploymentPolicyName, properties);
         }else {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 e7058f5..ce04409 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,6 +21,7 @@ package org.apache.stratos.manager.manager;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.openjpa.util.java$util$ArrayList$proxy;
 import org.apache.stratos.cloud.controller.stub.CloudControllerServiceUnregisteredCartridgeExceptionException;
 import org.apache.stratos.cloud.controller.stub.pojo.CartridgeInfo;
 import org.apache.stratos.cloud.controller.stub.pojo.LoadbalancerConfig;
@@ -28,8 +29,10 @@ import org.apache.stratos.cloud.controller.stub.pojo.Properties;
 import org.apache.stratos.cloud.controller.stub.pojo.Property;
 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;
@@ -37,6 +40,7 @@ import org.apache.stratos.manager.subscriber.Subscriber;
 import org.apache.stratos.manager.subscription.CartridgeSubscription;
 import org.apache.stratos.manager.subscription.PersistenceContext;
 import org.apache.stratos.manager.subscription.SubscriptionData;
+import org.apache.stratos.manager.subscription.SubscriptionDomain;
 import org.apache.stratos.manager.subscription.factory.CartridgeSubscriptionFactory;
 import org.apache.stratos.manager.subscription.tenancy.SubscriptionMultiTenantBehaviour;
 import org.apache.stratos.manager.subscription.tenancy.SubscriptionSingleTenantBehaviour;
@@ -46,14 +50,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.
@@ -290,25 +297,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);
@@ -375,13 +421,154 @@ 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);
 
         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().cacheAndUpdateSubscription(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 {
+
+        CartridgeSubscription cartridgeSubscription;
+        try {
+            cartridgeSubscription = getCartridgeSubscription(tenantId, subscriptionAlias);
+            if(cartridgeSubscription == null) {
+                throw new ADCException("Cartridge subscription not found");
+            }
+            cartridgeSubscription.removeSubscriptionDomain(domainName);
+            new DataInsertionAndRetrievalManager().cacheAndUpdateSubscription(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()) {
@@ -430,8 +617,11 @@ 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


[02/14] Clustering changes for stratos

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml b/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml
index fbb8b10..cd10030 100644
--- a/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml
+++ b/components/org.apache.stratos.rest.endpoint/src/main/webapp/stratos/WEB-INF/cxf-servlet.xml
@@ -31,6 +31,8 @@
         </jaxrs:serviceBeans>
 
         <jaxrs:providers>
+            <ref bean="throwableExceptionHandler"/>
+			<ref bean="genericExceptionHandler"/>
             <ref bean="jsonProvider"/>
             <ref bean="exceptionHandler"/>
             <ref bean="basicAuthenticationFilter"/>
@@ -46,6 +48,8 @@
         <property name="securedObject" ref="stratosRestEndpointBean"/>
     </bean>
     <bean id="exceptionHandler" class="org.apache.stratos.rest.endpoint.handlers.CustomExceptionMapper"/>
+    <bean id="genericExceptionHandler" class="org.apache.stratos.rest.endpoint.handlers.GenericExceptionMapper"/>
+    <bean id="throwableExceptionHandler" class="org.apache.stratos.rest.endpoint.handlers.CustomThrowableExceptionMapper"/>
     <!--The below config enables OAuth based authentication/authorization for REST API-->
     <bean id="OAuthFilter" class="org.apache.stratos.rest.endpoint.handlers.OAuthHandler">
         <property name="password" value="admin"/>

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/assembly/bin.xml
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/assembly/bin.xml b/products/cartridge-agent/modules/distribution/src/main/assembly/bin.xml
index 3662489..3171262 100644
--- a/products/cartridge-agent/modules/distribution/src/main/assembly/bin.xml
+++ b/products/cartridge-agent/modules/distribution/src/main/assembly/bin.xml
@@ -51,7 +51,16 @@
                 <include>instance-started.sh</include>
                 <include>start-servers.sh</include>
                 <include>clean.sh</include>
-                <include>mount_volumes.sh</include>
+                <include>mount-volumes.sh</include>
+		<include>member-activated.sh</include>
+                <include>member-started.sh</include>
+                <include>member-terminated.sh</include>
+                <include>member-suspended.sh</include>
+                <include>complete-topology.sh</include>
+                <include>complete-tenant.sh</include>
+                <include>subscription-domain-added.sh</include>
+                <include>subscription-domain-removed.sh</include>
+                <include>artifacts-copy.sh</include>
             </includes>
         </fileSet>
         <fileSet>

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/bin/stratos.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/bin/stratos.sh b/products/cartridge-agent/modules/distribution/src/main/bin/stratos.sh
index db86d7d..0c24f39 100644
--- a/products/cartridge-agent/modules/distribution/src/main/bin/stratos.sh
+++ b/products/cartridge-agent/modules/distribution/src/main/bin/stratos.sh
@@ -31,20 +31,43 @@ properties="-Dmb.ip=MB-IP
             -Dthrift.receiver.port=CEP-PORT
             -Djndi.properties.template.file.path=${script_path}/../conf/templates/jndi.properties.template
             -Djndi.properties.dir=${script_path}/../conf
-            -Dlog4j.properties.file.path=${script_path}/../conf/log4j.properties
+            -Dlog4j.configuration=file://${script_path}/../conf/log4j.properties
             -Dparam.file.path=${script_path}/../payload/launch-params
             -Dextensions.dir=${script_path}/../extensions
             -Dcep.stats.publisher.enabled=true
+            -Dlb.private.ip=
+            -Dlb.public.ip=
             -Djavax.net.ssl.trustStore=CERT-TRUSTSTORE
             -Djavax.net.ssl.trustStorePassword=TRUSTSTORE-PASSWORD
 	    -Denable.artifact.update=true
-	    -Dartifact.update.interval=10
-	    -Denable.data.publisher=ENABLE-DATA-PUBLISHER
+            -Dauto.commit=false
+            -Dauto.checkout=true
+            -Dartifact.update.interval=15
+            -Denable.data.publisher=ENABLE-DATA-PUBLISHER
             -Dmonitoring.server.ip=MONITORING-SERVER-IP
 	    -Dmonitoring.server.port=MONITORING-SERVER-PORT
 	    -Dmonitoring.server.secure.port=MONITORING-SERVER-SECURE-PORT
 	    -Dmonitoring.server.admin.username=MONITORING-SERVER-ADMIN-USERNAME
-	    -Dmonitoring.server.admin.password=MONITORING-SERVER-ADMIN-PASSWORD"
+	    -Dmonitoring.server.admin.password=MONITORING-SERVER-ADMIN-PASSWORD
+	    -Dlog.file.paths=LOG_FILE_PATHS
+	    -DAPP_PATH=APP_PATH
+            -Dsuper.tenant.repository.path=/repository/deployment/server/
+            -Dtenant.repository.path=/repository/tenants/
+	    -Dextension.instance.started=instance-started.sh
+            -Dextension.start.servers=start-servers.sh
+            -Dextension.instance.activated=instance-activated.sh
+            -Dextension.artifacts.updated=artifacts-updated.sh
+            -Dextension.clean=clean.sh
+            -Dextension.mount.volumes=mount_volumes.sh
+            -Dextension.member.started=member-started.sh
+            -Dextension.member.activated=member-activated.sh
+            -Dextension.member.suspended=member-suspended.sh
+            -Dextension.member.terminated=member-terminated.sh
+            -Dextension.complete.topology=complete-topology.sh
+            -Dextension.complete.tenant=complete-tenant.sh
+            -Dextension.subscription.domain.added=subscription-domain-added.sh
+            -Dextension.subscription.domain.removed=subscription-domain-removed.sh
+            -Dextension.artifacts.copy=artifacts-copy.sh"
 
 # Uncomment below line to enable remote debugging
 #debug="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/conf/log4j.properties
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/conf/log4j.properties b/products/cartridge-agent/modules/distribution/src/main/conf/log4j.properties
index 890a4db..178aa9f 100644
--- a/products/cartridge-agent/modules/distribution/src/main/conf/log4j.properties
+++ b/products/cartridge-agent/modules/distribution/src/main/conf/log4j.properties
@@ -35,5 +35,7 @@ log4j.appender.CONSOLE_APPENDER.layout=org.apache.log4j.PatternLayout
 log4j.appender.CONSOLE_APPENDER.layout.ConversionPattern=[%d{ISO8601}] %5p - [%c{1}] %m%n
 
 log4j.logger.org.apache.stratos.cartridge.agent=INFO
+log4j.logger.org.apache.stratos.cartridge.agent.statistics.publisher=ERROR
 log4j.logger.org.apache.stratos.messaging=INFO
-log4j.logger.org.wso2.andes.client=ERROR
\ No newline at end of file
+log4j.logger.org.wso2.andes.client=ERROR
+log4j.logger.org.apache.activemq.jndi.ActiveMQInitialContextFactory=ERROR
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/conf/templates/jndi.properties.template
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/conf/templates/jndi.properties.template b/products/cartridge-agent/modules/distribution/src/main/conf/templates/jndi.properties.template
index c6b062a..b5fed16 100644
--- a/products/cartridge-agent/modules/distribution/src/main/conf/templates/jndi.properties.template
+++ b/products/cartridge-agent/modules/distribution/src/main/conf/templates/jndi.properties.template
@@ -20,6 +20,6 @@
 # Please use loadbalancer.conf for updating mb-ip, mb-port and templates/jndi.properties.template
 # file for updating other configurations.
 #
-connectionfactoryName=topicConnectionfactory
-connectionfactory.topicConnectionfactory=amqp://admin:admin@carbon/carbon?brokerlist='tcp://$mb_ip:$mb_port'
-java.naming.factory.initial=org.wso2.andes.jndi.PropertiesFileInitialContextFactory
+connectionfactoryName=TopicConnectionFactory
+java.naming.provider.url=tcp://$mb_ip:$mb_port
+java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-copy.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-copy.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-copy.sh
new file mode 100644
index 0000000..5cad830
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-copy.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed once the update artifacts
+# event is received and they are copied to the given path.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+cp -rf $1* $2
+echo "Artifacts Copied" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-updated.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-updated.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-updated.sh
index 7f112b1..15d5591 100644
--- a/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-updated.sh
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/artifacts-updated.sh
@@ -25,4 +25,4 @@
 #
 
 log=/var/log/apache-stratos/cartridge-agent-extensions.log
-echo "Artifacts updated" | tee -a $log
\ No newline at end of file
+echo `date`": Artifacts Updated Event" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/clean.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/clean.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/clean.sh
index 3b87d36..c62ad35 100644
--- a/products/cartridge-agent/modules/distribution/src/main/extensions/clean.sh
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/clean.sh
@@ -25,4 +25,4 @@
 #
 
 log=/var/log/apache-stratos/cartridge-agent-extensions.log
-echo "Cleaning the cartridge" | tee -a $log
\ No newline at end of file
+echo `date`": Cleaning the cartridge" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/complete-tenant.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/complete-tenant.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/complete-tenant.sh
new file mode 100644
index 0000000..2586474
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/complete-tenant.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed when complete tenant
+# event is received.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+echo `date`": Complete Tenant Event: " | tee -a $log
+echo "Member List: ${STRATOS_MEMBER_LIST_JSON}" | tee -a $log
+echo "Tenant List: ${STRATOS_TENANT_LIST_JSON}" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/complete-topology.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/complete-topology.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/complete-topology.sh
new file mode 100644
index 0000000..ea2e941
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/complete-topology.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed when complete topology 
+# event is received.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+echo `date`": Complete Topology Event: " | tee -a $log
+echo "LB IP: ${STRATOS_LB_IP}" | tee -a $log
+echo "LB PUBLIC IP: $STRATOS_LB_PUBLIC_IP}" | tee -a $log
+echo "STRATOS_PARAM_FILE_PATH: ${STRATOS_PARAM_FILE_PATH}"
+echo "Member List: ${STRATOS_MEMBER_LIST_JSON}" | tee -a $log
+echo "Complete Topology: ${STRATOS_TOPOLOGY_JSON}" | tee -a $log
+echo "Members in LB: ${STRATOS_MEMBERS_IN_LB_JSON}" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/instance-activated.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/instance-activated.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/instance-activated.sh
index c892ca7..f5d60e8 100644
--- a/products/cartridge-agent/modules/distribution/src/main/extensions/instance-activated.sh
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/instance-activated.sh
@@ -25,4 +25,4 @@
 #
 
 log=/var/log/apache-stratos/cartridge-agent-extensions.log
-echo "Instance activated" | tee -a $log
\ No newline at end of file
+echo `date`": Instance activated" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/instance-started.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/instance-started.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/instance-started.sh
index b6c9105..7b5aa6a 100644
--- a/products/cartridge-agent/modules/distribution/src/main/extensions/instance-started.sh
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/instance-started.sh
@@ -24,4 +24,4 @@
 #
 
 log=/var/log/apache-stratos/cartridge-agent-extensions.log
-echo "Instance started" | tee -a $log
\ No newline at end of file
+echo `date`": Instance Started Event: " | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/member-activated.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/member-activated.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/member-activated.sh
new file mode 100644
index 0000000..3bf0b10
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/member-activated.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed when member activated
+# event is received.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+OUTPUT=`date`": Member Activated Event: "
+OUTPUT="$OUTPUT MEMBER_ID: ${STRATOS_MEMBER_ID}, "
+OUTPUT="$OUTPUT MEMBER_IP: ${STRATOS_MEMBER_IP}, "
+OUTPUT="$OUTPUT CLUSTER_ID: ${STRATOS_CLUSTER_ID}, "
+OUTPUT="$OUTPUT LB_CLUSTER_ID: ${STRATOS_LB_CLUSTER_ID}, "
+OUTPUT="$OUTPUT NETWORK_PARTITION_ID: ${STRATOS_NETWORK_PARTITION_ID}, "
+OUTPUT="$OUTPUT SERVICE_NAME: ${STRATOS_SERVICE_NAME}, "
+OUTPUT="$OUTPUT PORTS: ${STRATOS_PORTS},"
+OUTPUT="$OUTPUT STRATOS_LB_IP: ${STRATOS_LB_IP},"
+OUTPUT="$OUTPUT STRATOS_LB_PUBLIC_IP: ${STRATOS_LB_PUBLIC_IP},"
+OUTPUT="$OUTPUT APP_PATH: ${APP_PATH},"
+OUTPUT="$OUTPUT STRATOS_PARAM_FILE_PATH: ${STRATOS_PARAM_FILE_PATH}"
+echo $OUTPUT | tee -a $log
+echo "Member List: ${STRATOS_MEMBER_LIST_JSON}" | tee -a $log
+echo "Topology: ${STRATOS_TOPOLOGY_JSON}" | tee -a $log
+echo "---------------" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/member-started.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/member-started.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/member-started.sh
new file mode 100644
index 0000000..29f45c3
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/member-started.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed when member suspended
+# event is received.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+OUTPUT=`date`": Member Started Event: "
+OUTPUT="$OUTPUT MEMBER_ID: ${STRATOS_MEMBER_ID}, "
+OUTPUT="$OUTPUT MEMBER_IP: ${STRATOS_MEMBER_IP}, "
+OUTPUT="$OUTPUT CLUSTER_ID: ${STRATOS_CLUSTER_ID}, "
+OUTPUT="$OUTPUT LB_CLUSTER_ID: ${STRATOS_LB_CLUSTER_ID}, "
+OUTPUT="$OUTPUT NETWORK_PARTITION_ID: ${STRATOS_NETWORK_PARTITION_ID}, "
+OUTPUT="$OUTPUT SERVICE_NAME: ${STRATOS_SERVICE_NAME}, "
+OUTPUT="$OUTPUT PORTS: ${STRATOS_PORTS},"
+OUTPUT="$OUTPUT STRATOS_LB_IP: ${STRATOS_LB_IP},"
+OUTPUT="$OUTPUT STRATOS_LB_PUBLIC_IP: ${STRATOS_LB_PUBLIC_IP},"
+OUTPUT="$OUTPUT APP_PATH: ${APP_PATH},"
+OUTPUT="$OUTPUT STRATOS_PARAM_FILE_PATH: ${STRATOS_PARAM_FILE_PATH}"
+echo $OUTPUT | tee -a $log
+echo "Member List: ${STRATOS_MEMBER_LIST_JSON}" | tee -a $log
+echo "Topology: ${STRATOS_TOPOLOGY_JSON}" | tee -a $log
+echo "---------------" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/member-suspended.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/member-suspended.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/member-suspended.sh
new file mode 100644
index 0000000..866aa0d
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/member-suspended.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed when member suspended
+# event is received.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+OUTPUT=`date`": Member Suspended Event: "
+OUTPUT="$OUTPUT MEMBER_ID: ${STRATOS_MEMBER_ID}, "
+OUTPUT="$OUTPUT MEMBER_IP: ${STRATOS_MEMBER_IP}, "
+OUTPUT="$OUTPUT CLUSTER_ID: ${STRATOS_CLUSTER_ID}, "
+OUTPUT="$OUTPUT LB_CLUSTER_ID: ${STRATOS_LB_CLUSTER_ID}, "
+OUTPUT="$OUTPUT NETWORK_PARTITION_ID: ${STRATOS_NETWORK_PARTITION_ID}, "
+OUTPUT="$OUTPUT SERVICE_NAME: ${STRATOS_SERVICE_NAME}, "
+OUTPUT="$OUTPUT PORTS: ${STRATOS_PORTS},"
+OUTPUT="$OUTPUT STRATOS_LB_IP: ${STRATOS_LB_IP},"
+OUTPUT="$OUTPUT STRATOS_LB_PUBLIC_IP: ${STRATOS_LB_PUBLIC_IP},"
+OUTPUT="$OUTPUT APP_PATH: ${APP_PATH},"
+OUTPUT="$OUTPUT STRATOS_PARAM_FILE_PATH: ${STRATOS_PARAM_FILE_PATH}"
+echo $OUTPUT | tee -a $log
+echo "Member List: ${STRATOS_MEMBER_LIST_JSON}" | tee -a $log
+echo "Topology: ${STRATOS_TOPOLOGY_JSON}" | tee -a $log
+echo "---------------" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/member-terminated.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/member-terminated.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/member-terminated.sh
new file mode 100644
index 0000000..89cedf6
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/member-terminated.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed when member terminated
+# event is received.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+OUTPUT=`date`": Member Terminated Event: "
+OUTPUT="$OUTPUT MEMBER_ID: ${STRATOS_MEMBER_ID}, "
+OUTPUT="$OUTPUT MEMBER_IP: ${STRATOS_MEMBER_IP}, "
+OUTPUT="$OUTPUT CLUSTER_ID: ${STRATOS_CLUSTER_ID}, "
+OUTPUT="$OUTPUT LB_CLUSTER_ID: ${STRATOS_LB_CLUSTER_ID}, "
+OUTPUT="$OUTPUT NETWORK_PARTITION_ID: ${STRATOS_NETWORK_PARTITION_ID}, "
+OUTPUT="$OUTPUT SERVICE_NAME: ${STRATOS_SERVICE_NAME}, "
+OUTPUT="$OUTPUT PORTS: ${STRATOS_PORTS},"
+OUTPUT="$OUTPUT STRATOS_LB_IP: ${STRATOS_LB_IP},"
+OUTPUT="$OUTPUT STRATOS_LB_PUBLIC_IP: ${STRATOS_LB_PUBLIC_IP},"
+OUTPUT="$OUTPUT APP_PATH: ${APP_PATH},"
+OUTPUT="$OUTPUT STRATOS_PARAM_FILE_PATH: ${STRATOS_PARAM_FILE_PATH}"
+echo $OUTPUT | tee -a $log
+echo "Member List: ${STRATOS_MEMBER_LIST_JSON}" | tee -a $log
+echo "Topology: ${STRATOS_TOPOLOGY_JSON}" | tee -a $log
+echo "---------------" | tee -a $log

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/mount-volumes.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/mount-volumes.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/mount-volumes.sh
new file mode 100755
index 0000000..2e649bd
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/mount-volumes.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed to mount volumes
+# to the instance.
+# --------------------------------------------------------------
+#
+
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+echo -e "Starting mounting volumes" 2>&1 | tee -a $log
+
+# $1  is passed from Cartridge Agent code.
+echo -e "launh param file location $1" | tee -a $log
+#source /opt/apache-stratos-cartridge-agent/launch.params
+PERSISTENCE_MAPPING=$1
+echo -e "Persistance mappings : $PERSISTENCE_MAPPING" 2>&1 | tee -a $log
+
+mount_volume(){
+
+        device=$1;
+        mount_point=$2;
+        echo "device $device"
+        echo "point  $mount_point"
+        # check if the volume has a file system
+        output=`sudo file -s $device`;
+        echo $output | tee -a $log
+
+        # this is the pattern of the output of file -s if the volume does not have a file system
+        # refer to http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-using-volumes.html
+        pattern="$device: data"
+
+        if [[ $output ==  $pattern ]]
+        then
+                echo -e "Volume is not formatted. So formating the device $device \n" | tee -a $log
+                sudo mkfs -t ext4 $device
+        fi
+
+        echo "Mounting  the device $device to the mount point $mount_point \n" | tee -a $log
+        device_mounted=$(mount | grep "$device")
+
+        if [ ! -d "$mount_point" ]
+        then
+              echo "creating the  mount point directory $mount_point since it does not exist." | tee -a $log
+              sudo mkdir $mount_point
+        fi
+
+        #mounting the device if it is not already mounted
+        if [ ! "$device_mounted" = "" ]
+        then
+              echo -e "Device $device is already mounted." | tee -a $log
+        else
+              sudo mount $device $mount_point
+        fi
+
+}
+
+IFS='|' read -ra ADDR <<< "${PERSISTENCE_MAPPING}"
+echo "${ADDR[@]}" | tee -a $log
+
+for i in "${!ADDR[@]}"; do
+        # expected PERSISTANCE_MAPPING format is device1|mountPoint1|device2|mountpoint2...
+        # so that even indexes are devices and odd indexes are mount points..
+        if (( $i  % 2 == 0 ))
+        then
+           mount_volume ${ADDR[$i]} ${ADDR[$i + 1]}
+        fi
+done
+

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/start-servers.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/start-servers.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/start-servers.sh
index 1bb3f84..d70a193 100644
--- a/products/cartridge-agent/modules/distribution/src/main/extensions/start-servers.sh
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/start-servers.sh
@@ -24,4 +24,16 @@
 #
 
 log=/var/log/apache-stratos/cartridge-agent-extensions.log
-echo "Starting servers" | tee -a $log
\ No newline at end of file
+if [[ -z $STRATOS_CLUSTERING ]]; then
+   echo `date`": Starting servers..." | tee -a $log
+else
+   echo `date`": Starting servers in clustering mode..." | tee -a $log
+fi
+
+echo "LB IP: ${STRATOS_LB_IP}" | tee -a $log
+echo "LB PUBLIC IP: $STRATOS_LB_PUBLIC_IP}" | tee -a $log
+echo "STRATOS_PARAM_FILE_PATH: ${STRATOS_PARAM_FILE_PATH}"
+echo "Member List: ${STRATOS_MEMBER_LIST_JSON}" | tee -a $log
+echo "Complete Topology: ${STRATOS_TOPOLOGY_JSON}" | tee -a $log
+echo "Members in LB: ${STRATOS_MEMBERS_IN_LB_JSON}" | tee -a $log
+echo "APP_PATH: ${APP_PATH}" | tee -a $log
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/subscription-domain-added.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/subscription-domain-added.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/subscription-domain-added.sh
new file mode 100644
index 0000000..f78a5db
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/subscription-domain-added.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed when subscription domain
+# added event is received.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+OUTPUT=`date`": Subscription Domain Added Event"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_SERVICE_NAME: ${STRATOS_SUBSCRIPTION_SERVICE_NAME},"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_DOMAIN_NAME: ${STRATOS_SUBSCRIPTION_DOMAIN_NAME},"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_TENANT_ID: ${STRATOS_SUBSCRIPTION_TENANT_ID},"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_TENANT_DOMAIN: $STRATOS_SUBSCRIPTION_TENANT_DOMAIN},"
+OUTPUT="$OUTPUT APP_PATH: ${APP_PATH},"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_APPLICATION_CONTEXT: ${STRATOS_SUBSCRIPTION_APPLICATION_CONTEXT}"
+echo $OUTPUT | tee -a $log
+
+curl -k -v -X POST -H "Content-Type:application/soap+xml;charset=UTF-8;action=urn:addWebAppToHost" -d "<?xml version=\"1.0\" encoding=\"UTF-8\"?><s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"><s:Body><p:addWebAppToHost xmlns:p=\"http://mapper.url.carbon.wso2.org\"><xs:hostName xmlns:xs=\"http://mapper.url.carbon.wso2.org\">$STRATOS_SUBSCRIPTION_DOMAIN_NAME</xs:hostName><xs:uri xmlns:xs=\"http://mapper.url.carbon.wso2.org\">/t/$STRATOS_SUBSCRIPTION_TENANT_DOMAIN/webapps/$STRATOS_SUBSCRIPTION_APPLICATION_CONTEXT/</xs:uri><xs:appType xmlns:xs=\"http://mapper.url.carbon.wso2.org\">webapp</xs:appType></p:addWebAppToHost></s:Body></s:Envelope>" https://localhost:9443/services/UrlMapperAdminService -u admin:admin

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/cartridge-agent/modules/distribution/src/main/extensions/subscription-domain-removed.sh
----------------------------------------------------------------------
diff --git a/products/cartridge-agent/modules/distribution/src/main/extensions/subscription-domain-removed.sh b/products/cartridge-agent/modules/distribution/src/main/extensions/subscription-domain-removed.sh
new file mode 100644
index 0000000..b007044
--- /dev/null
+++ b/products/cartridge-agent/modules/distribution/src/main/extensions/subscription-domain-removed.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# --------------------------------------------------------------
+#
+# 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.
+#
+# --------------------------------------------------------------
+# This extension script will be executed when subscription domain
+# removed event is received.
+# --------------------------------------------------------------
+#
+
+log=/var/log/apache-stratos/cartridge-agent-extensions.log
+OUTPUT=`date`": Subscription Domain Removed Event"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_SERVICE_NAME: ${STRATOS_SUBSCRIPTION_SERVICE_NAME},"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_DOMAIN_NAME: ${STRATOS_SUBSCRIPTION_DOMAIN_NAME},"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_TENANT_ID: ${STRATOS_SUBSCRIPTION_TENANT_ID},"
+OUTPUT="$OUTPUT APP_PATH: ${APP_PATH},"
+OUTPUT="$OUTPUT STRATOS_SUBSCRIPTION_TENANT_DOMAIN: $STRATOS_SUBSCRIPTION_TENANT_DOMAIN}"
+echo $OUTPUT | tee -a $log
+
+curl -k -v -X POST -H "Content-Type:application/soap+xml;charset=UTF-8;action=urn:deleteHost" -d "<?xml version=\"1.0\" encoding=\"UTF-8\"?><s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"><s:Body><p:deleteHost xmlns:p=\"http://mapper.url.carbon.wso2.org\"><xs:hostName xmlns:xs=\"http://mapper.url.carbon.wso2.org\">$STRATOS_SUBSCRIPTION_DOMAIN_NAME</xs:hostName></p:deleteHost></s:Body></s:Envelope>" https://localhost:9443/services/UrlMapperAdminService -u admin:admin

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/stratos/conf/tenant-mgt.xml
----------------------------------------------------------------------
diff --git a/products/stratos/conf/tenant-mgt.xml b/products/stratos/conf/tenant-mgt.xml
new file mode 100644
index 0000000..ddfe83a
--- /dev/null
+++ b/products/stratos/conf/tenant-mgt.xml
@@ -0,0 +1,42 @@
+<!--
+ ~ 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.
+ -->
+<TenantManagers>
+    <TenantManager class="org.wso2.carbon.user.core.tenant.JDBCTenantManager">
+        <Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder</Property>
+    </TenantManager>
+</TenantManagers>
+
+<!--If the product is using LDAP user store in MT mode, use following tenant manager.-->
+<!--TenantManager class="org.wso2.carbon.user.core.tenant.CommonHybridLDAPTenantManager">
+    <Property name="RootPartition">dc=wso2,dc=com</Property>
+    <Property name="OrganizationalObjectClass">organizationalUnit</Property>
+    <Property name="OrganizationalAttribute">ou</Property>
+    <Property name="OrganizationalSubContextObjectClass">organizationalUnit</Property>
+    <Property name="OrganizationalSubContextAttribute">ou</Property>
+</TenantManager-->
+<!--Following tenant manager is used by Identity Server (IS) as its default tenant manager.
+    IS will do token replacement when building the product. Therefore do not change the syntax.-->
+<!--TenantManager class="org.wso2.carbon.user.core.tenant.JDBCTenantManager">
+    <Property name="RootPartition">dc=wso2,dc=org</Property>
+    <Property name="OrganizationalObjectClass">organizationalUnit</Property>
+    <Property name="OrganizationalAttribute">ou</Property>
+    <Property name="OrganizationalSubContextObjectClass">organizationalUnit</Property>
+    <Property name="OrganizationalSubContextAttribute">ou</Property>
+</TenantManager-->
+

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/stratos/modules/distribution/src/assembly/bin.xml
----------------------------------------------------------------------
diff --git a/products/stratos/modules/distribution/src/assembly/bin.xml b/products/stratos/modules/distribution/src/assembly/bin.xml
index 6e1d991..b5c4798 100755
--- a/products/stratos/modules/distribution/src/assembly/bin.xml
+++ b/products/stratos/modules/distribution/src/assembly/bin.xml
@@ -39,17 +39,18 @@
                 <exclude>**/LICENSE.txt</exclude>
                 <exclude>**/NOTICE</exclude>
                 <exclude>**/release-notes.html</exclude>
- 		<exclude>**/launch.ini</exclude>
+ 		        <exclude>**/launch.ini</exclude>
                 <exclude>**/carbon.xml</exclude>
                 <exclude>**/README*</exclude>
                 <exclude>**/log4j.properties</exclude>
                 <exclude>**/repository/components/**</exclude>
-		<exclude>**/lib/endorsed/**</exclude>
+		        <exclude>**/lib/endorsed/**</exclude>
                 <exclude>**/dbscripts/mysql.sql</exclude>
                 <exclude>**/repository/conf/security/cipher-tool.properties</exclude>
                 <exclude>**/repository/conf/security/cipher-text.properties</exclude>
-		<exclude>**/repository/conf/axis2/axis2.xml</exclude>
-		<exclude>**/repository/conf/registry.xml</exclude>
+		        <exclude>**/repository/conf/axis2/axis2.xml</exclude>
+		        <exclude>**/repository/conf/registry.xml</exclude>
+
 		<exclude>**/repository/conf/log4j.properties</exclude>
   		<exclude>**/repository/conf/data-bridge/**</exclude>
             </excludes>
@@ -153,6 +154,7 @@
                 <exclude>**/datasources.properties</exclude>
                 <exclude>.svn</exclude>
                 <exclude>**/temp-artifacts/**</exclude>
+                <exclude>tenant-mgt.xml</exclude>
                 <exclude>email-bill-generated.xml</exclude>
                 <exclude>email-billing-notifications.xml</exclude>
                 <exclude>email-new-tenant-activation.xml</exclude>
@@ -168,6 +170,7 @@
 		<exclude>tenant-reg-agent.xml</exclude>
                 <exclude>features-dashboard.xml</exclude>
                 <exclude>**/data-bridge/**</exclude>
+
             </excludes>
         </fileSet>
         <fileSet>
@@ -835,6 +838,12 @@
 	    <destName>jaas.conf</destName>
             <filtered>true</filtered>
         </file>
+        <file>
+            <source>../../conf/tenant-mgt.xml</source>
+            <outputDirectory>${pom.artifactId}-${pom.version}/repository/conf</outputDirectory>
+            <filtered>true</filtered>
+            <fileMode>644</fileMode>
+        </file>
         <!--Application authenticators -->
         <file>
             <source>../../conf/application-authenticators.xml</source>

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/stratos/modules/distribution/src/main/conf/autoscaler.xml
----------------------------------------------------------------------
diff --git a/products/stratos/modules/distribution/src/main/conf/autoscaler.xml b/products/stratos/modules/distribution/src/main/conf/autoscaler.xml
index 18c44a2..c0c4eb9 100644
--- a/products/stratos/modules/distribution/src/main/conf/autoscaler.xml
+++ b/products/stratos/modules/distribution/src/main/conf/autoscaler.xml
@@ -41,5 +41,7 @@
 		<!-->member expiry timeout (time waited till activation) in ms<-->
 		<expiryTimeout>900000</expiryTimeout>
 	    </member>
+	    <!-- monitor task interval -->
+	    <monitorInterval>90000</monitorInterval>
 	</autoscaler>
 </configuration>

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/stratos/modules/distribution/src/main/conf/mincheck.drl
----------------------------------------------------------------------
diff --git a/products/stratos/modules/distribution/src/main/conf/mincheck.drl b/products/stratos/modules/distribution/src/main/conf/mincheck.drl
index b1c0f7c..ceeab48 100755
--- a/products/stratos/modules/distribution/src/main/conf/mincheck.drl
+++ b/products/stratos/modules/distribution/src/main/conf/mincheck.drl
@@ -48,6 +48,8 @@ global org.apache.stratos.messaging.domain.topology.Topology $topology;
 global java.util.Map partitionCtxts;
 global java.lang.String clusterId;
 global java.lang.String lbRef;
+global java.lang.Boolean isPrimary;
+global Integer primaryMemberCount;
 
 rule "Minimum Rule"
 dialect "mvel"
@@ -56,11 +58,14 @@ dialect "mvel"
            eval(log.debug("Running minimum rule: [network-partition] " + $ctxt.getNetworkPartitionId() + " [partition] " + $ctxt.getPartitionId()))
 	       eval(log.debug("[min-check] [network-partition] " + $ctxt.getNetworkPartitionId() + " [partition] " + $ctxt.getPartitionId() + " Non terminated member count: " + $ctxt.getNonTerminatedMemberCount()))
 	       eval(log.debug("[min-check] [network-partition] " + $ctxt.getNetworkPartitionId() + " [partition] " + $ctxt.getPartitionId() + " Minimum member count: " + $ctxt.getMinimumMemberCount()))
-	       eval($ctxt.getNonTerminatedMemberCount() < $ctxt.getMinimumMemberCount())
-
+	       eval ( (isPrimary && (primaryMemberCount < $ctxt.getMinimumMemberCount() )) || ( !isPrimary && ($ctxt.getNonTerminatedMemberCount() < $ctxt.getMinimumMemberCount() )) )
        then
-	       $delegator.delegateSpawn($ctxt, clusterId, lbRef);
-	       
+           if (isPrimary){
+              log.debug("[min-check] true  [primary] true   [primary member count] " + primaryMemberCount);
+           } else{
+              log.debug("[min-check] true  [primary] false");
+           }
+	       $delegator.delegateSpawn($ctxt, clusterId, lbRef, isPrimary);
 end
 
 rule "Terminate Obsoleted Instances"

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/stratos/modules/distribution/src/main/conf/scaling.drl
----------------------------------------------------------------------
diff --git a/products/stratos/modules/distribution/src/main/conf/scaling.drl b/products/stratos/modules/distribution/src/main/conf/scaling.drl
index c192cd2..b3f6466 100644
--- a/products/stratos/modules/distribution/src/main/conf/scaling.drl
+++ b/products/stratos/modules/distribution/src/main/conf/scaling.drl
@@ -53,6 +53,8 @@ global java.lang.String lbRef;
 global java.lang.Boolean rifReset;
 global java.lang.Boolean mcReset;
 global java.lang.Boolean laReset;
+global java.lang.Boolean isPrimary;
+global java.util.List primaryMembers;
 
 rule "Scaling Rule"
 dialect "mvel"
@@ -109,7 +111,7 @@ dialect "mvel"
             if(partition != null){
                 log.info("[scale-up] Partition available, hence trying to spawn an instance to scale up!" );
                 log.debug("[scale-up] " + " [partition] " + partition.getId() + " [cluster] " + clusterId );
-                $delegator.delegateSpawn($networkPartitionContext.getPartitionCtxt(partition.getId()), clusterId, lbRef);
+                $delegator.delegateSpawn($networkPartitionContext.getPartitionCtxt(partition.getId()), clusterId, lbRef, isPrimary);
             }
         } else if(scaleDown){
 
@@ -126,8 +128,15 @@ dialect "mvel"
                     log.debug("[scale-down] " + " [partition] " + partition.getId() + " [cluster] " + clusterId);
                     partitionContext = $networkPartitionContext.getPartitionCtxt(partition.getId());
 
-                    for(MemberStatsContext memberStatsContext: partitionContext.getMemberStatsContexts().values()){
 
+					// In partition context member stat context, all the primary members need to be
+					// avoided being selected as the member to terminated
+					
+
+                    for(MemberStatsContext memberStatsContext: partitionContext.getMemberStatsContexts().values()){
+					
+						if( !primaryMembers.contains(memberStatsContext.getMemberId()) ) {
+						
                         LoadAverage loadAverage = memberStatsContext.getLoadAverage();
                         log.debug("[scale-down] " + " [cluster] "
                             + clusterId + " [member] " + memberStatsContext.getMemberId() + " Load average: " + loadAverage);
@@ -156,6 +165,10 @@ dialect "mvel"
                             selectedMemberStatsContext = memberStatsContext;
                             lowestOverallLoad = overallLoad;
                         }
+                        
+                        							
+					  }
+						
                     }
                     if(selectedMemberStatsContext != null) {
                         log.info("[scale-down] Trying to terminating an instace to scale down!" );

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/products/stratos/modules/distribution/src/main/conf/siddhi/siddhi.extension
----------------------------------------------------------------------
diff --git a/products/stratos/modules/distribution/src/main/conf/siddhi/siddhi.extension b/products/stratos/modules/distribution/src/main/conf/siddhi/siddhi.extension
index 6bb9aca..470d66c 100644
--- a/products/stratos/modules/distribution/src/main/conf/siddhi/siddhi.extension
+++ b/products/stratos/modules/distribution/src/main/conf/siddhi/siddhi.extension
@@ -1,3 +1,4 @@
 org.apache.stratos.cep.extension.GradientFinderWindowProcessor
 org.apache.stratos.cep.extension.SecondDerivativeFinderWindowProcessor
 org.apache.stratos.cep.extension.FaultHandlingWindowProcessor
+org.apache.stratos.cep.extension.ConcatWindowProcessor


[11/14] git commit: Merge branch '4.0.0' of https://git-wip-us.apache.org/repos/asf/stratos into 4.0.0

Posted by ma...@apache.org.
Merge branch '4.0.0' of https://git-wip-us.apache.org/repos/asf/stratos into 4.0.0


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

Branch: refs/heads/4.0.0
Commit: 47f9f253adcab43eb31661459449a1baf376cb41
Parents: 7b35e29 67b8e79
Author: Manula Thantriwatte <ma...@apache.org>
Authored: Tue Jul 1 06:37:44 2014 +0000
Committer: Manula Thantriwatte <ma...@apache.org>
Committed: Tue Jul 1 06:37:44 2014 +0000

----------------------------------------------------------------------
 README.md                                       |   4 +-
 .../apache/stratos/cli/StratosApplication.java  |   2 +-
 .../mgt/ui/servlets/ThemeResourceServlet.java   | 125 +++++++++++++++++++
 .../mgt/ui/servlets/ThemeResourceSevelet.java   | 125 -------------------
 .../src/main/resources/META-INF/component.xml   |   2 +-
 5 files changed, 129 insertions(+), 129 deletions(-)
----------------------------------------------------------------------



[08/14] Clustering changes for stratos

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/extensions/DefaultExtensionHandler.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/extensions/DefaultExtensionHandler.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/extensions/DefaultExtensionHandler.java
new file mode 100644
index 0000000..e861819
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/extensions/DefaultExtensionHandler.java
@@ -0,0 +1,992 @@
+/*
+ * 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.cartridge.agent.extensions;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.RepositoryInformation;
+import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.impl.GitBasedArtifactRepository;
+import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
+import org.apache.stratos.cartridge.agent.event.publisher.CartridgeAgentEventPublisher;
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentConstants;
+import org.apache.stratos.cartridge.agent.util.CartridgeAgentUtils;
+import org.apache.stratos.cartridge.agent.util.ExtensionUtils;
+import org.apache.stratos.messaging.domain.tenant.Tenant;
+import org.apache.stratos.messaging.domain.topology.*;
+import org.apache.stratos.messaging.event.instance.notifier.ArtifactUpdatedEvent;
+import org.apache.stratos.messaging.event.instance.notifier.InstanceCleanupClusterEvent;
+import org.apache.stratos.messaging.event.instance.notifier.InstanceCleanupMemberEvent;
+import org.apache.stratos.messaging.event.tenant.CompleteTenantEvent;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainAddedEvent;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainRemovedEvent;
+import org.apache.stratos.messaging.event.topology.*;
+import org.apache.stratos.messaging.message.receiver.tenant.TenantManager;
+import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
+import org.wso2.andes.util.Serial;
+
+import java.io.File;
+import java.lang.reflect.Type;
+import java.util.*;
+
+public class DefaultExtensionHandler implements ExtensionHandler {
+
+    private static final Log log = LogFactory.getLog(DefaultExtensionHandler.class);
+    private static final Gson gson = new Gson();
+    private static final Type memberType = new TypeToken<Collection<Member>>() {
+    }.getType();
+    private static final Type tenantType = new TypeToken<Collection<Tenant>>() {
+    }.getType();
+    private static final Type serviceType = new TypeToken<Collection<Service>>() {
+    }.getType();
+    private final ArrayList<Member> wkMembers = new ArrayList<Member>();
+
+    @Override
+    public void onInstanceStartedEvent() {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Processing instance started event...");
+            }
+            Map<String, String> env = new HashMap<String, String>();
+            ExtensionUtils.executeInstanceStartedExtension(env);
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Error processing instance started event", e);
+            }
+        }
+    }
+
+    @Override
+    public void onInstanceActivatedEvent() {
+        ExtensionUtils.executeInstanceActivatedExtension();
+    }
+
+    @Override
+    public void onArtifactUpdatedEvent(ArtifactUpdatedEvent artifactUpdatedEvent) {
+        if (log.isInfoEnabled()) {
+            log.info(String.format("Artifact update event received: [tenant] %s [cluster] %s [status] %s",
+                    artifactUpdatedEvent.getTenantId(), artifactUpdatedEvent.getClusterId(), artifactUpdatedEvent.getStatus()));
+        }
+
+        String clusterIdInMessage = artifactUpdatedEvent.getClusterId();
+        String clusterIdInPayload = CartridgeAgentConfiguration.getInstance().getClusterId();
+        String repoURL = artifactUpdatedEvent.getRepoURL();
+
+        // we need to execute the logic if only the update is relevant to this cluster domain
+        if (StringUtils.isNotEmpty(repoURL) && (clusterIdInPayload != null) && clusterIdInPayload.equals(clusterIdInMessage)) {
+
+            String localRepoPath = CartridgeAgentConfiguration.getInstance().getAppPath();
+            String repoPassword = CartridgeAgentUtils.decryptPassword(artifactUpdatedEvent.getRepoPassword());
+            String repoUsername = artifactUpdatedEvent.getRepoUserName();
+            String tenantId = artifactUpdatedEvent.getTenantId();
+            boolean isMultitenant = CartridgeAgentConfiguration.getInstance().isMultitenant();
+
+            if (log.isInfoEnabled()) {
+                log.info("Executing git checkout");
+            }
+            RepositoryInformation repoInformation = new RepositoryInformation();
+            repoInformation.setRepoUsername(repoUsername);
+            if (repoPassword == null) {
+                repoInformation.setRepoPassword("");
+            } else {
+                repoInformation.setRepoPassword(repoPassword);
+            }
+            repoInformation.setRepoUrl(repoURL);
+            repoInformation.setRepoPath(localRepoPath);
+            repoInformation.setTenantId(tenantId);
+            repoInformation.setMultitenant(isMultitenant);
+            boolean cloneExists = GitBasedArtifactRepository.getInstance().cloneExists(repoInformation);
+            try {
+                GitBasedArtifactRepository.getInstance().checkout(repoInformation);
+            } catch (Exception e) {
+                log.error(e);
+            }
+            Map<String, String> env = new HashMap<String, String>();
+            env.put("STRATOS_ARTIFACT_UPDATED_CLUSTER_ID", artifactUpdatedEvent.getClusterId());
+            env.put("STRATOS_ARTIFACT_UPDATED_TENANT_ID", artifactUpdatedEvent.getTenantId());
+            env.put("STRATOS_ARTIFACT_UPDATED_REPO_URL", artifactUpdatedEvent.getRepoURL());
+            env.put("STRATOS_ARTIFACT_UPDATED_REPO_PASSWORD", artifactUpdatedEvent.getRepoPassword());
+            env.put("STRATOS_ARTIFACT_UPDATED_REPO_USERNAME", artifactUpdatedEvent.getRepoUserName());
+            env.put("STRATOS_ARTIFACT_UPDATED_STATUS", artifactUpdatedEvent.getStatus());
+            ExtensionUtils.executeArtifactsUpdatedExtension(env);
+
+            if (!cloneExists) {
+                // Executed git clone, publish instance activated event
+                CartridgeAgentEventPublisher.publishInstanceActivatedEvent();
+            }
+
+            // Start the artifact update task
+            boolean artifactUpdateEnabled = Boolean.parseBoolean(System.getProperty(CartridgeAgentConstants.ENABLE_ARTIFACT_UPDATE));
+            if (artifactUpdateEnabled) {
+
+                boolean autoCommit = CartridgeAgentConfiguration.getInstance().isCommitsEnabled();
+                boolean autoCheckout = CartridgeAgentConfiguration.getInstance().isCheckoutEnabled();
+
+                long artifactUpdateInterval = 10;
+                // get update interval
+                String artifactUpdateIntervalStr = System.getProperty(CartridgeAgentConstants.ARTIFACT_UPDATE_INTERVAL);
+
+                if (artifactUpdateIntervalStr != null && !artifactUpdateIntervalStr.isEmpty()) {
+                    try {
+                        artifactUpdateInterval = Long.parseLong(artifactUpdateIntervalStr);
+
+                    } catch (NumberFormatException e) {
+                        log.error("Invalid artifact sync interval specified ", e);
+                        artifactUpdateInterval = 10;
+                    }
+                }
+
+                log.info("Artifact updating task enabled, update interval: " + artifactUpdateInterval + "s");
+                if (autoCommit) {
+                    log.info("Auto Commit is turned on ");
+                }  else {
+                    log.info("Auto Commit is turned off ");
+                }
+
+                if (autoCheckout) {
+                    log.info("Auto Checkout is turned on ");
+                } else {
+                    log.info("Auto Checkout is turned off ");
+                }
+
+                GitBasedArtifactRepository.getInstance().scheduleSyncTask(repoInformation, autoCheckout, autoCommit, artifactUpdateInterval);
+
+            } else {
+                log.info("Artifact updating task disabled");
+            }
+            
+            // If supert tenant temp app path is available,
+            // copy the artifacts to carbon server's deployment path
+            String src = CartridgeAgentConstants.SUPERTENANT_TEMP_PATH;
+            if (new File(src).exists() && tenantId.equals("-1234")) {
+                ExtensionUtils.executeCopyArtifactsExtension(src,
+    					CartridgeAgentConfiguration.getInstance().getAppPath()+ "/repository/deployment/server/");
+            }
+
+        }
+    }
+
+    @Override
+    public void onArtifactUpdateSchedulerEvent(String tenantId) {
+        Map<String, String> env = new HashMap<String, String>();
+        env.put("STRATOS_ARTIFACT_UPDATED_TENANT_ID", tenantId);
+        env.put("STRATOS_ARTIFACT_UPDATED_SCHEDULER", "true");
+        ExtensionUtils.executeArtifactsUpdatedExtension(env);
+    }
+
+    @Override
+    public void onInstanceCleanupClusterEvent(InstanceCleanupClusterEvent instanceCleanupClusterEvent) {
+        cleanup();
+    }
+
+    @Override
+    public void onInstanceCleanupMemberEvent(InstanceCleanupMemberEvent instanceCleanupMemberEvent) {
+        cleanup();
+    }
+
+    private void cleanup() {
+        if (log.isInfoEnabled()) {
+            log.info("Executing cleaning up the data in the cartridge instance...");
+        }
+        //sending event on the maintenance mode
+        CartridgeAgentEventPublisher.publishMaintenanceModeEvent();
+
+        //cleaning up the cartridge instance's data
+        ExtensionUtils.executeCleanupExtension();
+        if (log.isInfoEnabled()) {
+            log.info("cleaning up finished in the cartridge instance...");
+        }
+        if (log.isInfoEnabled()) {
+            log.info("publishing ready to shutdown event...");
+        }
+        //publishing the Ready to shutdown event after performing the cleanup
+        CartridgeAgentEventPublisher.publishInstanceReadyToShutdownEvent();
+    }
+
+
+    @Override
+    public void onMemberActivatedEvent(MemberActivatedEvent memberActivatedEvent) {
+        if (log.isInfoEnabled()) {
+            log.info(String.format("Member activated event received: [service] %s [cluster] %s [member] %s",
+                    memberActivatedEvent.getServiceName(), memberActivatedEvent.getClusterId(), memberActivatedEvent.getMemberId()));
+        }
+
+        if (log.isDebugEnabled()) {
+            String msg = gson.toJson(memberActivatedEvent);
+            log.debug("Member activated event msg:" + msg);
+        }
+
+        boolean isConsistent = ExtensionUtils.checkTopologyConsistency(memberActivatedEvent.getServiceName(),
+                memberActivatedEvent.getClusterId(), memberActivatedEvent.getMemberId());
+        if (!isConsistent) {
+            if (log.isErrorEnabled()) {
+                log.error("Topology is inconsistent...failed to execute member activated event");
+            }
+            return;
+        }
+
+        Topology topology = TopologyManager.getTopology();
+        Service service = topology.getService(memberActivatedEvent.getServiceName());
+        Cluster cluster = service.getCluster(memberActivatedEvent.getClusterId());
+        String lbClusterId = cluster.getMember(memberActivatedEvent.getMemberId()).getLbClusterId();
+        Member member = cluster.getMember(memberActivatedEvent.getMemberId());
+
+        // check whether member activated event is received from the same cluster, lbcluster or service group
+        if (ExtensionUtils.isRelevantMemberEvent(memberActivatedEvent.getServiceName(), memberActivatedEvent.getClusterId(), lbClusterId)) {
+            Map<String, String> env = new HashMap<String, String>();
+            env.put("STRATOS_MEMBER_ACTIVATED_MEMBER_IP", memberActivatedEvent.getMemberIp());
+            env.put("STRATOS_MEMBER_ACTIVATED_MEMBER_ID", memberActivatedEvent.getMemberId());
+            env.put("STRATOS_MEMBER_ACTIVATED_CLUSTER_ID", memberActivatedEvent.getClusterId());
+            env.put("STRATOS_MEMBER_ACTIVATED_LB_CLUSTER_ID", lbClusterId);
+            env.put("STRATOS_MEMBER_ACTIVATED_NETWORK_PARTITION_ID", memberActivatedEvent.getNetworkPartitionId());
+            env.put("STRATOS_MEMBER_ACTIVATED_SERVICE_NAME", memberActivatedEvent.getServiceName());
+
+            Collection<Port> ports = memberActivatedEvent.getPorts();
+            String ports_str = "";
+            for (Port port : ports) {
+                ports_str += port.getProtocol() + "," + port.getValue() + "," + port.getProxy() + "|";
+            }
+            env.put("STRATOS_MEMBER_ACTIVATED_PORTS", ports_str);
+
+            Collection<Member> members = cluster.getMembers();
+            env.put("STRATOS_MEMBER_ACTIVATED_MEMBER_LIST_JSON", gson.toJson(members, memberType));
+            String[] memberIps = ExtensionUtils.getLbMemberIp(lbClusterId);
+            if (memberIps != null && memberIps.length > 1) {
+                env.put("STRATOS_MEMBER_ACTIVATED_LB_IP", memberIps[0]);
+                env.put("STRATOS_MEMBER_ACTIVATED_LB_PUBLIC_IP", memberIps[1]);
+            }
+            env.put("STRATOS_TOPOLOGY_JSON", gson.toJson(topology.getServices(), serviceType));
+            ExtensionUtils.addProperties(service.getProperties(), env, "MEMBER_ACTIVATED_SERVICE_PROPERTY");
+            ExtensionUtils.addProperties(cluster.getProperties(), env, "MEMBER_ACTIVATED_CLUSTER_PROPERTY");
+            ExtensionUtils.addProperties(member.getProperties(), env, "MEMBER_ACTIVATED_MEMBER_PROPERTY");
+            
+            // if clustering is enabled check activated member is WK member
+            String flagClustering = CartridgeAgentConfiguration.getInstance().getIsClustered();
+
+            // if WK member is re-spawned, update axis2.xml
+            if (member.getProperties() != null && "true".equals(member.getProperties().getProperty(CartridgeAgentConstants.CLUSTERING_PRIMARY_KEY)) &&
+                    flagClustering != null && "true".equals(flagClustering.toLowerCase())){
+            	if(log.isDebugEnabled()) {
+            		log.debug(" If WK member is re-spawned, update axis2.xml ");
+            	}
+                boolean hasWKIpChanged = true;
+                for (Member m : this.wkMembers){
+                    if (m.getMemberIp().equals(memberActivatedEvent.getMemberIp())){
+                        hasWKIpChanged = false;
+                    }
+                }
+                if(log.isDebugEnabled()) {
+                	log.debug(" hasWKIpChanged " + hasWKIpChanged);
+                }
+                int minCount = Integer.parseInt(CartridgeAgentConfiguration.getInstance().getMinCount());                
+                boolean isWKMemberGroupReady = isWKMemberGroupReady(env, minCount);
+                if(log.isDebugEnabled()) {
+                	log.debug("minCount " + minCount);
+                	log.debug("isWKMemberGroupReady " + isWKMemberGroupReady);
+                }
+                if (hasWKIpChanged && isWKMemberGroupReady){
+                	if(log.isDebugEnabled()) {
+                		log.debug("Setting env var STRATOS_UPDATE_WK_IP to true");
+                	}
+                    env.put("STRATOS_UPDATE_WK_IP", "true");
+                }
+            }      
+            if(log.isDebugEnabled()) {
+            	log.debug("Setting env var STRATOS_CLUSTERING to " + flagClustering);
+            }
+            env.put("STRATOS_CLUSTERING", flagClustering);
+            env.put("STRATOS_WK_MEMBER_COUNT", CartridgeAgentConfiguration.getInstance().getMinCount());
+            ExtensionUtils.executeMemberActivatedExtension(env);
+        } else {
+            if (log.isDebugEnabled()) {
+                log.debug("Member activated event is not relevant...skipping agent extension");
+            }
+        }
+    }
+
+
+    @Override
+    public void onCompleteTopologyEvent(CompleteTopologyEvent completeTopologyEvent) {
+        if (log.isDebugEnabled()) {
+            log.debug("Complete topology event received");
+
+        }
+        String serviceNameInPayload = CartridgeAgentConfiguration.getInstance().getServiceName();
+        String clusterIdInPayload = CartridgeAgentConfiguration.getInstance().getClusterId();
+        String memberIdInPayload = CartridgeAgentConfiguration.getInstance().getMemberId();
+        ExtensionUtils.checkTopologyConsistency(serviceNameInPayload, clusterIdInPayload, memberIdInPayload);
+
+        Topology topology = completeTopologyEvent.getTopology();
+        Service service = topology.getService(serviceNameInPayload);
+        Cluster cluster = service.getCluster(clusterIdInPayload);
+
+        Map<String, String> env = new HashMap<String, String>();
+        env.put("STRATOS_TOPOLOGY_JSON", gson.toJson(topology.getServices(), serviceType));
+        env.put("STRATOS_MEMBER_LIST_JSON", gson.toJson(cluster.getMembers(), memberType));
+        ExtensionUtils.executeCompleteTopologyExtension(env);
+    }
+
+    @Override
+    public void onCompleteTenantEvent(CompleteTenantEvent completeTenantEvent) {
+        if (log.isDebugEnabled()) {
+            log.debug("Complete tenant event received");
+        }
+        String tenantListJson = gson.toJson(completeTenantEvent.getTenants(), tenantType);
+        if (log.isDebugEnabled()) {
+            log.debug("Complete tenants:" + tenantListJson);
+        }
+        Map<String, String> env = new HashMap<String, String>();
+        env.put("STRATOS_TENANT_LIST_JSON", tenantListJson);
+        ExtensionUtils.executeCompleteTenantExtension(env);
+    }
+
+    @Override
+    public void onMemberTerminatedEvent(MemberTerminatedEvent memberTerminatedEvent) {
+        if (log.isInfoEnabled()) {
+            log.info(String.format("Member terminated event received: [service] %s [cluster] %s [member] %s",
+                    memberTerminatedEvent.getServiceName(), memberTerminatedEvent.getClusterId(), memberTerminatedEvent.getMemberId()));
+        }
+
+        if (log.isDebugEnabled()) {
+            String msg = gson.toJson(memberTerminatedEvent);
+            log.debug("Member terminated event msg:" + msg);
+        }
+
+        boolean isConsistent = ExtensionUtils.checkTopologyConsistency(memberTerminatedEvent.getServiceName(),
+                memberTerminatedEvent.getClusterId(), memberTerminatedEvent.getMemberId());
+        if (!isConsistent) {
+            if (log.isErrorEnabled()) {
+                log.error("Topology is inconsistent...failed to execute member terminated event");
+            }
+            return;
+        }
+
+        Topology topology = TopologyManager.getTopology();
+        Service service = topology.getService(memberTerminatedEvent.getServiceName());
+        Cluster cluster = service.getCluster(memberTerminatedEvent.getClusterId());
+        Member terminatedMember = cluster.getMember(memberTerminatedEvent.getMemberId());
+        String lbClusterId = cluster.getMember(memberTerminatedEvent.getClusterId()).getLbClusterId();
+
+        // check whether terminated member is within the same cluster, LB cluster or service group
+        if (ExtensionUtils.isRelevantMemberEvent(memberTerminatedEvent.getServiceName(),
+                memberTerminatedEvent.getClusterId(), lbClusterId)) {
+
+            Collection<Member> members = cluster.getMembers();
+            Map<String, String> env = new HashMap<String, String>();
+            env.put("STRATOS_MEMBER_TERMINATED_MEMBER_IP", terminatedMember.getMemberIp());
+            env.put("STRATOS_MEMBER_TERMINATED_MEMBER_ID", memberTerminatedEvent.getMemberId());
+            env.put("STRATOS_MEMBER_TERMINATED_CLUSTER_ID", memberTerminatedEvent.getClusterId());
+            env.put("STRATOS_MEMBER_TERMINATED_LB_CLUSTER_ID", lbClusterId);
+            env.put("STRATOS_MEMBER_TERMINATED_NETWORK_PARTITION_ID", memberTerminatedEvent.getNetworkPartitionId());
+            env.put("STRATOS_MEMBER_TERMINATED_SERVICE_NAME", memberTerminatedEvent.getServiceName());
+            env.put("STRATOS_MEMBER_TERMINATED_MEMBER_LIST_JSON", gson.toJson(members, memberType));
+            env.put("STRATOS_TOPOLOGY_JSON", gson.toJson(topology.getServices(), serviceType));
+            String[] memberIps = ExtensionUtils.getLbMemberIp(lbClusterId);
+            if (memberIps != null && memberIps.length > 1) {
+                env.put("STRATOS_MEMBER_TERMINATED_LB_IP", memberIps[0]);
+                env.put("STRATOS_MEMBER_TERMINATED_LB_PUBLIC_IP", memberIps[1]);
+            }
+
+            ExtensionUtils.addProperties(service.getProperties(), env, "MEMBER_TERMINATED_SERVICE_PROPERTY");
+            ExtensionUtils.addProperties(cluster.getProperties(), env, "MEMBER_TERMINATED_CLUSTER_PROPERTY");
+            ExtensionUtils.addProperties(terminatedMember.getProperties(), env, "MEMBER_TERMINATED_MEMBER_PROPERTY");
+            ExtensionUtils.executeMemberTerminatedExtension(env);
+        } else {
+            if (log.isDebugEnabled()) {
+                log.debug("Member terminated event is not relevant...skipping agent extension");
+            }
+        }
+    }
+
+    @Override
+    public void onMemberSuspendedEvent(MemberSuspendedEvent memberSuspendedEvent) {
+        if (log.isInfoEnabled()) {
+            log.info(String.format("Member suspended event received: [service] %s [cluster] %s [member] %s",
+                    memberSuspendedEvent.getServiceName(), memberSuspendedEvent.getClusterId(), memberSuspendedEvent.getMemberId()));
+        }
+
+        if (log.isDebugEnabled()) {
+            String msg = gson.toJson(memberSuspendedEvent);
+            log.debug("Member suspended event msg:" + msg);
+        }
+
+        boolean isConsistent = ExtensionUtils.checkTopologyConsistency(memberSuspendedEvent.getServiceName(),
+                memberSuspendedEvent.getClusterId(), memberSuspendedEvent.getMemberId());
+        if (!isConsistent) {
+            if (log.isErrorEnabled()) {
+                log.error("Topology is inconsistent...failed to execute member suspended event");
+            }
+            return;
+        }
+
+        String clusterId = memberSuspendedEvent.getClusterId();
+        Topology topology = TopologyManager.getTopology();
+        Service service = topology.getService(memberSuspendedEvent.getServiceName());
+        Cluster cluster = service.getCluster(memberSuspendedEvent.getClusterId());
+        Member suspendedMember = cluster.getMember(memberSuspendedEvent.getMemberId());
+        String lbClusterId = cluster.getMember(memberSuspendedEvent.getClusterId()).getLbClusterId();
+
+        // check whether new member is in the same member cluster or LB cluster of this instance
+        if (ExtensionUtils.isRelevantMemberEvent(memberSuspendedEvent.getServiceName(),
+                memberSuspendedEvent.getClusterId(), lbClusterId)) {
+            Collection<Member> members = cluster.getMembers();
+            Map<String, String> env = new HashMap<String, String>();
+            env.put("STRATOS_MEMBER_SUSPENDED_MEMBER_IP", suspendedMember.getMemberIp());
+            env.put("STRATOS_MEMBER_SUSPENDED_MEMBER_ID", memberSuspendedEvent.getMemberId());
+            env.put("STRATOS_MEMBER_SUSPENDED_CLUSTER_ID", memberSuspendedEvent.getClusterId());
+            env.put("STRATOS_MEMBER_SUSPENDED_LB_CLUSTER_ID", lbClusterId);
+            env.put("STRATOS_MEMBER_SUSPENDED_NETWORK_PARTITION_ID", memberSuspendedEvent.getNetworkPartitionId());
+            env.put("STRATOS_MEMBER_SUSPENDED_SERVICE_NAME", memberSuspendedEvent.getServiceName());
+            env.put("STRATOS_MEMBER_SUSPENDED_MEMBER_LIST_JSON", gson.toJson(members, memberType));
+            env.put("STRATOS_TOPOLOGY_JSON", gson.toJson(topology.getServices(), serviceType));
+            String[] memberIps = ExtensionUtils.getLbMemberIp(lbClusterId);
+            if (memberIps != null && memberIps.length > 1) {
+                env.put("STRATOS_MEMBER_SUSPENDED_LB_IP", memberIps[0]);
+                env.put("STRATOS_MEMBER_SUSPENDED_LB_PUBLIC_IP", memberIps[1]);
+            }
+            ExtensionUtils.addProperties(service.getProperties(), env, "MEMBER_SUSPENDED_SERVICE_PROPERTY");
+            ExtensionUtils.addProperties(cluster.getProperties(), env, "MEMBER_SUSPENDED_CLUSTER_PROPERTY");
+            ExtensionUtils.addProperties(suspendedMember.getProperties(), env, "MEMBER_SUSPENDED_MEMBER_PROPERTY");
+            ExtensionUtils.executeMemberSuspendedExtension(env);
+        } else {
+            if (log.isDebugEnabled()) {
+                log.debug("Member suspended event is not relevant...skipping agent extension");
+            }
+        }
+    }
+
+    @Override
+    public void onMemberStartedEvent(MemberStartedEvent memberStartedEvent) {
+        if (log.isInfoEnabled()) {
+            log.info(String.format("Member started event received: [service] %s [cluster] %s [member] %s",
+                    memberStartedEvent.getServiceName(), memberStartedEvent.getClusterId(), memberStartedEvent.getMemberId()));
+        }
+
+        if (log.isDebugEnabled()) {
+            String msg = gson.toJson(memberStartedEvent);
+            log.debug("Member started event msg:" + msg);
+        }
+
+        boolean isConsistent = ExtensionUtils.checkTopologyConsistency(memberStartedEvent.getServiceName(),
+                memberStartedEvent.getClusterId(), memberStartedEvent.getMemberId());
+        if (!isConsistent) {
+            if (log.isErrorEnabled()) {
+                log.error("Topology is inconsistent...failed to execute member started event");
+            }
+            return;
+        }
+        String clusterId = memberStartedEvent.getClusterId();
+        Topology topology = TopologyManager.getTopology();
+        Service service = topology.getService(memberStartedEvent.getServiceName());
+        Cluster cluster = service.getCluster(memberStartedEvent.getClusterId());
+        Member startedMember = cluster.getMember(memberStartedEvent.getMemberId());
+        String lbClusterId = cluster.getMember(memberStartedEvent.getMemberId()).getLbClusterId();
+
+        // check whether new member is in the same member cluster or LB cluster of this instance
+        if (ExtensionUtils.isRelevantMemberEvent(memberStartedEvent.getServiceName(),
+                memberStartedEvent.getClusterId(), lbClusterId)) {
+            Collection<Member> members = cluster.getMembers();
+            Map<String, String> env = new HashMap<String, String>();
+            env.put("STRATOS_MEMBER_STARTED_MEMBER_IP", startedMember.getMemberIp());
+            env.put("STRATOS_MEMBER_STARTED_MEMBER_ID", memberStartedEvent.getMemberId());
+            env.put("STRATOS_MEMBER_STARTED_CLUSTER_ID", memberStartedEvent.getClusterId());
+            env.put("STRATOS_MEMBER_STARTED_LB_CLUSTER_ID", lbClusterId);
+            env.put("STRATOS_MEMBER_STARTED_NETWORK_PARTITION_ID", memberStartedEvent.getNetworkPartitionId());
+            env.put("STRATOS_MEMBER_STARTED_SERVICE_NAME", memberStartedEvent.getServiceName());
+            env.put("STRATOS_MEMBER_STARTED_MEMBER_LIST_JSON", gson.toJson(members, memberType));
+            env.put("STRATOS_MEMBER_STARTED_TOPOLOGY_JSON", gson.toJson(topology.getServices(), serviceType));
+            String[] memberIps = ExtensionUtils.getLbMemberIp(lbClusterId);
+            if (memberIps != null && memberIps.length > 1) {
+                env.put("STRATOS_MEMBER_STARTED_LB_IP", memberIps[0]);
+                env.put("STRATOS_MEMBER_STARTED_LB_PUBLIC_IP", memberIps[1]);
+            }
+            ExtensionUtils.addProperties(service.getProperties(), env, "MEMBER_STARTED_SERVICE_PROPERTY");
+            ExtensionUtils.addProperties(cluster.getProperties(), env, "MEMBER_STARTED_CLUSTER_PROPERTY");
+            ExtensionUtils.addProperties(startedMember.getProperties(), env, "MEMBER_STARTED_MEMBER_PROPERTY");
+            ExtensionUtils.executeMemberStartedExtension(env);
+        } else {
+            if (log.isDebugEnabled()) {
+                log.debug("Member started event is not relevant...skipping agent extension");
+            }
+        }
+    }
+
+    private boolean isWKMemberGroupReady(Map<String, String> envParameters, int minCount) {
+        Topology topology = TopologyManager.getTopology();
+        if (topology == null || !topology.isInitialized()) {
+            return false;
+        }
+        String serviceGroupInPayload = CartridgeAgentConfiguration.getInstance().getServiceGroup();
+        if (serviceGroupInPayload != null) {
+            envParameters.put("STRATOS_SERVICE_GROUP", serviceGroupInPayload);
+        }
+
+        // clustering logic for apimanager
+        if (serviceGroupInPayload != null && serviceGroupInPayload.equals("apim")) {
+
+            // handle apistore and publisher case
+            if (CartridgeAgentConfiguration.getInstance().getServiceName().equals("apistore") ||
+                    CartridgeAgentConfiguration.getInstance().getServiceName().equals("publisher")) {
+
+                Collection<Cluster> apistoreClusterCollection = topology.getService("apistore").getClusters();
+                Collection<Cluster> publisherClusterCollection = topology.getService("publisher").getClusters();
+
+                List<Member> apistoreMemberList = new ArrayList<Member>();
+                for (Member member : apistoreClusterCollection.iterator().next().getMembers()) {
+                    if (member.getStatus().equals(MemberStatus.Starting) || member.getStatus().equals(MemberStatus.Activated)) {
+                        apistoreMemberList.add(member);
+                        this.wkMembers.add(member);
+                    }
+                }
+                if (apistoreMemberList.isEmpty()) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("API Store members not yet created");
+                    }
+                    return false;
+                }
+                Member apistoreMember = apistoreMemberList.get(0);
+                envParameters.put("STRATOS_WK_APISTORE_MEMBER_IP", apistoreMember.getMemberIp());
+                if (log.isDebugEnabled()) {
+                    log.debug("STRATOS_WK_APISTORE_MEMBER_IP: " + apistoreMember.getMemberIp());
+                }
+
+                List<Member> publisherMemberList = new ArrayList<Member>();
+                for (Member member : publisherClusterCollection.iterator().next().getMembers()) {
+                    if (member.getStatus().equals(MemberStatus.Starting) || member.getStatus().equals(MemberStatus.Activated)) {
+                        publisherMemberList.add(member);
+                        this.wkMembers.add(member);
+                    }
+                }
+                if (publisherMemberList.isEmpty()) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("API Publisher members not yet created");
+                    }
+                    return false;
+                }
+                Member publisherMember = publisherMemberList.get(0);
+                envParameters.put("STRATOS_WK_PUBLISHER_MEMBER_IP", publisherMember.getMemberIp());
+                if (log.isDebugEnabled()) {
+                    log.debug("STRATOS_WK_PUBLISHER_MEMBER_IP: " + publisherMember.getMemberIp());
+                }
+
+                return true;
+
+            } else if (CartridgeAgentConfiguration.getInstance().getServiceName().equals("gatewaymgt") ||
+                    CartridgeAgentConfiguration.getInstance().getServiceName().equals("gateway")) {
+
+                if (CartridgeAgentConfiguration.getInstance().getDeployment() != null) {
+                    // check if deployment is Manager Worker separated
+                    if (CartridgeAgentConfiguration.getInstance().getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_MANAGER) ||
+                            CartridgeAgentConfiguration.getInstance().getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_WORKER)) {
+
+                        log.info("Deployment pattern for the node: " + CartridgeAgentConfiguration.getInstance().getDeployment());
+                        envParameters.put("DEPLOYMENT", CartridgeAgentConfiguration.getInstance().getDeployment());
+                        // check if WKA members of Manager Worker separated deployment is ready
+                        return isManagerWorkerWKAGroupReady(envParameters);
+                    }
+                }
+
+
+            } else if (CartridgeAgentConfiguration.getInstance().getServiceName().equals("keymanager")) {
+                return true;
+            }
+        } else {
+
+            if (CartridgeAgentConfiguration.getInstance().getDeployment() != null) {
+                // check if deployment is Manager Worker separated
+                if (CartridgeAgentConfiguration.getInstance().getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_MANAGER) ||
+                        CartridgeAgentConfiguration.getInstance().getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_WORKER)) {
+
+                    log.info("Deployment pattern for the node: " + CartridgeAgentConfiguration.getInstance().getDeployment());
+                    envParameters.put("DEPLOYMENT", CartridgeAgentConfiguration.getInstance().getDeployment());
+                    // check if WKA members of Manager Worker separated deployment is ready
+                    return isManagerWorkerWKAGroupReady(envParameters);
+                }
+            }
+
+            String serviceNameInPayload = CartridgeAgentConfiguration.getInstance().getServiceName();
+            String clusterIdInPayload = CartridgeAgentConfiguration.getInstance().getClusterId();
+            Service service = topology.getService(serviceNameInPayload);
+            Cluster cluster = service.getCluster(clusterIdInPayload);
+
+            List<Member> wkMembers = new ArrayList<Member>();
+            for (Member member : cluster.getMembers()) {
+                if (member.getProperties() != null &&
+                        member.getProperties().containsKey("PRIMARY") &&
+                        member.getProperties().getProperty("PRIMARY").toLowerCase().equals("true") &&
+                        (member.getStatus().equals(MemberStatus.Starting) || member.getStatus().equals(MemberStatus.Activated))
+                        ) {
+                    wkMembers.add(member);
+                    this.wkMembers.add(member);
+                    if (log.isDebugEnabled()) {
+                        log.debug("Found WKA: STRATOS_WK_MEMBER_IP: " + member.getMemberIp());
+                    }
+                }
+            }
+            if (wkMembers.size() >= minCount) {
+                int idx = 0;
+                for (Member member : wkMembers) {
+                    envParameters.put("STRATOS_WK_MEMBER_" + idx + "_IP", member.getMemberIp());
+                    if (log.isDebugEnabled()) {
+                        log.debug("STRATOS_WK_MEMBER_" + idx + "_IP: " + member.getMemberIp());
+                    }
+                    idx++;
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // generic worker manager separated clustering logic
+    private boolean isManagerWorkerWKAGroupReady (Map<String, String> envParameters) {
+
+        // for this, we need both manager cluster service name and worker cluster service name
+        String managerServiceName =  CartridgeAgentConfiguration.getInstance().getManagerServiceName();
+        String workerServiceName =  CartridgeAgentConfiguration.getInstance().getWorkerServiceName();
+
+        // managerServiceName and workerServiceName both should not be null /empty
+        if (managerServiceName == null || managerServiceName.isEmpty()) {
+            log.error("Manager service name [ "+ managerServiceName +" ] is invalid");
+            return false;
+        }
+        if (workerServiceName == null || workerServiceName.isEmpty()) {
+            log.error("Worker service name [ "+ workerServiceName +" ] is invalid");
+            return false;
+        }
+
+        boolean minManagerInstancesAvailable = false;
+        boolean minWorkerInstancesAvailable = false;
+
+        TopologyManager.acquireReadLock();
+
+        try {
+            Service managerService = TopologyManager.getTopology().getService(managerServiceName);
+            Service workerService = TopologyManager.getTopology().getService(workerServiceName);
+
+            if (managerService == null) {
+                log.warn("Service [ "+managerServiceName+" ] is not found");
+                return false;
+            }
+
+            if (workerService == null) {
+                log.warn("Service [ "+workerServiceName+" ] is not found");
+                return false;
+            }
+
+            // manager clusters
+            Collection<Cluster> managerClusters = managerService.getClusters();
+            if (managerClusters == null || managerClusters.isEmpty()) {
+                log.warn("No clusters found for service [ "+ managerServiceName + " ]");
+                return false;
+            }
+
+            int managerMinInstanceCount = 1;
+            boolean managerMinInstanceCountFound = false;
+
+            List<Member> managerWkaMembers = new ArrayList<Member>();
+            for (Member member : managerClusters.iterator().next().getMembers()) {
+
+                if (member.getProperties() != null && member.getProperties().containsKey("PRIMARY") &&
+                            member.getProperties().getProperty("PRIMARY").toLowerCase().equals("true") &&
+                            (member.getStatus().equals(MemberStatus.Starting) || member.getStatus().equals(MemberStatus.Activated))) {
+
+                    managerWkaMembers.add(member);
+                    this.wkMembers.add(member);
+                    
+                    // get the min instance count
+                    if (!managerMinInstanceCountFound) {
+                        managerMinInstanceCount = getMinInstanceCountFromMemberProperties(member);
+                        managerMinInstanceCountFound = true;
+                        log.info("Manager min instance count: " + managerMinInstanceCount);
+
+                    }
+                }
+            }
+
+            if (managerWkaMembers.size() >= managerMinInstanceCount) {
+                minManagerInstancesAvailable = true;
+                int idx = 0;
+                for (Member member : managerWkaMembers) {
+                    envParameters.put("STRATOS_WK_MANAGER_MEMBER_" + idx + "_IP", member.getMemberIp());
+                    if(log.isDebugEnabled()) {
+                        log.debug("STRATOS_WK_MANAGER_MEMBER_" + idx + "_IP: " + member.getMemberIp());
+                    }
+                    idx++;
+                }
+
+                envParameters.put("STRATOS_WK_MANAGER_MEMBER_COUNT", Integer.toString(managerMinInstanceCount));
+            }
+            
+            // If all the manager members are non primary and is greate than or equal to mincount, 
+            // minManagerInstancesAvailable should be true
+            boolean allManagersNonPrimary = true;
+            for (Member member : managerClusters.iterator().next().getMembers()) {
+            	
+            	// get the min instance count
+                if (!managerMinInstanceCountFound) {
+                    managerMinInstanceCount = getMinInstanceCountFromMemberProperties(member);
+                    managerMinInstanceCountFound = true;
+                    log.info("Manager min instance count when allManagersNonPrimary true : " + managerMinInstanceCount);
+                }
+                
+                if (member.getProperties() != null && member.getProperties().containsKey("PRIMARY") &&
+                            member.getProperties().getProperty("PRIMARY").toLowerCase().equals("true") ) {
+                	allManagersNonPrimary = false;
+                	break;
+                }
+            }
+            if(log.isDebugEnabled()){
+            	log.debug(" allManagerNonPrimary & managerMinInstanceCount [" 
+            		 + allManagersNonPrimary + "], [" + managerMinInstanceCount+"] ");
+            }
+			if (allManagersNonPrimary &&  managerClusters.size() >= managerMinInstanceCount) {
+				minManagerInstancesAvailable = true;
+			}
+
+            // worker cluster
+            Collection<Cluster> workerClusters = workerService.getClusters();
+            if (workerClusters == null || workerClusters.isEmpty()) {
+                log.warn("No clusters found for service [ "+ workerServiceName + " ]");
+                return false;
+            }
+
+            int workerMinInstanceCount = 1;
+            boolean workerMinInstanceCountFound = false;
+
+            List<Member> workerWkaMembers = new ArrayList<Member>();
+            for (Member member : workerClusters.iterator().next().getMembers()) {
+            	if (log.isDebugEnabled()) {
+            		log.debug("Checking member : " + member.getMemberId());
+            	}
+                if (member.getProperties() != null &&
+                        member.getProperties().containsKey("PRIMARY") &&
+                        member.getProperties().getProperty("PRIMARY").toLowerCase().equals("true") &&
+                        (member.getStatus().equals(MemberStatus.Starting) || member.getStatus().equals(MemberStatus.Activated))) {
+                	if (log.isDebugEnabled()) {
+                		log.debug("Added worker member " + member.getMemberId());
+                	}
+                    workerWkaMembers.add(member);
+                    this.wkMembers.add(member);
+
+                    // get the min instance count
+                    if (!workerMinInstanceCountFound) {
+                        workerMinInstanceCount = getMinInstanceCountFromMemberProperties(member);
+                        workerMinInstanceCountFound = true;
+                        if (log.isDebugEnabled()) {
+                            log.debug("Worker min instance count: " + workerMinInstanceCount);
+                        }
+                    }
+                }
+            }
+
+            if (workerWkaMembers.size() >= workerMinInstanceCount) {
+                minWorkerInstancesAvailable = true;
+                int idx = 0;
+                for (Member member : workerWkaMembers) {
+                    envParameters.put("STRATOS_WK_WORKER_MEMBER_" + idx + "_IP", member.getMemberIp());
+                    if (log.isDebugEnabled()) {
+                        log.debug("STRATOS_WK_WORKER_MEMBER_" + idx + "_IP: " + member.getMemberIp());
+                    }
+                    idx++;
+                }
+
+                envParameters.put("STRATOS_WK_WORKER_MEMBER_COUNT", Integer.toString(workerMinInstanceCount));
+            }
+
+        } finally {
+            TopologyManager.releaseReadLock();
+        }
+
+        if (log.isDebugEnabled()) {
+        	log.debug(" Returnning values minManagerInstancesAvailable && minWorkerInstancesAvailable [" +
+        		minManagerInstancesAvailable + "],  ["+ minWorkerInstancesAvailable+"] ");
+        }
+        return (minManagerInstancesAvailable && minWorkerInstancesAvailable);
+    }
+
+
+    private int getMinInstanceCountFromMemberProperties (Member member) {
+
+        // default value is 1
+        int minInstanceCount = 1;
+
+        if(member.getProperties().containsKey("MIN_COUNT")) {
+            minInstanceCount = Integer.parseInt(member.getProperties().getProperty("MIN_COUNT"));
+        }
+
+        return minInstanceCount;
+    }
+
+    private void waitForWKMembers(Map<String, String> envParameters) {
+        int minCount = Integer.parseInt(CartridgeAgentConfiguration.getInstance().getMinCount());
+        boolean isWKMemberGroupReady = false;
+        while (!isWKMemberGroupReady) {
+            if (log.isInfoEnabled()) {
+                log.info(String.format("Waiting for %d well known members...", minCount));
+            }
+            try {
+                Thread.sleep(5000);
+            } catch (InterruptedException e) {
+            }
+
+            TopologyManager.acquireReadLock();
+            isWKMemberGroupReady = isWKMemberGroupReady(envParameters, minCount);
+            TopologyManager.releaseReadLock();
+        }
+    }
+
+    @Override
+    public void startServerExtension() {
+
+        // wait until complete topology message is received to get LB IP
+        ExtensionUtils.waitForCompleteTopology();
+        if (log.isInfoEnabled()) {
+            log.info("[start server extension] complete topology event received");
+        }
+        String serviceNameInPayload = CartridgeAgentConfiguration.getInstance().getServiceName();
+        String clusterIdInPayload = CartridgeAgentConfiguration.getInstance().getClusterId();
+        String memberIdInPayload = CartridgeAgentConfiguration.getInstance().getMemberId();
+
+        try {
+            TopologyManager.acquireReadLock();
+            boolean isConsistent = ExtensionUtils.checkTopologyConsistency(serviceNameInPayload,
+                    clusterIdInPayload, memberIdInPayload);
+            if (!isConsistent) {
+                if (log.isErrorEnabled()) {
+                    log.error("Topology is inconsistent...failed to execute start server event");
+                }
+                return;
+            }
+            Topology topology = TopologyManager.getTopology();
+            Service service = topology.getService(serviceNameInPayload);
+            Cluster cluster = service.getCluster(clusterIdInPayload);
+
+            // store environment variable parameters to be passed to extension shell script
+            Map<String, String> env = new HashMap<String, String>();
+
+            // if clustering is enabled wait until all well known members have started
+            String flagClustering = CartridgeAgentConfiguration.getInstance().getIsClustered();
+            if (flagClustering != null && flagClustering.toLowerCase().equals("true")) {
+                env.put("STRATOS_CLUSTERING", "true");
+                env.put("STRATOS_WK_MEMBER_COUNT", CartridgeAgentConfiguration.getInstance().getMinCount());
+                if (CartridgeAgentConfiguration.getInstance().getIsPrimary().toLowerCase().equals("true")) {
+                    env.put("STRATOS_PRIMARY", "true");
+                } else {
+                    env.put("STRATOS_PRIMARY", "false");
+                }
+                TopologyManager.releaseReadLock();
+                waitForWKMembers(env);
+                if (log.isInfoEnabled()) {
+                    log.info(String.format("All well known members have started! Resuming start server extension..."));
+                }
+                TopologyManager.acquireReadLock();
+            }
+
+            env.put("STRATOS_TOPOLOGY_JSON", gson.toJson(topology.getServices(), serviceType));
+            env.put("STRATOS_MEMBER_LIST_JSON", gson.toJson(cluster.getMembers(), memberType));
+            ExtensionUtils.executeStartServersExtension(env);
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Error processing start servers event", e);
+            }
+        } finally {
+            TopologyManager.releaseReadLock();
+        }
+    }
+
+    @Override
+    public void volumeMountExtension(String persistenceMappingsPayload) {
+        ExtensionUtils.executeVolumeMountExtension(persistenceMappingsPayload);
+    }
+
+    @Override
+    public void onSubscriptionDomainAddedEvent(SubscriptionDomainAddedEvent subscriptionDomainAddedEvent) {
+        String tenantDomain = findTenantDomain(subscriptionDomainAddedEvent.getTenantId());
+        if (log.isInfoEnabled()) {
+            log.info(String.format("Subscription domain added event received: [tenant-id] %d [tenant-domain] %s " +
+                            "[domain-name] %s [application-context] %s",
+                    subscriptionDomainAddedEvent.getTenantId(),
+                    tenantDomain,
+                    subscriptionDomainAddedEvent.getDomainName(),
+                    subscriptionDomainAddedEvent.getApplicationContext()
+            ));
+        }
+
+        if (log.isDebugEnabled()) {
+            String msg = gson.toJson(subscriptionDomainAddedEvent);
+            log.debug("Subscription domain added event msg:" + msg);
+        }
+
+        Map<String, String> env = new HashMap<String, String>();
+        env.put("STRATOS_SUBSCRIPTION_SERVICE_NAME", subscriptionDomainAddedEvent.getServiceName());
+        env.put("STRATOS_SUBSCRIPTION_DOMAIN_NAME", subscriptionDomainAddedEvent.getDomainName());
+        env.put("STRATOS_SUBSCRIPTION_TENANT_ID", Integer.toString(subscriptionDomainAddedEvent.getTenantId()));
+        env.put("STRATOS_SUBSCRIPTION_TENANT_DOMAIN", tenantDomain);
+        env.put("STRATOS_SUBSCRIPTION_APPLICATION_CONTEXT", subscriptionDomainAddedEvent.getApplicationContext());
+        ExtensionUtils.executeSubscriptionDomainAddedExtension(env);
+    }
+
+    private String findTenantDomain(int tenantId) {
+        try {
+            TenantManager.acquireReadLock();
+            Tenant tenant = TenantManager.getInstance().getTenant(tenantId);
+            if (tenant == null) {
+                throw new RuntimeException(String.format("Tenant could not be found: [tenant-id] %d", tenantId));
+            }
+            return tenant.getTenantDomain();
+        } finally {
+            TenantManager.releaseReadLock();
+        }
+    }
+
+    @Override
+    public void onSubscriptionDomainRemovedEvent(SubscriptionDomainRemovedEvent subscriptionDomainRemovedEvent) {
+        String tenantDomain = findTenantDomain(subscriptionDomainRemovedEvent.getTenantId());
+        if (log.isInfoEnabled()) {
+            log.info(String.format("Subscription domain removed event received: [tenant-id] %d [tenant-domain] %s " +
+                            "[domain-name] %s",
+                    subscriptionDomainRemovedEvent.getTenantId(),
+                    tenantDomain,
+                    subscriptionDomainRemovedEvent.getDomainName()
+            ));
+        }
+
+        if (log.isDebugEnabled()) {
+            String msg = gson.toJson(subscriptionDomainRemovedEvent);
+            log.debug("Subscription domain removed event msg:" + msg);
+        }
+
+        Map<String, String> env = new HashMap<String, String>();
+        env.put("STRATOS_SUBSCRIPTION_SERVICE_NAME", subscriptionDomainRemovedEvent.getServiceName());
+        env.put("STRATOS_SUBSCRIPTION_DOMAIN_NAME", subscriptionDomainRemovedEvent.getDomainName());
+        env.put("STRATOS_SUBSCRIPTION_TENANT_ID", Integer.toString(subscriptionDomainRemovedEvent.getTenantId()));
+        env.put("STRATOS_SUBSCRIPTION_TENANT_DOMAIN", tenantDomain);
+        ExtensionUtils.executeSubscriptionDomainRemovedExtension(env);
+    }
+
+    @Override
+    public void onCopyArtifactsExtension(String src, String des) {
+        ExtensionUtils.executeCopyArtifactsExtension(src, des);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/extensions/ExtensionHandler.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/extensions/ExtensionHandler.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/extensions/ExtensionHandler.java
new file mode 100644
index 0000000..1ab380c
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/extensions/ExtensionHandler.java
@@ -0,0 +1,64 @@
+/*
+ * 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.cartridge.agent.extensions;
+
+import org.apache.stratos.messaging.event.instance.notifier.ArtifactUpdatedEvent;
+import org.apache.stratos.messaging.event.instance.notifier.InstanceCleanupClusterEvent;
+import org.apache.stratos.messaging.event.instance.notifier.InstanceCleanupMemberEvent;
+import org.apache.stratos.messaging.event.tenant.CompleteTenantEvent;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainAddedEvent;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainRemovedEvent;
+import org.apache.stratos.messaging.event.topology.*;
+
+public interface ExtensionHandler {
+    public void onInstanceStartedEvent();
+
+    public void onInstanceActivatedEvent();
+
+    public void onArtifactUpdatedEvent(ArtifactUpdatedEvent event);
+
+    public void onArtifactUpdateSchedulerEvent(String tenantId);
+
+    public void onInstanceCleanupClusterEvent(InstanceCleanupClusterEvent instanceCleanupClusterEvent);
+
+    public void onInstanceCleanupMemberEvent(InstanceCleanupMemberEvent instanceCleanupMemberEvent);
+
+    public void onMemberActivatedEvent(MemberActivatedEvent memberActivatedEvent);
+
+    public void onCompleteTopologyEvent(CompleteTopologyEvent completeTopologyEvent);
+
+    public void onCompleteTenantEvent(CompleteTenantEvent completeTenantEvent);
+
+    public void onMemberTerminatedEvent(MemberTerminatedEvent memberTerminatedEvent);
+
+    public void onMemberSuspendedEvent(MemberSuspendedEvent memberSuspendedEvent);
+
+    public void onMemberStartedEvent(MemberStartedEvent memberStartedEvent);
+
+    public void startServerExtension();
+
+    public void volumeMountExtension(String persistenceMappingsPayload);
+
+    public void onSubscriptionDomainAddedEvent(SubscriptionDomainAddedEvent subscriptionDomainAddedEvent);
+
+    public void onSubscriptionDomainRemovedEvent(SubscriptionDomainRemovedEvent subscriptionDomainRemovedEvent);
+
+    public void onCopyArtifactsExtension(String src, String des);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentConstants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentConstants.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentConstants.java
index 8434d6d..eb70a3b 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentConstants.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentConstants.java
@@ -27,30 +27,68 @@ public class CartridgeAgentConstants implements Serializable{
 	public static final String PARAM_FILE_PATH = "param.file.path";
     public static final String EXTENSIONS_DIR = "extensions.dir";
 
-    public static final String INSTANCE_STARTED_SH = "instance-started.sh";
-    public static final String START_SERVERS_SH = "start-servers.sh";
-    public static final String INSTANCE_ACTIVATED_SH = "instance-activated.sh";
-    public static final String ARTIFACTS_UPDATED_SH = "artifacts-updated.sh";
-    public static final String CLEAN_UP_SH = "clean.sh";
-    public static final String MOUNT_VOLUMES_SH = "mount_volumes.sh";
-	
+	// payload parameters keys
 	public static final String CARTRIDGE_KEY = "CARTRIDGE_KEY";
 	public static final String APP_PATH = "APP_PATH";
-	public static final String SERVICE_NAME = "SERVICE_NAME";
+    public static final String SERVICE_GROUP = "SERIVCE_GROUP";
+    public static final String SERVICE_NAME = "SERVICE_NAME";
     public static final String CLUSTER_ID = "CLUSTER_ID";
+    public static final String LB_CLUSTER_ID = "LB_CLUSTER_ID";
     public static final String NETWORK_PARTITION_ID = "NETWORK_PARTITION_ID";
     public static final String PARTITION_ID = "PARTITION_ID";
     public static final String MEMBER_ID = "MEMBER_ID";
+    public static final String TENANT_ID= "TENANT_ID";
     public static final String REPO_URL = "REPO_URL";
     public static final String PORTS = "PORTS";
+    public static final String DEPLOYMENT = "DEPLOYMENT";
+    public static final String MANAGER_SERVICE_TYPE = "MANAGER_SERVICE_TYPE";
+    public static final String WORKER_SERVICE_TYPE = "WORKER_SERVICE_TYPE";
+
+    // stratos.sh environment variables keys
     public static final String LOG_FILE_PATHS = "LOG_FILE_PATHS";
     public static final String MEMORY_CONSUMPTION = "memory_consumption";
     public static final String LOAD_AVERAGE = "load_average";
     public static final String PORTS_NOT_OPEN = "ports_not_open";
     public static final String MULTITENANT = "MULTITENANT";
+    public static final String CLUSTERING = "CLUSTERING";
+    public static final String MIN_INSTANCE_COUNT = "MIN_COUNT";
     public static final String ENABLE_ARTIFACT_UPDATE = "enable.artifact.update";
     public static final String ARTIFACT_UPDATE_INTERVAL = "artifact.update.interval";
     public static final String COMMIT_ENABLED = "COMMIT_ENABLED";
-
+    public static final String AUTO_COMMIT = "auto.commit";
+    public static final String AUTO_CHECKOUT = "auto.checkout";
     public static final String LISTEN_ADDRESS = "listen.address";
+    public static final String PROVIDER = "PROVIDER";
+    public static final String INTERNAL = "internal";
+    public static final String LB_PRIVATE_IP = "lb.private.ip";
+    public static final String LB_PUBLIC_IP = "lb.public.ip";
+
+    // stratos.sh extension points shell scripts names keys
+    public static final String INSTANCE_STARTED_SCRIPT = "extension.instance.started";
+    public static final String START_SERVERS_SCRIPT = "extension.start.servers";
+    public static final String INSTANCE_ACTIVATED_SCRIPT = "extension.instance.activated";
+    public static final String ARTIFACTS_UPDATED_SCRIPT = "extension.artifacts.updated";
+    public static final String CLEAN_UP_SCRIPT = "extension.clean";
+    public static final String MOUNT_VOLUMES_SCRIPT = "extension.mount.volumes";
+    public static final String MEMBER_ACTIVATED_SCRIPT = "extension.member.activated";
+    public static final String MEMBER_TERMINATED_SCRIPT = "extension.member.terminated";
+    public static final String MEMBER_SUSPENDED_SCRIPT = "extension.member.suspended";
+    public static final String MEMBER_STARTED_SCRIPT = "extension.member.started";
+    public static final String COMPLETE_TOPOLOGY_SCRIPT = "extension.complete.topology";
+    public static final String COMPLETE_TENANT_SCRIPT = "extension.complete.tenant";
+    public static final String SUBSCRIPTION_DOMAIN_ADDED_SCRIPT = "extension.subscription.domain.added";
+    public static final String SUBSCRIPTION_DOMAIN_REMOVED_SCRIPT = "extension.subscription.domain.removed";
+    public static final String ARTIFACTS_COPY_SCRIPT = "extension.artifacts.copy";
+
+    public static final String SERVICE_GROUP_TOPOLOGY_KEY = "payload_parameter.SERIVCE_GROUP";
+    public static final String CLUSTERING_TOPOLOGY_KEY = "payload_parameter.CLUSTERING";
+    public static final String CLUSTERING_PRIMARY_KEY = "PRIMARY";
+    
+    public static final String SUPERTENANT_TEMP_PATH = "/tmp/-1234/";
+
+    public static final String DEPLOYMENT_MANAGER = "manager";
+    public static final String DEPLOYMENT_WORKER = "worker";
+    public static final String DEPLOYMENT_DEFAULT = "default";
+    public static final String SUPER_TENANT_REPO_PATH = "super.tenant.repository.path";
+    public static final String TENANT_REPO_PATH = "tenant.repository.path";
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentUtils.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentUtils.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentUtils.java
index 8abb285..010462d 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentUtils.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/CartridgeAgentUtils.java
@@ -94,7 +94,7 @@ public class CartridgeAgentUtils {
         boolean active = false;
         while (!active) {
             if(log.isInfoEnabled()) {
-                log.info("Waiting for ports to be active: [IP] "+ipAddress+" [Ports] "+ports);
+                log.info("Waiting for ports to be active: [ip] "+ipAddress+" [ports] "+ports);
             }
             active = checkPortsActive(ipAddress,  ports);
             long endTime = System.currentTimeMillis();
@@ -107,6 +107,9 @@ public class CartridgeAgentUtils {
             } catch (InterruptedException e) {
             }
         }
+        if(log.isInfoEnabled()) {
+            log.info("Ports activated: [ip] " + ipAddress + " [ports] "+ports);
+        }
     }
 
     public static boolean checkPortsActive(String ipAddress, List<Integer> ports) {


[07/14] Clustering changes for stratos

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/ExtensionUtils.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/ExtensionUtils.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/ExtensionUtils.java
index 2a11103..ed7d3bb 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/ExtensionUtils.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/util/ExtensionUtils.java
@@ -24,8 +24,18 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
 import org.apache.stratos.common.util.CommandUtils;
+import org.apache.stratos.messaging.domain.topology.Cluster;
+import org.apache.stratos.messaging.domain.topology.Member;
+import org.apache.stratos.messaging.domain.topology.Service;
+import org.apache.stratos.messaging.domain.topology.Topology;
+import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 
 import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
 
 /**
  * Cartridge agent extension utility methods.
@@ -35,81 +45,272 @@ public class ExtensionUtils {
 
     private static String getExtensionsDir() {
         String extensionsDir = System.getProperty(CartridgeAgentConstants.EXTENSIONS_DIR);
-        if(StringUtils.isBlank(extensionsDir)) {
+        if (StringUtils.isBlank(extensionsDir)) {
             throw new RuntimeException(String.format("System property not found: %s", CartridgeAgentConstants.EXTENSIONS_DIR));
         }
         return extensionsDir;
     }
 
-    private static String prepareCommand(String scriptFile) {
+    private static String prepareCommand(String scriptFile) throws FileNotFoundException {
         String extensionsDir = getExtensionsDir();
-        return (extensionsDir.endsWith(File.separator)) ?
-                extensionsDir + scriptFile:
+        String filePath = (extensionsDir.endsWith(File.separator)) ?
+                extensionsDir + scriptFile :
                 extensionsDir + File.separator + scriptFile;
+
+        File file = new File(filePath);
+        if (file.exists() && !file.isDirectory()) {
+            return filePath;
+        }
+
+        throw new FileNotFoundException("Script file not found:" + filePath);
     }
 
-    public static void executeStartServersExtension() {
-        try {
-            if(log.isDebugEnabled()) {
-                log.debug("Executing start servers extension");
+    public static void addPayloadParameters(Map<String, String> envParameters){
+        envParameters.put("STRATOS_APP_PATH", CartridgeAgentConfiguration.getInstance().getAppPath());
+        envParameters.put("STRATOS_PARAM_FILE_PATH", System.getProperty(CartridgeAgentConstants.PARAM_FILE_PATH));
+        envParameters.put("STRATOS_SERVICE_NAME", CartridgeAgentConfiguration.getInstance().getServiceName());
+        envParameters.put("STRATOS_TENANT_ID", CartridgeAgentConfiguration.getInstance().getTenantId());
+        envParameters.put("STRATOS_CARTRIDGE_KEY", CartridgeAgentConfiguration.getInstance().getCartridgeKey());
+        envParameters.put("STRATOS_LB_CLUSTER_ID", CartridgeAgentConfiguration.getInstance().getLbClusterId());
+        envParameters.put("STRATOS_CLUSTER_ID", CartridgeAgentConfiguration.getInstance().getClusterId());
+        envParameters.put("STRATOS_NETWORK_PARTITION_ID", CartridgeAgentConfiguration.getInstance().getNetworkPartitionId());
+        envParameters.put("STRATOS_PARTITION_ID", CartridgeAgentConfiguration.getInstance().getPartitionId());
+        envParameters.put("STRATOS_PERSISTENCE_MAPPINGS", CartridgeAgentConfiguration.getInstance().getPersistenceMappings());
+        envParameters.put("STRATOS_REPO_URL", CartridgeAgentConfiguration.getInstance().getRepoUrl());
+
+        // Add LB instance public/private IPs to environment parameters
+        String lbClusterIdInPayload = CartridgeAgentConfiguration.getInstance().getLbClusterId();
+        String[] memberIps = getLbMemberIp(lbClusterIdInPayload);
+        String lbIp, lbPublicIp;
+        if (memberIps != null && memberIps.length > 1) {
+        	lbIp = memberIps[0];
+        	lbPublicIp = memberIps[1];
+        } else {
+        	lbIp = CartridgeAgentConfiguration.getInstance().getLbPrivateIp();
+        	lbPublicIp = CartridgeAgentConfiguration.getInstance().getLbPublicIp();
+        }
+        
+        envParameters.put("STRATOS_LB_IP", lbIp);
+        envParameters.put("STRATOS_LB_PUBLIC_IP", lbPublicIp);
+
+        Topology topology = TopologyManager.getTopology();
+        if (topology.isInitialized()){
+            Service service = topology.getService(CartridgeAgentConfiguration.getInstance().getServiceName());
+            Cluster cluster = service.getCluster(CartridgeAgentConfiguration.getInstance().getClusterId());
+            String memberIdInPayload = CartridgeAgentConfiguration.getInstance().getMemberId();
+            addProperties(service.getProperties(), envParameters, "SERVICE_PROPERTY");
+            addProperties(cluster.getProperties(), envParameters, "CLUSTER_PROPERTY");
+            addProperties(cluster.getMember(memberIdInPayload).getProperties(), envParameters, "MEMBER_PROPERTY");
+        }
+    }
+
+    public static void addProperties(Properties properties, Map<String, String> envParameters, String prefix){
+        if (properties == null || properties.entrySet() == null){
+            return;
+        }
+        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+            envParameters.put("STRATOS_ " + prefix + "_" + entry.getKey().toString(), entry.getValue().toString());
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Property added: [key] %s [value] %s",
+                        "STRATOS_ " + prefix + "_" + entry.getKey().toString(), entry.getValue().toString()));
             }
-            String command = prepareCommand(CartridgeAgentConstants.START_SERVERS_SH);
-            CommandUtils.executeCommand(command);
         }
-        catch (Exception e) {
-            log.error("Could not execute start servers extension", e);
+    }
+
+    public static String[] getLbMemberIp(String lbClusterId) {
+        Topology topology = TopologyManager.getTopology();
+        Collection<Service> serviceCollection = topology.getServices();
+
+        for (Service service : serviceCollection) {
+            Collection<Cluster> clusterCollection = service.getClusters();
+            for (Cluster cluster : clusterCollection) {
+                Collection<Member> memberCollection = cluster.getMembers();
+                for (Member member : memberCollection) {
+                    if (member.getClusterId().equals(lbClusterId)) {
+                        return new String[]{member.getMemberIp(), member.getMemberPublicIp()};
+                    }
+                }
+            }
         }
+        return null;
     }
 
-    public static void executeCleanupExtension() {
+    public static boolean isRelevantMemberEvent(String serviceName, String clusterId, String lbClusterId) {
+        String clusterIdInPayload = CartridgeAgentConfiguration.getInstance().getClusterId();
+        if (clusterIdInPayload == null) {
+            return false;
+        }
+        Topology topology = TopologyManager.getTopology();
+        if (topology == null || !topology.isInitialized()) {
+            return false;
+        }
+
+        if (clusterIdInPayload.equals(clusterId)) {
+            return true;
+        }
+
+        if (clusterIdInPayload.equals(lbClusterId)) {
+            return true;
+        }
+
+        String serviceGroupInPayload = CartridgeAgentConfiguration.getInstance().getServiceGroup();
+        if (serviceGroupInPayload != null) {
+            Properties serviceProperties = topology.getService(serviceName).getProperties();
+            if (serviceProperties == null) {
+                return false;
+            }
+            String memberServiceGroup = serviceProperties.getProperty(CartridgeAgentConstants.SERVICE_GROUP_TOPOLOGY_KEY);
+            if (memberServiceGroup != null && memberServiceGroup.equals(serviceGroupInPayload)) {            	
+            	if(serviceName.equals(CartridgeAgentConfiguration.getInstance().getServiceName())) {
+            		if (log.isDebugEnabled()) {
+            			log.debug("Service names are same");
+            		}
+            		return true;
+            	}else if(CartridgeAgentConfiguration.getInstance().getServiceName().equals("apistore") && "publisher".equals(serviceName)) {
+            		if (log.isDebugEnabled()) {
+            			log.debug("Service name in payload is [store]. Serivce name in event is ["+serviceName+"] ");
+            		}
+            		return true;
+            	}else if(CartridgeAgentConfiguration.getInstance().getServiceName().equals("publisher") && "apistore".equals(serviceName)) {
+            		if (log.isDebugEnabled()) {
+            			log.debug("Service name in payload is [publisher]. Serivce name in event is ["+serviceName+"] ");
+            		}
+            		return true;
+            	}else if(CartridgeAgentConstants.DEPLOYMENT_WORKER.equals(CartridgeAgentConfiguration.getInstance().getDeployment()) &&
+            			serviceName.equals(CartridgeAgentConfiguration.getInstance().getManagerServiceName())) {
+            		if (log.isDebugEnabled()) {
+            			log.debug("Deployment is worker. Worker's manager service name & service name in event are same");
+            		}
+            		return true;
+            	}else if (CartridgeAgentConstants.DEPLOYMENT_MANAGER.equals(CartridgeAgentConfiguration.getInstance().getDeployment()) &&
+            			serviceName.equals(CartridgeAgentConfiguration.getInstance().getWorkerServiceName())) {
+            		if (log.isDebugEnabled()) {
+            			log.debug("Deployment is manager. Manager's worker service name & service name in event are same");
+            		}
+            		return true;
+            	}
+            }
+        }
+                
+        return false;
+    }
+
+    private static Map<String, String> cleanProcessParameters(Map<String, String> envParameters) {
+        Iterator<Map.Entry<String, String>> iter = envParameters.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry<String, String> entry = iter.next();
+            if (entry.getValue() == null) {
+                iter.remove();
+            }
+        }
+        return envParameters;
+    }
+
+    public static void executeStartServersExtension(Map<String, String> envParameters) {
         try {
-            if(log.isDebugEnabled()) {
+            if (log.isDebugEnabled()) {
                 log.debug("Executing start servers extension");
             }
-            String command = prepareCommand(CartridgeAgentConstants.CLEAN_UP_SH);
-            CommandUtils.executeCommand(command);
+            String script = System.getProperty(CartridgeAgentConstants.START_SERVERS_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Start server script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute start servers extension", e);
+            }
         }
-        catch (Exception e) {
-            log.error("Could not execute start servers extension", e);
+    }
+
+    public static void executeCleanupExtension() {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing cleanup extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.CLEAN_UP_SCRIPT);
+            String command = prepareCommand(script);
+            String output = CommandUtils.executeCommand(command);
+            if (log.isDebugEnabled()) {
+                log.debug("Cleanup script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute cleanup extension", e);
+            }
         }
     }
 
-    public static void executeInstanceStartedExtension() {
+    public static void executeInstanceStartedExtension(Map<String, String> envParameters) {
         try {
-            if(log.isDebugEnabled()) {
+            if (log.isDebugEnabled()) {
                 log.debug("Executing instance started extension");
             }
-            String command = prepareCommand(CartridgeAgentConstants.INSTANCE_STARTED_SH);
-            CommandUtils.executeCommand(command);
-        }
-        catch (Exception e) {
-            log.error("Could not execute instance started extension", e);
+            String script = System.getProperty(CartridgeAgentConstants.INSTANCE_STARTED_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Instance started script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute instance started extension", e);
+            }
         }
     }
 
     public static void executeInstanceActivatedExtension() {
         try {
-            if(log.isDebugEnabled()) {
+            if (log.isDebugEnabled()) {
                 log.debug("Executing instance activated extension");
             }
-            String command = prepareCommand(CartridgeAgentConstants.INSTANCE_ACTIVATED_SH);
-            CommandUtils.executeCommand(command);
-        }
-        catch (Exception e) {
-            log.error("Could not execute instance activated extension", e);
+            String script = System.getProperty(CartridgeAgentConstants.INSTANCE_ACTIVATED_SCRIPT);
+            String command = prepareCommand(script);
+            String output = CommandUtils.executeCommand(command);
+            if (log.isDebugEnabled()) {
+                log.debug("Instance activated script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute instance activated extension", e);
+            }
         }
     }
 
-    public static void executeArtifactsUpdatedExtension() {
+    public static void executeArtifactsUpdatedExtension(Map<String, String> envParameters) {
         try {
-            if(log.isDebugEnabled()) {
+            if (log.isDebugEnabled()) {
                 log.debug("Executing artifacts updated extension");
             }
-            String command = prepareCommand(CartridgeAgentConstants.ARTIFACTS_UPDATED_SH);
-            CommandUtils.executeCommand(command);
+            String script = System.getProperty(CartridgeAgentConstants.ARTIFACTS_UPDATED_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Artifacts updated script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute artifacts updated extension", e);
+            }
         }
-        catch (Exception e) {
-            log.error("Could not execute artifacts updated extension", e);
+    }
+
+    public static void executeCopyArtifactsExtension(String source, String destination) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing artifacts copy extension");
+            }
+            String command = prepareCommand(System.getProperty(CartridgeAgentConstants.ARTIFACTS_COPY_SCRIPT));
+            CommandUtils.executeCommand(command + " " + source + " " + destination);
+        } catch (Exception e) {
+            log.error("Could not execute artifacts copy extension", e);
         }
     }
 
@@ -117,19 +318,230 @@ public class ExtensionUtils {
     This will execute the volume mounting script which format and mount the
     persistance volumes.
      */
-    public static void executeVolumeMountExtension(String persistanceMappingsPayload) {
+    public static void executeVolumeMountExtension(String persistenceMappingsPayload) {
         try {
-            if(log.isDebugEnabled()) {
-                    log.debug("Executing volume mounting extension");
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Executing volume mounting extension: [payload] %s", persistenceMappingsPayload));
             }
-            String command = prepareCommand(CartridgeAgentConstants.MOUNT_VOLUMES_SH);
+            String script = System.getProperty(CartridgeAgentConstants.MOUNT_VOLUMES_SCRIPT);
+            String command = prepareCommand(script);
             //String payloadPath = System.getProperty(CartridgeAgentConstants.PARAM_FILE_PATH);
             // add payload file path as argument so inside the script we can source
             // it  to get the env variables set by the startup script
-            CommandUtils.executeCommand(command + " " + persistanceMappingsPayload);
-        }
-        catch (Exception e) {
+            String output = CommandUtils.executeCommand(command + " " + persistenceMappingsPayload);
+            if (log.isDebugEnabled()) {
+                log.debug("Volume mount script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
                 log.error("Could not execute volume mounting extension", e);
+            }
+        }
+    }
+
+    public static void executeMemberActivatedExtension(Map<String, String> envParameters) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing member activated extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.MEMBER_ACTIVATED_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Member activated script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute member activated extension", e);
+            }
+        }
+    }
+
+    public static void executeMemberTerminatedExtension(Map<String, String> envParameters) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing member terminated extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.MEMBER_TERMINATED_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Member terminated script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute member terminated extension", e);
+            }
+        }
+    }
+
+    public static void executeMemberStartedExtension(Map<String, String> envParameters) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing member started extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.MEMBER_STARTED_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Member started script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute member started extension", e);
+            }
+        }
+    }
+
+    public static void executeMemberSuspendedExtension(Map<String, String> envParameters) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing member suspended extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.MEMBER_SUSPENDED_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Member suspended script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute member suspended extension", e);
+            }
+        }
+    }
+
+    public static void executeCompleteTopologyExtension(Map<String, String> envParameters) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing complete topology extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.COMPLETE_TOPOLOGY_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Complete topology script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute complete topology extension", e);
+            }
+        }
+    }
+
+    public static void executeCompleteTenantExtension(Map<String, String> envParameters) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing complete tenant extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.COMPLETE_TENANT_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Complete tenant script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute complete tenant extension", e);
+            }
+        }
+    }
+
+    public static void executeSubscriptionDomainAddedExtension(Map<String, String> envParameters) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing subscription domain added extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.SUBSCRIPTION_DOMAIN_ADDED_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Subscription domain added script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute subscription domain added extension", e);
+            }
+        }
+    }
+
+    public static void executeSubscriptionDomainRemovedExtension(Map<String, String> envParameters) {
+        try {
+            if (log.isDebugEnabled()) {
+                log.debug("Executing subscription domain removed extension");
+            }
+            String script = System.getProperty(CartridgeAgentConstants.SUBSCRIPTION_DOMAIN_REMOVED_SCRIPT);
+            String command = prepareCommand(script);
+            addPayloadParameters(envParameters);
+            cleanProcessParameters(envParameters);
+            String output = CommandUtils.executeCommand(command, envParameters);
+            if (log.isDebugEnabled()) {
+                log.debug("Subscription domain removed script returned:" + output);
+            }
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Could not execute subscription domain removed extension", e);
+            }
+
+        }
+    }
+
+    public static boolean isTopologyInitialized() {
+        TopologyManager.acquireReadLock();
+        boolean active = TopologyManager.getTopology().isInitialized();
+        TopologyManager.releaseReadLock();
+        return active;
+    }
+
+    public static void waitForCompleteTopology() {
+        while (!isTopologyInitialized()) {
+            if (log.isInfoEnabled()) {
+                log.info("Waiting for complete topology event...");
+            }
+            try {
+                Thread.sleep(5000);
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    public static boolean checkTopologyConsistency(String serviceName, String clusterId, String memberId){
+        Topology topology = TopologyManager.getTopology();
+        Service service = topology.getService(serviceName);
+        if (service == null) {
+            if (log.isErrorEnabled()) {
+                log.error(String.format("Service not found in topology [service] %s", serviceName));
+            }
+            return false;
+        }
+        Cluster cluster = service.getCluster(clusterId);
+        if (cluster == null) {
+            if (log.isErrorEnabled()) {
+                log.error(String.format("Cluster id not found in topology [cluster] %s", clusterId));
+            }
+            return false;
+        }
+        Member activatedMember = cluster.getMember(memberId);
+        if (activatedMember == null) {
+            if (log.isErrorEnabled()) {
+                log.error(String.format("Member id not found in topology [member] %s", memberId));
+            }
+            return false;
         }
+        return true;
     }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/RestCommandLineService.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/RestCommandLineService.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/RestCommandLineService.java
index 10c9d9e..857d1a1 100644
--- a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/RestCommandLineService.java
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/RestCommandLineService.java
@@ -94,6 +94,8 @@ public class RestCommandLineService {
     private final String deactivateTenantRestEndPoint = "/stratos/admin/tenant/deactivate";
     private final String activateTenantRestEndPoint = "/stratos/admin/tenant/activate";
     private final String listAllTenantRestEndPoint = "/stratos/admin/tenant/list";
+    private final String getListAvailableCartridgeInfoRestEndPoint = "/stratos/admin/cartridge/available/info";
+
 
     private static class SingletonHolder {
 		private final static RestCommandLineService INSTANCE = new RestCommandLineService();
@@ -210,6 +212,84 @@ public class RestCommandLineService {
         this.restClient = restClient;
     }
 
+    public Cartridge listCartridge(String cartridgeType) throws CommandException{
+        DefaultHttpClient httpClient = new DefaultHttpClient();
+        HttpResponse response = null;
+
+        try {
+            String endpoint = restClient.getBaseURL() + getListAvailableCartridgeInfoRestEndPoint + "/" + cartridgeType;
+            response = restClient.doGet(httpClient, endpoint);
+
+            String responseCode = "" + response.getStatusLine().getStatusCode();
+            String resultString = getHttpResponseString(response);
+            if (resultString == null) {
+                return null;
+            }
+
+            GsonBuilder gsonBuilder = new GsonBuilder();
+            Gson gson = gsonBuilder.create();
+
+            if (!responseCode.equals(CliConstants.RESPONSE_OK)) {
+                ExceptionMapper exception = gson.fromJson(resultString, ExceptionMapper.class);
+                System.out.println(exception);
+                return null;
+            }
+
+            String cartridgeString = resultString.substring(13, resultString.length() -1);
+            Cartridge cartridge = gson.fromJson(cartridgeString, Cartridge.class);
+            return cartridge;
+
+        } catch (Exception e) {
+            handleException("Exception in listing cartridge info", e);
+            return null;
+        } finally {
+            httpClient.getConnectionManager().shutdown();
+        }
+    }
+
+    public ArrayList<Cartridge> listCartridges(String serviceGroup) throws CommandException{
+        DefaultHttpClient httpClient = new DefaultHttpClient();
+        HttpResponse response = null;
+
+        try {
+            response = restClient.doGet(httpClient, restClient.getBaseURL() + listAvailableCartridgesRestEndpoint);
+
+            String responseCode = "" + response.getStatusLine().getStatusCode();
+            String resultString = getHttpResponseString(response);
+
+            if (resultString == null) {
+                return null;
+            }
+
+            GsonBuilder gsonBuilder = new GsonBuilder();
+            Gson gson = gsonBuilder.create();
+
+            if (!responseCode.equals(CliConstants.RESPONSE_OK)) {
+                ExceptionMapper exception = gson.fromJson(resultString, ExceptionMapper.class);
+                System.out.println(exception);
+                return null;
+            }
+
+            CartridgeList cartridgeList = gson.fromJson(resultString, CartridgeList.class);
+
+            ArrayList<Cartridge> cartridgesInServiceGroup = new ArrayList<Cartridge>();
+
+            for (int i = 0; i < cartridgeList.getCartridge().size(); i++) {
+                if (serviceGroup.equals(cartridgeList.getCartridge().get(i).getServiceGroup())) {
+                    cartridgesInServiceGroup.add(cartridgeList.getCartridge().get(i));
+                }
+            }
+
+            return cartridgesInServiceGroup;
+
+        } catch (Exception e) {
+            handleException("Exception in listing cartridge info", e);
+            return null;
+        } finally {
+            httpClient.getConnectionManager().shutdown();
+        }
+    }
+
     // List currently available multi tenant and single tenant cartridges
     public void listAvailableCartridges() throws CommandException {
         DefaultHttpClient httpClient = new DefaultHttpClient();
@@ -244,7 +324,14 @@ public class RestCommandLineService {
             ArrayList<Cartridge> multiTenetCartridge = new ArrayList<Cartridge>();
             ArrayList<Cartridge> singleTentCartridge = new ArrayList<Cartridge>();
 
+            HashSet<String> existingServiceGroups = new HashSet<String>();
+
             for (Cartridge cartridge : cartridgeList.getCartridge()) {
+                if(existingServiceGroups.contains(cartridge.getServiceGroup())){
+                    continue;
+                }else{
+                    existingServiceGroups.add(cartridge.getServiceGroup());
+                }
                 if (cartridge.isMultiTenant()) {
                     multiTenetCartridge.add(cartridge);
                 }
@@ -361,7 +448,6 @@ public class RestCommandLineService {
 
             String responseCode = "" + response.getStatusLine().getStatusCode();
             String resultString = getHttpResponseString(response);
-            
             GsonBuilder gsonBuilder = new GsonBuilder();
             Gson gson = gsonBuilder.create();
             
@@ -489,7 +575,7 @@ public class RestCommandLineService {
             System.out.println("\tTenancy Model	: "	+ tenancy);
             System.out.println("\tAlias : "	+ cartridge.getCartridgeAlias());
             System.out.println("\tStatus : "	+ cartridge.getStatus());
-            String instanceCount  = cartridge.isMultiTenant() ? "N/A" : String.valueOf(cartridge.getActiveInstances());
+            String instanceCount  = String.valueOf(cartridge.getActiveInstances());
             System.out.println("\tRunning Instances	: " + instanceCount);
             System.out.println("\tAccess URL(s) : " + getAccessURLs(cartridge));
 			if (cartridge.getRepoURL() != null) {
@@ -534,7 +620,7 @@ public class RestCommandLineService {
             // Invoke  cluster/{clusterId}
             for (String clusterId : lbClusterIdSet) {
 				HttpResponse responseCluster = restClient.doGet(httpClient, restClient.getBaseURL()
-						+ listClusterRestEndpoint + "clusterId/" + clusterId);
+						+ listClusterRestEndpoint + "lb");
 
                 String responseCode = "" + responseCluster.getStatusLine().getStatusCode();
                 String resultStringCluster = getHttpResponseString(responseCluster);
@@ -548,8 +634,8 @@ public class RestCommandLineService {
                     return null;
                 }
 
-                Cluster cluster = getClusterObjectFromString(resultStringCluster);
-
+                ArrayList<Cluster> clusterList = getClusterListObjectFromString(resultStringCluster);
+                Cluster cluster = clusterList.get(0);
                 if (cluster == null) {
                     System.out.println("Subscribe cartridge list is null");
                     return null;
@@ -683,6 +769,14 @@ public class RestCommandLineService {
 		Cluster cluster = gson.fromJson(resultString, Cluster.class);
 		return cluster;
 	}
+	
+	private ArrayList<Cluster> getClusterListObjectFromString(String resultString) {
+		GsonBuilder gsonBuilder = new GsonBuilder();
+		Gson gson = gsonBuilder.create();
+
+		ClusterList clusterlist = gson.fromJson(resultString, ClusterList.class);
+		return clusterlist.getCluster();
+	}
 
     private void printLBs(String resultString) {
     	
@@ -719,6 +813,88 @@ public class RestCommandLineService {
 		}
 	}
 
+    private String getAsPolicyFromServiceDefinition(String cartridgeType) throws CommandException{
+        DefaultHttpClient httpClient = new DefaultHttpClient();
+        try {
+            HttpResponse response = restClient.doGet(httpClient, restClient.getBaseURL()
+                    + listDeployServicesRestEndPoint + "/" + cartridgeType);
+
+            String responseCode = "" + response.getStatusLine().getStatusCode();
+
+            GsonBuilder gsonBuilder = new GsonBuilder();
+            Gson gson = gsonBuilder.create();
+
+            if ( ! responseCode.equals(CliConstants.RESPONSE_OK)) {
+                String resultString = getHttpResponseString(response);
+                ExceptionMapper exception = gson.fromJson(resultString, ExceptionMapper.class);
+                System.out.println(exception);
+                return null;
+            }
+
+            String resultString = getHttpResponseString(response);
+            if (resultString == null) {
+                System.out.println("Response content is empty");
+                return null;
+            }
+
+            String  serviceDefinitionString =  resultString.substring(25, resultString.length() -1);
+            ServiceDefinitionBean serviceDefinition= gson.fromJson(serviceDefinitionString, ServiceDefinitionBean.class);
+            if (serviceDefinition == null) {
+                System.out.println("Deploy service list is empty");
+                return null;
+            }
+
+            return serviceDefinition.getAutoscalingPolicyName();
+
+        } catch (Exception e) {
+            handleException("Exception in listing deploy services", e);
+            return null;
+        } finally {
+            httpClient.getConnectionManager().shutdown();
+        }
+    }
+
+    private String getDeploymentPolicyFromServiceDefinition(String cartridgeType) throws CommandException{
+        DefaultHttpClient httpClient = new DefaultHttpClient();
+        try {
+            HttpResponse response = restClient.doGet(httpClient, restClient.getBaseURL()
+                    + listDeployServicesRestEndPoint + "/" + cartridgeType);
+
+            String responseCode = "" + response.getStatusLine().getStatusCode();
+
+            GsonBuilder gsonBuilder = new GsonBuilder();
+            Gson gson = gsonBuilder.create();
+
+            if ( ! responseCode.equals(CliConstants.RESPONSE_OK)) {
+                String resultString = getHttpResponseString(response);
+                ExceptionMapper exception = gson.fromJson(resultString, ExceptionMapper.class);
+                System.out.println(exception);
+                return null;
+            }
+
+            String resultString = getHttpResponseString(response);
+            if (resultString == null) {
+                System.out.println("Response content is empty");
+                return null;
+            }
+
+            String  serviceDefinitionString =  resultString.substring(25, resultString.length() -1);
+            ServiceDefinitionBean serviceDefinition= gson.fromJson(serviceDefinitionString, ServiceDefinitionBean.class);
+            if (serviceDefinition == null) {
+                System.out.println("Deploy service list is empty");
+                return null;
+            }
+
+            return serviceDefinition.getDeploymentPolicyName();
+
+        } catch (Exception e) {
+            handleException("Exception in listing deploy services", e);
+            return null;
+        } finally {
+            httpClient.getConnectionManager().shutdown();
+        }
+    }
+
 	// This method does the cartridge subscription
     public void subscribe(String cartridgeType, String alias, String externalRepoURL, boolean privateRepo, String username,
                           String password,String asPolicy,
@@ -728,25 +904,16 @@ public class RestCommandLineService {
         DefaultHttpClient httpClient = new DefaultHttpClient();
 
         CartridgeInfoBean cartridgeInfoBean = new CartridgeInfoBean();
-        cartridgeInfoBean.setCartridgeType(null);
-        cartridgeInfoBean.setAlias(null);
-        cartridgeInfoBean.setRepoURL(null);
-        cartridgeInfoBean.setPrivateRepo(false);
-        cartridgeInfoBean.setRepoUsername(null);
-        cartridgeInfoBean.setRepoPassword(null);
-        cartridgeInfoBean.setAutoscalePolicy(null);
-        cartridgeInfoBean.setDeploymentPolicy(null);
-        cartridgeInfoBean.setSize(size);
-        cartridgeInfoBean.setRemoveOnTermination(remoOnTermination);
-        cartridgeInfoBean.setPersistanceRequired(persistanceMapping);
-        cartridgeInfoBean.setCommitsEnabled(enableCommits);
-
         GsonBuilder gsonBuilder = new GsonBuilder();
         Gson gson = gsonBuilder.create();
 
-        String jsonSubscribeString = gson.toJson(cartridgeInfoBean, CartridgeInfoBean.class);
-
         try {
+            Cartridge cartridge = listCartridge(cartridgeType);
+            if (cartridge.isMultiTenant()) {
+                asPolicy = getAsPolicyFromServiceDefinition(cartridgeType);
+                depPolicy = getDeploymentPolicyFromServiceDefinition(cartridgeType);
+            }
+
             cartridgeInfoBean.setCartridgeType(cartridgeType);
             cartridgeInfoBean.setAlias(alias);
             cartridgeInfoBean.setRepoURL(externalRepoURL);
@@ -760,7 +927,7 @@ public class RestCommandLineService {
             cartridgeInfoBean.setPersistanceRequired(persistanceMapping);
             cartridgeInfoBean.setCommitsEnabled(enableCommits);
             
-            jsonSubscribeString = gson.toJson(cartridgeInfoBean, CartridgeInfoBean.class);
+            String jsonSubscribeString = gson.toJson(cartridgeInfoBean, CartridgeInfoBean.class);
 
             HttpResponse response = restClient.doPost(httpClient, restClient.getBaseURL() + subscribCartridgeRestEndpoint,
                     jsonSubscribeString);
@@ -1229,14 +1396,12 @@ public class RestCommandLineService {
             }
 
             String resultString = getHttpResponseString(response);
-
             if (resultString == null) {
                 System.out.println("Response content is empty");
                 return;
             }
 
             ServiceDefinitionList definitionList = gson.fromJson(resultString, ServiceDefinitionList.class);
-
             if (definitionList == null) {
                 System.out.println("Deploy service list is empty");
                 return;
@@ -1245,14 +1410,12 @@ public class RestCommandLineService {
             RowMapper<ServiceDefinitionBean> deployServiceMapper = new RowMapper<ServiceDefinitionBean>() {
 
                 public String[] getData(ServiceDefinitionBean definition) {
-                    String[] data = new String[7];
-                    data[0] = definition.getServiceName();
-                    data[1] = definition.getCartridgeType();
-                    data[2] = definition.getDeploymentPolicyName();
-                    data[3] = definition.getAutoscalingPolicyName();
-                    data[4] = definition.getClusterDomain();
-                    data[5] = definition.getClusterSubDomain();
-                    data[6] = definition.getTenantRange();
+                    String[] data = new String[5];
+                    data[0] = definition.getCartridgeType();
+                    data[1] = definition.getDeploymentPolicyName();
+                    data[2] = definition.getAutoscalingPolicyName();
+                    data[3] = definition.getClusterDomain();
+                    data[4] = definition.getTenantRange();
                     return data;
                 }
             };
@@ -1268,17 +1431,10 @@ public class RestCommandLineService {
                 return;
             }
 
-            List<String> headers = new ArrayList<String>();
-            headers.add("Service Name");
-            headers.add("Cartridge Type");
-            headers.add("Deployment Policy Name");
-            headers.add("Autoscaling Policy Name");
-            headers.add("Cluster Domain");
-            headers.add("Cluster Sub Domain");
-            headers.add("Tenant Range");
-
             System.out.println("Available Deploy Services :");
-            CommandLineUtils.printTable(definitionArry, deployServiceMapper, headers.toArray(new String[headers.size()]));
+            CommandLineUtils.printTable(definitionArry, deployServiceMapper, "Cartridge Type", "Deployment Policy Name",
+                    "Autoscaling Policy Name", "Cluster Domain", "Tenant Range");
+            System.out.println();
 
         } catch (Exception e) {
             handleException("Exception in listing deploy services", e);
@@ -1712,18 +1868,18 @@ public class RestCommandLineService {
 
     // This class convert JSON string to servicedefinitionbean object
     private class ServiceDefinitionList {
-        private ArrayList<ServiceDefinitionBean> serviceDefinition;
+        private ArrayList<ServiceDefinitionBean> serviceDefinitionBean;
 
         public ArrayList<ServiceDefinitionBean> getServiceDefinition() {
-            return serviceDefinition;
+            return serviceDefinitionBean;
         }
 
-        public void setServiceDefinition(ArrayList<ServiceDefinitionBean> serviceDefinition) {
-            this.serviceDefinition = serviceDefinition;
+        public void setServiceDefinition(ArrayList<ServiceDefinitionBean> serviceDefinitionBean) {
+            this.serviceDefinitionBean = serviceDefinitionBean;
         }
 
         ServiceDefinitionList() {
-            serviceDefinition = new ArrayList<ServiceDefinitionBean>();
+            serviceDefinitionBean = new ArrayList<ServiceDefinitionBean>();
         }
     }
 
@@ -1778,6 +1934,19 @@ public class RestCommandLineService {
         }
     }
 
+    private class ClusterList{
+        private ArrayList<Cluster> cluster;
+
+        public ArrayList<Cluster> getCluster() {
+            return cluster;
+        }
+
+        public void setCluster(ArrayList<Cluster> clusters) {
+            this.cluster = clusters;
+        }
+        ClusterList(){cluster = new ArrayList<Cluster>();};
+    }
+
     // This will return access url from a given cartridge
     private String getAccessURLs(Cartridge cartridge) {
     	PortMapping[] portMappings = cartridge.getPortMappings();
@@ -1898,4 +2067,53 @@ public class RestCommandLineService {
 		public CartridgeWrapper() {
 		}
 	}
+
+    public boolean isMultiTenant(String type) throws CommandException {
+        DefaultHttpClient httpClient = new DefaultHttpClient();
+        try {
+            HttpResponse response = restClient.doGet(httpClient, restClient.getBaseURL() + listAvailableCartridgesRestEndpoint);
+
+            String responseCode = "" + response.getStatusLine().getStatusCode();
+            String resultString = getHttpResponseString(response);
+            if (resultString == null) {
+                return false;
+            }
+
+            GsonBuilder gsonBuilder = new GsonBuilder();
+            Gson gson = gsonBuilder.create();
+
+            if (!responseCode.equals(CliConstants.RESPONSE_OK)) {
+                ExceptionMapper exception = gson.fromJson(resultString, ExceptionMapper.class);
+                System.out.println(exception);
+                return false;
+            }
+
+            CartridgeList cartridgeList = gson.fromJson(resultString, CartridgeList.class);
+
+            if (cartridgeList == null) {
+                System.out.println("Available cartridge list is null");
+                return false;
+            }
+
+            ArrayList<Cartridge> multiTenetCartridge = new ArrayList<Cartridge>();
+
+            for (Cartridge cartridge : cartridgeList.getCartridge()) {
+                if (cartridge.isMultiTenant() && cartridge.getCartridgeType().equals(type)) {
+                    multiTenetCartridge.add(cartridge);
+                }
+            }
+
+            if (multiTenetCartridge.size() > 0) {
+                return true;
+            } else {
+                return false;
+            }
+
+        } catch (Exception e) {
+            handleException("Exception in listing available cartridges", e);
+            return false;
+        } finally {
+            httpClient.getConnectionManager().shutdown();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/beans/cartridge/Cartridge.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/beans/cartridge/Cartridge.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/beans/cartridge/Cartridge.java
index 6331e03..a148a2d 100644
--- a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/beans/cartridge/Cartridge.java
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/beans/cartridge/Cartridge.java
@@ -49,6 +49,7 @@ public class Cartridge implements Comparable<Cartridge> {
 
     private String[] accessURLs;
     private PortMapping[] portMappings;
+    private String serviceGroup;
 
     public String getDisplayName() {
         return displayName;
@@ -244,4 +245,12 @@ public class Cartridge implements Comparable<Cartridge> {
     public void setLoadBalancer(boolean isLoadBalancer) {
         this.loadBalancer = isLoadBalancer;
     }
+
+    public String getServiceGroup() {
+        return serviceGroup;
+    }
+
+    public void setServiceGroup(String serviceGroup) {
+        this.serviceGroup = serviceGroup;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java
index 6479a06..c068f65 100644
--- a/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java
+++ b/components/org.apache.stratos.cli/src/main/java/org/apache/stratos/cli/commands/SubscribeCommand.java
@@ -26,6 +26,7 @@ import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.stratos.cli.RestCommandLineService;
+import org.apache.stratos.cli.beans.cartridge.Cartridge;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.stratos.cli.Command;
@@ -33,28 +34,30 @@ import org.apache.stratos.cli.StratosCommandContext;
 import org.apache.stratos.cli.exception.CommandException;
 import org.apache.stratos.cli.utils.CliConstants;
 
+import java.util.ArrayList;
+
 public class SubscribeCommand implements Command<StratosCommandContext> {
 
-	private static final Logger logger = LoggerFactory.getLogger(ListSubscribedCartridgesCommand.class);
+    private static final Logger logger = LoggerFactory.getLogger(ListSubscribedCartridgesCommand.class);
 
-	private final Options options;
+    private final Options options;
 
-	public SubscribeCommand() {
-		options = constructOptions();
-	}
+    public SubscribeCommand() {
+        options = constructOptions();
+    }
 
-	/**
-	 * Construct Options.
-	 * 
-	 * @return Options expected from command-line.
-	 */
-	private Options constructOptions() {
-		final Options options = new Options();
-		//Option policyOption = new Option(CliConstants.POLICY_OPTION, CliConstants.POLICY_LONG_OPTION, true,
-		//		"Auto-scaling policy.\nPlease use \"" + CliConstants.POLICIES_ACTION
-		//				+ "\" command to view the available policies.");
-		//policyOption.setArgName("policy name");
-		//options.addOption(policyOption);
+    /**
+     * Construct Options.
+     *
+     * @return Options expected from command-line.
+     */
+    private Options constructOptions() {
+        final Options options = new Options();
+        //Option policyOption = new Option(CliConstants.POLICY_OPTION, CliConstants.POLICY_LONG_OPTION, true,
+        //		"Auto-scaling policy.\nPlease use \"" + CliConstants.POLICIES_ACTION
+        //				+ "\" command to view the available policies.");
+        //policyOption.setArgName("policy name");
+        //options.addOption(policyOption);
 
         Option autoscaling = new Option(CliConstants.AUTOSCALING_POLICY_OPTION, CliConstants.AUTOSCALING_POLICY_LONG_OPTION,
                 true, "Auto-scaling policy");
@@ -80,89 +83,86 @@ public class SubscribeCommand implements Command<StratosCommandContext> {
         persistance.setArgName("persistance-volume");
         options.addOption(persistance);
 
-		Option urlOption = new Option(CliConstants.REPO_URL_OPTION, CliConstants.REPO_URL_LONG_OPTION, true,
-				"GIT repository URL");
-		urlOption.setArgName("url");
-		options.addOption(urlOption);
-
-		//options.addOption(CliConstants.PRIVATE_REPO_OPTION, CliConstants.PRIVATE_REPO_LONG_OPTION, false,
-		//		"Private repository");
-
-		Option usernameOption = new Option(CliConstants.USERNAME_OPTION, CliConstants.USERNAME_LONG_OPTION, true,
-				"GIT repository username");
-		usernameOption.setArgName("username");
-		options.addOption(usernameOption);
-
-		Option passwordOption = new Option(CliConstants.PASSWORD_OPTION, CliConstants.PASSWORD_LONG_OPTION, true,
-				"GIT repository password");
-		passwordOption.setArgName("password");
-		passwordOption.setOptionalArg(true);
-		options.addOption(passwordOption);
-		
-		Option upstreamCommitsEnabledOption = new Option(CliConstants.ENABLE_COMMITS_OPTION, CliConstants.ENABLE_COMMITS_LONG_OPTION, true,
-		"Enable Git commit upstream");
-		upstreamCommitsEnabledOption.setArgName("enable-commits");
-		upstreamCommitsEnabledOption.setOptionalArg(true);
-		options.addOption(upstreamCommitsEnabledOption);
+        Option urlOption = new Option(CliConstants.REPO_URL_OPTION, CliConstants.REPO_URL_LONG_OPTION, true,
+                "GIT repository URL");
+        urlOption.setArgName("url");
+        options.addOption(urlOption);
+
+        //options.addOption(CliConstants.PRIVATE_REPO_OPTION, CliConstants.PRIVATE_REPO_LONG_OPTION, false,
+        //		"Private repository");
+
+        Option usernameOption = new Option(CliConstants.USERNAME_OPTION, CliConstants.USERNAME_LONG_OPTION, true,
+                "GIT repository username");
+        usernameOption.setArgName("username");
+        options.addOption(usernameOption);
+
+        Option passwordOption = new Option(CliConstants.PASSWORD_OPTION, CliConstants.PASSWORD_LONG_OPTION, true,
+                "GIT repository password");
+        passwordOption.setArgName("password");
+        passwordOption.setOptionalArg(true);
+        options.addOption(passwordOption);
+
+        Option upstreamCommitsEnabledOption = new Option(CliConstants.ENABLE_COMMITS_OPTION, CliConstants.ENABLE_COMMITS_LONG_OPTION, true,
+                "Enable Git commit upstream");
+        upstreamCommitsEnabledOption.setArgName("enable-commits");
+        upstreamCommitsEnabledOption.setOptionalArg(true);
+        options.addOption(upstreamCommitsEnabledOption);
 
         return options;
-	}
-
-	public String getName() {
-		return CliConstants.SUBSCRIBE_ACTION;
-	}
-
-	public String getDescription() {
-		return "Subscribe to a cartridge";
-	}
-
-	public String getArgumentSyntax() {
-		return "[Cartridge type] [Cartridge alias]";
-	}
-
-	public int execute(StratosCommandContext context, String[] args) throws CommandException {
-		if (logger.isDebugEnabled()) {
-			logger.debug("Executing {} command...", getName());
-		}
-		if (args != null && args.length > 0) {
-			String[] remainingArgs = null;
-			String type = null;
-			String alias = null;
-			String policy = null;
+    }
+
+    public String getName() {
+        return CliConstants.SUBSCRIBE_ACTION;
+    }
+
+    public String getDescription() {
+        return "Subscribe to a cartridge";
+    }
+
+    public String getArgumentSyntax() {
+        return "[Cartridge type] [Cartridge alias]";
+    }
+
+    public int execute(StratosCommandContext context, String[] args) throws CommandException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("Executing {} command...", getName());
+        }
+        if (args != null && args.length > 0) {
+            String[] remainingArgs = null;
+            String type = null;
+            String alias = null;
+            String policy = null;
             String asPolicy = null;
             String depPolicy = null;
-			String repoURL = null, username = "", password = "";
+            String repoURL = null, username = "", password = "";
             String size = null;
 
             boolean removeOnTermination = false;
-			boolean privateRepo = false;
+            boolean privateRepo = false;
             boolean persistanceMapping = false;
             boolean commitsEnabled = false;
+            boolean isMultiTenant = false;
+
+            final CommandLineParser parser = new GnuParser();
+            CommandLine commandLine;
+            try {
+                commandLine = parser.parse(options, args);
+                remainingArgs = commandLine.getArgs();
+                if (remainingArgs != null && remainingArgs.length == 2) {
+                    // Get type
+                    type = remainingArgs[0];
+                    alias = remainingArgs[1];
+                } else {
+                    context.getStratosApplication().printUsage(getName());
+                    return CliConstants.BAD_ARGS_CODE;
+                }
 
-			final CommandLineParser parser = new GnuParser();
-			CommandLine commandLine;
-			try {
-				commandLine = parser.parse(options, args);
-				remainingArgs = commandLine.getArgs();
-				if (remainingArgs != null && remainingArgs.length == 2) {
-					// Get type
-					type = remainingArgs[0];
-					alias = remainingArgs[1];
-				} else {
-					context.getStratosApplication().printUsage(getName());
-					return CliConstants.BAD_ARGS_CODE;
-				}
-
-				if (logger.isDebugEnabled()) {
-					logger.debug("Subscribing to {} cartridge with alias {}", type, alias);
-				}
-
-				//if (commandLine.hasOption(CliConstants.POLICY_OPTION)) {
-				//	if (logger.isTraceEnabled()) {
-				//		logger.trace("Policy option is passed");
-				//	}
-				//	policy = commandLine.getOptionValue(CliConstants.POLICY_OPTION);
-				//}
+                // This will check the subscribe cartridge type is multi tenant or single tenant
+                isMultiTenant = RestCommandLineService.getInstance().isMultiTenant(type);
+
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Subscribing to {} cartridge with alias {}", type, alias);
+                }
                 if (commandLine.hasOption(CliConstants.AUTOSCALING_POLICY_OPTION)) {
                     if (logger.isTraceEnabled()) {
                         logger.trace("Autoscaling policy option is passed");
@@ -175,18 +175,12 @@ public class SubscribeCommand implements Command<StratosCommandContext> {
                     }
                     depPolicy = commandLine.getOptionValue(CliConstants.DEPLOYMENT_POLICY_OPTION);
                 }
-				if (commandLine.hasOption(CliConstants.REPO_URL_OPTION)) {
-					if (logger.isTraceEnabled()) {
-						logger.trace("RepoURL option is passed");
-					}
-					repoURL = commandLine.getOptionValue(CliConstants.REPO_URL_OPTION);
-				}
-				//if (commandLine.hasOption(CliConstants.PRIVATE_REPO_OPTION)) {
-				//	if (logger.isTraceEnabled()) {
-				//		logger.trace("privateRepo option is passed");
-				//	}
-				//	privateRepo = true;
-				//}
+                if (commandLine.hasOption(CliConstants.REPO_URL_OPTION)) {
+                    if (logger.isTraceEnabled()) {
+                        logger.trace("RepoURL option is passed");
+                    }
+                    repoURL = commandLine.getOptionValue(CliConstants.REPO_URL_OPTION);
+                }
                 if (commandLine.hasOption(CliConstants.VOLUME_SIZE_OPTION)) {
                     if (logger.isTraceEnabled()) {
                         logger.trace("Volume size option is passed");
@@ -199,77 +193,124 @@ public class SubscribeCommand implements Command<StratosCommandContext> {
                         logger.trace("Remove on termination option is passed");
 
                     }
-                    removeOnTermination = true;
+
+                    String optionValue = commandLine.getOptionValue(CliConstants.REMOVE_ON_TERMINATION_OPTION);
+                    if (optionValue.equals("true")) {
+                        removeOnTermination = true;
+                    } else if (optionValue.equals("false")) {
+                        removeOnTermination = false;
+                    } else {
+                        if (logger.isTraceEnabled()) {
+                            logger.trace("Invalid remove on termination option value");
+                        }
+                        System.out.println("Invalid remove on termination option value.");
+                        context.getStratosApplication().printUsage(getName());
+                        return CliConstants.BAD_ARGS_CODE;
+                    }
                 }
                 if (commandLine.hasOption(CliConstants.PERSISTANCE_VOLUME_OPTION)) {
                     if (logger.isTraceEnabled()) {
                         logger.trace("Persistance volume option is passed");
 
                     }
-                    persistanceMapping = true;
+                    String optionValue = commandLine.getOptionValue(CliConstants.PERSISTANCE_VOLUME_OPTION);
+                    if (optionValue.equals("true")) {
+                        persistanceMapping = true;
+                    } else if (optionValue.equals("false")) {
+                        persistanceMapping = false;
+                    } else {
+                        if (logger.isTraceEnabled()) {
+                            logger.trace("Invalid persistance mapping option value");
+                        }
+                        System.out.println("Invalid persistance mapping option value.");
+                        context.getStratosApplication().printUsage(getName());
+                        return CliConstants.BAD_ARGS_CODE;
+                    }
+                }
+                if (commandLine.hasOption(CliConstants.USERNAME_OPTION)) {
+                    if (logger.isTraceEnabled()) {
+                        logger.trace("Username option is passed");
+                    }
+                    username = commandLine.getOptionValue(CliConstants.USERNAME_OPTION);
                 }
-				if (commandLine.hasOption(CliConstants.USERNAME_OPTION)) {
-					if (logger.isTraceEnabled()) {
-						logger.trace("Username option is passed");
-					}
-					username = commandLine.getOptionValue(CliConstants.USERNAME_OPTION);
-				}
-				if (commandLine.hasOption(CliConstants.PASSWORD_OPTION)) {
-					if (logger.isTraceEnabled()) {
-						logger.trace("Password option is passed");
-					}
-					password = commandLine.getOptionValue(CliConstants.PASSWORD_OPTION);
-				}
-				if (commandLine.hasOption(CliConstants.ENABLE_COMMITS_OPTION)) {
-					if (logger.isTraceEnabled()) {
-						logger.trace("Upstream git commits are enabled");
-					}
-					commitsEnabled = true;
-				}
-
-                if (depPolicy == null) {
+                if (commandLine.hasOption(CliConstants.PASSWORD_OPTION)) {
+                    if (logger.isTraceEnabled()) {
+                        logger.trace("Password option is passed");
+                    }
+                    password = commandLine.getOptionValue(CliConstants.PASSWORD_OPTION);
+                }
+                if (commandLine.hasOption(CliConstants.ENABLE_COMMITS_OPTION)) {
+                    if (logger.isTraceEnabled()) {
+                        logger.trace("Upstream git commits are enabled");
+                    }
+                    commitsEnabled = true;
+                }
+
+                if ( ! isMultiTenant && depPolicy == null) {
                     System.out.println("Deployment policy is required.");
                     context.getStratosApplication().printUsage(getName());
                     return CliConstants.BAD_ARGS_CODE;
                 }
 
-                if (asPolicy == null) {
+                if ( ! isMultiTenant && asPolicy == null) {
                     System.out.println("Autoscaling policy is required.");
                     context.getStratosApplication().printUsage(getName());
                     return CliConstants.BAD_ARGS_CODE;
                 }
 
-                if ( (! persistanceMapping) && ((size != null) || removeOnTermination)) {
+                if ((!persistanceMapping) && ((size != null) || removeOnTermination)) {
                     System.out.println("You have to enable persistance mapping in cartridge subscription");
                     context.getStratosApplication().printUsage(getName());
                     return CliConstants.BAD_ARGS_CODE;
                 }
-				
-				if (StringUtils.isNotBlank(username) && StringUtils.isBlank(password)) {
-					password = context.getApplication().getInput("GIT Repository Password", '*');
-				}
-
-                RestCommandLineService.getInstance().subscribe(type, alias, repoURL, privateRepo, username,
-                		password, asPolicy, depPolicy, size, removeOnTermination,
-                        persistanceMapping, commitsEnabled);
-
-				return CliConstants.SUCCESSFUL_CODE;
-
-			} catch (ParseException e) {
-				if (logger.isErrorEnabled()) {
-					logger.error("Error parsing arguments", e);
-				}
-				System.out.println(e.getMessage());
-				return CliConstants.BAD_ARGS_CODE;
-			}
-		} else {
-			context.getStratosApplication().printUsage(getName());
-			return CliConstants.BAD_ARGS_CODE;
-		}
-	}
-
-	public Options getOptions() {
-		return options;
-	}
+
+                if (StringUtils.isNotBlank(username) && StringUtils.isBlank(password)) {
+                    password = context.getApplication().getInput("GIT Repository Password", '*');
+                }
+
+                Cartridge cartridge = RestCommandLineService.getInstance().listCartridge(type);
+                if(cartridge == null){
+                    System.out.println("No cartridge found with the type " + type);
+                    return CliConstants.BAD_ARGS_CODE;
+                }
+
+                String serviceGroup = cartridge.getServiceGroup();
+
+                if (serviceGroup == null) {
+                    RestCommandLineService.getInstance().subscribe(type, alias, repoURL, privateRepo, username,
+                            password, asPolicy, depPolicy, size, removeOnTermination,
+                            persistanceMapping, commitsEnabled);
+                } else {
+                    ArrayList<Cartridge> cartridgesInSeriviceGroup = RestCommandLineService.getInstance().listCartridges(serviceGroup);
+                    Cartridge cart = null;
+                    int aliasCount = 1;
+                    for (int i = 0; i < cartridgesInSeriviceGroup.size(); i++, aliasCount++) {
+
+                        cart = cartridgesInSeriviceGroup.get(i);
+                        System.out.println("Subscribing to " + cart.getCartridgeType());
+                        RestCommandLineService.getInstance().subscribe(cart.getCartridgeType(), alias + aliasCount, repoURL, privateRepo, username,
+                                password, asPolicy, depPolicy, size, removeOnTermination,
+                                persistanceMapping, commitsEnabled);
+                    }
+                }
+
+                return CliConstants.SUCCESSFUL_CODE;
+
+            } catch (ParseException e) {
+                if (logger.isErrorEnabled()) {
+                    logger.error("Error parsing arguments", e);
+                }
+                System.out.println(e.getMessage());
+                return CliConstants.BAD_ARGS_CODE;
+            }
+        } else {
+            context.getStratosApplication().printUsage(getName());
+            return CliConstants.BAD_ARGS_CODE;
+        }
+    }
+
+    public Options getOptions() {
+        return options;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/concurrent/PartitionValidatorCallable.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/concurrent/PartitionValidatorCallable.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/concurrent/PartitionValidatorCallable.java
index 2ae5274..d0c2276 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/concurrent/PartitionValidatorCallable.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/concurrent/PartitionValidatorCallable.java
@@ -44,6 +44,10 @@ public class PartitionValidatorCallable implements Callable<IaasProvider> {
 
 	@Override
 	public IaasProvider call() throws Exception {
+		
+		if (log.isDebugEnabled()) {
+			log.debug("Partition validation started for "+partition+" of "+cartridge);
+		}
 		String provider = partition.getProvider();
         IaasProvider iaasProvider = cartridge.getIaasProvider(provider);
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java
index 56cc2b0..38a4234 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/impl/CloudControllerServiceImpl.java
@@ -271,11 +271,20 @@ public class CloudControllerServiceImpl implements CloudControllerService {
 
         IaasProvider iaasProvider = cartridge.getIaasProviderOfPartition(partitionId);
         if (iaasProvider == null) {
-            String msg =
-                         "Instance start-up failed. " + "There's no IaaS provided for the partition: " + partitionId +
-                         " and for the Cartridge type: " + cartridgeType+". Only following "
-                  		+ "partitions can be found in this Cartridge: "
-                  		+cartridge.getPartitionToIaasProvider().keySet().toString()+ memberContext.toString() + ". ";
+        	if (log.isDebugEnabled()) {
+        		log.debug("IaasToPartitionMap "+cartridge.hashCode()
+        				+ " for cartridge "+cartridgeType+ " and for partition: "+partitionId);
+        	}
+			String msg = "Instance start-up failed. "
+					+ "There's no IaaS provided for the partition: "
+					+ partitionId
+					+ " and for the Cartridge type: "
+					+ cartridgeType
+					+ ". Only following "
+					+ "partitions can be found in this Cartridge: "
+					+ cartridge.getPartitionToIaasProvider().keySet()
+							.toString() + ". " + memberContext.toString()
+					+ ". ";
             log.fatal(msg);
             throw new InvalidIaasProviderException(msg);
         }
@@ -290,6 +299,14 @@ public class CloudControllerServiceImpl implements CloudControllerService {
             addToPayload(payload, "LB_CLUSTER_ID", memberContext.getLbClusterId());
             addToPayload(payload, "NETWORK_PARTITION_ID", memberContext.getNetworkPartitionId());
             addToPayload(payload, "PARTITION_ID", partitionId);
+            if(memberContext.getProperties() != null) {
+            	org.apache.stratos.cloud.controller.pojo.Properties props1 = memberContext.getProperties();
+                if (props1 != null) {
+                    for (Property prop : props1.getProperties()) {
+                        addToPayload(payload, prop.getName(), prop.getValue());
+                    }
+                }
+            }
 
             Iaas iaas = iaasProvider.getIaas();
             if(ctxt.isVolumeRequired()){
@@ -351,6 +368,11 @@ public class CloudControllerServiceImpl implements CloudControllerService {
             }
             
             NodeMetadata node;
+            
+			if (log.isDebugEnabled()) {
+				log.debug("Cloud Controller is delegating request to start an instance for "
+						+ memberContext + " to Jclouds layer.");
+			}
 
 //            create and start a node
             Set<? extends NodeMetadata> nodes =
@@ -358,9 +380,19 @@ public class CloudControllerServiceImpl implements CloudControllerService {
                                                                                   template);
 
             node = nodes.iterator().next();
+            
+            if (log.isDebugEnabled()) {
+				log.debug("Cloud Controller received a response for the request to start "
+						+ memberContext + " from Jclouds layer.");
+			}
+            
+            
             //Start allocating ip as a new job
 
             ThreadExecutor exec = ThreadExecutor.getInstance();
+            if (log.isDebugEnabled()) {
+				log.debug("Cloud Controller is starting the IP Allocator thread.");
+			}
             exec.execute(new IpAllocator(memberContext, iaasProvider, cartridgeType, node));
 
 
@@ -371,11 +403,12 @@ public class CloudControllerServiceImpl implements CloudControllerService {
                 log.fatal(msg);
                 throw new IllegalStateException(msg);
             }
-                memberContext.setNodeId(nodeId);
-                if(log.isDebugEnabled()) {
-                    log.debug("Node id was set. "+memberContext.toString());
-                }
-                
+            
+			memberContext.setNodeId(nodeId);
+			if (log.isDebugEnabled()) {
+				log.debug("Node id was set. " + memberContext.toString());
+			}
+
                 // attach volumes
 			if (ctxt.isVolumeRequired()) {
 				// remove region prefix
@@ -581,7 +614,9 @@ public class CloudControllerServiceImpl implements CloudControllerService {
             String publicIp = null;
 
             try{
-
+            	if (log.isDebugEnabled()) {
+    				log.debug("IP allocation process started for "+memberContext);
+    			}
                 String autoAssignIpProp =
                                           iaasProvider.getProperty(CloudControllerConstants.AUTO_ASSIGN_IP_PROPERTY);
                 
@@ -669,11 +704,12 @@ public class CloudControllerServiceImpl implements CloudControllerService {
                     // persist in registry
                     persist();
 
-                    String memberID = memberContext.getMemberId();
 
                     // trigger topology
-                    TopologyBuilder.handleMemberSpawned(memberID, cartridgeType, clusterId, memberContext.getNetworkPartitionId(),
-                            partition.getId(), ip, memberContext.getLbClusterId(),publicIp);
+                    TopologyBuilder.handleMemberSpawned(cartridgeType, clusterId, 
+                    		partition.getId(), ip, publicIp, memberContext);
+                    
+                    String memberID = memberContext.getMemberId();
 
                     // update the topology with the newly spawned member
                     // publish data
@@ -685,14 +721,18 @@ public class CloudControllerServiceImpl implements CloudControllerService {
                                                         MemberStatus.Created.toString(),
                                                         node);
                     if (log.isDebugEnabled()) {
-                        log.debug("Node details: \n" + node.toString());
+                        log.debug("Node details: " + node.toString());
                     }
+                    
+                    if (log.isDebugEnabled()) {
+        				log.debug("IP allocation process ended for "+memberContext);
+        			}
 
             } catch (Exception e) {
                 String msg = "Error occurred while allocating an ip address. " + memberContext.toString();
                 log.error(msg, e);
                 throw new CloudControllerException(msg, e);
-            }
+            } 
 
 
         }
@@ -946,6 +986,7 @@ public class CloudControllerServiceImpl implements CloudControllerService {
     @Override
 	public void unregisterService(String clusterId) throws UnregisteredClusterException {
         final String clusterId_ = clusterId;
+        TopologyBuilder.handleClusterMaintenanceMode(dataHolder.getClusterContext(clusterId_));
 
         Runnable terminateInTimeout = new Runnable() {
             @Override
@@ -1048,6 +1089,10 @@ public class CloudControllerServiceImpl implements CloudControllerService {
 
         Map<String, IaasProvider> partitionToIaasProviders =
                                                              new ConcurrentHashMap<String, IaasProvider>();
+        
+        if (log.isDebugEnabled()) {
+			log.debug("Deployment policy validation started for cartridge type: "+cartridgeType);
+		}
 
         Cartridge cartridge = dataHolder.getCartridge(cartridgeType);
 
@@ -1073,6 +1118,9 @@ public class CloudControllerServiceImpl implements CloudControllerService {
             try {
             	// add to a temporary Map
             	partitionToIaasProviders.put(partitionId, job.get());
+				if (log.isDebugEnabled()) {
+					log.debug("Partition "+partitionId+" added to the map.");
+				}
             } catch (Exception e) {
                 log.error(e.getMessage(), e);
                 throw new InvalidPartitionException(e.getMessage(), e);

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Cartridge.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Cartridge.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Cartridge.java
index 46424e7..dafaa2c 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Cartridge.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/Cartridge.java
@@ -19,6 +19,8 @@
 package org.apache.stratos.cloud.controller.pojo;
 
 import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 import java.io.Serializable;
 import java.util.*;
@@ -29,6 +31,7 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 public class Cartridge implements Serializable{
 
+	private transient static final Log log = LogFactory.getLog(Cartridge.class);
     private static final long serialVersionUID = 6637409027085059072L;
 
 	private String type;
@@ -53,25 +56,25 @@ public class Cartridge implements Serializable{
     
     private LoadbalancerConfig lbConfig;
     
-    private List<PortMapping> portMappings = new ArrayList<PortMapping>();
+    private List<PortMapping> portMappings;
     
     private Persistence persistence;
     
-    private List<AppType> appTypeMappings = new ArrayList<AppType>();
+    private List<AppType> appTypeMappings;
     
     private String serviceGroup;
     
     /**
      * Property map of this Cartridge.
      */
-    private Map<String, String> properties = new HashMap<String, String>();
+    private Map<String, String> properties;
     
     /**
      * A Cartridge can have 1..n {@link IaasProvider}s
      */
-    private List<IaasProvider> iaases = new ArrayList<IaasProvider>();
+    private List<IaasProvider> iaases;
     
-    private List<String> deploymentDirs = new ArrayList<String>();
+    private List<String> deploymentDirs;
     
     private IaasProvider lastlyUsedIaas;
     
@@ -79,9 +82,11 @@ public class Cartridge implements Serializable{
      * Key - partition id
      * Value - Corresponding IaasProvider.
      */
-    private Map<String, IaasProvider> partitionToIaasProvider = new ConcurrentHashMap<String, IaasProvider>();
+    private Map<String, IaasProvider> partitionToIaasProvider;
     
-    public Cartridge(){}
+    public Cartridge(){
+    	init();
+    }
     
     public Cartridge(String type, String host, String provider, String version, boolean multiTenant) {
         this.type = type;
@@ -89,6 +94,17 @@ public class Cartridge implements Serializable{
         this.provider = provider;
         this.version = version;
         this.multiTenant = multiTenant;
+        init();
+    }
+    
+    private void init() {
+    	partitionToIaasProvider = new ConcurrentHashMap<String, IaasProvider>();
+    	portMappings = new ArrayList<PortMapping>();
+    	portMappings = new ArrayList<PortMapping>();
+    	appTypeMappings = new ArrayList<AppType>();
+    	properties = new HashMap<String, String>();
+    	iaases = new ArrayList<IaasProvider>();
+    	deploymentDirs = new ArrayList<String>();
     }
 
     public String getType() {
@@ -109,10 +125,18 @@ public class Cartridge implements Serializable{
             IaasProvider value = map.get(key);
             
             partitionToIaasProvider.put(key, value);
+            if(log.isDebugEnabled()) {
+            	log.debug("Partition map updated for the Cartridge: "+this.hashCode()+". "
+            			+ "Current Partition List: "+partitionToIaasProvider.keySet().toString());
+            }
         }
     }
     
     public IaasProvider getIaasProviderOfPartition(String partitionId) {
+    	if(log.isDebugEnabled()) {
+        	log.debug("Retrieving partition: "+partitionId+" for the Cartridge: "+this.hashCode()+". "
+        			+ "Current Partition List: "+partitionToIaasProvider.keySet().toString());
+        }
         return partitionToIaasProvider.get(partitionId);
     }
     
@@ -160,7 +184,19 @@ public class Cartridge implements Serializable{
         return iaases;
     }
 
-    public void setIaases(List<IaasProvider> iaases) {
+    @Override
+	public String toString() {
+		return "Cartridge [type=" + type + ", hostName=" + hostName
+				+ ", provider=" + provider + ", version=" + version
+				+ ", multiTenant=" + multiTenant
+				+ ", defaultAutoscalingPolicy=" + defaultAutoscalingPolicy
+				+ ", defaultDeploymentPolicy=" + defaultDeploymentPolicy
+				+ ", serviceGroup=" + serviceGroup + ", properties="
+				+ properties + ", partitionToIaasProvider="
+				+ partitionToIaasProvider + "]";
+	}
+
+	public void setIaases(List<IaasProvider> iaases) {
         this.iaases = iaases;
     }
     

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/CartridgeInfo.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/CartridgeInfo.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/CartridgeInfo.java
index d2d3603..0064b2e 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/CartridgeInfo.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/CartridgeInfo.java
@@ -58,6 +58,8 @@ public class CartridgeInfo {
 
     private Persistence persistence;
 
+    private String serviceGroup;
+
     public CartridgeInfo(){
     	
     }
@@ -206,4 +208,12 @@ public class CartridgeInfo {
     public void setPersistence(Persistence persistence) {
         this.persistence = persistence;
     }
+
+    public String getServiceGroup() {
+        return serviceGroup;
+    }
+
+    public void setServiceGroup(String serviceGroup) {
+        this.serviceGroup = serviceGroup;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/MemberContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/MemberContext.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/MemberContext.java
index 2618bb2..e3d67f1 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/MemberContext.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/pojo/MemberContext.java
@@ -54,6 +54,8 @@ public class MemberContext implements Serializable{
     private String lbClusterId;
     //network partition id
     private String networkPartitionId;
+
+    private Properties properties;
     
     public MemberContext(String id, String clusterId, Partition partition) {
         this.memberId = id;
@@ -200,4 +202,12 @@ public class MemberContext implements Serializable{
 	public void setInstanceId(String instanceId) {
 		this.instanceId = instanceId;
 	}
+
+    public Properties getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Properties properties) {
+        this.properties = properties;
+    }
 }


[09/14] Clustering changes for stratos

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java
index 0e3982b..7954dc9 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/impl/GitBasedArtifactRepository.java
@@ -21,15 +21,18 @@ package org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.CartridgeAgent;
 import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.RepositoryInformation;
 import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal.CustomJschConfigSessionFactory;
 import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal.GitDeploymentSynchronizerConstants;
 import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.internal.RepositoryContext;
 import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.util.Utilities;
-import org.apache.stratos.cartridge.agent.util.ExtensionUtils;
+import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
+import org.apache.stratos.cartridge.agent.extensions.ExtensionHandler;
 import org.eclipse.jgit.api.*;
 import org.eclipse.jgit.api.errors.*;
 import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.storage.file.FileRepository;
 import org.eclipse.jgit.transport.SshSessionFactory;
@@ -38,33 +41,32 @@ import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
 import java.io.File;
 import java.io.IOException;
 import java.util.Iterator;
-import java.util.Map.Entry;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.*;
 
 /**
  * Git based artifact repository.
- * 
- * 
  */
 public class GitBasedArtifactRepository {
 
     private static final int SUPER_TENANT_ID = -1234;
 
-	private static final Log log = LogFactory.getLog(GitBasedArtifactRepository.class);
+    private static final Log log = LogFactory.getLog(GitBasedArtifactRepository.class);
+    private final ExtensionHandler extensionHandler;
 
     //Map to keep track of git context per tenant (remote urls, jgit git objects, etc.)
     private static ConcurrentHashMap<Integer, RepositoryContext>
-    					tenantToRepoContextMap = new ConcurrentHashMap<Integer, RepositoryContext>();
+            tenantToRepoContextMap = new ConcurrentHashMap<Integer, RepositoryContext>();
     private static volatile GitBasedArtifactRepository gitBasedArtifactRepository;
-    private static String SUPER_TENANT_APP_PATH = "/repository/deployment/server/";
-    private static String TENANT_PATH = "/repository/tenants/";
-
-    private GitBasedArtifactRepository () {
+    private static String SUPER_TENANT_REPO_PATH = "/repository/deployment/server/";
+    private static String TENANT_REPO_PATH = "/repository/tenants/";
 
+    private GitBasedArtifactRepository() {
+        extensionHandler = CartridgeAgent.getExtensionHandler();
     }
 
-    public static GitBasedArtifactRepository getInstance () {
+    public static GitBasedArtifactRepository getInstance() {
 
         if (gitBasedArtifactRepository == null) {
             synchronized (GitBasedArtifactRepository.class) {
@@ -80,40 +82,38 @@ public class GitBasedArtifactRepository {
      * initializes and populates the git context with relevant data
      *
      * @param repositoryInformation id of the tenant
-     *
      */
-    private void initGitContext (RepositoryInformation repositoryInformation)  {
+    private void initGitContext(RepositoryInformation repositoryInformation) {
+
+
+        log.info("Initializing git context.");
 
-    	
-    	log.info("Initializing git context.");
-    	
-    	int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
-    	String gitLocalRepoPath = repositoryInformation.getRepoPath();
+        int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
+        String gitLocalRepoPath = repositoryInformation.getRepoPath();
         RepositoryContext gitRepoCtx = new RepositoryContext();
         String gitRemoteRepoUrl = repositoryInformation.getRepoUrl();
         boolean isMultitenant = repositoryInformation.isMultitenant();
-        
+
         log.info("local path " + gitLocalRepoPath);
         log.info("remote url " + gitRemoteRepoUrl);
         log.info("tenant " + tenantId);
-        
+
         gitRepoCtx.setTenantId(tenantId);
-        gitRepoCtx.setGitLocalRepoPath(getRepoPathForTenantId(tenantId,gitLocalRepoPath,isMultitenant));        
+        gitRepoCtx.setGitLocalRepoPath(getRepoPathForTenantId(tenantId, gitLocalRepoPath, isMultitenant));
         gitRepoCtx.setGitRemoteRepoUrl(gitRemoteRepoUrl);
-		
-		gitRepoCtx.setRepoUsername(repositoryInformation.getRepoUsername());
-		gitRepoCtx.setRepoPassword(repositoryInformation.getRepoPassword());
+
+        gitRepoCtx.setRepoUsername(repositoryInformation.getRepoUsername());
+        gitRepoCtx.setRepoPassword(repositoryInformation.getRepoPassword());
 
         try {
-			if(isKeyBasedAuthentication(gitRemoteRepoUrl, tenantId)) {
-			    gitRepoCtx.setKeyBasedAuthentication(true);
-			    initSSHAuthentication();
-			}
-			else
-			    gitRepoCtx.setKeyBasedAuthentication(false);
-		} catch (Exception e1) {
-			log.error("Exception occurred.. " + e1.getMessage(), e1);
-		}
+            if (isKeyBasedAuthentication(gitRemoteRepoUrl, tenantId)) {
+                gitRepoCtx.setKeyBasedAuthentication(true);
+                initSSHAuthentication();
+            } else
+                gitRepoCtx.setKeyBasedAuthentication(false);
+        } catch (Exception e1) {
+            log.error("Exception occurred.. " + e1.getMessage(), e1);
+        }
 
         FileRepository localRepo = null;
         try {
@@ -133,54 +133,66 @@ public class GitBasedArtifactRepository {
     }
 
 
-
     // If tenant id is "-1234", then its super tenant, else tenant
     private static String getRepoPathForTenantId(int tenantId,
-                       String gitLocalRepoPath, boolean isMultitenant) {
-               
-    	
-		StringBuilder repoPathBuilder = new StringBuilder();
-		String repoPath = null;
-
-		if (isMultitenant) {
-			if (tenantId == SUPER_TENANT_ID) {
-				repoPathBuilder.append(gitLocalRepoPath).append(
-						SUPER_TENANT_APP_PATH);
-			} else {
-				// create folder with tenant id
-				createTenantDir(tenantId, gitLocalRepoPath);
-				repoPathBuilder.append(gitLocalRepoPath).append(TENANT_PATH)
-						.append(tenantId);
-			}
-
-			repoPath = repoPathBuilder.toString();
-		} else {
-			repoPath = gitLocalRepoPath;
-		}
-		log.info("Repo path returned : " + repoPath);
-		return repoPath;
-       }
+                                                 String gitLocalRepoPath, boolean isMultitenant) {
 
-       private static void createTenantDir(int tenantId, String path) {
-               String dirPathName = path+TENANT_PATH+tenantId;
-               boolean dirStatus = new File(dirPathName).mkdir();
-               if(dirStatus){
-                       log.info("Successfully created directory ["+dirPathName+"] ");
-               }else {
-                       log.error("Directory creating failed in ["+dirPathName+"] ");
-               }       
-       }
 
+        StringBuilder repoPathBuilder = new StringBuilder();
+        String repoPath = null;
+
+        if (isMultitenant) {
+            if (tenantId == SUPER_TENANT_ID) {
+                //check if the relevant path is set as a startup param
+                String superTenantRepoPath = CartridgeAgentConfiguration.getInstance().getSuperTenantRepositoryPath();
+
+                if (superTenantRepoPath != null && !superTenantRepoPath.isEmpty()) {
+                    superTenantRepoPath = superTenantRepoPath.startsWith("/") ? superTenantRepoPath : "/".concat(superTenantRepoPath);
+                    repoPathBuilder.append(gitLocalRepoPath).append(superTenantRepoPath);
+
+                } else {
+                    repoPathBuilder.append(gitLocalRepoPath).append(SUPER_TENANT_REPO_PATH);
+                }
+            } else {
+                // create folder with tenant id
+                createTenantDir(tenantId, gitLocalRepoPath);
+                //check if the relevant path is set as a startup param
+                String tenantRepoPath = CartridgeAgentConfiguration.getInstance().getTenantRepositoryPath();
+
+                if (tenantRepoPath != null && !tenantRepoPath.isEmpty()) {
+                    tenantRepoPath = tenantRepoPath.startsWith("/") ? tenantRepoPath : "/".concat(tenantRepoPath);
+                    tenantRepoPath = tenantRepoPath.endsWith("/") ? tenantRepoPath : tenantRepoPath.concat("/");
+
+                    repoPathBuilder.append(gitLocalRepoPath).append(tenantRepoPath).append(tenantId);
+                } else {
+                    repoPathBuilder.append(gitLocalRepoPath).append(TENANT_REPO_PATH).append(tenantId);
+                }
+            }
 
+            repoPath = repoPathBuilder.toString();
+        } else {
+            repoPath = gitLocalRepoPath;
+        }
+        log.info("Repo path returned : " + repoPath);
+        return repoPath;
+    }
 
+    private static void createTenantDir(int tenantId, String path) {
+        String dirPathName = path + TENANT_REPO_PATH + tenantId;
+        boolean dirStatus = new File(dirPathName).mkdir();
+        if (dirStatus) {
+            log.info("Successfully created directory [" + dirPathName + "] ");
+        } else {
+            log.error("Directory creating failed in [" + dirPathName + "] ");
+        }
+    }
 
 
     /**
      * Checks if key based authentication (SSH) is required
      *
-     * @param url git repository url for the tenant
+     * @param url      git repository url for the tenant
      * @param tenantId id of the tenant
-     *
      * @return true if SSH authentication is required, else false
      */
     private boolean isKeyBasedAuthentication(String url, int tenantId) {
@@ -189,20 +201,14 @@ public class GitBasedArtifactRepository {
                 url.startsWith(GitDeploymentSynchronizerConstants.GIT_HTTPS_REPO_URL_PREFIX)) {//http or https url
             // authentication with username and password, not key based
             return false;
-        }
-
-        else if (url.startsWith(GitDeploymentSynchronizerConstants.GITHUB_READ_ONLY_REPO_URL_PREFIX)) { //github read-only repo url
+        } else if (url.startsWith(GitDeploymentSynchronizerConstants.GITHUB_READ_ONLY_REPO_URL_PREFIX)) { //github read-only repo url
             // no authentication required
             return false;
-        }
-
-        else if (url.startsWith(GitDeploymentSynchronizerConstants.GIT_REPO_SSH_URL_PREFIX) ||
+        } else if (url.startsWith(GitDeploymentSynchronizerConstants.GIT_REPO_SSH_URL_PREFIX) ||
                 url.contains(GitDeploymentSynchronizerConstants.GIT_REPO_SSH_URL_SUBSTRING)) { //other repo, needs ssh authentication
             // key based authentication
             return true;
-        }
-
-        else {
+        } else {
             log.error("Invalid git URL provided for tenant " + tenantId);
             throw new RuntimeException("Invalid git URL provided for tenant " + tenantId);
         }
@@ -211,7 +217,7 @@ public class GitBasedArtifactRepository {
     /**
      * Initializes SSH authentication
      */
-    private void initSSHAuthentication () {
+    private void initSSHAuthentication() {
 
         SshSessionFactory.setInstance(new CustomJschConfigSessionFactory());
     }
@@ -219,24 +225,23 @@ public class GitBasedArtifactRepository {
     /**
      * Caches RepositoryContext against tenant repository path
      *
-     * @param tenantId tenant repository path
+     * @param tenantId   tenant repository path
      * @param gitRepoCtx RepositoryContext instance for tenant
      */
     private void cacheGitRepoContext(int tenantId, RepositoryContext gitRepoCtx) {
 
-    	log.info("caching repo context");
-        tenantToRepoContextMap.put(tenantId, gitRepoCtx);
-    }
+        log.info("caching repo context");
 
+    tenantToRepoContextMap.put(tenantId, gitRepoCtx);
+}
     /**
      * Retrieve cached RepositoryContext relevant to the tenant's local repo path
      *
      * @param tenantId
-     *
      * @return corresponding RepositoryContext instance for the
      * tenant's local repo if available, else null
      */
-    private RepositoryContext retrieveCachedGitContext (int tenantId) {
+    private RepositoryContext retrieveCachedGitContext(int tenantId) {
 
         return tenantToRepoContextMap.get(tenantId);
     }
@@ -245,66 +250,55 @@ public class GitBasedArtifactRepository {
      * Commits any changes in the local repository to the relevant remote repository
      *
      * @return
-     *      
      */
-    public boolean commit() {
-    	// TODO implement later, this is applicable for management node.
-
-		for (Entry<Integer, RepositoryContext> tenantMap : tenantToRepoContextMap
-				.entrySet()) {
-
-			int tenantId = tenantMap.getKey();
-			//log.info("map count has values..tenant Id : " + tenantId);
-			
-			RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
-			if (gitRepoCtx == null) {
-				
-					log.info("No git repository context information found for tenant "
-							+ tenantId);
-
-				return false;
-			}
-
-			Git git = gitRepoCtx.getGit();
-			StatusCommand statusCmd = git.status();
-			Status status = null;
-			try {
-				status = statusCmd.call();
-
-			} catch (GitAPIException e) {
-				log.error(
-						"Git status operation for tenant "
-								+ gitRepoCtx.getTenantId() + " failed, ", e);
-				return false;
-			}
-			//log.info("status : " + status.toString());
-			if (status.isClean()) {// no changes, nothing to commit
-				
-					log.debug("No changes detected in the local repository for tenant "
-							+ tenantId);
-				return false;
-			}
-			
-			addArtifacts(gitRepoCtx, getNewArtifacts(status));
-			addArtifacts(gitRepoCtx, getModifiedArtifacts(status));
-			removeArtifacts(gitRepoCtx, getRemovedArtifacts(status));
-			commitToLocalRepo(gitRepoCtx);
-			pushToRemoteRepo(gitRepoCtx);
-
-			return false;
-
-		}
-		return false;
+    public void commit(RepositoryInformation repoInfo) {
+        // TODO implement later, this is applicable for management node.
+
+       // for (Entry<Integer, RepositoryContext> tenantMap : tenantToRepoContextMap
+       //         .entrySet()) {
+
+            int tenantId = Integer.parseInt(repoInfo.getTenantId());
+            //log.info("map count has values..tenant Id : " + tenantId);
+
+            RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
+            Git git = gitRepoCtx.getGit();
+            StatusCommand statusCmd = git.status();
+            Status status = null;
+            try {
+                status = statusCmd.call();
+
+            } catch (GitAPIException e) {
+                log.error(
+                        "Git status operation for tenant "
+                                + gitRepoCtx.getTenantId() + " failed, ", e);
+
+            }
+            //log.info("status : " + status.toString());
+            if (status.isClean()) {// no changes, nothing to commit
+                if (log.isDebugEnabled()) {
+                    log.debug("No changes detected in the local repository for tenant " + tenantId);
+                }
+
+                return;
+            }
+
+            addArtifacts(gitRepoCtx, getNewArtifacts(status));
+            addArtifacts(gitRepoCtx, getModifiedArtifacts(status));
+            removeArtifacts(gitRepoCtx, getRemovedArtifacts(status));
+            commitToLocalRepo(gitRepoCtx);
+            pushToRemoteRepo(gitRepoCtx);
+
+        //}
+        //return false;
     }
 
     /**
      * Returns the newly added artifact set relevant to the current status of the repository
      *
      * @param status git status
-     *
      * @return artifact names set
      */
-    private Set<String> getNewArtifacts (Status status) {
+    private Set<String> getNewArtifacts(Status status) {
 
         return status.getUntracked();
     }
@@ -313,10 +307,9 @@ public class GitBasedArtifactRepository {
      * Returns the removed (undeployed) artifact set relevant to the current status of the repository
      *
      * @param status git status
-     *
      * @return artifact names set
      */
-    private Set<String> getRemovedArtifacts (Status status) {
+    private Set<String> getRemovedArtifacts(Status status) {
 
         return status.getMissing();
     }
@@ -325,10 +318,9 @@ public class GitBasedArtifactRepository {
      * Return the modified artifacts set relevant to the current status of the repository
      *
      * @param status git status
-     *
      * @return artifact names set
      */
-    private Set<String> getModifiedArtifacts (Status status) {
+    private Set<String> getModifiedArtifacts(Status status) {
 
         return status.getModified();
     }
@@ -337,36 +329,40 @@ public class GitBasedArtifactRepository {
      * Adds the artifacts to the local staging area
      *
      * @param gitRepoCtx RepositoryContext instance
-     * @param artifacts set of artifacts
+     * @param artifacts  set of artifacts
      */
-    private void addArtifacts (RepositoryContext gitRepoCtx, Set<String> artifacts) {
+    private void addArtifacts(RepositoryContext gitRepoCtx, Set<String> artifacts) {
 
-        if(artifacts.isEmpty())
+        if (artifacts.isEmpty())
             return;
 
         AddCommand addCmd = gitRepoCtx.getGit().add();
         Iterator<String> it = artifacts.iterator();
-        while(it.hasNext())
+        while (it.hasNext())
             addCmd.addFilepattern(it.next());
 
         try {
             addCmd.call();
+            if (log.isDebugEnabled()) {
+                log.debug("Added artifacts for tenant : " + gitRepoCtx.getTenantId());
+            }
 
         } catch (GitAPIException e) {
             log.error("Adding artifact to the local repository at " + gitRepoCtx.getGitLocalRepoPath() + "failed", e);
-            e.printStackTrace();
+            log.error(e);
         }
+
     }
 
     /**
      * Removes the set of artifacts from local repo
      *
      * @param gitRepoCtx RepositoryContext instance
-     * @param artifacts Set of artifact names to remove
+     * @param artifacts  Set of artifact names to remove
      */
-    private void removeArtifacts (RepositoryContext gitRepoCtx, Set<String> artifacts) {
+    private void removeArtifacts(RepositoryContext gitRepoCtx, Set<String> artifacts) {
 
-        if(artifacts.isEmpty())
+        if (artifacts.isEmpty())
             return;
 
         RmCommand rmCmd = gitRepoCtx.getGit().rm();
@@ -377,10 +373,13 @@ public class GitBasedArtifactRepository {
 
         try {
             rmCmd.call();
+            if (log.isDebugEnabled()) {
+                log.debug("Removed artifacts for tenant : " + gitRepoCtx.getTenantId());
+            }
 
         } catch (GitAPIException e) {
             log.error("Removing artifact from the local repository at " + gitRepoCtx.getGitLocalRepoPath() + "failed", e);
-            e.printStackTrace();
+            log.error(e);
         }
     }
 
@@ -389,7 +388,7 @@ public class GitBasedArtifactRepository {
      *
      * @param gitRepoCtx RepositoryContext instance for the tenant
      */
-    private void commitToLocalRepo (RepositoryContext gitRepoCtx) {
+    private void commitToLocalRepo(RepositoryContext gitRepoCtx) {
 
         CommitCommand commitCmd = gitRepoCtx.getGit().commit();
         commitCmd.setMessage("tenant " + gitRepoCtx.getTenantId() + "'s artifacts committed to local repo at " +
@@ -397,10 +396,12 @@ public class GitBasedArtifactRepository {
 
         try {
             commitCmd.call();
+            if (log.isDebugEnabled()) {
+                log.debug("Committed artifacts for tenant : " + gitRepoCtx.getTenantId());
+            }
 
         } catch (GitAPIException e) {
             log.error("Committing artifacts to local repository failed for tenant " + gitRepoCtx.getTenantId(), e);
-            e.printStackTrace();
         }
     }
 
@@ -412,7 +413,7 @@ public class GitBasedArtifactRepository {
     private void pushToRemoteRepo(RepositoryContext gitRepoCtx) {
 
         PushCommand pushCmd = gitRepoCtx.getGit().push();
-        if(!gitRepoCtx.getKeyBasedAuthentication()) {
+        if (!gitRepoCtx.getKeyBasedAuthentication()) {
             UsernamePasswordCredentialsProvider credentialsProvider = createCredentialsProvider(gitRepoCtx);
             if (credentialsProvider != null)
                 pushCmd.setCredentialsProvider(credentialsProvider);
@@ -420,47 +421,173 @@ public class GitBasedArtifactRepository {
 
         try {
             pushCmd.call();
+            if (log.isDebugEnabled()) {
+                log.debug("Pushed artifacts for tenant : " + gitRepoCtx.getTenantId());
+            }
 
         } catch (GitAPIException e) {
             log.error("Pushing artifacts to remote repository failed for tenant " + gitRepoCtx.getTenantId(), e);
-            e.printStackTrace();
+
         }
     }
 
-    public boolean checkout(RepositoryInformation repositoryInformation) {
-        /*if(log.isInfoEnabled()) {
-    	    log.info("Executing checkout");
-        }*/
+   /* public boolean checkout(RepositoryInformation repositoryInformation) {
+
 
         if (log.isDebugEnabled()) {
             log.debug("Artifact checkout done by thread " + Thread.currentThread().getName() + " - " +
-                Thread.currentThread().getId());
+                    Thread.currentThread().getId());
         }
 
-    	int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
-    	
-    	// if context for tenant is not initialized
-    	if(tenantToRepoContextMap.get(tenantId) == null)
-	    	initGitContext(repositoryInformation);
-    	
-        
-		RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
-        if(gitRepoCtx == null) { //to handle super tenant scenario
-           // if(log.isDebugEnabled())
-                log.info("No git repository context information found for deployment synchronizer");
+        int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
+
+        // if context for tenant is not initialized
+        if (tenantToRepoContextMap.get(tenantId) == null)
+            initGitContext(repositoryInformation);
+
+
+        RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
+        if (gitRepoCtx == null) { //to handle super tenant scenario
+            // if(log.isDebugEnabled())
+            log.info("No git repository context information found for deployment synchronizer");
 
             return true;
         }
 
         synchronized (gitRepoCtx) {
-            if(!gitRepoCtx.cloneExists())
+            if (!gitRepoCtx.cloneExists())
                 cloneRepository(gitRepoCtx);
 
             return pullArtifacts(gitRepoCtx);
         }
+    } */
+   public boolean checkout (RepositoryInformation repositoryInformation) throws Exception {
+
+       int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
+
+       // if context for tenant is not initialized
+       if (tenantToRepoContextMap.get(tenantId) == null) {
+           initGitContext(repositoryInformation);
+       }
+
+       RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
+
+       File gitRepoDir = new File(gitRepoCtx.getGitLocalRepoPath());
+       if (!gitRepoDir.exists()) {
+           return cloneRepository(gitRepoCtx);
+       }
+       else {
+           if (isValidGitRepo(gitRepoCtx)) {
+               if (log.isDebugEnabled()) {
+                   log.debug("Existing git repository detected for tenant " + gitRepoCtx.getTenantId() + ", no clone required");
+               }
+
+               return pullAndHandleErrors(gitRepoCtx);
+
+           } else {
+               // not a valid git repo, check if the directory is non-empty
+               if (gitRepoDir.list().length > 0) {
+                   // directory is non empty. sync existing artifacts with the remote repository
+                   if (syncInitialLocalArtifacts(gitRepoCtx)) {
+                       log.info("Existing local artifacts for tenant [" + gitRepoCtx.getTenantId() + "] synchronized with remote repository successfully");
+                       // pull any changes from the remote repo
+                       return pullAndHandleErrors(gitRepoCtx);
+                   }
+                   return false;
+
+               } else {
+                   // directory is empty, clone
+                   return cloneRepository(gitRepoCtx);
+               }
+           }
+       }
+   }
+
+    private boolean pullAndHandleErrors (RepositoryContext gitRepoCtx) {
+
+        try {
+            return pullArtifacts(gitRepoCtx);
+
+        } catch (CheckoutConflictException e) {
+            // checkout from remote HEAD
+            return checkoutFromRemoteHead(gitRepoCtx, e.getConflictingPaths());
+            // pull again
+            /*try {
+                return pullArtifacts(gitRepoCtx);
+
+            } catch (GitAPIException e1) {
+                //cannot happen here
+                log.error("Git pull failed for tenant " + gitRepoCtx.getTenantId(), e1);
+                return false;
+            }*/
+        }
+    }
+
+    private boolean checkoutFromRemoteHead(RepositoryContext gitRepoCtx, List<String> paths) {
+
+        boolean checkoutSuccess = false;
+
+        CheckoutCommand checkoutCmd = gitRepoCtx.getGit().checkout();
+        for(String path : paths) {
+            checkoutCmd.addPath(path);
+            if(log.isDebugEnabled()) {
+                log.debug("Added the file path " + path + " to checkout from the remote repository");
+            }
+        }
+        // specify the start point as the HEAD of remote repository
+        checkoutCmd.setStartPoint(GitDeploymentSynchronizerConstants.REMOTES_ORIGIN_MASTER);
+
+        try {
+            checkoutCmd.call();
+            checkoutSuccess = true;
+            log.info("Checked out the conflicting files from the remote repository successfully");
+
+        } catch (GitAPIException e) {
+            log.error("Checking out artifacts from index failed", e);
+        }
+
+        return checkoutSuccess;
     }
-    
-    public void scheduleSyncTask (RepositoryInformation repoInformation, long delay) {
+
+    private void resetToRemoteHead (RepositoryContext gitRepoCtx, List<String> paths) {
+
+        ResetCommand resetCmd = gitRepoCtx.getGit().reset();
+
+        // reset type is HARD, to remote master branch
+        resetCmd.setMode(ResetCommand.ResetType.HARD).
+                setRef(GitDeploymentSynchronizerConstants.ORIGIN + "/" + GitDeploymentSynchronizerConstants.MASTER);
+
+        // add paths
+        for(String path : paths) {
+            resetCmd.addPath(path);
+            if(log.isDebugEnabled()) {
+                log.debug("Added the file path " + path + " to reset");
+            }
+        }
+
+        try {
+            resetCmd.call();
+            log.info("Reset the local branch to origin master successfully");
+
+        } catch (GitAPIException e) {
+            log.error("Reset to origin master failed", e);
+        }
+
+    }
+
+    private boolean syncInitialLocalArtifacts(RepositoryContext gitRepoCtx) throws Exception {
+
+        boolean syncedLocalArtifacts;
+
+        //initialize repository
+        InitGitRepository(new File(gitRepoCtx.getGitLocalRepoPath()));
+        //add the remote repository (origin)
+        syncedLocalArtifacts = addRemote(gitRepoCtx.getLocalRepo(), gitRepoCtx.getGitRemoteRepoUrl());
+
+        return syncedLocalArtifacts;
+    }
+
+    public void scheduleSyncTask(RepositoryInformation repoInformation, boolean autoCheckout, boolean autoCommit, long delay) {
 
         int tenantId = Integer.parseInt(repoInformation.getTenantId());
 
@@ -471,37 +598,38 @@ public class GitBasedArtifactRepository {
         }
 
         if (repoCtxt.getArtifactSyncSchedular() == null) {
-           synchronized (repoCtxt) {
-               if (repoCtxt.getArtifactSyncSchedular() == null) {
-                   // create a new ScheduledExecutorService instance
-                   final ScheduledExecutorService artifactSyncScheduler = Executors.newScheduledThreadPool(1,
-                           new ArtifactSyncTaskThreadFactory(repoCtxt.getGitLocalRepoPath()));
+            synchronized (repoCtxt) {
+                if (repoCtxt.getArtifactSyncSchedular() == null) {
+                    // create a new ScheduledExecutorService instance
+                    final ScheduledExecutorService artifactSyncScheduler = Executors.newScheduledThreadPool(1,
+                            new ArtifactSyncTaskThreadFactory(repoCtxt.getGitLocalRepoPath()));
 
-                   // schedule at the given interval
-                   artifactSyncScheduler.scheduleAtFixedRate(new ArtifactSyncTask(repoInformation), delay, delay, TimeUnit.SECONDS);
-                   // cache
-                   repoCtxt.setArtifactSyncSchedular(artifactSyncScheduler);
+                    // schedule at the given interval
+                    artifactSyncScheduler.scheduleAtFixedRate(new ArtifactSyncTask(repoInformation, autoCheckout, autoCommit), delay, delay, TimeUnit.SECONDS);
+                    // cache
+                    repoCtxt.setArtifactSyncSchedular(artifactSyncScheduler);
 
-                   log.info("Scheduled Artifact Synchronization Task for path " + repoCtxt.getGitLocalRepoPath());
+                    log.info("Scheduled Artifact Synchronization Task for path " + repoCtxt.getGitLocalRepoPath());
 
-               } else {
-                   log.info("Artifact Synchronization Task for path " + repoCtxt.getGitLocalRepoPath() + " already scheduled");
-               }
-           }
+                } else {
+                    log.info("Artifact Synchronization Task for path " + repoCtxt.getGitLocalRepoPath() + " already scheduled");
+                }
+            }
         }
     }
-    
+
     public boolean cloneExists(RepositoryInformation repositoryInformation) {
-    	
-    	int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
-    	
-    	// if context for tenant is not initialized
-    	if(tenantToRepoContextMap.get(tenantId) == null)
-	    	initGitContext(repositoryInformation);
-    	
-        
-		RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
-        if(gitRepoCtx == null) { 
+
+        int tenantId = Integer.parseInt(repositoryInformation.getTenantId());
+
+        // if context for tenant is not initialized
+        if (tenantToRepoContextMap.get(tenantId) == null) {
+            initGitContext(repositoryInformation);
+        }
+
+
+        RepositoryContext gitRepoCtx = retrieveCachedGitContext(tenantId);
+        if (gitRepoCtx == null) {
             return false;
         }
 
@@ -515,16 +643,15 @@ public class GitBasedArtifactRepository {
      * will call 'RepositoryInformationService' for credentials.
      *
      * @param gitRepoCtx RepositoryContext instance for tenant
-     *
      * @return true if success, else false
      */
-    private boolean pullArtifacts (RepositoryContext gitRepoCtx) {
-        if(log.isDebugEnabled())  {
-    	    log.debug("Pulling artifacts");
+    /*private boolean pullArtifacts(RepositoryContext gitRepoCtx) {
+        if (log.isDebugEnabled()) {
+            log.debug("Pulling artifacts");
         }
         PullCommand pullCmd = gitRepoCtx.getGit().pull();
 
-        if(!gitRepoCtx.getKeyBasedAuthentication()) {
+        if (!gitRepoCtx.getKeyBasedAuthentication()) {
             UsernamePasswordCredentialsProvider credentialsProvider = createCredentialsProvider(gitRepoCtx);
             if (credentialsProvider != null)
                 pullCmd.setCredentialsProvider(credentialsProvider);
@@ -540,7 +667,7 @@ public class GitBasedArtifactRepository {
                 }
 
                 // execute artifact update extension
-                ExtensionUtils.executeArtifactsUpdatedExtension();
+                extensionHandler.onArtifactUpdateSchedulerEvent(String.valueOf(gitRepoCtx.getTenantId()));
             }
 
         } catch (InvalidConfigurationException e) {
@@ -550,7 +677,7 @@ public class GitBasedArtifactRepository {
             Utilities.deleteFolderStructure(new File(gitRepoCtx.getGitLocalRepoPath()));
             cloneRepository(gitRepoCtx);
             // execute artifact update extension
-            ExtensionUtils.executeArtifactsUpdatedExtension();
+            extensionHandler.onArtifactUpdateSchedulerEvent(String.valueOf(gitRepoCtx.getTenantId()));
             return true;
 
         } catch (JGitInternalException e) {
@@ -567,7 +694,7 @@ public class GitBasedArtifactRepository {
             Utilities.deleteFolderStructure(new File(gitRepoCtx.getGitLocalRepoPath()));
             cloneRepository(gitRepoCtx);
             // execute artifact update extension
-            ExtensionUtils.executeArtifactsUpdatedExtension();
+            extensionHandler.onArtifactUpdateSchedulerEvent(String.valueOf(gitRepoCtx.getTenantId()));
             return true;
 
         } catch (GitAPIException e) {
@@ -576,6 +703,62 @@ public class GitBasedArtifactRepository {
             return false;
         }
         return true;
+    }*/
+
+    private boolean pullArtifacts (RepositoryContext gitRepoCtx) throws CheckoutConflictException {
+
+        PullCommand pullCmd = gitRepoCtx.getGit().pull();
+
+        UsernamePasswordCredentialsProvider credentialsProvider = createCredentialsProvider(gitRepoCtx);
+
+        if (credentialsProvider == null) {
+            log.warn ("Remote repository credentials not available for tenant " + gitRepoCtx.getTenantId() +
+                    ", aborting pull");
+            return false;
+        }
+        pullCmd.setCredentialsProvider(credentialsProvider);
+
+        try {
+            PullResult pullResult = pullCmd.call();
+            // check if we have received any updates
+            if (!pullResult.getFetchResult().getTrackingRefUpdates().isEmpty()) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Artifacts were updated as a result of the pull operation, thread: " + Thread.currentThread().getName() + " - " +
+                            Thread.currentThread().getId());
+                }
+
+                // execute artifact update extension
+                extensionHandler.onArtifactUpdateSchedulerEvent(String.valueOf(gitRepoCtx.getTenantId()));
+            }
+
+        } catch (InvalidConfigurationException e) {
+            log.warn("Git pull unsuccessful for tenant " + gitRepoCtx.getTenantId() + ", invalid configuration. " + e.getMessage());
+            // FileUtilities.deleteFolderStructure(new File(gitRepoCtx.getLocalRepoPath()));
+            //cloneRepository(gitRepoCtx);
+            Utilities.deleteFolderStructure(new File(gitRepoCtx.getGitLocalRepoPath()));
+            cloneRepository(gitRepoCtx);
+            // execute artifact update extension
+            extensionHandler.onArtifactUpdateSchedulerEvent(String.valueOf(gitRepoCtx.getTenantId()));
+            return true;
+
+        } catch (JGitInternalException e) {
+            log.warn("Git pull unsuccessful for tenant " + gitRepoCtx.getTenantId() + ", " + e.getMessage());
+            return false;
+
+        } catch (TransportException e) {
+            log.error("Accessing remote git repository " + gitRepoCtx.getGitRemoteRepoUrl() + " failed for tenant " + gitRepoCtx.getTenantId(), e);
+            return false;
+
+        } catch (CheckoutConflictException e) {
+            log.warn("Git pull unsuccessful for tenant " + gitRepoCtx.getTenantId() + ", conflicts detected");
+            throw e;
+
+        } catch (GitAPIException e) {
+            log.error("Git pull operation for tenant " + gitRepoCtx.getTenantId() + " failed", e);
+            return false;
+        }
+
+        return true;
     }
 
     /**
@@ -583,30 +766,30 @@ public class GitBasedArtifactRepository {
      *
      * @param gitRepoCtx RepositoryContext instance of the tenant
      */
-    private void handleInvalidConfigurationError (RepositoryContext gitRepoCtx) {
+    private void handleInvalidConfigurationError(RepositoryContext gitRepoCtx) {
 
         StoredConfig storedConfig = gitRepoCtx.getLocalRepo().getConfig();
         boolean modifiedConfig = false;
-        if(storedConfig != null) {
+        if (storedConfig != null) {
 
-            if(storedConfig.getString("branch", "master", "remote") == null ||
+            if (storedConfig.getString("branch", "master", "remote") == null ||
                     storedConfig.getString("branch", "master", "remote").isEmpty()) {
 
                 storedConfig.setString("branch", "master", "remote", "origin");
                 modifiedConfig = true;
             }
 
-            if(storedConfig.getString("branch", "master", "merge") == null ||
+            if (storedConfig.getString("branch", "master", "merge") == null ||
                     storedConfig.getString("branch", "master", "merge").isEmpty()) {
 
                 storedConfig.setString("branch", "master", "merge", "refs/heads/master");
                 modifiedConfig = true;
             }
 
-            if(modifiedConfig) {
+            if (modifiedConfig) {
                 try {
                     storedConfig.save();
-                   // storedConfig.load();
+                    // storedConfig.load();
 
                 } catch (IOException e) {
                     log.error("Error saving git configuration file in local repo at " + gitRepoCtx.getGitLocalRepoPath(), e);
@@ -623,27 +806,26 @@ public class GitBasedArtifactRepository {
      *
      * @param gitRepoCtx RepositoryContext for the tenant
      */
-    private static void cloneRepository (RepositoryContext gitRepoCtx) { //should happen only at the beginning
+    /*private static void cloneRepository(RepositoryContext gitRepoCtx) { //should happen only at the beginning
 
         File gitRepoDir = new File(gitRepoCtx.getGitLocalRepoPath());
         if (gitRepoDir.exists()) {
-            if(isValidGitRepo(gitRepoCtx)) { //check if a this is a valid git repo
+            if (isValidGitRepo(gitRepoCtx)) { //check if a this is a valid git repo
                 log.info("Existing git repository detected for tenant " + gitRepoCtx.getTenantId() + ", no clone required");
                 gitRepoCtx.setCloneExists(true);
                 return;
-            }
-            else {
-                if(log.isDebugEnabled())
+            } else {
+                if (log.isDebugEnabled())
                     log.debug("Repository for tenant " + gitRepoCtx.getTenantId() + " is not a valid git repo");
                 Utilities.deleteFolderStructure(gitRepoDir); //if not a valid git repo but non-empty, delete it (else the clone will not work)
             }
         }
 
-        CloneCommand cloneCmd =  gitRepoCtx.getGit().cloneRepository().
-                        setURI(gitRepoCtx.getGitRemoteRepoUrl()).
-                        setDirectory(gitRepoDir);
+        CloneCommand cloneCmd = gitRepoCtx.getGit().cloneRepository().
+                setURI(gitRepoCtx.getGitRemoteRepoUrl()).
+                setDirectory(gitRepoDir);
 
-        if(!gitRepoCtx.getKeyBasedAuthentication()) {
+        if (!gitRepoCtx.getKeyBasedAuthentication()) {
             UsernamePasswordCredentialsProvider credentialsProvider = createCredentialsProvider(gitRepoCtx);
             if (credentialsProvider != null)
                 cloneCmd.setCredentialsProvider(credentialsProvider);
@@ -662,6 +844,42 @@ public class GitBasedArtifactRepository {
             log.error("Git clone operation for tenant " + gitRepoCtx.getTenantId() + " failed", e);
             e.printStackTrace();
         }
+    }*/
+
+    private boolean cloneRepository (RepositoryContext gitRepoCtx) { //should happen only at the beginning
+
+        boolean cloneSuccess = false;
+
+        File gitRepoDir = new File(gitRepoCtx.getGitLocalRepoPath());
+
+        CloneCommand cloneCmd =  Git.cloneRepository().
+                setURI(gitRepoCtx.getGitRemoteRepoUrl()).
+                setDirectory(gitRepoDir).
+                setBranch(GitDeploymentSynchronizerConstants.GIT_REFS_HEADS_MASTER);
+
+        UsernamePasswordCredentialsProvider credentialsProvider = createCredentialsProvider(gitRepoCtx);
+
+        if (credentialsProvider == null) {
+            log.warn ("Remote repository credentials not available for tenant " + gitRepoCtx.getTenantId() +
+                    ", aborting clone");
+            return false;
+        }
+        cloneCmd.setCredentialsProvider(credentialsProvider);
+
+        try {
+            cloneCmd.call();
+            log.info("Git clone operation for tenant " + gitRepoCtx.getTenantId() + " successful");
+            gitRepoCtx.setCloneExists(true);
+            cloneSuccess = true;
+
+        } catch (TransportException e) {
+            log.error("Accessing remote git repository failed for tenant " + gitRepoCtx.getTenantId(), e);
+
+        } catch (GitAPIException e) {
+            log.error("Git clone operation for tenant " + gitRepoCtx.getTenantId() + " failed", e);
+        }
+
+        return cloneSuccess;
     }
 
     /**
@@ -669,11 +887,10 @@ public class GitBasedArtifactRepository {
      * and creates a UsernamePasswordCredentialsProvider from a valid username and a password
      *
      * @param gitRepoCtx RepositoryContext instance
-     *
      * @return UsernamePasswordCredentialsProvider instance or null if service invocation failed or
      * username/password is not valid
      */
-    private static UsernamePasswordCredentialsProvider createCredentialsProvider (RepositoryContext gitRepoCtx) {
+    private static UsernamePasswordCredentialsProvider createCredentialsProvider(RepositoryContext gitRepoCtx) {
         return new UsernamePasswordCredentialsProvider(gitRepoCtx.getRepoUsername(), gitRepoCtx.getRepoPassword());
     }
 
@@ -681,10 +898,15 @@ public class GitBasedArtifactRepository {
      * Checks if an existing local repository is a valid git repository
      *
      * @param gitRepoCtx RepositoryContext instance
-     *
      * @return true if a valid git repo, else false
      */
-    private static boolean isValidGitRepo (RepositoryContext gitRepoCtx) {
+    private static boolean isValidGitRepo(RepositoryContext gitRepoCtx) {
+
+        // check if has been marked as cloned before
+        if(gitRepoCtx.cloneExists()) {
+            // repo is valid
+            return true;
+        }
 
         for (Ref ref : gitRepoCtx.getLocalRepo().getAllRefs().values()) { //check if has been previously cloned successfully, not empty
             if (ref.getObjectId() == null)
@@ -695,6 +917,55 @@ public class GitBasedArtifactRepository {
         return false;
     }
 
+    public static void InitGitRepository (File gitRepoDir) throws Exception {
+
+        try {
+            Git.init().setDirectory(gitRepoDir).setBare(false).call();
+
+        } catch (GitAPIException e) {
+            String errorMsg = "Initializing local repo at " + gitRepoDir.getPath() + " failed";
+            log.error(errorMsg, e);
+            throw new Exception(errorMsg, e);
+        }
+    }
+
+    public static boolean addRemote (Repository repository, String remoteUrl) {
+
+        boolean remoteAdded = false;
+
+        StoredConfig config = repository.getConfig();
+        config.setString(GitDeploymentSynchronizerConstants.REMOTE,
+                GitDeploymentSynchronizerConstants.ORIGIN,
+                GitDeploymentSynchronizerConstants.URL,
+                remoteUrl);
+
+        config.setString(GitDeploymentSynchronizerConstants.REMOTE,
+                GitDeploymentSynchronizerConstants.ORIGIN,
+                GitDeploymentSynchronizerConstants.FETCH,
+                GitDeploymentSynchronizerConstants.FETCH_LOCATION);
+
+        config.setString(GitDeploymentSynchronizerConstants.BRANCH,
+                GitDeploymentSynchronizerConstants.MASTER,
+                GitDeploymentSynchronizerConstants.REMOTE,
+                GitDeploymentSynchronizerConstants.ORIGIN);
+
+        config.setString(GitDeploymentSynchronizerConstants.BRANCH,
+                GitDeploymentSynchronizerConstants.MASTER,
+                GitDeploymentSynchronizerConstants.MERGE,
+                GitDeploymentSynchronizerConstants.GIT_REFS_HEADS_MASTER);
+
+        try {
+            config.save();
+            remoteAdded = true;
+
+        } catch (IOException e) {
+            log.error("Error in adding remote origin " + remoteUrl + " for local repository " +
+                    repository.toString(), e);
+        }
+
+        return remoteAdded;
+    }
+
 
     public void cleanupAutoCheckout() {
 
@@ -705,17 +976,30 @@ public class GitBasedArtifactRepository {
         return null;
     }
 
-	private class ArtifactSyncTask implements Runnable {
+    private class ArtifactSyncTask implements Runnable {
 
         private RepositoryInformation repositoryInformation;
+        private boolean autoCheckout;
+        private boolean autoCommit;
 
-        public ArtifactSyncTask (RepositoryInformation repositoryInformation) {
+        public ArtifactSyncTask(RepositoryInformation repositoryInformation, boolean autoCheckout, boolean autoCommit) {
             this.repositoryInformation = repositoryInformation;
+            this.autoCheckout = autoCheckout;
+            this.autoCommit = autoCommit;
         }
 
         @Override
         public void run() {
-            checkout(repositoryInformation);
+            try {
+                if (autoCheckout) {
+                    checkout(repositoryInformation);
+                }
+            } catch (Exception e) {
+                log.error(e);
+            }
+            if (autoCommit) {
+                commit(repositoryInformation);
+            }
         }
     }
 
@@ -723,7 +1007,7 @@ public class GitBasedArtifactRepository {
 
         private String localRepoPath;
 
-        public ArtifactSyncTaskThreadFactory (String localRepoPath) {
+        public ArtifactSyncTaskThreadFactory(String localRepoPath) {
             this.localRepoPath = localRepoPath;
         }
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java
index 19c104d..dcada46 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/internal/GitDeploymentSynchronizerConstants.java
@@ -58,4 +58,16 @@ public class GitDeploymentSynchronizerConstants {
     public static final String USERNAME_REGEX = "username:(.*?),";
     public static final String PASSWORD_REGEX = "password:(.*?)}";
 
+    //Git based constants
+    public static final String GIT_REFS_HEADS_MASTER = "refs/heads/master";
+    public static final String REMOTES_ORIGIN_MASTER = "remotes/origin/master";
+    public static final String REMOTE = "remote";
+    public static final String ORIGIN = "origin";
+    public static final String URL = "url";
+    public static final String FETCH = "fetch";
+    public static final String BRANCH = "branch";
+    public static final String MASTER = "master";
+    public static final String MERGE = "merge";
+    public static final String FETCH_LOCATION = "+refs/heads/*:refs/remotes/origin/*";
+
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java
index a6c2f4b..6d9bec6 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/git/util/Utilities.java
@@ -64,6 +64,9 @@ public class Utilities {
 
         try {
             FileUtils.deleteDirectory(existingDir);
+            if(log.isDebugEnabled()) {
+            	log.debug(" Directory [" + existingDir + "] deleted. ");
+            }
 
         } catch (IOException e) {
             log.error("Deletion of existing non-git repository structure failed");

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java
index 7c378f6..947329d 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/CartridgeAgentConfiguration.java
@@ -28,11 +28,7 @@ import org.apache.stratos.cartridge.agent.util.CartridgeAgentConstants;
 import org.apache.stratos.cartridge.agent.util.CartridgeAgentUtils;
 
 import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
+import java.util.*;
 
 /**
  * Cartridge agent configuration.
@@ -41,7 +37,7 @@ public class CartridgeAgentConfiguration {
 
     private static final Log log = LogFactory.getLog(CartridgeAgentConfiguration.class);
     private static volatile CartridgeAgentConfiguration instance;
-
+    private final String serviceGroup;
     private final String serviceName;
     private final String clusterId;
     private final String networkPartitionId;
@@ -52,16 +48,32 @@ public class CartridgeAgentConfiguration {
     private final String repoUrl;
     private final List<Integer> ports;
     private final List<String> logFilePaths;
+    private final boolean isCommitsEnabled;
+    private final boolean isCheckoutEnabled;
+    private final String listenAddress;
+    private final String lbClusterId;
+    private final String tenantId;
+    private final String isClustered;
+    private final String minCount;
     private Map<String, String> parameters;
     private boolean isMultitenant;
     private String persistenceMappings;
-    private final boolean isCommitsEnabled;
-    private final String listenAddress;
+    private boolean isInternalRepo;
+    private String isPrimary;
+    private String lbPrivateIp;
+    private String lbPublicIp;
+    private String deployment;
+    private String managerServiceName;
+    private String workerServiceName;
+    private String superTenantRepositoryPath;
+    private String tenantRepositoryPath;
 
     private CartridgeAgentConfiguration() {
-    	parameters = loadParametersFile();
+        parameters = loadParametersFile();
 
         try {
+            serviceGroup = readServiceGroup();
+            isClustered = readClustering();
             serviceName = readParameterValue(CartridgeAgentConstants.SERVICE_NAME);
             clusterId = readParameterValue(CartridgeAgentConstants.CLUSTER_ID);
             networkPartitionId = readParameterValue(CartridgeAgentConstants.NETWORK_PARTITION_ID);
@@ -73,19 +85,34 @@ public class CartridgeAgentConfiguration {
             ports = readPorts();
             logFilePaths = readLogFilePaths();
             isMultitenant = readMultitenant(CartridgeAgentConstants.MULTITENANT);
-            persistenceMappings = readPersisenceMapping();
-            isCommitsEnabled = readCommitsEnabled(CartridgeAgentConstants.COMMIT_ENABLED);
-            listenAddress = System.getProperty(CartridgeAgentConstants.LISTEN_ADDRESS);
+            persistenceMappings = readPersistenceMapping();
+            isCommitsEnabled = readCommitParameterValue();
+            isCheckoutEnabled = Boolean.parseBoolean(System.getProperty(CartridgeAgentConstants.AUTO_CHECKOUT));
 
+            listenAddress = System.getProperty(CartridgeAgentConstants.LISTEN_ADDRESS);
+            isInternalRepo = readInternalRepo(CartridgeAgentConstants.PROVIDER);
+            tenantId = readParameterValue(CartridgeAgentConstants.TENANT_ID);
+            lbClusterId = readParameterValue(CartridgeAgentConstants.LB_CLUSTER_ID);
+            minCount = readParameterValue(CartridgeAgentConstants.MIN_INSTANCE_COUNT);
+            // not mandatory
+            lbPrivateIp = System.getProperty(CartridgeAgentConstants.LB_PRIVATE_IP);
+            lbPublicIp = System.getProperty(CartridgeAgentConstants.LB_PUBLIC_IP);
+            tenantRepositoryPath =  System.getProperty(CartridgeAgentConstants.TENANT_REPO_PATH);
+            superTenantRepositoryPath = System.getProperty(CartridgeAgentConstants.SUPER_TENANT_REPO_PATH);
+
+            deployment = readDeployment();
+            managerServiceName = readManagerServiceType();
+            workerServiceName = readWorkerServiceType();
+            isPrimary = readIsPrimary();
         } catch (ParameterNotFoundException e) {
             throw new RuntimeException(e);
         }
 
-        if(log.isInfoEnabled()) {
+        if (log.isInfoEnabled()) {
             log.info("Cartridge agent configuration initialized");
         }
 
-        if(log.isDebugEnabled()) {
+        if (log.isDebugEnabled()) {
             log.debug(String.format("service-name: %s", serviceName));
             log.debug(String.format("cluster-id: %s", clusterId));
             log.debug(String.format("network-partition-id: %s", networkPartitionId));
@@ -95,26 +122,76 @@ public class CartridgeAgentConfiguration {
             log.debug(String.format("app-path: %s", appPath));
             log.debug(String.format("repo-url: %s", repoUrl));
             log.debug(String.format("ports: %s", ports.toString()));
+            log.debug(String.format("lb-private-ip: %s", lbPrivateIp));
+            log.debug(String.format("lb-public-ip: %s", lbPublicIp));
         }
     }
 
-    private boolean readCommitsEnabled(String commitEnabled) {
-    	boolean isCommitEnabled = false;
-    	try {
-    		isCommitEnabled = Boolean.parseBoolean(readParameterValue(commitEnabled));
-		} catch (ParameterNotFoundException e) {
-			// Missing commits enabled flag is not an exception
-			log.error(" Commits enabled payload parameter is not found");
-		}
-		return isCommitEnabled;
-	}
+    private String readDeployment(){
+        if (parameters.containsKey(CartridgeAgentConstants.DEPLOYMENT)) {
+            return parameters.get(CartridgeAgentConstants.DEPLOYMENT);
+        }
+        return null;
+    }
 
-	private boolean readMultitenant(String multitenant) throws ParameterNotFoundException {
-    	String multitenantStringValue = readParameterValue(multitenant);
-    	return Boolean.parseBoolean(multitenantStringValue);
-	}
+    private String readManagerServiceType(){
+
+        if (deployment == null) {
+            return null;
+        }
+
+        if (getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_MANAGER)) {
+            // if this is a manager, manager service type = service name
+            return serviceName;
+
+        } else if (getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_WORKER)) {
+            // if a worker, need to read the manager service type sent by payload
+            if (parameters.containsKey(CartridgeAgentConstants.MANAGER_SERVICE_TYPE)) {
+                return parameters.get(CartridgeAgentConstants.MANAGER_SERVICE_TYPE);
+            }
+
+        } else if (getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_DEFAULT)) {
+            // for default deployment, no manager service type
+            return null;
+
+        }
+
+        return null;
+    }
+
+    private String readWorkerServiceType(){
+
+        if (deployment == null) {
+            return null;
+        }
+
+        if (getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_WORKER)) {
+            // if this is a worker, worker service type = service name
+            return serviceName;
+
+        } else if (getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_MANAGER)) {
+            // if a manager, need to read the worker service type sent by payload
+            if (parameters.containsKey(CartridgeAgentConstants.WORKER_SERVICE_TYPE)) {
+                return parameters.get(CartridgeAgentConstants.WORKER_SERVICE_TYPE);
+            }
 
-	/**
+        } else if (getDeployment().equalsIgnoreCase(CartridgeAgentConstants.DEPLOYMENT_DEFAULT)) {
+            // for default deployment, no worker service type
+            return null;
+
+        }
+
+        return null;
+    }
+
+    private String readIsPrimary(){
+        if (parameters.containsKey(CartridgeAgentConstants.CLUSTERING_PRIMARY_KEY)) {
+            return parameters.get(CartridgeAgentConstants.CLUSTERING_PRIMARY_KEY);
+        }
+        return null;
+    }
+
+    /**
      * Get cartridge agent configuration singleton instance.
      *
      * @return
@@ -130,7 +207,40 @@ public class CartridgeAgentConfiguration {
         return instance;
     }
 
-    private String readPersisenceMapping() {
+    private boolean readCommitsEnabled(String commitEnabled) {
+        boolean isCommitEnabled = false;
+        try {
+            isCommitEnabled = Boolean.parseBoolean(readParameterValue(commitEnabled));
+
+        } catch (ParameterNotFoundException e) {
+            // Missing commits enabled flag is not an exception
+            log.error(" Commits enabled payload parameter is not found");
+        }
+        return isCommitEnabled;
+    }
+
+    private boolean readMultitenant(String multitenant) throws ParameterNotFoundException {
+        String multitenantStringValue = readParameterValue(multitenant);
+        return Boolean.parseBoolean(multitenantStringValue);
+    }
+
+    private boolean readInternalRepo(String internalRepo) {
+        String internalRepoStringValue = null;
+        try {
+            internalRepoStringValue = readParameterValue(internalRepo);
+        } catch (ParameterNotFoundException e) {
+            // Missing INTERNAL parameter is not an exception
+            log.info(" INTERNAL payload parameter is not found");
+        }
+
+        if(internalRepoStringValue.equals(CartridgeAgentConstants.INTERNAL)) {
+            return true;
+        } else{
+            return false;
+        }
+    }
+
+    private String readPersistenceMapping() {
         String persistenceMapping = null;
         try {
             persistenceMapping = readParameterValue("PERSISTENCE_MAPPING");
@@ -145,14 +255,14 @@ public class CartridgeAgentConfiguration {
         return persistenceMapping;
     }
 
-    
+
     private Map<String, String> loadParametersFile() {
-    	Map<String, String> parameters = new HashMap<String, String>();
-    	try {
+        Map<String, String> parameters = new HashMap<String, String>();
+        try {
 
             // read launch params
             File file = new File(System.getProperty(CartridgeAgentConstants.PARAM_FILE_PATH));
-            if(!file.exists()) {
+            if (!file.exists()) {
                 log.warn(String.format("File not found: %s", CartridgeAgentConstants.PARAM_FILE_PATH));
                 return parameters;
             }
@@ -161,48 +271,81 @@ public class CartridgeAgentConfiguration {
                 String line = scanner.nextLine();
                 String[] params = line.split(",");
                 for (String string : params) {
-					if (string != null) {
-						String[] var = string.split("=");
-						if (var.length >= 2) {
-							parameters.put(var[0], var[1]);
-						}
-					}
+                    if (string != null) {
+                        String[] var = string.split("=");
+                        if (var.length >= 2) {
+                            parameters.put(var[0], var[1]);
+                        }
+                    }
                 }
             }
             scanner.close();
         } catch (Exception e) {
-        	String message = "Could not read launch parameter file, hence trying to read from System properties.";
-        	log.warn(message, e);
+            String message = "Could not read launch parameter file, hence trying to read from System properties.";
+            log.warn(message, e);
+        }
+
+        return parameters;
+    }
+
+    private String readServiceGroup() {
+        if (parameters.containsKey(CartridgeAgentConstants.SERVICE_GROUP)) {
+            return parameters.get(CartridgeAgentConstants.SERVICE_GROUP);
+        } else {
+            return null;
+        }
+    }
+
+    private String readClustering() {
+        if (parameters.containsKey(CartridgeAgentConstants.CLUSTERING)) {
+            return parameters.get(CartridgeAgentConstants.CLUSTERING);
+        } else {
+            return null;
         }
-    	
-    	return parameters;
     }
 
-	private String readParameterValue(String parameterName) throws ParameterNotFoundException{
+    private String readParameterValue(String parameterName) throws ParameterNotFoundException {
 
-		if (parameters.containsKey(parameterName)) {
-			return parameters.get(parameterName);
-		}
+        if (parameters.containsKey(parameterName)) {
+            return parameters.get(parameterName);
+        }
 
-		if (System.getProperty(parameterName) != null) {
-			return System.getProperty(parameterName);
-		}
+        if (System.getProperty(parameterName) != null) {
+            return System.getProperty(parameterName);
+        }
 
-		String message = "Cannot find the value of required parameter: "+parameterName;
-		throw new ParameterNotFoundException(message);
-	}
+        String message = "Cannot find the value of required parameter: " + parameterName;
+        throw new ParameterNotFoundException(message);
+    }
+
+    private boolean readCommitParameterValue() throws ParameterNotFoundException {
+
+        if (parameters.containsKey(CartridgeAgentConstants.COMMIT_ENABLED)) {
+            return Boolean.parseBoolean(parameters.get(CartridgeAgentConstants.COMMIT_ENABLED));
+        }
+
+        if (System.getProperty(CartridgeAgentConstants.COMMIT_ENABLED) != null) {
+            return Boolean.parseBoolean(System.getProperty(CartridgeAgentConstants.COMMIT_ENABLED));
+        }
+
+        if (System.getProperty(CartridgeAgentConstants.AUTO_COMMIT) != null) {
+            return Boolean.parseBoolean(System.getProperty(CartridgeAgentConstants.AUTO_COMMIT));
+        }
+        log.info(CartridgeAgentConstants.COMMIT_ENABLED + " is not found and setting it to false");
+        return false;
+    }
 
     private List<Integer> readPorts() throws ParameterNotFoundException {
         List<Integer> ports = new ArrayList<Integer>();
         String portsStr = readParameterValue(CartridgeAgentConstants.PORTS);
         List<String> portsStrList = CartridgeAgentUtils.splitUsingTokenizer(portsStr, "|");
-        for(String port : portsStrList) {
+        for (String port : portsStrList) {
             ports.add(Integer.parseInt(port));
         }
         return ports;
     }
 
-    private List<String> readLogFilePaths () {
+    private List<String> readLogFilePaths() {
 
         String logFileStr = null;
         try {
@@ -258,20 +401,99 @@ public class CartridgeAgentConfiguration {
         return logFilePaths;
     }
 
-	public boolean isMultitenant() {
-		return isMultitenant;
-	}
+    public boolean isMultitenant() {
+        return isMultitenant;
+    }
 
     public String getPersistenceMappings() {
         return persistenceMappings;
     }
 
-	public boolean isCommitsEnabled() {
-		return isCommitsEnabled;
-	}
-
+    public boolean isCommitsEnabled() {
+        return isCommitsEnabled;
+    }
 
     public String getListenAddress() {
         return listenAddress;
     }
+
+    public boolean isInternalRepo() {
+        return isInternalRepo;
+    }
+
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    public String getLbClusterId() {
+        return lbClusterId;
+    }
+
+    public String getServiceGroup() {
+        return serviceGroup;
+    }
+
+    public String getIsClustered() {
+        return isClustered;
+    }
+
+    public String getMinCount() {
+        return minCount;
+    }
+
+    public String getIsPrimary() {
+        return isPrimary;
+    }
+
+	public String getLbPublicIp() {
+		return lbPublicIp;
+	}
+
+	public void setLbPublicIp(String lbPublicIp) {
+		this.lbPublicIp = lbPublicIp;
+	}
+
+	public String getLbPrivateIp() {
+		return lbPrivateIp;
+	}
+
+	public void setLbPrivateIp(String lbPrivateIp) {
+		this.lbPrivateIp = lbPrivateIp;
+	}
+
+    public String getDeployment() {
+        return deployment;
+    }
+
+    public void setDeployment(String deployment) {
+        this.deployment = deployment;
+    }
+
+    public String getManagerServiceName() {
+        return managerServiceName;
+    }
+
+    public void setManagerServiceName(String managerServiceName) {
+        this.managerServiceName = managerServiceName;
+    }
+
+    public String getWorkerServiceName() {
+        return workerServiceName;
+    }
+
+    public void setWorkerServiceName(String workerServiceName) {
+        this.workerServiceName = workerServiceName;
+    }
+
+    public String getSuperTenantRepositoryPath() {
+        return superTenantRepositoryPath;
+    }
+
+    public String getTenantRepositoryPath() {
+        return tenantRepositoryPath;
+    }
+
+    public boolean isCheckoutEnabled() {
+        return isCheckoutEnabled;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java
index 072734d..838dfd7 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/config/configurator/JndiConfigurator.java
@@ -23,8 +23,6 @@ import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
-import org.wso2.carbon.utils.CarbonUtils;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -38,7 +36,7 @@ public class JndiConfigurator {
     private static final Log log = LogFactory.getLog(JndiConfigurator.class);
 
     public static void configure() {
-        if(log.isDebugEnabled()) {
+        if (log.isDebugEnabled()) {
             log.debug("Configuring jndi.properties file");
         }
         generateJndiPropertiesFile();
@@ -46,26 +44,25 @@ public class JndiConfigurator {
 
     private static void generateJndiPropertiesFile() {
         String mbIp = System.getProperty("mb.ip");
-        if(StringUtils.isBlank(mbIp)) {
+        if (StringUtils.isBlank(mbIp)) {
             throw new RuntimeException("System property not found: mb.ip");
         }
         String mbPort = System.getProperty("mb.port");
-        if(StringUtils.isBlank(mbPort)) {
+        if (StringUtils.isBlank(mbPort)) {
             throw new RuntimeException("System property not found: mb.port");
         }
-        String templateFilePath =  System.getProperty("jndi.properties.template.file.path");
-        if(StringUtils.isBlank(templateFilePath)) {
+        String templateFilePath = System.getProperty("jndi.properties.template.file.path");
+        if (StringUtils.isBlank(templateFilePath)) {
             throw new RuntimeException("System property not found: jndi.properties.template.file.path");
         }
         String jndiFileDir = System.getProperty("jndi.properties.dir");
-        if(StringUtils.isBlank(jndiFileDir)) {
+        if (StringUtils.isBlank(jndiFileDir)) {
             throw new RuntimeException("System property not found: jndi.properties.dir");
         }
         String jndiFilePath = null;
-        if(jndiFileDir.endsWith("/")) {
+        if (jndiFileDir.endsWith("/")) {
             jndiFilePath = jndiFileDir + "jndi.properties";
-        }
-        else {
+        } else {
             jndiFilePath = jndiFileDir + "/" + "jndi.properties";
         }
 
@@ -83,7 +80,7 @@ public class JndiConfigurator {
 
             // Write jndi.properties file
             writeFileContent(content, jndiFilePath);
-            if(log.isDebugEnabled()) {
+            if (log.isDebugEnabled()) {
                 log.debug(String.format("jndi.properties file written to: %s", jndiFilePath));
             }
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/Constants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/Constants.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/Constants.java
index 8a721fc..067961d 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/Constants.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/Constants.java
@@ -26,4 +26,17 @@ public class Constants {
     public static String TAIL_COMMAND = "tail -n 100 -F ";
     public static String MEMBER_ID = "memberId";
     public static String LOG_EVENT = "logEvent";
+    
+    public static String DATE_FORMATTER = "yyyy-MM-dd";
+    public static String DATE_TIME_FORMATTER = "yyyy-MM-dd HH:mm:ss,SSS";
+    public static String TENANT_ID = "tenantID";
+    public static String SERVER_NAME = "serverName";
+    public static String APP_NAME = "appName";
+    public static String LOG_TIME = "logTime";
+    public static String PRIORITY = "priority";
+    public static String MESSAGE = "message";
+    public static String LOGGER = "logger";
+    public static String IP = "ip";  
+    public static String INSTANCE = "instance";
+    public static String STACKTRACE = "stacktrace";
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/FileBasedLogPublisher.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/FileBasedLogPublisher.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/FileBasedLogPublisher.java
index f75aa27..01e681e 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/FileBasedLogPublisher.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/FileBasedLogPublisher.java
@@ -39,9 +39,9 @@ public class FileBasedLogPublisher extends LogPublisher implements Runnable {
     private Process process;
     private Scanner scanner;
 
-    public FileBasedLogPublisher(DataPublisherConfiguration dataPublisherConfig, StreamDefinition streamDefinition, String filePath, String memberId) {
+    public FileBasedLogPublisher(DataPublisherConfiguration dataPublisherConfig, StreamDefinition streamDefinition, String filePath, String memberId, String tenantId, String alias, Long datetime) {
 
-        super(dataPublisherConfig, streamDefinition, filePath, memberId);
+    	super(dataPublisherConfig, streamDefinition, filePath, memberId, tenantId, alias, datetime);
         this.executorService = Executors.newSingleThreadExecutor(new FileBasedLogPublisherTaskThreadFactory(filePath));
     }
 
@@ -88,7 +88,7 @@ public class FileBasedLogPublisher extends LogPublisher implements Runnable {
             // set the relevant data
             dataContext.setCorrelationData(null);
             dataContext.setMetaData(new Object[] {memberId});
-            dataContext.setPayloadData(new Object[] {scanner.nextLine()});
+            dataContext.setPayloadData(new Object[] {tenantId, alias, "", datetime, "", scanner.nextLine(), "","",memberId, ""});
             // publish data
             publish(dataContext);
         }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisher.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisher.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisher.java
index 306f109..ae7412c 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisher.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisher.java
@@ -31,12 +31,19 @@ public abstract class LogPublisher extends DataPublisher {
 
     protected String memberId;
     protected String filePath;
+    protected String tenantId;
+    protected String alias;
+    protected Long datetime;
+    protected String serverName;
 
-    public LogPublisher (DataPublisherConfiguration dataPublisherConfig, StreamDefinition streamDefinition, String filePath, String memberId) {
+    public LogPublisher (DataPublisherConfiguration dataPublisherConfig, StreamDefinition streamDefinition, String filePath, String memberId, String tenantId, String alias, Long datetime) {
 
         super(dataPublisherConfig, streamDefinition);
         this.filePath = filePath;
         this.memberId = memberId;
+        this.tenantId = tenantId;
+        this.alias = alias;
+        this.datetime = datetime;
     }
 
     public void start () {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisherManager.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisherManager.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisherManager.java
index 02b8e63..5ca3c89 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisherManager.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/data/publisher/log/LogPublisherManager.java
@@ -19,21 +19,25 @@
 
 package org.apache.stratos.cartridge.agent.data.publisher.log;
 
+import java.io.File;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
 import org.apache.stratos.cartridge.agent.data.publisher.DataPublisherConfiguration;
 import org.apache.stratos.cartridge.agent.data.publisher.exception.DataPublisherException;
 import org.apache.stratos.cartridge.agent.util.CartridgeAgentUtils;
+import org.wso2.carbon.base.MultitenantConstants;
 import org.wso2.carbon.databridge.commons.Attribute;
 import org.wso2.carbon.databridge.commons.AttributeType;
 import org.wso2.carbon.databridge.commons.StreamDefinition;
 import org.wso2.carbon.databridge.commons.exception.MalformedStreamDefinitionException;
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
 public class LogPublisherManager {
 
     private static final Log log = LogFactory.getLog(LogPublisherManager.class);
@@ -58,7 +62,7 @@ public class LogPublisherManager {
 
         // stream definition identifier = {log.publisher.<cluster id>}
         try {
-            streamDefinition = new StreamDefinition(Constants.LOG_PUBLISHER_STREAM_PREFIX + CartridgeAgentConfiguration.getInstance().getClusterId(),
+        	streamDefinition = new StreamDefinition(Constants.LOG_PUBLISHER_STREAM_PREFIX + getValidTenantId(CartridgeAgentConfiguration.getInstance().getTenantId()) + "." + getAlias(CartridgeAgentConfiguration.getInstance().getClusterId()) + "." + getCurrentDate(),
                     Constants.LOG_PUBLISHER_STREAM_VERSION);
 
         } catch (MalformedStreamDefinitionException e) {
@@ -71,8 +75,17 @@ public class LogPublisherManager {
         metaDataDefinition.add(new Attribute(Constants.MEMBER_ID, AttributeType.STRING));
 
         List<Attribute> payloadDataDefinition = new ArrayList<Attribute>();
-        payloadDataDefinition.add(new Attribute(Constants.LOG_EVENT, AttributeType.STRING));
-
+        payloadDataDefinition.add(new Attribute(Constants.TENANT_ID, AttributeType.STRING));
+        payloadDataDefinition.add(new Attribute(Constants.SERVER_NAME, AttributeType.STRING));
+        payloadDataDefinition.add(new Attribute(Constants.APP_NAME, AttributeType.STRING));
+        payloadDataDefinition.add(new Attribute(Constants.LOG_TIME, AttributeType.LONG));
+        payloadDataDefinition.add(new Attribute(Constants.PRIORITY, AttributeType.STRING));
+        payloadDataDefinition.add(new Attribute(Constants.MESSAGE, AttributeType.STRING));
+        payloadDataDefinition.add(new Attribute(Constants.LOGGER, AttributeType.STRING));
+        payloadDataDefinition.add(new Attribute(Constants.IP, AttributeType.STRING));
+        payloadDataDefinition.add(new Attribute(Constants.INSTANCE, AttributeType.STRING));
+        payloadDataDefinition.add(new Attribute(Constants.STACKTRACE, AttributeType.STRING));
+                 
         streamDefinition.setMetaData(metaDataDefinition);
         streamDefinition.setPayloadData(payloadDataDefinition);
     }
@@ -85,7 +98,10 @@ public class LogPublisherManager {
         }
 
         LogPublisher fileBasedLogPublisher = new FileBasedLogPublisher(dataPublisherConfig, streamDefinition, filePath,
-               CartridgeAgentConfiguration.getInstance().getMemberId());
+        		CartridgeAgentConfiguration.getInstance().getMemberId(),
+        		getValidTenantId(CartridgeAgentConfiguration.getInstance().getTenantId()),
+        		getAlias(CartridgeAgentConfiguration.getInstance().getClusterId()),
+        		getDateTime());
 
         fileBasedLogPublisher.initialize();
         fileBasedLogPublisher.start();
@@ -102,4 +118,37 @@ public class LogPublisherManager {
            }
        }
     }
+    
+	private String getCurrentDate() {
+		Date now = new Date();
+		DateFormat formatter = new SimpleDateFormat(Constants.DATE_FORMATTER);
+		String formattedDate = formatter.format(now);
+		return formattedDate.replace("-", ".");
+	}
+
+	private String getAlias(String clusterId) {
+		String alias;
+		try {
+			alias = clusterId.split("\\.")[0];
+		} catch (Exception e) {
+			e.printStackTrace();
+			alias = clusterId;
+		}
+		return alias;
+	}
+
+	private Long getDateTime() {
+		Date date = new Date();
+		return date.getTime();
+	}
+
+	private String getValidTenantId(String tenantId) {
+		if (tenantId.equals(String
+				.valueOf(MultitenantConstants.INVALID_TENANT_ID))
+				|| tenantId.equals(String
+						.valueOf(MultitenantConstants.SUPER_TENANT_ID))) {
+			return "0";
+		}
+		return tenantId;
+	}
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java
index 9c2e21f..1046482 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/event/publisher/CartridgeAgentEventPublisher.java
@@ -25,7 +25,6 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
 import org.apache.stratos.cartridge.agent.statistics.publisher.HealthStatisticsNotifier;
-import org.apache.stratos.cartridge.agent.util.ExtensionUtils;
 import org.apache.stratos.messaging.broker.publish.EventPublisher;
 import org.apache.stratos.messaging.broker.publish.EventPublisherPool;
 import org.apache.stratos.messaging.event.instance.status.InstanceActivatedEvent;
@@ -63,7 +62,6 @@ public class CartridgeAgentEventPublisher {
                 log.info("Instance started event published");
             }
 
-            ExtensionUtils.executeInstanceStartedExtension();
         } else {
             if (log.isWarnEnabled()) {
                 log.warn("Instance already started");
@@ -81,7 +79,8 @@ public class CartridgeAgentEventPublisher {
                     CartridgeAgentConfiguration.getInstance().getClusterId(),
                     CartridgeAgentConfiguration.getInstance().getNetworkPartitionId(),
                     CartridgeAgentConfiguration.getInstance().getPartitionId(),
-                    CartridgeAgentConfiguration.getInstance().getMemberId());
+                    CartridgeAgentConfiguration.getInstance().getMemberId()
+            );
 
             // Event publisher connection will
             EventPublisher eventPublisher = EventPublisherPool.getPublisher(Constants.INSTANCE_STATUS_TOPIC);
@@ -90,8 +89,6 @@ public class CartridgeAgentEventPublisher {
                 log.info("Instance activated event published");
             }
 
-            ExtensionUtils.executeInstanceActivatedExtension();
-
             if (log.isInfoEnabled()) {
                 log.info("Starting health statistics notifier");
             }
@@ -108,7 +105,7 @@ public class CartridgeAgentEventPublisher {
         }
     }
 
-     public static void publishInstanceReadyToShutdownEvent() {
+    public static void publishInstanceReadyToShutdownEvent() {
         if (!isReadyToShutdown()) {
             if (log.isInfoEnabled()) {
                 log.info("Publishing instance activated event");
@@ -133,7 +130,7 @@ public class CartridgeAgentEventPublisher {
         }
     }
 
-     public static void publishMaintenanceModeEvent() {
+    public static void publishMaintenanceModeEvent() {
         if (!isMaintenance()) {
             if (log.isInfoEnabled()) {
                 log.info("Publishing instance maintenance mode event");


[10/14] git commit: Clustering changes for stratos

Posted by ma...@apache.org.
Clustering changes for stratos


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

Branch: refs/heads/4.0.0
Commit: 7b35e29e5eebc9a7f3efb8bb42042dcc48150f1e
Parents: fcc90fc
Author: Manula Thantriwatte <ma...@apache.org>
Authored: Tue Jul 1 06:37:12 2014 +0000
Committer: Manula Thantriwatte <ma...@apache.org>
Committed: Tue Jul 1 06:37:12 2014 +0000

----------------------------------------------------------------------
 .../stratos/autoscaler/PartitionContext.java    |   6 +-
 .../cloud/controller/CloudControllerClient.java |  25 +-
 .../AutoscalerTopologyEventReceiver.java        |  82 +-
 .../autoscaler/monitor/AbstractMonitor.java     |  25 +-
 .../autoscaler/monitor/ClusterMonitor.java      | 115 ++-
 .../autoscaler/monitor/LbClusterMonitor.java    |  26 +-
 .../autoscaler/rule/RuleTasksDelegator.java     |  43 +-
 .../autoscaler/util/AutoScalerConstants.java    |   6 +
 .../stratos/autoscaler/util/AutoscalerUtil.java |  26 +-
 .../cartridge/agent/ArtifactCopyTask.java       |  39 +
 .../stratos/cartridge/agent/CartridgeAgent.java | 478 ++++++---
 .../apache/stratos/cartridge/agent/Main.java    |  40 +-
 .../cartridge/agent/RepositoryFileListener.java |   8 +-
 .../synchronizer/RepositoryInformation.java     |  10 +-
 .../git/impl/GitBasedArtifactRepository.java    | 740 +++++++++-----
 .../GitDeploymentSynchronizerConstants.java     |  12 +
 .../synchronizer/git/util/Utilities.java        |   3 +
 .../config/CartridgeAgentConfiguration.java     | 348 +++++--
 .../config/configurator/JndiConfigurator.java   |  21 +-
 .../agent/data/publisher/log/Constants.java     |  13 +
 .../publisher/log/FileBasedLogPublisher.java    |   6 +-
 .../agent/data/publisher/log/LogPublisher.java  |   9 +-
 .../data/publisher/log/LogPublisherManager.java |  65 +-
 .../publisher/CartridgeAgentEventPublisher.java |  11 +-
 .../extensions/DefaultExtensionHandler.java     | 992 +++++++++++++++++++
 .../agent/extensions/ExtensionHandler.java      |  64 ++
 .../agent/util/CartridgeAgentConstants.java     |  56 +-
 .../agent/util/CartridgeAgentUtils.java         |   5 +-
 .../cartridge/agent/util/ExtensionUtils.java    | 500 +++++++++-
 .../stratos/cli/RestCommandLineService.java     | 310 +++++-
 .../stratos/cli/beans/cartridge/Cartridge.java  |   9 +
 .../stratos/cli/commands/SubscribeCommand.java  | 347 ++++---
 .../concurrent/PartitionValidatorCallable.java  |   4 +
 .../impl/CloudControllerServiceImpl.java        |  80 +-
 .../cloud/controller/pojo/Cartridge.java        |  52 +-
 .../cloud/controller/pojo/CartridgeInfo.java    |  10 +
 .../cloud/controller/pojo/MemberContext.java    |  10 +
 .../CartridgeInstanceDataPublisher.java         | 123 ++-
 .../controller/topology/TopologyBuilder.java    |  98 +-
 .../topology/TopologyEventPublisher.java        |  27 +-
 .../controller/util/CloudControllerUtil.java    |   1 +
 .../validate/AWSEC2PartitionValidator.java      |  30 +-
 .../stratos/common/util/CommandUtils.java       |  30 +
 .../LoadBalancerTenantEventReceiver.java        | 199 ++--
 .../LoadBalancerTopologyEventReceiver.java      |  37 +-
 .../conf/LoadBalancerConfiguration.java         |  29 +-
 .../balancer/context/LoadBalancerContext.java   |  11 +-
 .../context/LoadBalancerContextUtil.java        | 417 +++++++-
 .../context/map/HostNameAppContextMap.java      |  51 +
 .../context/map/HostNameClusterMap.java         |   2 +-
 .../context/map/MultiTenantClusterMap.java      |  13 +-
 .../TenantAwareLoadBalanceEndpoint.java         | 398 ++++++--
 .../stratos/load/balancer/util/Constants.java   |   9 +-
 .../test/LoadBalancerConfigurationTest.java     |  20 +-
 .../behaviour/CartridgeMgtBehaviour.java        |  13 +-
 .../org/apache/stratos/manager/dao/Cluster.java |   6 +-
 .../stratos/manager/deploy/service/Service.java |   9 +-
 .../service/ServiceDeploymentManager.java       |  49 +-
 .../multitenant/lb/DefaultLBService.java        | 110 ++
 .../multitenant/lb/ExistingLBService.java       |  52 +
 .../service/multitenant/lb/LBService.java       |  69 ++
 .../multitenant/lb/ServiceAwareLBService.java   | 137 +++
 .../category/DefaultLoadBalancerCategory.java   |  13 +-
 .../ServiceLevelLoadBalancerCategory.java       |   6 +-
 .../manager/CartridgeSubscriptionManager.java   | 224 ++++-
 .../manager/payload/BasicPayloadData.java       |  15 +-
 .../InstanceNotificationPublisher.java          |   5 +-
 .../publisher/TenantSynzhronizerTask.java       |  19 +-
 .../stratos/manager/repository/Repository.java  |   9 +
 .../repository/RepositoryNotification.java      |   2 +-
 .../DataInsertionAndRetrievalManager.java       |  25 +
 .../subscription/CartridgeSubscription.java     |  34 +-
 .../InternalRepoBasedCartridgeSubscription.java |  14 +-
 .../subscription/LBCartridgeSubscription.java   |  26 +-
 .../manager/subscription/SubscriptionData.java  |  34 +
 .../subscription/SubscriptionDomain.java        |  48 +
 .../factory/CartridgeSubscriptionFactory.java   |   9 +-
 .../utils/CartridgeSubscriptionUtils.java       |  29 +-
 .../model/TopologyClusterInformationModel.java  |  19 +
 .../manager/utils/RepositoryCreator.java        |   7 +-
 components/org.apache.stratos.messaging/pom.xml |   5 +
 .../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 +
 .../messaging/domain/topology/Member.java       |  68 +-
 .../messaging/domain/topology/Service.java      |  30 +-
 .../instance/notifier/ArtifactUpdatedEvent.java |   9 +
 .../tenant/SubscriptionDomainAddedEvent.java    |  67 ++
 .../tenant/SubscriptionDomainRemovedEvent.java  |  60 ++
 .../tenant/SubscriptionDomainsAddedEvent.java   |  60 ++
 .../tenant/SubscriptionDomainsRemovedEvent.java |  60 ++
 .../event/tenant/TenantSubscribedEvent.java     |   9 +-
 .../event/tenant/TenantUnSubscribedEvent.java   |  10 +-
 .../topology/ClusterMaintenanceModeEvent.java   |  58 ++
 .../event/topology/InstanceSpawnedEvent.java    |  12 +-
 .../event/topology/MemberActivatedEvent.java    |  40 +-
 .../event/topology/MemberTerminatedEvent.java   |  11 +
 .../event/topology/ServiceCreatedEvent.java     |  37 +-
 .../SubscriptionDomainsAddedEventListener.java  |  28 +
 ...SubscriptionDomainsRemovedEventListener.java |  28 +
 .../ClusterMaintenanceModeEventListener.java    |  25 +
 ...SubscriptionDomainAddedMessageProcessor.java |  95 ++
 ...bscriptionDomainRemovedMessageProcessor.java |  94 ++
 .../tenant/TenantMessageProcessorChain.java     |  12 +
 .../TenantSubscribedMessageProcessor.java       |   5 +-
 .../TenantUnSubscribedMessageProcessor.java     |   2 +-
 .../ClusterMaintenanceModeMessageProcessor.java | 115 +++
 .../InstanceSpawnedMessageProcessor.java        |   1 +
 .../topology/TopologyMessageProcessorChain.java |   6 +
 .../message/receiver/tenant/TenantManager.java  |   5 +
 .../stratos/messaging/util/Constants.java       |   2 +
 .../messaging/test/TenantDomainTest.java        |  45 +
 .../rest/endpoint/bean/CartridgeInfoBean.java   |  11 +
 .../bean/SubscriptionDomainRequest.java         |  35 +
 .../domain/SubscriptionDomainBean.java          |  29 +
 .../bean/util/converter/PojoConverter.java      |  30 +
 .../CustomThrowableExceptionMapper.java         |  39 +
 .../handlers/GenericExceptionMapper.java        |  46 +
 .../handlers/StratosAuthenticationHandler.java  |  43 +-
 .../stratos/rest/endpoint/mock/MockContext.java |  88 ++
 .../rest/endpoint/mock/StratosTestAdmin.java    |  46 +-
 .../rest/endpoint/services/ServiceUtils.java    | 130 ++-
 .../rest/endpoint/services/StratosAdmin.java    | 106 +-
 .../webapp/stratos-test/WEB-INF/cxf-servlet.xml |   2 +
 .../main/webapp/stratos/WEB-INF/cxf-servlet.xml |   4 +
 .../distribution/src/main/assembly/bin.xml      |  11 +-
 .../distribution/src/main/bin/stratos.sh        |  31 +-
 .../distribution/src/main/conf/log4j.properties |   4 +-
 .../conf/templates/jndi.properties.template     |   6 +-
 .../src/main/extensions/artifacts-copy.sh       |  29 +
 .../src/main/extensions/artifacts-updated.sh    |   2 +-
 .../distribution/src/main/extensions/clean.sh   |   2 +-
 .../src/main/extensions/complete-tenant.sh      |  30 +
 .../src/main/extensions/complete-topology.sh    |  34 +
 .../src/main/extensions/instance-activated.sh   |   2 +-
 .../src/main/extensions/instance-started.sh     |   2 +-
 .../src/main/extensions/member-activated.sh     |  43 +
 .../src/main/extensions/member-started.sh       |  43 +
 .../src/main/extensions/member-suspended.sh     |  43 +
 .../src/main/extensions/member-terminated.sh    |  43 +
 .../src/main/extensions/mount-volumes.sh        |  87 ++
 .../src/main/extensions/start-servers.sh        |  14 +-
 .../extensions/subscription-domain-added.sh     |  37 +
 .../extensions/subscription-domain-removed.sh   |  36 +
 products/stratos/conf/tenant-mgt.xml            |  42 +
 .../modules/distribution/src/assembly/bin.xml   |  17 +-
 .../distribution/src/main/conf/autoscaler.xml   |   2 +
 .../distribution/src/main/conf/mincheck.drl     |  13 +-
 .../distribution/src/main/conf/scaling.drl      |  17 +-
 .../src/main/conf/siddhi/siddhi.extension       |   1 +
 .../main/resources/CloudControllerService.wsdl  | 769 +++++++-------
 153 files changed, 8445 insertions(+), 1790 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/PartitionContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/PartitionContext.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/PartitionContext.java
index 86c2e49..1def03c 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/PartitionContext.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/PartitionContext.java
@@ -358,8 +358,12 @@ public class PartitionContext implements Serializable{
     public int getNonTerminatedMemberCount() {
         return activeMembers.size() + pendingMembers.size() + terminationPendingMembers.size();
     }
+    
+    public List<MemberContext> getActiveMembers() {
+		return activeMembers;
+	}
 
-    public boolean removeActiveMemberById(String memberId) {
+	public boolean removeActiveMemberById(String memberId) {
         boolean removeActiveMember = false;
         synchronized (activeMembers) {
             Iterator<MemberContext> iterator = activeMembers.listIterator();

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/client/cloud/controller/CloudControllerClient.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/client/cloud/controller/CloudControllerClient.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/client/cloud/controller/CloudControllerClient.java
index ee86c0f..b6cdac9 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/client/cloud/controller/CloudControllerClient.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/client/cloud/controller/CloudControllerClient.java
@@ -32,6 +32,10 @@ import org.apache.stratos.autoscaler.util.ConfUtil;
 import org.apache.stratos.cloud.controller.stub.*;
 import org.apache.stratos.cloud.controller.stub.deployment.partition.Partition;
 import org.apache.stratos.cloud.controller.stub.pojo.MemberContext;
+import org.apache.stratos.cloud.controller.stub.pojo.Properties;
+import org.apache.stratos.cloud.controller.stub.pojo.Property;
+import org.apache.stratos.messaging.domain.topology.Topology;
+import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 
 import java.rmi.RemoteException;
 
@@ -75,7 +79,7 @@ public class CloudControllerClient {
      * This will validate the given partitions against the given cartridge type.
      */
     
-    public boolean validateDeploymentPolicy(String cartridgeType, DeploymentPolicy deploymentPolicy) throws PartitionValidationException{
+    public synchronized boolean validateDeploymentPolicy(String cartridgeType, DeploymentPolicy deploymentPolicy) throws PartitionValidationException{
         try {
             if(log.isInfoEnabled()) {
                 log.info(String.format("Validating partitions of policy via cloud controller: [id] %s", deploymentPolicy.getId()));
@@ -103,7 +107,7 @@ public class CloudControllerClient {
     /*
      * Calls the CC to validate the partition.
      */
-    public boolean validatePartition(Partition partition) throws PartitionValidationException{
+    public synchronized boolean validatePartition(Partition partition) throws PartitionValidationException{
         
         try {
             if(log.isInfoEnabled()) {
@@ -127,7 +131,7 @@ public class CloudControllerClient {
     }
 
     public synchronized MemberContext spawnAnInstance(Partition partition,
-    		String clusterId, String lbClusterId, String networkPartitionId) throws SpawningException {
+    		String clusterId, String lbClusterId, String networkPartitionId, boolean isPrimary, int minMemberCount) throws SpawningException {
         try {
             if(log.isInfoEnabled()) {
                 log.info(String.format("Trying to spawn an instance via cloud controller: [cluster] %s [partition] %s [lb-cluster] %s [network-partition-id] %s",
@@ -140,7 +144,20 @@ public class CloudControllerClient {
             member.setLbClusterId(lbClusterId);
             member.setInitTime(System.currentTimeMillis());
             member.setNetworkPartitionId(networkPartitionId);
-
+            Properties memberContextProps = new Properties();
+            Property isPrimaryProp = new Property();
+            isPrimaryProp.setName("PRIMARY");
+            isPrimaryProp.setValue(String.valueOf(isPrimary));
+            
+            Property minCountProp = new Property();
+            minCountProp.setName("MIN_COUNT");
+            minCountProp.setValue(String.valueOf(minMemberCount));
+            
+            memberContextProps.addProperties(isPrimaryProp);
+            memberContextProps.addProperties(minCountProp);
+            member.setProperties(memberContextProps);
+            
+            
             long startTime = System.currentTimeMillis();
             MemberContext memberContext = stub.startInstance(member);
             if(log.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/message/receiver/topology/AutoscalerTopologyEventReceiver.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/message/receiver/topology/AutoscalerTopologyEventReceiver.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/message/receiver/topology/AutoscalerTopologyEventReceiver.java
index cf6223c..601502f 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/message/receiver/topology/AutoscalerTopologyEventReceiver.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/message/receiver/topology/AutoscalerTopologyEventReceiver.java
@@ -22,9 +22,12 @@ package org.apache.stratos.autoscaler.message.receiver.topology;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.autoscaler.*;
+import org.apache.stratos.autoscaler.client.cloud.controller.CloudControllerClient;
+import org.apache.stratos.cloud.controller.stub.deployment.partition.Partition;
 import org.apache.stratos.autoscaler.deployment.policy.DeploymentPolicy;
 import org.apache.stratos.autoscaler.exception.PartitionValidationException;
 import org.apache.stratos.autoscaler.exception.PolicyValidationException;
+import org.apache.stratos.autoscaler.exception.TerminationException;
 import org.apache.stratos.autoscaler.monitor.AbstractMonitor;
 import org.apache.stratos.autoscaler.monitor.ClusterMonitor;
 import org.apache.stratos.autoscaler.monitor.LbClusterMonitor;
@@ -107,16 +110,89 @@ public class AutoscalerTopologyEventReceiver implements Runnable {
 
         });
 
+        topologyEventReceiver.addEventListener(new MemberReadyToShutdownEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                try {
+                    MemberReadyToShutdownEvent memberReadyToShutdownEvent = (MemberReadyToShutdownEvent)event;
+                    AutoscalerContext asCtx = AutoscalerContext.getInstance();
+                    AbstractMonitor monitor;
+                    String clusterId = memberReadyToShutdownEvent.getClusterId();
+                    String memberId = memberReadyToShutdownEvent.getMemberId();
+
+                    if(asCtx.monitorExist(clusterId)){
+                        monitor = asCtx.getMonitor(clusterId);
+                    }else if(asCtx.lbMonitorExist(clusterId)){
+                        monitor = asCtx.getLBMonitor(clusterId);
+                    }else{
+                        if(log.isDebugEnabled()){
+                            log.debug(String.format("A cluster monitor is not found in autoscaler context [cluster] %s", clusterId));
+                        }
+                        return;
+                    }
+
+                    NetworkPartitionContext nwPartitionCtxt;
+                    nwPartitionCtxt = monitor.getNetworkPartitionCtxt(memberReadyToShutdownEvent.getNetworkPartitionId());
+
+                    // start a new member in the same Partition
+                    String partitionId = monitor.getPartitionOfMember(memberId);
+                    Partition partition = monitor.getDeploymentPolicy().getPartitionById(partitionId);
+                    PartitionContext partitionCtxt = nwPartitionCtxt.getPartitionCtxt(partitionId);
+
+
+                    // terminate the shutdown ready member
+                    CloudControllerClient ccClient = CloudControllerClient.getInstance();
+                    ccClient.terminate(memberId);
+
+                    // remove from active member list
+                    partitionCtxt.removeActiveMemberById(memberId);
+
+                    if (log.isInfoEnabled()) {
+                        log.info(String.format("Member is terminated and removed from the active members list: [member] %s [partition] %s [cluster] %s ",
+                                               memberId, partitionId, clusterId));
+                    }
+                } catch (TerminationException e) {
+                    log.error(e);
+                }
+            }
+
+        });
+
         topologyEventReceiver.addEventListener(new ClusterCreatedEventListener() {
+                    @Override
+                    protected void onEvent(Event event) {
+                        try {
+                            log.info("Event received: " + event);
+                            ClusterCreatedEvent e = (ClusterCreatedEvent) event;
+                            TopologyManager.acquireReadLock();
+                            Service service = TopologyManager.getTopology().getService(e.getServiceName());
+                            Cluster cluster = service.getCluster(e.getClusterId());
+                            startClusterMonitor(cluster);
+                        } catch (Exception e) {
+                            log.error("Error processing event", e);
+                        } finally {
+                            TopologyManager.releaseReadLock();
+                        }
+                    }
+
+                });
+
+        topologyEventReceiver.addEventListener(new ClusterMaintenanceModeEventListener() {
             @Override
             protected void onEvent(Event event) {
                 try {
                     log.info("Event received: " + event);
-                    ClusterCreatedEvent e = (ClusterCreatedEvent) event;
+                    ClusterMaintenanceModeEvent e = (ClusterMaintenanceModeEvent) event;
                     TopologyManager.acquireReadLock();
                     Service service = TopologyManager.getTopology().getService(e.getServiceName());
                     Cluster cluster = service.getCluster(e.getClusterId());
-                    startClusterMonitor(cluster);
+                    if(AutoscalerContext.getInstance().monitorExist((cluster.getClusterId()))) {
+                        AutoscalerContext.getInstance().getMonitor(e.getClusterId()).setStatus(e.getStatus());
+                    } else if (AutoscalerContext.getInstance().lbMonitorExist((cluster.getClusterId()))) {
+                        AutoscalerContext.getInstance().getLBMonitor(e.getClusterId()).setStatus(e.getStatus());
+                    } else {
+                        log.error("cluster monitor not exists for the cluster: " + cluster.toString());
+                    }
                 } catch (Exception e) {
                     log.error("Error processing event", e);
                 } finally {
@@ -124,7 +200,7 @@ public class AutoscalerTopologyEventReceiver implements Runnable {
                 }
             }
 
-        });
+                });
 
         topologyEventReceiver.addEventListener(new ClusterRemovedEventListener() {
             @Override

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/AbstractMonitor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/AbstractMonitor.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/AbstractMonitor.java
index 30ed61a..c1441bb 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/AbstractMonitor.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/AbstractMonitor.java
@@ -20,12 +20,15 @@ package org.apache.stratos.autoscaler.monitor;
 
 import java.util.Map;
 
+import org.apache.commons.configuration.XMLConfiguration;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.autoscaler.NetworkPartitionContext;
 import org.apache.stratos.autoscaler.deployment.policy.DeploymentPolicy;
 import org.apache.stratos.autoscaler.policy.model.AutoscalePolicy;
 import org.apache.stratos.autoscaler.rule.AutoscalerRuleEvaluator;
+import org.apache.stratos.autoscaler.util.AutoScalerConstants;
+import org.apache.stratos.autoscaler.util.ConfUtil;
 import org.apache.stratos.messaging.domain.topology.Cluster;
 import org.apache.stratos.messaging.domain.topology.Member;
 import org.apache.stratos.messaging.domain.topology.Service;
@@ -59,7 +62,23 @@ import org.drools.runtime.rule.FactHandle;
 	protected String serviceId;
 	
 	protected AutoscalerRuleEvaluator autoscalerRuleEvaluator;
-	
+
+    // time intereval between two runs of the Monitor. Default is 90000ms.
+    protected int monitorInterval;
+
+    public AbstractMonitor() {
+        readConfigurations();
+    }
+
+    private void readConfigurations () {
+
+        XMLConfiguration conf = ConfUtil.getInstance(null).getConfiguration();
+        monitorInterval = conf.getInt(AutoScalerConstants.AUTOSCALER_MONITOR_INTERVAL, 90000);
+        if (log.isDebugEnabled()) {
+            log.debug("Cluster Monitor task interval: " + getMonitorInterval());
+        }
+    }
+
 	@Override
 	public void run() {
 		// TODO Auto-generated method stub
@@ -177,4 +196,8 @@ import org.drools.runtime.rule.FactHandle;
     public void setMinCheckFactHandle(FactHandle minCheckFactHandle) {
         this.minCheckFactHandle = minCheckFactHandle;
     }
+
+    public int getMonitorInterval() {
+        return monitorInterval;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/ClusterMonitor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/ClusterMonitor.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/ClusterMonitor.java
index 6c44e4e..5bb478e 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/ClusterMonitor.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/ClusterMonitor.java
@@ -25,7 +25,13 @@ import org.apache.stratos.autoscaler.PartitionContext;
 import org.apache.stratos.autoscaler.deployment.policy.DeploymentPolicy;
 import org.apache.stratos.autoscaler.policy.model.AutoscalePolicy;
 import org.apache.stratos.autoscaler.rule.AutoscalerRuleEvaluator;
+import org.apache.stratos.cloud.controller.stub.pojo.MemberContext;
+import org.apache.stratos.cloud.controller.stub.pojo.Properties;
+import org.apache.stratos.cloud.controller.stub.pojo.Property;
+import org.apache.stratos.messaging.domain.topology.ClusterStatus;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -34,10 +40,12 @@ import java.util.concurrent.ConcurrentHashMap;
  * rules engine.
  *
  */
-public class ClusterMonitor extends AbstractMonitor{
+public class ClusterMonitor extends AbstractMonitor {
 
-    private static final Log log = LogFactory.getLog(ClusterMonitor.class);    
+    private static final Log log = LogFactory.getLog(ClusterMonitor.class);
     private String lbReferenceType;
+    private boolean hasPrimary;
+    private ClusterStatus status;
 
     public ClusterMonitor(String clusterId, String serviceId, DeploymentPolicy deploymentPolicy,
                           AutoscalePolicy autoscalePolicy) {
@@ -64,34 +72,78 @@ public class ClusterMonitor extends AbstractMonitor{
             Thread.sleep(60000);
         } catch (InterruptedException ignore) {
         }
+
         while (!isDestroyed()) {
             if (log.isDebugEnabled()) {
-                log.debug("Cluster monitor is running.. "+this.toString());
+                log.debug("Cluster monitor is running.. " + this.toString());
             }
             try {
-                monitor();
+                if(!ClusterStatus.In_Maintenance.equals(status)) {
+                    monitor();
+                } else {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Cluster monitor is suspended as the cluster is in " +
+                                    ClusterStatus.In_Maintenance + " mode......");
+                    }
+                }
             } catch (Exception e) {
-                log.error("Cluster monitor: Monitor failed."+this.toString(), e);
+                log.error("Cluster monitor: Monitor failed." + this.toString(), e);
             }
             try {
-                // TODO make this configurable
-                Thread.sleep(30000);
+                Thread.sleep(monitorInterval);
             } catch (InterruptedException ignore) {
             }
         }
     }
-    
+
+    private boolean isPrimaryMember(MemberContext memberContext){
+        Properties props = memberContext.getProperties();
+        if (log.isDebugEnabled()) {
+            log.debug(" Properties [" + props + "] ");
+        }
+        if (props != null && props.getProperties() != null) {
+            for (Property prop : props.getProperties()) {
+                if (prop.getName().equals("PRIMARY")) {
+                    if (Boolean.parseBoolean(prop.getValue())) {
+                        log.debug("Adding member id [" + memberContext.getMemberId() + "] " +
+                                "member instance id [" + memberContext.getInstanceId() + "] as a primary member");
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
     private void monitor() {
-//        if(clusterCtxt != null ) {
-            //TODO make this concurrent
+
+        //TODO make this concurrent
         for (NetworkPartitionContext networkPartitionContext : networkPartitionCtxts.values()) {
+            // store primary members in the network partition context
+            List<String> primaryMemberListInNetworkPartition = new ArrayList<String>();
 
             //minimum check per partition
-            for(PartitionContext partitionContext: networkPartitionContext.getPartitionCtxts().values()){
-
+            for (PartitionContext partitionContext : networkPartitionContext.getPartitionCtxts().values()) {
+                // store primary members in the partition context
+                List<String> primaryMemberListInPartition = new ArrayList<String>();
+                // get active primary members in this partition context
+                for (MemberContext memberContext : partitionContext.getActiveMembers()) {
+                    if (isPrimaryMember(memberContext)){
+                        primaryMemberListInPartition.add(memberContext.getMemberId());
+                    }
+                }
+                // get pending primary members in this partition context
+                for (MemberContext memberContext : partitionContext.getPendingMembers()) {
+                    if (isPrimaryMember(memberContext)){
+                        primaryMemberListInPartition.add(memberContext.getMemberId());
+                    }
+                }
+                primaryMemberListInNetworkPartition.addAll(primaryMemberListInPartition);
                 minCheckKnowledgeSession.setGlobal("clusterId", clusterId);
                 minCheckKnowledgeSession.setGlobal("lbRef", lbReferenceType);
-                
+                minCheckKnowledgeSession.setGlobal("isPrimary", hasPrimary);
+                minCheckKnowledgeSession.setGlobal("primaryMemberCount", primaryMemberListInPartition.size());
+
                 if (log.isDebugEnabled()) {
                     log.debug(String.format("Running minimum check for partition %s ", partitionContext.getPartitionId()));
                 }
@@ -104,8 +156,11 @@ public class ClusterMonitor extends AbstractMonitor{
             boolean rifReset = networkPartitionContext.isRifReset();
             boolean memoryConsumptionReset = networkPartitionContext.isMemoryConsumptionReset();
             boolean loadAverageReset = networkPartitionContext.isLoadAverageReset();
-            if(rifReset || memoryConsumptionReset || loadAverageReset){
-
+            if (log.isDebugEnabled()) {
+                log.debug("flag of rifReset: "  + rifReset + " flag of memoryConsumptionReset" + memoryConsumptionReset
+                        + " flag of loadAverageReset" + loadAverageReset);
+            }
+            if (rifReset || memoryConsumptionReset || loadAverageReset) {
                 scaleCheckKnowledgeSession.setGlobal("clusterId", clusterId);
                 //scaleCheckKnowledgeSession.setGlobal("deploymentPolicy", deploymentPolicy);
                 scaleCheckKnowledgeSession.setGlobal("autoscalePolicy", autoscalePolicy);
@@ -113,9 +168,12 @@ public class ClusterMonitor extends AbstractMonitor{
                 scaleCheckKnowledgeSession.setGlobal("mcReset", memoryConsumptionReset);
                 scaleCheckKnowledgeSession.setGlobal("laReset", loadAverageReset);
                 scaleCheckKnowledgeSession.setGlobal("lbRef", lbReferenceType);
+                scaleCheckKnowledgeSession.setGlobal("isPrimary", false);
+                scaleCheckKnowledgeSession.setGlobal("primaryMembers", primaryMemberListInNetworkPartition);
 
                 if (log.isDebugEnabled()) {
                     log.debug(String.format("Running scale check for network partition %s ", networkPartitionContext.getId()));
+                    log.debug(" Primary members : " + primaryMemberListInNetworkPartition);
                 }
 
                 scaleCheckFactHandle = AutoscalerRuleEvaluator.evaluateScaleCheck(scaleCheckKnowledgeSession
@@ -124,9 +182,9 @@ public class ClusterMonitor extends AbstractMonitor{
                 networkPartitionContext.setRifReset(false);
                 networkPartitionContext.setMemoryConsumptionReset(false);
                 networkPartitionContext.setLoadAverageReset(false);
-            } else if(log.isDebugEnabled()){
-                    log.debug(String.format("Scale rule will not run since the LB statistics have not received before this " +
-                            "cycle for network partition %s", networkPartitionContext.getId()) );
+            } else if (log.isDebugEnabled()) {
+                log.debug(String.format("Scale rule will not run since the LB statistics have not received before this " +
+                        "cycle for network partition %s", networkPartitionContext.getId()));
             }
         }
     }
@@ -134,8 +192,9 @@ public class ClusterMonitor extends AbstractMonitor{
     @Override
     public String toString() {
         return "ClusterMonitor [clusterId=" + clusterId + ", serviceId=" + serviceId +
-               ", deploymentPolicy=" + deploymentPolicy + ", autoscalePolicy=" + autoscalePolicy +
-               ", lbReferenceType=" + lbReferenceType + "]";
+                ", deploymentPolicy=" + deploymentPolicy + ", autoscalePolicy=" + autoscalePolicy +
+                ", lbReferenceType=" + lbReferenceType +
+                ", hasPrimary=" + hasPrimary + " ]";
     }
 
     public String getLbReferenceType() {
@@ -145,4 +204,20 @@ public class ClusterMonitor extends AbstractMonitor{
     public void setLbReferenceType(String lbReferenceType) {
         this.lbReferenceType = lbReferenceType;
     }
+
+    public boolean isHasPrimary() {
+        return hasPrimary;
+    }
+
+    public void setHasPrimary(boolean hasPrimary) {
+        this.hasPrimary = hasPrimary;
+    }
+
+    public ClusterStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(ClusterStatus status) {
+        this.status = status;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/LbClusterMonitor.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/LbClusterMonitor.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/LbClusterMonitor.java
index d5c1c92..5774461 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/LbClusterMonitor.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/LbClusterMonitor.java
@@ -27,6 +27,9 @@ import org.apache.stratos.autoscaler.PartitionContext;
 import org.apache.stratos.autoscaler.deployment.policy.DeploymentPolicy;
 import org.apache.stratos.autoscaler.policy.model.AutoscalePolicy;
 import org.apache.stratos.autoscaler.rule.AutoscalerRuleEvaluator;
+import org.apache.stratos.messaging.domain.topology.ClusterStatus;
+
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Is responsible for monitoring a service cluster. This runs periodically
@@ -37,6 +40,7 @@ import org.apache.stratos.autoscaler.rule.AutoscalerRuleEvaluator;
 public class LbClusterMonitor extends AbstractMonitor{
 
     private static final Log log = LogFactory.getLog(LbClusterMonitor.class);
+    private ClusterStatus status;
 
     public LbClusterMonitor(String clusterId, String serviceId, DeploymentPolicy deploymentPolicy,
                             AutoscalePolicy autoscalePolicy) {
@@ -60,13 +64,19 @@ public class LbClusterMonitor extends AbstractMonitor{
                 log.debug("Cluster monitor is running.. "+this.toString());
             }
             try {
-                monitor();
+                if( !ClusterStatus.In_Maintenance.equals(status)) {
+                    monitor();
+                } else {
+                    if (log.isDebugEnabled()) {
+                        log.debug("LB Cluster monitor is suspended as the cluster is in " +
+                                    ClusterStatus.In_Maintenance + " mode......");
+                    }
+                }
             } catch (Exception e) {
                 log.error("Cluster monitor: Monitor failed. "+this.toString(), e);
             }
             try {
-                // TODO make this configurable
-                Thread.sleep(30000);
+                Thread.sleep(monitorInterval);
             } catch (InterruptedException ignore) {
             }
         }
@@ -82,7 +92,8 @@ public class LbClusterMonitor extends AbstractMonitor{
 
                 if (partitionContext != null) {
                     minCheckKnowledgeSession.setGlobal("clusterId", clusterId);
-
+                    minCheckKnowledgeSession.setGlobal("isPrimary", false);
+                    
                     if (log.isDebugEnabled()) {
                         log.debug(String.format("Running minimum check for partition %s ",
                                                 partitionContext.getPartitionId()));
@@ -107,4 +118,11 @@ public class LbClusterMonitor extends AbstractMonitor{
     }
 
 
+    public ClusterStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(ClusterStatus status) {
+        this.status = status;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/RuleTasksDelegator.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/RuleTasksDelegator.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/RuleTasksDelegator.java
index 7d8304b..94def43 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/RuleTasksDelegator.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/RuleTasksDelegator.java
@@ -74,14 +74,47 @@ public class RuleTasksDelegator {
         }
         return autoscaleAlgorithm;
     }
+    
+    public void delegateSpawn(PartitionContext partitionContext, String clusterId, String lbRefType, boolean isPrimary) {
+    	
+        try {
+
+            String nwPartitionId = partitionContext.getNetworkPartitionId();
+            NetworkPartitionLbHolder lbHolder =
+                                          PartitionManager.getInstance()
+                                                          .getNetworkPartitionLbHolder(nwPartitionId);
+            String lbClusterId = getLbClusterId(lbRefType, partitionContext, lbHolder);
+            MemberContext memberContext =
+                                         CloudControllerClient.getInstance()
+                                                              .spawnAnInstance(partitionContext.getPartition(),
+                                                                      clusterId,
+                                                                      lbClusterId, partitionContext.getNetworkPartitionId(),
+                                                                      isPrimary,
+                                                                      partitionContext.getMinimumMemberCount());
+            if (memberContext != null) {
+                partitionContext.addPendingMember(memberContext);
+                if(log.isDebugEnabled()){
+                    log.debug(String.format("Pending member added, [member] %s [partition] %s", memberContext.getMemberId(),
+                            memberContext.getPartition().getId()));
+                }
+            } else if(log.isDebugEnabled()){
+                log.debug("Returned member context is null, did not add to pending members");
+            }
+
+        } catch (Throwable e) {
+            String message = "Cannot spawn an instance";
+            log.error(message, e);
+            throw new RuntimeException(message, e);
+        }
+    }
 
-    public void delegateSpawn(PartitionContext partitionContext, String clusterId, String lbRefType) {
+    // Original method. Assume this is invoked from mincheck.drl
+    
+   /* public void delegateSpawn(PartitionContext partitionContext, String clusterId, String lbRefType) {
         try {
 
             String nwPartitionId = partitionContext.getNetworkPartitionId();
-//            NetworkPartitionContext ctxt =
-//                                          PartitionManager.getInstance()
-//                                                          .getNetworkPartitionLbHolder(nwPartitionId);
+                                                         .getNetworkPartitionLbHolder(nwPartitionId);
             NetworkPartitionLbHolder lbHolder =
                                           PartitionManager.getInstance()
                                                           .getNetworkPartitionLbHolder(nwPartitionId);
@@ -109,7 +142,7 @@ public class RuleTasksDelegator {
             log.error(message, e);
             throw new RuntimeException(message, e);
         }
-   	}
+   	}*/
 
 
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoScalerConstants.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoScalerConstants.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoScalerConstants.java
index 5395d96..03cf861 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoScalerConstants.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoScalerConstants.java
@@ -38,5 +38,11 @@ public final class AutoScalerConstants {
 	public static final String NETWORK_PARTITION_LB_HOLDER_RESOURCE = "/network-partitions";
 	public static final String AS_POLICY_RESOURCE = "/policies/autoscalingPolicies";
 	public static final String DEPLOYMENT_POLICY_RESOURCE = "/policies/deploymentPolicies";
+
+
+    /**
+     * Configs
+     */
+    public static final String AUTOSCALER_MONITOR_INTERVAL = "autoscaler.monitorInterval";
        
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoscalerUtil.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoscalerUtil.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoscalerUtil.java
index 9ab1460..69b5acf 100644
--- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoscalerUtil.java
+++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/util/AutoscalerUtil.java
@@ -38,9 +38,11 @@ import org.apache.stratos.autoscaler.policy.PolicyManager;
 import org.apache.stratos.autoscaler.policy.model.AutoscalePolicy;
 import org.apache.stratos.cloud.controller.stub.deployment.partition.Partition;
 import org.apache.stratos.cloud.controller.stub.pojo.MemberContext;
+import org.apache.stratos.cloud.controller.stub.pojo.Property;
 import org.apache.stratos.cloud.controller.stub.pojo.Properties;
 import org.apache.stratos.cloud.controller.stub.pojo.Property;
 import org.apache.stratos.messaging.domain.topology.Cluster;
+import org.apache.stratos.messaging.domain.topology.ClusterStatus;
 import org.apache.stratos.messaging.domain.topology.Member;
 import org.apache.stratos.messaging.domain.topology.MemberStatus;
 import org.apache.stratos.messaging.util.Constants;
@@ -111,6 +113,7 @@ public class AutoscalerUtil {
                                         new ClusterMonitor(cluster.getClusterId(),
                                                            cluster.getServiceName(),
                                                            deploymentPolicy, policy);
+        clusterMonitor.setStatus(ClusterStatus.Created);
         
         for (PartitionGroup partitionGroup: deploymentPolicy.getPartitionGroups()){
 
@@ -130,7 +133,8 @@ public class AutoscalerUtil {
                         memberContext.setClusterId(member.getClusterId());
                         memberContext.setMemberId(memberId);
                         memberContext.setPartition(partition);
-
+                        memberContext.setProperties(convertMemberPropsToMemberContextProps(member.getProperties()));
+                        
                         if(MemberStatus.Activated.equals(member.getStatus())){
                             partitionContext.addActiveMember(memberContext);
 //                            networkPartitionContext.increaseMemberCountOfPartition(partition.getNetworkPartitionId(), 1);
@@ -175,12 +179,29 @@ public class AutoscalerUtil {
                 log.debug("Set the lb reference type: "+value);
             }
         }
+        
+        // set hasPrimary property
+        // hasPrimary is true if there are primary members available in that cluster
+        clusterMonitor.setHasPrimary(Boolean.parseBoolean(cluster.getProperties().getProperty(Constants.IS_PRIMARY)));
 
         log.info("Cluster monitor created: "+clusterMonitor.toString());
         return clusterMonitor;
     }
     
-    public static LbClusterMonitor getLBClusterMonitor(Cluster cluster) throws PolicyValidationException, PartitionValidationException {
+    private static Properties convertMemberPropsToMemberContextProps(
+			java.util.Properties properties) {
+    	Properties props = new Properties();
+    	for (Map.Entry<Object, Object> e : properties.entrySet()	) {
+			Property prop = new Property();
+			prop.setName((String)e.getKey());
+			prop.setValue((String)e.getValue());
+			props.addProperties(prop);
+		}    	
+		return props;
+	}
+
+
+	public static LbClusterMonitor getLBClusterMonitor(Cluster cluster) throws PolicyValidationException, PartitionValidationException {
         // FIXME fix the following code to correctly update
         // AutoscalerContext context = AutoscalerContext.getInstance();
         if (null == cluster) {
@@ -213,6 +234,7 @@ public class AutoscalerUtil {
                                         new LbClusterMonitor(clusterId,
                                                            cluster.getServiceName(),
                                                            deploymentPolicy, policy);
+        clusterMonitor.setStatus(ClusterStatus.Created);
         // partition group = network partition context
         for (PartitionGroup partitionGroup : deploymentPolicy.getPartitionGroups()) {
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/ArtifactCopyTask.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/ArtifactCopyTask.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/ArtifactCopyTask.java
new file mode 100644
index 0000000..75a5d1e
--- /dev/null
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/ArtifactCopyTask.java
@@ -0,0 +1,39 @@
+/**
+ *
+ */
+package org.apache.stratos.cartridge.agent;
+
+import java.io.File;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cartridge.agent.extensions.ExtensionHandler;
+
+/**
+ *
+ */
+public class ArtifactCopyTask implements Runnable {
+
+    private static final Log log = LogFactory.getLog(ArtifactCopyTask.class);
+    private final ExtensionHandler extensionHandler;
+    private String source;
+    private String destination;
+
+    public ArtifactCopyTask(String src, String des) {
+    	this.source = src;
+    	this.destination = des;
+        extensionHandler = CartridgeAgent.getExtensionHandler();
+    }
+
+    @Override
+    public void run() {
+        if (log.isDebugEnabled()) {
+            log.debug("Executing Artifact Copy Task source[" + source +"] destination[" + destination +"] ");
+        }        
+
+        if (new File(destination).exists()) {
+            extensionHandler.onCopyArtifactsExtension(source, destination);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java
index e4ddaed..dac128a 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/CartridgeAgent.java
@@ -20,28 +20,38 @@ package org.apache.stratos.cartridge.agent;
  *
 */
 
-
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.RepositoryInformation;
-import org.apache.stratos.cartridge.agent.artifact.deployment.synchronizer.git.impl.GitBasedArtifactRepository;
 import org.apache.stratos.cartridge.agent.config.CartridgeAgentConfiguration;
 import org.apache.stratos.cartridge.agent.data.publisher.DataPublisherConfiguration;
 import org.apache.stratos.cartridge.agent.data.publisher.exception.DataPublisherException;
 import org.apache.stratos.cartridge.agent.data.publisher.log.LogPublisherManager;
 import org.apache.stratos.cartridge.agent.event.publisher.CartridgeAgentEventPublisher;
+import org.apache.stratos.cartridge.agent.extensions.DefaultExtensionHandler;
+import org.apache.stratos.cartridge.agent.extensions.ExtensionHandler;
 import org.apache.stratos.cartridge.agent.util.CartridgeAgentConstants;
 import org.apache.stratos.cartridge.agent.util.CartridgeAgentUtils;
-import org.apache.stratos.cartridge.agent.util.ExtensionUtils;
 import org.apache.stratos.messaging.event.Event;
 import org.apache.stratos.messaging.event.instance.notifier.ArtifactUpdatedEvent;
 import org.apache.stratos.messaging.event.instance.notifier.InstanceCleanupClusterEvent;
 import org.apache.stratos.messaging.event.instance.notifier.InstanceCleanupMemberEvent;
+import org.apache.stratos.messaging.event.tenant.CompleteTenantEvent;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainAddedEvent;
+import org.apache.stratos.messaging.event.tenant.SubscriptionDomainRemovedEvent;
+import org.apache.stratos.messaging.event.topology.*;
 import org.apache.stratos.messaging.listener.instance.notifier.ArtifactUpdateEventListener;
 import org.apache.stratos.messaging.listener.instance.notifier.InstanceCleanupClusterEventListener;
 import org.apache.stratos.messaging.listener.instance.notifier.InstanceCleanupMemberEventListener;
+import org.apache.stratos.messaging.listener.tenant.CompleteTenantEventListener;
+import org.apache.stratos.messaging.listener.tenant.SubscriptionDomainsAddedEventListener;
+import org.apache.stratos.messaging.listener.tenant.SubscriptionDomainsRemovedEventListener;
+import org.apache.stratos.messaging.listener.topology.*;
 import org.apache.stratos.messaging.message.receiver.instance.notifier.InstanceNotifierEventReceiver;
+import org.apache.stratos.messaging.message.receiver.tenant.TenantEventReceiver;
+import org.apache.stratos.messaging.message.receiver.tenant.TenantManager;
+import org.apache.stratos.messaging.message.receiver.topology.TopologyEventReceiver;
+import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 
 import java.util.List;
 import java.util.concurrent.Executors;
@@ -53,13 +63,13 @@ import java.util.concurrent.TimeUnit;
  */
 public class CartridgeAgent implements Runnable {
 
-    private static final Log log = LogFactory.getLog(CartridgeAgent.class);
-
+   	private static final Log log = LogFactory.getLog(CartridgeAgent.class);
+    private static final ExtensionHandler extensionHandler = new DefaultExtensionHandler();
     private boolean terminated;
 
     @Override
     public void run() {
-        if(log.isInfoEnabled()) {
+        if (log.isInfoEnabled()) {
             log.info("Cartridge agent started");
         }
 
@@ -68,11 +78,26 @@ public class CartridgeAgent implements Runnable {
         // Start instance notifier listener thread
         subscribeToTopicsAndRegisterListeners();
 
+        // Start topology event receiver thread
+        registerTopologyEventListeners();
+
+        // Start tenant event receiver thread
+        registerTenantEventListeners();
+
+        // Execute instance started shell script
+        extensionHandler.onInstanceStartedEvent();
+
         // Publish instance started event
         CartridgeAgentEventPublisher.publishInstanceStartedEvent();
 
         // Execute start servers extension
-        ExtensionUtils.executeStartServersExtension();
+        try {
+            extensionHandler.startServerExtension();
+        } catch (Exception e) {
+            if (log.isErrorEnabled()) {
+                log.error("Error processing start servers event", e);
+            }
+        }
 
         // Wait for all ports to be active
         CartridgeAgentUtils.waitUntilPortsActive(CartridgeAgentConfiguration.getInstance().getListenAddress(),
@@ -80,128 +105,379 @@ public class CartridgeAgent implements Runnable {
 
         // Check repo url
         String repoUrl = CartridgeAgentConfiguration.getInstance().getRepoUrl();
+        /*if(CartridgeAgentConfiguration.getInstance().isMultitenant()) {
+            if (CartridgeAgentConfiguration.getInstance().isCommitsEnabled()) {
+                log.info(" Commits enabled. Starting File listener ");
+                ScheduledExecutorService scheduler = Executors
+                        .newScheduledThreadPool(1);
+                scheduler.scheduleWithFixedDelay(new RepositoryFileListener(), 0,
+                        10, TimeUnit.SECONDS);
+            }
+            
+            // Start super tenant artifact copy task
+            // from temp location to super tenant app path
+			//ScheduledExecutorService scheduler = Executors
+			//		.newScheduledThreadPool(1);
+			//scheduler.scheduleWithFixedDelay(new ArtifactCopyTask(
+			//		CartridgeAgentConstants.SUPERTENANT_TEMP_PATH,
+			//		CartridgeAgentConfiguration.getInstance().getAppPath()+ "/repository/deployment/server/"
+			//		),
+			//		0, 10, TimeUnit.SECONDS);
+        } */
+
         if ("null".equals(repoUrl) || StringUtils.isBlank(repoUrl)) {
-            if(log.isInfoEnabled()) {
+            if (log.isInfoEnabled()) {
                 log.info("No artifact repository found");
             }
+            // Execute instance activated shell script
+            extensionHandler.onInstanceActivatedEvent();
 
             // Publish instance activated event
             CartridgeAgentEventPublisher.publishInstanceActivatedEvent();
         } else {
             //Start periodical file checker task
-    		if (CartridgeAgentConfiguration.getInstance().isCommitsEnabled()) {
-    			log.info(" Commits enabled. Starting File listener ");
-    			ScheduledExecutorService scheduler = Executors
-    					.newScheduledThreadPool(1);
-    			scheduler.scheduleWithFixedDelay(new RepositoryFileListener(), 0,
-    					10, TimeUnit.SECONDS);
-    		}
+            /*if (CartridgeAgentConfiguration.getInstance().isCommitsEnabled()) {
+                log.info(" Commits enabled. Starting File listener ");
+                ScheduledExecutorService scheduler = Executors
+                        .newScheduledThreadPool(1);
+                scheduler.scheduleWithFixedDelay(new RepositoryFileListener(), 0,
+                        10, TimeUnit.SECONDS);
+            } */
         }
 
-        String persistanceMappingsPayload = CartridgeAgentConfiguration.getInstance().getPersistenceMappings();
-        if(persistanceMappingsPayload != null) {
-            ExtensionUtils.executeVolumeMountExtension(persistanceMappingsPayload);
+//        if (CartridgeAgentConfiguration.getInstance().isInternalRepo()) {
+//            // Start periodic file copy for super tenant
+//            // From repo/deployment/server to /tmp/-1234
+//
+//            ScheduledExecutorService scheduler = Executors
+//                    .newScheduledThreadPool(1);
+//            scheduler.scheduleWithFixedDelay(
+//            		new ArtifactCopyTask(CartridgeAgentConfiguration.getInstance().getAppPath()
+//            		+ "/repository/deployment/server/",
+//            		CartridgeAgentConstants.SUPERTENANT_TEMP_PATH), 0,
+//                    10, TimeUnit.SECONDS);
+//        }
+
+        String persistenceMappingsPayload = CartridgeAgentConfiguration.getInstance().getPersistenceMappings();
+        if (persistenceMappingsPayload != null) {
+            extensionHandler.volumeMountExtension(persistenceMappingsPayload);
         }
-       
-
-        // Keep the thread live until terminated
 
         // start log publishing
         LogPublisherManager logPublisherManager = new LogPublisherManager();
         publishLogs(logPublisherManager);
 
+        // Keep the thread live until terminated
         while (!terminated) {
-        	try {
-				Thread.sleep(1000);
-			} catch (InterruptedException ignore) {
-			}
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ignore) {
+            }
         }
 
         logPublisherManager.stop();
     }
 
-	protected void subscribeToTopicsAndRegisterListeners() {
-		if(log.isDebugEnabled()) {
+    protected void subscribeToTopicsAndRegisterListeners() {
+        if (log.isDebugEnabled()) {
             log.debug("Starting instance notifier event message receiver thread");
         }
 
-        InstanceNotifierEventReceiver eventReceiver = new InstanceNotifierEventReceiver();
-        eventReceiver.addEventListener(new ArtifactUpdateEventListener() {
+        InstanceNotifierEventReceiver instanceNotifierEventReceiver = new InstanceNotifierEventReceiver();
+        instanceNotifierEventReceiver.addEventListener(new ArtifactUpdateEventListener() {
             @Override
             protected void onEvent(Event event) {
-                onArtifactUpdateEvent((ArtifactUpdatedEvent) event);
+                try {
+                    extensionHandler.onArtifactUpdatedEvent((ArtifactUpdatedEvent) event);
+                } catch (Exception e) {
+                    if (log.isErrorEnabled()) {
+                        log.error("Error processing artifact update event", e);
+                    }
+                }
             }
         });
 
-        eventReceiver.addEventListener(new InstanceCleanupMemberEventListener() {
+        instanceNotifierEventReceiver.addEventListener(new InstanceCleanupMemberEventListener() {
             @Override
             protected void onEvent(Event event) {
-                String memberIdInPayload = CartridgeAgentConfiguration.getInstance().getMemberId();
-                InstanceCleanupMemberEvent instanceCleanupMemberEvent = (InstanceCleanupMemberEvent) event;
-                if (memberIdInPayload.equals(instanceCleanupMemberEvent.getMemberId())) {
-                    onInstanceCleanupEvent();
+                try {
+                    String memberIdInPayload = CartridgeAgentConfiguration.getInstance().getMemberId();
+                    InstanceCleanupMemberEvent instanceCleanupMemberEvent = (InstanceCleanupMemberEvent) event;
+                    if (memberIdInPayload.equals(instanceCleanupMemberEvent.getMemberId())) {
+                        extensionHandler.onInstanceCleanupMemberEvent(instanceCleanupMemberEvent);
+                    }
+                } catch (Exception e) {
+                    if (log.isErrorEnabled()) {
+                        log.error("Error processing instance cleanup member event", e);
+                    }
                 }
+
             }
         });
 
-        eventReceiver.addEventListener(new InstanceCleanupClusterEventListener() {
+        instanceNotifierEventReceiver.addEventListener(new InstanceCleanupClusterEventListener() {
             @Override
             protected void onEvent(Event event) {
                 String clusterIdInPayload = CartridgeAgentConfiguration.getInstance().getClusterId();
                 InstanceCleanupClusterEvent instanceCleanupClusterEvent = (InstanceCleanupClusterEvent) event;
                 if (clusterIdInPayload.equals(instanceCleanupClusterEvent.getClusterId())) {
-                    onInstanceCleanupEvent();
+                    extensionHandler.onInstanceCleanupClusterEvent(instanceCleanupClusterEvent);
                 }
             }
         });
-        Thread eventReceiverThread = new Thread(eventReceiver);
-        eventReceiverThread.start();
 
-        // Wait until message receiver is subscribed to the topic to
-        // send the instance started event
-        while (!eventReceiver.isSubscribed())  {
+        Thread instanceNotifierEventReceiverThread = new Thread(instanceNotifierEventReceiver);
+        instanceNotifierEventReceiverThread.start();
+        if (log.isInfoEnabled()) {
+            log.info("Instance notifier event message receiver thread started");
+        }
+
+        if (log.isDebugEnabled()) {
+            log.debug("Starting tenant event message receiver thread");
+        }
+
+        // Wait until message receiver is subscribed to the topic to send the instance started event
+        while (!instanceNotifierEventReceiver.isSubscribed()) {
             try {
                 Thread.sleep(2000);
             } catch (InterruptedException e) {
             }
         }
-	}
+    }
+
+    protected void registerTopologyEventListeners() {
+        if (log.isDebugEnabled()) {
+            log.debug("Starting topology event message receiver thread");
+        }
+        TopologyEventReceiver topologyEventReceiver = new TopologyEventReceiver();
+        topologyEventReceiver.addEventListener(new MemberActivatedEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                try {
+                    TopologyManager.acquireReadLock();
+                    if (log.isDebugEnabled()) {
+                        log.debug("Member activated event received");
+                    }
+                    MemberActivatedEvent memberActivatedEvent = (MemberActivatedEvent) event;
+                    extensionHandler.onMemberActivatedEvent(memberActivatedEvent);
+                } catch (Exception e) {
+                    if (log.isErrorEnabled()) {
+                        log.error("Error processing member activated event", e);
+                    }
+                } finally {
+                    TopologyManager.releaseReadLock();
+                }
+            }
+        });
+
+        topologyEventReceiver.addEventListener(new MemberTerminatedEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                try {
+                    TopologyManager.acquireReadLock();
+                    if (log.isDebugEnabled()) {
+                        log.debug("Member terminated event received");
+                    }
+                    MemberTerminatedEvent memberTerminatedEvent = (MemberTerminatedEvent) event;
+                    extensionHandler.onMemberTerminatedEvent(memberTerminatedEvent);
+                } catch (Exception e) {
+                    if (log.isErrorEnabled()) {
+                        log.error("Error processing member terminated event", e);
+                    }
+                } finally {
+                    TopologyManager.releaseReadLock();
+                }
+            }
+        });
+
+        topologyEventReceiver.addEventListener(new MemberSuspendedEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                try {
+                    TopologyManager.acquireReadLock();
+                    if (log.isDebugEnabled()) {
+                        log.debug("Member suspended event received");
+                    }
+                    MemberSuspendedEvent memberSuspendedEvent = (MemberSuspendedEvent) event;
+                    extensionHandler.onMemberSuspendedEvent(memberSuspendedEvent);
+                } catch (Exception e) {
+                    if (log.isErrorEnabled()) {
+                        log.error("Error processing member suspended event", e);
+                    }
+                } finally {
+                    TopologyManager.releaseReadLock();
+                }
+            }
+        });
+
+        topologyEventReceiver.addEventListener(new CompleteTopologyEventListener() {
+            private boolean initialized;
+
+            @Override
+            protected void onEvent(Event event) {
+                if (!initialized) {
+                    try {
+                        TopologyManager.acquireReadLock();
+                        if (log.isDebugEnabled()) {
+                            log.debug("Complete topology event received");
+                        }
+                        CompleteTopologyEvent completeTopologyEvent = (CompleteTopologyEvent) event;
+                        extensionHandler.onCompleteTopologyEvent(completeTopologyEvent);
+                        initialized = true;
+                    } catch (Exception e) {
+                        if (log.isErrorEnabled()) {
+                            log.error("Error processing complete topology event", e);
+                        }
+                    } finally {
+                        TopologyManager.releaseReadLock();
+                    }
+                }
+            }
+        });
+
+        topologyEventReceiver.addEventListener(new MemberStartedEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                try {
+                    TopologyManager.acquireReadLock();
+                    if (log.isDebugEnabled()) {
+                        log.debug("Member started event received");
+                    }
+                    MemberStartedEvent memberStartedEvent = (MemberStartedEvent) event;
+                    extensionHandler.onMemberStartedEvent(memberStartedEvent);
+                } catch (Exception e) {
+                    if (log.isErrorEnabled()) {
+                        log.error("Error processing member started event", e);
+                    }
+                } finally {
+                    TopologyManager.releaseReadLock();
+                }
+            }
+        });
+
+        Thread thread = new Thread(topologyEventReceiver);
+        thread.start();
+        if (log.isDebugEnabled()) {
+            log.info("Cartridge Agent topology receiver thread started");
+        }
+    }
+
+    protected void registerTenantEventListeners() {
+
+        if (log.isDebugEnabled()) {
+            log.debug("Starting tenant event message receiver thread");
+        }
 
-	protected void validateRequiredSystemProperties() {
-		String jndiPropertiesDir = System.getProperty(CartridgeAgentConstants.JNDI_PROPERTIES_DIR);
-        if(StringUtils.isBlank(jndiPropertiesDir)) {
-            if(log.isErrorEnabled()){
+        TenantEventReceiver tenantEventReceiver = new TenantEventReceiver();
+        tenantEventReceiver.addEventListener(new SubscriptionDomainsAddedEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                try {
+                    TenantManager.acquireReadLock();
+                    if (log.isDebugEnabled()) {
+                        log.debug("Subscription domain added event received");
+                    }
+                    SubscriptionDomainAddedEvent subscriptionDomainAddedEvent = (SubscriptionDomainAddedEvent) event;
+                    extensionHandler.onSubscriptionDomainAddedEvent(subscriptionDomainAddedEvent);
+                } catch (Exception e) {
+                    if (log.isErrorEnabled()) {
+                        log.error("Error processing subscription domains added event", e);
+                    }
+                } finally {
+                    TenantManager.releaseReadLock();
+                }
+
+            }
+        });
+
+        tenantEventReceiver.addEventListener(new SubscriptionDomainsRemovedEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                try {
+                    TenantManager.acquireReadLock();
+                    if (log.isDebugEnabled()) {
+                        log.debug("Subscription domain removed event received");
+                    }
+                    SubscriptionDomainRemovedEvent subscriptionDomainRemovedEvent = (SubscriptionDomainRemovedEvent) event;
+                    extensionHandler.onSubscriptionDomainRemovedEvent(subscriptionDomainRemovedEvent);
+                } catch (Exception e) {
+                    if (log.isErrorEnabled()) {
+                        log.error("Error processing subscription domains removed event", e);
+                    }
+                } finally {
+                    TenantManager.releaseReadLock();
+                }
+            }
+        });
+
+        tenantEventReceiver.addEventListener(new CompleteTenantEventListener() {
+            private boolean initialized;
+            @Override
+            protected void onEvent(Event event) {
+                if (!initialized) {
+                    try {
+                        TenantManager.acquireReadLock();
+                        if (log.isDebugEnabled()) {
+                            log.debug("Complete tenant event received");
+                        }
+                        CompleteTenantEvent completeTenantEvent = (CompleteTenantEvent) event;
+                        extensionHandler.onCompleteTenantEvent(completeTenantEvent);
+                        initialized = true;
+                    } catch (Exception e) {
+                        if (log.isErrorEnabled()) {
+                            log.error("Error processing complete tenant event", e);
+                        }
+                    } finally {
+                        TenantManager.releaseReadLock();
+                    }
+
+                } else {
+                    if (log.isInfoEnabled()) {
+                        log.info("Complete tenant event updating task disabled");
+                    }
+                }
+            }
+        });
+
+        Thread tenantEventReceiverThread = new Thread(tenantEventReceiver);
+        tenantEventReceiverThread.start();
+        if (log.isInfoEnabled()) {
+            log.info("Tenant event message receiver thread started");
+        }
+    }
+
+    protected void validateRequiredSystemProperties() {
+        String jndiPropertiesDir = System.getProperty(CartridgeAgentConstants.JNDI_PROPERTIES_DIR);
+        if (StringUtils.isBlank(jndiPropertiesDir)) {
+            if (log.isErrorEnabled()) {
                 log.error(String.format("System property not found: %s", CartridgeAgentConstants.JNDI_PROPERTIES_DIR));
             }
             return;
         }
 
         String payloadPath = System.getProperty(CartridgeAgentConstants.PARAM_FILE_PATH);
-        if(StringUtils.isBlank(payloadPath)) {
-            if(log.isErrorEnabled()){
+        if (StringUtils.isBlank(payloadPath)) {
+            if (log.isErrorEnabled()) {
                 log.error(String.format("System property not found: %s", CartridgeAgentConstants.PARAM_FILE_PATH));
             }
             return;
         }
 
         String extensionsDir = System.getProperty(CartridgeAgentConstants.EXTENSIONS_DIR);
-        if(StringUtils.isBlank(extensionsDir)) {
-            if(log.isWarnEnabled()){
+        if (StringUtils.isBlank(extensionsDir)) {
+            if (log.isWarnEnabled()) {
                 log.warn(String.format("System property not found: %s", CartridgeAgentConstants.EXTENSIONS_DIR));
             }
         }
-	}
-
-    private static void publishLogs (LogPublisherManager logPublisherManager) {
+    }
 
+    private static void publishLogs(LogPublisherManager logPublisherManager) {
         // check if enabled
         if (DataPublisherConfiguration.getInstance().isEnabled()) {
-
             List<String> logFilePaths = CartridgeAgentConfiguration.getInstance().getLogFilePaths();
             if (logFilePaths == null) {
                 log.error("No valid log file paths found, no logs will be published");
                 return;
-
             } else {
                 // initialize the log publishing
                 try {
@@ -216,7 +492,6 @@ public class CartridgeAgent implements Runnable {
                 for (String logFilePath : logFilePaths) {
                     try {
                         logPublisherManager.start(logFilePath);
-
                     } catch (DataPublisherException e) {
                         log.error("Error occurred in publishing logs ", e);
                     }
@@ -225,91 +500,8 @@ public class CartridgeAgent implements Runnable {
         }
     }
 
-    private void onArtifactUpdateEvent(ArtifactUpdatedEvent event) {
-        ArtifactUpdatedEvent artifactUpdatedEvent = event;
-        if(log.isInfoEnabled()) {
-            log.info(String.format("Artifact update event received: %s", artifactUpdatedEvent.toString()));
-        }
-
-        String clusterIdInPayload = CartridgeAgentConfiguration.getInstance().getClusterId();
-        String localRepoPath = CartridgeAgentConfiguration.getInstance().getAppPath();
-        String clusterIdInMessage = artifactUpdatedEvent.getClusterId();
-        String repoURL = artifactUpdatedEvent.getRepoURL();
-        String repoPassword = CartridgeAgentUtils.decryptPassword(artifactUpdatedEvent.getRepoPassword());
-        String repoUsername = artifactUpdatedEvent.getRepoUserName();
-        String tenantId = artifactUpdatedEvent.getTenantId();
-        boolean isMultitenant = CartridgeAgentConfiguration.getInstance().isMultitenant();
-
-        if(StringUtils.isNotEmpty(repoURL) && (clusterIdInPayload != null) && clusterIdInPayload.equals(clusterIdInMessage)) {
-            if(log.isInfoEnabled()) {
-                log.info("Executing git checkout");
-            }
-            RepositoryInformation repoInformation = new RepositoryInformation();
-            repoInformation.setRepoUsername(repoUsername);
-            if(repoPassword == null) {
-            	repoInformation.setRepoPassword("");
-            }else {
-            	repoInformation.setRepoPassword(repoPassword);
-            }            
-            repoInformation.setRepoUrl(repoURL);
-            repoInformation.setRepoPath(localRepoPath);
-            repoInformation.setTenantId(tenantId);
-            repoInformation.setMultitenant(isMultitenant);
-            boolean cloneExists = GitBasedArtifactRepository.getInstance().cloneExists(repoInformation);
-            GitBasedArtifactRepository.getInstance().checkout(repoInformation);
-
-            ExtensionUtils.executeArtifactsUpdatedExtension();
-
-            if(!cloneExists){
-                // Executed git clone, publish instance activated event
-                CartridgeAgentEventPublisher.publishInstanceActivatedEvent();
-            }
-
-            // Start the artifact update task
-            boolean artifactUpdateEnabled = Boolean.parseBoolean(System.getProperty(CartridgeAgentConstants.ENABLE_ARTIFACT_UPDATE));
-            if (artifactUpdateEnabled) {
-
-                long artifactUpdateInterval = 10;
-                // get update interval
-                String artifactUpdateIntervalStr = System.getProperty(CartridgeAgentConstants.ARTIFACT_UPDATE_INTERVAL);
-
-                if (artifactUpdateIntervalStr != null && !artifactUpdateIntervalStr.isEmpty()) {
-                    try {
-                        artifactUpdateInterval = Long.parseLong(artifactUpdateIntervalStr);
-
-                    } catch (NumberFormatException e) {
-                        log.error("Invalid artifact sync interval specified ", e);
-                        artifactUpdateInterval = 10;
-                    }
-                }
-
-                log.info("Artifact updating task enabled, update interval: " + artifactUpdateInterval + "s");
-                GitBasedArtifactRepository.getInstance().scheduleSyncTask(repoInformation, artifactUpdateInterval);
-
-            } else {
-                log.info("Artifact updating task disabled");
-            }
-
-        }
-    }
-
-    private void onInstanceCleanupEvent() {
-        if(log.isInfoEnabled()) {
-            log.info("Executing cleaning up the data in the cartridge instance...");
-        }
-        //sending event on the maintenance mode
-        CartridgeAgentEventPublisher.publishMaintenanceModeEvent();
-
-        //cleaning up the cartridge instance's data
-        ExtensionUtils.executeCleanupExtension();
-        if(log.isInfoEnabled()) {
-            log.info("cleaning up finished in the cartridge instance...");
-        }
-        if(log.isInfoEnabled()) {
-            log.info("publishing ready to shutdown event...");
-        }
-        //publishing the Ready to shutdown event after performing the cleanup
-        CartridgeAgentEventPublisher.publishInstanceReadyToShutdownEvent();
+    public static ExtensionHandler getExtensionHandler() {
+        return extensionHandler;
     }
 
     public void terminate() {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java
index a1be237..c2fbed1 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/Main.java
@@ -53,12 +53,6 @@ public class Main {
                 }
             });
 
-            // Configure log4j properties
-            if(log.isDebugEnabled()) {
-                log.debug("Configuring log4j.properties file path");
-            }
-            PropertyConfigurator.configure(System.getProperty("log4j.properties.file.path"));
-
             // Generate jndi.properties file
             JndiConfigurator.configure();
 
@@ -66,25 +60,25 @@ public class Main {
             CartridgeAgentConfiguration.getInstance();
 
             if (args.length >= 1) {
-            	String className = args[0];
-				try {
-					Constructor<?> c = Class.forName(className)
-							.getConstructor();
-					cartridgeAgent = (CartridgeAgent) c.newInstance();
-					log.info("Loaded Cartridge Agent using [class] "+className);
-				} catch (Exception e) {
-					String msg = String.format("Cannot load Cartridge Agent from [class name] %s, "
-							+ "hence using the default agent.", className);
-					log.warn(msg, e);
-				}
+                String className = args[0];
+                try {
+                    Constructor<?> c = Class.forName(className)
+                            .getConstructor();
+                    cartridgeAgent = (CartridgeAgent) c.newInstance();
+                    log.info("Loaded Cartridge Agent using [class] " + className);
+                } catch (Exception e) {
+                    String msg = String.format("Cannot load Cartridge Agent from [class name] %s, "
+                            + "hence using the default agent.", className);
+                    log.warn(msg, e);
+                }
             }
-            
+
             if (cartridgeAgent == null) {
-            	// load default agent
-            	cartridgeAgent = new CartridgeAgent();
-            	if (log.isDebugEnabled()) {
-            		log.debug("Loading default Cartridge Agent.");
-            	}
+                // load default agent
+                cartridgeAgent = new CartridgeAgent();
+                if (log.isDebugEnabled()) {
+                    log.debug("Loading default Cartridge Agent.");
+                }
             }
             // start agent
             Thread thread = new Thread(cartridgeAgent);

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java
index 8e79c66..59163d5 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/RepositoryFileListener.java
@@ -32,10 +32,10 @@ public class RepositoryFileListener implements Runnable {
         if(log.isDebugEnabled()) {
 		    log.debug("Executing repository file listener");
         }
-		boolean commitStatus = GitBasedArtifactRepository.getInstance().commit();
-        if(log.isDebugEnabled()) {
-		    log.debug("Commit status: " + commitStatus);
-        }
+		//boolean commitStatus = GitBasedArtifactRepository.getInstance().commit();
+        //if(log.isDebugEnabled()) {
+		//    log.debug("Commit status: " + commitStatus);
+       // }
 	}
 
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java
index 1be78a4..c35b70d 100644
--- a/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java
+++ b/components/org.apache.stratos.cartridge.agent/src/main/java/org/apache/stratos/cartridge/agent/artifact/deployment/synchronizer/RepositoryInformation.java
@@ -31,6 +31,7 @@ public class RepositoryInformation {
 	private String repoPath;
 	private String tenantId;
 	private boolean isMultitenant;
+    private boolean commitEnabled;
 	
 	public String getRepoUrl() {
 		return repoUrl;
@@ -68,5 +69,12 @@ public class RepositoryInformation {
 	public void setMultitenant(boolean isMultitenant) {
 		this.isMultitenant = isMultitenant;
 	}
-	
+
+    public boolean isCommitEnabled() {
+        return commitEnabled;
+    }
+
+    public void setCommitEnabled(boolean commitEnabled) {
+        this.commitEnabled = commitEnabled;
+    }
 }


[14/14] git commit: Merge branch '4.0.0' of https://git-wip-us.apache.org/repos/asf/stratos into 4.0.0

Posted by ma...@apache.org.
Merge branch '4.0.0' of https://git-wip-us.apache.org/repos/asf/stratos into 4.0.0


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

Branch: refs/heads/4.0.0
Commit: e1c15c4e986e7358fef5ea1a2c03a4459bcc14a0
Parents: 07965e5 37372c2
Author: Manula Thantriwatte <ma...@apache.org>
Authored: Tue Jul 8 03:55:25 2014 +0000
Committer: Manula Thantriwatte <ma...@apache.org>
Committed: Tue Jul 8 03:55:25 2014 +0000

----------------------------------------------------------------------
 .../balancer/extension/api/LoadBalancerExtension.java  | 13 ++++++++-----
 .../org/apache/stratos/haproxy/extension/HAProxy.java  |  3 +++
 .../stratos/haproxy/extension/HAProxyConfigWriter.java |  5 +++++
 .../haproxy/extension/HAProxyStatisticsReader.java     |  5 +++--
 4 files changed, 19 insertions(+), 7 deletions(-)
----------------------------------------------------------------------



[13/14] git commit: Merge branch '4.0.0' of https://git-wip-us.apache.org/repos/asf/stratos into 4.0.0

Posted by ma...@apache.org.
Merge branch '4.0.0' of https://git-wip-us.apache.org/repos/asf/stratos into 4.0.0


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

Branch: refs/heads/4.0.0
Commit: 07965e544ae0e3fc12bbcacb85992fb0199b4a2a
Parents: 6b6e509 862a71d
Author: Manula Thantriwatte <ma...@apache.org>
Authored: Thu Jul 3 12:57:13 2014 +0000
Committer: Manula Thantriwatte <ma...@apache.org>
Committed: Thu Jul 3 12:57:13 2014 +0000

----------------------------------------------------------------------
 tools/puppet3/modules/haproxy/files/README.txt  | 12 +++
 tools/puppet3/modules/haproxy/manifests/init.pp | 70 ++++++++++++++++++
 .../modules/haproxy/manifests/initialize.pp     | 77 ++++++++++++++++++++
 .../modules/haproxy/manifests/push_templates.pp | 30 ++++++++
 .../puppet3/modules/haproxy/manifests/start.pp  | 25 +++++++
 .../templates/bin/haproxy-extension.sh.erb      | 48 ++++++++++++
 .../haproxy/templates/conf/jndi.properties.erb  | 33 +++++++++
 7 files changed, 295 insertions(+)
----------------------------------------------------------------------



[04/14] Clustering changes for stratos

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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..70fb974 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(",");
@@ -216,4 +219,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/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/InstanceNotificationPublisher.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/InstanceNotificationPublisher.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/InstanceNotificationPublisher.java
index e10d4ff..6a885e8 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/InstanceNotificationPublisher.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/InstanceNotificationPublisher.java
@@ -57,10 +57,11 @@ public class InstanceNotificationPublisher {
         artifactUpdateEvent.setRepoPassword(repository.getPassword());
         artifactUpdateEvent.setRepoURL(repository.getUrl());
         artifactUpdateEvent.setTenantId(tenantId);
+        artifactUpdateEvent.setCommitEnabled(repository.isCommitEnabled());
 
         log.info(String.format("Publishing artifact updated event: [cluster] %s " +
-                "[repo-URL] %s [repo-username] %s [repo-password] %s [tenant-id] %s",
-                clusterId, repository.getUrl(), repository.getUserName(), repository.getPassword(), tenantId));
+                "[repo-URL] %s [repo-username] %s [tenant-id] %s",
+                clusterId, repository.getUrl(), repository.getUserName(), tenantId));
         publish(artifactUpdateEvent);
     }
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/TenantSynzhronizerTask.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/TenantSynzhronizerTask.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/TenantSynzhronizerTask.java
index 3eac3f5..1e291ab 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/TenantSynzhronizerTask.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/publisher/TenantSynzhronizerTask.java
@@ -24,18 +24,17 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.manager.internal.DataHolder;
 import org.apache.stratos.manager.retriever.DataInsertionAndRetrievalManager;
 import org.apache.stratos.manager.subscription.CartridgeSubscription;
+import org.apache.stratos.manager.subscription.SubscriptionDomain;
 import org.apache.stratos.messaging.broker.publish.EventPublisher;
 import org.apache.stratos.messaging.broker.publish.EventPublisherPool;
+import org.apache.stratos.messaging.domain.tenant.Subscription;
 import org.apache.stratos.messaging.domain.tenant.Tenant;
 import org.apache.stratos.messaging.event.tenant.CompleteTenantEvent;
 import org.apache.stratos.messaging.util.Constants;
 import org.wso2.carbon.ntask.core.Task;
 import org.wso2.carbon.user.core.tenant.TenantManager;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * Tenant synchronizer task for publishing complete tenant event periodically
@@ -71,12 +70,18 @@ public class TenantSynzhronizerTask implements Task {
                 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                 Collection<CartridgeSubscription> cartridgeSubscriptions = new DataInsertionAndRetrievalManager().getCartridgeSubscriptions(tenant.getTenantId());
                 if (cartridgeSubscriptions != null && !cartridgeSubscriptions.isEmpty()) {
-                    for (CartridgeSubscription subscription : cartridgeSubscriptions) {
+                    for (CartridgeSubscription cartridgeSubscription : cartridgeSubscriptions) {
                         if(log.isDebugEnabled()) {
                             log.debug(String.format("Tenant subscription found: [tenant-id] %d [tenant-domain] %s [service] %s",
-                                    carbonTenant.getId(), carbonTenant.getDomain(), subscription.getType()));
+                                    carbonTenant.getId(), carbonTenant.getDomain(), cartridgeSubscription.getType()));
                         }
-                        tenant.addServiceSubscription(subscription.getType());
+                        HashSet<String> clusterIds = new HashSet<String>();
+                        clusterIds.add(cartridgeSubscription.getCluster().getClusterDomain());
+                        Subscription subscription = new Subscription(cartridgeSubscription.getType(),clusterIds);
+                        for(SubscriptionDomain subscriptionDomain : cartridgeSubscription.getSubscriptionDomains()) {
+                            subscription.addSubscriptionDomain(subscriptionDomain.getDomainName(), subscriptionDomain.getApplicationContext());
+                        }
+                        tenant.addSubscription(subscription);
                     }
                 }
                 tenants.add(tenant);

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/RepositoryNotification.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/RepositoryNotification.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/RepositoryNotification.java
index 8c10d5a..778b3fc 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/RepositoryNotification.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/repository/RepositoryNotification.java
@@ -57,7 +57,7 @@ public class RepositoryNotification {
 		if (cartridgeSubscription.getRepository() != null) {
 			InstanceNotificationPublisher publisher = new InstanceNotificationPublisher();
 			publisher.sendArtifactUpdateEvent(cartridgeSubscription.getRepository(),
-					String.valueOf(cartridgeSubscription.getCluster().getId()),
+					String.valueOf(cartridgeSubscription.getCluster().getClusterDomain()),
 					String.valueOf(cartridgeSubscription.getSubscriber().getTenantId()));
 
 			if (log.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/retriever/DataInsertionAndRetrievalManager.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/retriever/DataInsertionAndRetrievalManager.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/retriever/DataInsertionAndRetrievalManager.java
index 386758f..0504fd3 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/retriever/DataInsertionAndRetrievalManager.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/retriever/DataInsertionAndRetrievalManager.java
@@ -68,6 +68,31 @@ public class DataInsertionAndRetrievalManager {
         }
     }
 
+    public void cacheAndUpdateSubscription(CartridgeSubscription cartridgeSubscription) throws PersistenceManagerException {
+
+        // get the write lock
+        LookupDataHolder.getInstance().acquireWriteLock();
+
+        try {
+            // store in LookupDataHolder
+            LookupDataHolder.getInstance().putSubscription(cartridgeSubscription);
+
+            try {
+                // store in Persistence Manager
+                persistenceManager.persistCartridgeSubscription(cartridgeSubscription);
+
+            } catch (PersistenceManagerException e) {
+                String errorMsg = "Error in updating cartridge subscription in persistence manager";
+                log.error(errorMsg, e);
+                throw e;
+            }
+
+        } finally {
+            // release the write lock
+            LookupDataHolder.getInstance().releaseWriteLock();
+        }
+    }
+
     public void removeSubscription (int tenantId, String subscriptionAlias) throws PersistenceManagerException {
 
         CartridgeSubscription cartridgeSubscription = getCartridgeSubscription(tenantId, subscriptionAlias);

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 e143bc3..ebf7276 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
@@ -34,7 +34,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 {
 
@@ -58,7 +58,7 @@ public abstract class CartridgeSubscription implements Serializable {
     //private List<String> connectedSubscriptionAliases;
     private String subscriptionKey;
     private SubscriptionTenancyBehaviour subscriptionTenancyBehaviour;
-
+    private Map<String, SubscriptionDomain> subscriptionDomainMap;
     
     /**
      * Constructor
@@ -79,6 +79,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>();
     }
 
     /**
@@ -117,6 +118,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
      *
@@ -387,7 +415,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/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/InternalRepoBasedCartridgeSubscription.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/InternalRepoBasedCartridgeSubscription.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/InternalRepoBasedCartridgeSubscription.java
index ebd9a32..1b698e2 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/InternalRepoBasedCartridgeSubscription.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/InternalRepoBasedCartridgeSubscription.java
@@ -52,11 +52,23 @@ public class InternalRepoBasedCartridgeSubscription extends CartridgeSubscriptio
 			RepositoryRequiredException,
 			RepositoryCredentialsRequiredException,
 			RepositoryTransportException, InvalidRepositoryException {
+
+        if(log.isDebugEnabled()) {
+            log.debug("Managing internal repo for repo URL: " + repoURL);
+        }
 		
 		Repository repository = null;
 		String defaultRepoUserName = System.getProperty(CartridgeConstants.INTERNAL_GIT_USERNAME);
 		String defaultRepoPassword = System.getProperty(CartridgeConstants.INTERNAL_GIT_PASSWORD);
-		String[] dirArray = null;
+		String[] dirArray = {"test"};
+
+        if (repoURL != null && !repoURL.equalsIgnoreCase("null") && !repoURL.isEmpty()) {
+            repository = new Repository();
+            repository.setUrl(repoURL);
+            repository.setUserName(defaultRepoUserName);
+            repository.setPassword(defaultRepoPassword);
+            return repository;
+        }
 		
 		// Repo URL will be generated inside createInternalRepository method
 		RepositoryInfoBean repoInfoBean = new RepositoryInfoBean(repoURL, getAlias(), getSubscriber().getTenantDomain(),

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 3bad5fd..84610e6 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
@@ -41,6 +41,8 @@ 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;
@@ -71,24 +73,26 @@ 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) throws ADCException, UnregisteredCartridgeException {    	
-    	if(!loadBalancerCategory.isLoadBalancedServiceMultiTenant()) {
-    		if(log.isDebugEnabled()) {
-    		 log.debug("Loadbalanced service is single tenant.");
-    		}
+    public CartridgeSubscriptionInfo registerSubscription(Properties properties) throws ADCException, UnregisteredCartridgeException {
+    	//if(!loadBalancerCategory.isLoadBalancedServiceMultiTenant()) {
+    		//if(log.isDebugEnabled()) {
+    		 //log.debug("Loadbalanced service is single tenant.");
+    		//}
     		getLoadBalancerCategory().register (getCartridgeInfo(), getCluster(), getPayloadData(), getAutoscalingPolicyName(),
     	                getDeploymentPolicyName(), properties);
-    	}
-       
+    	//}
+
 
         return ApplicationManagementUtil.createCartridgeSubscription(getCartridgeInfo(), getAutoscalingPolicyName(),
                 getType(), getAlias(), getSubscriber().getTenantId(), getSubscriber().getTenantDomain(),

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 e267c24..ed14d87 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
@@ -20,6 +20,10 @@ package org.apache.stratos.manager.subscription;
 
 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.
  */
@@ -42,6 +46,12 @@ public class SubscriptionData {
     private PersistenceContext persistanceCtxt;
     private boolean isCommitsEnabled;
     private String serviceGroup;
+    private Set<String> domains;
+    private String serviceName;
+    
+    public SubscriptionData() {
+        this.domains = new HashSet<String>();
+    }
 
     public String getCartridgeType() {
         return cartridgeType;
@@ -170,5 +180,29 @@ public class SubscriptionData {
 	public void setServiceGroup(String serviceGroup) {
 		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 String getServiceName() {
+		return serviceName;
+	}
+
+	public void setServiceName(String serviceName) {
+		this.serviceName = serviceName;
+	}
     
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionDomain.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionDomain.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionDomain.java
new file mode 100644
index 0000000..9fed0b0
--- /dev/null
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/SubscriptionDomain.java
@@ -0,0 +1,48 @@
+/*
+ * 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.subscription;
+
+import java.io.Serializable;
+
+/**
+ * Subscription domain definition.
+ */
+public class SubscriptionDomain implements Serializable{
+    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;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("[domain-name] %s [application-context] %s", getDomainName(), getApplicationContext());
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/factory/CartridgeSubscriptionFactory.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/factory/CartridgeSubscriptionFactory.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/factory/CartridgeSubscriptionFactory.java
index fbeb159..203ae87 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/factory/CartridgeSubscriptionFactory.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/subscription/factory/CartridgeSubscriptionFactory.java
@@ -49,8 +49,13 @@ public class CartridgeSubscriptionFactory {
         //TODO: fix the logic properly
         CartridgeSubscription cartridgeSubscription = null;
         if(cartridgeInfo.getMultiTenant()) {
-            cartridgeSubscription = new FrameworkCartridgeSubscription(cartridgeInfo, subscriptionTenancyBehaviour);
-
+            if (cartridgeInfo.getProvider().equals(CartridgeConstants.INTERNAL_REPO_BASED_CARTRIDGE_PROVIDER)) {
+                cartridgeSubscription = new InternalRepoBasedCartridgeSubscription(cartridgeInfo, subscriptionTenancyBehaviour);
+            } else if (cartridgeInfo.getProvider().equals("application")) {
+                cartridgeSubscription = new ApplicationCartridgeSubscription(cartridgeInfo, subscriptionTenancyBehaviour);
+            } else {
+                cartridgeSubscription = new FrameworkCartridgeSubscription(cartridgeInfo, subscriptionTenancyBehaviour);
+            }
         } else {
             // TODO: fix properly with cartridgeCategory element
             if(cartridgeInfo.getProvider().equals(CartridgeConstants.DATA_CARTRIDGE_PROVIDER)) {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 a5c5517..a12f1f7 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
@@ -44,6 +44,8 @@ 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.HashSet;
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.regex.Pattern;
 
@@ -57,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());
@@ -95,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()));
@@ -146,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() {
@@ -166,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) {
@@ -178,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() {
@@ -188,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) {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/topology/model/TopologyClusterInformationModel.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/topology/model/TopologyClusterInformationModel.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/topology/model/TopologyClusterInformationModel.java
index 928c3ce..2b73dff 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/topology/model/TopologyClusterInformationModel.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/topology/model/TopologyClusterInformationModel.java
@@ -41,6 +41,7 @@ public class TopologyClusterInformationModel {
     //private Map<Integer, Set<CartridgeTypeContext>> tenantIdToCartridgeTypeContextMap;
     private static TopologyClusterInformationModel topologyClusterInformationModel;
     private Map<String, Cluster> clusterIdToClusterMap;
+    private Map<String, Cluster> serviceNameToClusterMap;
     private DataInsertionAndRetrievalManager dataInsertionNRetrievalMgr;
     private boolean initialized;
 
@@ -51,6 +52,7 @@ public class TopologyClusterInformationModel {
     private TopologyClusterInformationModel() {
         //tenantIdToCartridgeTypeContextMap = new HashMap<Integer, Set<CartridgeTypeContext>>();
         clusterIdToClusterMap = new HashMap<String, Cluster>();
+        serviceNameToClusterMap = new HashMap<String, Cluster>();
         dataInsertionNRetrievalMgr = new DataInsertionAndRetrievalManager();
     }
 
@@ -73,6 +75,7 @@ public class TopologyClusterInformationModel {
     		log.debug(" Adding cluster ["+cluster.getClusterId()+"] ");
     	}
     	clusterIdToClusterMap.put(cluster.getClusterId(), cluster);
+    	serviceNameToClusterMap.put(cluster.getServiceName(), cluster);
     }   
 
     public Cluster getCluster (int tenantId, String cartridgeType, String subscriptionAlias) {
@@ -136,6 +139,22 @@ public class TopologyClusterInformationModel {
     	return clusterSet;
     }
    
+	public Set<Cluster> getClusters(String cartridgeType) {
+
+		Set<Cluster> clusterSet = new HashSet<Cluster>();
+
+		if (log.isDebugEnabled()) {
+			log.info("Finding cluster with service name [" + cartridgeType
+					+ "] ");
+		}
+		Cluster foundCluster = serviceNameToClusterMap.get(cartridgeType);
+		if (foundCluster != null) {
+			clusterSet.add(foundCluster);
+		}
+
+		return clusterSet;
+	}
+	
 //    public void removeCluster (int tenantId, String cartridgeType, String subscriptionAlias) {
 //
 //        Set<CartridgeTypeContext> cartridgeTypeContextSet = null;

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/RepositoryCreator.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/RepositoryCreator.java b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/RepositoryCreator.java
index b17b85f..c6406f1 100644
--- a/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/RepositoryCreator.java
+++ b/components/org.apache.stratos.manager/src/main/java/org/apache/stratos/manager/utils/RepositoryCreator.java
@@ -120,7 +120,7 @@ public class RepositoryCreator implements Runnable {
 			handleException(e.getMessage(), e);
 		}
 		
-		repository.setUrl(System.getProperty(CartridgeConstants.INTERNAL_GIT_URL)+repoName);
+		repository.setUrl(System.getProperty(CartridgeConstants.INTERNAL_GIT_URL) + "/git/" + repoName);
 		repository.setUserName(userName);
 		repository.setPassword(password);
 		
@@ -155,8 +155,9 @@ public class RepositoryCreator implements Runnable {
 
 		CloneCommand cloneCmd =
 		                        git.cloneRepository()
-		                           .setURI(System.getProperty(CartridgeConstants.INTERNAL_GIT_URL) + tenantDomain + "/" +
-		                                           cartridgeName + ".git")
+		                           .setURI(System.getProperty(CartridgeConstants.INTERNAL_GIT_URL) +
+                                                    "/git/" + tenantDomain + "/" +
+		                                            cartridgeName + ".git")
 		                           .setDirectory(new File(parentDirName));
 
 		cloneCmd.setCredentialsProvider(credentialsProvider);

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.messaging/pom.xml
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/pom.xml b/components/org.apache.stratos.messaging/pom.xml
index f145a1e..8545681 100644
--- a/components/org.apache.stratos.messaging/pom.xml
+++ b/components/org.apache.stratos.messaging/pom.xml
@@ -64,6 +64,11 @@
             <version>${wso2carbon.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.utils</artifactId>
+            <version>${wso2carbon.version}</version>
+        </dependency>
+        <dependency>
     		<groupId>com.jamesmurty.utils</groupId>
     		<artifactId>java-xmlbuilder</artifactId>
     		<version>0.6</version>

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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/7b35e29e/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/7b35e29e/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/7b35e29e/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/7b35e29e/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/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Member.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Member.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Member.java
index b942e2e..4a3bf17 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Member.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Member.java
@@ -24,10 +24,7 @@ import org.apache.stratos.messaging.util.bean.type.map.MapAdapter;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
+import java.util.*;
 
 /**
  * Defines a member node in a cluster.
@@ -42,13 +39,13 @@ public class Member implements Serializable {
     private final String networkPartitionId;
     private final String partitionId;
     private final String memberId;
-    
+    // Key: Port.proxy
+    @XmlJavaTypeAdapter(MapAdapter.class)
+    private final Map<Integer, Port> portMap;
     private String memberPublicIp;
     private MemberStatus status;
     private String memberIp;
     @XmlJavaTypeAdapter(MapAdapter.class)
-    private final Map<String, Port> portMap;
-    @XmlJavaTypeAdapter(MapAdapter.class)
     private Properties properties;
     private String lbClusterId;
 
@@ -58,7 +55,7 @@ public class Member 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() {
@@ -86,33 +83,32 @@ public class Member implements Serializable {
     }
 
     public Collection<Port> getPorts() {
-        return portMap.values();
+        return Collections.unmodifiableCollection(portMap.values());
+    }
+
+    public Port getPort(int proxy) {
+        if(portMap.containsKey(proxy)) {
+            return portMap.get(proxy);
+        }
+        return null;
     }
 
     public void addPort(Port port) {
-        this.portMap.put(port.getProtocol(), port);
+        this.portMap.put(port.getProxy(), port);
     }
 
     public void addPorts(Collection<Port> ports) {
-        for(Port port: ports) {
+        for(Port port : ports) {
             addPort(port);
         }
     }
 
     public void removePort(Port port) {
-        this.portMap.remove(port.getProtocol());
-    }
-
-    public void removePort(String protocol) {
-        this.portMap.remove(protocol);
+        this.portMap.remove(port.getProxy());
     }
 
     public boolean portExists(Port port) {
-        return this.portMap.containsKey(port.getProtocol());
-    }
-
-    public Port getPort(String protocol) {
-        return this.portMap.get(protocol);
+        return this.portMap.containsKey(port.getProxy());
     }
 
     public Properties getProperties() {
@@ -123,37 +119,37 @@ public class Member implements Serializable {
         this.properties = properties;
     }
 
-	public String getMemberIp() {
-	    return memberIp;
+    public String getMemberIp() {
+        return memberIp;
     }
 
-	public void setMemberIp(String memberIp) {
-	    this.memberIp = memberIp;
+    public void setMemberIp(String memberIp) {
+        this.memberIp = memberIp;
     }
 
     public String getPartitionId() {
         return partitionId;
     }
 
-    public void setLbClusterId(String lbClusterId) {
-        this.lbClusterId = lbClusterId;
-    }
-
     public String getLbClusterId() {
         return lbClusterId;
     }
 
+    public void setLbClusterId(String lbClusterId) {
+        this.lbClusterId = lbClusterId;
+    }
+
     public String getNetworkPartitionId() {
         return networkPartitionId;
     }
 
-	public String getMemberPublicIp() {
-		return memberPublicIp;
-	}
+    public String getMemberPublicIp() {
+        return memberPublicIp;
+    }
+
+    public void setMemberPublicIp(String memberPublicIp) {
+        this.memberPublicIp = memberPublicIp;
+    }
 
-	public void setMemberPublicIp(String memberPublicIp) {
-		this.memberPublicIp = memberPublicIp;
-	}
-    
 }
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Service.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Service.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Service.java
index 21cc5e7..46d46d4 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Service.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/domain/topology/Service.java
@@ -34,14 +34,15 @@ public class Service implements Serializable{
     private final ServiceType serviceType;
     // Key: Cluster.clusterId
     private Map<String, Cluster> clusterIdClusterMap;
-    private Map<String, Port> portMap;
+    // Key: Port.proxy
+    private Map<Integer, Port> portMap;
     private Properties properties;
 
     public Service(String serviceName, ServiceType serviceType) {
         this.serviceName = serviceName;
         this.serviceType = serviceType;
         this.clusterIdClusterMap = new HashMap<String, Cluster>();
-        this.portMap = new HashMap<String, Port>();
+        this.portMap = new HashMap<Integer, Port>();
     }
 
     public String getServiceName() {
@@ -77,33 +78,32 @@ public class Service implements Serializable{
     }
 
     public Collection<Port> getPorts() {
-        return portMap.values();
+        return Collections.unmodifiableCollection(portMap.values());
+    }
+
+    public Port getPort(int proxy) {
+        if(portMap.containsKey(proxy)) {
+            return portMap.get(proxy);
+        }
+        return null;
     }
 
     public void addPort(Port port) {
-        this.portMap.put(port.getProtocol(), port);
+        this.portMap.put(port.getProxy(), port);
     }
 
     public void addPorts(Collection<Port> ports) {
-        for(Port port: ports) {
+        for(Port port : ports) {
             addPort(port);
         }
     }
 
     public void removePort(Port port) {
-        this.portMap.remove(port.getProtocol());
-    }
-
-    public void removePort(String protocol) {
-        this.portMap.remove(protocol);
+        this.portMap.remove(port.getProxy());
     }
 
     public boolean portExists(Port port) {
-        return this.portMap.containsKey(port.getProtocol());
-    }
-
-    public Port getPort(String protocol) {
-        return this.portMap.get(protocol);
+        return this.portMap.containsKey(port.getProxy());
     }
 
     public Properties getProperties() {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/instance/notifier/ArtifactUpdatedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/instance/notifier/ArtifactUpdatedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/instance/notifier/ArtifactUpdatedEvent.java
index fe0240d..0f6aaef 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/instance/notifier/ArtifactUpdatedEvent.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/instance/notifier/ArtifactUpdatedEvent.java
@@ -33,6 +33,7 @@ public class ArtifactUpdatedEvent extends InstanceNotifierEvent implements Seria
     private String repoPassword;
     private String repoURL;
     private String tenantId;
+    private boolean commitEnabled;
 
     public String getClusterId() {
         return clusterId;
@@ -87,4 +88,12 @@ public class ArtifactUpdatedEvent extends InstanceNotifierEvent implements Seria
         return String.format("[cluster] %s [repo-url] %s [repo-username] %s [tenant] %s",
                 getClusterId(), getRepoURL(), getRepoUserName(), getTenantId());
     }
+
+    public boolean isCommitEnabled() {
+        return commitEnabled;
+    }
+
+    public void setCommitEnabled(boolean commitEnabled) {
+        this.commitEnabled = commitEnabled;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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/7b35e29e/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/7b35e29e/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/7b35e29e/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/7b35e29e/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/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantUnSubscribedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantUnSubscribedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantUnSubscribedEvent.java
index 2262cd4..5cfcfdf 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantUnSubscribedEvent.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/tenant/TenantUnSubscribedEvent.java
@@ -20,6 +20,8 @@
 package org.apache.stratos.messaging.event.tenant;
 
 import java.io.Serializable;
+import java.util.Collections;
+import java.util.Set;
 
 /**
  * This event is fired when a tenant is un-subscribed from a service.
@@ -29,10 +31,12 @@ public class TenantUnSubscribedEvent extends TenantEvent implements Serializable
 
     private final int tenantId;
     private final String serviceName;
+    private final Set<String> clusterIds;
 
-    public TenantUnSubscribedEvent(int tenantId, String serviceName) {
+    public TenantUnSubscribedEvent(int tenantId, String serviceName, Set<String> clusterIds) {
         this.tenantId = tenantId;
         this.serviceName = serviceName;
+        this.clusterIds = clusterIds;
     }
 
     public int getTenantId() {
@@ -42,4 +46,8 @@ public class TenantUnSubscribedEvent 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/7b35e29e/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/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/InstanceSpawnedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/InstanceSpawnedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/InstanceSpawnedEvent.java
index f42dda8..3e99a30 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/InstanceSpawnedEvent.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/InstanceSpawnedEvent.java
@@ -20,6 +20,7 @@ package org.apache.stratos.messaging.event.topology;
 
 
 import java.io.Serializable;
+import java.util.Properties;
 
 
 /**
@@ -36,6 +37,8 @@ public class InstanceSpawnedEvent extends TopologyEvent implements Serializable
     private String lbClusterId;
     private String memberPublicIp;
     private String memberIp;
+    private Properties properties;
+
 
     public InstanceSpawnedEvent(String serviceName, String clusterId, String networkPartitionId, String partitionId, String memberId) {
         this.serviceName = serviceName;
@@ -88,5 +91,12 @@ public class InstanceSpawnedEvent extends TopologyEvent implements Serializable
 	public void setMemberIp(String memberIp) {
 		this.memberIp = memberIp;
 	}
-    
+
+    public Properties getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Properties properties) {
+        this.properties = properties;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 3cda807..e505537 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
@@ -20,9 +20,7 @@
 package org.apache.stratos.messaging.event.topology;
 
 import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
 import org.apache.stratos.messaging.domain.topology.Port;
 
@@ -38,7 +36,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;
+    // Key: Port.proxy
+    private Map<Integer, Port> portMap;
     private String memberIp;
 
     public MemberActivatedEvent(String serviceName, String clusterId, String networkPartitionId, String partitionId, String memberId) {
@@ -47,7 +46,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() {
@@ -69,32 +68,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;
     }
 

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 986b309..21aa340 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.
@@ -33,6 +34,8 @@ public class
     private final String networkPartitionId;
     private final String partitionId;
     private final String memberId;
+    private Properties properties;
+
 
     public MemberTerminatedEvent(String serviceName, String clusterId, String networkPartitionId, String partitionId, String memberId) {
         this.serviceName = serviceName;
@@ -61,4 +64,12 @@ public class
     public String getNetworkPartitionId() {
         return networkPartitionId;
     }
+
+    public Properties getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Properties properties) {
+        this.properties = properties;
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ServiceCreatedEvent.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ServiceCreatedEvent.java b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ServiceCreatedEvent.java
index 846091e..8ed701a 100644
--- a/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ServiceCreatedEvent.java
+++ b/components/org.apache.stratos.messaging/src/main/java/org/apache/stratos/messaging/event/topology/ServiceCreatedEvent.java
@@ -23,10 +23,7 @@ import org.apache.stratos.messaging.domain.topology.Port;
 import org.apache.stratos.messaging.domain.topology.ServiceType;
 
 import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
+import java.util.*;
 
 /**
  * This event is fired by Cloud Controller when a service is added to a topology.
@@ -37,13 +34,14 @@ public class ServiceCreatedEvent extends TopologyEvent implements Serializable {
 
     private final String serviceName;
     private final ServiceType serviceType;
-    private final Map<String, Port> portMap;
+    // Key: Port.proxy
+    private final Map<Integer, Port> portMap;
     private Properties properties;
 
     public ServiceCreatedEvent(String serviceName, ServiceType serviceType) {
         this.serviceName = serviceName;
         this.serviceType = serviceType;
-        this.portMap = new HashMap<String, Port>();
+        this.portMap = new HashMap<Integer, Port>();
     }
 
     public String getServiceName() {
@@ -55,27 +53,32 @@ public class ServiceCreatedEvent extends TopologyEvent implements Serializable {
     }
 
     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 Properties getProperties() {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/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 {
+}


[06/14] Clustering changes for stratos

Posted by ma...@apache.org.
http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/publisher/CartridgeInstanceDataPublisher.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/publisher/CartridgeInstanceDataPublisher.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/publisher/CartridgeInstanceDataPublisher.java
index d56e7fb..69c9863 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/publisher/CartridgeInstanceDataPublisher.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/publisher/CartridgeInstanceDataPublisher.java
@@ -23,7 +23,7 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cloud.controller.exception.CloudControllerException;
 import org.apache.stratos.cloud.controller.exception.UnregisteredCartridgeException;
 import org.apache.stratos.cloud.controller.impl.CloudControllerServiceImpl;
-import org.apache.stratos.cloud.controller.pojo.CartridgeInfo;
+import org.apache.stratos.cloud.controller.pojo.Cartridge;
 import org.apache.stratos.cloud.controller.pojo.MemberContext;
 import org.apache.stratos.cloud.controller.runtime.FasterLookUpDataHolder;
 import org.apache.stratos.cloud.controller.util.CloudControllerConstants;
@@ -75,73 +75,68 @@ public class CartridgeInstanceDataPublisher {
                 return;
             }
         }
-        CartridgeInfo cartridgeInfo = null;
+        Cartridge cartridge = null;
+        cartridge = FasterLookUpDataHolder.getInstance().getCartridge(serviceName);
+
+        MemberContext memberContext = FasterLookUpDataHolder.getInstance().getMemberContextOfMemberId(memberId);
+        //Construct the data to be published
+        List<Object> payload = new ArrayList<Object>();
+        // Payload values
+        payload.add(memberId);
+        payload.add(serviceName);
+        payload.add(clusterId);
+        payload.add(memberContext.getLbClusterId());
+        payload.add(partitionId);
+        payload.add(networkId);
+        if(cartridge != null) {
+            payload.add(String.valueOf(cartridge.isMultiTenant()));
+        } else {
+            payload.add("");
+        }
+        payload.add(memberContext.getPartition().getProvider());
+        payload.add(status);
+
+        if(metadata != null) {
+            payload.add(metadata.getHostname());
+            payload.add(metadata.getHardware().getHypervisor());
+            payload.add(String.valueOf(metadata.getHardware().getRam()));
+            payload.add(metadata.getImageId());
+            payload.add(metadata.getLoginPort());
+            payload.add(metadata.getOperatingSystem().getName());
+            payload.add(metadata.getOperatingSystem().getVersion());
+            payload.add(metadata.getOperatingSystem().getArch());
+            payload.add(String.valueOf(metadata.getOperatingSystem().is64Bit()));
+        } else {
+            payload.add("");
+            payload.add("");
+            payload.add("");
+            payload.add("");
+            payload.add(0);
+            payload.add("");
+            payload.add("");
+            payload.add("");
+            payload.add("");
+        }
+
+        payload.add(memberContext.getPrivateIpAddress());
+        payload.add(memberContext.getPublicIpAddress());
+        payload.add(memberContext.getAllocatedIpAddress());
+
+        Event event = new Event();
+        event.setPayloadData(payload.toArray());
+        event.setArbitraryDataMap(new HashMap<String, String>());
+
         try {
-            cartridgeInfo = new CloudControllerServiceImpl().getCartridgeInfo(serviceName);
-        } catch (UnregisteredCartridgeException e) {
-            log.error("error while getting the cartridge information when publishing the state changes... ");
-        } finally {
-            MemberContext memberContext = FasterLookUpDataHolder.getInstance().getMemberContextOfMemberId(memberId);
-            //Construct the data to be published
-            List<Object> payload = new ArrayList<Object>();
-            // Payload values
-            payload.add(memberId);
-            payload.add(serviceName);
-            payload.add(clusterId);
-            payload.add(memberContext.getLbClusterId());
-            payload.add(partitionId);
-            payload.add(networkId);
-            if(cartridgeInfo != null) {
-                payload.add(String.valueOf(cartridgeInfo.isMultiTenant()));
-            } else {
-                payload.add("");
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Publishing BAM event: [stream] %s [version] %s", streamDefinition.getName(), streamDefinition.getVersion()));
             }
-            payload.add(memberContext.getPartition().getProvider());
-            payload.add(status);
-
-            if(metadata != null) {
-                payload.add(metadata.getHostname());
-                payload.add(metadata.getHardware().getHypervisor());
-                payload.add(String.valueOf(metadata.getHardware().getRam()));
-                payload.add(metadata.getImageId());
-                payload.add(metadata.getLoginPort());
-                payload.add(metadata.getOperatingSystem().getName());
-                payload.add(metadata.getOperatingSystem().getVersion());
-                payload.add(metadata.getOperatingSystem().getArch());
-                payload.add(String.valueOf(metadata.getOperatingSystem().is64Bit()));
-            } else {
-                payload.add("");
-                payload.add("");
-                payload.add("");
-                payload.add("");
-                payload.add(0);
-                payload.add("");
-                payload.add("");
-                payload.add("");
-                payload.add("");
+            dataPublisher.publish(streamDefinition.getName(), streamDefinition.getVersion(), event);
+        } catch (AgentException e) {
+            if (log.isErrorEnabled()) {
+                log.error(String.format("Could not publish BAM event: [stream] %s [version] %s", streamDefinition.getName(), streamDefinition.getVersion()), e);
             }
-
-            payload.add(memberContext.getPrivateIpAddress());
-            payload.add(memberContext.getPublicIpAddress());
-            payload.add(memberContext.getAllocatedIpAddress());
-
-            Event event = new Event();
-            event.setPayloadData(payload.toArray());
-            event.setArbitraryDataMap(new HashMap<String, String>());
-
-            try {
-                if (log.isDebugEnabled()) {
-                    log.debug(String.format("Publishing BAM event: [stream] %s [version] %s", streamDefinition.getName(), streamDefinition.getVersion()));
-                }
-                dataPublisher.publish(streamDefinition.getName(), streamDefinition.getVersion(), event);
-            } catch (AgentException e) {
-                if (log.isErrorEnabled()) {
-                    log.error(String.format("Could not publish BAM event: [stream] %s [version] %s", streamDefinition.getName(), streamDefinition.getVersion()), e);
-                }
-            }
-
+        }
     }
-}
     
     private static void release(){
         FasterLookUpDataHolder.getInstance().setPublisherRunning(false);

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyBuilder.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyBuilder.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyBuilder.java
index 9c3ea70..39e403c 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyBuilder.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyBuilder.java
@@ -22,11 +22,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cloud.controller.exception.InvalidCartridgeTypeException;
 import org.apache.stratos.cloud.controller.exception.InvalidMemberException;
-import org.apache.stratos.cloud.controller.impl.CloudControllerServiceImpl;
-import org.apache.stratos.cloud.controller.pojo.Cartridge;
-import org.apache.stratos.cloud.controller.pojo.ClusterContext;
-import org.apache.stratos.cloud.controller.pojo.PortMapping;
-import org.apache.stratos.cloud.controller.pojo.Registrant;
+import org.apache.stratos.cloud.controller.pojo.*;
 import org.apache.stratos.cloud.controller.publisher.CartridgeInstanceDataPublisher;
 import org.apache.stratos.cloud.controller.runtime.FasterLookUpDataHolder;
 import org.apache.stratos.cloud.controller.util.CloudControllerUtil;
@@ -38,8 +34,10 @@ import org.apache.stratos.messaging.event.instance.status.InstanceStartedEvent;
 import org.apache.stratos.messaging.event.topology.MemberActivatedEvent;
 import org.apache.stratos.messaging.event.topology.MemberMaintenanceModeEvent;
 import org.apache.stratos.messaging.event.topology.MemberReadyToShutdownEvent;
+import org.apache.stratos.messaging.util.Constants;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 
 /**
@@ -63,7 +61,12 @@ public class TopologyBuilder {
             for (Cartridge cartridge : cartridgeList) {
                 if (!topology.serviceExists(cartridge.getType())) {
                     service = new Service(cartridge.getType(), cartridge.isMultiTenant() ? ServiceType.MultiTenant : ServiceType.SingleTenant);
-                     List<PortMapping> portMappings = cartridge.getPortMappings();
+                    List<PortMapping> portMappings = cartridge.getPortMappings();
+                    Properties properties = new Properties();
+                    for (Map.Entry<String, String> entry : cartridge.getProperties().entrySet()) {
+                        properties.setProperty(entry.getKey(), entry.getValue());
+                    }
+                    service.setProperties(properties);
                     Port port;
                     //adding ports to the event
                     for (PortMapping portMapping : portMappings) {
@@ -125,6 +128,9 @@ public class TopologyBuilder {
                 if(service.getServiceType() == ServiceType.MultiTenant) {
                     cluster.setTenantRange(registrant.getTenantRange());
                 }
+                if(service.getProperties().getProperty(Constants.IS_PRIMARY) != null) {
+                    props.setProperty(Constants.IS_PRIMARY, service.getProperties().getProperty(Constants.IS_PRIMARY));
+                }
                 cluster.setProperties(props);
                 cluster.setLbCluster(isLb);
             } else {
@@ -134,8 +140,12 @@ public class TopologyBuilder {
                 if(service.getServiceType() == ServiceType.MultiTenant) {
                     cluster.setTenantRange(registrant.getTenantRange());
                 }
+                if(service.getProperties().getProperty(Constants.IS_PRIMARY) != null) {
+                    props.setProperty(Constants.IS_PRIMARY, service.getProperties().getProperty(Constants.IS_PRIMARY));
+                }
                 cluster.setProperties(props);
                 cluster.setLbCluster(isLb);
+                cluster.setStatus(ClusterStatus.Created);
                 service.addCluster(cluster);
             }
             TopologyManager.updateTopology(topology);
@@ -174,33 +184,72 @@ public class TopologyBuilder {
         TopologyEventPublisher.sendClusterRemovedEvent(ctxt, deploymentPolicy);
     }
 
-    public static void handleMemberSpawned(String memberId, String serviceName, String clusterId,
-                                           String networkPartitionId, String partitionId, String privateIp, String lbClusterId, String publicIp) {
-        //adding the new member to the cluster after it is successfully started in IaaS.
+    public static void handleClusterMaintenanceMode(ClusterContext ctxt) {
+
         Topology topology = TopologyManager.getTopology();
-        Service service = topology.getService(serviceName);
-        Cluster cluster = service.getCluster(clusterId);
+        Service service = topology.getService(ctxt.getCartridgeType());
+        if (service == null) {
+            log.warn(String.format("Service %s does not exist",
+                    ctxt.getCartridgeType()));
+            return;
+        }
 
-        if (cluster.memberExists(memberId)) {
-        	log.warn(String.format("Member %s already exists", memberId));
-        	return;
+        if (!service.clusterExists(ctxt.getClusterId())) {
+            log.warn(String.format("Cluster %s does not exist for service %s",
+                    ctxt.getClusterId(),
+                    ctxt.getCartridgeType()));
+            return;
         }
 
         try {
             TopologyManager.acquireWriteLock();
-            Member member = new Member(serviceName, clusterId, networkPartitionId, partitionId, memberId);
-            member.setStatus(MemberStatus.Created);
-            member.setMemberIp(privateIp);
-            member.setLbClusterId(lbClusterId);
-            member.setMemberPublicIp(publicIp);
-            cluster.addMember(member);
+            Cluster cluster = service.getCluster(ctxt.getClusterId());
+            cluster.setStatus(ClusterStatus.In_Maintenance);
             TopologyManager.updateTopology(topology);
         } finally {
             TopologyManager.releaseWriteLock();
         }
-        TopologyEventPublisher.sendInstanceSpawnedEvent(serviceName, clusterId, networkPartitionId, partitionId, memberId, lbClusterId, publicIp, privateIp);
+        TopologyEventPublisher.sendClusterMaintenanceModeEvent(ctxt);
     }
 
+
+	public static void handleMemberSpawned(String serviceName,
+			String clusterId, String partitionId,
+			String privateIp, String publicIp, MemberContext context) {
+		// adding the new member to the cluster after it is successfully started
+		// in IaaS.
+		Topology topology = TopologyManager.getTopology();
+		Service service = topology.getService(serviceName);
+		Cluster cluster = service.getCluster(clusterId);
+		String memberId = context.getMemberId();
+		String networkPartitionId = context.getNetworkPartitionId();
+		String lbClusterId = context.getLbClusterId();
+
+		if (cluster.memberExists(memberId)) {
+			log.warn(String.format("Member %s already exists", memberId));
+			return;
+		}
+
+		try {
+			TopologyManager.acquireWriteLock();
+			Member member = new Member(serviceName, clusterId,
+					networkPartitionId, partitionId, memberId);
+			member.setStatus(MemberStatus.Created);
+			member.setMemberIp(privateIp);
+			member.setLbClusterId(lbClusterId);
+			member.setMemberPublicIp(publicIp);
+			member.setProperties(CloudControllerUtil.toJavaUtilProperties(context.getProperties()));
+			cluster.addMember(member);
+			TopologyManager.updateTopology(topology);
+		} finally {
+			TopologyManager.releaseWriteLock();
+		}
+		
+		TopologyEventPublisher.sendInstanceSpawnedEvent(serviceName, clusterId,
+				networkPartitionId, partitionId, memberId, lbClusterId,
+				publicIp, privateIp, context);
+	}
+    
     public static void handleMemberStarted(InstanceStartedEvent instanceStartedEvent) {
         Topology topology = TopologyManager.getTopology();
         Service service = topology.getService(instanceStartedEvent.getServiceName());
@@ -353,9 +402,6 @@ public class TopologyBuilder {
                                             instanceReadyToShutdownEvent.getServiceName(),
                                             MemberStatus.ReadyToShutDown.toString(),
                                             null);
-        //calling the actual termination of the instance
-        new CloudControllerServiceImpl().terminateInstance(memberId);
-
     }
 
      public static void handleMemberMaintenance(InstanceMaintenanceModeEvent instanceMaintenanceModeEvent)
@@ -405,6 +451,7 @@ public class TopologyBuilder {
     public static void handleMemberTerminated(String serviceName, String clusterId, String networkPartitionId, String partitionId, String memberId) {
         Topology topology = TopologyManager.getTopology();
         Service service = topology.getService(serviceName);
+        Properties properties;
         if (service == null) {
             log.warn(String.format("Service %s does not exist",
                                                      serviceName));
@@ -427,12 +474,13 @@ public class TopologyBuilder {
 
         try {
             TopologyManager.acquireWriteLock();
+            properties = member.getProperties();
             cluster.removeMember(member);
             TopologyManager.updateTopology(topology);
         } finally {
             TopologyManager.releaseWriteLock();
         }
-        TopologyEventPublisher.sendMemberTerminatedEvent(serviceName, clusterId, networkPartitionId, partitionId, memberId);
+        TopologyEventPublisher.sendMemberTerminatedEvent(serviceName, clusterId, networkPartitionId, partitionId, memberId, properties);
     }
 
     public static void handleMemberSuspended() {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyEventPublisher.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyEventPublisher.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyEventPublisher.java
index 86237d8..fe86198 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyEventPublisher.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/topology/TopologyEventPublisher.java
@@ -21,19 +21,19 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.stratos.cloud.controller.pojo.Cartridge;
 import org.apache.stratos.cloud.controller.pojo.ClusterContext;
+import org.apache.stratos.cloud.controller.pojo.MemberContext;
 import org.apache.stratos.cloud.controller.pojo.PortMapping;
+import org.apache.stratos.cloud.controller.util.CloudControllerUtil;
 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.Port;
-import org.apache.stratos.messaging.domain.topology.ServiceType;
-import org.apache.stratos.messaging.domain.topology.Topology;
+import org.apache.stratos.messaging.domain.topology.*;
 import org.apache.stratos.messaging.event.Event;
 import org.apache.stratos.messaging.event.instance.status.InstanceStartedEvent;
 import org.apache.stratos.messaging.event.topology.*;
 import org.apache.stratos.messaging.util.Constants;
 
 import java.util.List;
+import java.util.Properties;
 
 /**
  * this is to send the relevant events from cloud controller to topology topic
@@ -96,12 +96,25 @@ public class TopologyEventPublisher {
 
     }
 
+    public static void sendClusterMaintenanceModeEvent(ClusterContext ctxt) {
+
+        ClusterMaintenanceModeEvent clusterMaintenanceModeEvent = new ClusterMaintenanceModeEvent(ctxt.getCartridgeType(), ctxt.getClusterId());
+        clusterMaintenanceModeEvent.setStatus(ClusterStatus.In_Maintenance);
+        if(log.isInfoEnabled()) {
+            log.info(String.format("Publishing cluster maintenance mode event: [service] %s [cluster] %s",
+                    clusterMaintenanceModeEvent.getServiceName(), clusterMaintenanceModeEvent.getClusterId()));
+        }
+        publishEvent(clusterMaintenanceModeEvent);
+
+    }
+
     public static void sendInstanceSpawnedEvent(String serviceName, String clusterId, String networkPartitionId, String partitionId, String memberId,
-    		String lbClusterId, String publicIp, String privateIp) {
+    		String lbClusterId, String publicIp, String privateIp, MemberContext context) {
         InstanceSpawnedEvent instanceSpawnedEvent = new InstanceSpawnedEvent(serviceName, clusterId, networkPartitionId, partitionId, memberId);
         instanceSpawnedEvent.setLbClusterId(lbClusterId);
         instanceSpawnedEvent.setMemberIp(privateIp);
         instanceSpawnedEvent.setMemberPublicIp(publicIp);
+        instanceSpawnedEvent.setProperties(CloudControllerUtil.toJavaUtilProperties(context.getProperties()));
         if(log.isInfoEnabled()) {
             log.info(String.format("Publishing instance spawned event: [service] %s [cluster] %s [network-partition] %s [partition] %s [member] %s [lb-cluster-id] %s",
                     serviceName, clusterId, networkPartitionId, partitionId, memberId, lbClusterId));
@@ -145,8 +158,10 @@ public class TopologyEventPublisher {
        }
 
 
-    public static void sendMemberTerminatedEvent(String serviceName, String clusterId, String networkPartitionId, String partitionId, String memberId) {
+    public static void sendMemberTerminatedEvent(String serviceName, String clusterId, String networkPartitionId,
+                                                 String partitionId, String memberId, Properties properties) {
         MemberTerminatedEvent memberTerminatedEvent = new MemberTerminatedEvent(serviceName, clusterId, networkPartitionId, partitionId, memberId);
+        memberTerminatedEvent.setProperties(properties);
         if(log.isInfoEnabled()) {
             log.info(String.format("Publishing member terminated event: [service] %s [cluster] %s [network-partition] %s [partition] %s [member] %s", serviceName, clusterId, networkPartitionId, partitionId, memberId));
         }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerUtil.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerUtil.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerUtil.java
index a213adf..3a423e0 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerUtil.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/util/CloudControllerUtil.java
@@ -185,6 +185,7 @@ public class CloudControllerUtil {
 		carInfo.setAppTypes(cartridge.getAppTypeMappings()
                                 .toArray(new AppType[cartridge.getAppTypeMappings()
                                                                   .size()]));
+        carInfo.setServiceGroup(cartridge.getServiceGroup());
 		
 		List<Property> propList = new ArrayList<Property>();
         carInfo.setPersistence(cartridge.getPersistence());

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/AWSEC2PartitionValidator.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/AWSEC2PartitionValidator.java b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/AWSEC2PartitionValidator.java
index 0a251a6..28d92cf 100644
--- a/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/AWSEC2PartitionValidator.java
+++ b/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/validate/AWSEC2PartitionValidator.java
@@ -20,6 +20,7 @@ package org.apache.stratos.cloud.controller.validate;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.stratos.cloud.controller.exception.InvalidIaasProviderException;
 import org.apache.stratos.cloud.controller.exception.InvalidPartitionException;
 import org.apache.stratos.cloud.controller.interfaces.Iaas;
 import org.apache.stratos.cloud.controller.pojo.IaasProvider;
@@ -73,6 +74,8 @@ public class AWSEC2PartitionValidator implements PartitionValidator {
                     updatedIaas.setIaasProvider(updatedIaasProvider);
                 } 
                 
+                updateOtherProperties(updatedIaasProvider, properties);
+                
                 return updatedIaasProvider;
                 
             } else {
@@ -87,7 +90,32 @@ public class AWSEC2PartitionValidator implements PartitionValidator {
         
     }
 
-    @Override
+    private void updateOtherProperties(IaasProvider updatedIaasProvider,
+			Properties properties) {
+    	Iaas updatedIaas;
+		try {
+			updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider);
+
+			for (Object property : properties.keySet()) {
+				if (property instanceof String) {
+					String key = (String) property;
+					if (!Scope.zone.toString().equals(key)) {
+						updatedIaasProvider.setProperty(key,
+								properties.getProperty(key));
+						if (log.isDebugEnabled()) {
+							log.debug("Added property "+key+ " to the IaasProvider.");
+						}
+					}
+				}
+			}
+			updatedIaas = CloudControllerUtil.getIaas(updatedIaasProvider);
+			updatedIaas.setIaasProvider(updatedIaasProvider);
+		} catch (InvalidIaasProviderException ignore) {
+		}
+    	
+	}
+
+	@Override
     public void setIaasProvider(IaasProvider iaas) {
         this.iaasProvider = iaas;
         this.iaas = iaas.getIaas();

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.common/src/main/java/org/apache/stratos/common/util/CommandUtils.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.common/src/main/java/org/apache/stratos/common/util/CommandUtils.java b/components/org.apache.stratos.common/src/main/java/org/apache/stratos/common/util/CommandUtils.java
index 0eaf369..d581057 100644
--- a/components/org.apache.stratos.common/src/main/java/org/apache/stratos/common/util/CommandUtils.java
+++ b/components/org.apache.stratos.common/src/main/java/org/apache/stratos/common/util/CommandUtils.java
@@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.util.Map;
 
 /**
  * A utility class for executing shell commands.
@@ -63,4 +64,33 @@ public class CommandUtils {
 
         return output.toString();
     }
+
+    public static String executeCommand(String command, Map<String, String> envParameters) throws IOException {
+        String line;
+        ProcessBuilder pb = new ProcessBuilder(command);
+        Map<String, String> env = pb.environment();
+        env.putAll(envParameters);
+
+        Process p = pb.start();
+        StringBuilder output = new StringBuilder();
+        BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
+        while ((line = in.readLine()) != null) {
+            if (log.isDebugEnabled()) {
+                log.debug("output = " + line);
+            }
+            output.append(line).append(NEW_LINE);
+        }
+        StringBuilder errors = new StringBuilder();
+        BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+        while ((line = error.readLine()) != null) {
+            if (log.isDebugEnabled()) {
+                log.debug("error = " + line);
+            }
+            errors.append(line).append(NEW_LINE);
+        }
+        if (errors.length() > 0) {
+            throw new RuntimeException("Command execution failed: " + NEW_LINE + errors.toString());
+        }
+        return output.toString();
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTenantEventReceiver.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTenantEventReceiver.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTenantEventReceiver.java
index ad1907a..027ace0 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTenantEventReceiver.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTenantEventReceiver.java
@@ -21,18 +21,16 @@ package org.apache.stratos.load.balancer;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.stratos.load.balancer.context.LoadBalancerContext;
+import org.apache.stratos.load.balancer.context.LoadBalancerContextUtil;
+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.domain.topology.Cluster;
 import org.apache.stratos.messaging.domain.topology.Service;
 import org.apache.stratos.messaging.domain.topology.ServiceType;
 import org.apache.stratos.messaging.event.Event;
-import org.apache.stratos.messaging.event.tenant.CompleteTenantEvent;
-import org.apache.stratos.messaging.event.tenant.TenantSubscribedEvent;
-import org.apache.stratos.messaging.event.tenant.TenantUnSubscribedEvent;
-import org.apache.stratos.messaging.listener.tenant.CompleteTenantEventListener;
-import org.apache.stratos.messaging.listener.tenant.TenantSubscribedEventListener;
-import org.apache.stratos.messaging.listener.tenant.TenantUnSubscribedEventListener;
+import org.apache.stratos.messaging.event.tenant.*;
+import org.apache.stratos.messaging.listener.tenant.*;
 import org.apache.stratos.messaging.message.receiver.tenant.TenantEventReceiver;
 import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 
@@ -57,15 +55,36 @@ public class LoadBalancerTenantEventReceiver implements Runnable {
 
     private void addEventListeners() {
         tenantEventReceiver.addEventListener(new CompleteTenantEventListener() {
+            private boolean initialized;
+
             @Override
             protected void onEvent(Event event) {
-                CompleteTenantEvent completeTenantEvent = (CompleteTenantEvent) event;
-                for (Tenant tenant : completeTenantEvent.getTenants()) {
-                    for (String serviceName : tenant.getServiceSubscriptions()) {
-                        if(isMultiTenantService(serviceName)) {
-                            addTenantSubscriptionToLbContext(serviceName, tenant.getTenantId());
+                if (!initialized) {
+                    CompleteTenantEvent completeTenantEvent = (CompleteTenantEvent) event;
+                    if (log.isDebugEnabled()) {
+                        log.debug("Complete tenant event received");
+                    }
+                    for (Tenant tenant : completeTenantEvent.getTenants()) {
+                        for (Subscription subscription : tenant.getSubscriptions()) {
+                            if (isMultiTenantService(subscription.getServiceName())) {
+                                LoadBalancerContextUtil.addClustersAgainstHostNamesAndTenantIds(
+                                        subscription.getServiceName(),
+                                        tenant.getTenantId(),
+                                        subscription.getClusterIds());
+                            }
+
+                            for (SubscriptionDomain subscriptionDomain : subscription.getSubscriptionDomains()) {
+                                LoadBalancerContextUtil.addClustersAgainstDomain(
+                                        subscription.getServiceName(),
+                                        subscription.getClusterIds(),
+                                        subscriptionDomain.getDomainName());
+
+                                LoadBalancerContextUtil.addAppContextAgainstDomain(subscriptionDomain.getDomainName(),
+                                        subscriptionDomain.getApplicationContext());
+                            }
                         }
                     }
+                    initialized = true;
                 }
             }
         });
@@ -73,12 +92,18 @@ public class LoadBalancerTenantEventReceiver implements Runnable {
             @Override
             protected void onEvent(Event event) {
                 TenantSubscribedEvent tenantSubscribedEvent = (TenantSubscribedEvent) event;
-                if(log.isDebugEnabled()) {
-                    log.debug(String.format("Tenant subscribed event received: [tenant-id] %d [service] %s",
-                            tenantSubscribedEvent.getTenantId(), tenantSubscribedEvent.getServiceName()));
+                if (log.isDebugEnabled()) {
+                    log.debug(String.format("Tenant subscribed event received: [tenant-id] %d [service] %s [cluster-ids] %s",
+                            tenantSubscribedEvent.getTenantId(),
+                            tenantSubscribedEvent.getServiceName(),
+                            tenantSubscribedEvent.getClusterIds()));
                 }
-                if(isMultiTenantService(tenantSubscribedEvent.getServiceName())) {
-                    addTenantSubscriptionToLbContext(tenantSubscribedEvent.getServiceName(), tenantSubscribedEvent.getTenantId());
+
+                if (isMultiTenantService(tenantSubscribedEvent.getServiceName())) {
+                    LoadBalancerContextUtil.addClustersAgainstHostNamesAndTenantIds(
+                            tenantSubscribedEvent.getServiceName(),
+                            tenantSubscribedEvent.getTenantId(),
+                            tenantSubscribedEvent.getClusterIds());
                 }
             }
         });
@@ -86,90 +111,86 @@ public class LoadBalancerTenantEventReceiver implements Runnable {
             @Override
             protected void onEvent(Event event) {
                 TenantUnSubscribedEvent tenantUnSubscribedEvent = (TenantUnSubscribedEvent) event;
-                if(log.isDebugEnabled()) {
-                    log.debug(String.format("Tenant un-subscribed event received: [tenant-id] %d [service] %s",
-                            tenantUnSubscribedEvent.getTenantId(), tenantUnSubscribedEvent.getServiceName()));
+                if (log.isDebugEnabled()) {
+                    log.debug(String.format("Tenant un-subscribed event received: [tenant-id] %d [service] %s [cluster-ids] %s",
+                            tenantUnSubscribedEvent.getTenantId(),
+                            tenantUnSubscribedEvent.getServiceName(),
+                            tenantUnSubscribedEvent.getClusterIds()));
                 }
-                if(isMultiTenantService(tenantUnSubscribedEvent.getServiceName())) {
-                    removeTenantSubscriptionFromLbContext(tenantUnSubscribedEvent.getServiceName(), tenantUnSubscribedEvent.getTenantId());
+
+                if (isMultiTenantService(tenantUnSubscribedEvent.getServiceName())) {
+                    LoadBalancerContextUtil.removeClustersAgainstHostNamesAndTenantIds(
+                            tenantUnSubscribedEvent.getServiceName(),
+                            tenantUnSubscribedEvent.getTenantId(),
+                            tenantUnSubscribedEvent.getClusterIds()
+                    );
                 }
-            }
-        });
-    }
 
-    private boolean isMultiTenantService(String serviceName) {
-        try {
-            TopologyManager.acquireReadLock();
-            Service service = TopologyManager.getTopology().getService(serviceName);
-            if(service != null) {
-                return (service.getServiceType() == ServiceType.MultiTenant);
-            }
-            return false;
-        }
-        finally {
-            TopologyManager.releaseReadLock();
-        }
-    }
+                LoadBalancerContextUtil.removeClustersAgainstAllDomains(
+                        tenantUnSubscribedEvent.getServiceName(),
+                        tenantUnSubscribedEvent.getTenantId(),
+                        tenantUnSubscribedEvent.getClusterIds());
 
-    private void addTenantSubscriptionToLbContext(String serviceName, int tenantId) {
-        // Find cluster of tenant
-        Cluster cluster = findCluster(serviceName, tenantId);
-        if (cluster != null) {
-            for (String hostName : cluster.getHostNames()) {
-                // Add hostName, tenantId, cluster to multi-tenant map
-                Map<Integer, Cluster> clusterMap = LoadBalancerContext.getInstance().getMultiTenantClusterMap().getClusters(hostName);
-                if (clusterMap == null) {
-                    clusterMap = new HashMap<Integer, Cluster>();
-                    clusterMap.put(tenantId, cluster);
-                    LoadBalancerContext.getInstance().getMultiTenantClusterMap().addClusters(hostName, clusterMap);
-                } else {
-                    clusterMap.put(tenantId, cluster);
-                }
+                LoadBalancerContextUtil.removeAppContextAgainstAllDomains(
+                        tenantUnSubscribedEvent.getServiceName(),
+                        tenantUnSubscribedEvent.getTenantId());
+            }
+        });
+        tenantEventReceiver.addEventListener(new SubscriptionDomainsAddedEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                SubscriptionDomainAddedEvent subscriptionDomainAddedEvent = (SubscriptionDomainAddedEvent) event;
                 if (log.isDebugEnabled()) {
-                    log.debug(String.format("Cluster added to multi-tenant cluster map: [host-name] %s [tenant-id] %d [cluster] %s",
-                            hostName, tenantId, cluster.getClusterId()));
+                    log.debug(String.format("Tenant subscription domain added event received: [tenant-id] %d " +
+                            "[service] %s [cluster-ids] %s [domain-name] %s",
+                            subscriptionDomainAddedEvent.getTenantId(),
+                            subscriptionDomainAddedEvent.getServiceName(),
+                            subscriptionDomainAddedEvent.getClusterIds(),
+                            subscriptionDomainAddedEvent.getDomainName()));
                 }
-            }
-        } else {
-            if (log.isErrorEnabled()) {
-                log.error(String.format("Could not find cluster of tenant: [service] %s [tenant-id] %d",
-                        serviceName, tenantId));
-            }
-        }
-    }
 
-    private void removeTenantSubscriptionFromLbContext(String serviceName, int tenantId) {
-        // Find cluster of tenant
-        Cluster cluster = findCluster(serviceName, tenantId);
-        if (cluster != null) {
-            for (String hostName : cluster.getHostNames()) {
-                LoadBalancerContext.getInstance().getMultiTenantClusterMap().removeClusters(hostName);
+                LoadBalancerContextUtil.addClustersAgainstDomain(
+                        subscriptionDomainAddedEvent.getServiceName(),
+                        subscriptionDomainAddedEvent.getClusterIds(),
+                        subscriptionDomainAddedEvent.getDomainName());
+
+                LoadBalancerContextUtil.addAppContextAgainstDomain(
+                        subscriptionDomainAddedEvent.getDomainName(),
+                        subscriptionDomainAddedEvent.getApplicationContext());
+            }
+        });
+        tenantEventReceiver.addEventListener(new SubscriptionDomainsRemovedEventListener() {
+            @Override
+            protected void onEvent(Event event) {
+                SubscriptionDomainRemovedEvent subscriptionDomainRemovedEvent = (SubscriptionDomainRemovedEvent) event;
                 if (log.isDebugEnabled()) {
-                    log.debug(String.format("Cluster removed from multi-tenant clusters map: [host-name] %s [tenant-id] %d [cluster] %s",
-                            hostName, tenantId, cluster.getClusterId()));
+                    log.debug(String.format("Tenant subscription domain removed event received: [tenant-id] %d " +
+                            "[service] %s [cluster-ids] %s [domain-name] %s",
+                            subscriptionDomainRemovedEvent.getTenantId(),
+                            subscriptionDomainRemovedEvent.getServiceName(),
+                            subscriptionDomainRemovedEvent.getClusterIds(),
+                            subscriptionDomainRemovedEvent.getDomainName()));
                 }
+
+                LoadBalancerContextUtil.removeClustersAgainstDomain(
+                        subscriptionDomainRemovedEvent.getServiceName(),
+                        subscriptionDomainRemovedEvent.getClusterIds(),
+                        subscriptionDomainRemovedEvent.getDomainName());
+
+                LoadBalancerContextUtil.removeAppContextAgainstDomain(
+                        subscriptionDomainRemovedEvent.getDomainName());
             }
-        } else {
-            if (log.isErrorEnabled()) {
-                log.error(String.format("Could not find cluster of tenant: [service] %s [tenant-id] %d",
-                        serviceName, tenantId));
-            }
-        }
+        });
     }
 
-    private Cluster findCluster(String serviceName, int tenantId) {
+    private boolean isMultiTenantService(String serviceName) {
         try {
             TopologyManager.acquireReadLock();
             Service service = TopologyManager.getTopology().getService(serviceName);
-            if (service == null) {
-                throw new RuntimeException(String.format("Service not found: %s", serviceName));
-            }
-            for (Cluster cluster : service.getClusters()) {
-                if (cluster.tenantIdInRange(tenantId)) {
-                    return cluster;
-                }
+            if (service != null) {
+                return (service.getServiceType() == ServiceType.MultiTenant);
             }
-            return null;
+            return false;
         } finally {
             TopologyManager.releaseReadLock();
         }
@@ -182,10 +203,10 @@ public class LoadBalancerTenantEventReceiver implements Runnable {
 
         // Keep the thread live until terminated
         while (!terminated) {
-        	try {
-				Thread.sleep(1000);
-			} catch (InterruptedException ignore) {
-			}
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ignore) {
+            }
         }
         if (log.isInfoEnabled()) {
             log.info("Load balancer tenant receiver thread terminated");

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTopologyEventReceiver.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTopologyEventReceiver.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTopologyEventReceiver.java
index 7efaa1c..f10256c 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTopologyEventReceiver.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/LoadBalancerTopologyEventReceiver.java
@@ -77,25 +77,30 @@ public class LoadBalancerTopologyEventReceiver implements Runnable {
     private void addEventListeners() {
         // Listen to topology events that affect clusters
         topologyEventReceiver.addEventListener(new CompleteTopologyEventListener() {
+            private boolean initialized;
+
             @Override
             protected void onEvent(Event event) {
-                try {
-                    TopologyManager.acquireReadLock();
-                    for (Service service : TopologyManager.getTopology().getServices()) {
-                        for (Cluster cluster : service.getClusters()) {
-                            if (clusterHasActiveMembers(cluster)) {
-                                LoadBalancerContextUtil.addClusterToLbContext(cluster);
-                            } else {
-                                if (log.isDebugEnabled()) {
-                                    log.debug("Cluster does not have any active members");
+                if(!initialized) {
+                    try {
+                        TopologyManager.acquireReadLock();
+                        for (Service service : TopologyManager.getTopology().getServices()) {
+                            for (Cluster cluster : service.getClusters()) {
+                                if (clusterHasActiveMembers(cluster)) {
+                                    LoadBalancerContextUtil.addClusterAgainstHostNames(cluster);
+                                } else {
+                                    if (log.isDebugEnabled()) {
+                                        log.debug("Cluster does not have any active members");
+                                    }
                                 }
                             }
                         }
+                        initialized = true;
+                    } catch (Exception e) {
+                        log.error("Error processing event", e);
+                    } finally {
+                        TopologyManager.releaseReadLock();
                     }
-                } catch (Exception e) {
-                    log.error("Error processing event", e);
-                } finally {
-                    TopologyManager.releaseReadLock();
                 }
             }
 
@@ -128,7 +133,7 @@ public class LoadBalancerTopologyEventReceiver implements Runnable {
                     if (service != null) {
                         Cluster cluster = service.getCluster(memberActivatedEvent.getClusterId());
                         if (cluster != null) {
-                            LoadBalancerContextUtil.addClusterToLbContext(cluster);
+                            LoadBalancerContextUtil.addClusterAgainstHostNames(cluster);
                         } else {
                             if (log.isErrorEnabled()) {
                                 log.error(String.format("Cluster not found in topology: [service] %s [cluster] %s",
@@ -157,7 +162,7 @@ public class LoadBalancerTopologyEventReceiver implements Runnable {
                     ClusterRemovedEvent clusterRemovedEvent = (ClusterRemovedEvent) event;
                     Cluster cluster = LoadBalancerContext.getInstance().getClusterIdClusterMap().getCluster(clusterRemovedEvent.getClusterId());
                     if (cluster != null) {
-                        LoadBalancerContextUtil.removeClusterFromLbContext(cluster.getClusterId());
+                        LoadBalancerContextUtil.removeClusterAgainstHostNames(cluster.getClusterId());
                     } else {
                         if (log.isWarnEnabled()) {
                             log.warn(String.format("Cluster not found in load balancer context: [service] %s [cluster] %s",
@@ -182,7 +187,7 @@ public class LoadBalancerTopologyEventReceiver implements Runnable {
                     Service service = TopologyManager.getTopology().getService(serviceRemovedEvent.getServiceName());
                     if (service != null) {
                         for (Cluster cluster : service.getClusters()) {
-                            LoadBalancerContextUtil.removeClusterFromLbContext(cluster.getClusterId());
+                            LoadBalancerContextUtil.removeClusterAgainstHostNames(cluster.getClusterId());
                         }
                     } else {
                         if (log.isWarnEnabled()) {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
index 65f7857..2b67852 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/conf/LoadBalancerConfiguration.java
@@ -35,10 +35,7 @@ import org.apache.stratos.messaging.domain.topology.*;
 import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 
 import java.io.File;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Scanner;
+import java.util.*;
 import java.util.regex.Pattern;
 
 /**
@@ -65,7 +62,7 @@ public class LoadBalancerConfiguration {
     private String topologyClusterFilter;
     private boolean multiTenancyEnabled;
     private TenantIdentifier tenantIdentifier;
-    private String tenantIdentifierRegex;
+    private List<String> tenantIdentifierRegexList;
     private String topologyMemberFilter;
     private String networkPartitionId;
 
@@ -255,12 +252,12 @@ public class LoadBalancerConfiguration {
         return tenantIdentifier;
     }
 
-    public void setTenantIdentifierRegex(String tenantIdentifierRegex) {
-        this.tenantIdentifierRegex = tenantIdentifierRegex;
+    public void setTenantIdentifierRegexList(List<String> tenantIdentifierRegexList) {
+        this.tenantIdentifierRegexList = tenantIdentifierRegexList;
     }
 
-    public String getTenantIdentifierRegex() {
-        return tenantIdentifierRegex;
+    public List<String> getTenantIdentifierRegexList() {
+        return tenantIdentifierRegexList;
     }
 
     public void setNetworkPartitionId(String networkPartitionId) {
@@ -423,7 +420,17 @@ public class LoadBalancerConfiguration {
                 } catch (Exception e) {
                     throw new InvalidConfigurationException(String.format("Invalid tenant identifier regular expression: %s", tenantIdentifierRegex), e);
                 }
-                configuration.setTenantIdentifierRegex(tenantIdentifierRegex);
+                List<String> regexList = new ArrayList<String>();
+                if(tenantIdentifierRegex.contains(org.apache.stratos.messaging.util.Constants.FILTER_VALUE_SEPARATOR)) {
+                    String[] regexArray;
+                    regexArray = tenantIdentifierRegex.split(org.apache.stratos.messaging.util.Constants.FILTER_VALUE_SEPARATOR);
+                    for(String regex: regexArray) {
+                       regexList.add(regex);
+                    }
+                } else {
+                    regexList.add(tenantIdentifierRegex);
+                }
+                configuration.setTenantIdentifierRegexList(regexList);
             }
 
             Node algorithmsNode = loadBalancerNode.findChildNodeByName(Constants.CONF_ELEMENT_ALGORITHMS);
@@ -515,7 +522,7 @@ public class LoadBalancerConfiguration {
                         }
 
                         // Add cluster to load balancer context
-                        LoadBalancerContextUtil.addClusterToLbContext(cluster);
+                        LoadBalancerContextUtil.addClusterAgainstHostNames(cluster);
                     }
                 }
             }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContext.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContext.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContext.java
index 90c8e9a..67d63ee 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContext.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContext.java
@@ -59,9 +59,11 @@ public class LoadBalancerContext {
     // Map<ClusterId, Cluster>
     // Keep track of all clusters
     private ClusterIdClusterMap clusterIdClusterMap;
-    // Map<HostName, Cluster>
+    // Map<Host/Domain-Name, Cluster>
     // Keep tack of all clusters
     private HostNameClusterMap hostNameClusterMap;
+    // Map<Host/Domain-Name, AppContext>
+    private HostNameAppContextMap hostNameAppContextMap;
     // Map<HostName, Map<TenantId, Cluster>>
     // Keep track of multi-tenant service clusters
     private MultiTenantClusterMap multiTenantClusterMap;
@@ -72,6 +74,7 @@ public class LoadBalancerContext {
         clusterIdClusterContextMap = new ClusterIdClusterContextMap();
         clusterIdClusterMap = new ClusterIdClusterMap();
         hostNameClusterMap = new HostNameClusterMap();
+        hostNameAppContextMap = new HostNameAppContextMap();
         multiTenantClusterMap = new MultiTenantClusterMap();
     }
 
@@ -182,7 +185,11 @@ public class LoadBalancerContext {
         return hostNameClusterMap;
     }
 
+    public HostNameAppContextMap getHostNameAppContextMap() {
+        return hostNameAppContextMap;
+    }
+
     public MultiTenantClusterMap getMultiTenantClusterMap() {
-        return multiTenantClusterMap;
+       return multiTenantClusterMap;
     }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContextUtil.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContextUtil.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContextUtil.java
index 037a7c3..5761428 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContextUtil.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/LoadBalancerContextUtil.java
@@ -19,19 +19,33 @@
 
 package org.apache.stratos.load.balancer.context;
 
+import org.apache.commons.lang3.StringUtils;
 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.domain.topology.Cluster;
 import org.apache.stratos.messaging.domain.topology.Service;
+import org.apache.stratos.messaging.message.receiver.tenant.TenantManager;
 import org.apache.stratos.messaging.message.receiver.topology.TopologyManager;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * Load balancer context utility class.
  */
 public class LoadBalancerContextUtil {
     private static final Log log = LogFactory.getLog(LoadBalancerContextUtil.class);
 
-    public static void addClusterToLbContext(Cluster cluster) {
+    /**
+     * Add cluster against its host names.
+     *
+     * @param cluster
+     */
+    public static void addClusterAgainstHostNames(Cluster cluster) {
         if (cluster == null)
             return;
 
@@ -48,16 +62,21 @@ public class LoadBalancerContextUtil {
 
         // Add cluster to HostNameClusterMap
         for (String hostName : cluster.getHostNames()) {
-            if (!LoadBalancerContext.getInstance().getHostNameClusterMap().containsCluster((hostName))) {
-                LoadBalancerContext.getInstance().getHostNameClusterMap().addCluster(hostName, cluster);
-                if (log.isDebugEnabled()) {
-                    log.debug(String.format("Cluster added to hostname -> cluster map: [hostname] %s [cluster] %s ", hostName, cluster.getClusterId()));
-                }
+            addClusterToHostNameClusterMap(hostName, cluster);
+
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Cluster added to host/domain name -> cluster map: [hostName] %s [cluster] %s",
+                        hostName, cluster.getClusterId()));
             }
         }
     }
 
-    public static void removeClusterFromLbContext(String clusterId) {
+    /**
+     * Remove cluster mapped against its host names.
+     *
+     * @param clusterId
+     */
+    public static void removeClusterAgainstHostNames(String clusterId) {
         Cluster cluster = LoadBalancerContext.getInstance().getClusterIdClusterMap().getCluster(clusterId);
         if (cluster == null) {
             return;
@@ -70,11 +89,10 @@ public class LoadBalancerContextUtil {
 
         // Remove cluster from HostNameClusterMap
         for (String hostName : cluster.getHostNames()) {
-            if (LoadBalancerContext.getInstance().getHostNameClusterMap().containsCluster(hostName)) {
-                LoadBalancerContext.getInstance().getHostNameClusterMap().removeCluster(hostName);
-                if (log.isDebugEnabled()) {
-                    log.debug(String.format("Cluster removed from hostname -> cluster map: [hostname] %s [cluster] %s ", hostName, cluster.getClusterId()));
-                }
+            removeClusterFromHostNameClusterMap(hostName, cluster);
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Cluster removed from host/domain name -> clusters map: [host-name] %s [cluster] %s",
+                        hostName, cluster.getClusterId()));
             }
         }
 
@@ -84,4 +102,379 @@ public class LoadBalancerContextUtil {
             log.debug(String.format("Cluster removed from cluster-id -> cluster map: [cluster] %s ", cluster.getClusterId()));
         }
     }
+
+    /**
+     * Add clusters against host names, tenant id for the given service, cluster ids.
+     *
+     * @param serviceName
+     * @param tenantId
+     * @param clusterIds
+     */
+    public static void addClustersAgainstHostNamesAndTenantIds(String serviceName, int tenantId, Set<String> clusterIds) {
+        try {
+            TopologyManager.acquireReadLock();
+
+            Service service = TopologyManager.getTopology().getService(serviceName);
+            if (service == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("Service not found in topology: [service] %s", serviceName));
+                }
+                return;
+            }
+            Cluster cluster;
+            for (String clusterId : clusterIds) {
+                cluster = service.getCluster(clusterId);
+                if (cluster != null) {
+                    // Add cluster against host names and tenant id
+                    addClusterAgainstHostNamesAndTenantId(serviceName, tenantId, cluster);
+                } else {
+                    if (log.isWarnEnabled()) {
+                        log.warn(String.format("Cluster not found in service: [service] %s [cluster] %s", serviceName, clusterId));
+                    }
+                }
+            }
+        } finally {
+            TopologyManager.releaseReadLock();
+        }
+    }
+
+    /**
+     * Remove clusters mapped against host names and tenant id.
+     *
+     * @param serviceName
+     * @param tenantId
+     */
+    public static void removeClustersAgainstHostNamesAndTenantIds(String serviceName, int tenantId, Set<String> clusterIds) {
+        try {
+            TopologyManager.acquireReadLock();
+
+            Service service = TopologyManager.getTopology().getService(serviceName);
+            if (service == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("Service not found in topology: [service] %s", serviceName));
+                }
+                return;
+            }
+            Cluster cluster;
+            for (String clusterId : clusterIds) {
+                cluster = service.getCluster(clusterId);
+                if (cluster != null) {
+                    // Remove cluster mapped against host names and tenant id
+                    removeClusterAgainstHostNamesAndTenantId(serviceName, tenantId, cluster);
+                } else {
+                    if (log.isWarnEnabled()) {
+                        log.warn(String.format("Cluster not found in service: [service] %s [cluster] %s", serviceName, clusterId));
+                    }
+                }
+            }
+        } finally {
+            TopologyManager.releaseReadLock();
+        }
+    }
+
+    /**
+     * Add clusters against domain name for the given service, cluster ids.
+     *
+     * @param serviceName
+     * @param clusterIds
+     * @param domainName
+     */
+    public static void addClustersAgainstDomain(String serviceName, Set<String> clusterIds, String domainName) {
+        try {
+            TopologyManager.acquireReadLock();
+            Service service = TopologyManager.getTopology().getService(serviceName);
+            if (service == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("Service not found in topology: [service] %s", serviceName));
+                }
+                return;
+            }
+            Cluster cluster;
+            for (String clusterId : clusterIds) {
+                cluster = service.getCluster(clusterId);
+                if (cluster != null) {
+                    addClusterAgainstDomain(serviceName, cluster, domainName);
+                } else {
+                    if (log.isWarnEnabled()) {
+                        log.warn(String.format("Cluster not found in service: [service] %s [cluster] %s", serviceName, clusterId));
+                    }
+                }
+            }
+        } finally {
+            TopologyManager.releaseReadLock();
+        }
+    }
+
+    /**
+     * Remove clusters mapped against domain name for the given service, cluster ids.
+     *
+     * @param serviceName
+     * @param clusterIds
+     * @param domainName
+     */
+    public static void removeClustersAgainstDomain(String serviceName, Set<String> clusterIds, String domainName) {
+        try {
+            TopologyManager.acquireReadLock();
+
+            Service service = TopologyManager.getTopology().getService(serviceName);
+            if (service == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("Service not found in topology: [service] %s", serviceName));
+                }
+                return;
+            }
+            Cluster cluster;
+            for (String clusterId : clusterIds) {
+                cluster = service.getCluster(clusterId);
+                if (cluster != null) {
+                    // Remove clusters mapped against domain names
+                    removeClusterAgainstDomain(cluster, domainName);
+                } else {
+                    if (log.isWarnEnabled()) {
+                        log.warn(String.format("Cluster not found in service: [service] %s [cluster] %s", serviceName, clusterId));
+                    }
+                }
+            }
+        } finally {
+            TopologyManager.releaseReadLock();
+        }
+    }
+
+    /**
+     * Find cluster from service name, tenant id.
+     * Acquire a topology manager read lock appropriately.
+     *
+     * @param serviceName
+     * @param tenantId
+     * @return
+     */
+    private static Cluster findCluster(String serviceName, int tenantId) {
+        Service service = TopologyManager.getTopology().getService(serviceName);
+        if (service == null) {
+            throw new RuntimeException(String.format("Service not found: %s", serviceName));
+        }
+        for (Cluster cluster : service.getClusters()) {
+            if (cluster.tenantIdInRange(tenantId)) {
+                return cluster;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Add clusters against host names and tenant id to load balancer context.
+     *
+     * @param serviceName
+     * @param tenantId
+     * @param cluster
+     */
+    private static void addClusterAgainstHostNamesAndTenantId(String serviceName, int tenantId, Cluster cluster) {
+        // Add clusters against host names
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Adding cluster to multi-tenant cluster map against host names: [service] %s " +
+                    "[tenant-id] %d [cluster] %s", serviceName, tenantId, cluster.getClusterId()));
+        }
+        for (String hostName : cluster.getHostNames()) {
+            addClusterToMultiTenantClusterMap(hostName, tenantId, cluster);
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Cluster added to multi-tenant cluster map: [host-name] %s [tenant-id] %d [cluster] %s",
+                        hostName, tenantId, cluster.getClusterId()));
+            }
+        }
+    }
+
+    /**
+     * Remove clusters mapped against host names and tenant id from load balancer context.
+     *
+     * @param serviceName
+     * @param tenantId
+     * @param cluster
+     */
+    private static void removeClusterAgainstHostNamesAndTenantId(String serviceName, int tenantId, Cluster cluster) {
+        // Remove clusters mapped against host names
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Removing cluster from multi-tenant cluster map against host names: [service] %s " +
+                    "[tenant-id] %d [cluster] %s", serviceName, tenantId, cluster.getClusterId()));
+        }
+        for (String hostName : cluster.getHostNames()) {
+            LoadBalancerContext.getInstance().getMultiTenantClusterMap().removeCluster(hostName, tenantId);
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Cluster removed from multi-tenant clusters map: [host-name] %s [tenant-id] %d [cluster] %s",
+                        hostName, tenantId, cluster.getClusterId()));
+            }
+        }
+    }
+
+
+    /**
+     * Add clusters against domains to load balancer context.
+     *
+     * @param serviceName
+     * @param cluster
+     * @param domainName
+     */
+    private static void addClusterAgainstDomain(String serviceName, Cluster cluster, String domainName) {
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Adding cluster to host/domain name -> cluster map against domain: [service] %s " +
+                    "[domain-name] %s [cluster] %s", serviceName, domainName, cluster.getClusterId()));
+        }
+        if (StringUtils.isNotBlank(domainName)) {
+            addClusterToHostNameClusterMap(domainName, cluster);
+
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Cluster added to host/domain name -> cluster map: [domain-name] %s [cluster] %s",
+                        domainName, cluster.getClusterId()));
+            }
+        }
+    }
+
+    /**
+     * Remove clusters mapped against all subscription domain names for the given service, tenant, cluster ids.
+     *
+     * @param serviceName
+     * @param tenantId
+     * @param clusterIds
+     */
+    public static void removeClustersAgainstAllDomains(String serviceName, int tenantId, Set<String> clusterIds) {
+        try {
+            TenantManager.acquireReadLock();
+            TopologyManager.acquireReadLock();
+
+            Service service = TopologyManager.getTopology().getService(serviceName);
+            if (service == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("Service not found in topology: [service] %s", serviceName));
+                }
+                return;
+            }
+            for (String clusterId : clusterIds) {
+                Cluster cluster = service.getCluster(clusterId);
+                Tenant tenant = TenantManager.getInstance().getTenant(tenantId);
+                if (tenant != null) {
+                    for (Subscription subscription : tenant.getSubscriptions()) {
+                        if (subscription.getServiceName().equals(serviceName)) {
+                            if (log.isDebugEnabled()) {
+                                log.debug(String.format("Removing cluster from host/domain name -> cluster map: [service] %s " +
+                                        "[tenant-id] %d [domains] %s", serviceName, tenantId, subscription.getSubscriptionDomains()));
+                            }
+                            for (SubscriptionDomain subscriptionDomain : subscription.getSubscriptionDomains()) {
+                                removeClusterAgainstDomain(cluster, subscriptionDomain.getDomainName());
+                            }
+                        } else {
+                            if (log.isDebugEnabled()) {
+                                log.debug(String.format("Tenant not subscribed to service: %s", serviceName));
+                            }
+                        }
+                    }
+                }
+            }
+        } finally {
+            TopologyManager.releaseReadLock();
+            TenantManager.releaseReadLock();
+        }
+    }
+
+    private static void removeClusterAgainstDomain(Cluster cluster, String domainName) {
+        removeClusterFromHostNameClusterMap(domainName, cluster);
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Cluster removed from host/domain name -> cluster map: [domain-name] %s [cluster] %s",
+                    domainName, cluster.getClusterId()));
+        }
+    }
+
+    /**
+     * Add cluster to host/domain name cluster map.
+     *
+     * @param hostName
+     * @param cluster
+     */
+    private static void addClusterToHostNameClusterMap(String hostName, Cluster cluster) {
+        if (!LoadBalancerContext.getInstance().getHostNameClusterMap().containsCluster((hostName))) {
+            LoadBalancerContext.getInstance().getHostNameClusterMap().addCluster(hostName, cluster);
+        }
+    }
+
+    /**
+     * Remove cluseter from host/domain names cluster map.
+     *
+     * @param hostName
+     * @param cluster
+     */
+    private static void removeClusterFromHostNameClusterMap(String hostName, Cluster cluster) {
+        if (LoadBalancerContext.getInstance().getHostNameClusterMap().containsCluster(hostName)) {
+            LoadBalancerContext.getInstance().getHostNameClusterMap().removeCluster(hostName);
+        }
+    }
+
+    /**
+     * Add cluster to multi-tenant cluster map.
+     *
+     * @param hostName
+     * @param tenantId
+     * @param cluster
+     */
+    private static void addClusterToMultiTenantClusterMap(String hostName, int tenantId, Cluster cluster) {
+        // Add hostName, tenantId, cluster to multi-tenant map
+        Map<Integer, Cluster> clusterMap = LoadBalancerContext.getInstance().getMultiTenantClusterMap().getClusters(hostName);
+        if (clusterMap == null) {
+            clusterMap = new HashMap<Integer, Cluster>();
+            clusterMap.put(tenantId, cluster);
+            LoadBalancerContext.getInstance().getMultiTenantClusterMap().addClusters(hostName, clusterMap);
+        } else {
+            clusterMap.put(tenantId, cluster);
+        }
+    }
+
+    public static void addAppContextAgainstDomain(String domainName, String appContext) {
+        LoadBalancerContext.getInstance().getHostNameAppContextMap().addAppContext(domainName, appContext);
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Application context added against domain name: [domain-name] %s [app-context] %s",
+                    domainName, appContext));
+        }
+    }
+
+    public static void removeAppContextAgainstDomain(String domainName) {
+        LoadBalancerContext.getInstance().getHostNameAppContextMap().removeAppContext(domainName);
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Application context removed against domain name: [domain-name] %s",
+                    domainName));
+        }
+    }
+
+    public static void removeAppContextAgainstAllDomains(String serviceName, int tenantId) {
+        try {
+            TenantManager.acquireReadLock();
+            TopologyManager.acquireReadLock();
+
+            Service service = TopologyManager.getTopology().getService(serviceName);
+            if (service == null) {
+                if (log.isErrorEnabled()) {
+                    log.error(String.format("Service not found in topology: [service] %s", serviceName));
+                }
+                return;
+            }
+
+            Tenant tenant = TenantManager.getInstance().getTenant(tenantId);
+            if (tenant != null) {
+                for (Subscription subscription : tenant.getSubscriptions()) {
+                    if (subscription.getServiceName().equals(serviceName)) {
+                        if (log.isDebugEnabled()) {
+                            log.debug(String.format("Removing appContext against domain name: [service] %s " +
+                                    "[tenant-id] %d [domains] %s", serviceName, tenantId, subscription.getSubscriptionDomains()));
+                        }
+                        for (SubscriptionDomain subscriptionDomain : subscription.getSubscriptionDomains()) {
+                            removeAppContextAgainstDomain(subscriptionDomain.getDomainName());
+                        }
+                    } else {
+                        if (log.isDebugEnabled()) {
+                            log.debug(String.format("Tenant not subscribed to service: %s", serviceName));
+                        }
+                    }
+                }
+            }
+        } finally {
+            TopologyManager.releaseReadLock();
+            TenantManager.releaseReadLock();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameAppContextMap.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameAppContextMap.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameAppContextMap.java
new file mode 100644
index 0000000..411b896
--- /dev/null
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameAppContextMap.java
@@ -0,0 +1,51 @@
+/*
+ * 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.load.balancer.context.map;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Host/domain name application context map.
+ */
+public class HostNameAppContextMap {
+    private ConcurrentHashMap<String, String> concurrentHashMap;
+
+    public HostNameAppContextMap() {
+        concurrentHashMap = new ConcurrentHashMap<String, String>();
+    }
+
+    public void addAppContext(String hostName, String appContext) {
+        concurrentHashMap.put(hostName, appContext);
+    }
+
+    public String getAppContext(String hostName) {
+        return concurrentHashMap.get(hostName);
+    }
+
+    public void removeAppContext(String hostName) {
+        if (contains(hostName)) {
+            concurrentHashMap.remove(hostName);
+        }
+    }
+
+    public boolean contains(String hostName) {
+        return concurrentHashMap.containsKey(hostName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameClusterMap.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameClusterMap.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameClusterMap.java
index e1c52f8..c855dd3 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameClusterMap.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/HostNameClusterMap.java
@@ -24,7 +24,7 @@ import org.apache.stratos.messaging.domain.topology.Cluster;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * Host name cluster map for accessing clusters using host name:
+ * Host/domain name cluster map for accessing clusters using host name:
  * Map[HostName, Cluster]
  */
 public class HostNameClusterMap {

http://git-wip-us.apache.org/repos/asf/stratos/blob/7b35e29e/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/MultiTenantClusterMap.java
----------------------------------------------------------------------
diff --git a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/MultiTenantClusterMap.java b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/MultiTenantClusterMap.java
index 339ad02..d038fbc 100644
--- a/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/MultiTenantClusterMap.java
+++ b/components/org.apache.stratos.load.balancer/src/main/java/org/apache/stratos/load/balancer/context/map/MultiTenantClusterMap.java
@@ -39,7 +39,9 @@ public class MultiTenantClusterMap {
     public Cluster getCluster(String hostName, int tenantId) {
         Map<Integer, Cluster> clusterMap = getClusters(hostName);
         if (clusterMap != null) {
-            return clusterMap.get(tenantId);
+            if(clusterMap.containsKey(tenantId)) {
+                return clusterMap.get(tenantId);
+            }
         }
         return null;
     }
@@ -63,4 +65,13 @@ public class MultiTenantClusterMap {
     public void clear() {
         concurrentHashMap.clear();
     }
+
+    public void removeCluster(String hostName, int tenantId) {
+        Map<Integer, Cluster> clusterMap = getClusters(hostName);
+        if(clusterMap != null) {
+            if(clusterMap.containsKey(tenantId)) {
+                clusterMap.remove(tenantId);
+            }
+        }
+    }
 }