incubator-cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kis...@apache.org
Subject [1/4] - Separated RegionServiceImpl and RegionManagerImpl - Added comments - Changed package name to org.apache.cloudstack.region
Date Thu, 31 Jan 2013 12:57:32 GMT
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/RegionManagerImpl.java
----------------------------------------------------------------------
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..d93ab10
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionManagerImpl.java
@@ -0,0 +1,861 @@
+// 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
+    private RegionDao _regionDao;
+    @Inject
+    private 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) {
+		return _regionDao.listByNameAndId(id, name);
+	}
+
+    /**
+     * {@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());
+			}
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/RegionServiceImpl.java
----------------------------------------------------------------------
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..db592ad
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/RegionServiceImpl.java
@@ -0,0 +1,299 @@
+// 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.InvalidParameterValueException;
+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.getIsPropagate())){
+			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;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/RegionSyncVO.java
----------------------------------------------------------------------
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;
+	}
+		
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/RegionUser.java
----------------------------------------------------------------------
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;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/RegionVO.java
----------------------------------------------------------------------
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;
+	}
+
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/RegionsApiUtil.java
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/dao/RegionDao.java
----------------------------------------------------------------------
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..1360eac
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/dao/RegionDao.java
@@ -0,0 +1,30 @@
+// 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 java.util.List;
+
+import org.apache.cloudstack.region.RegionVO;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface RegionDao extends GenericDao<RegionVO, Integer> {
+
+	RegionVO findByName(String name);
+
+	List<RegionVO> listByNameAndId(Integer id, String name);
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/dao/RegionDaoImpl.java
----------------------------------------------------------------------
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..feb6e62
--- /dev/null
+++ b/server/src/org/apache/cloudstack/region/dao/RegionDaoImpl.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.region.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.region.RegionVO;
+import org.apache.log4j.Logger;
+
+import com.cloud.user.UserVO;
+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();
+    	
+    	AllFieldsSearch = createSearchBuilder();
+    	AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), SearchCriteria.Op.EQ);
+    	AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), SearchCriteria.Op.EQ);
+    	AllFieldsSearch.done();
+    }
+    
+	@Override
+	public RegionVO findByName(String name) {
+        SearchCriteria<RegionVO> sc = NameSearch.create();
+        sc.setParameters("name", NameSearch);
+        return findOneBy(sc);
+	}
+	
+	@Override
+	public List<RegionVO> listByNameAndId(Integer id, String name) {
+	    SearchCriteria<RegionVO> sc = AllFieldsSearch.create();
+	    sc.setParameters("id", id);
+        sc.setParameters("name", name);
+        return listBy(sc);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/dao/RegionSyncDao.java
----------------------------------------------------------------------
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> {
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/server/src/org/apache/cloudstack/region/dao/RegionSyncDaoImpl.java
----------------------------------------------------------------------
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(){
+    	
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8b1a5b1d/setup/db/create-schema.sql
----------------------------------------------------------------------
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index 9a5dc2b..d50d1fa 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -2259,7 +2259,7 @@ CREATE TABLE  `cloud`.`netscaler_pod_ref` (
 
 CREATE TABLE  `cloud`.`region` (
   `id` int unsigned NOT NULL UNIQUE,
-  `name` varchar(255) NOT NULL,
+  `name` varchar(255) NOT NULL UNIQUE,
   `end_point` varchar(255) NOT NULL,
   `api_key` varchar(255),
   `secret_key` varchar(255),


Mime
View raw message