Merge branch 'master' into regions

Conflicts:
	client/tomcatconf/components.xml.in
	server/src/com/cloud/api/ApiResponseHelper.java
diff --git a/api/src/com/cloud/domain/Domain.java b/api/src/com/cloud/domain/Domain.java
index cfed519..97bdfb7 100644
--- a/api/src/com/cloud/domain/Domain.java
+++ b/api/src/com/cloud/domain/Domain.java
@@ -58,4 +58,8 @@
     void setState(State state);
 
     String getNetworkDomain();
+    
+    public String getUuid();
+    
+    int getRegionId();
 }
diff --git a/api/src/com/cloud/user/Account.java b/api/src/com/cloud/user/Account.java
index a5b3e87..e65e017 100755
--- a/api/src/com/cloud/user/Account.java
+++ b/api/src/com/cloud/user/Account.java
@@ -62,5 +62,8 @@
     public String getNetworkDomain();
 
     public Long getDefaultZoneId();
-
+    
+    public int getRegionId();
+    
+    public String getUuid();
 }
diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java
index 9f5f4d22..0c1fc77 100755
--- a/api/src/com/cloud/user/AccountService.java
+++ b/api/src/com/cloud/user/AccountService.java
@@ -23,15 +23,10 @@
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 
-import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
 import org.apache.cloudstack.api.command.admin.user.RegisterCmd;
-import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
-import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
 
 import com.cloud.domain.Domain;
-import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.PermissionDeniedException;
-import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.utils.Pair;
 
 public interface AccountService {
@@ -63,35 +58,7 @@
      * @return the user if created successfully, null otherwise
      */
     UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long domainId, String networkDomain,
-            Map<String, String> details);
-
-    /**
-     * Deletes a user by userId
-     *
-     * @param accountId
-     *            - id of the account do delete
-     *
-     * @return true if delete was successful, false otherwise
-     */
-    boolean deleteUserAccount(long accountId);
-
-    /**
-     * Disables a user by userId
-     *
-     * @param userId
-     *            - the userId
-     * @return UserAccount object
-     */
-    UserAccount disableUser(long userId);
-
-    /**
-     * Enables a user
-     *
-     * @param userId
-     *            - the userId
-     * @return UserAccount object
-     */
-    UserAccount enableUser(long userId);
+            Map<String, String> details, String accountUUID, String userUUID, Integer regionId);
 
     /**
      * Locks a user by userId. A locked user cannot access the API, but will still have running VMs/IP addresses
@@ -102,71 +69,11 @@
      */
     UserAccount lockUser(long userId);
 
-    /**
-     * Update a user by userId
-     *
-     * @param userId
-     * @return UserAccount object
-     */
-    UserAccount updateUser(UpdateUserCmd cmd);
-
-    /**
-     * Disables an account by accountName and domainId
-     *
-     * @param accountName
-     *            TODO
-     * @param domainId
-     *            TODO
-     * @param accountId
-     * @param disabled
-     *            account if success
-     * @return true if disable was successful, false otherwise
-     */
-    Account disableAccount(String accountName, Long domainId, Long accountId) throws ConcurrentOperationException, ResourceUnavailableException;
-
-    /**
-     * Enables an account by accountId
-     *
-     * @param accountName
-     *            - the enableAccount command defining the accountId to be deleted.
-     * @param domainId
-     *            TODO
-     * @param accountId
-     * @return account object
-     */
-    Account enableAccount(String accountName, Long domainId, Long accountId);
-
-    /**
-     * Locks an account by accountId. A locked account cannot access the API, but will still have running VMs/IP
-     * addresses
-     * allocated/etc.
-     *
-     * @param accountName
-     *            - the LockAccount command defining the accountId to be locked.
-     * @param domainId
-     *            TODO
-     * @param accountId
-     * @return account object
-     */
-    Account lockAccount(String accountName, Long domainId, Long accountId);
-
-    /**
-     * Updates an account name
-     *
-     * @param cmd
-     *            - the parameter containing accountId
-     * @return updated account object
-     */
-
-    Account updateAccount(UpdateAccountCmd cmd);
-
     Account getSystemAccount();
 
     User getSystemUser();
 
-    User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId);
-
-    boolean deleteUser(DeleteUserCmd deleteUserCmd);
+    User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID, Integer regionId);
 
     boolean isAdmin(short accountType);
 
diff --git a/api/src/com/cloud/user/DomainService.java b/api/src/com/cloud/user/DomainService.java
index cd20060..1a96354 100644
--- a/api/src/com/cloud/user/DomainService.java
+++ b/api/src/com/cloud/user/DomainService.java
@@ -20,13 +20,14 @@
 
 import org.apache.cloudstack.api.command.admin.domain.ListDomainChildrenCmd;
 import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd;
+
 import com.cloud.domain.Domain;
 import com.cloud.exception.PermissionDeniedException;
 import com.cloud.utils.Pair;
 
 public interface DomainService {
 
-    Domain createDomain(String name, Long parentId, String networkDomain);
+    Domain createDomain(String name, Long parentId, String networkDomain, String domainUUID, Integer regionId);
 
     Domain getDomain(long id);
 
@@ -40,12 +41,19 @@
      */
     boolean isChildDomain(Long parentId, Long childId);
 
-    boolean deleteDomain(long domainId, Boolean cleanup);
-
     Pair<List<? extends Domain>, Integer> searchForDomains(ListDomainsCmd cmd)
             throws PermissionDeniedException;
 
     Pair<List<? extends Domain>, Integer> searchForDomainChildren(ListDomainChildrenCmd cmd)
             throws PermissionDeniedException;
 
+    /**
+     * find the domain by its path
+     * 
+     * @param domainPath
+     *            the path to use to lookup a domain
+     * @return domainVO the domain with the matching path, or null if no domain with the given path exists
+     */
+    Domain findDomainByPath(String domainPath);
+
 }
diff --git a/api/src/com/cloud/user/User.java b/api/src/com/cloud/user/User.java
index 36a7c65..ed1e405 100644
--- a/api/src/com/cloud/user/User.java
+++ b/api/src/com/cloud/user/User.java
@@ -72,5 +72,6 @@
     String getRegistrationToken();
 
     boolean isRegistered();
-
+    
+    public int getRegionId();
 }
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 6d2a9a3..f704aec 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -374,6 +374,9 @@
     public static final String VSM_CONFIG_STATE = "vsmconfigstate";
     public static final String VSM_DEVICE_STATE = "vsmdevicestate";
     public static final String ADD_VSM_FLAG = "addvsmflag";
+	public static final String END_POINT = "endpoint";
+	public static final String REGION_ID = "regionid";
+	public static final String IS_PROPAGATE = "ispropagate";
     public static final String VPC_OFF_ID = "vpcofferingid";
     public static final String NETWORK = "network";
     public static final String VPC_ID = "vpcid";
diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java
index 966e39c..070360e 100644
--- a/api/src/org/apache/cloudstack/api/BaseCmd.java
+++ b/api/src/org/apache/cloudstack/api/BaseCmd.java
@@ -26,6 +26,7 @@
 import java.util.regex.Pattern;
 
 import org.apache.cloudstack.query.QueryService;
+import org.apache.cloudstack.region.RegionService;
 import org.apache.log4j.Logger;
 
 import com.cloud.configuration.ConfigurationService;
@@ -118,6 +119,7 @@
     public static ResourceLimitService _resourceLimitService;
     public static IdentityService _identityService;
     public static StorageNetworkService _storageNetworkService;
+    public static RegionService _regionService;
     public static TaggedResourceService _taggedResourceService;
     public static VpcService _vpcService;
     public static NetworkACLService _networkACLService;
@@ -152,6 +154,7 @@
         _resourceLimitService = locator.getManager(ResourceLimitService.class);
         _identityService = locator.getManager(IdentityService.class);
         _storageNetworkService = locator.getManager(StorageNetworkService.class);
+        _regionService = locator.getManager(RegionService.class);
         _taggedResourceService = locator.getManager(TaggedResourceService.class);
         _vpcService = locator.getManager(VpcService.class);
         _networkACLService = locator.getManager(NetworkACLService.class);
diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
index 63df4dc..0b9eb50 100644
--- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
@@ -60,10 +60,12 @@
 import org.apache.cloudstack.api.response.ProjectInvitationResponse;
 import org.apache.cloudstack.api.response.ProjectResponse;
 import org.apache.cloudstack.api.response.ProviderResponse;
+import org.apache.cloudstack.api.response.RegionResponse;
 import org.apache.cloudstack.api.response.RemoteAccessVpnResponse;
 import org.apache.cloudstack.api.response.ResourceCountResponse;
 import org.apache.cloudstack.api.response.ResourceLimitResponse;
 import org.apache.cloudstack.api.response.ResourceTagResponse;
+import org.apache.cloudstack.api.response.S3Response;
 import org.apache.cloudstack.api.response.SecurityGroupResponse;
 import org.apache.cloudstack.api.response.ServiceOfferingResponse;
 import org.apache.cloudstack.api.response.ServiceResponse;
@@ -91,8 +93,7 @@
 import org.apache.cloudstack.api.response.VpcResponse;
 import org.apache.cloudstack.api.response.VpnUsersResponse;
 import org.apache.cloudstack.api.response.ZoneResponse;
-
-import org.apache.cloudstack.api.response.S3Response;
+import org.apache.cloudstack.region.Region;
 
 import com.cloud.async.AsyncJob;
 import com.cloud.capacity.Capacity;
@@ -313,6 +314,8 @@
     LDAPConfigResponse createLDAPConfigResponse(String hostname, Integer port, Boolean useSSL, String queryFilter, String baseSearch, String dn);
 
     StorageNetworkIpRangeResponse createStorageNetworkIpRangeResponse(StorageNetworkIpRange result);
+    
+    RegionResponse createRegionResponse(Region region);
 
     /**
      * @param resourceTag
diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
index a13cf62..7c2f2d1 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java
@@ -73,7 +73,20 @@
 
     @Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters")
     private Map<String, String> details;
+	
+	//@Parameter(name = ApiConstants.REGION_DETAILS, type = CommandType.MAP, description = "details for account used to store region specific parameters")
+    //private Map<String, String> regionDetails;
+	
+    @Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.STRING, description="Account UUID, required for adding account from another Region")
+    private String accountUUID;
 
+    @Parameter(name=ApiConstants.USER_ID, type=CommandType.STRING, description="User UUID, required for adding account from another Region")
+    private String userUUID;
+
+    @Parameter(name=ApiConstants.REGION_ID, type=CommandType.INTEGER, description="Id of the Region creating the account")
+    private Integer regionId;
+
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -128,11 +141,23 @@
         return params;
     }
 
+    public String getAccountUUID() {
+		return accountUUID;
+	}
+
+	public String getUserUUID() {
+		return userUUID;
+	}
+
+	public Integer getRegionId() {
+		return regionId;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
 
-    @Override
+	@Override
     public String getCommandName() {
         return s_name;
     }
@@ -145,7 +170,8 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("Account Name: "+getAccountName()+", Domain Id:"+getDomainId());
-        UserAccount userAccount = _accountService.createUserAccount(getUsername(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimeZone(), getAccountName(), getAccountType(), getDomainId(), getNetworkDomain(), getDetails());
+        UserAccount userAccount = _accountService.createUserAccount(getUsername(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimeZone(), getAccountName(), getAccountType(), getDomainId(), getNetworkDomain(), getDetails(), 
+        		getAccountUUID(), getUserUUID(), getRegionId());
         if (userAccount != null) {
             AccountResponse response = _responseGenerator.createUserAccountResponse(userAccount);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java
index 86ccb4b..22cab8a 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java
@@ -41,13 +41,21 @@
             required=true, description="Account id")
     private Long id;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
 
-    public Long getId() {
+
+	public Long getId() {
         return id;
     }
+    
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
 
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
@@ -86,7 +94,8 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("Account Id: "+getId());
-        boolean result = _accountService.deleteUserAccount(getId());
+ 
+        boolean	result = _regionService.deleteUserAccount(this);
         if (result) {
             SuccessResponse response = new SuccessResponse(getCommandName());
             this.setResponseObject(response);
diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java
index 318dfda..e78a09c 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java
@@ -52,6 +52,9 @@
     @Parameter(name=ApiConstants.LOCK, type=CommandType.BOOLEAN, required=true, description="If true, only lock the account; else disable the account")
     private Boolean lockRequested;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -68,11 +71,19 @@
         return domainId;
     }
 
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
+
+    public Boolean getLockRequested() {
+		return lockRequested;
+	}
+	
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
 
-    @Override
+	@Override
     public String getCommandName() {
         return s_name;
     }
@@ -105,11 +116,7 @@
     @Override
     public void execute() throws ConcurrentOperationException, ResourceUnavailableException{
         UserContext.current().setEventDetails("Account Name: "+getAccountName()+", Domain Id:"+getDomainId());
-        Account result = null;
-        if(lockRequested)
-            result = _accountService.lockAccount(getAccountName(), getDomainId(), getId());
-        else
-            result = _accountService.disableAccount(getAccountName(), getDomainId(), getId());
+    	Account result = _regionService.disableAccount(this);
         if (result != null){
             AccountResponse response = _responseGenerator.createAccountResponse(result);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java
index 2688ef1..09aafea 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java
@@ -48,6 +48,9 @@
             description="Enables specified account in this domain.")
     private Long domainId;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -64,6 +67,10 @@
         return domainId;
     }
 
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -90,7 +97,7 @@
 
     @Override
     public void execute(){
-        Account result = _accountService.enableAccount(getAccountName(), getDomainId(), getId());
+    	Account result = _regionService.enableAccount(this);
         if (result != null){
             AccountResponse response = _responseGenerator.createAccountResponse(result);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java
index ea6d907..5840647 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java
@@ -61,6 +61,9 @@
     @Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "details for account used to store specific parameters")
     private Map details;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+	
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -95,6 +98,10 @@
         return params;
     }
 
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -120,7 +127,7 @@
 
     @Override
     public void execute(){
-        Account result = _accountService.updateAccount(this);
+    	Account result = _regionService.updateAccount(this);
         if (result != null){
             AccountResponse response = _responseGenerator.createAccountResponse(result);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java b/api/src/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java
index 61614d1..f51738c 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java
@@ -45,6 +45,12 @@
     @Parameter(name=ApiConstants.NETWORK_DOMAIN, type=CommandType.STRING, description="Network domain for networks in the domain")
     private String networkDomain;
 
+    @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.STRING, description="Domain UUID, required for adding domain from another Region")
+    private String domainUUID;
+    
+    @Parameter(name=ApiConstants.REGION_ID, type=CommandType.INTEGER, description="Id of the Region creating the Domain")
+    private Integer regionId;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -61,6 +67,14 @@
         return networkDomain;
     }
 
+    public String getDomainUUID() {
+        return domainUUID;
+    }
+    
+	public Integer getRegionId() {
+		return regionId;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -78,7 +92,7 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("Domain Name: "+getDomainName()+((getParentDomainId()!=null)?", Parent DomainId :"+getParentDomainId():""));
-        Domain domain = _domainService.createDomain(getDomainName(), getParentDomainId(), getNetworkDomain());
+        Domain domain = _domainService.createDomain(getDomainName(), getParentDomainId(), getNetworkDomain(), getDomainUUID(), getRegionId());
         if (domain != null) {
             DomainResponse response = _responseGenerator.createDomainResponse(domain);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java b/api/src/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java
index 3fda960..39250fd 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java
@@ -43,6 +43,8 @@
     @Parameter(name=ApiConstants.CLEANUP, type=CommandType.BOOLEAN, description="true if all domain resources (child domains, accounts) have to be cleaned up, false otherwise")
     private Boolean cleanup;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean propagate;
 
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
@@ -56,6 +58,10 @@
         return cleanup;
     }
 
+	public Boolean isPropagate() {
+		return propagate;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -88,7 +94,7 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("Domain Id: "+getId());
-        boolean result = _domainService.deleteDomain(id, cleanup);
+        boolean result = _regionService.deleteDomain(this);
         if (result) {
             SuccessResponse response = new SuccessResponse(getCommandName());
             this.setResponseObject(response);
diff --git a/api/src/org/apache/cloudstack/api/command/admin/domain/UpdateDomainCmd.java b/api/src/org/apache/cloudstack/api/command/admin/domain/UpdateDomainCmd.java
index 607120c..79e57a6 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/domain/UpdateDomainCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/domain/UpdateDomainCmd.java
@@ -23,6 +23,7 @@
 import org.apache.cloudstack.api.response.DomainResponse;
 import com.cloud.domain.Domain;
 import com.cloud.user.Account;
+import com.cloud.user.UserAccount;
 import com.cloud.user.UserContext;
 
 @APICommand(name = "updateDomain", description="Updates a domain with a new name", responseObject=DomainResponse.class)
@@ -44,6 +45,9 @@
     @Parameter(name=ApiConstants.NETWORK_DOMAIN, type=CommandType.STRING, description="Network domain for the domain's networks; empty string will update domainName with NULL value")
     private String networkDomain;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -60,6 +64,10 @@
         return networkDomain;
     }
 
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -77,7 +85,8 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("Domain Id: "+getId());
-        Domain domain = _mgr.updateDomain(this);
+        Domain domain =  _regionService.updateDomain(this);
+        
         if (domain != null) {
             DomainResponse response = _responseGenerator.createDomainResponse(domain);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/region/AddRegionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/region/AddRegionCmd.java
new file mode 100644
index 0000000..f9663b7
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/region/AddRegionCmd.java
@@ -0,0 +1,104 @@
+// 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.cloudstack.api.command.admin.region;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.RegionResponse;
+import org.apache.cloudstack.region.Region;
+import org.apache.log4j.Logger;
+
+import com.cloud.user.Account;
+
+@APICommand(name = "addRegion", description="Adds a Region", responseObject=RegionResponse.class)
+public class AddRegionCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(AddRegionCmd.class.getName());
+
+    private static final String s_name = "addregionresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+    @Parameter(name=ApiConstants.ID, type=CommandType.INTEGER, required=true, description="Id of the Region")
+    private Integer id;
+    
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="Name of the region")
+    private String regionName;
+
+    @Parameter(name=ApiConstants.END_POINT, type=CommandType.STRING, required=true, description="Region service endpoint")
+    private String endPoint;
+
+    @Parameter(name=ApiConstants.API_KEY, type=CommandType.STRING, description="API key of Admin user")
+    private String apiKey;
+    
+    @Parameter(name=ApiConstants.SECRET_KEY, type=CommandType.STRING, description="Secret Key of Admin user")
+    private String secretKey;
+    
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Integer getId() {
+        return id;
+    }
+    
+    public String getRegionName() {
+        return regionName;
+    }
+
+    public String getEndPoint() {
+        return endPoint;
+    }
+
+    public String getApiKey() {
+        return apiKey;
+    }
+    
+    public String getSecretKey() {
+        return secretKey;
+    }
+    
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+    
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+    
+    @Override
+    public void execute(){
+        Region region = _regionService.addRegion(getId(), getRegionName(), getEndPoint(), getApiKey(), getSecretKey());
+        if (region != null) {
+        	RegionResponse response = _responseGenerator.createRegionResponse(region);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Region");
+        }
+    }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java
new file mode 100644
index 0000000..bb74c17
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java
@@ -0,0 +1,74 @@
+// 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.cloudstack.api.command.admin.region;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.log4j.Logger;
+
+import com.cloud.user.Account;
+
+@APICommand(name = "removeRegion", description="Removes specified region", responseObject=SuccessResponse.class)
+public class RemoveRegionCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(RemoveRegionCmd.class.getName());
+    private static final String s_name = "updateregionresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.INTEGER, required=true, description="ID of the region to delete")
+    private Integer id;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Integer getId() {
+        return id;
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM; 
+    }
+
+    @Override
+    public void execute(){
+        boolean result = _regionService.removeRegion(id);
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove region");
+        }
+    }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/region/UpdateRegionCmd.java b/api/src/org/apache/cloudstack/api/command/admin/region/UpdateRegionCmd.java
new file mode 100644
index 0000000..bc6576c
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/admin/region/UpdateRegionCmd.java
@@ -0,0 +1,103 @@
+// 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.cloudstack.api.command.admin.region;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.RegionResponse;
+import org.apache.cloudstack.region.Region;
+import org.apache.log4j.Logger;
+
+import com.cloud.user.Account;
+
+@APICommand(name = "updateRegion", description="Updates a region", responseObject=RegionResponse.class)
+public class UpdateRegionCmd extends BaseCmd {
+    public static final Logger s_logger = Logger.getLogger(UpdateRegionCmd.class.getName());
+    private static final String s_name = "updateregionresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.INTEGER, required=true, description="Id of region to update")
+    private Integer id;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="updates region with this name")
+    private String regionName;
+    
+    @Parameter(name=ApiConstants.END_POINT, type=CommandType.STRING, description="updates region with this end point")
+    private String endPoint;
+
+    @Parameter(name=ApiConstants.API_KEY, type=CommandType.STRING, description="new API key for the Region")
+    private String apiKey;
+    
+    @Parameter(name=ApiConstants.SECRET_KEY, type=CommandType.STRING, description="new Secret Key for the Region")
+    private String secretKey;
+    
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Integer getId() {
+        return id;
+    }
+
+    public String getRegionName() {
+        return regionName;
+    }
+    
+    public String getEndPoint() {
+        return endPoint;
+    }
+
+    public String getApiKey() {
+        return apiKey;
+    }
+    
+    public String getSecretKey() {
+        return secretKey;
+    }
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+    
+    @Override
+    public long getEntityOwnerId() {
+        return Account.ACCOUNT_ID_SYSTEM;
+    }
+    
+    @Override
+    public void execute(){
+    	Region region = _regionService.updateRegion(getId(), getRegionName(), getEndPoint(), getApiKey(), getSecretKey());
+    	if (region != null) {
+    		RegionResponse response = _responseGenerator.createRegionResponse(region);
+    		response.setResponseName(getCommandName());
+    		this.setResponseObject(response);
+    	} else {
+    		throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update Region");
+    	}
+    }
+}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java
index 1f1e3ab..1221aa4 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java
@@ -65,6 +65,12 @@
     @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required=true, description="Unique username.")
     private String username;
 
+    @Parameter(name=ApiConstants.USER_ID, type=CommandType.STRING, description="User UUID, required for adding account from another Region")
+    private String userUUID;
+    
+    @Parameter(name=ApiConstants.REGION_ID, type=CommandType.INTEGER, description="Id of the Region creating the User")
+    private Integer regionId;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -101,6 +107,14 @@
         return username;
     }
 
+	public String getUserUUID() {
+		return userUUID;
+	}
+    
+	public Integer getRegionId() {
+		return regionId;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -132,7 +146,7 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("UserName: "+getUserName()+", FirstName :"+getFirstName()+", LastName: "+getLastName());
-        User user = _accountService.createUser(getUserName(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimezone(), getAccountName(), getDomainId());
+        User user = _accountService.createUser(getUserName(), getPassword(), getFirstName(), getLastName(), getEmail(), getTimezone(), getAccountName(), getDomainId(), getUserUUID(), getRegionId());
         if (user != null) {
             UserResponse response = _responseGenerator.createUserResponse(user);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java
index 74a073c..d333f60 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java
@@ -42,6 +42,9 @@
     @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=UserResponse.class, required=true, description="Deletes a user")
     private Long id;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -50,6 +53,10 @@
         return id;
     }
 
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -72,7 +79,7 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("UserId: "+getId());
-        boolean result = _accountService.deleteUser(this);
+        boolean result = _regionService.deleteUser(this);
         if (result) {
             SuccessResponse response = new SuccessResponse(getCommandName());
             this.setResponseObject(response);
diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java
index 6b59de5..91a9253 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java
@@ -21,7 +21,6 @@
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.BaseAsyncCmd;
-import org.apache.cloudstack.api.BaseCmd;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.Parameter;
 import org.apache.cloudstack.api.ServerApiException;
@@ -46,6 +45,9 @@
             required=true, description="Disables user by user ID.")
     private Long id;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -54,6 +56,10 @@
         return id;
     }
 
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -87,7 +93,8 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("UserId: "+getId());
-        UserAccount user = _accountService.disableUser(getId());
+        UserAccount user = _regionService.disableUser(this);
+        
         if (user != null){
             UserResponse response = _responseGenerator.createUserResponse(user);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java
index bcd0f43..082b5ac 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java
@@ -39,7 +39,9 @@
             required=true, description="Enables user by user ID.")
     private Long id;
 
-
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -48,6 +50,10 @@
         return id;
     }
 
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -70,7 +76,8 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("UserId: "+getId());
-        UserAccount user = _accountService.enableUser(getId());
+        UserAccount user = _regionService.enableUser(this);
+        
         if (user != null){
             UserResponse response = _responseGenerator.createUserResponse(user);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java
index 00bfccc..b6f23a2 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java
@@ -64,6 +64,9 @@
     @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, description="Unique username")
     private String username;
 
+    @Parameter(name=ApiConstants.IS_PROPAGATE, type=CommandType.BOOLEAN, description="True if command is sent from another Region")
+    private Boolean isPropagate;
+    
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -104,6 +107,10 @@
         return username;
     }
 
+	public Boolean getIsPropagate() {
+		return isPropagate;
+	}
+    
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -126,7 +133,8 @@
     @Override
     public void execute(){
         UserContext.current().setEventDetails("UserId: "+getId());
-        UserAccount user = _accountService.updateUser(this);
+        UserAccount user = _regionService.updateUser(this);
+        
         if (user != null){
             UserResponse response = _responseGenerator.createUserResponse(user);
             response.setResponseName(getCommandName());
diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ListRegionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ListRegionsCmd.java
new file mode 100644
index 0000000..999eeb0
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/region/ListRegionsCmd.java
@@ -0,0 +1,83 @@
+// 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.cloudstack.api.command.user.region;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.RegionResponse;
+import org.apache.cloudstack.region.Region;
+import org.apache.log4j.Logger;
+
+@APICommand(name = "listRegions", description="Lists Regions", responseObject=RegionResponse.class)
+public class ListRegionsCmd extends BaseListCmd {
+	public static final Logger s_logger = Logger.getLogger(ListRegionsCmd.class.getName());
+	
+    private static final String s_name = "listregionsresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.INTEGER, description="List Region by region ID.")
+    private Integer id;
+
+    @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="List Region by region name.")
+    private String name;
+    
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public Integer getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+    
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public void execute(){
+        List<? extends Region> result = _regionService.listRegions(this);
+        ListResponse<RegionResponse> response = new ListResponse<RegionResponse>();
+        List<RegionResponse> regionResponses = new ArrayList<RegionResponse>();
+        for (Region region : result) {
+        	RegionResponse regionResponse = _responseGenerator.createRegionResponse(region);
+        	regionResponse.setObjectName("region");
+        	regionResponses.add(regionResponse);
+        }
+
+        response.setResponses(regionResponses);
+        response.setResponseName(getCommandName());
+        this.setResponseObject(response);
+    }
+}
diff --git a/api/src/org/apache/cloudstack/api/response/RegionResponse.java b/api/src/org/apache/cloudstack/api/response/RegionResponse.java
new file mode 100644
index 0000000..f8bfe53
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/RegionResponse.java
@@ -0,0 +1,62 @@
+// 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.cloudstack.api.response;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+import org.apache.cloudstack.region.Region;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@EntityReference(value = Region.class)
+public class RegionResponse extends BaseResponse {
+    @SerializedName(ApiConstants.ID) @Param(description="the ID of the region")
+    private Integer id;
+
+    @SerializedName(ApiConstants.NAME) @Param(description="the name of the region")
+    private String name;
+
+    @SerializedName(ApiConstants.END_POINT) @Param(description="the end point of the region")
+    private String endPoint;
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getEndPoint() {
+		return endPoint;
+	}
+
+	public void setEndPoint(String endPoint) {
+		this.endPoint = endPoint;
+	}
+
+  }
diff --git a/api/src/org/apache/cloudstack/region/Region.java b/api/src/org/apache/cloudstack/region/Region.java
new file mode 100644
index 0000000..7f0aeea
--- /dev/null
+++ b/api/src/org/apache/cloudstack/region/Region.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.cloudstack.region;
+
+/**
+ *
+ */
+public interface Region  {
+    
+    public int getId();
+
+	public String getName();
+
+	public void setName(String name);
+
+	public String getEndPoint();
+	
+	public String getApiKey();
+	
+	public String getSecretKey();
+}
diff --git a/api/src/org/apache/cloudstack/region/RegionService.java b/api/src/org/apache/cloudstack/region/RegionService.java
new file mode 100644
index 0000000..8679ca9
--- /dev/null
+++ b/api/src/org/apache/cloudstack/region/RegionService.java
@@ -0,0 +1,157 @@
+// 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.cloudstack.region;
+
+import java.util.List;
+
+import org.apache.cloudstack.api.command.admin.account.DeleteAccountCmd;
+import org.apache.cloudstack.api.command.admin.account.DisableAccountCmd;
+import org.apache.cloudstack.api.command.admin.account.EnableAccountCmd;
+import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
+import org.apache.cloudstack.api.command.admin.domain.DeleteDomainCmd;
+import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
+import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
+import org.apache.cloudstack.api.command.admin.user.DisableUserCmd;
+import org.apache.cloudstack.api.command.admin.user.EnableUserCmd;
+import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
+import org.apache.cloudstack.api.command.user.region.ListRegionsCmd;
+
+import com.cloud.domain.Domain;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.UserAccount;
+
+
+public interface RegionService {
+	/**
+	 * Adds a Region to the local Region
+	 * @param id
+	 * @param name
+	 * @param endPoint
+	 * @param apiKey
+	 * @param secretKey
+	 * @return Return added Region object
+	 */
+	public Region addRegion(int id, String name, String endPoint, String apiKey, String secretKey);
+	
+	/**
+	 * Update details of the Region with specified Id
+	 * @param id
+	 * @param name
+	 * @param endPoint
+	 * @param apiKey
+	 * @param secretKey
+	 * @return Return updated Region object
+	 */
+	public Region updateRegion(int id, String name, String endPoint, String apiKey, String secretKey);
+	
+	/**
+	 * @param id
+	 * @return True if region is successfully removed
+	 */
+	public boolean removeRegion(int id);
+	
+	/** List all Regions or by Id/Name
+	 * @param id
+	 * @param name
+	 * @return List of Regions
+	 */
+	public List<? extends Region> listRegions(ListRegionsCmd cmd);
+	
+    /**
+     * Deletes a user by userId
+     * isPopagate flag is set to true if sent from peer Region
+     * @param cmd
+     *
+     * @return true if delete was successful, false otherwise
+     */
+	boolean deleteUserAccount(DeleteAccountCmd cmd);
+	
+    /**
+     * Updates an account
+     * isPopagate falg is set to true if sent from peer Region 
+     *
+     * @param cmd
+     *            - the parameter containing accountId or account nameand domainId
+     * @return updated account object
+     */
+    Account updateAccount(UpdateAccountCmd cmd);
+	
+	/**
+	 * Disables an account by accountName and domainId or accountId
+	 * @param cmd
+	 * @return
+	 * @throws ResourceUnavailableException 
+	 * @throws ConcurrentOperationException 
+	 */
+	Account disableAccount(DisableAccountCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException;
+	
+	/**
+	 * Enables an account by accountId
+	 * @param cmd
+	 * @return
+	 */
+	Account enableAccount(EnableAccountCmd cmd);
+
+    /**
+     * Deletes user by Id
+     * @param deleteUserCmd
+     * @return true if delete was successful, false otherwise
+     */
+    boolean deleteUser(DeleteUserCmd deleteUserCmd); 	
+    
+    /**
+     * update an existing domain
+     * 
+     * @param cmd
+     *            - the command containing domainId and new domainName
+     * @return Domain object if the command succeeded
+     */
+	public Domain updateDomain(UpdateDomainCmd updateDomainCmd);    
+    
+	/**
+	 * Deletes domain
+	 * @param cmd
+	 * @return true if delete was successful, false otherwise
+	 */
+	public boolean deleteDomain(DeleteDomainCmd cmd);
+	
+    /**
+     * Update a user by userId
+     *
+     * @param userId
+     * @return UserAccount object
+     */
+	public UserAccount updateUser(UpdateUserCmd updateUserCmd);
+	
+    /**
+     * Disables a user by userId
+     *
+     * @param cmd
+     * @return UserAccount object
+     */
+	public UserAccount disableUser(DisableUserCmd cmd);
+	
+    /**
+     * Enables a user
+     *
+     * @param cmd
+     * @return UserAccount object
+     */
+	public UserAccount enableUser(EnableUserCmd cmd);
+}
diff --git a/api/src/org/apache/cloudstack/region/RegionSync.java b/api/src/org/apache/cloudstack/region/RegionSync.java
new file mode 100644
index 0000000..5a1f5a6
--- /dev/null
+++ b/api/src/org/apache/cloudstack/region/RegionSync.java
@@ -0,0 +1,33 @@
+// 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.cloudstack.region;
+
+import java.util.Date;
+
+/**
+ *
+ */
+public interface RegionSync  {
+    
+    public long getId();
+    
+    public int getRegionId();
+    
+	public String getApi();
+
+	Date getCreateDate();
+}
diff --git a/api/test/org/apache/cloudstack/api/command/test/RegionCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/RegionCmdTest.java
new file mode 100644
index 0000000..01cd33b
--- /dev/null
+++ b/api/test/org/apache/cloudstack/api/command/test/RegionCmdTest.java
@@ -0,0 +1,104 @@
+// 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.cloudstack.api.command.test;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.cloudstack.api.ResponseGenerator;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.command.admin.region.AddRegionCmd;
+import org.apache.cloudstack.api.response.RegionResponse;
+import org.apache.cloudstack.region.Region;
+import org.apache.cloudstack.region.RegionService;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+
+public class RegionCmdTest extends TestCase {
+
+    private AddRegionCmd addRegionCmd;
+    private ResponseGenerator responseGenerator;
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+
+    	addRegionCmd = new AddRegionCmd() {
+
+            @Override
+            public Integer getId() {
+                return 2;
+            }
+
+            @Override
+            public String getRegionName() {
+                return "APAC";
+            }
+
+        };
+    }
+
+    @Test
+    public void testCreateSuccess() {
+
+        RegionService regionService = Mockito.mock(RegionService.class);
+
+        Region region = Mockito.mock(Region.class);
+        Mockito.when(
+        		regionService.addRegion(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString()))
+        		.thenReturn(region);
+
+        addRegionCmd._regionService = regionService;
+        responseGenerator = Mockito.mock(ResponseGenerator.class);
+        
+        RegionResponse regionResponse = Mockito.mock(RegionResponse.class);
+
+        Mockito.when(responseGenerator.createRegionResponse(region)).thenReturn(
+        		regionResponse);
+        
+        addRegionCmd._responseGenerator = responseGenerator;                
+        addRegionCmd.execute();
+
+    }
+
+    @Test
+    public void testCreateFailure() {
+
+        RegionService regionService = Mockito.mock(RegionService.class);
+
+        Region region = Mockito.mock(Region.class);
+        Mockito.when(
+        		regionService.addRegion(Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString()))
+        		.thenReturn(null);
+
+        addRegionCmd._regionService = regionService;
+
+        try {
+        	addRegionCmd.execute();
+        } catch (ServerApiException exception) {
+            Assert.assertEquals("Failed to add Region",
+                    exception.getDescription());
+        }
+
+    }    
+
+}
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 755a5f2..4b0506f 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -525,3 +525,9 @@
 
 getApiLimit=15
 resetApiLimit=1
+
+#### Region commands
+addRegion=1
+updateRegion=1
+removeRegion=1
+listRegions=15
diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in
index e9bd56a..e84be04 100755
--- a/client/tomcatconf/components.xml.in
+++ b/client/tomcatconf/components.xml.in
@@ -271,6 +271,7 @@
         <dao name="Site2SiteCustomerGatewayDao" class="com.cloud.network.dao.Site2SiteCustomerGatewayDaoImpl" singleton="false"/>
         <dao name="Site2SiteVpnGatewayDao" class="com.cloud.network.dao.Site2SiteVpnGatewayDaoImpl" singleton="false"/>
         <dao name="Site2SiteVpnConnectionDao" class="com.cloud.network.dao.Site2SiteVpnConnectionDaoImpl" singleton="false"/>
+        <dao name="RegionDao" class="org.apache.cloudstack.region.dao.RegionDaoImpl" singleton="false"/>
         <dao name="UserIpv6AddressDao" class="com.cloud.network.dao.UserIpv6AddressDaoImpl" singleton="false"/>
     </configuration-server>
     
diff --git a/client/tomcatconf/db.properties.in b/client/tomcatconf/db.properties.in
index e383667..96e0d5e 100644
--- a/client/tomcatconf/db.properties.in
+++ b/client/tomcatconf/db.properties.in
@@ -19,6 +19,7 @@
 # in which the management server(Tomcat) is running
 cluster.node.IP=127.0.0.1
 cluster.servlet.port=9090
+region.id=1
 
 # CloudStack database settings
 db.cloud.username=@DBUSER@
diff --git a/client/tomcatconf/environment.properties.in b/client/tomcatconf/environment.properties.in
index 49544a1..f2956cc 100644
--- a/client/tomcatconf/environment.properties.in
+++ b/client/tomcatconf/environment.properties.in
@@ -19,4 +19,4 @@
 
 paths.script=@COMMONLIBDIR@
 mount.parent=@MSMNTDIR@
-cloud-stack-components-specification=@COMPONENTS-SPEC@
+cloud-stack-components-specification=components.xml
diff --git a/core/src/com/cloud/user/AccountVO.java b/core/src/com/cloud/user/AccountVO.java
index 922c8b9..fd37c77 100644
--- a/core/src/com/cloud/user/AccountVO.java
+++ b/core/src/com/cloud/user/AccountVO.java
@@ -28,9 +28,7 @@
 import javax.persistence.Id;
 import javax.persistence.Table;
 
-import org.apache.cloudstack.api.Identity;
 import com.cloud.utils.db.GenericDao;
-import org.apache.cloudstack.api.InternalIdentity;
 
 @Entity
 @Table(name="account")
@@ -68,6 +66,9 @@
     @Column(name="default_zone_id")
     private Long defaultZoneId = null;
 
+    @Column(name="region_id")
+    private int regionId;
+    
     public AccountVO() {
     	this.uuid = UUID.randomUUID().toString();
     }
@@ -76,14 +77,15 @@
         this.id = id;
     	this.uuid = UUID.randomUUID().toString();
     }
-
-    public AccountVO(String accountName, long domainId, String networkDomain, short type) {
+    
+    public AccountVO(String accountName, long domainId, String networkDomain, short type, String uuid, int regionId) {
         this.accountName = accountName;
         this.domainId = domainId;
         this.networkDomain = networkDomain;
         this.type = type;
         this.state = State.enabled;
-    	this.uuid = UUID.randomUUID().toString();
+        this.uuid = uuid;
+        this.regionId = regionId;
     }
 
     public void setNeedsCleanup(boolean value) {
@@ -99,7 +101,11 @@
         return id;
     }
 
-    @Override
+    public void setId(long id) {
+		this.id = id;
+	}
+
+	@Override
     public String getAccountName() {
         return accountName;
     }
@@ -176,4 +182,12 @@
     public void setUuid(String uuid) {
     	this.uuid = uuid;
     }
+
+	public int getRegionId() {
+		return regionId;
+	}
+
+	public void setRegionId(int regionId) {
+		this.regionId = regionId;
+	}
 }
diff --git a/core/src/com/cloud/user/UserVO.java b/core/src/com/cloud/user/UserVO.java
index 919f413..de7f31b 100644
--- a/core/src/com/cloud/user/UserVO.java
+++ b/core/src/com/cloud/user/UserVO.java
@@ -93,6 +93,9 @@
     @Column(name="uuid")
     private String uuid;
 
+    @Column(name="region_id")
+    private int regionId;
+    
     public UserVO() {
         this.uuid = UUID.randomUUID().toString();
     }
@@ -101,8 +104,8 @@
         this.id = id;
         this.uuid = UUID.randomUUID().toString();
     }
-
-    public UserVO(long accountId, String username, String password, String firstName, String lastName, String email, String timezone) {
+    
+    public UserVO(long accountId, String username, String password, String firstName, String lastName, String email, String timezone, String uuid, int regionId) {
         this.accountId = accountId;
         this.username = username;
         this.password = password;
@@ -111,9 +114,10 @@
         this.email = email;
         this.timezone = timezone;
         this.state = State.enabled;
-        this.uuid = UUID.randomUUID().toString();
+    	this.uuid = uuid;
+    	this.regionId = regionId;
     }
-
+    
     @Override
     public long getId() {
         return id;
@@ -261,4 +265,12 @@
     public void setUuid(String uuid) {
         this.uuid = uuid;
     }
+    
+	public int getRegionId() {
+		return regionId;
+	}
+
+	public void setRegionId(int regionId) {
+		this.regionId = regionId;
+	}
 }
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index 7b2fe2a..0ae4f0f 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -68,6 +68,7 @@
 import com.cloud.storage.snapshot.SnapshotSchedule;
 import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.user.Account;
+import com.cloud.user.AccountVO;
 import com.cloud.user.User;
 import com.cloud.user.UserAccount;
 import com.cloud.user.UserContext;
@@ -88,6 +89,7 @@
 import org.apache.cloudstack.api.ResponseGenerator;
 import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
 import org.apache.cloudstack.api.response.*;
+import org.apache.cloudstack.region.Region;
 import org.apache.log4j.Logger;
 
 import java.text.DecimalFormat;
@@ -2591,6 +2593,16 @@
         return response;
     }
 
+	@Override
+	public RegionResponse createRegionResponse(Region region) {
+		RegionResponse response = new RegionResponse();
+		response.setId(region.getId());
+		response.setName(region.getName());
+		response.setEndPoint(region.getEndPoint());
+		response.setObjectName("region");
+		return response;
+	}
+
     @Override
     public ResourceTagResponse createResourceTagResponse(ResourceTag resourceTag, boolean keyValueOnly) {
         ResourceTagJoinVO rto = ApiDBUtils.newResourceTagView(resourceTag);
@@ -2969,9 +2981,7 @@
         response.setObjectName("vpnconnection");
         return response;
     }
-
-
-
+    
     @Override
     public GuestOSResponse createGuestOSResponse(GuestOS guestOS) {
         GuestOSResponse response = new GuestOSResponse();
@@ -3010,5 +3020,4 @@
         return response;
     }
 
-
 }
diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
index b4612ae..714a500 100755
--- a/server/src/com/cloud/api/ApiServer.java
+++ b/server/src/com/cloud/api/ApiServer.java
@@ -105,6 +105,7 @@
 import com.cloud.api.response.ApiResponseSerializer;
 import org.apache.cloudstack.api.response.ExceptionResponse;
 import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.region.RegionManager;
 
 import com.cloud.async.AsyncCommandQueued;
 import com.cloud.async.AsyncJob;
@@ -161,6 +162,8 @@
 
     private Account _systemAccount = null;
     private User _systemUser = null;
+    @Inject private RegionManager _regionMgr = null;
+    
     private static int _workerCount = 0;
     private static ApiServer s_instance = null;
     private static final DateFormat _dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java
index 8939439..60f60df 100755
--- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java
+++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java
@@ -21,6 +21,11 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.cloudstack.region.RegionManagerImpl;
+import org.apache.cloudstack.region.RegionServiceImpl;
+import org.apache.cloudstack.region.dao.RegionDaoImpl;
+import org.apache.cloudstack.region.dao.RegionSyncDaoImpl;
+
 import com.cloud.agent.manager.ClusteredAgentManagerImpl;
 import com.cloud.alert.AlertManagerImpl;
 import com.cloud.alert.dao.AlertDaoImpl;
@@ -372,6 +377,7 @@
         addDao("NetworkServiceMapDao", NetworkServiceMapDaoImpl.class);
         addDao("StorageNetworkIpAddressDao", StorageNetworkIpAddressDaoImpl.class);
         addDao("StorageNetworkIpRangeDao", StorageNetworkIpRangeDaoImpl.class);
+        addDao("RegionDao", RegionDaoImpl.class);
         addDao("VpcDao", VpcDaoImpl.class);
         addDao("VpcOfferingDao", VpcOfferingDaoImpl.class);
         addDao("VpcOfferingServiceMapDao", VpcOfferingServiceMapDaoImpl.class);
@@ -401,6 +407,7 @@
         addDao("DiskOfferingJoinDao", DiskOfferingJoinDaoImpl.class);
         addDao("ServiceOfferingJoinDao", ServiceOfferingJoinDaoImpl.class);
         addDao("DataCenterJoinDao", DataCenterJoinDaoImpl.class);
+        addDao("RegionSyncDao", RegionSyncDaoImpl.class);
     }
 
     @Override
@@ -459,6 +466,8 @@
         addManager("StorageNetworkManager", StorageNetworkManagerImpl.class);
         addManager("ExternalLoadBalancerUsageManager", ExternalLoadBalancerUsageManagerImpl.class);
         addManager("HA Manager", HighAvailabilityManagerImpl.class);
+        addManager("Region Service", RegionServiceImpl.class);        
+        addManager("Region Manager", RegionManagerImpl.class);
         addManager("VPC Manager", VpcManagerImpl.class);
         addManager("VpcVirtualRouterManager", VpcVirtualNetworkApplianceManagerImpl.class);
         addManager("NetworkACLManager", NetworkACLManagerImpl.class);
diff --git a/server/src/com/cloud/domain/DomainVO.java b/server/src/com/cloud/domain/DomainVO.java
index bb4ce0c..346e19f 100644
--- a/server/src/com/cloud/domain/DomainVO.java
+++ b/server/src/com/cloud/domain/DomainVO.java
@@ -75,15 +75,12 @@
     @Column(name="uuid")
     private String uuid;
 
+    @Column(name="region_id")
+    private int regionId;
+    
     public DomainVO() {}
-
-    public DomainVO(long id, String name, long owner, Long parentId, String networkDomain) {
-        this(name, owner, parentId, networkDomain);
-        this.id = id;
-        this.uuid = UUID.randomUUID().toString();
-    }
-
-    public DomainVO(String name, long owner, Long parentId, String networkDomain) {
+    
+    public DomainVO(String name, long owner, Long parentId, String networkDomain, int regionId) {
     	this.parent = parentId;
         this.name = name;
         this.accountId = owner;
@@ -92,8 +89,21 @@
         this.state = Domain.State.Active;
         this.networkDomain = networkDomain;
         this.uuid = UUID.randomUUID().toString();
+        this.regionId = regionId;
     }
 
+    public DomainVO(String name, long owner, Long parentId, String networkDomain, String uuid, int regionId) {
+    	this.parent = parentId;
+        this.name = name;
+        this.accountId = owner;
+        this.path ="";
+        this.level = 0;
+        this.state = Domain.State.Active;
+        this.networkDomain = networkDomain;
+        this.uuid = uuid;
+        this.regionId = regionId;
+    }
+    
     @Override
     public long getId() {
         return id;
@@ -205,5 +215,13 @@
     public void setUuid(String uuid) {
     	this.uuid = uuid;
     }
+    
+	public int getRegionId() {
+		return regionId;
+	}
+
+	public void setRegionId(int regionId) {
+		this.regionId = regionId;
+	}
 }
 
diff --git a/server/src/com/cloud/domain/dao/DomainDaoImpl.java b/server/src/com/cloud/domain/dao/DomainDaoImpl.java
index 442b5e5..b3a1706 100644
--- a/server/src/com/cloud/domain/dao/DomainDaoImpl.java
+++ b/server/src/com/cloud/domain/dao/DomainDaoImpl.java
@@ -31,7 +31,6 @@
 import com.cloud.domain.DomainVO;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.GenericDaoBase;
-import com.cloud.utils.db.GlobalLock;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.Transaction;
@@ -270,4 +269,5 @@
         
         return parentDomains;
     }
+    
 }
diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java
index 15d3675..f65627e 100755
--- a/server/src/com/cloud/projects/ProjectManagerImpl.java
+++ b/server/src/com/cloud/projects/ProjectManagerImpl.java
@@ -205,9 +205,9 @@
         //Create an account associated with the project
         StringBuilder acctNm = new StringBuilder("PrjAcct-");
         acctNm.append(name).append("-").append(owner.getDomainId());
-
-        Account projectAccount = _accountMgr.createAccount(acctNm.toString(), Account.ACCOUNT_TYPE_PROJECT, domainId, null, null);
-
+        
+        Account projectAccount = _accountMgr.createAccount(acctNm.toString(), Account.ACCOUNT_TYPE_PROJECT, domainId, null, null, "", 0);
+        
         Project project = _projectDao.persist(new ProjectVO(name, displayText, owner.getDomainId(), projectAccount.getId()));
 
         //assign owner to the project
diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java
index b0abd04..2ae0843 100755
--- a/server/src/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/com/cloud/server/ConfigurationServerImpl.java
@@ -70,6 +70,10 @@
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.utils.script.Script;
+import com.cloud.uuididentity.dao.IdentityDao;
+
+import org.apache.cloudstack.region.RegionVO;
+import org.apache.cloudstack.region.dao.RegionDao;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.log4j.Logger;
 
@@ -102,6 +106,8 @@
     private final AccountDao _accountDao;
     private final ResourceCountDao _resourceCountDao;
     private final NetworkOfferingServiceMapDao _ntwkOfferingServiceMapDao;
+    private final IdentityDao _identityDao;
+    private final RegionDao _regionDao;
 
     public ConfigurationServerImpl() {
         ComponentLocator locator = ComponentLocator.getLocator(Name);
@@ -118,6 +124,8 @@
         _accountDao = locator.getDao(AccountDao.class);
         _resourceCountDao = locator.getDao(ResourceCountDao.class);
         _ntwkOfferingServiceMapDao = locator.getDao(NetworkOfferingServiceMapDao.class);
+        _identityDao = locator.getDao(IdentityDao.class);
+        _regionDao = locator.getDao(RegionDao.class);
     }
 
     @Override
@@ -206,6 +214,8 @@
             // Create default networks
             createDefaultNetworks();
 
+            createDefaultRegion();
+            
             // Create userIpAddress ranges
 
             // Update existing vlans with networkId
@@ -253,7 +263,6 @@
 
         // We should not update seed data UUID column here since this will be invoked in upgrade case as well.
         //updateUuids();
-
         // Set init to true
         _configDao.update("init", "Hidden", "true");
     }
@@ -306,6 +315,7 @@
 
     @DB
     protected void saveUser() {
+    	//ToDo: Add regionId to default users and accounts
         // insert system account
         String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id) VALUES (1, UUID(), 'system', '1', '1')";
         Transaction txn = Transaction.currentTxn();
@@ -1238,5 +1248,10 @@
 
         return svcProviders;
     }
+    
+    private void createDefaultRegion(){
+    	//Get Region name and URL from db.properties    	
+    	_regionDao.persist(new RegionVO(_regionDao.getRegionId(), "Local", "http://localhost:8080/client/api", "", ""));
+    }
 
 }
diff --git a/server/src/com/cloud/user/AccountManager.java b/server/src/com/cloud/user/AccountManager.java
index 9ca4721..4b3a601 100755
--- a/server/src/com/cloud/user/AccountManager.java
+++ b/server/src/com/cloud/user/AccountManager.java
@@ -20,6 +20,10 @@
 import java.util.Map;
 
 import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
+import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
+import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
+
 import com.cloud.api.query.vo.ControlledViewEntity;
 import com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.ResourceUnavailableException;
@@ -47,7 +51,7 @@
 
 	Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId);
 	
-	Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details);
+	Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid, int regionId);
 	
 	UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone);
 	
@@ -102,5 +106,94 @@
 
 	void buildACLSearchParameters(Account caller, Long id,
 			String accountName, Long projectId, List<Long> permittedAccounts, Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation);
-   
+	
+    /**
+     * Deletes a user by userId
+     *
+     * @param accountId
+     *            - id of the account do delete
+     *
+     * @return true if delete was successful, false otherwise
+     */
+    boolean deleteUserAccount(long accountId);
+    
+    /**
+     * Updates an account
+     *
+     * @param cmd
+     *            - the parameter containing accountId or account nameand domainId
+     * @return updated account object
+     */
+    Account updateAccount(UpdateAccountCmd cmd);
+    
+    /**
+     * Disables an account by accountName and domainId
+     *
+     * @param accountName
+     * @param domainId
+     * @param accountId
+     * @param disabled
+     *            account if success
+     * @return true if disable was successful, false otherwise
+     */
+    Account disableAccount(String accountName, Long domainId, Long accountId) throws ConcurrentOperationException, ResourceUnavailableException;
+    
+    /**
+     * Enables an account by accountId
+     *
+     * @param accountName
+     *            - the enableAccount command defining the accountId to be deleted.
+     * @param domainId
+     *            TODO
+     * @param accountId
+     * @return account object
+     */
+    Account enableAccount(String accountName, Long domainId, Long accountId); 
+    
+    /**
+     * Deletes user by Id
+     * @param deleteUserCmd
+     * @return
+     */
+    boolean deleteUser(DeleteUserCmd deleteUserCmd);
+    
+    /**
+     * Update a user by userId
+     *
+     * @param userId
+     * @return UserAccount object
+     */
+    UserAccount updateUser(UpdateUserCmd cmd);   
+    
+    /**
+     * Disables a user by userId
+     *
+     * @param userId
+     *            - the userId
+     * @return UserAccount object
+     */
+    UserAccount disableUser(long userId);
+    
+    /**
+     * Enables a user
+     *
+     * @param userId
+     *            - the userId
+     * @return UserAccount object
+     */
+    UserAccount enableUser(long userId);
+    
+    /**
+     * Locks an account by accountId. A locked account cannot access the API, but will still have running VMs/IP
+     * addresses
+     * allocated/etc.
+     *
+     * @param accountName
+     *            - the LockAccount command defining the accountId to be locked.
+     * @param domainId
+     *            TODO
+     * @param accountId
+     * @return account object
+     */
+    Account lockAccount(String accountName, Long domainId, Long accountId);    
 }
diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java
index 1f8334d..c5a8c75 100755
--- a/server/src/com/cloud/user/AccountManagerImpl.java
+++ b/server/src/com/cloud/user/AccountManagerImpl.java
@@ -53,6 +53,8 @@
 
 import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
 import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
+import org.apache.cloudstack.region.RegionManager;
+
 import com.cloud.configuration.Config;
 import com.cloud.configuration.ConfigurationManager;
 import com.cloud.configuration.ResourceLimit;
@@ -214,6 +216,8 @@
     @Inject
     private IPAddressDao _ipAddressDao;
     @Inject
+    private RegionManager _regionMgr;
+    
     private VpcManager _vpcMgr;
     @Inject
     private DomainRouterDao _routerDao;
@@ -766,7 +770,7 @@
     @DB
     @ActionEvent(eventType = EventTypes.EVENT_ACCOUNT_CREATE, eventDescription = "creating Account")
     public UserAccount createUserAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long domainId, String networkDomain,
-            Map<String, String> details) {
+            Map<String, String> details, String accountUUID, String userUUID, Integer regionId) {
 
         if (accountName == null) {
             accountName = userName;
@@ -808,29 +812,55 @@
             }
         }
 
-        Transaction txn = Transaction.currentTxn();
-        txn.start();
+        if(regionId == null){
+            Transaction txn = Transaction.currentTxn();
+            txn.start();
 
-        // create account
-        Account account = createAccount(accountName, accountType, domainId, networkDomain, details);
-        long accountId = account.getId();
+        	// create account
+        	AccountVO account = createAccount(accountName, accountType, domainId, networkDomain, details, UUID.randomUUID().toString(), _regionMgr.getId());
+        	long accountId = account.getId();
 
-        // create the first user for the account
-        UserVO user = createUser(accountId, userName, password, firstName, lastName, email, timezone);
+        	// create the first user for the account
+        	UserVO user = createUser(accountId, userName, password, firstName, lastName, email, timezone);
 
-        if (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
-            // set registration token
-            byte[] bytes = (domainId + accountName + userName + System.currentTimeMillis()).getBytes();
-            String registrationToken = UUID.nameUUIDFromBytes(bytes).toString();
-            user.setRegistrationToken(registrationToken);
+        	if (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
+        		// set registration token
+        		byte[] bytes = (domainId + accountName + userName + System.currentTimeMillis()).getBytes();
+        		String registrationToken = UUID.nameUUIDFromBytes(bytes).toString();
+        		user.setRegistrationToken(registrationToken);
+        	}
+        	txn.commit();
+        	//Propagate Add account to other Regions
+        	_regionMgr.propagateAddAccount(userName, password, firstName, lastName, email, timezone, accountName, accountType, domainId, 
+        			networkDomain, details, account.getUuid(), user.getUuid());
+        	//check success
+            return _userAccountDao.findById(user.getId());
+        } else {
+        	// Account is propagated from another Region
+
+        	Transaction txn = Transaction.currentTxn();
+            txn.start();
+
+            // create account
+            AccountVO account = createAccount(accountName, accountType, domainId, networkDomain, details, accountUUID, regionId);
+            long accountId = account.getId();
+
+            // create the first user for the account
+            UserVO user = createUser(accountId, userName, password, firstName, lastName, email, timezone, userUUID, regionId);
+
+            if (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) {
+                // set registration token
+                byte[] bytes = (domainId + accountName + userName + System.currentTimeMillis()).getBytes();
+                String registrationToken = UUID.nameUUIDFromBytes(bytes).toString();
+                user.setRegistrationToken(registrationToken);
+            }
+            txn.commit();
+            return _userAccountDao.findById(user.getId());
         }
-
-        txn.commit();
-        return _userAccountDao.findById(user.getId());
     }
 
     @Override
-    public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId) {
+    public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID, Integer regionId) {
 
         // default domain to ROOT if not specified
         if (domainId == null) {
@@ -858,9 +888,14 @@
         if (!_userAccountDao.validateUsernameInDomain(userName, domainId)) {
             throw new CloudRuntimeException("The user " + userName + " already exists in domain " + domainId);
         }
-
-        UserVO user = createUser(account.getId(), userName, password, firstName, lastName, email, timeZone);
-
+        UserVO user = null;
+        if(regionId == null){
+        	user = createUser(account.getId(), userName, password, firstName, lastName, email, timeZone);
+        	//Propagate Add user to peer Regions
+        	_regionMgr.propagateAddUser(userName, password, firstName, lastName, email, timeZone, accountName, domain.getUuid(), user.getUuid());
+        } else {
+        	user = createUser(account.getId(), userName, password, firstName, lastName, email, timeZone, userUUID, regionId);
+        }
         return user;
     }
 
@@ -1167,7 +1202,6 @@
 
             throw new InvalidParameterValueException("The account id=" + accountId + " manages project(s) with ids " + projectIds + "and can't be removed");
         }
-
         return deleteAccount(account, callerUserId, caller);
     }
 
@@ -1269,7 +1303,7 @@
         String newAccountName = cmd.getNewName();
         String networkDomain = cmd.getNetworkDomain();
         Map<String, String> details = cmd.getDetails();
-
+        
         boolean success = false;
         Account account = null;
         if (accountId != null) {
@@ -1649,7 +1683,7 @@
 
     @Override
     @DB
-    public Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details) {
+    public AccountVO createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid, int regionId) {
         // Validate domain
         Domain domain = _domainMgr.getDomain(domainId);
         if (domain == null) {
@@ -1693,7 +1727,7 @@
         Transaction txn = Transaction.currentTxn();
         txn.start();
 
-        Account account = _accountDao.persist(new AccountVO(accountName, domainId, networkDomain, accountType));
+        AccountVO account = _accountDao.persist(new AccountVO(accountName, domainId, networkDomain, accountType, uuid, regionId));
 
         if (account == null) {
             throw new CloudRuntimeException("Failed to create account name " + accountName + " in domain id=" + domainId);
@@ -1710,7 +1744,6 @@
 
         // Create default security group
         _networkGroupMgr.createDefaultSecurityGroup(accountId);
-
         txn.commit();
 
         return account;
@@ -1722,6 +1755,17 @@
         if (s_logger.isDebugEnabled()) {
             s_logger.debug("Creating user: " + userName + ", accountId: " + accountId + " timezone:" + timezone);
         }
+        
+        UserVO user = _userDao.persist(new UserVO(accountId, userName, password, firstName, lastName, email, timezone, UUID.randomUUID().toString(), _regionMgr.getId()));
+
+        return user;
+    }
+
+    //ToDo Add events??
+    public UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone, String uuid, int regionId) {
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Creating user: " + userName + ", accountId: " + accountId + " timezone:" + timezone);
+        }
 
         String encodedPassword = null;
         for (Enumeration<UserAuthenticator> en = _userAuthenticators.enumeration(); en.hasMoreElements();) {
@@ -1734,8 +1778,8 @@
         if (encodedPassword == null) {
         	throw new CloudRuntimeException("Failed to encode password");
         }
-
-        UserVO user = _userDao.persist(new UserVO(accountId, userName, encodedPassword, firstName, lastName, email, timezone));
+        
+        UserVO user = _userDao.persist(new UserVO(accountId, userName, encodedPassword, firstName, lastName, email, timezone, uuid, regionId));
 
         return user;
     }
@@ -1966,6 +2010,7 @@
 
     @Override @DB
     public String[] createApiKeyAndSecretKey(RegisterCmd cmd) {
+    	//Send keys to other Regions
         Long userId = cmd.getId();
 
         User user = getUserIncludingRemoved(userId);
@@ -2194,7 +2239,7 @@
         }
     }
 
-    @Override
+	@Override
     public void buildACLViewSearchBuilder(SearchBuilder<? extends ControlledViewEntity> sb, Long domainId,
             boolean isRecursive, List<Long> permittedAccounts, ListProjectResourcesCriteria listProjectResourcesCriteria) {
 
diff --git a/server/src/com/cloud/user/DomainManager.java b/server/src/com/cloud/user/DomainManager.java
index dae7241..af102e2 100644
--- a/server/src/com/cloud/user/DomainManager.java
+++ b/server/src/com/cloud/user/DomainManager.java
@@ -19,22 +19,15 @@
 import java.util.List;
 import java.util.Set;
 
+import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
+
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 
 public interface DomainManager extends DomainService {
     Set<Long> getDomainChildrenIds(String parentDomainPath);
 
-    Domain createDomain(String name, Long parentId, Long ownerId, String networkDomain);
-
-    /**
-     * find the domain by its path
-     * 
-     * @param domainPath
-     *            the path to use to lookup a domain
-     * @return domainVO the domain with the matching path, or null if no domain with the given path exists
-     */
-    DomainVO findDomainByPath(String domainPath);
+    Domain createDomain(String name, Long parentId, Long ownerId, String networkDomain, String domainUUID, Integer regionId);
 
     Set<Long> getDomainParentIds(long domainId);
 
@@ -43,5 +36,15 @@
     List<? extends Domain> findInactiveDomains();
 
     boolean deleteDomain(DomainVO domain, Boolean cleanup);
-
+    
+    boolean deleteDomain(long domainId, Boolean cleanup);
+    
+    /**
+     * update an existing domain
+     * 
+     * @param cmd
+     *            - the command containing domainId and new domainName
+     * @return Domain object if the command succeeded
+     */
+    Domain updateDomain(UpdateDomainCmd cmd);    
 }
diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java
index 791f581..6791c73 100644
--- a/server/src/com/cloud/user/DomainManagerImpl.java
+++ b/server/src/com/cloud/user/DomainManagerImpl.java
@@ -26,6 +26,8 @@
 
 import org.apache.cloudstack.api.command.admin.domain.ListDomainChildrenCmd;
 import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd;
+import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
+import org.apache.cloudstack.region.RegionManager;
 import org.apache.log4j.Logger;
 
 import com.cloud.configuration.ResourceLimit;
@@ -79,7 +81,9 @@
     private ProjectDao _projectDao;
     @Inject
     private ProjectManager _projectMgr;
-
+    @Inject
+    private RegionManager _regionMgr;
+    
     @Override
     public Domain getDomain(long domainId) {
         return _domainDao.findById(domainId);
@@ -134,7 +138,7 @@
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_DOMAIN_CREATE, eventDescription = "creating Domain")
-    public Domain createDomain(String name, Long parentId, String networkDomain) {
+    public Domain createDomain(String name, Long parentId, String networkDomain, String domainUUID, Integer regionId) {
         Account caller = UserContext.current().getCaller();
 
         if (parentId == null) {
@@ -152,13 +156,13 @@
 
         _accountMgr.checkAccess(caller, parentDomain);
 
-        return createDomain(name, parentId, caller.getId(), networkDomain);
+        return createDomain(name, parentId, caller.getId(), networkDomain, domainUUID, regionId);
 
     }
 
     @Override
     @DB
-    public Domain createDomain(String name, Long parentId, Long ownerId, String networkDomain) {
+    public Domain createDomain(String name, Long parentId, Long ownerId, String networkDomain, String domainUUID, Integer regionId) {
         // Verify network domain
         if (networkDomain != null) {
             if (!NetUtils.verifyDomainName(networkDomain)) {
@@ -177,15 +181,28 @@
             throw new InvalidParameterValueException("Domain with name " + name + " already exists for the parent id=" + parentId);
         }
 
-        Transaction txn = Transaction.currentTxn();
-        txn.start();
+        if(regionId == null){
+        	Transaction txn = Transaction.currentTxn();
+        	txn.start();
 
-        DomainVO domain = _domainDao.create(new DomainVO(name, ownerId, parentId, networkDomain));
-        _resourceCountDao.createResourceCounts(domain.getId(), ResourceLimit.ResourceOwnerType.Domain);
+        	DomainVO domain = _domainDao.create(new DomainVO(name, ownerId, parentId, networkDomain, _regionMgr.getId()));
+        	_resourceCountDao.createResourceCounts(domain.getId(), ResourceLimit.ResourceOwnerType.Domain);
+        	txn.commit();
+        	//Propagate domain creation to peer Regions
+        	_regionMgr.propagateAddDomain(name, parentId, networkDomain, domain.getUuid());        	
+        	return domain;
+        } else {
+        	Transaction txn = Transaction.currentTxn();
+        	txn.start();
 
-        txn.commit();
+        	DomainVO domain = _domainDao.create(new DomainVO(name, ownerId, parentId, networkDomain, domainUUID, regionId));
+        	_resourceCountDao.createResourceCounts(domain.getId(), ResourceLimit.ResourceOwnerType.Domain);
 
-        return domain;
+        	txn.commit();
+        	return domain;
+        	
+        }
+        
     }
 
     @Override
@@ -477,4 +494,97 @@
         return _domainDao.searchAndCount(sc, searchFilter);
     }
 
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_DOMAIN_UPDATE, eventDescription = "updating Domain")
+    @DB
+    public DomainVO updateDomain(UpdateDomainCmd cmd) {
+        Long domainId = cmd.getId();
+        String domainName = cmd.getDomainName();
+        String networkDomain = cmd.getNetworkDomain();
+
+        // check if domain exists in the system
+        DomainVO domain = _domainDao.findById(domainId);
+        if (domain == null) {
+        	InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find domain with specified domain id");
+        	ex.addProxyObject(domain, domainId, "domainId");            
+            throw ex;
+        } else if (domain.getParent() == null && domainName != null) {
+            // check if domain is ROOT domain - and deny to edit it with the new name
+            throw new InvalidParameterValueException("ROOT domain can not be edited with a new name");
+        }
+
+        // check permissions
+        Account caller = UserContext.current().getCaller();
+        _accountMgr.checkAccess(caller, domain);
+
+        // domain name is unique in the cloud
+        if (domainName != null) {
+            SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
+            sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
+            List<DomainVO> domains = _domainDao.search(sc, null);
+
+            boolean sameDomain = (domains.size() == 1 && domains.get(0).getId() == domainId);
+
+            if (!domains.isEmpty() && !sameDomain) {
+                InvalidParameterValueException ex = new InvalidParameterValueException("Failed to update specified domain id with name '" + domainName + "' since it already exists in the system");
+                ex.addProxyObject(domain, domainId, "domainId");                
+            	throw ex;
+            }
+        }
+
+        // validate network domain
+        if (networkDomain != null && !networkDomain.isEmpty()) {
+            if (!NetUtils.verifyDomainName(networkDomain)) {
+                throw new InvalidParameterValueException(
+                        "Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
+                                + "and the hyphen ('-'); can't start or end with \"-\"");
+            }
+        }
+
+        Transaction txn = Transaction.currentTxn();
+
+        txn.start();
+
+        if (domainName != null) {
+            String updatedDomainPath = getUpdatedDomainPath(domain.getPath(), domainName);
+            updateDomainChildren(domain, updatedDomainPath);
+            domain.setName(domainName);
+            domain.setPath(updatedDomainPath);
+        }
+
+        if (networkDomain != null) {
+            if (networkDomain.isEmpty()) {
+                domain.setNetworkDomain(null);
+            } else {
+                domain.setNetworkDomain(networkDomain);
+            }
+        }
+        _domainDao.update(domainId, domain);
+
+        txn.commit();
+
+        return _domainDao.findById(domainId);
+
+    }
+
+    private String getUpdatedDomainPath(String oldPath, String newName) {
+        String[] tokenizedPath = oldPath.split("/");
+        tokenizedPath[tokenizedPath.length - 1] = newName;
+        StringBuilder finalPath = new StringBuilder();
+        for (String token : tokenizedPath) {
+            finalPath.append(token);
+            finalPath.append("/");
+        }
+        return finalPath.toString();
+    }
+
+    private void updateDomainChildren(DomainVO domain, String updatedDomainPrefix) {
+        List<DomainVO> domainChildren = _domainDao.findAllChildren(domain.getPath(), domain.getId());
+        // for each child, update the path
+        for (DomainVO dom : domainChildren) {
+            dom.setPath(dom.getPath().replaceFirst(domain.getPath(), updatedDomainPrefix));
+            _domainDao.update(dom.getId(), dom);
+        }
+    }
+    
 }
diff --git a/server/src/com/cloud/user/dao/AccountDaoImpl.java b/server/src/com/cloud/user/dao/AccountDaoImpl.java
index 7300bb1..f7ad679 100755
--- a/server/src/com/cloud/user/dao/AccountDaoImpl.java
+++ b/server/src/com/cloud/user/dao/AccountDaoImpl.java
@@ -261,4 +261,5 @@
         	}
 		}
 	}
+	
 }
diff --git a/server/src/com/cloud/user/dao/UserAccountDaoImpl.java b/server/src/com/cloud/user/dao/UserAccountDaoImpl.java
index 663e58f..fc4166d 100644
--- a/server/src/com/cloud/user/dao/UserAccountDaoImpl.java
+++ b/server/src/com/cloud/user/dao/UserAccountDaoImpl.java
@@ -62,4 +62,5 @@
 		sc.setParameters("apiKey",apiKey);
 		return findOneBy(sc);
 	}
+	
 }
diff --git a/server/src/com/cloud/user/dao/UserDaoImpl.java b/server/src/com/cloud/user/dao/UserDaoImpl.java
index fefbb8a..e1f4a2e 100644
--- a/server/src/com/cloud/user/dao/UserDaoImpl.java
+++ b/server/src/com/cloud/user/dao/UserDaoImpl.java
@@ -122,4 +122,5 @@
         sc.setParameters("username", username);
         return listBy(sc);
 	}
+	
 }
diff --git a/server/src/org/apache/cloudstack/region/RegionAccount.java b/server/src/org/apache/cloudstack/region/RegionAccount.java
new file mode 100644
index 0000000..dba3101
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionAccount.java
@@ -0,0 +1,287 @@
+// 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.cloudstack.region;
+
+import com.cloud.user.AccountVO;
+
+public class RegionAccount extends AccountVO {
+    String accountUuid;
+    String domainUuid;
+	String domain;
+	String receivedbytes;
+	String sentbytes;
+	String vmlimit;
+	String vmtotal;
+	String vmavailable;
+	String iplimit;
+	String iptotal;
+	String ipavailable;
+	String volumelimit;
+	String volumetotal;
+	String volumeavailable;
+	String snapshotlimit;
+	String snapshottotal;
+	String snapshotavailable;
+	String templatelimit;
+	String templatetotal;
+	String templateavailable;
+	String vmstopped;
+	String vmrunning;
+	String projectlimit;
+	String projecttotal;
+	String projectavailable;
+	String networklimit;
+	String networktotal;
+	String networkavailable;
+	RegionUser user;
+
+	public RegionAccount() {
+    }
+    
+    public String getAccountuuid() {
+		return accountUuid;
+	}
+
+	public void setAccountuuid(String accountUuid) {
+		this.accountUuid = accountUuid;
+	}
+
+	public String getDomainUuid() {
+		return domainUuid;
+	}
+
+	public void setDomainUuid(String domainUuid) {
+		this.domainUuid = domainUuid;
+	}
+
+	public String getDomain() {
+		return domain;
+	}
+
+	public void setDomain(String domain) {
+		this.domain = domain;
+	}
+
+	public String getReceivedbytes() {
+		return receivedbytes;
+	}
+
+	public void setReceivedbytes(String receivedbytes) {
+		this.receivedbytes = receivedbytes;
+	}
+
+	public String getSentbytes() {
+		return sentbytes;
+	}
+
+	public void setSentbytes(String sentbytes) {
+		this.sentbytes = sentbytes;
+	}
+
+	public String getVmlimit() {
+		return vmlimit;
+	}
+
+	public void setVmlimit(String vmlimit) {
+		this.vmlimit = vmlimit;
+	}
+
+	public String getVmtotal() {
+		return vmtotal;
+	}
+
+	public void setVmtotal(String vmtotal) {
+		this.vmtotal = vmtotal;
+	}
+
+	public String getVmavailable() {
+		return vmavailable;
+	}
+
+	public void setVmavailable(String vmavailable) {
+		this.vmavailable = vmavailable;
+	}
+
+	public String getIplimit() {
+		return iplimit;
+	}
+
+	public void setIplimit(String iplimit) {
+		this.iplimit = iplimit;
+	}
+
+	public String getIptotal() {
+		return iptotal;
+	}
+
+	public void setIptotal(String iptotal) {
+		this.iptotal = iptotal;
+	}
+
+	public String getIpavailable() {
+		return ipavailable;
+	}
+
+	public void setIpavailable(String ipavailable) {
+		this.ipavailable = ipavailable;
+	}
+
+	public String getVolumelimit() {
+		return volumelimit;
+	}
+
+	public void setVolumelimit(String volumelimit) {
+		this.volumelimit = volumelimit;
+	}
+
+	public String getVolumetotal() {
+		return volumetotal;
+	}
+
+	public void setVolumetotal(String volumetotal) {
+		this.volumetotal = volumetotal;
+	}
+
+	public String getVolumeavailable() {
+		return volumeavailable;
+	}
+
+	public void setVolumeavailable(String volumeavailable) {
+		this.volumeavailable = volumeavailable;
+	}
+
+	public String getSnapshotlimit() {
+		return snapshotlimit;
+	}
+
+	public void setSnapshotlimit(String snapshotlimit) {
+		this.snapshotlimit = snapshotlimit;
+	}
+
+	public String getSnapshottotal() {
+		return snapshottotal;
+	}
+
+	public void setSnapshottotal(String snapshottotal) {
+		this.snapshottotal = snapshottotal;
+	}
+
+	public String getSnapshotavailable() {
+		return snapshotavailable;
+	}
+
+	public void setSnapshotavailable(String snapshotavailable) {
+		this.snapshotavailable = snapshotavailable;
+	}
+
+	public String getTemplatelimit() {
+		return templatelimit;
+	}
+
+	public void setTemplatelimit(String templatelimit) {
+		this.templatelimit = templatelimit;
+	}
+
+	public String getTemplatetotal() {
+		return templatetotal;
+	}
+
+	public void setTemplatetotal(String templatetotal) {
+		this.templatetotal = templatetotal;
+	}
+
+	public String getTemplateavailable() {
+		return templateavailable;
+	}
+
+	public void setTemplateavailable(String templateavailable) {
+		this.templateavailable = templateavailable;
+	}
+
+	public String getVmstopped() {
+		return vmstopped;
+	}
+
+	public void setVmstopped(String vmstopped) {
+		this.vmstopped = vmstopped;
+	}
+
+	public String getVmrunning() {
+		return vmrunning;
+	}
+
+	public void setVmrunning(String vmrunning) {
+		this.vmrunning = vmrunning;
+	}
+
+	public String getProjectlimit() {
+		return projectlimit;
+	}
+
+	public void setProjectlimit(String projectlimit) {
+		this.projectlimit = projectlimit;
+	}
+
+	public String getProjecttotal() {
+		return projecttotal;
+	}
+
+	public void setProjecttotal(String projecttotal) {
+		this.projecttotal = projecttotal;
+	}
+
+	public String getProjectavailable() {
+		return projectavailable;
+	}
+
+	public void setProjectavailable(String projectavailable) {
+		this.projectavailable = projectavailable;
+	}
+
+	public String getNetworklimit() {
+		return networklimit;
+	}
+
+	public void setNetworklimit(String networklimit) {
+		this.networklimit = networklimit;
+	}
+
+	public String getNetworktotal() {
+		return networktotal;
+	}
+
+	public void setNetworktotal(String networktotal) {
+		this.networktotal = networktotal;
+	}
+
+	public String getNetworkavailable() {
+		return networkavailable;
+	}
+
+	public void setNetworkavailable(String networkavailable) {
+		this.networkavailable = networkavailable;
+	}
+
+	public RegionUser getUser() {
+		return user;
+	}
+
+	public void setUser(RegionUser user) {
+		this.user = user;
+	}
+
+}
diff --git a/server/src/org/apache/cloudstack/region/RegionDomain.java b/server/src/org/apache/cloudstack/region/RegionDomain.java
new file mode 100644
index 0000000..df46198
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionDomain.java
@@ -0,0 +1,61 @@
+// 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.cloudstack.region;
+
+import com.cloud.domain.DomainVO;
+
+public class RegionDomain extends DomainVO {
+    String accountUuid;
+    String parentUuid;
+    String parentdomainname;
+    Boolean haschild;
+
+	public RegionDomain() {
+    }
+    
+    public String getAccountuuid() {
+		return accountUuid;
+	}
+
+	public void setAccountuuid(String accountUuid) {
+		this.accountUuid = accountUuid;
+	}
+
+	public String getParentUuid() {
+		return parentUuid;
+	}
+
+	public void setParentUuid(String parentUuid) {
+		this.parentUuid = parentUuid;
+	}
+
+	public String getParentdomainname() {
+		return parentdomainname;
+	}
+
+	public void setParentdomainname(String parentdomainname) {
+		this.parentdomainname = parentdomainname;
+	}
+
+	public Boolean getHaschild() {
+		return haschild;
+	}
+
+	public void setHaschild(Boolean haschild) {
+		this.haschild = haschild;
+	}
+}
diff --git a/server/src/org/apache/cloudstack/region/RegionManager.java b/server/src/org/apache/cloudstack/region/RegionManager.java
new file mode 100644
index 0000000..56bdb9b
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionManager.java
@@ -0,0 +1,216 @@
+// 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.cloudstack.region;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
+import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
+import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
+import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
+
+import com.cloud.domain.Domain;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.UserAccount;
+
+public interface RegionManager {
+	
+	/**
+	 * Propagates Account details to peer Regions
+	 * @param userName
+	 * @param password
+	 * @param firstName
+	 * @param lastName
+	 * @param email
+	 * @param timezone
+	 * @param accountName
+	 * @param accountType
+	 * @param domainId
+	 * @param networkDomain
+	 * @param details
+	 * @param accountUUID
+	 * @param userUUID
+	 * @return
+	 */
+	public boolean propagateAddAccount(String userName, String password, String firstName, String lastName, String email, String timezone, String accountName, short accountType, Long domainId, String networkDomain,
+            Map<String, String> details, String accountUUID, String userUUID);
+	
+	/**
+	 * Returns the Id of local Region
+	 * @return
+	 */
+	public int getId();
+	
+	/**
+	 * Propagates User details to peer Regions
+	 * @param userName
+	 * @param password
+	 * @param firstName
+	 * @param lastName
+	 * @param email
+	 * @param timeZone
+	 * @param accountName
+	 * @param domainUUId
+	 * @param userUUID
+	 */
+	public void propagateAddUser(String userName, String password,
+			String firstName, String lastName, String email, String timeZone,
+			String accountName, String domainUUId, String userUUID);
+	
+	/**
+	 * Propagates Domain details to peer Regions
+	 * @param name
+	 * @param parentId
+	 * @param networkDomain
+	 * @param uuid
+	 */
+	public void propagateAddDomain(String name, Long parentId, String networkDomain, String uuid);
+	
+	
+	/**
+	 * Adds a peer Region to the local Region
+	 * @param id
+	 * @param name 
+	 * @param endPoint
+	 * @param apiKey
+	 * @param secretKey
+	 * @return Returns added Region object
+	 */
+	Region addRegion(int id, String name, String endPoint, String apiKey, String secretKey);
+	
+	/**
+	 * Update details of the Region with specified Id
+	 * @param id
+	 * @param name
+	 * @param endPoint
+	 * 
+	 * @param apiKey
+	 * @param secretKey
+	 * @return Returns update Region object
+	 */
+	Region updateRegion(int id, String name, String endPoint, String apiKey, String secretKey);
+	
+	/**
+	 * @param id
+	 * @return True if region is successfully removed
+	 */
+	boolean removeRegion(int id);
+	
+	/** List all Regions or by Id/Name
+	 * @param id
+	 * @param name
+	 * @return List of Regions
+	 */
+	List<RegionVO> listRegions(Integer id, String name);
+	
+    /**
+     * Deletes a user by userId and propagates the change to peer Regions
+     *
+     * @param accountId
+     *            - id of the account do delete
+     *
+     * @return true if delete was successful, false otherwise
+     */
+	boolean deleteUserAccount(long accountId);
+	
+    /**
+     * Updates an account
+     * isPopagate falg is set to true if sent from peer Region 
+     *
+     * @param cmd
+     *            - the parameter containing accountId or account nameand domainId
+     * @return updated account object
+     */
+    Account updateAccount(UpdateAccountCmd cmd);
+    
+	/**
+	 * Disables an account by accountName and domainId or accountId
+	 * @param accountName
+	 * @param domainId
+	 * @param id
+	 * @param lockRequested
+	 * @return
+	 * @throws ConcurrentOperationException
+	 * @throws ResourceUnavailableException
+	 */
+	Account disableAccount(String accountName, Long domainId, Long id, Boolean lockRequested) throws ConcurrentOperationException, ResourceUnavailableException;
+	
+    /**
+     * Enables an account by accountId
+     *
+     * @param accountName
+     *            - the enableAccount command defining the accountId to be deleted.
+     * @param domainId
+     *            TODO
+     * @param accountId
+     * @return account object
+     */
+    Account enableAccount(String accountName, Long domainId, Long accountId); 	
+    
+    /**
+     * Deletes user by Id
+     * @param deleteUserCmd
+     * @return
+     */
+    boolean deleteUser(DeleteUserCmd deleteUserCmd);
+    
+    /**
+     * update an existing domain
+     * 
+     * @param cmd
+     *            - the command containing domainId and new domainName
+     * @return Domain object if the command succeeded
+     */
+	Domain updateDomain(UpdateDomainCmd updateDomainCmd);    
+    
+	/**
+	 * Deletes domain by Id
+	 * @param id
+	 * @param cleanup
+	 * @return true if delete was successful, false otherwise
+	 */
+	boolean deleteDomain(Long id, Boolean cleanup);
+	
+    /**
+     * Update a user by userId
+     *
+     * @param userId
+     * @return UserAccount object
+     */
+	UserAccount updateUser(UpdateUserCmd updateUserCmd);
+	
+    /**
+     * Disables a user by userId
+     *
+     * @param userId
+     *            - the userId
+     * @return UserAccount object
+     */	
+	UserAccount disableUser(Long id);
+	
+    /**
+     * Enables a user
+     *
+     * @param userId
+     *            - the userId
+     * @return UserAccount object
+     */
+    UserAccount enableUser(long userId);
+}
diff --git a/server/src/org/apache/cloudstack/region/RegionManagerImpl.java b/server/src/org/apache/cloudstack/region/RegionManagerImpl.java
new file mode 100755
index 0000000..cac5a68
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionManagerImpl.java
@@ -0,0 +1,876 @@
+// 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.cloudstack.region;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
+import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
+import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
+import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
+import org.apache.cloudstack.region.dao.RegionDao;
+import org.apache.cloudstack.region.dao.RegionSyncDao;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.log4j.Logger;
+
+import com.cloud.domain.Domain;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.AccountVO;
+import com.cloud.user.DomainManager;
+import com.cloud.user.UserAccount;
+import com.cloud.user.UserVO;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.user.dao.UserAccountDao;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.component.Manager;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.uuididentity.dao.IdentityDao;
+
+@Local(value = { RegionManager.class })
+public class RegionManagerImpl implements RegionManager, Manager{
+    public static final Logger s_logger = Logger.getLogger(RegionManagerImpl.class);
+    
+    @Inject
+    RegionDao _regionDao;
+    @Inject
+    AccountDao _accountDao;
+    @Inject
+    private AccountManager _accountMgr;
+    @Inject
+    private UserDao _userDao;
+    @Inject
+    private DomainDao _domainDao;
+    @Inject
+    private DomainManager _domainMgr;
+    @Inject
+    private UserAccountDao _userAccountDao;    
+    @Inject
+    private IdentityDao _identityDao;
+    @Inject
+    private RegionSyncDao _regionSyncDao;
+    
+    private String _name;
+    private int _id; 
+    
+    @Override
+    public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
+        _name = name;
+        _id = _regionDao.getRegionId();
+        return true;
+    }
+    
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+	public int getId() {
+		return _id;
+	}
+
+	/* 
+	 * Propagates Account creation to peer Regions
+	 * Adds an entry in region_sync table on failure
+	 */
+	@Override
+	public boolean propagateAddAccount(String userName, String password, String firstName, String lastName, String email, String timezone, 
+			String accountName, short accountType, Long domainId, String networkDomain, Map<String, String> details, String accountUUID, String userUUID) {
+		String command = "createAccount";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.USERNAME, userName));
+		params.add(new NameValuePair(ApiConstants.PASSWORD, password));
+		params.add(new NameValuePair(ApiConstants.FIRSTNAME, firstName));
+		params.add(new NameValuePair(ApiConstants.LASTNAME, lastName));
+		params.add(new NameValuePair(ApiConstants.EMAIL, email));
+		params.add(new NameValuePair(ApiConstants.TIMEZONE, timezone));
+		params.add(new NameValuePair(ApiConstants.ACCOUNT, accountName));
+		params.add(new NameValuePair(ApiConstants.ACCOUNT_TYPE, ""+accountType));
+		//ToDo: use domain UUID
+		params.add(new NameValuePair(ApiConstants.DOMAIN_ID, ((domainId != null) ? domainId.toString() : "")));
+		params.add(new NameValuePair(ApiConstants.NETWORK_DOMAIN, networkDomain));
+		params.add(new NameValuePair(ApiConstants.ACCOUNT_DETAILS, (details != null) ? details.toString() : ""));
+		params.add(new NameValuePair(ApiConstants.ACCOUNT_ID, accountUUID));
+		params.add(new NameValuePair(ApiConstants.USER_ID, userUUID));
+		params.add(new NameValuePair(ApiConstants.REGION_ID, ""+getId()));
+
+		List<RegionVO> regions =  _regionDao.listAll();
+		for (Region region : regions){
+			if(region.getId() == getId()){
+				continue;
+			}
+			s_logger.debug("Adding account :"+accountName+" to Region: "+region.getId());
+			if (RegionsApiUtil.makeAPICall(region, command, params)) {
+				s_logger.debug("Successfully added account :"+accountName+" to Region: "+region.getId());
+			} else {
+				// api call failed. Add entry in region_sync table
+				addRegionSyncItem(region.getId(), command, params);
+				s_logger.error("Error while Adding account :"+accountName+" to Region: "+region.getId());
+			}
+		}
+		return true;
+	}
+
+	/* 
+	 * Propagates User creation to peer Regions
+	 * Adds an entry in region_sync table on failure
+	 */
+	@Override
+	public void propagateAddUser(String userName, String password,
+			String firstName, String lastName, String email, String timezone,
+			String accountName, String domainUUId, String userUUID) {
+		
+        String command = "createUser";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.USERNAME, userName));
+		params.add(new NameValuePair(ApiConstants.PASSWORD, password));
+		params.add(new NameValuePair(ApiConstants.FIRSTNAME, firstName));
+		params.add(new NameValuePair(ApiConstants.LASTNAME, lastName));
+		params.add(new NameValuePair(ApiConstants.EMAIL, email));
+		params.add(new NameValuePair(ApiConstants.TIMEZONE, timezone));
+		params.add(new NameValuePair(ApiConstants.ACCOUNT, accountName));		
+		params.add(new NameValuePair(ApiConstants.DOMAIN_ID, domainUUId));
+		params.add(new NameValuePair(ApiConstants.USER_ID, userUUID));
+		params.add(new NameValuePair(ApiConstants.REGION_ID, ""+getId()));
+		
+		List<RegionVO> regions =  _regionDao.listAll();
+		for (Region region : regions){
+			if(region.getId() == getId()){
+				continue;
+			}
+			s_logger.debug("Adding account :"+accountName+" to Region: "+region.getId());
+			if (RegionsApiUtil.makeAPICall(region, command, params)) {
+				s_logger.debug("Successfully added user :"+userName+" to Region: "+region.getId());
+			} else {
+				// api call failed. Add entry in region_sync table				
+				addRegionSyncItem(region.getId(), command, params);
+				s_logger.error("Error while Adding user :"+userName+" to Region: "+region.getId());
+			}
+		}
+		return;		
+	}
+	
+	/* 
+	 * Propagates Domain creation details to peer Regions
+	 * Adds an entry in region_sync table on failure
+	 */
+	@Override
+	public void propagateAddDomain(String name, Long parentId, String networkDomain, String uuid) {
+		
+        String command = "createDomain";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.NAME, name));
+		if(parentId != null){
+			DomainVO domain = _domainDao.findById(parentId);
+			if(domain != null){
+				params.add(new NameValuePair(ApiConstants.PARENT_DOMAIN_ID, domain.getUuid()));
+			}
+		}
+		params.add(new NameValuePair(ApiConstants.NETWORK_DOMAIN, networkDomain));
+		params.add(new NameValuePair(ApiConstants.DOMAIN_ID, uuid));
+		params.add(new NameValuePair(ApiConstants.REGION_ID, ""+getId()));
+		
+		List<RegionVO> regions =  _regionDao.listAll();
+		for (Region region : regions){
+			if(region.getId() == getId()){
+				continue;
+			}
+			s_logger.debug("Adding domain :"+name+" to Region: "+region.getId());
+			if (RegionsApiUtil.makeAPICall(region, command, params)) {
+				s_logger.debug("Successfully added domain :"+name+" to Region: "+region.getId());
+			} else {
+				// api call failed. Add entry in region_sync table				
+				addRegionSyncItem(region.getId(), command, params);
+				s_logger.error("Error while Adding domain :"+name+" to Region: "+region.getId());
+			}
+		}
+		return;		
+	}
+	
+	/**
+	 * Adds an entry to region_sync table
+	 * Entry contains region Id along with failed api
+	 * @param regionId
+	 * @param command
+	 * @param params
+	 */
+	private void addRegionSyncItem(int regionId, String command, List<NameValuePair> params){
+		String api = RegionsApiUtil.buildParams(command, params);
+		RegionSyncVO sync = new RegionSyncVO(regionId, api);
+		if(_regionSyncDao.persist(sync) == null){
+			s_logger.error("Failed to add Region Sync Item. RegionId: "+regionId + "API command: "+api);
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public Region addRegion(int id, String name, String endPoint, String apiKey, String secretKey) {
+		//Region Id should be unique
+		if( _regionDao.findById(id) != null ){
+			throw new InvalidParameterValueException("Region with id: "+id+" already exists");
+		}
+		//Region Name should be unique
+		if( _regionDao.findByName(name) != null ){
+			throw new InvalidParameterValueException("Region with name: "+name+" already exists");
+		}
+		RegionVO region = new RegionVO(id, name, endPoint, apiKey, secretKey);
+		return _regionDao.persist(region);
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public Region updateRegion(int id, String name, String endPoint, String apiKey, String secretKey) {
+		RegionVO region = _regionDao.findById(id);
+		
+		if(region == null){
+			throw new InvalidParameterValueException("Region with id: "+id+" does not exist");
+		}
+		
+		//Ensure region name is unique
+		if(name != null){
+			RegionVO region1 = _regionDao.findByName(name);
+			if(region1 != null && id != region1.getId()){
+				throw new InvalidParameterValueException("Region with name: "+name+" already exists");	
+			}
+		}
+		
+		if(name != null){
+			region.setName(name);
+		}
+		
+		if(endPoint != null){
+			region.setEndPoint(endPoint);
+		}
+		
+		if(apiKey != null){
+			region.setApiKey(apiKey);
+		}
+		
+		if(secretKey != null){
+			region.setSecretKey(secretKey);
+		}
+		
+		_regionDao.update(id, region);
+		return _regionDao.findById(id);
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public boolean removeRegion(int id) {
+		RegionVO region = _regionDao.findById(id);
+		if(region == null){
+			throw new InvalidParameterValueException("Failed to delete Region: " + id + ", Region not found");
+		}		
+		return _regionDao.remove(id);
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public List<RegionVO> listRegions(Integer id, String name) {
+		List<RegionVO> regions = new ArrayList<RegionVO>();
+		if(id != null){
+			RegionVO region = _regionDao.findById(id);
+			if(region != null){
+				regions.add(region);
+			} 
+			return regions;
+		}
+		if(name != null){
+			RegionVO region = _regionDao.findByName(name);
+			if(region != null){
+				regions.add(region);
+			} 
+			return regions;
+		}
+		return _regionDao.listAll();
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public boolean deleteUserAccount(long accountId) {
+		AccountVO account = _accountDao.findById(accountId);
+		if(account == null){
+			throw new InvalidParameterValueException("The specified account does not exist in the system");
+		}
+		String accountUUID = account.getUuid();
+		int regionId = account.getRegionId();
+		
+		String command = "deleteAccount";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.ID, accountUUID));
+
+		if(getId() == regionId){
+			if(_accountMgr.deleteUserAccount(accountId)){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully deleted account :"+accountUUID+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while deleting account :"+accountUUID+" in Region: "+region.getId());
+					}
+				}
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			//First delete in the Region where account is created
+			Region region = _regionDao.findById(regionId);
+			if (RegionsApiUtil.makeAPICall(region, command, params)) {
+				s_logger.debug("Successfully deleted account :"+accountUUID+" in Region: "+region.getId());
+				return true;
+			} else {
+				s_logger.error("Error while deleting account :"+accountUUID+" in Region: "+region.getId());
+				return false;
+			}
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public Account updateAccount(UpdateAccountCmd cmd) {
+        Long accountId = cmd.getId();
+        Long domainId = cmd.getDomainId();
+        DomainVO domain = _domainDao.findById(domainId);
+        String accountName = cmd.getAccountName();
+        String newAccountName = cmd.getNewName();
+        String networkDomain = cmd.getNetworkDomain();
+        //ToDo send details
+        Map<String, String> details = cmd.getDetails();		
+        
+        Account account = null;
+        if (accountId != null) {
+            account = _accountDao.findById(accountId);
+        } else {
+            account = _accountDao.findEnabledAccount(accountName, domainId);
+        }
+        
+        // Check if account exists
+        if (account == null || account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+            s_logger.error("Unable to find account by accountId: " + accountId + " OR by name: " + accountName + " in domain " + domainId);
+            throw new InvalidParameterValueException("Unable to find account by accountId: " + accountId + " OR by name: " + accountName + " in domain " + domainId);
+        }	
+
+        String command = "updateAccount";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.NEW_NAME, newAccountName));
+		params.add(new NameValuePair(ApiConstants.ID, account.getUuid()));
+		params.add(new NameValuePair(ApiConstants.ACCOUNT, accountName));
+		params.add(new NameValuePair(ApiConstants.DOMAIN_ID, domain.getUuid()));
+		params.add(new NameValuePair(ApiConstants.NETWORK_DOMAIN, networkDomain));
+		params.add(new NameValuePair(ApiConstants.NEW_NAME, newAccountName));
+		if(details != null){
+			params.add(new NameValuePair(ApiConstants.ACCOUNT_DETAILS, details.toString()));
+		}
+		int regionId = account.getRegionId();
+		if(getId() == regionId){
+			Account updatedAccount = _accountMgr.updateAccount(cmd);
+			if(updatedAccount != null){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully updated account :"+account.getUuid()+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while updating account :"+account.getUuid()+" in Region: "+region.getId());
+					}
+				}
+			}
+			return updatedAccount;
+		} else {
+			//First update in the Region where account is created
+			Region region = _regionDao.findById(regionId);
+			RegionAccount updatedAccount = RegionsApiUtil.makeAccountAPICall(region, command, params);
+			if (updatedAccount != null) {
+				Long id = _identityDao.getIdentityId("account", updatedAccount.getUuid());
+				updatedAccount.setId(id);
+				Long domainID = _identityDao.getIdentityId("domain", updatedAccount.getDomainUuid());
+				updatedAccount.setDomainId(domainID);
+				s_logger.debug("Successfully updated account :"+account.getUuid()+" in source Region: "+region.getId());
+				return updatedAccount;
+			} else {
+				throw new CloudRuntimeException("Error while updating account :"+account.getUuid()+" in source Region: "+region.getId());
+			}
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public Account disableAccount(String accountName, Long domainId, Long accountId, Boolean lockRequested) throws ConcurrentOperationException, ResourceUnavailableException {
+		Account account = null;
+        if (accountId != null) {
+            account = _accountDao.findById(accountId);
+        } else {
+            account = _accountDao.findActiveAccount(accountName, domainId);
+        }
+
+        if (account == null || account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+            throw new InvalidParameterValueException("Unable to find active account by accountId: " + accountId + " OR by name: " + accountName + " in domain " + domainId);
+        }	
+        
+		String accountUUID = account.getUuid();
+		
+		String command = "disableAccount";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.LOCK, lockRequested.toString()));
+		params.add(new NameValuePair(ApiConstants.ID, accountUUID));
+		DomainVO domain = _domainDao.findById(domainId);
+		if(domain != null){		
+			params.add(new NameValuePair(ApiConstants.DOMAIN_ID, domain.getUuid()));
+		}
+		
+		int regionId = account.getRegionId();
+		if(getId() == regionId){
+			Account retAccount = null;
+			if(lockRequested){
+				retAccount = _accountMgr.lockAccount(accountName, domainId, accountId);
+			} else {
+				retAccount = _accountMgr.disableAccount(accountName, domainId, accountId);
+			}
+			if(retAccount != null){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully disabled account :"+accountUUID+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while disabling account :"+accountUUID+" in Region: "+region.getId());
+					}
+				}
+			}
+			return retAccount;
+		} else {
+			//First disable account in the Region where account is created
+			Region region = _regionDao.findById(regionId);
+			Account retAccount = RegionsApiUtil.makeAccountAPICall(region, command, params);
+			if (retAccount != null) {
+				s_logger.debug("Successfully disabled account :"+accountUUID+" in source Region: "+region.getId());
+				return retAccount;
+			} else {
+				throw new CloudRuntimeException("Error while disabling account :"+accountUUID+" in source Region: "+region.getId());
+			}
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public Account enableAccount(String accountName, Long domainId, Long accountId) {
+        // Check if account exists
+        Account account = null;
+        if (accountId != null) {
+            account = _accountDao.findById(accountId);
+        } else {
+            account = _accountDao.findActiveAccount(accountName, domainId);
+        }
+
+        if (account == null || account.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+            throw new InvalidParameterValueException("Unable to find account by accountId: " + accountId + " OR by name: " + accountName + " in domain " + domainId);
+        }	
+        
+        String accountUUID = account.getUuid();
+        
+        String command = "enableAccount";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.ID, accountUUID));
+		params.add(new NameValuePair(ApiConstants.ACCOUNT, accountName));
+        DomainVO domain = _domainDao.findById(domainId);
+		if(domain != null){
+			params.add(new NameValuePair(ApiConstants.DOMAIN_ID, domain.getUuid()));
+		}
+		
+		int regionId = account.getRegionId();
+		if(getId() == regionId){
+			Account retAccount = _accountMgr.enableAccount(accountName, domainId, accountId);
+			if(retAccount != null){
+				List<RegionVO> regions =  _regionDao.listAll();
+
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully enabled account :"+accountUUID+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while enabling account :"+accountUUID+" in Region: "+region.getId());
+					}
+				}
+			}
+			return retAccount;
+		} else {
+			//First disable account in the Region where account is created
+			Region region = _regionDao.findById(regionId);
+			Account retAccount = RegionsApiUtil.makeAccountAPICall(region, command, params);
+			if (retAccount != null) {
+				s_logger.debug("Successfully enabled account :"+accountUUID+" in source Region: "+region.getId());
+				return retAccount;
+			} else {
+				throw new CloudRuntimeException("Error while enabling account :"+accountUUID+" in source Region: "+region.getId());
+			}
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public boolean deleteUser(DeleteUserCmd cmd) {
+        long id = cmd.getId();
+
+        UserVO user = _userDao.findById(id);
+
+        if (user == null) {
+            throw new InvalidParameterValueException("The specified user doesn't exist in the system");
+        }	
+        
+		String userUUID = user.getUuid();
+		int regionId = user.getRegionId();
+		
+		String command = "deleteUser";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.ID, userUUID));
+		
+		if(getId() == regionId){
+			if(_accountMgr.deleteUser(cmd)){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully deleted user :"+userUUID+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while deleting account :"+userUUID+" in Region: "+region.getId());
+					}
+				}
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			//First delete in the Region where account is created
+			Region region = _regionDao.findById(regionId);
+			if (RegionsApiUtil.makeAPICall(region, command, params)) {
+				s_logger.debug("Successfully deleted user :"+userUUID+" in source Region: "+region.getId());
+				return true;
+			} else {
+				s_logger.error("Error while deleting user :"+userUUID+" in source Region: "+region.getId());
+				return false;
+			}
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public Domain updateDomain(UpdateDomainCmd cmd) {
+		long id = cmd.getId();
+		DomainVO domain = _domainDao.findById(id);
+		if(domain == null){
+			throw new InvalidParameterValueException("The specified domain doesn't exist in the system");
+		}	
+		
+		String domainUUID = domain.getUuid();
+		
+		String command = "updateDomain";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.ID, domainUUID));
+		params.add(new NameValuePair(ApiConstants.NAME, cmd.getDomainName()));
+		params.add(new NameValuePair(ApiConstants.NETWORK_DOMAIN, cmd.getNetworkDomain()));
+		
+		int regionId = domain.getRegionId();
+		if(getId() == regionId){
+			Domain updatedDomain = _domainMgr.updateDomain(cmd);
+			if(updatedDomain != null){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully updated updatedDomain :"+domainUUID+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while updating updatedDomain :"+domainUUID+" in Region: "+region.getId());
+					}
+				}
+			}
+			return updatedDomain;
+		} else {
+			//First update in the Region where domain was created
+			Region region = _regionDao.findById(regionId);
+			RegionDomain updatedDomain = RegionsApiUtil.makeDomainAPICall(region, command, params);
+			if (updatedDomain != null) {
+				Long parentId = _identityDao.getIdentityId("domain", updatedDomain.getParentUuid());
+				updatedDomain.setParent(parentId);
+				s_logger.debug("Successfully updated user :"+domainUUID+" in source Region: "+region.getId());
+				return (DomainVO)updatedDomain;
+			} else {
+				throw new CloudRuntimeException("Error while updating user :"+domainUUID+" in source Region: "+region.getId());
+			}
+		}
+	}
+	
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public boolean deleteDomain(Long id, Boolean cleanup) {
+		DomainVO domain = _domainDao.findById(id);
+		if(domain == null){
+			throw new InvalidParameterValueException("The specified domain doesn't exist in the system");
+		}	
+		
+		String domainUUID = domain.getUuid();
+		
+		String command = "deleteDomain";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.ID, domainUUID));
+		params.add(new NameValuePair(ApiConstants.CLEANUP, cleanup.toString()));
+		
+        int regionId = domain.getRegionId();
+		if(getId() == regionId){
+			if(_domainMgr.deleteDomain(id, cleanup)){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully deleted domain :"+domainUUID+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while deleting domain :"+domainUUID+" in Region: "+region.getId());
+					}
+				}
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			//First delete in the Region where domain is created
+			Region region = _regionDao.findById(regionId);
+			if (RegionsApiUtil.makeAPICall(region, command, params)) {
+				s_logger.debug("Successfully deleted domain :"+domainUUID+" in Region: "+region.getId());
+				return true;
+			} else {
+				s_logger.error("Error while deleting domain :"+domainUUID+" in Region: "+region.getId());
+				return false;
+			}
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public UserAccount updateUser(UpdateUserCmd cmd) {
+        long id = cmd.getId();
+
+        UserVO user = _userDao.findById(id);
+        if (user == null) {
+            throw new InvalidParameterValueException("The specified user doesn't exist in the system");
+        }	
+        
+		String userUUID = user.getUuid();
+		
+		String command = "updateUser";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.ID, userUUID));
+		params.add(new NameValuePair(ApiConstants.API_KEY, cmd.getApiKey()));
+		params.add(new NameValuePair(ApiConstants.EMAIL, cmd.getEmail()));
+		params.add(new NameValuePair(ApiConstants.FIRSTNAME, cmd.getFirstname()));
+		params.add(new NameValuePair(ApiConstants.LASTNAME, cmd.getLastname()));
+		params.add(new NameValuePair(ApiConstants.PASSWORD, cmd.getPassword()));
+		params.add(new NameValuePair(ApiConstants.SECRET_KEY, cmd.getSecretKey()));
+		params.add(new NameValuePair(ApiConstants.TIMEZONE, cmd.getTimezone()));
+		params.add(new NameValuePair(ApiConstants.USERNAME, cmd.getUsername()));
+		
+		int regionId = user.getRegionId();
+		if(getId() == regionId){
+			UserAccount updateUser = _accountMgr.updateUser(cmd);
+			if(updateUser != null){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully updated user :"+userUUID+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while updating user :"+userUUID+" in Region: "+region.getId());
+					}
+				}
+			}
+			return updateUser;
+		} else {
+			//First update in the Region where user was created
+			Region region = _regionDao.findById(regionId);
+			UserAccount updateUser = RegionsApiUtil.makeUserAccountAPICall(region, command, params);
+			if (updateUser != null) {
+				s_logger.debug("Successfully updated user :"+userUUID+" in source Region: "+region.getId());
+				return updateUser;
+			} else {
+				throw new CloudRuntimeException("Error while updating user :"+userUUID+" in source Region: "+region.getId());
+			}
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public UserAccount disableUser(Long userId) {
+        UserVO user = _userDao.findById(userId);
+        if (user == null || user.getRemoved() != null) {
+            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
+        }        
+        
+        int regionId = user.getRegionId();
+        
+        String command = "disableUser";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.ID, user.getUuid()));
+        
+		if(getId() == regionId){
+			UserAccount disabledUser = _accountMgr.disableUser(userId);
+			if(disabledUser != null){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully disabled user :"+user.getUuid()+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while disabling user :"+user.getUuid()+" in Region: "+region.getId());
+					}
+				}
+			}
+			return disabledUser;
+		} else {
+			//First disable in the Region where user was created
+			Region region = _regionDao.findById(regionId);
+			UserAccount disabledUser = RegionsApiUtil.makeUserAccountAPICall(region, command, params);
+			if (disabledUser != null) {
+				s_logger.debug("Successfully disabled user :"+user.getUuid()+" in source Region: "+region.getId());
+				return disabledUser;
+			} else {
+				throw new CloudRuntimeException("Error while disabling user :"+user.getUuid()+" in source Region: "+region.getId());
+			}
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public UserAccount enableUser(long userId) {
+        UserVO user = _userDao.findById(userId);
+        if (user == null || user.getRemoved() != null) {
+            throw new InvalidParameterValueException("Unable to find active user by id " + userId);
+        }		        
+        
+        int regionId = user.getRegionId();
+        
+        String command = "enableUser";
+		List<NameValuePair> params = new ArrayList<NameValuePair>();
+		params.add(new NameValuePair(ApiConstants.ID, user.getUuid()));
+        
+		if(getId() == regionId){
+			UserAccount enabledUser = _accountMgr.enableUser(userId);
+			if(enabledUser != null){
+				List<RegionVO> regions =  _regionDao.listAll();
+				for (Region region : regions){
+					if(region.getId() == getId()){
+						continue;
+					}
+					params.add(new NameValuePair(ApiConstants.IS_PROPAGATE, "true"));
+					if (RegionsApiUtil.makeAPICall(region, command, params)) {
+						s_logger.debug("Successfully enabled user :"+user.getUuid()+" in Region: "+region.getId());
+					} else {
+						s_logger.error("Error while disabling user :"+user.getUuid()+" in Region: "+region.getId());
+					}
+				}
+			}
+			return enabledUser;
+		} else {
+			//First enable in the Region where user was created
+			Region region = _regionDao.findById(regionId);
+			UserAccount enabledUser = RegionsApiUtil.makeUserAccountAPICall(region, command, params);
+			if (enabledUser != null) {
+				s_logger.debug("Successfully enabled user :"+user.getUuid()+" in source Region: "+region.getId());
+				return enabledUser;
+			} else {
+				throw new CloudRuntimeException("Error while enabling user :"+user.getUuid()+" in source Region: "+region.getId());
+			}
+		}
+	}
+
+}
diff --git a/server/src/org/apache/cloudstack/region/RegionServiceImpl.java b/server/src/org/apache/cloudstack/region/RegionServiceImpl.java
new file mode 100755
index 0000000..f5a0a80
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionServiceImpl.java
@@ -0,0 +1,298 @@
+// 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.cloudstack.region;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.api.command.admin.account.DeleteAccountCmd;
+import org.apache.cloudstack.api.command.admin.account.DisableAccountCmd;
+import org.apache.cloudstack.api.command.admin.account.EnableAccountCmd;
+import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;
+import org.apache.cloudstack.api.command.admin.domain.DeleteDomainCmd;
+import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
+import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
+import org.apache.cloudstack.api.command.admin.user.DisableUserCmd;
+import org.apache.cloudstack.api.command.admin.user.EnableUserCmd;
+import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
+import org.apache.cloudstack.api.command.user.region.ListRegionsCmd;
+import org.apache.cloudstack.region.dao.RegionDao;
+import org.apache.log4j.Logger;
+
+import com.cloud.domain.Domain;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.PermissionDeniedException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.DomainManager;
+import com.cloud.user.UserAccount;
+import com.cloud.user.UserContext;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.component.Manager;
+
+@Local(value = { RegionService.class })
+public class RegionServiceImpl implements RegionService, Manager {
+    public static final Logger s_logger = Logger.getLogger(RegionServiceImpl.class);
+    
+    @Inject
+    private RegionDao _regionDao;
+    @Inject
+    private AccountDao _accountDao;
+    @Inject
+    private UserDao _userDao;
+    @Inject
+    private DomainDao _domainDao;    
+    @Inject
+    private RegionManager _regionMgr;
+    @Inject
+    private AccountManager _accountMgr;
+    @Inject
+    private DomainManager _domainMgr;
+    
+    private String _name;
+    
+    @Override
+    public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
+        _name = name;
+        return true;
+    }
+    
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */    
+	@Override
+	public Region addRegion(int id, String name, String endPoint, String apiKey, String secretKey) {
+		//Check for valid Name
+		//Check valid end_point url
+		return _regionMgr.addRegion(id, name, endPoint, apiKey, secretKey);
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public Region updateRegion(int id, String name, String endPoint, String apiKey, String secretKey) {
+		//Check for valid Name
+		//Check valid end_point url		
+		return _regionMgr.updateRegion(id, name, endPoint, apiKey, secretKey);
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public boolean removeRegion(int id) {
+		return _regionMgr.removeRegion(id);
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public List<? extends Region> listRegions(ListRegionsCmd cmd) {
+		return _regionMgr.listRegions(cmd.getId(), cmd.getName());
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public boolean deleteUserAccount(DeleteAccountCmd cmd) {
+        boolean result = false;
+        if(checkIsPropagate(cmd.getIsPropagate())){
+        	result = _accountMgr.deleteUserAccount(cmd.getId());
+        } else {
+        	result = _regionMgr.deleteUserAccount(cmd.getId());
+        }
+		return result;
+	}
+	
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public Account updateAccount(UpdateAccountCmd cmd) {
+    	Account result = null;
+    	if(checkIsPropagate(cmd.getIsPropagate())){
+    		result = _accountMgr.updateAccount(cmd);
+        } else {
+        	result = _regionMgr.updateAccount(cmd);
+        }
+		
+		return result;
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public Account disableAccount(DisableAccountCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException {
+    	Account result = null;
+    	if(checkIsPropagate(cmd.getIsPropagate())){
+    		if(cmd.getLockRequested())
+    			result = _accountMgr.lockAccount(cmd.getAccountName(), cmd.getDomainId(), cmd.getId());
+    		else
+    			result = _accountMgr.disableAccount(cmd.getAccountName(), cmd.getDomainId(), cmd.getId());
+    	} else {
+    		result = _regionMgr.disableAccount(cmd.getAccountName(), cmd.getDomainId(), cmd.getId(), cmd.getLockRequested());
+    	}
+		return result;
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public Account enableAccount(EnableAccountCmd cmd) {
+    	Account result = null;
+    	if(checkIsPropagate(cmd.getIsPropagate())){
+    		result = _accountMgr.enableAccount(cmd.getAccountName(), cmd.getDomainId(), cmd.getId());
+    	} else {
+    		result = _regionMgr.enableAccount(cmd.getAccountName(), cmd.getDomainId(), cmd.getId());
+    	}
+		return result;
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public boolean deleteUser(DeleteUserCmd cmd) {
+        boolean result = false;
+        if(checkIsPropagate(cmd.getIsPropagate())){
+        	result = _accountMgr.deleteUser(cmd);
+        } else {
+        	result = _regionMgr.deleteUser(cmd);
+        }		
+		return result;
+	}
+	
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public Domain updateDomain(UpdateDomainCmd cmd) {
+        Domain domain = null;
+        if(checkIsPropagate(cmd.getIsPropagate())){
+        	domain = _domainMgr.updateDomain(cmd);
+        } else {
+        	domain = _regionMgr.updateDomain(cmd);
+        }		
+		return domain;
+	}	
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public boolean deleteDomain(DeleteDomainCmd cmd) {
+		boolean result = false;
+		if(checkIsPropagate(cmd.isPropagate())){
+			result = _domainMgr.deleteDomain(cmd.getId(), cmd.getCleanup());
+		} else {
+			result = _regionMgr.deleteDomain(cmd.getId(), cmd.getCleanup());
+		}
+		return result;
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 	
+	@Override
+	public UserAccount updateUser(UpdateUserCmd cmd){
+        UserAccount user = null;
+        if(checkIsPropagate(cmd.getIsPropagate())){
+        	user = _accountMgr.updateUser(cmd);
+        } else {
+        	user = _regionMgr.updateUser(cmd);
+        }		
+		return user;
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public UserAccount disableUser(DisableUserCmd cmd) {
+        UserAccount user = null;
+        if(checkIsPropagate(cmd.getIsPropagate())){
+    		user = _accountMgr.disableUser(cmd.getId());
+        } else {
+        	user = _regionMgr.disableUser(cmd.getId());
+        }
+		return user;
+	}
+
+    /**
+     * {@inheritDoc}
+     */ 
+	@Override
+	public UserAccount enableUser(EnableUserCmd cmd) {
+		UserAccount user = null;
+		if(checkIsPropagate(cmd.getIsPropagate())){
+			user = _accountMgr.enableUser(cmd.getId());
+		} else {
+			user = _regionMgr.enableUser(cmd.getId());
+		}		
+		return user;
+	}
+	
+    private boolean isRootAdmin(short accountType) {
+        return (accountType == Account.ACCOUNT_TYPE_ADMIN);
+    }
+    
+    /**
+     * Check isPopagate flag, Only ROOT Admin can use this param
+     * @param isPopagate
+     * @return
+     */
+    private boolean checkIsPropagate(Boolean isPopagate){
+    	if(isPopagate == null || !isPopagate){
+    		return false;
+    	}
+		// Only Admin can use isPopagate flag
+    	UserContext ctx = UserContext.current();
+    	Account caller = ctx.getCaller();
+    	if(!isRootAdmin(caller.getType())){
+    		throw new PermissionDeniedException("isPropagate param cannot be used by non ROOT Admin");
+    	}          	
+    	return true;
+    }
+
+}
diff --git a/server/src/org/apache/cloudstack/region/RegionSyncVO.java b/server/src/org/apache/cloudstack/region/RegionSyncVO.java
new file mode 100644
index 0000000..271f8e3
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionSyncVO.java
@@ -0,0 +1,93 @@
+// 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.cloudstack.region;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import com.cloud.utils.db.GenericDao;
+
+
+@Entity
+@Table(name="region_sync")
+public class RegionSyncVO implements RegionSync {
+
+	@Id
+	@Column(name="id")
+	private long id;
+
+	@Column(name="region_id")
+	private int regionId;
+
+	@Column(name="api")
+	private String api;
+
+	@Column(name=GenericDao.CREATED_COLUMN)
+	private Date createDate;
+
+	@Column(name="processed")
+	boolean processed;
+
+	public RegionSyncVO() {
+	}
+
+	public RegionSyncVO(int regionId, String api) {
+		this.regionId = regionId;
+		this.api = api;
+	}
+
+	public int getRegionId() {
+		return regionId;
+	}
+
+	public void setRegionId(int regionId) {
+		this.regionId = regionId;
+	}
+
+	public String getApi() {
+		return api;
+	}
+
+	public void setApi(String api) {
+		this.api = api;
+	}
+
+	public Date getCreateDate() {
+		return createDate;
+	}
+
+	public void setCreateDate(Date createDate) {
+		this.createDate = createDate;
+	}
+
+	public boolean isProcessed() {
+		return processed;
+	}
+
+	public void setProcessed(boolean processed) {
+		this.processed = processed;
+	}
+
+	public long getId() {
+		return id;
+	}
+		
+}
diff --git a/server/src/org/apache/cloudstack/region/RegionUser.java b/server/src/org/apache/cloudstack/region/RegionUser.java
new file mode 100644
index 0000000..298638e
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionUser.java
@@ -0,0 +1,76 @@
+// 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.cloudstack.region;
+
+import com.cloud.user.UserVO;
+
+public class RegionUser extends UserVO {
+    String accountUuid;
+    String created;
+    String account;
+    String accounttype;
+    String domainid;
+    String domain;
+
+	public RegionUser() {
+    }
+    
+    public String getAccountuuid() {
+		return accountUuid;
+	}
+
+	public void setAccountuuid(String accountUuid) {
+		this.accountUuid = accountUuid;
+	}
+
+	public void setCreated(String created) {
+		this.created = created;
+	}
+
+	public String getAccount() {
+		return account;
+	}
+
+	public void setAccount(String account) {
+		this.account = account;
+	}
+
+	public String getAccounttype() {
+		return accounttype;
+	}
+
+	public void setAccounttype(String accounttype) {
+		this.accounttype = accounttype;
+	}
+
+	public String getDomainid() {
+		return domainid;
+	}
+
+	public void setDomainid(String domainid) {
+		this.domainid = domainid;
+	}
+
+	public String getDomain() {
+		return domain;
+	}
+
+	public void setDomain(String domain) {
+		this.domain = domain;
+	}
+
+}
diff --git a/server/src/org/apache/cloudstack/region/RegionVO.java b/server/src/org/apache/cloudstack/region/RegionVO.java
new file mode 100644
index 0000000..0c36db2
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionVO.java
@@ -0,0 +1,93 @@
+// 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.cloudstack.region;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+
+@Entity
+@Table(name="region")
+public class RegionVO implements Region{
+
+    @Id
+    @Column(name="id")
+    private int id;
+    
+    @Column(name="name")
+    private String name;
+
+    @Column(name="end_point")
+    private String endPoint;
+    
+    @Column(name="api_key")
+    private String apiKey;
+    
+    @Column(name="secret_key")
+    private String secretKey;
+    
+    public RegionVO() {
+    }
+    
+    public RegionVO(int id, String name, String endPoint, String apiKey, String secretKey) {
+    	this.id = id;
+    	this.name = name;
+    	this.endPoint = endPoint;
+    	this.apiKey = apiKey;
+    	this.secretKey = secretKey;
+    }
+
+	public int getId() {
+		return id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getEndPoint() {
+		return endPoint;
+	}
+
+	public void setEndPoint(String endPoint) {
+		this.endPoint = endPoint;
+	}
+
+	public String getApiKey() {
+		return apiKey;
+	}
+
+	public void setApiKey(String apiKey) {
+		this.apiKey = apiKey;
+	}
+
+	public String getSecretKey() {
+		return secretKey;
+	}
+
+	public void setSecretKey(String secretKey) {
+		this.secretKey = secretKey;
+	}
+
+    
+}
diff --git a/server/src/org/apache/cloudstack/region/RegionsApiUtil.java b/server/src/org/apache/cloudstack/region/RegionsApiUtil.java
new file mode 100644
index 0000000..c7625db
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionsApiUtil.java
@@ -0,0 +1,306 @@
+// 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.cloudstack.region;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.log4j.Logger;
+
+import com.cloud.domain.DomainVO;
+import com.cloud.user.UserAccount;
+import com.cloud.user.UserAccountVO;
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.io.xml.DomDriver;
+
+/**
+ * Utility class for making API calls between peer Regions
+ *
+ */
+public class RegionsApiUtil {
+	public static final Logger s_logger = Logger.getLogger(RegionsApiUtil.class);
+
+	/**
+	 * Makes an api call using region service end_point, api command and params
+	 * @param region
+	 * @param command
+	 * @param params
+	 * @return True, if api is successful
+	 */
+	protected static boolean makeAPICall(Region region, String command, List<NameValuePair> params){
+		try {
+			String apiParams = buildParams(command, params);
+			String url = buildUrl(apiParams, region);
+			HttpClient client = new HttpClient();
+			HttpMethod method = new GetMethod(url);
+			if( client.executeMethod(method) == 200){
+				return true;
+			} else {
+				return false;
+			}
+		} catch (HttpException e) {
+			s_logger.error(e.getMessage());
+			return false;
+		} catch (IOException e) {
+			s_logger.error(e.getMessage());
+			return false;
+		} 		
+	}
+
+	/**
+	 * Makes an api call using region service end_point, api command and params
+	 * Returns Account object on success
+	 * @param region
+	 * @param command
+	 * @param params
+	 * @return
+	 */
+	protected static RegionAccount makeAccountAPICall(Region region, String command, List<NameValuePair> params){
+		try {
+			String url = buildUrl(buildParams(command, params), region);
+			HttpClient client = new HttpClient();
+			HttpMethod method = new GetMethod(url);
+			if( client.executeMethod(method) == 200){
+				InputStream is = method.getResponseBodyAsStream();
+				//Translate response to Account object
+				XStream xstream = new XStream(new DomDriver());
+				xstream.alias("account", RegionAccount.class);
+				xstream.alias("user", RegionUser.class);
+				xstream.aliasField("id", RegionAccount.class, "uuid");
+				xstream.aliasField("name", RegionAccount.class, "accountName");
+				xstream.aliasField("accounttype", RegionAccount.class, "type");
+				xstream.aliasField("domainid", RegionAccount.class, "domainUuid");
+				xstream.aliasField("networkdomain", RegionAccount.class, "networkDomain");
+				xstream.aliasField("id", RegionUser.class, "uuid");
+				xstream.aliasField("accountId", RegionUser.class, "accountUuid");
+				ObjectInputStream in = xstream.createObjectInputStream(is);
+				return (RegionAccount)in.readObject();
+			} else {
+				return null;
+			}
+		} catch (HttpException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} catch (IOException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} catch (ClassNotFoundException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} 	
+	}
+
+	/**
+	 * Makes an api call using region service end_point, api command and params
+	 * Returns Domain object on success
+	 * @param region
+	 * @param command
+	 * @param params
+	 * @return
+	 */
+	protected static RegionDomain makeDomainAPICall(Region region, String command, List<NameValuePair> params){
+		try {
+			String url = buildUrl(buildParams(command, params), region);
+			HttpClient client = new HttpClient();
+			HttpMethod method = new GetMethod(url);
+			if( client.executeMethod(method) == 200){
+				InputStream is = method.getResponseBodyAsStream();
+				XStream xstream = new XStream(new DomDriver());
+				//Translate response to Domain object
+				xstream.alias("domain", RegionDomain.class);
+				xstream.aliasField("id", RegionDomain.class, "uuid");
+				xstream.aliasField("parentdomainid", RegionDomain.class, "parentUuid");
+				xstream.aliasField("networkdomain", DomainVO.class, "networkDomain");
+				ObjectInputStream in = xstream.createObjectInputStream(is);
+				return (RegionDomain)in.readObject();
+			} else {
+				return null;
+			}
+		} catch (HttpException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} catch (IOException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} catch (ClassNotFoundException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} 	
+	}
+
+	/**
+	 * Makes an api call using region service end_point, api command and params
+	 * Returns UserAccount object on success
+	 * @param region
+	 * @param command
+	 * @param params
+	 * @return
+	 */
+	protected static UserAccount makeUserAccountAPICall(Region region, String command, List<NameValuePair> params){
+		try {
+			String url = buildUrl(buildParams(command, params), region);
+			HttpClient client = new HttpClient();
+			HttpMethod method = new GetMethod(url);
+			if( client.executeMethod(method) == 200){
+				InputStream is = method.getResponseBodyAsStream();
+				XStream xstream = new XStream(new DomDriver());
+				xstream.alias("useraccount", UserAccountVO.class);
+				xstream.aliasField("id", UserAccountVO.class, "uuid");
+				ObjectInputStream in = xstream.createObjectInputStream(is);
+				return (UserAccountVO)in.readObject();
+			} else {
+				return null;
+			}
+		} catch (HttpException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} catch (IOException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} catch (ClassNotFoundException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		} 	
+	}
+
+	/**
+	 * Builds parameters string with command and encoded param values 
+	 * @param command
+	 * @param params
+	 * @return
+	 */
+	protected static String buildParams(String command, List<NameValuePair> params) {
+		StringBuffer paramString = new StringBuffer("command="+command);
+		Iterator<NameValuePair> iter = params.iterator();
+		try {
+			while(iter.hasNext()){
+				NameValuePair param = iter.next();
+				if(param.getValue() != null && !(param.getValue().isEmpty())){
+					paramString.append("&"+param.getName()+"="+URLEncoder.encode(param.getValue(), "UTF-8"));
+				}
+			}
+		}
+		catch (UnsupportedEncodingException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		}
+		return paramString.toString();
+	}
+	
+	/**
+	 * Build URL for api call using region end_point
+	 * Parameters are sorted and signed using secret_key
+	 * @param apiParams
+	 * @param region
+	 * @return
+	 */
+	private static String buildUrl(String apiParams, Region region) {
+
+		String apiKey = region.getApiKey();
+		String secretKey = region.getSecretKey();
+
+
+		if (apiKey == null || secretKey == null) {
+			return region.getEndPoint() +"?"+ apiParams;
+		}
+
+		String encodedApiKey;
+		try {
+			encodedApiKey = URLEncoder.encode(apiKey, "UTF-8");
+
+			List<String> sortedParams = new ArrayList<String>();
+			sortedParams.add("apikey=" + encodedApiKey.toLowerCase());
+			StringTokenizer st = new StringTokenizer(apiParams, "&");
+			String url = null;
+			boolean first = true;
+			while (st.hasMoreTokens()) {
+				String paramValue = st.nextToken();
+				String param = paramValue.substring(0, paramValue.indexOf("="));
+				String value = paramValue.substring(paramValue.indexOf("=") + 1, paramValue.length());
+				if (first) {
+					url = param + "=" + value;
+					first = false;
+				} else {
+					url = url + "&" + param + "=" + value;
+				}
+				sortedParams.add(param.toLowerCase() + "=" + value.toLowerCase());
+			}
+			Collections.sort(sortedParams);
+
+
+			//Construct the sorted URL and sign and URL encode the sorted URL with your secret key
+			String sortedUrl = null;
+			first = true;
+			for (String param : sortedParams) {
+				if (first) {
+					sortedUrl = param;
+					first = false;
+				} else {
+					sortedUrl = sortedUrl + "&" + param;
+				}
+			}
+			String encodedSignature = signRequest(sortedUrl, secretKey);
+
+			String finalUrl = region.getEndPoint() +"?"+apiParams+ "&apiKey=" + apiKey + "&signature=" + encodedSignature;
+			
+			return finalUrl;
+
+		} catch (UnsupportedEncodingException e) {
+			s_logger.error(e.getMessage());
+			return null;
+		}
+	}
+
+	/**
+	 * 1. Signs a string with a secret key using SHA-1 2. Base64 encode the result 3. URL encode the final result
+	 * 
+	 * @param request
+	 * @param key
+	 * @return
+	 */
+	private static String signRequest(String request, String key) {
+		try {
+			Mac mac = Mac.getInstance("HmacSHA1");
+			SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
+			mac.init(keySpec);
+			mac.update(request.getBytes());
+			byte[] encryptedBytes = mac.doFinal();
+			return URLEncoder.encode(Base64.encodeBase64String(encryptedBytes), "UTF-8");
+		} catch (Exception ex) {
+			s_logger.error(ex.getMessage());
+			return null;
+		}
+	}
+	
+}
\ No newline at end of file
diff --git a/server/src/org/apache/cloudstack/region/dao/RegionDao.java b/server/src/org/apache/cloudstack/region/dao/RegionDao.java
new file mode 100644
index 0000000..91b51d3
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/dao/RegionDao.java
@@ -0,0 +1,27 @@
+// 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.cloudstack.region.dao;
+
+import org.apache.cloudstack.region.RegionVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface RegionDao extends GenericDao<RegionVO, Integer> {
+
+	RegionVO findByName(String name);
+
+}
diff --git a/server/src/org/apache/cloudstack/region/dao/RegionDaoImpl.java b/server/src/org/apache/cloudstack/region/dao/RegionDaoImpl.java
new file mode 100644
index 0000000..4099835
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/dao/RegionDaoImpl.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.cloudstack.region.dao;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.region.RegionVO;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Local(value={RegionDao.class})
+public class RegionDaoImpl extends GenericDaoBase<RegionVO, Integer> implements RegionDao {
+    private static final Logger s_logger = Logger.getLogger(RegionDaoImpl.class);
+    protected SearchBuilder<RegionVO> NameSearch;
+    protected SearchBuilder<RegionVO> AllFieldsSearch;
+    
+    public RegionDaoImpl(){
+    	NameSearch = createSearchBuilder();
+    	NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ);
+    	NameSearch.done();
+    }
+    
+	@Override
+	public RegionVO findByName(String name) {
+        SearchCriteria<RegionVO> sc = NameSearch.create();
+        sc.setParameters("name", name);
+        return findOneBy(sc);
+	}
+}
diff --git a/server/src/org/apache/cloudstack/region/dao/RegionSyncDao.java b/server/src/org/apache/cloudstack/region/dao/RegionSyncDao.java
new file mode 100644
index 0000000..df287e5
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/dao/RegionSyncDao.java
@@ -0,0 +1,24 @@
+// 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.cloudstack.region.dao;
+
+import org.apache.cloudstack.region.RegionSyncVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface RegionSyncDao extends GenericDao<RegionSyncVO, Integer> {
+}
diff --git a/server/src/org/apache/cloudstack/region/dao/RegionSyncDaoImpl.java b/server/src/org/apache/cloudstack/region/dao/RegionSyncDaoImpl.java
new file mode 100644
index 0000000..a8fa33f
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/dao/RegionSyncDaoImpl.java
@@ -0,0 +1,33 @@
+// 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.cloudstack.region.dao;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.region.RegionSyncVO;
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.db.GenericDaoBase;
+
+@Local(value={RegionSyncDao.class})
+public class RegionSyncDaoImpl extends GenericDaoBase<RegionSyncVO, Integer> implements RegionSyncDao {
+    private static final Logger s_logger = Logger.getLogger(RegionSyncDaoImpl.class);
+    
+    public RegionSyncDaoImpl(){
+    	
+    }
+}
diff --git a/server/test/com/cloud/async/TestAsyncJobManager.java b/server/test/com/cloud/async/TestAsyncJobManager.java
index 8ce51fa..9b154ff 100644
--- a/server/test/com/cloud/async/TestAsyncJobManager.java
+++ b/server/test/com/cloud/async/TestAsyncJobManager.java
@@ -228,25 +228,25 @@
 		getRandomMilliseconds(1, 100);		
 		DomainDao domainDao = new DomainDaoImpl();
 		
-		DomainVO domain1 = new DomainVO("d1", 2L, 1L, null);
+		DomainVO domain1 = new DomainVO("d1", 2L, 1L, null, 1);
 		domainDao.create(domain1);
 		
-		DomainVO domain2 = new DomainVO("d2", 2L, 1L, null);
+		DomainVO domain2 = new DomainVO("d2", 2L, 1L, null, 1);
 		domainDao.create(domain2);
 		
-		DomainVO domain3 = new DomainVO("d3", 2L, 1L, null);
+		DomainVO domain3 = new DomainVO("d3", 2L, 1L, null, 1);
 		domainDao.create(domain3);
 
-		DomainVO domain11 = new DomainVO("d11", 2L, domain1.getId(), null);
+		DomainVO domain11 = new DomainVO("d11", 2L, domain1.getId(), null, 1);
 		domainDao.create(domain11);
 		
 		domainDao.remove(domain11.getId());
 		
-		DomainVO domain12 = new DomainVO("d12", 2L, domain1.getId(), null);
+		DomainVO domain12 = new DomainVO("d12", 2L, domain1.getId(), null, 1);
 		domainDao.create(domain12);
 		
 		domainDao.remove(domain3.getId());
-		DomainVO domain4 = new DomainVO("d4", 2L, 1L, null);
+		DomainVO domain4 = new DomainVO("d4", 2L, 1L, null, 1);
 		domainDao.create(domain4);
 	}
 }
diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java
index 135ae9a..b5433ba 100644
--- a/server/test/com/cloud/user/MockAccountManagerImpl.java
+++ b/server/test/com/cloud/user/MockAccountManagerImpl.java
@@ -209,12 +209,6 @@
     }
 
     @Override
-    public UserVO createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
     public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) {
         // TODO Auto-generated method stub
         return null;
@@ -282,23 +276,6 @@
         return true;
     }
 
-
-	@Override
-	public UserAccount createUserAccount(String userName, String password,
-			String firstName, String lastName, String email, String timezone,
-			String accountName, short accountType, Long domainId,
-			String networkDomain, Map<String, String> details) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Account createAccount(String accountName, short accountType,
-			Long domainId, String networkDomain, Map details) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
 	@Override
 	public boolean enableAccount(long accountId) {
 		// TODO Auto-generated method stub
@@ -345,6 +322,31 @@
         return null;
     }
 
+	@Override
+	public UserAccount createUserAccount(String userName, String password,
+			String firstName, String lastName, String email, String timezone,
+			String accountName, short accountType, Long domainId,
+			String networkDomain, Map<String, String> details,
+			String accountUUID, String userUUID, Integer regionId) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public User createUser(String userName, String password, String firstName,
+			String lastName, String email, String timeZone, String accountName,
+			Long domainId, String userUUID, Integer regionId) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Account createAccount(String accountName, short accountType,
+			Long domainId, String networkDomain, Map details, String uuid,
+			int regionId) {
+		// TODO Auto-generated method stub
+		return null;
+	}
     @Override
     public RoleType getRoleType(Account account) {
         return null;
diff --git a/server/test/com/cloud/user/MockDomainManagerImpl.java b/server/test/com/cloud/user/MockDomainManagerImpl.java
index 0fe259d..4f134a0 100644
--- a/server/test/com/cloud/user/MockDomainManagerImpl.java
+++ b/server/test/com/cloud/user/MockDomainManagerImpl.java
@@ -25,6 +25,8 @@
 
 import org.apache.cloudstack.api.command.admin.domain.ListDomainChildrenCmd;
 import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd;
+import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
+
 import com.cloud.domain.Domain;
 import com.cloud.domain.DomainVO;
 import com.cloud.exception.PermissionDeniedException;
@@ -35,12 +37,6 @@
 public class MockDomainManagerImpl implements  Manager, DomainManager, DomainService {
 
     @Override
-    public Domain createDomain(String name, Long parentId, String networkDomain) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
     public Domain getDomain(long id) {
         // TODO Auto-generated method stub
         return null;
@@ -85,13 +81,6 @@
     }
 
     @Override
-    public Domain createDomain(String name, Long parentId, Long ownerId,
-            String networkDomain) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
     public DomainVO findDomainByPath(String domainPath) {
         // TODO Auto-generated method stub
         return null;
@@ -145,4 +134,24 @@
         return null;
     }
 
+	@Override
+	public Domain createDomain(String name, Long parentId,
+			String networkDomain, String domainUUID, Integer regionId) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Domain updateDomain(UpdateDomainCmd cmd) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Domain createDomain(String name, Long parentId, Long ownerId,
+			String networkDomain, String domainUUID, Integer regionId) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
 }
diff --git a/server/test/com/cloud/vm/MockUserVmManagerImpl.java b/server/test/com/cloud/vm/MockUserVmManagerImpl.java
index 1fe4728..3e70153 100644
--- a/server/test/com/cloud/vm/MockUserVmManagerImpl.java
+++ b/server/test/com/cloud/vm/MockUserVmManagerImpl.java
@@ -39,7 +39,6 @@
 import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
 import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
 import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
-import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
 import org.apache.cloudstack.api.command.user.vm.RebootVMCmd;
 import org.apache.cloudstack.api.command.user.vm.ResetVMPasswordCmd;
 import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd;
diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
index d0f0c62..17ad2e1 100644
--- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java
@@ -319,8 +319,7 @@
      */
     @Override
     public Long getDefaultPageSize() {
-        // TODO Auto-generated method stub
-        return null;
+        return 500L;
     }
 
     /* (non-Javadoc)
diff --git a/server/test/org/apache/cloudstack/region/RegionManagerTest.java b/server/test/org/apache/cloudstack/region/RegionManagerTest.java
new file mode 100644
index 0000000..330f0b4
--- /dev/null
+++ b/server/test/org/apache/cloudstack/region/RegionManagerTest.java
@@ -0,0 +1,74 @@
+// 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.cloudstack.region;
+
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.cloudstack.api.command.admin.domain.DeleteDomainCmd;
+import org.apache.cloudstack.region.dao.RegionDao;
+import org.apache.log4j.Logger;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.user.dao.AccountDao;
+
+
+
+public class RegionManagerTest extends TestCase {
+    private static final Logger s_logger = Logger.getLogger(RegionManagerTest.class);
+
+    @Before
+    @Override
+    protected void setUp() {
+
+    }
+    
+    @Test
+    public void testUniqueName() {
+    	RegionManagerImpl regionMgr = new RegionManagerImpl();
+    	RegionDao regionDao = Mockito.mock(RegionDao.class);
+    	RegionVO region = new RegionVO(2, "APAC", "", null, null);    	
+    	Mockito.when(regionDao.findByName(Mockito.anyString())).thenReturn(region);    	
+    	regionMgr._regionDao = regionDao;
+    	try {
+    		regionMgr.addRegion(2, "APAC", "", null, null);
+    	} catch (InvalidParameterValueException e){
+    		Assert.assertEquals("Region with name: APAC already exists", e.getMessage());
+    	}
+    }
+    
+    @Test
+    public void testUserDelete() {
+    	RegionManagerImpl regionMgr = new RegionManagerImpl();
+    	AccountDao accountDao = Mockito.mock(AccountDao.class);
+    	Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(null);
+    	regionMgr._accountDao = accountDao;
+    	try {
+    		regionMgr.deleteUserAccount(5);
+    	} catch (InvalidParameterValueException e){
+    		Assert.assertEquals("The specified account does not exist in the system", e.getMessage());
+    	}    	
+    }
+
+}
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index 7760f5d..ad19e0f 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -141,6 +141,7 @@
 DROP TABLE IF EXISTS `cloud`.`cluster_vsm_map`;
 DROP TABLE IF EXISTS `cloud`.`virtual_supervisor_module`;
 DROP TABLE IF EXISTS `cloud`.`port_profile`;
+DROP TABLE IF EXISTS `cloud`.`region`;
 DROP TABLE IF EXISTS `cloud`.`s2s_customer_gateway`;
 DROP TABLE IF EXISTS `cloud`.`s2s_vpn_gateway`;
 DROP TABLE IF EXISTS `cloud`.`s2s_vpn_connection`;
@@ -909,6 +910,7 @@
   `timezone` varchar(30) default NULL,
   `registration_token` varchar(255) default NULL,
   `is_registered` tinyint NOT NULL DEFAULT 0 COMMENT '1: yes, 0: no',
+  `region_id` int unsigned,
   `incorrect_login_attempts` integer unsigned NOT NULL DEFAULT 0,
   PRIMARY KEY  (`id`),
   INDEX `i_user__removed`(`removed`),
@@ -1259,6 +1261,7 @@
   `state` char(32) NOT NULL default 'Active' COMMENT 'state of the domain',
   `network_domain` varchar(255),
   `type` varchar(255) NOT NULL DEFAULT 'Normal' COMMENT 'type of the domain - can be Normal or Project',
+  `region_id` int unsigned,  
   PRIMARY KEY  (`id`),
   UNIQUE (parent, name, removed),
   INDEX `i_domain__path`(`path`),
@@ -1277,6 +1280,7 @@
   `cleanup_needed` tinyint(1) NOT NULL default '0',
   `network_domain` varchar(255),
   `default_zone_id` bigint unsigned,
+  `region_id` int unsigned,  
   PRIMARY KEY  (`id`),
   INDEX i_account__removed(`removed`),
   CONSTRAINT `fk_account__default_zone_id` FOREIGN KEY `fk_account__default_zone_id`(`default_zone_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE,
@@ -2260,6 +2264,15 @@
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
 
+CREATE TABLE  `cloud`.`region` (
+  `id` int unsigned NOT NULL UNIQUE,
+  `name` varchar(255) NOT NULL UNIQUE,
+  `end_point` varchar(255) NOT NULL,
+  `api_key` varchar(255),
+  `secret_key` varchar(255),
+  PRIMARY KEY  (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
 CREATE TABLE `cloud`.`vpc` (
   `id` bigint unsigned NOT NULL auto_increment COMMENT 'id',
   `uuid` varchar(40) NOT NULL,
@@ -2546,6 +2559,15 @@
   INDEX `i_autoscale_vmgroup_policy_map__vmgroup_id`(`vmgroup_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
+CREATE TABLE `cloud`.`region_sync` (
+  `id` bigint unsigned NOT NULL auto_increment,
+  `region_id` int unsigned NOT NULL,
+  `api` varchar(1024) NOT NULL,
+  `created` datetime NOT NULL COMMENT 'date created',
+  `processed` tinyint NOT NULL default '0',
+  PRIMARY KEY  (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
 INSERT INTO `cloud`.`counter` (id, uuid, source, name, value,created) VALUES (1, UUID(), 'snmp','Linux User CPU - percentage', '1.3.6.1.4.1.2021.11.9.0', now());
 INSERT INTO `cloud`.`counter` (id, uuid, source, name, value,created) VALUES (2, UUID(), 'snmp','Linux System CPU - percentage', '1.3.6.1.4.1.2021.11.10.0', now());
 INSERT INTO `cloud`.`counter` (id, uuid, source, name, value,created) VALUES (3, UUID(), 'snmp','Linux CPU Idle - percentage', '1.3.6.1.4.1.2021.11.11.0', now());
diff --git a/utils/conf/db.properties b/utils/conf/db.properties
index 18bf54c..d81b27d 100644
--- a/utils/conf/db.properties
+++ b/utils/conf/db.properties
@@ -20,6 +20,7 @@
 # in which the management server(Tomcat) is running
 cluster.node.IP=127.0.0.1
 cluster.servlet.port=9090
+region.id=1
 
 # CloudStack database settings
 db.cloud.username=cloud
diff --git a/utils/src/com/cloud/utils/db/GenericDao.java b/utils/src/com/cloud/utils/db/GenericDao.java
index 31a25fd..c0a9029 100755
--- a/utils/src/com/cloud/utils/db/GenericDao.java
+++ b/utils/src/com/cloud/utils/db/GenericDao.java
@@ -268,6 +268,8 @@
      * @return
      */
     Class<T> getEntityBeanType();
+    
+    public int getRegionId();
 
     /**
      * @param sc
diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java
index 0d73b90..4ecf242 100755
--- a/utils/src/com/cloud/utils/db/GenericDaoBase.java
+++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java
@@ -1802,6 +1802,11 @@
         factory.setCallback(0, sc);
         return sc;
     }
+    
+    @Override
+    public int getRegionId(){
+    	return Transaction.s_region_id;
+    }
 
     public Integer getCount(SearchCriteria<T> sc) {
         String clause = sc != null ? sc.getWhereClause() : null;
diff --git a/utils/src/com/cloud/utils/db/Transaction.java b/utils/src/com/cloud/utils/db/Transaction.java
index eaa31f6..13125f8 100755
--- a/utils/src/com/cloud/utils/db/Transaction.java
+++ b/utils/src/com/cloud/utils/db/Transaction.java
@@ -82,6 +82,7 @@
     public static final short AWSAPI_DB = 2;
     public static final short SIMULATOR_DB = 3;
     public static final short CONNECTED_DB = -1;
+    public static int s_region_id;
 
     private static AtomicLong s_id = new AtomicLong();
     private static final TransactionMBeanImpl s_mbean = new TransactionMBeanImpl();
@@ -1049,6 +1050,12 @@
                 System.setProperty("javax.net.ssl.trustStorePassword", dbProps.getProperty("db.cloud.trustStorePassword"));
             }
 
+            String regionId = dbProps.getProperty("region.id");
+            if(regionId == null){
+            	s_region_id = 1;
+            } else {
+            	s_region_id = Integer.parseInt(regionId);
+            }
             final GenericObjectPool cloudConnectionPool = new GenericObjectPool(null, cloudMaxActive, GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION,
                     cloudMaxWait, cloudMaxIdle, cloudTestOnBorrow, false, cloudTimeBtwEvictionRunsMillis, 1, cloudMinEvcitableIdleTimeMillis, cloudTestWhileIdle);
             final ConnectionFactory cloudConnectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://"+cloudHost + ":" + cloudPort + "/" + cloudDbName +