Skip to content

Commit

Permalink
Merge remote-tracking branch 'apache/4.20' into 4.20.1-upgrade-path
Browse files Browse the repository at this point in the history
  • Loading branch information
weizhouapache committed Dec 3, 2024
2 parents 78e7da3 + 52e7b41 commit f3da229
Show file tree
Hide file tree
Showing 50 changed files with 878 additions and 98 deletions.
1 change: 1 addition & 0 deletions api/src/main/java/com/cloud/event/EventTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ public class EventTypes {

//register for user API and secret keys
public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY";
public static final String API_KEY_ACCESS_UPDATE = "API.KEY.ACCESS.UPDATE";

// Template Events
public static final String EVENT_TEMPLATE_CREATE = "TEMPLATE.CREATE";
Expand Down
47 changes: 41 additions & 6 deletions api/src/main/java/com/cloud/hypervisor/Hypervisor.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,57 @@
import org.apache.commons.lang3.StringUtils;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.EnumSet;
import java.util.stream.Collectors;

import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.DirectDownloadTemplate;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.RootDiskSizeOverride;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.VmStorageMigration;

public class Hypervisor {
public static class HypervisorType {
public enum Functionality {
DirectDownloadTemplate,
RootDiskSizeOverride,
VmStorageMigration
}

private static final Map<String, HypervisorType> hypervisorTypeMap = new LinkedHashMap<>();
public static final HypervisorType None = new HypervisorType("None"); //for storage hosts
public static final HypervisorType XenServer = new HypervisorType("XenServer", ImageFormat.VHD);
public static final HypervisorType KVM = new HypervisorType("KVM", ImageFormat.QCOW2);
public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA);
public static final HypervisorType XenServer = new HypervisorType("XenServer", ImageFormat.VHD, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
public static final HypervisorType KVM = new HypervisorType("KVM", ImageFormat.QCOW2, EnumSet.of(DirectDownloadTemplate, RootDiskSizeOverride, VmStorageMigration));
public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
public static final HypervisorType Hyperv = new HypervisorType("Hyperv");
public static final HypervisorType VirtualBox = new HypervisorType("VirtualBox");
public static final HypervisorType Parralels = new HypervisorType("Parralels");
public static final HypervisorType BareMetal = new HypervisorType("BareMetal");
public static final HypervisorType Simulator = new HypervisorType("Simulator");
public static final HypervisorType Simulator = new HypervisorType("Simulator", null, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
public static final HypervisorType Ovm = new HypervisorType("Ovm", ImageFormat.RAW);
public static final HypervisorType Ovm3 = new HypervisorType("Ovm3", ImageFormat.RAW);
public static final HypervisorType LXC = new HypervisorType("LXC");
public static final HypervisorType Custom = new HypervisorType("Custom");
public static final HypervisorType Custom = new HypervisorType("Custom", null, EnumSet.of(RootDiskSizeOverride));
public static final HypervisorType Any = new HypervisorType("Any"); /*If you don't care about the hypervisor type*/
private final String name;
private final ImageFormat imageFormat;
private final Set<Functionality> supportedFunctionalities;

public HypervisorType(String name) {
this(name, null);
this(name, null, EnumSet.noneOf(Functionality.class));
}

public HypervisorType(String name, ImageFormat imageFormat) {
this(name, imageFormat, EnumSet.noneOf(Functionality.class));
}

public HypervisorType(String name, ImageFormat imageFormat, Set<Functionality> supportedFunctionalities) {
this.name = name;
this.imageFormat = imageFormat;
this.supportedFunctionalities = supportedFunctionalities;
if (name.equals("Parralels")){ // typo in the original code
hypervisorTypeMap.put("parallels", this);
} else {
Expand Down Expand Up @@ -81,6 +101,12 @@ public static HypervisorType valueOf(String name) {
return hypervisorType;
}

public static List<HypervisorType> getListOfHypervisorsSupportingFunctionality(Functionality functionality) {
return hypervisorTypeMap.values().stream()
.filter(hypervisor -> hypervisor.supportedFunctionalities.contains(functionality))
.collect(Collectors.toList());
}

/**
* Returns the display name of a hypervisor type in case the custom hypervisor is used,
* using the 'hypervisor.custom.display.name' setting. Otherwise, returns hypervisor name
Expand All @@ -102,6 +128,15 @@ public String name() {
return name;
}

/**
* Make this method to be part of the properties of the hypervisor type itself.
*
* @return true if the hypervisor plugin support the specified functionality
*/
public boolean isFunctionalitySupported(Functionality functionality) {
return supportedFunctionalities.contains(functionality);
}

@Override
public int hashCode() {
return Objects.hash(name);
Expand Down
4 changes: 4 additions & 0 deletions api/src/main/java/com/cloud/user/Account.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,8 @@ public static Type getFromValue(Integer type){

boolean isDefault();

public void setApiKeyAccess(Boolean apiKeyAccess);

public Boolean getApiKeyAccess();

}
5 changes: 3 additions & 2 deletions api/src/main/java/com/cloud/user/AccountService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.List;
import java.util.Map;

import com.cloud.utils.Pair;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
Expand Down Expand Up @@ -127,9 +128,9 @@ User createUser(String userName, String password, String firstName, String lastN
*/
UserAccount getUserAccountById(Long userId);

public Map<String, String> getKeys(GetUserKeysCmd cmd);
public Pair<Boolean, Map<String, String>> getKeys(GetUserKeysCmd cmd);

public Map<String, String> getKeys(Long userId);
public Pair<Boolean, Map<String, String>> getKeys(Long userId);

/**
* Lists user two-factor authentication provider plugins
Expand Down
5 changes: 5 additions & 0 deletions api/src/main/java/com/cloud/user/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,9 @@ public enum Source {
public boolean isUser2faEnabled();

public String getKeyFor2fa();

public void setApiKeyAccess(Boolean apiKeyAccess);

public Boolean getApiKeyAccess();

}
27 changes: 27 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class ApiConstants {
public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm";
public static final String ANNOTATION = "annotation";
public static final String API_KEY = "apikey";
public static final String API_KEY_ACCESS = "apikeyaccess";
public static final String ARCHIVED = "archived";
public static final String ARCH = "arch";
public static final String AS_NUMBER = "asnumber";
Expand Down Expand Up @@ -1247,4 +1248,30 @@ public enum VMDetails {
public enum DomainDetails {
all, resource, min;
}

public enum ApiKeyAccess {
DISABLED(false),
ENABLED(true),
INHERIT(null);

Boolean apiKeyAccess;

ApiKeyAccess(Boolean keyAccess) {
apiKeyAccess = keyAccess;
}

public Boolean toBoolean() {
return apiKeyAccess;
}

public static ApiKeyAccess fromBoolean(Boolean value) {
if (value == null) {
return INHERIT;
} else if (value) {
return ENABLED;
} else {
return DISABLED;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

import javax.inject.Inject;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.RoleResponse;

import org.apache.cloudstack.acl.SecurityChecker.AccessType;
Expand All @@ -40,8 +42,8 @@
import com.cloud.user.Account;

@APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {Account.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
public class UpdateAccountCmd extends BaseCmd {
responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
public class UpdateAccountCmd extends BaseCmd implements UserCmd {

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
Expand Down Expand Up @@ -70,6 +72,9 @@ public class UpdateAccountCmd extends BaseCmd {
@Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "Details for the account used to store specific parameters")
private Map details;

@Parameter(name = ApiConstants.API_KEY_ACCESS, type = CommandType.STRING, description = "Determines if Api key access for this user is enabled, disabled or inherits the value from its parent, the domain level setting api.key.access", since = "4.20.1.0", authorized = {RoleType.Admin})
private String apiKeyAccess;

@Inject
RegionService _regionService;

Expand Down Expand Up @@ -109,6 +114,10 @@ public Map getDetails() {
return params;
}

public String getApiKeyAccess() {
return apiKeyAccess;
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand All @@ -131,7 +140,7 @@ public long getEntityOwnerId() {
public void execute() {
Account result = _regionService.updateAccount(this);
if (result != null){
AccountResponse response = _responseGenerator.createAccountResponse(ResponseView.Full, result);
AccountResponse response = _responseGenerator.createAccountResponse(getResponseView(), result);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Pair;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
Expand Down Expand Up @@ -54,11 +55,13 @@ public Long getID(){
else return Account.ACCOUNT_ID_SYSTEM;
}
public void execute(){
Map<String, String> keys = _accountService.getKeys(this);
Pair<Boolean, Map<String, String>> keys = _accountService.getKeys(this);

RegisterResponse response = new RegisterResponse();
if(keys != null){
response.setApiKey(keys.get("apikey"));
response.setSecretKey(keys.get("secretkey"));
response.setApiKeyAccess(keys.first());
response.setApiKey(keys.second().get("apikey"));
response.setSecretKey(keys.second().get("secretkey"));
}

response.setObjectName("userkeys");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,23 @@
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
import com.cloud.user.Account;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.ResourceIconResponse;

import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.UserResponse;

import java.util.List;

@APICommand(name = "listUsers", description = "Lists user accounts", responseObject = UserResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
public class ListUsersCmd extends BaseListAccountResourcesCmd {
responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
public class ListUsersCmd extends BaseListAccountResourcesCmd implements UserCmd {


/////////////////////////////////////////////////////
Expand All @@ -53,6 +56,9 @@ public class ListUsersCmd extends BaseListAccountResourcesCmd {
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "List user by the username")
private String username;

@Parameter(name = ApiConstants.API_KEY_ACCESS, type = CommandType.STRING, description = "List users by the Api key access value", since = "4.20.1.0", authorized = {RoleType.Admin})
private String apiKeyAccess;

@Parameter(name = ApiConstants.SHOW_RESOURCE_ICON, type = CommandType.BOOLEAN,
description = "flag to display the resource icon for users")
private Boolean showIcon;
Expand All @@ -77,6 +83,10 @@ public String getUsername() {
return username;
}

public String getApiKeyAccess() {
return apiKeyAccess;
}

public Boolean getShowIcon() {
return showIcon != null ? showIcon : false;
}
Expand All @@ -87,7 +97,7 @@ public Boolean getShowIcon() {

@Override
public void execute() {
ListResponse<UserResponse> response = _queryService.searchForUsers(this);
ListResponse<UserResponse> response = _queryService.searchForUsers(getResponseView(), this);
response.setResponseName(getCommandName());
this.setResponseObject(response);
if (response != null && response.getCount() > 0 && getShowIcon()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import javax.inject.Inject;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
Expand Down Expand Up @@ -69,6 +70,9 @@ public class UpdateUserCmd extends BaseCmd {
@Parameter(name = ApiConstants.USER_SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey")
private String secretKey;

@Parameter(name = ApiConstants.API_KEY_ACCESS, type = CommandType.STRING, description = "Determines if Api key access for this user is enabled, disabled or inherits the value from its parent, the owning account", since = "4.20.1.0", authorized = {RoleType.Admin})
private String apiKeyAccess;

@Parameter(name = ApiConstants.TIMEZONE,
type = CommandType.STRING,
description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
Expand Down Expand Up @@ -120,6 +124,10 @@ public String getSecretKey() {
return secretKey;
}

public String getApiKeyAccess() {
return apiKeyAccess;
}

public String getTimezone() {
return timezone;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.EnumSet;
import java.util.List;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
Expand Down Expand Up @@ -70,6 +71,9 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC
description = "comma separated list of account details requested, value can be a list of [ all, resource, min]")
private List<String> viewDetails;

@Parameter(name = ApiConstants.API_KEY_ACCESS, type = CommandType.STRING, description = "List accounts by the Api key access value", since = "4.20.1.0", authorized = {RoleType.Admin})
private String apiKeyAccess;

@Parameter(name = ApiConstants.SHOW_RESOURCE_ICON, type = CommandType.BOOLEAN,
description = "flag to display the resource icon for accounts")
private Boolean showIcon;
Expand Down Expand Up @@ -120,6 +124,10 @@ public EnumSet<DomainDetails> getDetails() throws InvalidParameterValueException
return dv;
}

public String getApiKeyAccess() {
return apiKeyAccess;
}

public boolean getShowIcon() {
return showIcon != null ? showIcon : false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,9 @@ protected void validateParameters() {
"Parameter zoneids cannot combine all zones (-1) option with other zones");

String customHypervisor = HypervisorGuru.HypervisorCustomDisplayName.value();
if (isDirectDownload() && !(getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.KVM.toString())
if (isDirectDownload() &&
!(Hypervisor.HypervisorType.getType(getHypervisor())
.isFunctionalitySupported(Hypervisor.HypervisorType.Functionality.DirectDownloadTemplate)
|| getHypervisor().equalsIgnoreCase(customHypervisor))) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Parameter directdownload " +
"is only allowed for KVM or %s templates", customHypervisor));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
@Param(description = "The tagged resource limit and count for the account", since = "4.20.0")
List<TaggedResourceLimitAndCountResponse> taggedResources;

@SerializedName(ApiConstants.API_KEY_ACCESS)
@Param(description = "whether api key access is Enabled, Disabled or set to Inherit (it inherits the value from the parent)", since = "4.20.1.0")
ApiConstants.ApiKeyAccess apiKeyAccess;

@Override
public String getObjectId() {
return id;
Expand Down Expand Up @@ -554,4 +558,8 @@ public void setResourceIconResponse(ResourceIconResponse icon) {
public void setTaggedResourceLimitsAndCounts(List<TaggedResourceLimitAndCountResponse> taggedResourceLimitsAndCounts) {
this.taggedResources = taggedResourceLimitsAndCounts;
}

public void setApiKeyAccess(Boolean apiKeyAccess) {
this.apiKeyAccess = ApiConstants.ApiKeyAccess.fromBoolean(apiKeyAccess);
}
}
Loading

0 comments on commit f3da229

Please sign in to comment.