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