You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ke...@apache.org on 2013/02/01 20:38:11 UTC
[28/50] [abbrv] - Separated RegionServiceImpl and RegionManagerImpl -
Added comments - Changed package name to org.apache.cloudstack.region
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),