Merge remote-tracking branch 'apache/4.20'

This commit is contained in:
Wei Zhou 2024-12-03 09:44:42 +01:00
commit da94ae2c1c
No known key found for this signature in database
GPG Key ID: 1503DFE7C8226103
114 changed files with 3995 additions and 296 deletions

View File

@ -21,6 +21,7 @@ import com.cloud.network.Network;
import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.Vpc;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd; import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.network.BgpPeer;
import java.util.List; import java.util.List;
@ -36,4 +37,8 @@ public interface BGPService {
boolean applyBgpPeers(Network network, boolean continueOnError) throws ResourceUnavailableException; boolean applyBgpPeers(Network network, boolean continueOnError) throws ResourceUnavailableException;
boolean applyBgpPeers(Vpc vpc, boolean continueOnError) throws ResourceUnavailableException; boolean applyBgpPeers(Vpc vpc, boolean continueOnError) throws ResourceUnavailableException;
List<? extends BgpPeer> getBgpPeersForNetwork(Network network);
List<? extends BgpPeer> getBgpPeersForVpc(Vpc vpc);
} }

View File

@ -292,6 +292,7 @@ public class EventTypes {
//register for user API and secret keys //register for user API and secret keys
public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY"; 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 // Template Events
public static final String EVENT_TEMPLATE_CREATE = "TEMPLATE.CREATE"; public static final String EVENT_TEMPLATE_CREATE = "TEMPLATE.CREATE";

View File

@ -20,37 +20,57 @@ import com.cloud.storage.Storage.ImageFormat;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; 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 class Hypervisor {
public static class HypervisorType { public static class HypervisorType {
public enum Functionality {
DirectDownloadTemplate,
RootDiskSizeOverride,
VmStorageMigration
}
private static final Map<String, HypervisorType> hypervisorTypeMap = new LinkedHashMap<>(); private static final Map<String, HypervisorType> hypervisorTypeMap = new LinkedHashMap<>();
public static final HypervisorType None = new HypervisorType("None"); //for storage hosts 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 XenServer = new HypervisorType("XenServer", ImageFormat.VHD, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
public static final HypervisorType KVM = new HypervisorType("KVM", ImageFormat.QCOW2); 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); 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 Hyperv = new HypervisorType("Hyperv");
public static final HypervisorType VirtualBox = new HypervisorType("VirtualBox"); public static final HypervisorType VirtualBox = new HypervisorType("VirtualBox");
public static final HypervisorType Parralels = new HypervisorType("Parralels"); public static final HypervisorType Parralels = new HypervisorType("Parralels");
public static final HypervisorType BareMetal = new HypervisorType("BareMetal"); 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 Ovm = new HypervisorType("Ovm", ImageFormat.RAW);
public static final HypervisorType Ovm3 = new HypervisorType("Ovm3", ImageFormat.RAW); public static final HypervisorType Ovm3 = new HypervisorType("Ovm3", ImageFormat.RAW);
public static final HypervisorType LXC = new HypervisorType("LXC"); 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*/ public static final HypervisorType Any = new HypervisorType("Any"); /*If you don't care about the hypervisor type*/
private final String name; private final String name;
private final ImageFormat imageFormat; private final ImageFormat imageFormat;
private final Set<Functionality> supportedFunctionalities;
public HypervisorType(String name) { public HypervisorType(String name) {
this(name, null); this(name, null, EnumSet.noneOf(Functionality.class));
} }
public HypervisorType(String name, ImageFormat imageFormat) { 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.name = name;
this.imageFormat = imageFormat; this.imageFormat = imageFormat;
this.supportedFunctionalities = supportedFunctionalities;
if (name.equals("Parralels")){ // typo in the original code if (name.equals("Parralels")){ // typo in the original code
hypervisorTypeMap.put("parallels", this); hypervisorTypeMap.put("parallels", this);
} else { } else {
@ -81,6 +101,12 @@ public class Hypervisor {
return hypervisorType; 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, * 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 * using the 'hypervisor.custom.display.name' setting. Otherwise, returns hypervisor name
@ -102,6 +128,15 @@ public class Hypervisor {
return 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 @Override
public int hashCode() { public int hashCode() {
return Objects.hash(name); return Objects.hash(name);

View File

@ -32,6 +32,8 @@ public interface ManagementServerHostStats {
String getManagementServerHostUuid(); String getManagementServerHostUuid();
long getManagementServerRunId();
long getSessions(); long getSessions();
double getCpuUtilization(); double getCpuUtilization();

View File

@ -93,4 +93,8 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity {
boolean isDefault(); boolean isDefault();
public void setApiKeyAccess(Boolean apiKeyAccess);
public Boolean getApiKeyAccess();
} }

View File

@ -19,6 +19,7 @@ package com.cloud.user;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.cloud.utils.Pair;
import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -127,9 +128,9 @@ public interface AccountService {
*/ */
UserAccount getUserAccountById(Long userId); 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 * Lists user two-factor authentication provider plugins

View File

@ -94,4 +94,9 @@ public interface User extends OwnedBy, InternalIdentity {
public boolean isUser2faEnabled(); public boolean isUser2faEnabled();
public String getKeyFor2fa(); public String getKeyFor2fa();
public void setApiKeyAccess(Boolean apiKeyAccess);
public Boolean getApiKeyAccess();
} }

View File

@ -35,6 +35,7 @@ public class ApiConstants {
public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm"; public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm";
public static final String ANNOTATION = "annotation"; public static final String ANNOTATION = "annotation";
public static final String API_KEY = "apikey"; 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 ARCHIVED = "archived";
public static final String ARCH = "arch"; public static final String ARCH = "arch";
public static final String AS_NUMBER = "asnumber"; public static final String AS_NUMBER = "asnumber";
@ -381,6 +382,14 @@ public class ApiConstants {
public static final String PATH = "path"; public static final String PATH = "path";
public static final String PAYLOAD = "payload"; public static final String PAYLOAD = "payload";
public static final String PAYLOAD_URL = "payloadurl"; public static final String PAYLOAD_URL = "payloadurl";
public static final String PEERS = "peers";
public static final String PEER_ID = "peerid";
public static final String PEER_NAME = "peername";
public static final String PEER_MSID = "peermsid";
public static final String PEER_RUNID = "peerrunid";
public static final String PEER_SERVICE_IP = "peerserviceip";
public static final String PEER_SERVICE_PORT = "peerserviceport";
public static final String PEER_STATE = "peerstate";
public static final String POD_ID = "podid"; public static final String POD_ID = "podid";
public static final String POD_NAME = "podname"; public static final String POD_NAME = "podname";
public static final String POD_IDS = "podids"; public static final String POD_IDS = "podids";
@ -986,6 +995,7 @@ public class ApiConstants {
public static final String ACL_NAME = "aclname"; public static final String ACL_NAME = "aclname";
public static final String NUMBER = "number"; public static final String NUMBER = "number";
public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable"; public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable";
public static final String ROUTED_MODE_ENABLED = "routedmodeenabled";
public static final String ROUTING = "isrouting"; public static final String ROUTING = "isrouting";
public static final String ROUTING_MODE = "routingmode"; public static final String ROUTING_MODE = "routingmode";
public static final String MAX_CONNECTIONS = "maxconnections"; public static final String MAX_CONNECTIONS = "maxconnections";
@ -1238,4 +1248,30 @@ public class ApiConstants {
public enum DomainDetails { public enum DomainDetails {
all, resource, min; 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;
}
}
}
} }

View File

@ -21,7 +21,9 @@ import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiCommandResourceType; 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.api.response.RoleResponse;
import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -40,8 +42,8 @@ import org.apache.cloudstack.region.RegionService;
import com.cloud.user.Account; import com.cloud.user.Account;
@APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {Account.class}, @APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {Account.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
public class UpdateAccountCmd extends BaseCmd { public class UpdateAccountCmd extends BaseCmd implements UserCmd {
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
//////////////// API parameters ///////////////////// //////////////// API parameters /////////////////////
@ -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") @Parameter(name = ApiConstants.ACCOUNT_DETAILS, type = CommandType.MAP, description = "Details for the account used to store specific parameters")
private Map details; 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 @Inject
RegionService _regionService; RegionService _regionService;
@ -109,6 +114,10 @@ public class UpdateAccountCmd extends BaseCmd {
return params; return params;
} }
public String getApiKeyAccess() {
return apiKeyAccess;
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -131,7 +140,7 @@ public class UpdateAccountCmd extends BaseCmd {
public void execute() { public void execute() {
Account result = _regionService.updateAccount(this); Account result = _regionService.updateAccount(this);
if (result != null){ if (result != null){
AccountResponse response = _responseGenerator.createAccountResponse(ResponseView.Full, result); AccountResponse response = _responseGenerator.createAccountResponse(getResponseView(), result);
response.setResponseName(getCommandName()); response.setResponseName(getCommandName());
setResponseObject(response); setResponseObject(response);
} else { } else {

View File

@ -23,6 +23,7 @@ import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ManagementServerResponse; import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.commons.lang3.BooleanUtils;
@APICommand(name = "listManagementServers", description = "Lists management servers.", responseObject = ManagementServerResponse.class, @APICommand(name = "listManagementServers", description = "Lists management servers.", responseObject = ManagementServerResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@ -39,6 +40,11 @@ public class ListMgmtsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the management server") @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the management server")
private String hostName; private String hostName;
@Parameter(name = ApiConstants.PEERS, type = CommandType.BOOLEAN,
description = "Whether to return the management server peers or not. By default, the management server peers will not be returned.",
since = "4.20.0.0")
private Boolean peers;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -51,6 +57,10 @@ public class ListMgmtsCmd extends BaseListCmd {
return hostName; return hostName;
} }
public Boolean getPeers() {
return BooleanUtils.toBooleanDefaultIfNull(peers, false);
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@ -20,6 +20,7 @@ package org.apache.cloudstack.api.command.admin.user;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.user.User; import com.cloud.user.User;
import com.cloud.utils.Pair;
import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
@ -54,11 +55,13 @@ public class GetUserKeysCmd extends BaseCmd{
else return Account.ACCOUNT_ID_SYSTEM; else return Account.ACCOUNT_ID_SYSTEM;
} }
public void execute(){ public void execute(){
Map<String, String> keys = _accountService.getKeys(this); Pair<Boolean, Map<String, String>> keys = _accountService.getKeys(this);
RegisterResponse response = new RegisterResponse(); RegisterResponse response = new RegisterResponse();
if(keys != null){ if(keys != null){
response.setApiKey(keys.get("apikey")); response.setApiKeyAccess(keys.first());
response.setSecretKey(keys.get("secretkey")); response.setApiKey(keys.second().get("apikey"));
response.setSecretKey(keys.second().get("secretkey"));
} }
response.setObjectName("userkeys"); response.setObjectName("userkeys");

View File

@ -19,20 +19,23 @@ package org.apache.cloudstack.api.command.admin.user;
import com.cloud.server.ResourceIcon; import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag;
import com.cloud.user.Account; 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.response.ResourceIconResponse;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListAccountResourcesCmd; import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
import org.apache.cloudstack.api.Parameter; 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.ListResponse;
import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserResponse;
import java.util.List; import java.util.List;
@APICommand(name = "listUsers", description = "Lists user accounts", responseObject = UserResponse.class, @APICommand(name = "listUsers", description = "Lists user accounts", responseObject = UserResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
public class ListUsersCmd extends BaseListAccountResourcesCmd { public class ListUsersCmd extends BaseListAccountResourcesCmd implements UserCmd {
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -53,6 +56,9 @@ public class ListUsersCmd extends BaseListAccountResourcesCmd {
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "List user by the username") @Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "List user by the username")
private String 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, @Parameter(name = ApiConstants.SHOW_RESOURCE_ICON, type = CommandType.BOOLEAN,
description = "flag to display the resource icon for users") description = "flag to display the resource icon for users")
private Boolean showIcon; private Boolean showIcon;
@ -77,6 +83,10 @@ public class ListUsersCmd extends BaseListAccountResourcesCmd {
return username; return username;
} }
public String getApiKeyAccess() {
return apiKeyAccess;
}
public Boolean getShowIcon() { public Boolean getShowIcon() {
return showIcon != null ? showIcon : false; return showIcon != null ? showIcon : false;
} }
@ -87,7 +97,7 @@ public class ListUsersCmd extends BaseListAccountResourcesCmd {
@Override @Override
public void execute() { public void execute() {
ListResponse<UserResponse> response = _queryService.searchForUsers(this); ListResponse<UserResponse> response = _queryService.searchForUsers(getResponseView(), this);
response.setResponseName(getCommandName()); response.setResponseName(getCommandName());
this.setResponseObject(response); this.setResponseObject(response);
if (response != null && response.getCount() > 0 && getShowIcon()) { if (response != null && response.getCount() > 0 && getShowIcon()) {

View File

@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.admin.user;
import javax.inject.Inject; import javax.inject.Inject;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
@ -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") @Parameter(name = ApiConstants.USER_SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey")
private String secretKey; 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, @Parameter(name = ApiConstants.TIMEZONE,
type = CommandType.STRING, type = CommandType.STRING,
description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.") description = "Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format.")
@ -120,6 +124,10 @@ public class UpdateUserCmd extends BaseCmd {
return secretKey; return secretKey;
} }
public String getApiKeyAccess() {
return apiKeyAccess;
}
public String getTimezone() { public String getTimezone() {
return timezone; return timezone;
} }

View File

@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
@ -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]") description = "comma separated list of account details requested, value can be a list of [ all, resource, min]")
private List<String> viewDetails; 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, @Parameter(name = ApiConstants.SHOW_RESOURCE_ICON, type = CommandType.BOOLEAN,
description = "flag to display the resource icon for accounts") description = "flag to display the resource icon for accounts")
private Boolean showIcon; private Boolean showIcon;
@ -120,6 +124,10 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC
return dv; return dv;
} }
public String getApiKeyAccess() {
return apiKeyAccess;
}
public boolean getShowIcon() { public boolean getShowIcon() {
return showIcon != null ? showIcon : false; return showIcon != null ? showIcon : false;
} }

View File

@ -362,7 +362,9 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
"Parameter zoneids cannot combine all zones (-1) option with other zones"); "Parameter zoneids cannot combine all zones (-1) option with other zones");
String customHypervisor = HypervisorGuru.HypervisorCustomDisplayName.value(); 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))) { || getHypervisor().equalsIgnoreCase(customHypervisor))) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Parameter directdownload " + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Parameter directdownload " +
"is only allowed for KVM or %s templates", customHypervisor)); "is only allowed for KVM or %s templates", customHypervisor));

View File

@ -73,6 +73,10 @@ public class ResizeVolumeCmd extends BaseAsyncCmd implements UserCmd {
description = "new disk offering id") description = "new disk offering id")
private Long newDiskOfferingId; private Long newDiskOfferingId;
@Parameter(name = ApiConstants.AUTO_MIGRATE, type = CommandType.BOOLEAN, required = false,
description = "Flag to allow automatic migration of the volume to another suitable storage pool that accommodates the new size", since = "4.20.1")
private Boolean autoMigrate;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -129,6 +133,10 @@ public class ResizeVolumeCmd extends BaseAsyncCmd implements UserCmd {
return newDiskOfferingId; return newDiskOfferingId;
} }
public boolean getAutoMigrate() {
return autoMigrate == null ? false : autoMigrate;
}
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////// API Implementation/////////////////// /////////////// API Implementation///////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@ -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") @Param(description = "The tagged resource limit and count for the account", since = "4.20.0")
List<TaggedResourceLimitAndCountResponse> taggedResources; 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 @Override
public String getObjectId() { public String getObjectId() {
return id; return id;
@ -554,4 +558,8 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou
public void setTaggedResourceLimitsAndCounts(List<TaggedResourceLimitAndCountResponse> taggedResourceLimitsAndCounts) { public void setTaggedResourceLimitsAndCounts(List<TaggedResourceLimitAndCountResponse> taggedResourceLimitsAndCounts) {
this.taggedResources = taggedResourceLimitsAndCounts; this.taggedResources = taggedResourceLimitsAndCounts;
} }
public void setApiKeyAccess(Boolean apiKeyAccess) {
this.apiKeyAccess = ApiConstants.ApiKeyAccess.fromBoolean(apiKeyAccess);
}
} }

View File

@ -24,7 +24,9 @@ import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference; import org.apache.cloudstack.api.EntityReference;
import org.apache.cloudstack.management.ManagementServerHost.State; import org.apache.cloudstack.management.ManagementServerHost.State;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
@EntityReference(value = ManagementServerHost.class) @EntityReference(value = ManagementServerHost.class)
public class ManagementServerResponse extends BaseResponse { public class ManagementServerResponse extends BaseResponse {
@ -76,6 +78,10 @@ public class ManagementServerResponse extends BaseResponse {
@Param(description = "the IP Address for this Management Server") @Param(description = "the IP Address for this Management Server")
private String serviceIp; private String serviceIp;
@SerializedName(ApiConstants.PEERS)
@Param(description = "the Management Server Peers")
private List<PeerManagementServerNodeResponse> peers;
public String getId() { public String getId() {
return this.id; return this.id;
} }
@ -171,4 +177,19 @@ public class ManagementServerResponse extends BaseResponse {
public String getKernelVersion() { public String getKernelVersion() {
return kernelVersion; return kernelVersion;
} }
public List<PeerManagementServerNodeResponse> getPeers() {
return peers;
}
public void setPeers(List<PeerManagementServerNodeResponse> peers) {
this.peers = peers;
}
public void addPeer(PeerManagementServerNodeResponse peer) {
if (peers == null) {
peers = new ArrayList<>();
}
peers.add(peer);
}
} }

View File

@ -0,0 +1,100 @@
// 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 com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.management.ManagementServerHost.State;
import java.util.Date;
public class PeerManagementServerNodeResponse extends BaseResponse {
@SerializedName(ApiConstants.STATE)
@Param(description = "the state of the management server peer")
private State state;
@SerializedName(ApiConstants.LAST_UPDATED)
@Param(description = "the last updated time of the management server peer state")
private Date lastUpdated;
@SerializedName(ApiConstants.PEER_ID)
@Param(description = "the ID of the peer management server")
private String peerId;
@SerializedName(ApiConstants.PEER_NAME)
@Param(description = "the name of the peer management server")
private String peerName;
@SerializedName(ApiConstants.PEER_MSID)
@Param(description = "the management ID of the peer management server")
private String peerMsId;
@SerializedName(ApiConstants.PEER_RUNID)
@Param(description = "the run ID of the peer management server")
private String peerRunId;
@SerializedName(ApiConstants.PEER_STATE)
@Param(description = "the state of the peer management server")
private String peerState;
@SerializedName(ApiConstants.PEER_SERVICE_IP)
@Param(description = "the IP Address for the peer Management Server")
private String peerServiceIp;
@SerializedName(ApiConstants.PEER_SERVICE_PORT)
@Param(description = "the service port for the peer Management Server")
private String peerServicePort;
public void setState(State state) {
this.state = state;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public void setPeerId(String peerId) {
this.peerId = peerId;
}
public void setPeerName(String peerName) {
this.peerName = peerName;
}
public void setPeerMsId(String peerMsId) {
this.peerMsId = peerMsId;
}
public void setPeerRunId(String peerRunId) {
this.peerRunId = peerRunId;
}
public void setPeerState(String peerState) {
this.peerState = peerState;
}
public void setPeerServiceIp(String peerServiceIp) {
this.peerServiceIp = peerServiceIp;
}
public void setPeerServicePort(String peerServicePort) {
this.peerServicePort = peerServicePort;
}
}

View File

@ -18,19 +18,24 @@ package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param; import com.cloud.serializer.Param;
public class RegisterResponse extends BaseResponse { public class RegisterResponse extends BaseResponse {
@SerializedName("apikey") @SerializedName(ApiConstants.API_KEY)
@Param(description = "the api key of the registered user", isSensitive = true) @Param(description = "the api key of the registered user", isSensitive = true)
private String apiKey; private String apiKey;
@SerializedName("secretkey") @SerializedName(ApiConstants.SECRET_KEY)
@Param(description = "the secret key of the registered user", isSensitive = true) @Param(description = "the secret key of the registered user", isSensitive = true)
private String secretKey; private String secretKey;
@SerializedName(ApiConstants.API_KEY_ACCESS)
@Param(description = "whether api key access is allowed or not", isSensitive = true)
private Boolean apiKeyAccess;
public String getApiKey() { public String getApiKey() {
return apiKey; return apiKey;
} }
@ -46,4 +51,8 @@ public class RegisterResponse extends BaseResponse {
public void setSecretKey(String secretKey) { public void setSecretKey(String secretKey) {
this.secretKey = secretKey; this.secretKey = secretKey;
} }
public void setApiKeyAccess(Boolean apiKeyAccess) {
this.apiKeyAccess = apiKeyAccess;
}
} }

View File

@ -128,6 +128,10 @@ public class UserResponse extends BaseResponse implements SetResourceIconRespons
@Param(description = "true if user has two factor authentication is mandated", since = "4.18.0.0") @Param(description = "true if user has two factor authentication is mandated", since = "4.18.0.0")
private Boolean is2FAmandated; private Boolean is2FAmandated;
@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 @Override
public String getObjectId() { public String getObjectId() {
return this.getId(); return this.getId();
@ -309,4 +313,8 @@ public class UserResponse extends BaseResponse implements SetResourceIconRespons
public void set2FAmandated(Boolean is2FAmandated) { public void set2FAmandated(Boolean is2FAmandated) {
this.is2FAmandated = is2FAmandated; this.is2FAmandated = is2FAmandated;
} }
public void setApiKeyAccess(Boolean apiKeyAccess) {
this.apiKeyAccess = ApiConstants.ApiKeyAccess.fromBoolean(apiKeyAccess);
}
} }

View File

@ -157,6 +157,11 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
@Param(description = "AS Number Range") @Param(description = "AS Number Range")
private String asnRange; private String asnRange;
@SerializedName(ApiConstants.ROUTED_MODE_ENABLED)
@Param(description = "true, if routed network/vpc is enabled", since = "4.20.1")
private boolean routedModeEnabled = false;
public ZoneResponse() { public ZoneResponse() {
tags = new LinkedHashSet<ResourceTagResponse>(); tags = new LinkedHashSet<ResourceTagResponse>();
} }
@ -412,4 +417,12 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
public String getAsnRange() { public String getAsnRange() {
return asnRange; return asnRange;
} }
public boolean isRoutedModeEnabled() {
return routedModeEnabled;
}
public void setRoutedModeEnabled(boolean routedModeEnabled) {
this.routedModeEnabled = routedModeEnabled;
}
} }

View File

@ -57,6 +57,13 @@ import java.util.List;
public interface RoutedIpv4Manager extends PluggableService, Configurable { public interface RoutedIpv4Manager extends PluggableService, Configurable {
ConfigKey<Boolean> RoutedNetworkVpcEnabled = new ConfigKey<>(ConfigKey.CATEGORY_NETWORK, Boolean.class,
"routed.network.vpc.enabled",
"true",
"If true, the Routed network and VPC are enabled in the zone.",
true,
ConfigKey.Scope.Zone);
ConfigKey<Integer> RoutedNetworkIPv4MaxCidrSize = new ConfigKey<>(ConfigKey.CATEGORY_NETWORK, Integer.class, ConfigKey<Integer> RoutedNetworkIPv4MaxCidrSize = new ConfigKey<>(ConfigKey.CATEGORY_NETWORK, Integer.class,
"routed.network.ipv4.max.cidr.size", "30", "The maximum value of the cidr size for isolated networks in ROUTED mode", "routed.network.ipv4.max.cidr.size", "30", "The maximum value of the cidr size for isolated networks in ROUTED mode",
true, ConfigKey.Scope.Account); true, ConfigKey.Scope.Account);
@ -196,4 +203,6 @@ public interface RoutedIpv4Manager extends PluggableService, Configurable {
void removeBgpPeersByAccountId(long accountId); void removeBgpPeersByAccountId(long accountId);
void removeBgpPeersByDomainId(long domainId); void removeBgpPeersByDomainId(long domainId);
Boolean isRoutedNetworkVpcEnabled(long zoneId);
} }

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.query;
import java.util.List; import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd; import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd;
import org.apache.cloudstack.api.command.admin.host.ListHostTagsCmd; import org.apache.cloudstack.api.command.admin.host.ListHostTagsCmd;
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
@ -130,7 +131,7 @@ public interface QueryService {
ConfigKey<Boolean> ReturnVmStatsOnVmList = new ConfigKey<>("Advanced", Boolean.class, "list.vm.default.details.stats", "true", ConfigKey<Boolean> ReturnVmStatsOnVmList = new ConfigKey<>("Advanced", Boolean.class, "list.vm.default.details.stats", "true",
"Determines whether VM stats should be returned when details are not explicitly specified in listVirtualMachines API request. When false, details default to [group, nics, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp]. When true, all details are returned including 'stats'.", true, ConfigKey.Scope.Global); "Determines whether VM stats should be returned when details are not explicitly specified in listVirtualMachines API request. When false, details default to [group, nics, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp]. When true, all details are returned including 'stats'.", true, ConfigKey.Scope.Global);
ListResponse<UserResponse> searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException; ListResponse<UserResponse> searchForUsers(ResponseObject.ResponseView responseView, ListUsersCmd cmd) throws PermissionDeniedException;
ListResponse<UserResponse> searchForUsers(Long domainId, boolean recursive) throws PermissionDeniedException; ListResponse<UserResponse> searchForUsers(Long domainId, boolean recursive) throws PermissionDeniedException;

View File

@ -40,6 +40,7 @@ public interface CapacityManager {
static final String StorageCapacityDisableThresholdCK = "pool.storage.capacity.disablethreshold"; static final String StorageCapacityDisableThresholdCK = "pool.storage.capacity.disablethreshold";
static final String StorageOverprovisioningFactorCK = "storage.overprovisioning.factor"; static final String StorageOverprovisioningFactorCK = "storage.overprovisioning.factor";
static final String StorageAllocatedCapacityDisableThresholdCK = "pool.storage.allocated.capacity.disablethreshold"; static final String StorageAllocatedCapacityDisableThresholdCK = "pool.storage.allocated.capacity.disablethreshold";
static final String StorageAllocatedCapacityDisableThresholdForVolumeResizeCK = "pool.storage.allocated.resize.capacity.disablethreshold";
static final ConfigKey<Float> CpuOverprovisioningFactor = static final ConfigKey<Float> CpuOverprovisioningFactor =
new ConfigKey<>( new ConfigKey<>(
@ -118,6 +119,17 @@ public interface CapacityManager {
"Percentage (as a value between 0 and 1) of secondary storage capacity threshold.", "Percentage (as a value between 0 and 1) of secondary storage capacity threshold.",
true); true);
static final ConfigKey<Double> StorageAllocatedCapacityDisableThresholdForVolumeSize =
new ConfigKey<>(
ConfigKey.CATEGORY_ALERT,
Double.class,
StorageAllocatedCapacityDisableThresholdForVolumeResizeCK,
"0.90",
"Percentage (as a value between 0 and 1) of allocated storage utilization above which allocators will disable using the pool for volume resize. " +
"This is applicable only when volume.resize.allowed.beyond.allocation is set to true.",
true,
ConfigKey.Scope.Zone);
public boolean releaseVmCapacity(VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId); public boolean releaseVmCapacity(VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId);
void allocateVmCapacity(VirtualMachine vm, boolean fromLastHost); void allocateVmCapacity(VirtualMachine vm, boolean fromLastHost);

View File

@ -209,6 +209,11 @@ public interface StorageManager extends StorageService {
ConfigKey<Long> HEURISTICS_SCRIPT_TIMEOUT = new ConfigKey<>("Advanced", Long.class, "heuristics.script.timeout", "3000", ConfigKey<Long> HEURISTICS_SCRIPT_TIMEOUT = new ConfigKey<>("Advanced", Long.class, "heuristics.script.timeout", "3000",
"The maximum runtime, in milliseconds, to execute the heuristic rule; if it is reached, a timeout will happen.", true); "The maximum runtime, in milliseconds, to execute the heuristic rule; if it is reached, a timeout will happen.", true);
ConfigKey<Boolean> AllowVolumeReSizeBeyondAllocation = new ConfigKey<Boolean>("Advanced", Boolean.class, "volume.resize.allowed.beyond.allocation", "false",
"Determines whether volume size can exceed the pool capacity allocation disable threshold (pool.storage.allocated.capacity.disablethreshold) " +
"when resize a volume upto resize capacity disable threshold (pool.storage.allocated.resize.capacity.disablethreshold)",
true, ConfigKey.Scope.Zone);
/** /**
* should we execute in sequence not involving any storages? * should we execute in sequence not involving any storages?
* @return tru if commands should execute in sequence * @return tru if commands should execute in sequence

View File

@ -31,7 +31,7 @@ public interface VMSnapshotManager extends VMSnapshotService, Manager {
static final ConfigKey<Integer> VMSnapshotExpireInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vmsnapshot.expire.interval", "-1", static final ConfigKey<Integer> VMSnapshotExpireInterval = new ConfigKey<Integer>("Advanced", Integer.class, "vmsnapshot.expire.interval", "-1",
"VM Snapshot expire interval in hours", true, ConfigKey.Scope.Account); "VM Snapshot expire interval in hours", true, ConfigKey.Scope.Account);
public static final int VMSNAPSHOTMAX = 10; ConfigKey<Integer> VMSnapshotMax = new ConfigKey<Integer>("Advanced", Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a single vm", true, ConfigKey.Scope.Global);
/** /**
* Delete all VM snapshots belonging to one VM * Delete all VM snapshots belonging to one VM

View File

@ -88,6 +88,7 @@ import com.cloud.upgrade.dao.Upgrade41800to41810;
import com.cloud.upgrade.dao.Upgrade41810to41900; import com.cloud.upgrade.dao.Upgrade41810to41900;
import com.cloud.upgrade.dao.Upgrade41900to41910; import com.cloud.upgrade.dao.Upgrade41900to41910;
import com.cloud.upgrade.dao.Upgrade41910to42000; import com.cloud.upgrade.dao.Upgrade41910to42000;
import com.cloud.upgrade.dao.Upgrade42000to42010;
import com.cloud.upgrade.dao.Upgrade420to421; import com.cloud.upgrade.dao.Upgrade420to421;
import com.cloud.upgrade.dao.Upgrade421to430; import com.cloud.upgrade.dao.Upgrade421to430;
import com.cloud.upgrade.dao.Upgrade430to440; import com.cloud.upgrade.dao.Upgrade430to440;
@ -230,6 +231,7 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
.next("4.18.1.0", new Upgrade41810to41900()) .next("4.18.1.0", new Upgrade41810to41900())
.next("4.19.0.0", new Upgrade41900to41910()) .next("4.19.0.0", new Upgrade41900to41910())
.next("4.19.1.0", new Upgrade41910to42000()) .next("4.19.1.0", new Upgrade41910to42000())
.next("4.20.0.0", new Upgrade42000to42010())
.build(); .build();
} }

View File

@ -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 com.cloud.upgrade.dao;
import java.io.InputStream;
import java.sql.Connection;
import com.cloud.upgrade.SystemVmTemplateRegistration;
import com.cloud.utils.exception.CloudRuntimeException;
public class Upgrade42000to42010 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate {
private SystemVmTemplateRegistration systemVmTemplateRegistration;
@Override
public String[] getUpgradableVersionRange() {
return new String[] {"4.20.0.0", "4.20.1.0"};
}
@Override
public String getUpgradedVersion() {
return "4.20.1.0";
}
@Override
public boolean supportsRollingUpgrade() {
return false;
}
@Override
public InputStream[] getPrepareScripts() {
final String scriptFile = "META-INF/db/schema-42000to42010.sql";
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
if (script == null) {
throw new CloudRuntimeException("Unable to find " + scriptFile);
}
return new InputStream[] {script};
}
@Override
public void performDataMigration(Connection conn) {
}
@Override
public InputStream[] getCleanupScripts() {
final String scriptFile = "META-INF/db/schema-42000to42010-cleanup.sql";
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
if (script == null) {
throw new CloudRuntimeException("Unable to find " + scriptFile);
}
return new InputStream[] {script};
}
private void initSystemVmTemplateRegistration() {
systemVmTemplateRegistration = new SystemVmTemplateRegistration("");
}
@Override
public void updateSystemVmTemplates(Connection conn) {
logger.debug("Updating System Vm template IDs");
initSystemVmTemplateRegistration();
try {
systemVmTemplateRegistration.updateSystemVmTemplates(conn);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to find / register SystemVM template(s)");
}
}
}

View File

@ -77,6 +77,9 @@ public class AccountVO implements Account {
@Column(name = "default") @Column(name = "default")
boolean isDefault; boolean isDefault;
@Column(name = "api_key_access")
private Boolean apiKeyAccess;
public AccountVO() { public AccountVO() {
uuid = UUID.randomUUID().toString(); uuid = UUID.randomUUID().toString();
} }
@ -229,4 +232,14 @@ public class AccountVO implements Account {
public String reflectionToString() { public String reflectionToString() {
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "uuid", "accountName", "domainId"); return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "uuid", "accountName", "domainId");
} }
@Override
public void setApiKeyAccess(Boolean apiKeyAccess) {
this.apiKeyAccess = apiKeyAccess;
}
@Override
public Boolean getApiKeyAccess() {
return apiKeyAccess;
}
} }

View File

@ -115,6 +115,9 @@ public class UserVO implements User, Identity, InternalIdentity {
@Column(name = "key_for_2fa") @Column(name = "key_for_2fa")
private String keyFor2fa; private String keyFor2fa;
@Column(name = "api_key_access")
private Boolean apiKeyAccess;
public UserVO() { public UserVO() {
this.uuid = UUID.randomUUID().toString(); this.uuid = UUID.randomUUID().toString();
} }
@ -350,4 +353,13 @@ public class UserVO implements User, Identity, InternalIdentity {
this.user2faProvider = user2faProvider; this.user2faProvider = user2faProvider;
} }
@Override
public void setApiKeyAccess(Boolean apiKeyAccess) {
this.apiKeyAccess = apiKeyAccess;
}
@Override
public Boolean getApiKeyAccess() {
return apiKeyAccess;
}
} }

View File

@ -41,8 +41,8 @@ import java.util.List;
@Component @Component
public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements AccountDao { public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements AccountDao {
private static final String FIND_USER_ACCOUNT_BY_API_KEY = "SELECT u.id, u.username, u.account_id, u.secret_key, u.state, " private static final String FIND_USER_ACCOUNT_BY_API_KEY = "SELECT u.id, u.username, u.account_id, u.secret_key, u.state, u.api_key_access, "
+ "a.id, a.account_name, a.type, a.role_id, a.domain_id, a.state " + "FROM `cloud`.`user` u, `cloud`.`account` a " + "a.id, a.account_name, a.type, a.role_id, a.domain_id, a.state, a.api_key_access " + "FROM `cloud`.`user` u, `cloud`.`account` a "
+ "WHERE u.account_id = a.id AND u.api_key = ? and u.removed IS NULL"; + "WHERE u.account_id = a.id AND u.api_key = ? and u.removed IS NULL";
protected final SearchBuilder<AccountVO> AllFieldsSearch; protected final SearchBuilder<AccountVO> AllFieldsSearch;
@ -148,13 +148,25 @@ public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements A
u.setAccountId(rs.getLong(3)); u.setAccountId(rs.getLong(3));
u.setSecretKey(DBEncryptionUtil.decrypt(rs.getString(4))); u.setSecretKey(DBEncryptionUtil.decrypt(rs.getString(4)));
u.setState(State.getValueOf(rs.getString(5))); u.setState(State.getValueOf(rs.getString(5)));
boolean apiKeyAccess = rs.getBoolean(6);
if (rs.wasNull()) {
u.setApiKeyAccess(null);
} else {
u.setApiKeyAccess(apiKeyAccess);
}
AccountVO a = new AccountVO(rs.getLong(6)); AccountVO a = new AccountVO(rs.getLong(7));
a.setAccountName(rs.getString(7)); a.setAccountName(rs.getString(8));
a.setType(Account.Type.getFromValue(rs.getInt(8))); a.setType(Account.Type.getFromValue(rs.getInt(9)));
a.setRoleId(rs.getLong(9)); a.setRoleId(rs.getLong(10));
a.setDomainId(rs.getLong(10)); a.setDomainId(rs.getLong(11));
a.setState(State.getValueOf(rs.getString(11))); a.setState(State.getValueOf(rs.getString(12)));
apiKeyAccess = rs.getBoolean(13);
if (rs.wasNull()) {
a.setApiKeyAccess(null);
} else {
a.setApiKeyAccess(apiKeyAccess);
}
userAcctPair = new Pair<User, Account>(u, a); userAcctPair = new Pair<User, Account>(u, a);
} }

View File

@ -117,6 +117,7 @@
<bean id="loadBalancerCertMapDaoImpl" class="com.cloud.network.dao.LoadBalancerCertMapDaoImpl" /> <bean id="loadBalancerCertMapDaoImpl" class="com.cloud.network.dao.LoadBalancerCertMapDaoImpl" />
<bean id="managementServerHostDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostDaoImpl" /> <bean id="managementServerHostDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostDaoImpl" />
<bean id="managementServerHostPeerDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostPeerDaoImpl" /> <bean id="managementServerHostPeerDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostPeerDaoImpl" />
<bean id="managementServerHostPeerJoinDaoImpl" class="com.cloud.cluster.dao.ManagementServerHostPeerJoinDaoImpl" />
<bean id="managementServerStatusDaoImpl" class="com.cloud.cluster.dao.ManagementServerStatusDaoImpl" /> <bean id="managementServerStatusDaoImpl" class="com.cloud.cluster.dao.ManagementServerStatusDaoImpl" />
<bean id="networkAccountDaoImpl" class="com.cloud.network.dao.NetworkAccountDaoImpl" /> <bean id="networkAccountDaoImpl" class="com.cloud.network.dao.NetworkAccountDaoImpl" />
<bean id="networkACLDaoImpl" class="com.cloud.network.vpc.dao.NetworkACLDaoImpl" /> <bean id="networkACLDaoImpl" class="com.cloud.network.vpc.dao.NetworkACLDaoImpl" />

View File

@ -0,0 +1,28 @@
-- 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.
DROP PROCEDURE IF EXISTS `cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY`;
CREATE PROCEDURE `cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY` (
IN in_table_name VARCHAR(200)
, IN in_key_name VARCHAR(200)
, IN in_foreign_key VARCHAR(200)
, IN in_references VARCHAR(1000)
)
BEGIN
DECLARE CONTINUE HANDLER FOR 1061 BEGIN END; SET @ddl = CONCAT_WS(' ', 'ALTER TABLE ', in_table_name, ' ADD CONSTRAINT ', in_key_name, ' FOREIGN KEY ', in_foreign_key, ' REFERENCES ', in_references, ' ON DELETE CASCADE'); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; END;

View File

@ -425,3 +425,10 @@ INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (uuid, hypervisor_type, hypervi
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vm_instance', 'delete_protection', 'boolean DEFAULT FALSE COMMENT "delete protection for vm" '); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vm_instance', 'delete_protection', 'boolean DEFAULT FALSE COMMENT "delete protection for vm" ');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.volumes', 'delete_protection', 'boolean DEFAULT FALSE COMMENT "delete protection for volumes" '); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.volumes', 'delete_protection', 'boolean DEFAULT FALSE COMMENT "delete protection for volumes" ');
-- Modify index for mshost_peer
DELETE FROM `cloud`.`mshost_peer`;
CALL `cloud`.`IDEMPOTENT_DROP_FOREIGN_KEY`('cloud.mshost_peer','fk_mshost_peer__owner_mshost');
CALL `cloud`.`IDEMPOTENT_DROP_INDEX`('i_mshost_peer__owner_peer_runid','mshost_peer');
CALL `cloud`.`IDEMPOTENT_ADD_UNIQUE_KEY`('cloud.mshost_peer', 'i_mshost_peer__owner_peer', '(owner_mshost, peer_mshost)');
CALL `cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY`('cloud.mshost_peer', 'fk_mshost_peer__owner_mshost', '(owner_mshost)', '`mshost`(`id`)');

View File

@ -0,0 +1,20 @@
-- 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.
--;
-- Schema upgrade cleanup from 4.20.0.0 to 4.20.1.0
--;

View File

@ -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.
--;
-- Schema upgrade from 4.20.0.0 to 4.20.1.0
--;
-- Add column api_key_access to user and account tables
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.user', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the user" AFTER `secret_key`');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.account', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the account" ');

View File

@ -31,6 +31,7 @@ select
`account`.`cleanup_needed` AS `cleanup_needed`, `account`.`cleanup_needed` AS `cleanup_needed`,
`account`.`network_domain` AS `network_domain` , `account`.`network_domain` AS `network_domain` ,
`account`.`default` AS `default`, `account`.`default` AS `default`,
`account`.`api_key_access` AS `api_key_access`,
`domain`.`id` AS `domain_id`, `domain`.`id` AS `domain_id`,
`domain`.`uuid` AS `domain_uuid`, `domain`.`uuid` AS `domain_uuid`,
`domain`.`name` AS `domain_name`, `domain`.`name` AS `domain_name`,

View File

@ -0,0 +1,44 @@
-- 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.
DROP VIEW IF EXISTS `cloud`.`mshost_peer_view`;
CREATE VIEW `cloud`.`mshost_peer_view` AS
SELECT
`mshost_peer`.`id` AS `id`,
`mshost_peer`.`peer_state` AS `peer_state`,
`mshost_peer`.`last_update` AS `last_update`,
`owner_mshost`.`id` AS `owner_mshost_id`,
`owner_mshost`.`msid` AS `owner_mshost_msid`,
`owner_mshost`.`runid` AS `owner_mshost_runid`,
`owner_mshost`.`name` AS `owner_mshost_name`,
`owner_mshost`.`uuid` AS `owner_mshost_uuid`,
`owner_mshost`.`state` AS `owner_mshost_state`,
`owner_mshost`.`service_ip` AS `owner_mshost_service_ip`,
`owner_mshost`.`service_port` AS `owner_mshost_service_port`,
`peer_mshost`.`id` AS `peer_mshost_id`,
`peer_mshost`.`msid` AS `peer_mshost_msid`,
`peer_mshost`.`runid` AS `peer_mshost_runid`,
`peer_mshost`.`name` AS `peer_mshost_name`,
`peer_mshost`.`uuid` AS `peer_mshost_uuid`,
`peer_mshost`.`state` AS `peer_mshost_state`,
`peer_mshost`.`service_ip` AS `peer_mshost_service_ip`,
`peer_mshost`.`service_port` AS `peer_mshost_service_port`
FROM `cloud`.`mshost_peer`
LEFT JOIN `cloud`.`mshost` AS owner_mshost on `mshost_peer`.`owner_mshost` = `owner_mshost`.`id`
LEFT JOIN `cloud`.`mshost` AS peer_mshost on `mshost_peer`.`peer_mshost` = `peer_mshost`.`id`;

View File

@ -39,6 +39,7 @@ select
user.incorrect_login_attempts, user.incorrect_login_attempts,
user.source, user.source,
user.default, user.default,
user.api_key_access,
account.id account_id, account.id account_id,
account.uuid account_uuid, account.uuid account_uuid,
account.account_name account_name, account.account_name account_name,

View File

@ -419,7 +419,7 @@ public class DefaultVMSnapshotStrategy extends ManagerBase implements VMSnapshot
if (answer != null && answer.getDetails() != null) if (answer != null && answer.getDetails() != null)
errMsg = errMsg + " due to " + answer.getDetails(); errMsg = errMsg + " due to " + answer.getDetails();
logger.error(errMsg); logger.error(errMsg);
throw new CloudRuntimeException(errMsg); throw new CloudRuntimeException(String.format("Unable to revert VM %s to snapshot %s.", userVm.getInstanceName(), vmSnapshotVO.getName()));
} }
} catch (OperationTimedoutException e) { } catch (OperationTimedoutException e) {
logger.debug("Failed to revert vm snapshot", e); logger.debug("Failed to revert vm snapshot", e);

View File

@ -27,9 +27,9 @@ import com.cloud.utils.component.Manager;
public interface ClusterManager extends Manager { public interface ClusterManager extends Manager {
static final String ALERT_SUBJECT = "cluster-alert"; static final String ALERT_SUBJECT = "cluster-alert";
final ConfigKey<Integer> HeartbeatInterval = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.interval", "management-server", "1500", final ConfigKey<Integer> HeartbeatInterval = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.interval", "management-server", "1500",
"Interval to check for the heart beat between management server nodes", false); "Interval (in milliseconds) to check for the heart beat between management server nodes", false);
final ConfigKey<Integer> HeartbeatThreshold = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.threshold", "management-server", "150000", final ConfigKey<Integer> HeartbeatThreshold = new ConfigKey<Integer>(Integer.class, "cluster.heartbeat.threshold", "management-server", "150000",
"Threshold before self-fence the management server", true); "Threshold (in milliseconds) before self-fence the management server. The threshold should be larger than management.server.stats.interval", true);
/** /**
* Adds a new packet to the incoming queue. * Adds a new packet to the incoming queue.

View File

@ -758,24 +758,19 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
} }
switch (msg.getMessageType()) { switch (msg.getMessageType()) {
case nodeAdded: { case nodeAdded:
final List<ManagementServerHostVO> l = msg.getNodes();
if (l != null && l.size() > 0) {
for (final ManagementServerHostVO mshost : l) {
_mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Up);
}
}
}
break; break;
case nodeRemoved: { case nodeRemoved: {
final List<ManagementServerHostVO> l = msg.getNodes(); final List<ManagementServerHostVO> l = msg.getNodes();
if (l != null && l.size() > 0) { if (l != null && l.size() > 0) {
for (final ManagementServerHostVO mshost : l) { for (final ManagementServerHostVO mshost : l) {
if (mshost.getId() != _mshostId) {
_mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Down); _mshostPeerDao.updatePeerInfo(_mshostId, mshost.getId(), mshost.getRunid(), ManagementServerHost.State.Down);
} }
} }
} }
}
break; break;
default: default:
@ -823,8 +818,9 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
final List<ManagementServerHostVO> downHostList = new ArrayList<ManagementServerHostVO>(); final List<ManagementServerHostVO> downHostList = new ArrayList<ManagementServerHostVO>();
for (final ManagementServerHostVO host : inactiveList) { for (final ManagementServerHostVO host : inactiveList) {
if (!pingManagementNode(host)) { // Check if peer state is Up in the period
logger.warn("Management node " + host.getId() + " is detected inactive by timestamp and also not pingable"); if (!_mshostPeerDao.isPeerUpState(_mshostId, host.getId(), new Date(cutTime.getTime() - HeartbeatThreshold.value()))) {
logger.warn("Management node " + host.getId() + " is detected inactive by timestamp and did not send node status to this node");
downHostList.add(host); downHostList.add(host);
} }
} }
@ -898,6 +894,44 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
final Profiler profilerInvalidatedNodeList = new Profiler(); final Profiler profilerInvalidatedNodeList = new Profiler();
profilerInvalidatedNodeList.start(); profilerInvalidatedNodeList.start();
processInvalidatedNodes(invalidatedNodeList);
profilerInvalidatedNodeList.stop();
final Profiler profilerRemovedList = new Profiler();
profilerRemovedList.start();
processRemovedNodes(cutTime, removedNodeList);
profilerRemovedList.stop();
final Profiler profilerNewList = new Profiler();
profilerNewList.start();
processNewNodes(cutTime, currentList);
profilerNewList.stop();
final Profiler profilerInactiveList = new Profiler();
profilerInactiveList.start();
processInactiveNodes(cutTime);
profilerInactiveList.stop();
profiler.stop();
logger.debug(String.format("Peer scan is finished. profiler: %s , profilerQueryActiveList: %s, " +
", profilerSyncClusterInfo: %s, profilerInvalidatedNodeList: %s, profilerRemovedList: %s," +
", profilerNewList: %s, profilerInactiveList: %s",
profiler, profilerQueryActiveList, profilerSyncClusterInfo, profilerInvalidatedNodeList, profilerRemovedList,
profilerNewList, profilerInactiveList));
if (profiler.getDurationInMillis() >= HeartbeatInterval.value()) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Peer scan takes too long to finish. profiler: %s , profilerQueryActiveList: %s, " +
", profilerSyncClusterInfo: %s, profilerInvalidatedNodeList: %s, profilerRemovedList: %s," +
", profilerNewList: %s, profilerInactiveList: %s",
profiler, profilerQueryActiveList, profilerSyncClusterInfo, profilerInvalidatedNodeList, profilerRemovedList,
profilerNewList, profilerInactiveList));
}
}
}
private void processInvalidatedNodes(List<ManagementServerHostVO> invalidatedNodeList) {
// process invalidated node list // process invalidated node list
if (invalidatedNodeList.size() > 0) { if (invalidatedNodeList.size() > 0) {
for (final ManagementServerHostVO mshost : invalidatedNodeList) { for (final ManagementServerHostVO mshost : invalidatedNodeList) {
@ -911,16 +945,16 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, invalidatedNodeList)); queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, invalidatedNodeList));
} }
profilerInvalidatedNodeList.stop(); }
final Profiler profilerRemovedList = new Profiler(); private void processRemovedNodes(Date cutTime, List<ManagementServerHostVO> removedNodeList) {
profilerRemovedList.start();
// process removed node list // process removed node list
final Iterator<ManagementServerHostVO> it = removedNodeList.iterator(); final Iterator<ManagementServerHostVO> it = removedNodeList.iterator();
while (it.hasNext()) { while (it.hasNext()) {
final ManagementServerHostVO mshost = it.next(); final ManagementServerHostVO mshost = it.next();
if (!pingManagementNode(mshost)) { // Check if peer state is Up in the period
logger.warn("Management node " + mshost.getId() + " is detected inactive by timestamp and also not pingable"); if (!_mshostPeerDao.isPeerUpState(_mshostId, mshost.getId(), new Date(cutTime.getTime() - HeartbeatThreshold.value()))) {
logger.warn("Management node " + mshost.getId() + " is detected inactive by timestamp and did not send node status to this node");
_activePeers.remove(mshost.getId()); _activePeers.remove(mshost.getId());
try { try {
JmxUtil.unregisterMBean("ClusterManager", "Node " + mshost.getId()); JmxUtil.unregisterMBean("ClusterManager", "Node " + mshost.getId());
@ -928,7 +962,7 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
logger.warn("Unable to deregiester cluster node from JMX monitoring due to exception " + e.toString()); logger.warn("Unable to deregiester cluster node from JMX monitoring due to exception " + e.toString());
} }
} else { } else {
logger.info("Management node " + mshost.getId() + " is detected inactive by timestamp but is pingable"); logger.info("Management node " + mshost.getId() + " is detected inactive by timestamp but sent node status to this node");
it.remove(); it.remove();
} }
} }
@ -936,8 +970,9 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
if (removedNodeList.size() > 0) { if (removedNodeList.size() > 0) {
queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, removedNodeList)); queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeRemoved, removedNodeList));
} }
profilerRemovedList.stop(); }
private void processNewNodes(Date cutTime, List<ManagementServerHostVO> currentList) {
final List<ManagementServerHostVO> newNodeList = new ArrayList<ManagementServerHostVO>(); final List<ManagementServerHostVO> newNodeList = new ArrayList<ManagementServerHostVO>();
for (final ManagementServerHostVO mshost : currentList) { for (final ManagementServerHostVO mshost : currentList) {
if (!_activePeers.containsKey(mshost.getId())) { if (!_activePeers.containsKey(mshost.getId())) {
@ -959,17 +994,30 @@ public class ClusterManagerImpl extends ManagerBase implements ClusterManager, C
if (newNodeList.size() > 0) { if (newNodeList.size() > 0) {
queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeAdded, newNodeList)); queueNotification(new ClusterManagerMessage(ClusterManagerMessage.MessageType.nodeAdded, newNodeList));
} }
}
profiler.stop(); private void processInactiveNodes(Date cutTime) {
final List<ManagementServerHostVO> inactiveList = _mshostDao.getInactiveList(new Date(cutTime.getTime() - HeartbeatThreshold.value()));
if (inactiveList.size() > 0) {
if (logger.isInfoEnabled()) {
logger.info(String.format("Found %s inactive management server node based on timestamp", inactiveList.size()));
}
for (final ManagementServerHostVO host : inactiveList) {
logger.info(String.format("management server node msid: %s, name: %s, service ip: %s, version: %s",
host.getMsid(), host.getName(), host.getServiceIP(), host.getVersion()));
// Check if any peer state is Up in the period
if (ManagementServerHost.State.Up.equals(host.getState()) &&
!_mshostPeerDao.isPeerUpState(host.getId(), new Date(cutTime.getTime() - HeartbeatThreshold.value()))) {
logger.warn("Management node " + host.getId() + " is detected inactive by timestamp and did not send node status to all other nodes");
host.setState(ManagementServerHost.State.Down);
_mshostDao.update(host.getId(), host);
}
}
} else {
logger.info("No inactive management server node found");
}
}
if (profiler.getDurationInMillis() >= HeartbeatInterval.value()) {
if (logger.isDebugEnabled()) {
logger.debug("Peer scan takes too long to finish. profiler: " + profiler.toString() + ", profilerQueryActiveList: " +
profilerQueryActiveList.toString() + ", profilerSyncClusterInfo: " + profilerSyncClusterInfo.toString() + ", profilerInvalidatedNodeList: " +
profilerInvalidatedNodeList.toString() + ", profilerRemovedList: " + profilerRemovedList.toString());
}
}
}
private static ManagementServerHostVO getInListById(final Long id, final List<ManagementServerHostVO> l) { private static ManagementServerHostVO getInListById(final Long id, final List<ManagementServerHostVO> l) {
for (final ManagementServerHostVO mshost : l) { for (final ManagementServerHostVO mshost : l) {

View File

@ -0,0 +1,177 @@
// 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 com.cloud.cluster;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.cloudstack.management.ManagementServerHost;
@Entity
@Table(name = "mshost_peer_view")
public class ManagementServerHostPeerJoinVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "peer_state")
@Enumerated(value = EnumType.STRING)
private ManagementServerHost.State peerState;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "last_update")
private Date lastUpdateTime;
@Column(name = "owner_mshost_id")
private long ownerMshostId;
@Column(name = "owner_mshost_msid")
private long ownerMshostMsId;
@Column(name = "owner_mshost_runid")
private long ownerMshostRunId;
@Column(name = "owner_mshost_name")
private String ownerMshostName;
@Column(name = "owner_mshost_uuid")
private String ownerMshostUuid;
@Column(name = "owner_mshost_state")
private String ownerMshostState;
@Column(name = "owner_mshost_service_ip")
private String ownerMshostServiceIp;
@Column(name = "owner_mshost_service_port")
private Integer ownerMshostServicePort;
@Column(name = "peer_mshost_id")
private long peerMshostId;
@Column(name = "peer_mshost_msid")
private long peerMshostMsId;
@Column(name = "peer_mshost_runid")
private long peerMshostRunId;
@Column(name = "peer_mshost_name")
private String peerMshostName;
@Column(name = "peer_mshost_uuid")
private String peerMshostUuid;
@Column(name = "peer_mshost_state")
private String peerMshostState;
@Column(name = "peer_mshost_service_ip")
private String peerMshostServiceIp;
@Column(name = "peer_mshost_service_port")
private Integer peerMshostServicePort;
public ManagementServerHostPeerJoinVO() {
}
public long getId() {
return id;
}
public ManagementServerHost.State getPeerState() {
return peerState;
}
public Date getLastUpdateTime() {
return lastUpdateTime;
}
public long getOwnerMshostId() {
return ownerMshostId;
}
public long getOwnerMshostMsId() {
return ownerMshostMsId;
}
public long getOwnerMshostRunId() {
return ownerMshostRunId;
}
public String getOwnerMshostName() {
return ownerMshostName;
}
public String getOwnerMshostUuid() {
return ownerMshostUuid;
}
public String getOwnerMshostState() {
return ownerMshostState;
}
public String getOwnerMshostServiceIp() {
return ownerMshostServiceIp;
}
public Integer getOwnerMshostServicePort() {
return ownerMshostServicePort;
}
public long getPeerMshostId() {
return peerMshostId;
}
public long getPeerMshostMsId() {
return peerMshostMsId;
}
public long getPeerMshostRunId() {
return peerMshostRunId;
}
public String getPeerMshostName() {
return peerMshostName;
}
public String getPeerMshostUuid() {
return peerMshostUuid;
}
public String getPeerMshostState() {
return peerMshostState;
}
public String getPeerMshostServiceIp() {
return peerMshostServiceIp;
}
public Integer getPeerMshostServicePort() {
return peerMshostServicePort;
}
}

View File

@ -130,7 +130,7 @@ public class ManagementServerHostDaoImpl extends GenericDaoBase<ManagementServer
try { try {
txn.start(); txn.start();
pstmt = txn.prepareAutoCloseStatement("update mshost set last_update=?, removed=null, alert_count=0 where id=? and runid=?"); pstmt = txn.prepareAutoCloseStatement("update mshost set last_update=?, removed=null, alert_count=0, state='Up' where id=? and runid=?");
pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate)); pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), lastUpdate));
pstmt.setLong(2, id); pstmt.setLong(2, id);
pstmt.setLong(3, runid); pstmt.setLong(3, runid);

View File

@ -20,10 +20,17 @@ import org.apache.cloudstack.management.ManagementServerHost;
import com.cloud.cluster.ManagementServerHostPeerVO; import com.cloud.cluster.ManagementServerHostPeerVO;
import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.GenericDao;
import java.util.Date;
public interface ManagementServerHostPeerDao extends GenericDao<ManagementServerHostPeerVO, Long> { public interface ManagementServerHostPeerDao extends GenericDao<ManagementServerHostPeerVO, Long> {
void clearPeerInfo(long ownerMshost); void clearPeerInfo(long ownerMshost);
void updatePeerInfo(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState); void updatePeerInfo(long ownerMshost, long peerMshost, long peerRunid, ManagementServerHost.State peerState);
int countStateSeenInPeers(long mshost, long runid, ManagementServerHost.State state); int countStateSeenInPeers(long peerMshost, long runid, ManagementServerHost.State state);
boolean isPeerUpState(long peerMshost, Date cutTime);
boolean isPeerUpState(long ownerMshost, long peerMshost, Date cutTime);
} }

View File

@ -16,10 +16,10 @@
// under the License. // under the License.
package com.cloud.cluster.dao; package com.cloud.cluster.dao;
import java.util.Date;
import java.util.List; import java.util.List;
import org.apache.cloudstack.management.ManagementServerHost; import org.apache.cloudstack.management.ManagementServerHost;
import com.cloud.cluster.ManagementServerHostPeerVO; import com.cloud.cluster.ManagementServerHostPeerVO;
import com.cloud.utils.db.DB; import com.cloud.utils.db.DB;
@ -33,10 +33,12 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
private final SearchBuilder<ManagementServerHostPeerVO> ClearPeerSearch; private final SearchBuilder<ManagementServerHostPeerVO> ClearPeerSearch;
private final SearchBuilder<ManagementServerHostPeerVO> FindForUpdateSearch; private final SearchBuilder<ManagementServerHostPeerVO> FindForUpdateSearch;
private final SearchBuilder<ManagementServerHostPeerVO> CountSearch; private final SearchBuilder<ManagementServerHostPeerVO> CountSearch;
private final SearchBuilder<ManagementServerHostPeerVO> ActiveSearch;
public ManagementServerHostPeerDaoImpl() { public ManagementServerHostPeerDaoImpl() {
ClearPeerSearch = createSearchBuilder(); ClearPeerSearch = createSearchBuilder();
ClearPeerSearch.and("ownerMshost", ClearPeerSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ); ClearPeerSearch.and("ownerMshost", ClearPeerSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ);
ClearPeerSearch.or("peerMshost", ClearPeerSearch.entity().getPeerMshost(), SearchCriteria.Op.EQ);
ClearPeerSearch.done(); ClearPeerSearch.done();
FindForUpdateSearch = createSearchBuilder(); FindForUpdateSearch = createSearchBuilder();
@ -50,6 +52,13 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
CountSearch.and("peerRunid", CountSearch.entity().getPeerRunid(), SearchCriteria.Op.EQ); CountSearch.and("peerRunid", CountSearch.entity().getPeerRunid(), SearchCriteria.Op.EQ);
CountSearch.and("peerState", CountSearch.entity().getPeerState(), SearchCriteria.Op.EQ); CountSearch.and("peerState", CountSearch.entity().getPeerState(), SearchCriteria.Op.EQ);
CountSearch.done(); CountSearch.done();
ActiveSearch = createSearchBuilder();
ActiveSearch.and("ownerMshost", ActiveSearch.entity().getOwnerMshost(), SearchCriteria.Op.EQ);
ActiveSearch.and("peerMshost", ActiveSearch.entity().getPeerMshost(), SearchCriteria.Op.EQ);
ActiveSearch.and("peerState", ActiveSearch.entity().getPeerState(), SearchCriteria.Op.EQ);
ActiveSearch.and("lastUpdateTime", ActiveSearch.entity().getLastUpdateTime(), SearchCriteria.Op.GT);
ActiveSearch.done();
} }
@Override @Override
@ -57,6 +66,7 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
public void clearPeerInfo(long ownerMshost) { public void clearPeerInfo(long ownerMshost) {
SearchCriteria<ManagementServerHostPeerVO> sc = ClearPeerSearch.create(); SearchCriteria<ManagementServerHostPeerVO> sc = ClearPeerSearch.create();
sc.setParameters("ownerMshost", ownerMshost); sc.setParameters("ownerMshost", ownerMshost);
sc.setParameters("peerMshost", ownerMshost);
expunge(sc); expunge(sc);
} }
@ -71,11 +81,12 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
SearchCriteria<ManagementServerHostPeerVO> sc = FindForUpdateSearch.create(); SearchCriteria<ManagementServerHostPeerVO> sc = FindForUpdateSearch.create();
sc.setParameters("ownerMshost", ownerMshost); sc.setParameters("ownerMshost", ownerMshost);
sc.setParameters("peerMshost", peerMshost); sc.setParameters("peerMshost", peerMshost);
sc.setParameters("peerRunid", peerRunid);
List<ManagementServerHostPeerVO> l = listBy(sc); List<ManagementServerHostPeerVO> l = listBy(sc);
if (l.size() == 1) { if (l.size() == 1) {
ManagementServerHostPeerVO peer = l.get(0); ManagementServerHostPeerVO peer = l.get(0);
peer.setPeerRunid(peerRunid);
peer.setPeerState(peerState); peer.setPeerState(peerState);
peer.setLastUpdateTime(new Date());
update(peer.getId(), peer); update(peer.getId(), peer);
} else { } else {
ManagementServerHostPeerVO peer = new ManagementServerHostPeerVO(ownerMshost, peerMshost, peerRunid, peerState); ManagementServerHostPeerVO peer = new ManagementServerHostPeerVO(ownerMshost, peerMshost, peerRunid, peerState);
@ -90,13 +101,36 @@ public class ManagementServerHostPeerDaoImpl extends GenericDaoBase<ManagementSe
@Override @Override
@DB @DB
public int countStateSeenInPeers(long mshost, long runid, ManagementServerHost.State state) { public int countStateSeenInPeers(long peerMshost, long runid, ManagementServerHost.State state) {
SearchCriteria<ManagementServerHostPeerVO> sc = CountSearch.create(); SearchCriteria<ManagementServerHostPeerVO> sc = CountSearch.create();
sc.setParameters("peerMshost", mshost); sc.setParameters("peerMshost", peerMshost);
sc.setParameters("peerRunid", runid); sc.setParameters("peerRunid", runid);
sc.setParameters("peerState", state); sc.setParameters("peerState", state);
List<ManagementServerHostPeerVO> l = listBy(sc); List<ManagementServerHostPeerVO> l = listBy(sc);
return l.size(); return l.size();
} }
@Override
@DB
public boolean isPeerUpState(long peerMshost, Date cutTime) {
SearchCriteria<ManagementServerHostPeerVO> sc = ActiveSearch.create();
sc.setParameters("peerMshost", peerMshost);
sc.setParameters("peerState", ManagementServerHost.State.Up);
sc.setParameters("lastUpdateTime", cutTime);
return listBy(sc).size() > 0;
}
@Override
@DB
public boolean isPeerUpState(long ownerMshost, long peerMshost, Date cutTime) {
SearchCriteria<ManagementServerHostPeerVO> sc = ActiveSearch.create();
sc.setParameters("ownerMshost", ownerMshost);
sc.setParameters("peerMshost", peerMshost);
sc.setParameters("peerState", ManagementServerHost.State.Up);
sc.setParameters("lastUpdateTime", cutTime);
return listBy(sc).size() > 0;
}
} }

View File

@ -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 com.cloud.cluster.dao;
import com.cloud.cluster.ManagementServerHostPeerJoinVO;
import com.cloud.utils.db.GenericDao;
import java.util.List;
public interface ManagementServerHostPeerJoinDao extends GenericDao<ManagementServerHostPeerJoinVO, Long> {
List<ManagementServerHostPeerJoinVO> listByOwnerMshostId(long ownerMshostId);
}

View File

@ -0,0 +1,42 @@
// 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 com.cloud.cluster.dao;
import java.util.List;
import com.cloud.cluster.ManagementServerHostPeerJoinVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
public class ManagementServerHostPeerJoinDaoImpl extends GenericDaoBase<ManagementServerHostPeerJoinVO, Long> implements ManagementServerHostPeerJoinDao {
private final SearchBuilder<ManagementServerHostPeerJoinVO> AllFieldSearch;
public ManagementServerHostPeerJoinDaoImpl() {
AllFieldSearch = createSearchBuilder();
AllFieldSearch.and("ownerMshostId", AllFieldSearch.entity().getOwnerMshostId(), SearchCriteria.Op.EQ);
AllFieldSearch.done();
}
@Override
public List<ManagementServerHostPeerJoinVO> listByOwnerMshostId(long ownerMshostId) {
SearchCriteria<ManagementServerHostPeerJoinVO> sc = AllFieldSearch.create();
sc.setParameters("ownerMshostId", ownerMshostId);
return listBy(sc);
}
}

View File

@ -34,6 +34,7 @@ public class ConfigKey<T> {
public static final String CATEGORY_ADVANCED = "Advanced"; public static final String CATEGORY_ADVANCED = "Advanced";
public static final String CATEGORY_ALERT = "Alert"; public static final String CATEGORY_ALERT = "Alert";
public static final String CATEGORY_NETWORK = "Network"; public static final String CATEGORY_NETWORK = "Network";
public static final String CATEGORY_SYSTEM = "System";
public enum Scope { public enum Scope {
Global, Zone, Cluster, StoragePool, Account, ManagementServer, ImageStore, Domain Global, Zone, Cluster, StoragePool, Account, ManagementServer, ImageStore, Domain

View File

@ -157,7 +157,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
.map(quotaUsageVO -> new Pair<>(quotaUsageVO.getStartDate(), quotaUsageVO.getEndDate())) .map(quotaUsageVO -> new Pair<>(quotaUsageVO.getStartDate(), quotaUsageVO.getEndDate()))
.collect(Collectors.toCollection(LinkedHashSet::new)); .collect(Collectors.toCollection(LinkedHashSet::new));
logger.info(String.format("Processing quota balance for account[{}] between [{}] and [{}].", accountToString, startDate, lastQuotaUsageEndDate)); logger.info("Processing quota balance for account [{}] between [{}] and [{}].", accountToString, startDate, lastQuotaUsageEndDate);
long accountId = accountVo.getAccountId(); long accountId = accountVo.getAccountId();
long domainId = accountVo.getDomainId(); long domainId = accountVo.getDomainId();

View File

@ -486,12 +486,12 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
} }
@Override @Override
public Map<String, String> getKeys(GetUserKeysCmd cmd){ public Pair<Boolean, Map<String, String>> getKeys(GetUserKeysCmd cmd){
return null; return null;
} }
@Override @Override
public Map<String, String> getKeys(Long userId) { public Pair<Boolean, Map<String, String>> getKeys(Long userId) {
return null; return null;
} }

View File

@ -50,7 +50,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<project.systemvm.template.location>https://download.cloudstack.org/systemvm</project.systemvm.template.location> <project.systemvm.template.location>https://download.cloudstack.org/systemvm</project.systemvm.template.location>
<project.systemvm.template.version>4.21.0.0-SNAPSHOT</project.systemvm.template.version> <project.systemvm.template.version>4.20.0.0</project.systemvm.template.version>
<sonar.organization>apache</sonar.organization> <sonar.organization>apache</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url> <sonar.host.url>https://sonarcloud.io</sonar.host.url>

View File

@ -1945,11 +1945,11 @@ public class ApiDBUtils {
} }
public static UserResponse newUserResponse(UserAccountJoinVO usr) { public static UserResponse newUserResponse(UserAccountJoinVO usr) {
return newUserResponse(usr, null); return newUserResponse(ResponseView.Restricted, null, usr);
} }
public static UserResponse newUserResponse(UserAccountJoinVO usr, Long domainId) { public static UserResponse newUserResponse(ResponseView view, Long domainId, UserAccountJoinVO usr) {
UserResponse response = s_userAccountJoinDao.newUserResponse(usr); UserResponse response = s_userAccountJoinDao.newUserResponse(view, usr);
if(!AccountManager.UseSecretKeyInResponse.value()){ if(!AccountManager.UseSecretKeyInResponse.value()){
response.setSecretKey(null); response.setSecretKey(null);
} }

View File

@ -188,6 +188,7 @@ import com.cloud.utils.exception.ExceptionProxyObject;
import com.cloud.utils.net.NetUtils; import com.cloud.utils.net.NetUtils;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import static com.cloud.user.AccountManagerImpl.apiKeyAccess;
import static org.apache.cloudstack.user.UserPasswordResetManager.UserPasswordResetEnabled; import static org.apache.cloudstack.user.UserPasswordResetManager.UserPasswordResetEnabled;
@Component @Component
@ -896,6 +897,34 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
} }
} }
protected boolean verifyApiKeyAccessAllowed(User user, Account account) {
Boolean apiKeyAccessEnabled = user.getApiKeyAccess();
if (apiKeyAccessEnabled != null) {
if (Boolean.TRUE.equals(apiKeyAccessEnabled)) {
return true;
} else {
logger.info("Api-Key access is disabled for the User " + user.toString());
return false;
}
}
apiKeyAccessEnabled = account.getApiKeyAccess();
if (apiKeyAccessEnabled != null) {
if (Boolean.TRUE.equals(apiKeyAccessEnabled)) {
return true;
} else {
logger.info("Api-Key access is disabled for the Account " + account.toString());
return false;
}
}
apiKeyAccessEnabled = apiKeyAccess.valueIn(account.getDomainId());
if (Boolean.TRUE.equals(apiKeyAccessEnabled)) {
return true;
} else {
logger.info("Api-Key access is disabled by the Domain level setting api.key.access");
}
return false;
}
@Override @Override
public boolean verifyRequest(final Map<String, Object[]> requestParameters, final Long userId, InetAddress remoteAddress) throws ServerApiException { public boolean verifyRequest(final Map<String, Object[]> requestParameters, final Long userId, InetAddress remoteAddress) throws ServerApiException {
try { try {
@ -1012,6 +1041,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
return false; return false;
} }
if (!verifyApiKeyAccessAllowed(user, account)) {
return false;
}
if (!commandAvailable(remoteAddress, commandName, user)) { if (!commandAvailable(remoteAddress, commandName, user)) {
return false; return false;
} }

View File

@ -36,7 +36,6 @@ import java.util.stream.Stream;
import javax.inject.Inject; import javax.inject.Inject;
import com.cloud.cpu.CPU;
import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker;
@ -114,6 +113,7 @@ import org.apache.cloudstack.api.response.IpQuarantineResponse;
import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ManagementServerResponse; import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.ObjectStoreResponse; import org.apache.cloudstack.api.response.ObjectStoreResponse;
import org.apache.cloudstack.api.response.PeerManagementServerNodeResponse;
import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse;
import org.apache.cloudstack.api.response.ProjectInvitationResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse;
import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ProjectResponse;
@ -214,8 +214,11 @@ import com.cloud.api.query.vo.TemplateJoinVO;
import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.api.query.vo.VolumeJoinVO; import com.cloud.api.query.vo.VolumeJoinVO;
import com.cloud.cluster.ManagementServerHostPeerJoinVO;
import com.cloud.cluster.ManagementServerHostVO; import com.cloud.cluster.ManagementServerHostVO;
import com.cloud.cluster.dao.ManagementServerHostDao; import com.cloud.cluster.dao.ManagementServerHostDao;
import com.cloud.cluster.dao.ManagementServerHostPeerJoinDao;
import com.cloud.cpu.CPU;
import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter;
import com.cloud.dc.DedicatedResourceVO; import com.cloud.dc.DedicatedResourceVO;
@ -607,6 +610,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
@Inject @Inject
private ClusterDao clusterDao; private ClusterDao clusterDao;
@Inject
private ManagementServerHostPeerJoinDao mshostPeerJoinDao;
private SearchCriteria<ServiceOfferingJoinVO> getMinimumCpuServiceOfferingJoinSearchCriteria(int cpu) { private SearchCriteria<ServiceOfferingJoinVO> getMinimumCpuServiceOfferingJoinSearchCriteria(int cpu) {
SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria(); SearchCriteria<ServiceOfferingJoinVO> sc = _srvOfferingJoinDao.createSearchCriteria();
@ -655,10 +661,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
* .api.command.admin.user.ListUsersCmd) * .api.command.admin.user.ListUsersCmd)
*/ */
@Override @Override
public ListResponse<UserResponse> searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException { public ListResponse<UserResponse> searchForUsers(ResponseView responseView, ListUsersCmd cmd) throws PermissionDeniedException {
Pair<List<UserAccountJoinVO>, Integer> result = searchForUsersInternal(cmd); Pair<List<UserAccountJoinVO>, Integer> result = searchForUsersInternal(cmd);
ListResponse<UserResponse> response = new ListResponse<UserResponse>(); ListResponse<UserResponse> response = new ListResponse<UserResponse>();
List<UserResponse> userResponses = ViewResponseHelper.createUserResponse(CallContext.current().getCallingAccount().getDomainId(), if (CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN) {
responseView = ResponseView.Full;
}
List<UserResponse> userResponses = ViewResponseHelper.createUserResponse(responseView, CallContext.current().getCallingAccount().getDomainId(),
result.first().toArray(new UserAccountJoinVO[result.first().size()])); result.first().toArray(new UserAccountJoinVO[result.first().size()]));
response.setResponses(userResponses, result.second()); response.setResponses(userResponses, result.second());
return response; return response;
@ -685,10 +694,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Object state = null; Object state = null;
String keyword = null; String keyword = null;
Pair<List<UserAccountJoinVO>, Integer> result = getUserListInternal(caller, permittedAccounts, listAll, id, username, type, accountName, state, keyword, domainId, recursive, Pair<List<UserAccountJoinVO>, Integer> result = getUserListInternal(caller, permittedAccounts, listAll, id,
null); username, type, accountName, state, keyword, null, domainId, recursive, null);
ListResponse<UserResponse> response = new ListResponse<UserResponse>(); ListResponse<UserResponse> response = new ListResponse<UserResponse>();
List<UserResponse> userResponses = ViewResponseHelper.createUserResponse(CallContext.current().getCallingAccount().getDomainId(), List<UserResponse> userResponses = ViewResponseHelper.createUserResponse(ResponseView.Restricted, CallContext.current().getCallingAccount().getDomainId(),
result.first().toArray(new UserAccountJoinVO[result.first().size()])); result.first().toArray(new UserAccountJoinVO[result.first().size()]));
response.setResponses(userResponses, result.second()); response.setResponses(userResponses, result.second());
return response; return response;
@ -713,6 +722,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
String accountName = cmd.getAccountName(); String accountName = cmd.getAccountName();
Object state = cmd.getState(); Object state = cmd.getState();
String keyword = cmd.getKeyword(); String keyword = cmd.getKeyword();
String apiKeyAccess = cmd.getApiKeyAccess();
Long domainId = cmd.getDomainId(); Long domainId = cmd.getDomainId();
boolean recursive = cmd.isRecursive(); boolean recursive = cmd.isRecursive();
@ -721,11 +731,11 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Filter searchFilter = new Filter(UserAccountJoinVO.class, "id", true, startIndex, pageSizeVal); Filter searchFilter = new Filter(UserAccountJoinVO.class, "id", true, startIndex, pageSizeVal);
return getUserListInternal(caller, permittedAccounts, listAll, id, username, type, accountName, state, keyword, domainId, recursive, searchFilter); return getUserListInternal(caller, permittedAccounts, listAll, id, username, type, accountName, state, keyword, apiKeyAccess, domainId, recursive, searchFilter);
} }
private Pair<List<UserAccountJoinVO>, Integer> getUserListInternal(Account caller, List<Long> permittedAccounts, boolean listAll, Long id, Object username, Object type, private Pair<List<UserAccountJoinVO>, Integer> getUserListInternal(Account caller, List<Long> permittedAccounts, boolean listAll, Long id, Object username, Object type,
String accountName, Object state, String keyword, Long domainId, boolean recursive, Filter searchFilter) { String accountName, Object state, String keyword, String apiKeyAccess, Long domainId, boolean recursive, Filter searchFilter) {
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, recursive, null); Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(domainId, recursive, null);
accountMgr.buildACLSearchParameters(caller, id, accountName, null, permittedAccounts, domainIdRecursiveListProject, listAll, false); accountMgr.buildACLSearchParameters(caller, id, accountName, null, permittedAccounts, domainIdRecursiveListProject, listAll, false);
domainId = domainIdRecursiveListProject.first(); domainId = domainIdRecursiveListProject.first();
@ -751,6 +761,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sb.and("domainId", sb.entity().getDomainId(), Op.EQ); sb.and("domainId", sb.entity().getDomainId(), Op.EQ);
sb.and("accountName", sb.entity().getAccountName(), Op.EQ); sb.and("accountName", sb.entity().getAccountName(), Op.EQ);
sb.and("state", sb.entity().getState(), Op.EQ); sb.and("state", sb.entity().getState(), Op.EQ);
if (apiKeyAccess != null) {
sb.and("apiKeyAccess", sb.entity().getApiKeyAccess(), Op.EQ);
}
if ((accountName == null) && (domainId != null)) { if ((accountName == null) && (domainId != null)) {
sb.and("domainPath", sb.entity().getDomainPath(), Op.LIKE); sb.and("domainPath", sb.entity().getDomainPath(), Op.LIKE);
@ -805,6 +818,15 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.setParameters("state", state); sc.setParameters("state", state);
} }
if (apiKeyAccess != null) {
try {
ApiConstants.ApiKeyAccess access = ApiConstants.ApiKeyAccess.valueOf(apiKeyAccess.toUpperCase());
sc.setParameters("apiKeyAccess", access.toBoolean());
} catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit");
}
}
return _userAccountJoinDao.searchAndCount(sc, searchFilter); return _userAccountJoinDao.searchAndCount(sc, searchFilter);
} }
@ -2891,6 +2913,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Object state = cmd.getState(); Object state = cmd.getState();
Object isCleanupRequired = cmd.isCleanupRequired(); Object isCleanupRequired = cmd.isCleanupRequired();
Object keyword = cmd.getKeyword(); Object keyword = cmd.getKeyword();
String apiKeyAccess = cmd.getApiKeyAccess();
SearchBuilder<AccountVO> accountSearchBuilder = _accountDao.createSearchBuilder(); SearchBuilder<AccountVO> accountSearchBuilder = _accountDao.createSearchBuilder();
accountSearchBuilder.select(null, Func.DISTINCT, accountSearchBuilder.entity().getId()); // select distinct accountSearchBuilder.select(null, Func.DISTINCT, accountSearchBuilder.entity().getId()); // select distinct
@ -2903,6 +2926,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
accountSearchBuilder.and("typeNEQ", accountSearchBuilder.entity().getType(), SearchCriteria.Op.NEQ); accountSearchBuilder.and("typeNEQ", accountSearchBuilder.entity().getType(), SearchCriteria.Op.NEQ);
accountSearchBuilder.and("idNEQ", accountSearchBuilder.entity().getId(), SearchCriteria.Op.NEQ); accountSearchBuilder.and("idNEQ", accountSearchBuilder.entity().getId(), SearchCriteria.Op.NEQ);
accountSearchBuilder.and("type2NEQ", accountSearchBuilder.entity().getType(), SearchCriteria.Op.NEQ); accountSearchBuilder.and("type2NEQ", accountSearchBuilder.entity().getType(), SearchCriteria.Op.NEQ);
if (apiKeyAccess != null) {
accountSearchBuilder.and("apiKeyAccess", accountSearchBuilder.entity().getApiKeyAccess(), Op.EQ);
}
if (domainId != null && isRecursive) { if (domainId != null && isRecursive) {
SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder(); SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder();
@ -2966,6 +2992,15 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
} }
} }
if (apiKeyAccess != null) {
try {
ApiConstants.ApiKeyAccess access = ApiConstants.ApiKeyAccess.valueOf(apiKeyAccess.toUpperCase());
sc.setParameters("apiKeyAccess", access.toBoolean());
} catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit");
}
}
Pair<List<AccountVO>, Integer> uniqueAccountPair = _accountDao.searchAndCount(sc, searchFilter); Pair<List<AccountVO>, Integer> uniqueAccountPair = _accountDao.searchAndCount(sc, searchFilter);
Integer count = uniqueAccountPair.second(); Integer count = uniqueAccountPair.second();
List<Long> accountIds = uniqueAccountPair.first().stream().map(AccountVO::getId).collect(Collectors.toList()); List<Long> accountIds = uniqueAccountPair.first().stream().map(AccountVO::getId).collect(Collectors.toList());
@ -5342,7 +5377,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
List<ManagementServerResponse> hostResponses = new ArrayList<>(); List<ManagementServerResponse> hostResponses = new ArrayList<>();
for (ManagementServerJoinVO host : result.first()) { for (ManagementServerJoinVO host : result.first()) {
ManagementServerResponse hostResponse = createManagementServerResponse(host); ManagementServerResponse hostResponse = createManagementServerResponse(host, cmd.getPeers());
hostResponses.add(hostResponse); hostResponses.add(hostResponse);
} }
@ -5365,7 +5400,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
return managementServerJoinDao.searchAndCount(sc, null); return managementServerJoinDao.searchAndCount(sc, null);
} }
protected ManagementServerResponse createManagementServerResponse(ManagementServerJoinVO mgmt) { protected ManagementServerResponse createManagementServerResponse(ManagementServerJoinVO mgmt, boolean listPeers) {
ManagementServerResponse mgmtResponse = new ManagementServerResponse(); ManagementServerResponse mgmtResponse = new ManagementServerResponse();
mgmtResponse.setId(mgmt.getUuid()); mgmtResponse.setId(mgmt.getUuid());
mgmtResponse.setName(mgmt.getName()); mgmtResponse.setName(mgmt.getName());
@ -5378,10 +5413,34 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
mgmtResponse.setLastServerStop(mgmt.getLastJvmStop()); mgmtResponse.setLastServerStop(mgmt.getLastJvmStop());
mgmtResponse.setLastBoot(mgmt.getLastSystemBoot()); mgmtResponse.setLastBoot(mgmt.getLastSystemBoot());
mgmtResponse.setServiceIp(mgmt.getServiceIP()); mgmtResponse.setServiceIp(mgmt.getServiceIP());
if (listPeers) {
List<ManagementServerHostPeerJoinVO> peers = mshostPeerJoinDao.listByOwnerMshostId(mgmt.getId());
for (ManagementServerHostPeerJoinVO peer: peers) {
mgmtResponse.addPeer(createPeerManagementServerNodeResponse(peer));
}
}
mgmtResponse.setObjectName("managementserver"); mgmtResponse.setObjectName("managementserver");
return mgmtResponse; return mgmtResponse;
} }
private PeerManagementServerNodeResponse createPeerManagementServerNodeResponse(ManagementServerHostPeerJoinVO peer) {
PeerManagementServerNodeResponse response = new PeerManagementServerNodeResponse();
response.setState(peer.getPeerState());
response.setLastUpdated(peer.getLastUpdateTime());
response.setPeerId(peer.getPeerMshostUuid());
response.setPeerName(peer.getPeerMshostName());
response.setPeerMsId(String.valueOf(peer.getPeerMshostMsId()));
response.setPeerRunId(String.valueOf(peer.getPeerMshostRunId()));
response.setPeerState(peer.getPeerMshostState());
response.setPeerServiceIp(peer.getPeerMshostServiceIp());
response.setPeerServicePort(String.valueOf(peer.getPeerMshostServicePort()));
response.setObjectName("peermanagementserver");
return response;
}
@Override @Override
public List<RouterHealthCheckResultResponse> listRouterHealthChecks(GetRouterHealthCheckResultsCmd cmd) { public List<RouterHealthCheckResultResponse> listRouterHealthChecks(GetRouterHealthCheckResultsCmd cmd) {
logger.info("Executing health check command " + cmd); logger.info("Executing health check command " + cmd);

View File

@ -105,13 +105,13 @@ public class ViewResponseHelper {
protected Logger logger = LogManager.getLogger(getClass()); protected Logger logger = LogManager.getLogger(getClass());
public static List<UserResponse> createUserResponse(UserAccountJoinVO... users) { public static List<UserResponse> createUserResponse(UserAccountJoinVO... users) {
return createUserResponse(null, users); return createUserResponse(ResponseView.Restricted, null, users);
} }
public static List<UserResponse> createUserResponse(Long domainId, UserAccountJoinVO... users) { public static List<UserResponse> createUserResponse(ResponseView responseView, Long domainId, UserAccountJoinVO... users) {
List<UserResponse> respList = new ArrayList<UserResponse>(); List<UserResponse> respList = new ArrayList<UserResponse>();
for (UserAccountJoinVO vt : users) { for (UserAccountJoinVO vt : users) {
respList.add(ApiDBUtils.newUserResponse(vt, domainId)); respList.add(ApiDBUtils.newUserResponse(responseView, domainId, vt));
} }
return respList; return respList;
} }

View File

@ -82,6 +82,9 @@ public class AccountJoinDaoImpl extends GenericDaoBase<AccountJoinVO, Long> impl
accountResponse.setNetworkDomain(account.getNetworkDomain()); accountResponse.setNetworkDomain(account.getNetworkDomain());
accountResponse.setDefaultZone(account.getDataCenterUuid()); accountResponse.setDefaultZone(account.getDataCenterUuid());
accountResponse.setIsDefault(account.isDefault()); accountResponse.setIsDefault(account.isDefault());
if (view == ResponseView.Full) {
accountResponse.setApiKeyAccess(account.getApiKeyAccess());
}
// get network stat // get network stat
accountResponse.setBytesReceived(account.getBytesReceived()); accountResponse.setBytesReceived(account.getBytesReceived());

View File

@ -34,6 +34,7 @@ import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.ResourceTagResponse;
import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -141,6 +142,8 @@ public class DataCenterJoinDaoImpl extends GenericDaoBase<DataCenterJoinVO, Long
String asRange = asNumberRange.stream().map(range -> range.getStartASNumber() + "-" + range.getEndASNumber()).collect(Collectors.joining(", ")); String asRange = asNumberRange.stream().map(range -> range.getStartASNumber() + "-" + range.getEndASNumber()).collect(Collectors.joining(", "));
zoneResponse.setAsnRange(asRange); zoneResponse.setAsnRange(asRange);
zoneResponse.setRoutedModeEnabled(RoutedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(dataCenter.getId()));
zoneResponse.setResourceDetails(ApiDBUtils.getResourceDetails(dataCenter.getId(), ResourceObjectType.Zone)); zoneResponse.setResourceDetails(ApiDBUtils.getResourceDetails(dataCenter.getId(), ResourceObjectType.Zone));
zoneResponse.setHasAnnotation(annotationDao.hasAnnotations(dataCenter.getUuid(), AnnotationService.EntityType.ZONE.name(), zoneResponse.setHasAnnotation(annotationDao.hasAnnotations(dataCenter.getUuid(), AnnotationService.EntityType.ZONE.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId()))); _accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));

View File

@ -18,6 +18,7 @@ package com.cloud.api.query.dao;
import java.util.List; import java.util.List;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserResponse;
import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.api.query.vo.UserAccountJoinVO;
@ -27,7 +28,7 @@ import com.cloud.utils.db.GenericDao;
public interface UserAccountJoinDao extends GenericDao<UserAccountJoinVO, Long> { public interface UserAccountJoinDao extends GenericDao<UserAccountJoinVO, Long> {
UserResponse newUserResponse(UserAccountJoinVO usr); UserResponse newUserResponse(ResponseObject.ResponseView responseView, UserAccountJoinVO usr);
UserAccountJoinVO newUserView(User usr); UserAccountJoinVO newUserView(User usr);

View File

@ -20,6 +20,7 @@ import java.util.List;
import com.cloud.user.AccountManagerImpl; import com.cloud.user.AccountManagerImpl;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserResponse;
@ -52,7 +53,7 @@ public class UserAccountJoinDaoImpl extends GenericDaoBase<UserAccountJoinVO, Lo
} }
@Override @Override
public UserResponse newUserResponse(UserAccountJoinVO usr) { public UserResponse newUserResponse(ResponseView view, UserAccountJoinVO usr) {
UserResponse userResponse = new UserResponse(); UserResponse userResponse = new UserResponse();
userResponse.setAccountId(usr.getAccountUuid()); userResponse.setAccountId(usr.getAccountUuid());
userResponse.setAccountName(usr.getAccountName()); userResponse.setAccountName(usr.getAccountName());
@ -75,6 +76,9 @@ public class UserAccountJoinDaoImpl extends GenericDaoBase<UserAccountJoinVO, Lo
long domainId = usr.getDomainId(); long domainId = usr.getDomainId();
boolean is2FAmandated = Boolean.TRUE.equals(AccountManagerImpl.enableUserTwoFactorAuthentication.valueIn(domainId)) && Boolean.TRUE.equals(AccountManagerImpl.mandateUserTwoFactorAuthentication.valueIn(domainId)); boolean is2FAmandated = Boolean.TRUE.equals(AccountManagerImpl.enableUserTwoFactorAuthentication.valueIn(domainId)) && Boolean.TRUE.equals(AccountManagerImpl.mandateUserTwoFactorAuthentication.valueIn(domainId));
userResponse.set2FAmandated(is2FAmandated); userResponse.set2FAmandated(is2FAmandated);
if (view == ResponseView.Full) {
userResponse.setApiKeyAccess(usr.getApiKeyAccess());
}
// set async job // set async job
if (usr.getJobId() != null) { if (usr.getJobId() != null) {

View File

@ -189,6 +189,9 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident
@Column(name = "default") @Column(name = "default")
boolean isDefault; boolean isDefault;
@Column(name = "api_key_access")
Boolean apiKeyAccess;
public AccountJoinVO() { public AccountJoinVO() {
} }
@ -393,4 +396,8 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident
public boolean isDefault() { public boolean isDefault() {
return isDefault; return isDefault;
} }
public Boolean getApiKeyAccess() {
return apiKeyAccess;
}
} }

View File

@ -133,6 +133,9 @@ public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, I
@Column(name = "is_user_2fa_enabled") @Column(name = "is_user_2fa_enabled")
boolean user2faEnabled; boolean user2faEnabled;
@Column(name = "api_key_access")
Boolean apiKeyAccess;
public UserAccountJoinVO() { public UserAccountJoinVO() {
} }
@ -281,4 +284,8 @@ public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, I
public boolean isUser2faEnabled() { public boolean isUser2faEnabled() {
return user2faEnabled; return user2faEnabled;
} }
public Boolean getApiKeyAccess() {
return apiKeyAccess;
}
} }

View File

@ -24,6 +24,7 @@ import com.cloud.dc.dao.ASNumberRangeDao;
import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.Domain; import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao; import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network; import com.cloud.network.Network;
import com.cloud.network.NetworkModel; import com.cloud.network.NetworkModel;
@ -54,6 +55,7 @@ import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd; import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.network.BgpPeer;
import org.apache.cloudstack.network.BgpPeerVO; import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.RoutedIpv4Manager; import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.BgpPeerDao; import org.apache.cloudstack.network.dao.BgpPeerDao;
@ -116,6 +118,9 @@ public class BGPServiceImpl implements BGPService {
LOGGER.error(msg); LOGGER.error(msg);
throw new InvalidParameterException(msg); throw new InvalidParameterException(msg);
} }
if (!routedIpv4Manager.isRoutedNetworkVpcEnabled(zoneId)) {
throw new InvalidParameterValueException("Cannot create ASN range as Routed networks and VPCs are not enabled for the zone.");
}
if (startASNumber > endASNumber) { if (startASNumber > endASNumber) {
String msg = "Please specify a valid AS Number range"; String msg = "Please specify a valid AS Number range";
LOGGER.error(msg); LOGGER.error(msg);
@ -391,19 +396,7 @@ public class BGPServiceImpl implements BGPService {
if (gatewayProviderStr != null) { if (gatewayProviderStr != null) {
NetworkElement provider = networkModel.getElementImplementingProvider(gatewayProviderStr); NetworkElement provider = networkModel.getElementImplementingProvider(gatewayProviderStr);
if (provider != null && provider instanceof BgpServiceProvider) { if (provider != null && provider instanceof BgpServiceProvider) {
List<BgpPeerVO> bgpPeers; List<? extends BgpPeer> bgpPeers = getBgpPeersForNetwork(network);
if (network.getVpcId() != null) {
bgpPeers = bgpPeerDao.listNonRevokeByVpcId(network.getVpcId());
} else {
bgpPeers = bgpPeerDao.listNonRevokeByNetworkId(network.getId());
}
if (CollectionUtils.isEmpty(bgpPeers)) {
Account owner = accountDao.findByIdIncludingRemoved(network.getAccountId());
List<Long> bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, network.getDataCenterId());
bgpPeers = bgpPeerIds.stream()
.map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
.collect(Collectors.toList());
}
LOGGER.debug(String.format("Applying BPG Peers for network [%s]: [%s]", network, bgpPeers)); LOGGER.debug(String.format("Applying BPG Peers for network [%s]: [%s]", network, bgpPeers));
return ((BgpServiceProvider) provider).applyBgpPeers(null, network, bgpPeers); return ((BgpServiceProvider) provider).applyBgpPeers(null, network, bgpPeers);
} }
@ -420,6 +413,35 @@ public class BGPServiceImpl implements BGPService {
if (gatewayProviderStr != null) { if (gatewayProviderStr != null) {
NetworkElement provider = networkModel.getElementImplementingProvider(gatewayProviderStr); NetworkElement provider = networkModel.getElementImplementingProvider(gatewayProviderStr);
if (provider != null && provider instanceof BgpServiceProvider) { if (provider != null && provider instanceof BgpServiceProvider) {
List<? extends BgpPeer> bgpPeers = getBgpPeersForVpc(vpc);
LOGGER.debug(String.format("Applying BPG Peers for VPC [%s]: [%s]", vpc, bgpPeers));
return ((BgpServiceProvider) provider).applyBgpPeers(vpc, null, bgpPeers);
}
}
return true;
}
@Override
public List<? extends BgpPeer> getBgpPeersForNetwork(Network network) {
List<BgpPeerVO> bgpPeers;
if (network.getVpcId() != null) {
bgpPeers = bgpPeerDao.listNonRevokeByVpcId(network.getVpcId());
} else {
bgpPeers = bgpPeerDao.listNonRevokeByNetworkId(network.getId());
}
if (CollectionUtils.isEmpty(bgpPeers)) {
Account owner = accountDao.findByIdIncludingRemoved(network.getAccountId());
List<Long> bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, network.getDataCenterId());
bgpPeers = bgpPeerIds.stream()
.map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
.collect(Collectors.toList());
}
return bgpPeers;
}
@Override
public List<? extends BgpPeer> getBgpPeersForVpc(Vpc vpc) {
List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByVpcId(vpc.getId()); List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByVpcId(vpc.getId());
if (CollectionUtils.isEmpty(bgpPeers)) { if (CollectionUtils.isEmpty(bgpPeers)) {
Account owner = accountDao.findByIdIncludingRemoved(vpc.getAccountId()); Account owner = accountDao.findByIdIncludingRemoved(vpc.getAccountId());
@ -428,11 +450,6 @@ public class BGPServiceImpl implements BGPService {
.map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId)) .map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
LOGGER.debug(String.format("Applying BPG Peers for VPC [%s]: [%s]", vpc, bgpPeers)); return bgpPeers;
return ((BgpServiceProvider) provider).applyBgpPeers(vpc, null, bgpPeers);
}
}
return true;
} }
} }

View File

@ -1254,6 +1254,7 @@ public class CapacityManagerImpl extends ManagerBase implements CapacityManager,
@Override @Override
public ConfigKey<?>[] getConfigKeys() { public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {CpuOverprovisioningFactor, MemOverprovisioningFactor, StorageCapacityDisableThreshold, StorageOverprovisioningFactor, return new ConfigKey<?>[] {CpuOverprovisioningFactor, MemOverprovisioningFactor, StorageCapacityDisableThreshold, StorageOverprovisioningFactor,
StorageAllocatedCapacityDisableThreshold, StorageOperationsExcludeCluster, ImageStoreNFSVersion, SecondaryStorageCapacityThreshold}; StorageAllocatedCapacityDisableThreshold, StorageOperationsExcludeCluster, ImageStoreNFSVersion, SecondaryStorageCapacityThreshold,
StorageAllocatedCapacityDisableThresholdForVolumeSize };
} }
} }

View File

@ -1740,7 +1740,6 @@ DefaultMaxAccountProjects(
null), null),
// VMSnapshots // VMSnapshots
VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null),
VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "1800", "In second, timeout for create vm snapshot", null), VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "1800", "In second, timeout for create vm snapshot", null),
CloudDnsName("Advanced", ManagementServer.class, String.class, "cloud.dns.name", null, "DNS name of the cloud for the GSLB service", null), CloudDnsName("Advanced", ManagementServer.class, String.class, "cloud.dns.name", null, "DNS name of the cloud for the GSLB service", null),

View File

@ -53,6 +53,7 @@ import org.apache.cloudstack.agent.lb.IndirectAgentLB;
import org.apache.cloudstack.agent.lb.IndirectAgentLBServiceImpl; import org.apache.cloudstack.agent.lb.IndirectAgentLBServiceImpl;
import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao; import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd; import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd;
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
@ -106,6 +107,7 @@ import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.MessageSubscriber; import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
import org.apache.cloudstack.framework.messagebus.PublishScope; import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.query.QueryService; import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIp;
import org.apache.cloudstack.region.PortableIpDao; import org.apache.cloudstack.region.PortableIpDao;
@ -309,6 +311,7 @@ import com.googlecode.ipv6.IPv6Network;
import static com.cloud.configuration.Config.SecStorageAllowedInternalDownloadSites; import static com.cloud.configuration.Config.SecStorageAllowedInternalDownloadSites;
import static com.cloud.offering.NetworkOffering.RoutingMode.Dynamic; import static com.cloud.offering.NetworkOffering.RoutingMode.Dynamic;
import static com.cloud.offering.NetworkOffering.RoutingMode.Static; import static com.cloud.offering.NetworkOffering.RoutingMode.Static;
import static org.apache.cloudstack.framework.config.ConfigKey.CATEGORY_SYSTEM;
public class ConfigurationManagerImpl extends ManagerBase implements ConfigurationManager, ConfigurationService, Configurable { public class ConfigurationManagerImpl extends ManagerBase implements ConfigurationManager, ConfigurationService, Configurable {
public static final String PERACCOUNT = "peraccount"; public static final String PERACCOUNT = "peraccount";
@ -590,6 +593,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
weightBasedParametersForValidation.add(Config.LocalStorageCapacityThreshold.key()); weightBasedParametersForValidation.add(Config.LocalStorageCapacityThreshold.key());
weightBasedParametersForValidation.add(CapacityManager.StorageAllocatedCapacityDisableThreshold.key()); weightBasedParametersForValidation.add(CapacityManager.StorageAllocatedCapacityDisableThreshold.key());
weightBasedParametersForValidation.add(CapacityManager.StorageCapacityDisableThreshold.key()); weightBasedParametersForValidation.add(CapacityManager.StorageCapacityDisableThreshold.key());
weightBasedParametersForValidation.add(CapacityManager.StorageAllocatedCapacityDisableThresholdForVolumeSize.key());
weightBasedParametersForValidation.add(DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.key()); weightBasedParametersForValidation.add(DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.key());
weightBasedParametersForValidation.add(DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.key()); weightBasedParametersForValidation.add(DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.key());
weightBasedParametersForValidation.add(Config.AgentLoadThreshold.key()); weightBasedParametersForValidation.add(Config.AgentLoadThreshold.key());
@ -706,6 +710,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
value = DBEncryptionUtil.encrypt(value); value = DBEncryptionUtil.encrypt(value);
} }
ApiCommandResourceType resourceType;
ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope); ConfigKey.Scope scopeVal = ConfigKey.Scope.valueOf(scope);
switch (scopeVal) { switch (scopeVal) {
case Zone: case Zone:
@ -713,6 +718,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (zone == null) { if (zone == null) {
throw new InvalidParameterValueException("unable to find zone by id " + resourceId); throw new InvalidParameterValueException("unable to find zone by id " + resourceId);
} }
resourceType = ApiCommandResourceType.Zone;
_dcDetailsDao.addDetail(resourceId, name, value, true); _dcDetailsDao.addDetail(resourceId, name, value, true);
break; break;
case Cluster: case Cluster:
@ -720,6 +726,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (cluster == null) { if (cluster == null) {
throw new InvalidParameterValueException("unable to find cluster by id " + resourceId); throw new InvalidParameterValueException("unable to find cluster by id " + resourceId);
} }
resourceType = ApiCommandResourceType.Cluster;
String newName = name; String newName = name;
if (name.equalsIgnoreCase("cpu.overprovisioning.factor")) { if (name.equalsIgnoreCase("cpu.overprovisioning.factor")) {
newName = "cpuOvercommitRatio"; newName = "cpuOvercommitRatio";
@ -742,6 +749,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (pool == null) { if (pool == null) {
throw new InvalidParameterValueException("unable to find storage pool by id " + resourceId); throw new InvalidParameterValueException("unable to find storage pool by id " + resourceId);
} }
resourceType = ApiCommandResourceType.StoragePool;
if(name.equals(CapacityManager.StorageOverprovisioningFactor.key())) { if(name.equals(CapacityManager.StorageOverprovisioningFactor.key())) {
if(!pool.getPoolType().supportsOverProvisioning() ) { if(!pool.getPoolType().supportsOverProvisioning() ) {
throw new InvalidParameterValueException("Unable to update storage pool with id " + resourceId + ". Overprovision not supported for " + pool.getPoolType()); throw new InvalidParameterValueException("Unable to update storage pool with id " + resourceId + ". Overprovision not supported for " + pool.getPoolType());
@ -763,6 +771,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (account == null) { if (account == null) {
throw new InvalidParameterValueException("unable to find account by id " + resourceId); throw new InvalidParameterValueException("unable to find account by id " + resourceId);
} }
resourceType = ApiCommandResourceType.Account;
AccountDetailVO accountDetailVO = _accountDetailsDao.findDetail(resourceId, name); AccountDetailVO accountDetailVO = _accountDetailsDao.findDetail(resourceId, name);
if (accountDetailVO == null) { if (accountDetailVO == null) {
accountDetailVO = new AccountDetailVO(resourceId, name, value); accountDetailVO = new AccountDetailVO(resourceId, name, value);
@ -776,6 +785,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
case ImageStore: case ImageStore:
final ImageStoreVO imgStore = _imageStoreDao.findById(resourceId); final ImageStoreVO imgStore = _imageStoreDao.findById(resourceId);
Preconditions.checkState(imgStore != null); Preconditions.checkState(imgStore != null);
resourceType = ApiCommandResourceType.ImageStore;
_imageStoreDetailsDao.addDetail(resourceId, name, value, true); _imageStoreDetailsDao.addDetail(resourceId, name, value, true);
break; break;
@ -784,6 +794,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (domain == null) { if (domain == null) {
throw new InvalidParameterValueException("unable to find domain by id " + resourceId); throw new InvalidParameterValueException("unable to find domain by id " + resourceId);
} }
resourceType = ApiCommandResourceType.Domain;
DomainDetailVO domainDetailVO = _domainDetailsDao.findDetail(resourceId, name); DomainDetailVO domainDetailVO = _domainDetailsDao.findDetail(resourceId, name);
if (domainDetailVO == null) { if (domainDetailVO == null) {
domainDetailVO = new DomainDetailVO(resourceId, name, value); domainDetailVO = new DomainDetailVO(resourceId, name, value);
@ -798,6 +809,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
throw new InvalidParameterValueException("Scope provided is invalid"); throw new InvalidParameterValueException("Scope provided is invalid");
} }
CallContext.current().setEventResourceType(resourceType);
CallContext.current().setEventResourceId(resourceId);
CallContext.current().setEventDetails(String.format(" Name: %s, New Value: %s, Scope: %s", name, value, scope));
_configDepot.invalidateConfigCache(name, scopeVal, resourceId); _configDepot.invalidateConfigCache(name, scopeVal, resourceId);
return valueEncrypted ? DBEncryptionUtil.decrypt(value) : value; return valueEncrypted ? DBEncryptionUtil.decrypt(value) : value;
} }
@ -955,6 +970,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
category = config.getCategory(); category = config.getCategory();
} }
if (CATEGORY_SYSTEM.equals(category) && !_accountMgr.isRootAdmin(caller.getId())) {
logger.warn("Only Root Admin is allowed to edit the configuration " + name);
throw new CloudRuntimeException("Only Root Admin is allowed to edit this configuration.");
}
if (value == null) { if (value == null) {
return _configDao.findByName(name); return _configDao.findByName(name);
} }
@ -1006,7 +1026,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (value.isEmpty() || value.equals("null")) { if (value.isEmpty() || value.equals("null")) {
value = (id == null) ? null : ""; value = (id == null) ? null : "";
} }
final String updatedValue = updateConfiguration(userId, name, category, value, scope, id); final String updatedValue = updateConfiguration(userId, name, category, value, scope, id);
if (value == null && updatedValue == null || updatedValue.equalsIgnoreCase(value)) { if (value == null && updatedValue == null || updatedValue.equalsIgnoreCase(value)) {
return _configDao.findByName(name); return _configDao.findByName(name);
@ -6673,6 +6692,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
throw new InvalidParameterValueException("networkMode should be set only for Isolated network offerings"); throw new InvalidParameterValueException("networkMode should be set only for Isolated network offerings");
} }
if (NetworkOffering.NetworkMode.ROUTED.equals(networkMode)) { if (NetworkOffering.NetworkMode.ROUTED.equals(networkMode)) {
if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.value()) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed networks", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key()));
}
if (zoneIds != null) {
for (Long zoneId: zoneIds) {
if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(zoneId)) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed networks in zone (ID: %s)", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key(), zoneId));
}
}
}
boolean useVirtualRouterOnly = true; boolean useVirtualRouterOnly = true;
for (Service service : serviceProviderMap.keySet()) { for (Service service : serviceProviderMap.keySet()) {
Set<Provider> providers = serviceProviderMap.get(service); Set<Provider> providers = serviceProviderMap.get(service);

View File

@ -1795,7 +1795,7 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
useLocalStorage = diskOffering.isUseLocalStorage(); useLocalStorage = diskOffering.isUseLocalStorage();
} }
diskProfile.setUseLocalStorage(useLocalStorage); diskProfile.setUseLocalStorage(useLocalStorage);
logger.debug(String.format("Calling StoragePoolAllocators to find suitable pools to allocate volume [{}] necessary to deploy VM [{}].", toBeCreated.getUuid(), vmProfile.getUuid())); logger.debug("Calling StoragePoolAllocators to find suitable pools to allocate volume [{}] necessary to deploy VM [{}].", toBeCreated.getUuid(), vmProfile.getUuid());
boolean foundPotentialPools = tryToFindPotentialPoolsToAlocateVolume(vmProfile, plan, avoid, returnUpTo, suitableVolumeStoragePools, toBeCreated, diskProfile); boolean foundPotentialPools = tryToFindPotentialPoolsToAlocateVolume(vmProfile, plan, avoid, returnUpTo, suitableVolumeStoragePools, toBeCreated, diskProfile);
if (avoid.getPoolsToAvoid() != null) { if (avoid.getPoolsToAvoid() != null) {

View File

@ -1384,7 +1384,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
} }
} }
void validateNetworkCidrSize(Account caller, Integer cidrSize, String cidr, NetworkOffering networkOffering, long accountId) { void validateNetworkCidrSize(Account caller, Integer cidrSize, String cidr, NetworkOffering networkOffering, long accountId, long zoneId) {
if (!GuestType.Isolated.equals(networkOffering.getGuestType())) { if (!GuestType.Isolated.equals(networkOffering.getGuestType())) {
if (cidrSize != null) { if (cidrSize != null) {
throw new InvalidParameterValueException("network cidr size is only applicable on Isolated networks"); throw new InvalidParameterValueException("network cidr size is only applicable on Isolated networks");
@ -1405,11 +1405,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
if (cidrSize == null) { if (cidrSize == null) {
throw new InvalidParameterValueException("network cidr or cidr size is required for Isolated networks with ROUTED mode"); throw new InvalidParameterValueException("network cidr or cidr size is required for Isolated networks with ROUTED mode");
} }
Integer maxCidrSize = routedIpv4Manager.RoutedNetworkIPv4MaxCidrSize.valueIn(accountId); Integer maxCidrSize = RoutedIpv4Manager.RoutedNetworkIPv4MaxCidrSize.valueIn(accountId);
if (cidrSize > maxCidrSize) { if (cidrSize > maxCidrSize) {
throw new InvalidParameterValueException("network cidr size cannot be bigger than maximum cidr size " + maxCidrSize); throw new InvalidParameterValueException("network cidr size cannot be bigger than maximum cidr size " + maxCidrSize);
} }
Integer minCidrSize = routedIpv4Manager.RoutedNetworkIPv4MinCidrSize.valueIn(accountId); Integer minCidrSize = RoutedIpv4Manager.RoutedNetworkIPv4MinCidrSize.valueIn(accountId);
if (cidrSize < minCidrSize) { if (cidrSize < minCidrSize) {
throw new InvalidParameterValueException("network cidr size cannot be smaller than minimum cidr size " + minCidrSize); throw new InvalidParameterValueException("network cidr size cannot be smaller than minimum cidr size " + minCidrSize);
} }
@ -1656,11 +1656,16 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
} }
} }
if (NetworkOffering.NetworkMode.ROUTED.equals(ntwkOff.getNetworkMode())
&& !routedIpv4Manager.isRoutedNetworkVpcEnabled(zone.getId())) {
throw new InvalidParameterValueException("Routed network is not enabled in this zone");
}
if (isNonVpcNetworkSupportingDynamicRouting(ntwkOff) && ntwkOff.isSpecifyAsNumber() && asNumber == null) { if (isNonVpcNetworkSupportingDynamicRouting(ntwkOff) && ntwkOff.isSpecifyAsNumber() && asNumber == null) {
throw new InvalidParameterValueException("AS number is required for the network but not passed."); throw new InvalidParameterValueException("AS number is required for the network but not passed.");
} }
validateNetworkCidrSize(caller, networkCidrSize, cidr, ntwkOff, owner.getAccountId()); validateNetworkCidrSize(caller, networkCidrSize, cidr, ntwkOff, owner.getAccountId(), zone.getId());
validateSharedNetworkRouterIPs(gateway, startIP, endIP, netmask, routerIPv4, routerIPv6, startIPv6, endIPv6, ip6Cidr, ntwkOff); validateSharedNetworkRouterIPs(gateway, startIP, endIP, netmask, routerIPv4, routerIPv6, startIPv6, endIPv6, ip6Cidr, ntwkOff);

View File

@ -65,10 +65,8 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO; import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO;
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.network.BgpPeerVO; import org.apache.cloudstack.network.BgpPeer;
import org.apache.cloudstack.network.RoutedIpv4Manager; import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.BgpPeerDao;
import org.apache.cloudstack.network.dao.BgpPeerNetworkMapDao;
import org.apache.cloudstack.network.topology.NetworkTopology; import org.apache.cloudstack.network.topology.NetworkTopology;
import org.apache.cloudstack.network.topology.NetworkTopologyContext; import org.apache.cloudstack.network.topology.NetworkTopologyContext;
import org.apache.cloudstack.utils.CloudStackVersion; import org.apache.cloudstack.utils.CloudStackVersion;
@ -114,6 +112,7 @@ import com.cloud.api.query.dao.DomainRouterJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.vo.DomainRouterJoinVO; import com.cloud.api.query.vo.DomainRouterJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.bgp.BGPService;
import com.cloud.cluster.ManagementServerHostVO; import com.cloud.cluster.ManagementServerHostVO;
import com.cloud.cluster.dao.ManagementServerHostDao; import com.cloud.cluster.dao.ManagementServerHostDao;
import com.cloud.configuration.Config; import com.cloud.configuration.Config;
@ -348,9 +347,7 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
@Inject @Inject
RoutedIpv4Manager routedIpv4Manager; RoutedIpv4Manager routedIpv4Manager;
@Inject @Inject
BgpPeerDao bgpPeerDao; BGPService bgpService;
@Inject
BgpPeerNetworkMapDao bgpPeerNetworkMapDao;
private int _routerRamSize; private int _routerRamSize;
private int _routerCpuMHz; private int _routerCpuMHz;
@ -2508,12 +2505,12 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
if (guestNetwork.getVpcId() != null) { if (guestNetwork.getVpcId() != null) {
final Vpc vpc = _vpcDao.findById(guestNetwork.getVpcId()); final Vpc vpc = _vpcDao.findById(guestNetwork.getVpcId());
if (routedIpv4Manager.isDynamicRoutedVpc(vpc)) { if (routedIpv4Manager.isDynamicRoutedVpc(vpc)) {
final List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByVpcId(guestNetwork.getVpcId()); List<? extends BgpPeer> bgpPeers = bgpService.getBgpPeersForVpc(vpc);
_commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, guestNetwork); _commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, guestNetwork);
} }
} else { } else {
if (routedIpv4Manager.isDynamicRoutedNetwork(guestNetwork)) { if (routedIpv4Manager.isDynamicRoutedNetwork(guestNetwork)) {
final List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByNetworkId(guestNetworkId); List<? extends BgpPeer> bgpPeers = bgpService.getBgpPeersForNetwork(guestNetwork);
_commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, guestNetwork); _commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, guestNetwork);
} }
} }

View File

@ -502,6 +502,18 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
} }
networkMode = NetworkOffering.NetworkMode.valueOf(networkModeStr); networkMode = NetworkOffering.NetworkMode.valueOf(networkModeStr);
} }
if (NetworkOffering.NetworkMode.ROUTED.equals(networkMode)) {
if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.value()) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed VPCs", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key()));
}
if (zoneIds != null) {
for (Long zoneId: zoneIds) {
if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(zoneId)) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed VPCs in zone (ID: %s)", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key(), zoneId));
}
}
}
}
boolean specifyAsNumber = cmd.getSpecifyAsNumber(); boolean specifyAsNumber = cmd.getSpecifyAsNumber();
String routingModeString = cmd.getRoutingMode(); String routingModeString = cmd.getRoutingMode();
@ -1163,12 +1175,17 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
throw ex; throw ex;
} }
if (NetworkOffering.NetworkMode.ROUTED.equals(vpcOff.getNetworkMode())
&& !routedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(zoneId)) {
throw new InvalidParameterValueException("Routed VPC is not enabled in this zone");
}
if (NetworkOffering.RoutingMode.Dynamic.equals(vpcOff.getRoutingMode()) && vpcOff.isSpecifyAsNumber() && asNumber == null) { if (NetworkOffering.RoutingMode.Dynamic.equals(vpcOff.getRoutingMode()) && vpcOff.isSpecifyAsNumber() && asNumber == null) {
throw new InvalidParameterValueException("AS number is required for the VPC but not passed."); throw new InvalidParameterValueException("AS number is required for the VPC but not passed.");
} }
// Validate VPC cidr/cidrsize // Validate VPC cidr/cidrsize
validateVpcCidrSize(caller, owner.getAccountId(), vpcOff, cidr, cidrSize); validateVpcCidrSize(caller, owner.getAccountId(), vpcOff, cidr, cidrSize, zoneId);
// Validate BGP peers // Validate BGP peers
if (CollectionUtils.isNotEmpty(bgpPeerIds)) { if (CollectionUtils.isNotEmpty(bgpPeerIds)) {
@ -1253,7 +1270,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
return newVpc; return newVpc;
} }
private void validateVpcCidrSize(Account caller, long accountId, VpcOffering vpcOffering, String cidr, Integer cidrSize) { private void validateVpcCidrSize(Account caller, long accountId, VpcOffering vpcOffering, String cidr, Integer cidrSize, long zoneId) {
if (ObjectUtils.allNull(cidr, cidrSize)) { if (ObjectUtils.allNull(cidr, cidrSize)) {
throw new InvalidParameterValueException("VPC cidr or cidr size must be specified"); throw new InvalidParameterValueException("VPC cidr or cidr size must be specified");
} }

View File

@ -24,6 +24,7 @@ public class ManagementServerHostStatsEntry implements ManagementServerHostStats
private long managementServerHostId; private long managementServerHostId;
private String managementServerHostUuid; private String managementServerHostUuid;
private long managementServerRunId;
private Date collectionTime; private Date collectionTime;
private long sessions; private long sessions;
@ -94,6 +95,15 @@ public class ManagementServerHostStatsEntry implements ManagementServerHostStats
this.managementServerHostUuid = managementServerHostUuid; this.managementServerHostUuid = managementServerHostUuid;
} }
@Override
public long getManagementServerRunId() {
return managementServerRunId;
}
public void setManagementServerRunId(long managementServerRunId) {
this.managementServerRunId = managementServerRunId;
}
@Override @Override
public Date getCollectionTime(){ public Date getCollectionTime(){
return collectionTime; return collectionTime;

View File

@ -68,11 +68,6 @@ import org.apache.cloudstack.api.command.admin.affinitygroup.UpdateVMAffinityGro
import org.apache.cloudstack.api.command.admin.alert.GenerateAlertCmd; import org.apache.cloudstack.api.command.admin.alert.GenerateAlertCmd;
import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd; import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd;
import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd; import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd;
import org.apache.cloudstack.api.command.admin.bgp.CreateASNRangeCmd;
import org.apache.cloudstack.api.command.admin.bgp.DeleteASNRangeCmd;
import org.apache.cloudstack.api.command.admin.bgp.ListASNRangesCmd;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.api.command.admin.bgp.ReleaseASNumberCmd;
import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd; import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd;
import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd; import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd;
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
@ -4017,12 +4012,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(RemoveSecondaryStorageSelectorCmd.class); cmdList.add(RemoveSecondaryStorageSelectorCmd.class);
cmdList.add(ListAffectedVmsForStorageScopeChangeCmd.class); cmdList.add(ListAffectedVmsForStorageScopeChangeCmd.class);
cmdList.add(CreateASNRangeCmd.class);
cmdList.add(ListASNRangesCmd.class);
cmdList.add(DeleteASNRangeCmd.class);
cmdList.add(ListASNumbersCmd.class);
cmdList.add(ReleaseASNumberCmd.class);
// Out-of-band management APIs for admins // Out-of-band management APIs for admins
cmdList.add(EnableOutOfBandManagementForHostCmd.class); cmdList.add(EnableOutOfBandManagementForHostCmd.class);
cmdList.add(DisableOutOfBandManagementForHostCmd.class); cmdList.add(DisableOutOfBandManagementForHostCmd.class);

View File

@ -95,6 +95,7 @@ import com.cloud.cluster.ClusterServicePdu;
import com.cloud.cluster.ManagementServerHostVO; import com.cloud.cluster.ManagementServerHostVO;
import com.cloud.cluster.ManagementServerStatusVO; import com.cloud.cluster.ManagementServerStatusVO;
import com.cloud.cluster.dao.ManagementServerHostDao; import com.cloud.cluster.dao.ManagementServerHostDao;
import com.cloud.cluster.dao.ManagementServerHostPeerDao;
import com.cloud.cluster.dao.ManagementServerStatusDao; import com.cloud.cluster.dao.ManagementServerStatusDao;
import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.VlanVO; import com.cloud.dc.VlanVO;
@ -346,6 +347,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
@Inject @Inject
private ManagementServerStatusDao managementServerStatusDao; private ManagementServerStatusDao managementServerStatusDao;
@Inject @Inject
private ManagementServerHostPeerDao managementServerHostPeerDao;
@Inject
VirtualMachineManager virtualMachineManager; VirtualMachineManager virtualMachineManager;
private final ConcurrentHashMap<String, ManagementServerHostStats> managementServerHostStats = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, ManagementServerHostStats> managementServerHostStats = new ConcurrentHashMap<>();
@ -796,6 +799,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
logger.trace("Metrics collection start..."); logger.trace("Metrics collection start...");
newEntry.setManagementServerHostId(mshost.getId()); newEntry.setManagementServerHostId(mshost.getId());
newEntry.setManagementServerHostUuid(mshost.getUuid()); newEntry.setManagementServerHostUuid(mshost.getUuid());
newEntry.setManagementServerRunId(mshost.getRunid());
newEntry.setDbLocal(isDbLocal()); newEntry.setDbLocal(isDbLocal());
newEntry.setUsageLocal(isUsageLocal()); newEntry.setUsageLocal(isUsageLocal());
retrieveSession(newEntry); retrieveSession(newEntry);
@ -1153,6 +1157,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
try { try {
hostStatsEntry = gson.fromJson(pdu.getJsonPackage(),new TypeToken<ManagementServerHostStatsEntry>(){}.getType()); hostStatsEntry = gson.fromJson(pdu.getJsonPackage(),new TypeToken<ManagementServerHostStatsEntry>(){}.getType());
managementServerHostStats.put(hostStatsEntry.getManagementServerHostUuid(), hostStatsEntry); managementServerHostStats.put(hostStatsEntry.getManagementServerHostUuid(), hostStatsEntry);
// Update peer state to Up in mshost_peer
updatePeerInfo(hostStatsEntry);
} catch (JsonParseException e) { } catch (JsonParseException e) {
logger.error("Exception in decoding of other MS hosts status from : " + pdu.getSourcePeer()); logger.error("Exception in decoding of other MS hosts status from : " + pdu.getSourcePeer());
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
@ -1162,6 +1169,23 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
return null; return null;
} }
private void updatePeerInfo(ManagementServerHostStatsEntry hostStatsEntry) {
// Update msId to id of the management server if msId is same as managementServerNodeId
if (msId == managementServerNodeId) {
ManagementServerHostVO mgmtServerVo = managementServerHostDao.findByMsid(managementServerNodeId);
if (mgmtServerVo != null) {
msId = mgmtServerVo.getId();
} else {
logger.warn(String.format("Cannot find management server with msid [%s]. Therefore, do not update peer info.", managementServerNodeId));
return;
}
}
// Update peer state to Up in mshost_peer
if (msId != hostStatsEntry.getManagementServerHostId()) {
managementServerHostPeerDao.updatePeerInfo(msId, hostStatsEntry.getManagementServerHostId(), hostStatsEntry.getManagementServerRunId(), ManagementServerHost.State.Up);
}
}
@Override @Override
public void onManagementNodeJoined(List<? extends ManagementServerHost> nodeList, long selfNodeId) { public void onManagementNodeJoined(List<? extends ManagementServerHost> nodeList, long selfNodeId) {
// do nothing, but wait for the status to come through // do nothing, but wait for the status to come through

View File

@ -3101,7 +3101,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
} else { } else {
final StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId()); final StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId());
final long allocatedSizeWithTemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null); final long allocatedSizeWithTemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null);
return checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize); return checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize, true);
} }
} }
@ -3164,6 +3164,10 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
} }
protected boolean checkPoolforSpace(StoragePool pool, long allocatedSizeWithTemplate, long totalAskingSize) { protected boolean checkPoolforSpace(StoragePool pool, long allocatedSizeWithTemplate, long totalAskingSize) {
return checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize, false);
}
protected boolean checkPoolforSpace(StoragePool pool, long allocatedSizeWithTemplate, long totalAskingSize, boolean forVolumeResize) {
// allocated space includes templates // allocated space includes templates
StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId()); StoragePoolVO poolVO = _storagePoolDao.findById(pool.getId());
@ -3196,11 +3200,23 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
if (usedPercentage > storageAllocatedThreshold) { if (usedPercentage > storageAllocatedThreshold) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for storage allocation since its allocated percentage: " + usedPercentage logger.debug("Insufficient un-allocated capacity on: " + pool.getId() + " for storage allocation since its allocated percentage: " + usedPercentage
+ " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " + storageAllocatedThreshold + ", skipping this pool"); + " has crossed the allocated pool.storage.allocated.capacity.disablethreshold: " + storageAllocatedThreshold);
}
if (!forVolumeResize) {
return false;
}
if (!AllowVolumeReSizeBeyondAllocation.valueIn(pool.getDataCenterId())) {
logger.debug(String.format("Skipping the pool %s as %s is false", pool, AllowVolumeReSizeBeyondAllocation.key()));
return false;
} }
double storageAllocatedThresholdForResize = CapacityManager.StorageAllocatedCapacityDisableThresholdForVolumeSize.valueIn(pool.getDataCenterId());
if (usedPercentage > storageAllocatedThresholdForResize) {
logger.debug(String.format("Skipping the pool %s since its allocated percentage: %s has crossed the allocated %s: %s",
pool, usedPercentage, CapacityManager.StorageAllocatedCapacityDisableThresholdForVolumeSize.key(), storageAllocatedThresholdForResize));
return false; return false;
} }
}
if (totalOverProvCapacity < (allocatedSizeWithTemplate + totalAskingSize)) { if (totalOverProvCapacity < (allocatedSizeWithTemplate + totalAskingSize)) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
@ -4050,7 +4066,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
MountDisabledStoragePool, MountDisabledStoragePool,
VmwareCreateCloneFull, VmwareCreateCloneFull,
VmwareAllowParallelExecution, VmwareAllowParallelExecution,
DataStoreDownloadFollowRedirects DataStoreDownloadFollowRedirects,
AllowVolumeReSizeBeyondAllocation
}; };
} }

View File

@ -1093,6 +1093,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
Long newMaxIops = cmd.getMaxIops(); Long newMaxIops = cmd.getMaxIops();
Integer newHypervisorSnapshotReserve = null; Integer newHypervisorSnapshotReserve = null;
boolean shrinkOk = cmd.isShrinkOk(); boolean shrinkOk = cmd.isShrinkOk();
boolean autoMigrateVolume = cmd.getAutoMigrate();
VolumeVO volume = _volsDao.findById(cmd.getEntityId()); VolumeVO volume = _volsDao.findById(cmd.getEntityId());
if (volume == null) { if (volume == null) {
@ -1154,8 +1155,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
newSize = volume.getSize(); newSize = volume.getSize();
} }
newMinIops = cmd.getMinIops();
if (newMinIops != null) { if (newMinIops != null) {
if (!volume.getVolumeType().equals(Volume.Type.ROOT) && (diskOffering.isCustomizedIops() == null || !diskOffering.isCustomizedIops())) { if (!volume.getVolumeType().equals(Volume.Type.ROOT) && (diskOffering.isCustomizedIops() == null || !diskOffering.isCustomizedIops())) {
throw new InvalidParameterValueException("The current disk offering does not support customization of the 'Min IOPS' parameter."); throw new InvalidParameterValueException("The current disk offering does not support customization of the 'Min IOPS' parameter.");
@ -1165,8 +1164,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
newMinIops = volume.getMinIops(); newMinIops = volume.getMinIops();
} }
newMaxIops = cmd.getMaxIops();
if (newMaxIops != null) { if (newMaxIops != null) {
if (!volume.getVolumeType().equals(Volume.Type.ROOT) && (diskOffering.isCustomizedIops() == null || !diskOffering.isCustomizedIops())) { if (!volume.getVolumeType().equals(Volume.Type.ROOT) && (diskOffering.isCustomizedIops() == null || !diskOffering.isCustomizedIops())) {
throw new InvalidParameterValueException("The current disk offering does not support customization of the 'Max IOPS' parameter."); throw new InvalidParameterValueException("The current disk offering does not support customization of the 'Max IOPS' parameter.");
@ -1288,6 +1285,54 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
return volume; return volume;
} }
Long newDiskOfferingId = newDiskOffering != null ? newDiskOffering.getId() : diskOffering.getId();
boolean volumeMigrateRequired = false;
List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = null;
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
if (!storageMgr.storagePoolHasEnoughSpaceForResize(storagePool, currentSize, newSize)) {
if (!autoMigrateVolume) {
throw new CloudRuntimeException(String.format("Failed to resize volume %s since the storage pool does not have enough space to accommodate new size for the volume %s, try with automigrate set to true in order to check in the other suitable pools for the new size and then migrate & resize volume there.", volume.getUuid(), volume.getName()));
}
Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOfferingId, currentSize, newMinIops, newMaxIops, true, false);
List<? extends StoragePool> suitableStoragePools = poolsPair.second();
if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) found for migrating to support new disk offering or new size", volume.getUuid()));
}
final Long newSizeFinal = newSize;
suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume resize failed for volume ID: %s as no suitable pool(s) with enough space found.", volume.getUuid()));
}
Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
volumeMigrateRequired = true;
}
boolean volumeResizeRequired = false;
if (currentSize != newSize || !compareEqualsIncludingNullOrZero(newMaxIops, volume.getMaxIops()) || !compareEqualsIncludingNullOrZero(newMinIops, volume.getMinIops())) {
volumeResizeRequired = true;
}
if (!volumeMigrateRequired && !volumeResizeRequired && newDiskOffering != null) {
_volsDao.updateDiskOffering(volume.getId(), newDiskOffering.getId());
volume = _volsDao.findById(volume.getId());
updateStorageWithTheNewDiskOffering(volume, newDiskOffering);
return volume;
}
if (volumeMigrateRequired) {
MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOfferingId, true);
try {
Volume result = migrateVolume(migrateVolumeCmd);
volume = (result != null) ? _volsDao.findById(result.getId()) : null;
if (volume == null) {
throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
}
} catch (Exception e) {
throw new CloudRuntimeException(String.format("Volume resize operation failed for volume ID: %s as migration failed to storage pool %s accommodating new size", volume.getUuid(), suitableStoragePoolsWithEnoughSpace.get(0).getId()));
}
}
UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); UserVmVO userVm = _userVmDao.findById(volume.getInstanceId());
if (userVm != null) { if (userVm != null) {
@ -1973,6 +2018,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
public Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) throws ResourceAllocationException { public Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) throws ResourceAllocationException {
Long newSize = cmd.getSize(); Long newSize = cmd.getSize();
Long newMinIops = cmd.getMinIops(); Long newMinIops = cmd.getMinIops();
Long newMaxIops = cmd.getMaxIops(); Long newMaxIops = cmd.getMaxIops();
Long newDiskOfferingId = cmd.getNewDiskOfferingId(); Long newDiskOfferingId = cmd.getNewDiskOfferingId();
boolean shrinkOk = cmd.isShrinkOk(); boolean shrinkOk = cmd.isShrinkOk();
@ -2055,7 +2101,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
StoragePoolVO existingStoragePool = _storagePoolDao.findById(volume.getPoolId()); StoragePoolVO existingStoragePool = _storagePoolDao.findById(volume.getPoolId());
Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOffering.getId(), newSize, newMinIops, newMaxIops, true, false); Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = managementService.listStoragePoolsForSystemMigrationOfVolume(volume.getId(), newDiskOffering.getId(), currentSize, newMinIops, newMaxIops, true, false);
List<? extends StoragePool> suitableStoragePools = poolsPair.second(); List<? extends StoragePool> suitableStoragePools = poolsPair.second();
if (!suitableStoragePools.stream().anyMatch(p -> (p.getId() == existingStoragePool.getId()))) { if (!suitableStoragePools.stream().anyMatch(p -> (p.getId() == existingStoragePool.getId()))) {
@ -2077,10 +2123,16 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) { if (CollectionUtils.isEmpty(poolsPair.first()) && CollectionUtils.isEmpty(poolsPair.second())) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume ID: %s as no suitable pool(s) found for migrating to support new disk offering", volume.getUuid())); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume ID: %s as no suitable pool(s) found for migrating to support new disk offering", volume.getUuid()));
} }
Collections.shuffle(suitableStoragePools); final Long newSizeFinal = newSize;
MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePools.get(0).getId(), newDiskOffering.getId(), true); List<? extends StoragePool> suitableStoragePoolsWithEnoughSpace = suitableStoragePools.stream().filter(pool -> storageMgr.storagePoolHasEnoughSpaceForResize(pool, 0L, newSizeFinal)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(suitableStoragePoolsWithEnoughSpace)) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Volume change offering operation failed for volume ID: %s as no suitable pool(s) with enough space found for volume migration.", volume.getUuid()));
}
Collections.shuffle(suitableStoragePoolsWithEnoughSpace);
MigrateVolumeCmd migrateVolumeCmd = new MigrateVolumeCmd(volume.getId(), suitableStoragePoolsWithEnoughSpace.get(0).getId(), newDiskOffering.getId(), true);
try { try {
volume = (VolumeVO) migrateVolume(migrateVolumeCmd); Volume result = migrateVolume(migrateVolumeCmd);
volume = (result != null) ? _volsDao.findById(result.getId()) : null;
if (volume == null) { if (volume == null) {
throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume ID: %s migration failed to storage pool %s", volume.getUuid(), suitableStoragePools.get(0).getId())); throw new CloudRuntimeException(String.format("Volume change offering operation failed for volume ID: %s migration failed to storage pool %s", volume.getUuid(), suitableStoragePools.get(0).getId()));
} }

View File

@ -373,6 +373,13 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
"totp", "totp",
"The default user two factor authentication provider. Eg. totp, staticpin", true, ConfigKey.Scope.Domain); "The default user two factor authentication provider. Eg. totp, staticpin", true, ConfigKey.Scope.Domain);
public static final ConfigKey<Boolean> apiKeyAccess = new ConfigKey<>(ConfigKey.CATEGORY_SYSTEM, Boolean.class,
"api.key.access",
"true",
"Determines whether API (api-key/secret-key) access is allowed or not. Editable only by Root Admin.",
true,
ConfigKey.Scope.Domain);
protected AccountManagerImpl() { protected AccountManagerImpl() {
super(); super();
} }
@ -1463,6 +1470,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
logger.debug("Updating user with Id: " + user.getUuid()); logger.debug("Updating user with Id: " + user.getUuid());
validateAndUpdateApiAndSecretKeyIfNeeded(updateUserCmd, user); validateAndUpdateApiAndSecretKeyIfNeeded(updateUserCmd, user);
validateAndUpdateUserApiKeyAccess(updateUserCmd, user);
Account account = retrieveAndValidateAccount(user); Account account = retrieveAndValidateAccount(user);
validateAndUpdateFirstNameIfNeeded(updateUserCmd, user); validateAndUpdateFirstNameIfNeeded(updateUserCmd, user);
@ -1682,6 +1690,38 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
user.setSecretKey(secretKey); user.setSecretKey(secretKey);
} }
protected void validateAndUpdateUserApiKeyAccess(UpdateUserCmd updateUserCmd, UserVO user) {
if (updateUserCmd.getApiKeyAccess() != null) {
try {
ApiConstants.ApiKeyAccess access = ApiConstants.ApiKeyAccess.valueOf(updateUserCmd.getApiKeyAccess().toUpperCase());
user.setApiKeyAccess(access.toBoolean());
Long callingUserId = CallContext.current().getCallingUserId();
Account callingAccount = CallContext.current().getCallingAccount();
ActionEventUtils.onActionEvent(callingUserId, callingAccount.getAccountId(), callingAccount.getDomainId(),
EventTypes.API_KEY_ACCESS_UPDATE, "Api key access was changed for the User to " + access.toString(),
user.getId(), ApiCommandResourceType.User.toString());
} catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit");
}
}
}
protected void validateAndUpdateAccountApiKeyAccess(UpdateAccountCmd updateAccountCmd, AccountVO account) {
if (updateAccountCmd.getApiKeyAccess() != null) {
try {
ApiConstants.ApiKeyAccess access = ApiConstants.ApiKeyAccess.valueOf(updateAccountCmd.getApiKeyAccess().toUpperCase());
account.setApiKeyAccess(access.toBoolean());
Long callingUserId = CallContext.current().getCallingUserId();
Account callingAccount = CallContext.current().getCallingAccount();
ActionEventUtils.onActionEvent(callingUserId, callingAccount.getAccountId(), callingAccount.getDomainId(),
EventTypes.API_KEY_ACCESS_UPDATE, "Api key access was changed for the Account to " + access.toString(),
account.getId(), ApiCommandResourceType.Account.toString());
} catch (IllegalArgumentException ex) {
throw new InvalidParameterValueException("ApiKeyAccess value can only be Enabled/Disabled/Inherit");
}
}
}
/** /**
* Searches for a user with the given userId. If no user is found we throw an {@link InvalidParameterValueException}. * Searches for a user with the given userId. If no user is found we throw an {@link InvalidParameterValueException}.
*/ */
@ -2048,6 +2088,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
Account caller = getCurrentCallingAccount(); Account caller = getCurrentCallingAccount();
checkAccess(caller, _domainMgr.getDomain(account.getDomainId())); checkAccess(caller, _domainMgr.getDomain(account.getDomainId()));
validateAndUpdateAccountApiKeyAccess(cmd, acctForUpdate);
if(newAccountName != null) { if(newAccountName != null) {
if (newAccountName.isEmpty()) { if (newAccountName.isEmpty()) {
@ -2794,18 +2836,18 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
} }
@Override @Override
public Map<String, String> getKeys(GetUserKeysCmd cmd) { public Pair<Boolean, Map<String, String>> getKeys(GetUserKeysCmd cmd) {
final long userId = cmd.getID(); final long userId = cmd.getID();
return getKeys(userId); return getKeys(userId);
} }
@Override @Override
public Map<String, String> getKeys(Long userId) { public Pair<Boolean, Map<String, String>> getKeys(Long userId) {
User user = getActiveUser(userId); User user = getActiveUser(userId);
if (user == null) { if (user == null) {
throw new InvalidParameterValueException("Unable to find user by id"); throw new InvalidParameterValueException("Unable to find user by id");
} }
final ControlledEntity account = getAccount(getUserAccountById(userId).getAccountId()); //Extracting the Account from the userID of the requested user. final Account account = getAccount(getUserAccountById(userId).getAccountId()); //Extracting the Account from the userID of the requested user.
User caller = CallContext.current().getCallingUser(); User caller = CallContext.current().getCallingUser();
preventRootDomainAdminAccessToRootAdminKeys(caller, account); preventRootDomainAdminAccessToRootAdminKeys(caller, account);
checkAccess(caller, account); checkAccess(caller, account);
@ -2814,7 +2856,15 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
keys.put("apikey", user.getApiKey()); keys.put("apikey", user.getApiKey());
keys.put("secretkey", user.getSecretKey()); keys.put("secretkey", user.getSecretKey());
return keys; Boolean apiKeyAccess = user.getApiKeyAccess();
if (apiKeyAccess == null) {
apiKeyAccess = account.getApiKeyAccess();
if (apiKeyAccess == null) {
apiKeyAccess = AccountManagerImpl.apiKeyAccess.valueIn(account.getDomainId());
}
}
return new Pair<Boolean, Map<String, String>>(apiKeyAccess, keys);
} }
protected void preventRootDomainAdminAccessToRootAdminKeys(User caller, ControlledEntity account) { protected void preventRootDomainAdminAccessToRootAdminKeys(User caller, ControlledEntity account) {
@ -3320,7 +3370,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Override @Override
public ConfigKey<?>[] getConfigKeys() { public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {UseSecretKeyInResponse, enableUserTwoFactorAuthentication, return new ConfigKey<?>[] {UseSecretKeyInResponse, enableUserTwoFactorAuthentication,
userTwoFactorAuthenticationDefaultProvider, mandateUserTwoFactorAuthentication, userTwoFactorAuthenticationIssuer}; userTwoFactorAuthenticationDefaultProvider, mandateUserTwoFactorAuthentication, userTwoFactorAuthenticationIssuer, apiKeyAccess};
} }
public List<UserTwoFactorAuthenticator> getUserTwoFactorAuthenticationProviders() { public List<UserTwoFactorAuthenticator> getUserTwoFactorAuthenticationProviders() {

View File

@ -16,6 +16,7 @@
// under the License. // under the License.
package com.cloud.vm; package com.cloud.vm;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality;
import static com.cloud.storage.Volume.IOPS_LIMIT; import static com.cloud.storage.Volume.IOPS_LIMIT;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize; import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS; import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
@ -679,23 +680,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
private static final ConfigKey<Boolean> VmDestroyForcestop = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.destroy.forcestop", "false", private static final ConfigKey<Boolean> VmDestroyForcestop = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.destroy.forcestop", "false",
"On destroy, force-stop takes this value ", true); "On destroy, force-stop takes this value ", true);
public static final List<HypervisorType> VM_STORAGE_MIGRATION_SUPPORTING_HYPERVISORS = new ArrayList<>(Arrays.asList(
HypervisorType.KVM,
HypervisorType.VMware,
HypervisorType.XenServer,
HypervisorType.Simulator
));
protected static final List<HypervisorType> ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS = Arrays.asList(
HypervisorType.KVM,
HypervisorType.XenServer,
HypervisorType.VMware,
HypervisorType.Simulator,
HypervisorType.Custom
);
private static final List<HypervisorType> HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS = Arrays.asList(HypervisorType.KVM, HypervisorType.VMware);
@Override @Override
public UserVmVO getVirtualMachine(long vmId) { public UserVmVO getVirtualMachine(long vmId) {
return _vmDao.findById(vmId); return _vmDao.findById(vmId);
@ -4563,7 +4547,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
* @throws InvalidParameterValueException if the hypervisor does not support rootdisksize override * @throws InvalidParameterValueException if the hypervisor does not support rootdisksize override
*/ */
protected void verifyIfHypervisorSupportsRootdiskSizeOverride(HypervisorType hypervisorType) { protected void verifyIfHypervisorSupportsRootdiskSizeOverride(HypervisorType hypervisorType) {
if (!ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS.contains(hypervisorType)) { if (!hypervisorType.isFunctionalitySupported(Functionality.RootDiskSizeOverride)) {
throw new InvalidParameterValueException("Hypervisor " + hypervisorType + " does not support rootdisksize override"); throw new InvalidParameterValueException("Hypervisor " + hypervisorType + " does not support rootdisksize override");
} }
} }
@ -6606,9 +6590,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
} }
HypervisorType hypervisorType = vm.getHypervisorType(); HypervisorType hypervisorType = vm.getHypervisorType();
if (vm.getType() != VirtualMachine.Type.User && !HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS.contains(hypervisorType)) { List<HypervisorType> supportedHypervisorsForNonUserVMStorageMigration = HypervisorType.getListOfHypervisorsSupportingFunctionality(Functionality.VmStorageMigration)
throw new InvalidParameterValueException(String.format("Unable to migrate storage of non-user VMs for hypervisor [%s]. Operation only supported for the following" .stream().filter(hypervisor -> !hypervisor.equals(HypervisorType.XenServer)).collect(Collectors.toList());
+ " hypervisors: [%s].", hypervisorType, HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS)); if (vm.getType() != VirtualMachine.Type.User && !supportedHypervisorsForNonUserVMStorageMigration.contains(hypervisorType)) {
throw new InvalidParameterValueException(String.format(
"Unable to migrate storage of non-user VMs for hypervisor [%s]. Operation only supported for the following hypervisors: [%s].",
hypervisorType, supportedHypervisorsForNonUserVMStorageMigration));
} }
List<VolumeVO> vols = _volsDao.findByInstance(vm.getId()); List<VolumeVO> vols = _volsDao.findByInstance(vm.getId());
@ -7318,8 +7305,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported"); throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
} }
if (!VM_STORAGE_MIGRATION_SUPPORTING_HYPERVISORS.contains(vm.getHypervisorType())) { if (!vm.getHypervisorType().isFunctionalitySupported(Functionality.VmStorageMigration)) {
throw new InvalidParameterValueException(String.format("Unsupported hypervisor: %s for VM migration, we support XenServer/VMware/KVM only", vm.getHypervisorType())); throw new InvalidParameterValueException(
String.format("Unsupported hypervisor: %s for VM migration, we support [%s] only",
vm.getHypervisorType(),
HypervisorType.getListOfHypervisorsSupportingFunctionality(Functionality.VmStorageMigration)));
} }
if (_vmSnapshotDao.findByVm(vmId).size() > 0) { if (_vmSnapshotDao.findByVm(vmId).size() > 0) {

View File

@ -174,7 +174,6 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this); VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
int _vmSnapshotMax;
int _wait; int _wait;
static final ConfigKey<Long> VmJobCheckInterval = new ConfigKey<Long>("Advanced", static final ConfigKey<Long> VmJobCheckInterval = new ConfigKey<Long>("Advanced",
@ -188,8 +187,6 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
throw new ConfigurationException("Unable to get the configuration dao."); throw new ConfigurationException("Unable to get the configuration dao.");
} }
_vmSnapshotMax = NumbersUtil.parseInt(_configDao.getValue("vmsnapshot.max"), VMSNAPSHOTMAX);
String value = _configDao.getValue("vmsnapshot.create.wait"); String value = _configDao.getValue("vmsnapshot.create.wait");
_wait = NumbersUtil.parseInt(value, 1800); _wait = NumbersUtil.parseInt(value, 1800);
@ -398,8 +395,10 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
_accountMgr.checkAccess(caller, null, true, userVmVo); _accountMgr.checkAccess(caller, null, true, userVmVo);
// check max snapshot limit for per VM // check max snapshot limit for per VM
if (_vmSnapshotDao.findByVm(vmId).size() >= _vmSnapshotMax) { int vmSnapshotMax = VMSnapshotManager.VMSnapshotMax.value();
throw new CloudRuntimeException("Creating vm snapshot failed due to a VM can just have : " + _vmSnapshotMax + " VM snapshots. Please delete old ones");
if (_vmSnapshotDao.findByVm(vmId).size() >= vmSnapshotMax) {
throw new CloudRuntimeException("Creating vm snapshot failed due to a VM can just have : " + vmSnapshotMax + " VM snapshots. Please delete old ones");
} }
// check if there are active volume snapshots tasks // check if there are active volume snapshots tasks
@ -1391,6 +1390,6 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
@Override @Override
public ConfigKey<?>[] getConfigKeys() { public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {VMSnapshotExpireInterval}; return new ConfigKey<?>[] {VMSnapshotExpireInterval, VMSnapshotMax};
} }
} }

View File

@ -57,6 +57,10 @@ import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils; import com.cloud.utils.net.NetUtils;
import org.apache.cloudstack.api.command.admin.bgp.CreateASNRangeCmd;
import org.apache.cloudstack.api.command.admin.bgp.DeleteASNRangeCmd;
import org.apache.cloudstack.api.command.admin.bgp.ListASNRangesCmd;
import org.apache.cloudstack.api.command.admin.bgp.ReleaseASNumberCmd;
import org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForZoneCmd; import org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForZoneCmd;
import org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForGuestNetworkCmd; import org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForGuestNetworkCmd;
import org.apache.cloudstack.api.command.admin.network.DedicateIpv4SubnetForZoneCmd; import org.apache.cloudstack.api.command.admin.network.DedicateIpv4SubnetForZoneCmd;
@ -74,6 +78,7 @@ import org.apache.cloudstack.api.command.admin.network.bgp.DeleteBgpPeerCmd;
import org.apache.cloudstack.api.command.admin.network.bgp.ListBgpPeersCmd; import org.apache.cloudstack.api.command.admin.network.bgp.ListBgpPeersCmd;
import org.apache.cloudstack.api.command.admin.network.bgp.ReleaseDedicatedBgpPeerCmd; import org.apache.cloudstack.api.command.admin.network.bgp.ReleaseDedicatedBgpPeerCmd;
import org.apache.cloudstack.api.command.admin.network.bgp.UpdateBgpPeerCmd; import org.apache.cloudstack.api.command.admin.network.bgp.UpdateBgpPeerCmd;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.api.command.user.network.routing.CreateRoutingFirewallRuleCmd; import org.apache.cloudstack.api.command.user.network.routing.CreateRoutingFirewallRuleCmd;
import org.apache.cloudstack.api.command.user.network.routing.DeleteRoutingFirewallRuleCmd; import org.apache.cloudstack.api.command.user.network.routing.DeleteRoutingFirewallRuleCmd;
import org.apache.cloudstack.api.command.user.network.routing.ListRoutingFirewallRulesCmd; import org.apache.cloudstack.api.command.user.network.routing.ListRoutingFirewallRulesCmd;
@ -154,6 +159,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
@Override @Override
public ConfigKey<?>[] getConfigKeys() { public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey[] { return new ConfigKey[] {
RoutedNetworkVpcEnabled,
RoutedNetworkIPv4MaxCidrSize, RoutedNetworkIPv4MinCidrSize, RoutedIPv4NetworkCidrAutoAllocationEnabled, RoutedNetworkIPv4MaxCidrSize, RoutedNetworkIPv4MinCidrSize, RoutedIPv4NetworkCidrAutoAllocationEnabled,
RoutedVpcIPv4MaxCidrSize, RoutedVpcIPv4MinCidrSize, UseSystemBgpPeers RoutedVpcIPv4MaxCidrSize, RoutedVpcIPv4MinCidrSize, UseSystemBgpPeers
}; };
@ -162,19 +168,25 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
@Override @Override
public List<Class<?>> getCommands() { public List<Class<?>> getCommands() {
final List<Class<?>> cmdList = new ArrayList<Class<?>>(); final List<Class<?>> cmdList = new ArrayList<Class<?>>();
if (!RoutedNetworkVpcEnabled.value()) {
return cmdList;
}
cmdList.add(CreateIpv4SubnetForZoneCmd.class); cmdList.add(CreateIpv4SubnetForZoneCmd.class);
cmdList.add(DeleteIpv4SubnetForZoneCmd.class); cmdList.add(DeleteIpv4SubnetForZoneCmd.class);
cmdList.add(ListIpv4SubnetsForZoneCmd.class); cmdList.add(ListIpv4SubnetsForZoneCmd.class);
cmdList.add(UpdateIpv4SubnetForZoneCmd.class); cmdList.add(UpdateIpv4SubnetForZoneCmd.class);
cmdList.add(DedicateIpv4SubnetForZoneCmd.class); cmdList.add(DedicateIpv4SubnetForZoneCmd.class);
cmdList.add(ReleaseDedicatedIpv4SubnetForZoneCmd.class); cmdList.add(ReleaseDedicatedIpv4SubnetForZoneCmd.class);
cmdList.add(CreateIpv4SubnetForGuestNetworkCmd.class); cmdList.add(CreateIpv4SubnetForGuestNetworkCmd.class);
cmdList.add(ListIpv4SubnetsForGuestNetworkCmd.class); cmdList.add(ListIpv4SubnetsForGuestNetworkCmd.class);
cmdList.add(DeleteIpv4SubnetForGuestNetworkCmd.class); cmdList.add(DeleteIpv4SubnetForGuestNetworkCmd.class);
cmdList.add(CreateRoutingFirewallRuleCmd.class); cmdList.add(CreateRoutingFirewallRuleCmd.class);
cmdList.add(ListRoutingFirewallRulesCmd.class); cmdList.add(ListRoutingFirewallRulesCmd.class);
cmdList.add(UpdateRoutingFirewallRuleCmd.class); cmdList.add(UpdateRoutingFirewallRuleCmd.class);
cmdList.add(DeleteRoutingFirewallRuleCmd.class); cmdList.add(DeleteRoutingFirewallRuleCmd.class);
cmdList.add(CreateBgpPeerCmd.class); cmdList.add(CreateBgpPeerCmd.class);
cmdList.add(DeleteBgpPeerCmd.class); cmdList.add(DeleteBgpPeerCmd.class);
cmdList.add(ListBgpPeersCmd.class); cmdList.add(ListBgpPeersCmd.class);
@ -183,6 +195,13 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
cmdList.add(ReleaseDedicatedBgpPeerCmd.class); cmdList.add(ReleaseDedicatedBgpPeerCmd.class);
cmdList.add(ChangeBgpPeersForNetworkCmd.class); cmdList.add(ChangeBgpPeersForNetworkCmd.class);
cmdList.add(ChangeBgpPeersForVpcCmd.class); cmdList.add(ChangeBgpPeersForVpcCmd.class);
cmdList.add(CreateASNRangeCmd.class);
cmdList.add(ListASNRangesCmd.class);
cmdList.add(DeleteASNRangeCmd.class);
cmdList.add(ListASNumbersCmd.class);
cmdList.add(ReleaseASNumberCmd.class);
return cmdList; return cmdList;
} }
@ -198,6 +217,8 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
throw new InvalidParameterValueException("Invalid IPv4 subnet: " + subnet); throw new InvalidParameterValueException("Invalid IPv4 subnet: " + subnet);
} }
checkIfRoutedNetworkVpcEnabled(zoneId);
// check conflicts // check conflicts
List<DataCenterIpv4GuestSubnetVO> existingSubnets = dataCenterIpv4GuestSubnetDao.listByDataCenterId(zoneId); List<DataCenterIpv4GuestSubnetVO> existingSubnets = dataCenterIpv4GuestSubnetDao.listByDataCenterId(zoneId);
checkConflicts(existingSubnets, subnet, null); checkConflicts(existingSubnets, subnet, null);
@ -319,7 +340,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return dataCenterIpv4GuestSubnetDao.findById(subnetId); return dataCenterIpv4GuestSubnetDao.findById(subnetId);
} }
private void checkConflicts(List<DataCenterIpv4GuestSubnetVO> existingSubnets, String newSubnet, Long ignoreSubnetId) { protected void checkConflicts(List<DataCenterIpv4GuestSubnetVO> existingSubnets, String newSubnet, Long ignoreSubnetId) {
for (DataCenterIpv4GuestSubnetVO existing : existingSubnets) { for (DataCenterIpv4GuestSubnetVO existing : existingSubnets) {
if ((ignoreSubnetId == null || existing.getId() != ignoreSubnetId) && NetUtils.isNetworksOverlap(existing.getSubnet(), newSubnet)) { if ((ignoreSubnetId == null || existing.getId() != ignoreSubnetId) && NetUtils.isNetworksOverlap(existing.getSubnet(), newSubnet)) {
throw new InvalidParameterValueException(String.format("Existing zone subnet %s has overlap with: %s", existing.getSubnet(), newSubnet)); throw new InvalidParameterValueException(String.format("Existing zone subnet %s has overlap with: %s", existing.getSubnet(), newSubnet));
@ -553,11 +574,6 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
response.setParentSubnet(parent.getSubnet()); response.setParentSubnet(parent.getSubnet());
zoneId = parent.getDataCenterId(); zoneId = parent.getDataCenterId();
} }
} else if (subnet.getNetworkId() != null) {
Network network = ApiDBUtils.findNetworkById(subnet.getNetworkId());
if (network != null) {
zoneId = network.getDataCenterId();
}
} }
if (zoneId != null) { if (zoneId != null) {
DataCenter zone = ApiDBUtils.findZoneById(zoneId); DataCenter zone = ApiDBUtils.findZoneById(zoneId);
@ -590,7 +606,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(vpcCidrSize, vpc.getDomainId(), vpc.getAccountId(), vpc.getZoneId()); return getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(vpcCidrSize, vpc.getDomainId(), vpc.getAccountId(), vpc.getZoneId());
} }
private Ipv4GuestSubnetNetworkMap getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(Integer cidrSize, Long ownerDomainId, Long ownerAccountId, Long zoneId) { protected Ipv4GuestSubnetNetworkMap getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(Integer cidrSize, Long ownerDomainId, Long ownerAccountId, Long zoneId) {
validateNetworkCidrSize(ownerAccountId, cidrSize); validateNetworkCidrSize(ownerAccountId, cidrSize);
List<DataCenterIpv4GuestSubnetVO> subnets = getZoneSubnetsForAccount(ownerDomainId, ownerAccountId, zoneId); List<DataCenterIpv4GuestSubnetVO> subnets = getZoneSubnetsForAccount(ownerDomainId, ownerAccountId, zoneId);
for (DataCenterIpv4GuestSubnetVO subnet : subnets) { for (DataCenterIpv4GuestSubnetVO subnet : subnets) {
@ -602,7 +618,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return null; return null;
} }
private Ipv4GuestSubnetNetworkMap getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(Integer cidrSize, DataCenterIpv4GuestSubnetVO subnet) { protected Ipv4GuestSubnetNetworkMap getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(Integer cidrSize, DataCenterIpv4GuestSubnetVO subnet) {
Ipv4GuestSubnetNetworkMap map = ipv4GuestSubnetNetworkMapDao.findFirstAvailable(subnet.getId(), cidrSize); Ipv4GuestSubnetNetworkMap map = ipv4GuestSubnetNetworkMapDao.findFirstAvailable(subnet.getId(), cidrSize);
if (map != null) { if (map != null) {
return map; return map;
@ -615,7 +631,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return null; return null;
} }
private void getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(String networkCidr, Long ownerDomainId, Long ownerAccountId, Long zoneId) { protected void getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(String networkCidr, Long ownerDomainId, Long ownerAccountId, Long zoneId) {
Ipv4GuestSubnetNetworkMapVO subnetMap = ipv4GuestSubnetNetworkMapDao.findBySubnet(networkCidr); Ipv4GuestSubnetNetworkMapVO subnetMap = ipv4GuestSubnetNetworkMapDao.findBySubnet(networkCidr);
if (subnetMap != null) { if (subnetMap != null) {
// check if the subnet is in use // check if the subnet is in use
@ -650,7 +666,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
} }
} }
private DataCenterIpv4GuestSubnet getParentOfNetworkCidr(Long zoneId, String networkCidr) { protected DataCenterIpv4GuestSubnet getParentOfNetworkCidr(Long zoneId, String networkCidr) {
List<DataCenterIpv4GuestSubnetVO> existingSubnets = dataCenterIpv4GuestSubnetDao.listByDataCenterId(zoneId); List<DataCenterIpv4GuestSubnetVO> existingSubnets = dataCenterIpv4GuestSubnetDao.listByDataCenterId(zoneId);
for (DataCenterIpv4GuestSubnetVO existing : existingSubnets) { for (DataCenterIpv4GuestSubnetVO existing : existingSubnets) {
if (NetUtils.isNetworkAWithinNetworkB(networkCidr, existing.getSubnet())) { if (NetUtils.isNetworkAWithinNetworkB(networkCidr, existing.getSubnet())) {
@ -689,14 +705,22 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
private List<DataCenterIpv4GuestSubnetVO> getZoneSubnetsForAccount(long domainId, long accountId, long zoneId) { private List<DataCenterIpv4GuestSubnetVO> getZoneSubnetsForAccount(long domainId, long accountId, long zoneId) {
// Get dedicated guest subnets for the account // Get dedicated guest subnets for the account
List<DataCenterIpv4GuestSubnetVO> subnets = dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndAccountId(zoneId, accountId); List<DataCenterIpv4GuestSubnetVO> subnets = new ArrayList<>();
subnets.addAll(dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndAccountId(zoneId, accountId));
subnets.addAll(dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndDomainId(zoneId, domainId)); subnets.addAll(dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndDomainId(zoneId, domainId));
// Get non-dedicated zone guest subnets for the account // Get non-dedicated zone guest subnets for the account
subnets.addAll(dataCenterIpv4GuestSubnetDao.listNonDedicatedByDataCenterId(zoneId)); subnets.addAll(dataCenterIpv4GuestSubnetDao.listNonDedicatedByDataCenterId(zoneId));
return subnets; return subnets;
} }
private Ipv4GuestSubnetNetworkMap createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, Integer networkCidrSize) { protected Ipv4GuestSubnetNetworkMap createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, Integer networkCidrSize) {
String networkCidr = createIpv4SubnetStringFromParentSubnet(parent, networkCidrSize);
// create DB record
Ipv4GuestSubnetNetworkMapVO subnetMap = new Ipv4GuestSubnetNetworkMapVO(parent.getId(), NetUtils.transformCidr(networkCidr), null, State.Free);
return ipv4GuestSubnetNetworkMapDao.persist(subnetMap);
}
protected String createIpv4SubnetStringFromParentSubnet(DataCenterIpv4GuestSubnet parent, Integer networkCidrSize) {
DataCenterIpv4GuestSubnetVO subnetVO = dataCenterIpv4GuestSubnetDao.findById(parent.getId()); DataCenterIpv4GuestSubnetVO subnetVO = dataCenterIpv4GuestSubnetDao.findById(parent.getId());
if (subnetVO == null) { if (subnetVO == null) {
throw new InvalidParameterValueException(String.format("Invalid subnet ID: %s", parent.getId())); throw new InvalidParameterValueException(String.format("Invalid subnet ID: %s", parent.getId()));
@ -733,9 +757,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
if (networkCidr == null) { if (networkCidr == null) {
throw new CloudRuntimeException("Failed to automatically allocate a subnet with specified cidrsize"); throw new CloudRuntimeException("Failed to automatically allocate a subnet with specified cidrsize");
} }
// create DB record return networkCidr;
Ipv4GuestSubnetNetworkMapVO subnetMap = new Ipv4GuestSubnetNetworkMapVO(parent.getId(), NetUtils.transformCidr(networkCidr), null, State.Free);
return ipv4GuestSubnetNetworkMapDao.persist(subnetMap);
} }
private String getFreeNetworkCidr(List<Pair<Long, Integer>> subnetsInFreeIpRanges, int networkCidrSize) { private String getFreeNetworkCidr(List<Pair<Long, Integer>> subnetsInFreeIpRanges, int networkCidrSize) {
@ -752,7 +774,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return null; return null;
} }
private Ipv4GuestSubnetNetworkMap createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, String networkCidr) { protected Ipv4GuestSubnetNetworkMap createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, String networkCidr) {
// Validate the network cidr // Validate the network cidr
if (!NetUtils.isNetworkAWithinNetworkB(networkCidr, parent.getSubnet())) { if (!NetUtils.isNetworkAWithinNetworkB(networkCidr, parent.getSubnet())) {
throw new InvalidParameterValueException(String.format("networkCidr %s is not within parent cidr: %s", networkCidr, parent.getSubnet())); throw new InvalidParameterValueException(String.format("networkCidr %s is not within parent cidr: %s", networkCidr, parent.getSubnet()));
@ -941,9 +963,11 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
} }
if (!FirewallRule.Purpose.Firewall.equals(rule.getPurpose())) { if (!FirewallRule.Purpose.Firewall.equals(rule.getPurpose())) {
logger.error(String.format("Cannot apply routing firewall rule with ID: %d as purpose %s is not %s", id, rule.getPurpose(), FirewallRule.Purpose.Firewall)); logger.error(String.format("Cannot apply routing firewall rule with ID: %d as purpose %s is not %s", id, rule.getPurpose(), FirewallRule.Purpose.Firewall));
return false;
} }
logger.debug(String.format("Applying routing firewall rules for rule with ID: %s", rule.getUuid())); logger.debug(String.format("Applying routing firewall rules for rule with ID: %s", rule.getUuid()));
List<FirewallRuleVO> rules = firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), FirewallRule.TrafficType.Egress); List<FirewallRuleVO> rules = new ArrayList<>();
rules.addAll(firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), FirewallRule.TrafficType.Egress));
rules.addAll(firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), FirewallRule.TrafficType.Ingress)); rules.addAll(firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), FirewallRule.TrafficType.Ingress));
return firewallManager.applyFirewallRules(rules, false, CallContext.current().getCallingAccount()); return firewallManager.applyFirewallRules(rules, false, CallContext.current().getCallingAccount());
} }
@ -1014,6 +1038,8 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
String password = createBgpPeerCmd.getPassword(); String password = createBgpPeerCmd.getPassword();
Map<String, String> detailsStr = createBgpPeerCmd.getDetails(); Map<String, String> detailsStr = createBgpPeerCmd.getDetails();
checkIfRoutedNetworkVpcEnabled(zoneId);
if (ObjectUtils.allNull(ip4Address, ip6Address)) { if (ObjectUtils.allNull(ip4Address, ip6Address)) {
throw new InvalidParameterValueException("At least one of IPv4 and IPv6 address must be specified."); throw new InvalidParameterValueException("At least one of IPv4 and IPv6 address must be specified.");
} }
@ -1398,7 +1424,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return changeBgpPeersForNetworkInternal(network, null); return changeBgpPeersForNetworkInternal(network, null);
} }
private Network changeBgpPeersForNetworkInternal(Network network, List<Long> bgpPeerIds) { protected Network changeBgpPeersForNetworkInternal(Network network, List<Long> bgpPeerIds) {
final List<Long> bgpPeerIdsToBeAdded; final List<Long> bgpPeerIdsToBeAdded;
if (CollectionUtils.isNotEmpty(bgpPeerIds)) { if (CollectionUtils.isNotEmpty(bgpPeerIds)) {
bgpPeerIdsToBeAdded = new ArrayList<>(bgpPeerIds); bgpPeerIdsToBeAdded = new ArrayList<>(bgpPeerIds);
@ -1529,7 +1555,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return bgpPeerDao.listAvailableBgpPeerIdsForAccount(zoneId, owner.getDomainId(), owner.getId(), UseSystemBgpPeers.valueIn(owner.getId())); return bgpPeerDao.listAvailableBgpPeerIdsForAccount(zoneId, owner.getDomainId(), owner.getId(), UseSystemBgpPeers.valueIn(owner.getId()));
} }
private Vpc changeBgpPeersForVpcInternal(Vpc vpc, List<Long> bgpPeerIds) { protected Vpc changeBgpPeersForVpcInternal(Vpc vpc, List<Long> bgpPeerIds) {
final List<Long> bgpPeerIdsToBeAdded; final List<Long> bgpPeerIdsToBeAdded;
if (CollectionUtils.isNotEmpty(bgpPeerIds)) { if (CollectionUtils.isNotEmpty(bgpPeerIds)) {
bgpPeerIdsToBeAdded = new ArrayList<>(bgpPeerIds); bgpPeerIdsToBeAdded = new ArrayList<>(bgpPeerIds);
@ -1618,4 +1644,15 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
public void removeBgpPeersByDomainId(long domainId) { public void removeBgpPeersByDomainId(long domainId) {
bgpPeerDao.removeByDomainId(domainId); bgpPeerDao.removeByDomainId(domainId);
} }
@Override
public Boolean isRoutedNetworkVpcEnabled(long zoneId) {
return RoutedNetworkVpcEnabled.valueIn(zoneId);
}
private void checkIfRoutedNetworkVpcEnabled(long zoneId) {
if (!isRoutedNetworkVpcEnabled(zoneId)) {
throw new InvalidParameterValueException("Routed networks and VPCs are not enabled for the zone.");
}
}
} }

View File

@ -17,6 +17,8 @@
package com.cloud.api; package com.cloud.api;
import com.cloud.domain.Domain; import com.cloud.domain.Domain;
import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.user.UserAccount; import com.cloud.user.UserAccount;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.ConfigKey;
@ -147,4 +149,31 @@ public class ApiServerTest {
Mockito.when(domain.getState()).thenReturn(Domain.State.Inactive); Mockito.when(domain.getState()).thenReturn(Domain.State.Inactive);
apiServer.forgotPassword(userAccount, domain); apiServer.forgotPassword(userAccount, domain);
} }
@Test
public void testVerifyApiKeyAccessAllowed() {
Long domainId = 1L;
User user = Mockito.mock(User.class);
Account account = Mockito.mock(Account.class);
Mockito.when(user.getApiKeyAccess()).thenReturn(true);
Assert.assertEquals(true, apiServer.verifyApiKeyAccessAllowed(user, account));
Mockito.verify(account, Mockito.never()).getApiKeyAccess();
Mockito.when(user.getApiKeyAccess()).thenReturn(false);
Assert.assertEquals(false, apiServer.verifyApiKeyAccessAllowed(user, account));
Mockito.verify(account, Mockito.never()).getApiKeyAccess();
Mockito.when(user.getApiKeyAccess()).thenReturn(null);
Mockito.when(account.getApiKeyAccess()).thenReturn(true);
Assert.assertEquals(true, apiServer.verifyApiKeyAccessAllowed(user, account));
Mockito.when(user.getApiKeyAccess()).thenReturn(null);
Mockito.when(account.getApiKeyAccess()).thenReturn(false);
Assert.assertEquals(false, apiServer.verifyApiKeyAccessAllowed(user, account));
Mockito.when(user.getApiKeyAccess()).thenReturn(null);
Mockito.when(account.getApiKeyAccess()).thenReturn(null);
Assert.assertEquals(true, apiServer.verifyApiKeyAccessAllowed(user, account));
}
} }

View File

@ -17,13 +17,18 @@
package com.cloud.api.query; package com.cloud.api.query;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.dao.TemplateJoinDao; import com.cloud.api.query.dao.TemplateJoinDao;
import com.cloud.api.query.dao.UserAccountJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.vo.EventJoinVO; import com.cloud.api.query.vo.EventJoinVO;
import com.cloud.api.query.vo.TemplateJoinVO; import com.cloud.api.query.vo.TemplateJoinVO;
import com.cloud.api.query.vo.UserAccountJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterDao;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.EventVO; import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao; import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.EventJoinDao; import com.cloud.event.dao.EventJoinDao;
@ -45,6 +50,7 @@ import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO; import com.cloud.user.AccountVO;
import com.cloud.user.User; import com.cloud.user.User;
import com.cloud.user.UserVO; import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import com.cloud.utils.db.EntityManager; import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.Filter; import com.cloud.utils.db.Filter;
@ -56,8 +62,11 @@ import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.command.admin.storage.ListObjectStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListObjectStoragePoolsCmd;
import org.apache.cloudstack.api.command.admin.user.ListUsersCmd;
import org.apache.cloudstack.api.command.admin.vm.ListAffectedVmsForStorageScopeChangeCmd; import org.apache.cloudstack.api.command.admin.vm.ListAffectedVmsForStorageScopeChangeCmd;
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
import org.apache.cloudstack.api.command.user.bucket.ListBucketsCmd; import org.apache.cloudstack.api.command.user.bucket.ListBucketsCmd;
import org.apache.cloudstack.api.command.user.event.ListEventsCmd; import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
import org.apache.cloudstack.api.command.user.resource.ListDetailOptionsCmd; import org.apache.cloudstack.api.command.user.resource.ListDetailOptionsCmd;
@ -65,6 +74,7 @@ import org.apache.cloudstack.api.response.DetailOptionsResponse;
import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.EventResponse;
import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ObjectStoreResponse; import org.apache.cloudstack.api.response.ObjectStoreResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.VirtualMachineResponse; import org.apache.cloudstack.api.response.VirtualMachineResponse;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao; import org.apache.cloudstack.storage.datastore.db.ObjectStoreDao;
@ -150,6 +160,15 @@ public class QueryManagerImplTest {
@Mock @Mock
UserVmJoinDao userVmJoinDao; UserVmJoinDao userVmJoinDao;
@Mock
UserAccountJoinDao userAccountJoinDao;
@Mock
DomainDao domainDao;
@Mock
AccountDao accountDao;
private AccountVO account; private AccountVO account;
private UserVO user; private UserVO user;
@ -477,4 +496,79 @@ public class QueryManagerImplTest {
Assert.assertEquals(response.getResponses().get(0).getId(), instanceUuid); Assert.assertEquals(response.getResponses().get(0).getId(), instanceUuid);
Assert.assertEquals(response.getResponses().get(0).getName(), vmName); Assert.assertEquals(response.getResponses().get(0).getName(), vmName);
} }
@Test
public void testSearchForUsers() {
ListUsersCmd cmd = Mockito.mock(ListUsersCmd.class);
String username = "Admin";
String accountName = "Admin";
Account.Type accountType = Account.Type.ADMIN;
Long domainId = 1L;
String apiKeyAccess = "Disabled";
Mockito.when(cmd.getUsername()).thenReturn(username);
Mockito.when(cmd.getAccountName()).thenReturn(accountName);
Mockito.when(cmd.getAccountType()).thenReturn(accountType);
Mockito.when(cmd.getDomainId()).thenReturn(domainId);
Mockito.when(cmd.getApiKeyAccess()).thenReturn(apiKeyAccess);
UserAccountJoinVO user = new UserAccountJoinVO();
DomainVO domain = Mockito.mock(DomainVO.class);
SearchBuilder<UserAccountJoinVO> sb = Mockito.mock(SearchBuilder.class);
SearchCriteria<UserAccountJoinVO> sc = Mockito.mock(SearchCriteria.class);
List<UserAccountJoinVO> users = new ArrayList<>();
Pair<List<UserAccountJoinVO>, Integer> result = new Pair<>(users, 0);
UserResponse response = Mockito.mock(UserResponse.class);
Mockito.when(userAccountJoinDao.createSearchBuilder()).thenReturn(sb);
Mockito.when(sb.entity()).thenReturn(user);
Mockito.when(sb.create()).thenReturn(sc);
Mockito.when(userAccountJoinDao.searchAndCount(any(SearchCriteria.class), any(Filter.class))).thenReturn(result);
queryManager.searchForUsers(ResponseObject.ResponseView.Restricted, cmd);
Mockito.verify(sc).setParameters("username", username);
Mockito.verify(sc).setParameters("accountName", accountName);
Mockito.verify(sc).setParameters("type", accountType);
Mockito.verify(sc).setParameters("domainId", domainId);
Mockito.verify(sc).setParameters("apiKeyAccess", false);
Mockito.verify(userAccountJoinDao, Mockito.times(1)).searchAndCount(
any(SearchCriteria.class), any(Filter.class));
}
@Test
public void testSearchForAccounts() {
ListAccountsCmd cmd = Mockito.mock(ListAccountsCmd.class);
Long domainId = 1L;
String accountName = "Admin";
Account.Type accountType = Account.Type.ADMIN;
String apiKeyAccess = "Enabled";
Mockito.when(cmd.getId()).thenReturn(null);
Mockito.when(cmd.getDomainId()).thenReturn(domainId);
Mockito.when(cmd.getSearchName()).thenReturn(accountName);
Mockito.when(cmd.getAccountType()).thenReturn(accountType);
Mockito.when(cmd.getApiKeyAccess()).thenReturn(apiKeyAccess);
DomainVO domain = Mockito.mock(DomainVO.class);
SearchBuilder<AccountVO> sb = Mockito.mock(SearchBuilder.class);
SearchCriteria<AccountVO> sc = Mockito.mock(SearchCriteria.class);
Pair<List<AccountVO>, Integer> uniqueAccountPair = new Pair<>(new ArrayList<>(), 0);
Mockito.when(domainDao.findById(domainId)).thenReturn(domain);
Mockito.doNothing().when(accountManager).checkAccess(account, domain);
Mockito.when(accountDao.createSearchBuilder()).thenReturn(sb);
Mockito.when(sb.entity()).thenReturn(account);
Mockito.when(sb.create()).thenReturn(sc);
Mockito.when(accountDao.searchAndCount(any(SearchCriteria.class), any(Filter.class))).thenReturn(uniqueAccountPair);
try (MockedStatic<ApiDBUtils> apiDBUtilsMocked = Mockito.mockStatic(ApiDBUtils.class)) {
queryManager.searchForAccounts(cmd);
}
Mockito.verify(sc).setParameters("domainId", domainId);
Mockito.verify(sc).setParameters("accountName", accountName);
Mockito.verify(sc).setParameters("type", accountType);
Mockito.verify(sc).setParameters("apiKeyAccess", true);
Mockito.verify(accountDao, Mockito.times(1)).searchAndCount(
any(SearchCriteria.class), any(Filter.class));
}
} }

View File

@ -18,14 +18,39 @@
package com.cloud.bgp; package com.cloud.bgp;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.element.VirtualRouterElement;
import com.cloud.network.element.VpcVirtualRouterElement;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.dao.VpcServiceMapDao;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.BgpPeerDao;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy; import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class BGPServiceImplTest { public class BGPServiceImplTest {
@ -33,6 +58,24 @@ public class BGPServiceImplTest {
@InjectMocks @InjectMocks
BGPServiceImpl bGPServiceImplSpy = new BGPServiceImpl(); BGPServiceImpl bGPServiceImplSpy = new BGPServiceImpl();
@Mock
RoutedIpv4Manager routedIpv4Manager;
@Mock
NetworkServiceMapDao ntwkSrvcDao;
@Mock
NetworkModel networkModel;
@Mock
BgpPeerDao bgpPeerDao;
@Mock
AccountDao accountDao;
@Mock
VpcServiceMapDao vpcServiceMapDao;
@Test @Test
public void testASNumbersOverlap() { public void testASNumbersOverlap() {
Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(1,2,3,4), false); Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(1,2,3,4), false);
@ -42,4 +85,92 @@ public class BGPServiceImplTest {
Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(1,4,2,3), true); Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(1,4,2,3), true);
Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(3,4,1,2), false); Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(3,4,1,2), false);
} }
@Test
public void testApplyBgpPeersForIsolatedNetwork() throws ResourceUnavailableException {
Long networkId = 11L;
Network network = Mockito.mock(Network.class);
when(network.getId()).thenReturn(networkId);
when(network.getVpcId()).thenReturn(null);
when(routedIpv4Manager.isDynamicRoutedNetwork(network)).thenReturn(true);
when(ntwkSrvcDao.getProviderForServiceInNetwork(networkId, Network.Service.Gateway)).thenReturn("VirtualRouter");
VirtualRouterElement virtualRouterElement = Mockito.mock(VirtualRouterElement.class);
when(networkModel.getElementImplementingProvider("VirtualRouter")).thenReturn(virtualRouterElement);
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
List<BgpPeerVO> bgpPeers = Arrays.asList(bgpPeer1);
when(bgpPeerDao.listNonRevokeByNetworkId(networkId)).thenReturn(bgpPeers);
doReturn(true).when(virtualRouterElement).applyBgpPeers(null, network, bgpPeers);
bGPServiceImplSpy.applyBgpPeers(network, true);
verify(virtualRouterElement).applyBgpPeers(null, network, bgpPeers);
}
@Test
public void testApplyBgpPeersForVpcTier() throws ResourceUnavailableException {
Long networkId = 11L;
Long accountId = 12L;
Long vpcId = 13L;
Long zoneId = 1L;
Network network = Mockito.mock(Network.class);
when(network.getId()).thenReturn(networkId);
when(network.getVpcId()).thenReturn(vpcId);
when(network.getAccountId()).thenReturn(accountId);
when(network.getDataCenterId()).thenReturn(zoneId);
when(routedIpv4Manager.isDynamicRoutedNetwork(network)).thenReturn(true);
when(ntwkSrvcDao.getProviderForServiceInNetwork(networkId, Network.Service.Gateway)).thenReturn("VirtualRouter");
VirtualRouterElement virtualRouterElement = Mockito.mock(VirtualRouterElement.class);
when(networkModel.getElementImplementingProvider("VirtualRouter")).thenReturn(virtualRouterElement);
when(bgpPeerDao.listNonRevokeByVpcId(vpcId)).thenReturn(new ArrayList<>());
AccountVO owner = Mockito.mock(AccountVO.class);
when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(owner);
Long bgpPeerId1 = 14L;
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
when(bgpPeerDao.findById(bgpPeerId1)).thenReturn(bgpPeer1);
when(routedIpv4Manager.getBgpPeerIdsForAccount(owner, zoneId)).thenReturn(Arrays.asList(bgpPeerId1));
doReturn(true).when(virtualRouterElement).applyBgpPeers(eq(null), eq(network), any());
bGPServiceImplSpy.applyBgpPeers(network, true);
verify(virtualRouterElement).applyBgpPeers(eq(null), eq(network), any());
}
@Test
public void testApplyBgpPeersForVpcWithBgpPeers() throws ResourceUnavailableException {
Long accountId = 12L;
Long vpcId = 13L;
Long zoneId = 1L;
Vpc vpc = Mockito.mock(Vpc.class);
when(vpc.getId()).thenReturn(vpcId);
when(vpc.getAccountId()).thenReturn(accountId);
when(vpc.getZoneId()).thenReturn(zoneId);
when(routedIpv4Manager.isDynamicRoutedVpc(vpc)).thenReturn(true);
when(vpcServiceMapDao.getProviderForServiceInVpc(vpcId, Network.Service.Gateway)).thenReturn("VPCVirtualRouter");
VpcVirtualRouterElement vpcVirtualRouterElement = Mockito.mock(VpcVirtualRouterElement.class);
when(networkModel.getElementImplementingProvider("VPCVirtualRouter")).thenReturn(vpcVirtualRouterElement);
when(bgpPeerDao.listNonRevokeByVpcId(vpcId)).thenReturn(new ArrayList<>());
AccountVO owner = Mockito.mock(AccountVO.class);
when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(owner);
Long bgpPeerId1 = 14L;
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
when(bgpPeerDao.findById(bgpPeerId1)).thenReturn(bgpPeer1);
when(routedIpv4Manager.getBgpPeerIdsForAccount(owner, zoneId)).thenReturn(Arrays.asList(bgpPeerId1));
doReturn(true).when(vpcVirtualRouterElement).applyBgpPeers(eq(vpc), eq(null), any());
bGPServiceImplSpy.applyBgpPeers(vpc, true);
verify(vpcVirtualRouterElement).applyBgpPeers(eq(vpc), eq(null), any());
}
} }

View File

@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -29,6 +30,7 @@ import static org.mockito.Mockito.doReturn;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@ -46,6 +48,7 @@ import com.cloud.user.dao.AccountDao;
import com.cloud.utils.net.Ip; import com.cloud.utils.net.Ip;
import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientAddressCapacityException;
import org.apache.cloudstack.alert.AlertService; import org.apache.cloudstack.alert.AlertService;
import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin;
import org.apache.cloudstack.api.command.user.address.UpdateQuarantinedIpCmd; import org.apache.cloudstack.api.command.user.address.UpdateQuarantinedIpCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd; import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd;
@ -753,13 +756,14 @@ public class NetworkServiceImplTest {
} }
@Test @Test
public void testCreateIpv4RoutedNetwork() throws InsufficientCapacityException, ResourceAllocationException { public void testCreateIpv4RoutedNetwork() {
registerCallContext(); registerCallContext();
CreateNetworkCmd cmd = Mockito.mock(CreateNetworkCmd.class); CreateNetworkCmd cmd = Mockito.mock(CreateNetworkCmd.class);
Mockito.when(cmd.getCidrSize()).thenReturn(24); Mockito.when(cmd.getCidrSize()).thenReturn(24);
prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, false, true); prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, false, true);
when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED); when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static); when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
when(routedIpv4Manager.isRoutedNetworkVpcEnabled(nullable(Long.class))).thenReturn(true);
when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true); when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true);
doNothing().when(routedIpv4Manager).assignIpv4SubnetToNetwork(nullable(Network.class)); doNothing().when(routedIpv4Manager).assignIpv4SubnetToNetwork(nullable(Network.class));
@ -812,6 +816,91 @@ public class NetworkServiceImplTest {
null, null, null, null, null, null, null, new Pair<>(0, privateMtu), null); null, null, null, null, null, null, null, new Pair<>(0, privateMtu), null);
} }
public void testCreateIpv4RoutedNetworkWithBgpPeersFailure1() {
registerCallContext();
CreateNetworkCmdByAdmin cmd = Mockito.mock(CreateNetworkCmdByAdmin.class);
Mockito.when(cmd.getCidrSize()).thenReturn(24);
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
Mockito.when(cmd.getBgpPeerIds()).thenReturn(bgpPeerIds);
prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, true, true);
when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
when(routedIpv4Manager.isRoutedNetworkVpcEnabled(nullable(Long.class))).thenReturn(true);
when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true);
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
when(cmd.getZoneId()).thenReturn(zoneId);
when(dcDao.findById(zoneId)).thenReturn(zone);
when(zone.getId()).thenReturn(zoneId);
try {
service.createGuestNetwork(cmd);
} catch (InsufficientCapacityException | ResourceAllocationException e) {
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
} catch (InvalidParameterValueException ex) {
Assert.assertEquals("The BGP peers of VPC tiers will inherit from the VPC, do not add separately.", ex.getMessage());
}
}
@Test
public void testCreateIpv4RoutedNetworkWithBgpPeersFailure2() {
registerCallContext();
CreateNetworkCmdByAdmin cmd = Mockito.mock(CreateNetworkCmdByAdmin.class);
Mockito.when(cmd.getCidrSize()).thenReturn(24);
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
Mockito.when(cmd.getBgpPeerIds()).thenReturn(bgpPeerIds);
prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, false, true);
when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
when(routedIpv4Manager.isRoutedNetworkVpcEnabled(nullable(Long.class))).thenReturn(true);
when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true);
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
when(cmd.getZoneId()).thenReturn(zoneId);
when(dcDao.findById(zoneId)).thenReturn(zone);
when(zone.getId()).thenReturn(zoneId);
try {
service.createGuestNetwork(cmd);
} catch (InsufficientCapacityException | ResourceAllocationException e) {
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
} catch (InvalidParameterValueException ex) {
Assert.assertEquals("The network offering does not support Dynamic routing", ex.getMessage());
}
}
@Test
public void testCreateIpv4RoutedNetworkWithBgpPeersFailure3() {
registerCallContext();
CreateNetworkCmdByAdmin cmd = Mockito.mock(CreateNetworkCmdByAdmin.class);
Mockito.when(cmd.getCidrSize()).thenReturn(24);
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
Mockito.when(cmd.getBgpPeerIds()).thenReturn(bgpPeerIds);
prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, false, true);
when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
when(routedIpv4Manager.isRoutedNetworkVpcEnabled(nullable(Long.class))).thenReturn(true);
when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true);
when(routedIpv4Manager.isDynamicRoutedNetwork(networkOfferingVO)).thenReturn(true);
doThrow(new InvalidParameterValueException("validation error")).when(routedIpv4Manager).validateBgpPeers(nullable(Account.class), nullable(Long.class), any(List.class));
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
when(cmd.getZoneId()).thenReturn(zoneId);
when(dcDao.findById(zoneId)).thenReturn(zone);
when(zone.getId()).thenReturn(zoneId);
try {
service.createGuestNetwork(cmd);
} catch (InsufficientCapacityException | ResourceAllocationException e) {
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
} catch (InvalidParameterValueException ex) {
Assert.assertEquals("validation error", ex.getMessage());
}
}
@Test @Test
public void testCheckAndUpdateNetworkResetSuccess() { public void testCheckAndUpdateNetworkResetSuccess() {
NetworkVO networkVO = new NetworkVO(); NetworkVO networkVO = new NetworkVO();

View File

@ -65,6 +65,7 @@ import com.cloud.network.router.VirtualRouter;
import com.cloud.network.router.VirtualRouter.RedundantState; import com.cloud.network.router.VirtualRouter.RedundantState;
import com.cloud.network.router.VpcVirtualNetworkApplianceManagerImpl; import com.cloud.network.router.VpcVirtualNetworkApplianceManagerImpl;
import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.network.vpc.VpcVO;
import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingDao;
@ -98,7 +99,11 @@ import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinitionBuilder; import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinitionBuilder;
import org.apache.cloudstack.network.topology.NetworkTopology;
import org.apache.cloudstack.network.topology.NetworkTopologyContext;
import org.junit.Assert;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -111,6 +116,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer; import org.mockito.stubbing.Answer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -122,6 +128,7 @@ import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
@ -178,6 +185,7 @@ public class VirtualRouterElementTest {
@Mock private ResourceManager _resourceMgr; @Mock private ResourceManager _resourceMgr;
@Mock private UserVmManager _userVmMgr; @Mock private UserVmManager _userVmMgr;
@Mock private VirtualMachineManager _itMgr; @Mock private VirtualMachineManager _itMgr;
@Mock private NetworkTopologyContext networkTopologyContext;
@InjectMocks @InjectMocks
private RouterDeploymentDefinitionBuilder routerDeploymentDefinitionBuilder; private RouterDeploymentDefinitionBuilder routerDeploymentDefinitionBuilder;
@ -517,4 +525,52 @@ public class VirtualRouterElementTest {
assertTrue(counterNames.contains(AutoScaleCounterType.Memory.getName())); assertTrue(counterNames.contains(AutoScaleCounterType.Memory.getName()));
assertTrue(counterNames.contains(AutoScaleCounterType.VirtualRouter.getName())); assertTrue(counterNames.contains(AutoScaleCounterType.VirtualRouter.getName()));
} }
@Test
public void testApplyBgpPeersForVpc() throws ResourceUnavailableException {
List<BgpPeerVO> bgpPeers = Mockito.mock(List.class);
VpcVO vpc = Mockito.mock(VpcVO.class);
DomainRouterVO router = Mockito.mock(DomainRouterVO.class);
when(router.getState()).thenReturn(VirtualMachine.State.Running);
long zoneId = 10L;
long vpcId = 11L;
when(vpc.getId()).thenReturn(vpcId);
when(vpc.getZoneId()).thenReturn(zoneId);
when(_routerDao.listByVpcId(vpcId)).thenReturn(Arrays.asList(router));
DataCenterVO dc = Mockito.mock(DataCenterVO.class);
when(_dcDao.findById(zoneId)).thenReturn(dc);
NetworkTopology networkTopology = Mockito.mock(NetworkTopology.class);
when(networkTopologyContext.retrieveNetworkTopology(dc)).thenReturn(networkTopology);
doReturn(true).when(networkTopology).applyBgpPeers(any(), any(), any());
boolean result = virtualRouterElement.applyBgpPeers(vpc, null, bgpPeers);
Assert.assertTrue(result);
verify(networkTopology).applyBgpPeers(any(), any(), any());
}
@Test
public void testApplyBgpPeersForNetwork() throws ResourceUnavailableException {
List<BgpPeerVO> bgpPeers = Mockito.mock(List.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
DomainRouterVO router = Mockito.mock(DomainRouterVO.class);
when(router.getState()).thenReturn(VirtualMachine.State.Running);
long zoneId = 10L;
long networkId = 11L;
when(network.getId()).thenReturn(networkId);
when(network.getDataCenterId()).thenReturn(zoneId);
when(_routerDao.listByNetworkAndRole(networkId, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(Arrays.asList(router));
DataCenterVO dc = Mockito.mock(DataCenterVO.class);
when(_dcDao.findById(zoneId)).thenReturn(dc);
NetworkTopology networkTopology = Mockito.mock(NetworkTopology.class);
when(networkTopologyContext.retrieveNetworkTopology(dc)).thenReturn(networkTopology);
doReturn(true).when(networkTopology).applyBgpPeers(any(), any(), any());
boolean result = virtualRouterElement.applyBgpPeers(null, network, bgpPeers);
Assert.assertTrue(result);
verify(networkTopology).applyBgpPeers(any(), any(), any());
}
} }

View File

@ -17,12 +17,15 @@
package com.cloud.network.router; package com.cloud.network.router;
import com.cloud.agent.api.Command; import com.cloud.agent.api.Command;
import com.cloud.agent.api.routing.SetBgpPeersCommand;
import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.manager.Commands; import com.cloud.agent.manager.Commands;
import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.ASNumberVO;
import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVO;
import com.cloud.dc.VlanVO; import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.ASNumberDao;
import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao; import com.cloud.dc.dao.VlanDao;
import com.cloud.network.NetworkModel; import com.cloud.network.NetworkModel;
@ -43,6 +46,8 @@ import com.cloud.utils.net.Ip;
import com.cloud.vm.NicVO; import com.cloud.vm.NicVO;
import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.NicDao;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.dao.BgpPeerDetailsDao;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -55,10 +60,13 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class CommandSetupHelperTest { public class CommandSetupHelperTest {
@ -88,6 +96,10 @@ public class CommandSetupHelperTest {
RouterControlHelper routerControlHelper; RouterControlHelper routerControlHelper;
@Mock @Mock
DataCenterDao dcDao; DataCenterDao dcDao;
@Mock
ASNumberDao asNumberDao;
@Mock
BgpPeerDetailsDao bgpPeerDetailsDao;
@Before @Before
public void setUp() { public void setUp() {
@ -173,24 +185,90 @@ public class CommandSetupHelperTest {
VpcVO vpc = new VpcVO(); VpcVO vpc = new VpcVO();
DataCenterVO dc = new DataCenterVO(1L, null, null, null, null, null, null, null, null, null, DataCenter.NetworkType.Advanced, null, null); DataCenterVO dc = new DataCenterVO(1L, null, null, null, null, null, null, null, null, null, DataCenter.NetworkType.Advanced, null, null);
Mockito.when(router.getId()).thenReturn(14L); when(router.getId()).thenReturn(14L);
Mockito.when(router.getDataCenterId()).thenReturn(4L); when(router.getDataCenterId()).thenReturn(4L);
Mockito.when(nicDao.listByVmId(ArgumentMatchers.anyLong())).thenReturn(List.of(nicVO)); when(nicDao.listByVmId(ArgumentMatchers.anyLong())).thenReturn(List.of(nicVO));
Mockito.when(networkDao.findById(ArgumentMatchers.anyLong())).thenReturn(networkVO); when(networkDao.findById(ArgumentMatchers.anyLong())).thenReturn(networkVO);
Mockito.when(ipAddressDao.listByAssociatedVpc(ArgumentMatchers.anyLong(), ArgumentMatchers.nullable(Boolean.class))).thenReturn(userIps); when(ipAddressDao.listByAssociatedVpc(ArgumentMatchers.anyLong(), ArgumentMatchers.nullable(Boolean.class))).thenReturn(userIps);
Mockito.when(vlanDao.findById(ArgumentMatchers.anyLong())).thenReturn(vlanVO); when(vlanDao.findById(ArgumentMatchers.anyLong())).thenReturn(vlanVO);
Mockito.when(networkModel.getNetworkRate(ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong())).thenReturn(1200); when(networkModel.getNetworkRate(ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong())).thenReturn(1200);
Mockito.when(networkModel.getNetwork(ArgumentMatchers.anyLong())).thenReturn(networkVO); when(networkModel.getNetwork(ArgumentMatchers.anyLong())).thenReturn(networkVO);
Mockito.when(networkOfferingDao.findById(ArgumentMatchers.anyLong())).thenReturn(networkOfferingVO); when(networkOfferingDao.findById(ArgumentMatchers.anyLong())).thenReturn(networkOfferingVO);
Mockito.when(configurationManager.getNetworkOfferingNetworkRate(ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong())).thenReturn(1200); when(configurationManager.getNetworkOfferingNetworkRate(ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong())).thenReturn(1200);
Mockito.when(networkModel.isSecurityGroupSupportedInNetwork(networkVO)).thenReturn(false); when(networkModel.isSecurityGroupSupportedInNetwork(networkVO)).thenReturn(false);
Mockito.when(networkOfferingDetailsDao.getNtwkOffDetails(ArgumentMatchers.anyLong())).thenReturn(details); when(networkOfferingDetailsDao.getNtwkOffDetails(ArgumentMatchers.anyLong())).thenReturn(details);
Mockito.when(networkDetailsDao.findDetail(ArgumentMatchers.anyLong(), ArgumentMatchers.anyString())).thenReturn(null); when(networkDetailsDao.findDetail(ArgumentMatchers.anyLong(), ArgumentMatchers.anyString())).thenReturn(null);
Mockito.when(vpcDao.findById(ArgumentMatchers.anyLong())).thenReturn(vpc); when(vpcDao.findById(ArgumentMatchers.anyLong())).thenReturn(vpc);
Mockito.when(routerControlHelper.getRouterControlIp(ArgumentMatchers.anyLong())).thenReturn("10.1.11.101"); when(routerControlHelper.getRouterControlIp(ArgumentMatchers.anyLong())).thenReturn("10.1.11.101");
Mockito.when(dcDao.findById(ArgumentMatchers.anyLong())).thenReturn(dc); when(dcDao.findById(ArgumentMatchers.anyLong())).thenReturn(dc);
commandSetupHelper.createVpcAssociatePublicIPCommands(router, pubIpList, commands, vlanMacAddress); commandSetupHelper.createVpcAssociatePublicIPCommands(router, pubIpList, commands, vlanMacAddress);
Assert.assertEquals(2, commands.size()); Assert.assertEquals(2, commands.size());
} }
@Test
public void testCreateBgpPeersCommandsForNetwork() {
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
BgpPeerVO bgpPeer2 = Mockito.mock(BgpPeerVO.class);
List<BgpPeerVO> bgpPeers = Arrays.asList(bgpPeer1, bgpPeer2);
Commands cmds = new Commands(Command.OnError.Stop);
VirtualRouter router = Mockito.mock(VirtualRouter.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
long zoneId = 10L;
long networkId = 11L;
when(router.getDataCenterId()).thenReturn(zoneId);
when(router.getVpcId()).thenReturn(null);
when(network.getId()).thenReturn(networkId);
ASNumberVO asNumberVO = Mockito.mock(ASNumberVO.class);
when(asNumberDao.findByZoneAndNetworkId(zoneId, networkId)).thenReturn(asNumberVO);
DataCenterVO dc = Mockito.mock(DataCenterVO.class);
when(dcDao.findById(zoneId)).thenReturn(dc);
when(dc.getNetworkType()).thenReturn(DataCenter.NetworkType.Advanced);
commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, network);
Assert.assertEquals(1, cmds.size());
Command cmd = cmds.toCommands()[0];
Assert.assertTrue(cmd instanceof SetBgpPeersCommand);
Assert.assertEquals(2, ((SetBgpPeersCommand) cmd).getBpgPeers().length);
}
@Test
public void testCreateBgpPeersCommandsForVpc() {
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
BgpPeerVO bgpPeer2 = Mockito.mock(BgpPeerVO.class);
List<BgpPeerVO> bgpPeers = Arrays.asList(bgpPeer1, bgpPeer2);
Commands cmds = new Commands(Command.OnError.Stop);
VirtualRouter router = Mockito.mock(VirtualRouter.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
long zoneId = 10L;
long vpcId = 11L;
when(router.getDataCenterId()).thenReturn(zoneId);
when(router.getVpcId()).thenReturn(vpcId);
ASNumberVO asNumberVO = Mockito.mock(ASNumberVO.class);
when(asNumberDao.findByZoneAndVpcId(zoneId, vpcId)).thenReturn(asNumberVO);
long networkOfferingId = 12L;
NetworkOfferingVO offering = Mockito.mock(NetworkOfferingVO.class);
when(networkOfferingDao.findByIdIncludingRemoved(networkOfferingId)).thenReturn(offering);
when(offering.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Dynamic);
NetworkVO network1 = Mockito.mock(NetworkVO.class);
when(network1.getNetworkOfferingId()).thenReturn(networkOfferingId);
NetworkVO network2 = Mockito.mock(NetworkVO.class);
when(network2.getNetworkOfferingId()).thenReturn(networkOfferingId);
when(networkDao.listByVpc(vpcId)).thenReturn(Arrays.asList(network1, network2));
DataCenterVO dc = Mockito.mock(DataCenterVO.class);
when(dcDao.findById(zoneId)).thenReturn(dc);
when(dc.getNetworkType()).thenReturn(DataCenter.NetworkType.Advanced);
commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, network);
Assert.assertEquals(1, cmds.size());
Command cmd = cmds.toCommands()[0];
Assert.assertTrue(cmd instanceof SetBgpPeersCommand);
Assert.assertEquals(4, ((SetBgpPeersCommand) cmd).getBpgPeers().length);
}
} }

View File

@ -19,7 +19,10 @@ package com.cloud.network.router;
import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager;
import com.cloud.agent.api.CheckS2SVpnConnectionsAnswer; import com.cloud.agent.api.CheckS2SVpnConnectionsAnswer;
import com.cloud.agent.api.CheckS2SVpnConnectionsCommand; import com.cloud.agent.api.CheckS2SVpnConnectionsCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager; import com.cloud.alert.AlertManager;
import com.cloud.bgp.BGPService;
import com.cloud.cluster.dao.ManagementServerHostDao; import com.cloud.cluster.dao.ManagementServerHostDao;
import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterDao;
@ -30,6 +33,8 @@ import com.cloud.host.HostVO;
import com.cloud.host.Status; import com.cloud.host.Status;
import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressDao;
@ -37,6 +42,7 @@ import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.MonitoringServiceDao; import com.cloud.network.dao.MonitoringServiceDao;
import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.OpRouterMonitorServiceDao; import com.cloud.network.dao.OpRouterMonitorServiceDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.RemoteAccessVpnDao;
@ -49,6 +55,8 @@ import com.cloud.network.dao.UserIpv6AddressDao;
import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.dao.VirtualRouterProviderDao;
import com.cloud.network.dao.VpnUserDao; import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpn.Site2SiteVpnManager; import com.cloud.network.vpn.Site2SiteVpnManager;
import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.service.dao.ServiceOfferingDao;
@ -69,12 +77,15 @@ import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.BgpPeer;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.utils.identity.ManagementServerNode; import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList; import java.util.ArrayList;
@ -233,6 +244,20 @@ public class VirtualNetworkApplianceManagerImplTest {
@InjectMocks @InjectMocks
private VirtualNetworkApplianceManagerImpl virtualNetworkApplianceManagerImpl; private VirtualNetworkApplianceManagerImpl virtualNetworkApplianceManagerImpl;
@Mock
private NetworkModel _networkModel;
@Mock
private RoutedIpv4Manager routedIpv4Manager;
@Mock
private CommandSetupHelper _commandSetupHelper;
@Mock
private VpcDao _vpcDao;
@Mock
private BGPService bgpService;
// @InjectMocks // @InjectMocks
// private VirtualNetworkApplianceManagerImpl virtualNetworkApplianceManagerImpl; // private VirtualNetworkApplianceManagerImpl virtualNetworkApplianceManagerImpl;
@ -328,4 +353,42 @@ public class VirtualNetworkApplianceManagerImplTest {
result = virtualNetworkApplianceManagerImpl.checkLogrotateTimerPattern(foo); result = virtualNetworkApplianceManagerImpl.checkLogrotateTimerPattern(foo);
Assert.assertTrue(result); Assert.assertTrue(result);
} }
@Test
public void testFinalizeNetworkRulesForNetwork() {
Long guestNetworkId = 10L;
Commands cmds = new Commands(Command.OnError.Stop);
DomainRouterVO router = Mockito.mock(DomainRouterVO.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
when(_networkDao.findById(guestNetworkId)).thenReturn(network);
when(network.getVpcId()).thenReturn(null);
when(routedIpv4Manager.isDynamicRoutedNetwork(network)).thenReturn(true);
List<? extends BgpPeer> bgpPeers = Mockito.mock(List.class);
doReturn(bgpPeers).when(bgpService).getBgpPeersForNetwork(network);
virtualNetworkApplianceManagerImpl.finalizeNetworkRulesForNetwork(cmds, router, Network.Provider.VirtualRouter, guestNetworkId);
Mockito.verify(_commandSetupHelper).createBgpPeersCommands(bgpPeers, router, cmds, network);
}
@Test
public void testFinalizeNetworkRulesForVpcNetwork() {
Long guestNetworkId = 10L;
Long vpcId = 11L;
Commands cmds = new Commands(Command.OnError.Stop);
DomainRouterVO router = Mockito.mock(DomainRouterVO.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
when(_networkDao.findById(guestNetworkId)).thenReturn(network);
when(network.getVpcId()).thenReturn(vpcId);
VpcVO vpc = Mockito.mock(VpcVO.class);
when(_vpcDao.findById(vpcId)).thenReturn(vpc);
when(routedIpv4Manager.isDynamicRoutedVpc(vpc)).thenReturn(true);
List<? extends BgpPeer> bgpPeers = Mockito.mock(List.class);
doReturn(bgpPeers).when(bgpService).getBgpPeersForVpc(vpc);
virtualNetworkApplianceManagerImpl.finalizeNetworkRulesForNetwork(cmds, router, Network.Provider.VirtualRouter, guestNetworkId);
Mockito.verify(_commandSetupHelper).createBgpPeersCommands(bgpPeers, router, cmds, network);
}
} }

View File

@ -73,6 +73,7 @@ import org.apache.cloudstack.api.command.user.vpc.UpdateVPCCmd;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.network.Ipv4GuestSubnetNetworkMap;
import org.apache.cloudstack.network.RoutedIpv4Manager; import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
@ -87,6 +88,7 @@ import org.springframework.test.util.ReflectionTestUtils;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -98,6 +100,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
@ -541,6 +544,30 @@ public class VpcManagerImplTest {
verify(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyString()); verify(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyString());
} }
@Test
public void testCreateRoutedVpcWithDynamicRouting() {
mockVpcDnsResources(true, false);
VpcVO vpc = Mockito.mock(VpcVO.class);
Mockito.when(vpcDao.persist(any(), anyMap())).thenReturn(vpc);
Mockito.when(vpc.getUuid()).thenReturn("uuid");
doReturn(true).when(routedIpv4Manager).isRoutedVpc(any());
doReturn(true).when(routedIpv4Manager).isVpcVirtualRouterGateway(vpcOfferingVO);
doReturn(true).when(routedIpv4Manager).isDynamicRoutedVpc(vpcOfferingVO);
Ipv4GuestSubnetNetworkMap ipv4GuestSubnetNetworkMap = Mockito.mock(Ipv4GuestSubnetNetworkMap.class);
doReturn(ipv4GuestSubnetNetworkMap).when(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyInt());
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
try {
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc);
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, null, vpcDomain,
ip4Dns[0], ip4Dns[1], null, null, true, 1500, 24, null, bgpPeerIds);
} catch (ResourceAllocationException e) {
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
}
verify(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyInt());
verify(routedIpv4Manager).validateBgpPeers(any(), any(), any());
}
@Test @Test
public void validateVpcPrivateGatewayAclIdTestNullAclVoThrowsInvalidParameterValueException() { public void validateVpcPrivateGatewayAclIdTestNullAclVoThrowsInvalidParameterValueException() {
Mockito.doReturn(null).when(networkACLDaoMock).findById(aclId); Mockito.doReturn(null).when(networkACLDaoMock).findById(aclId);

View File

@ -16,6 +16,7 @@
// under the License. // under the License.
package com.cloud.storage; package com.cloud.storage;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -42,6 +43,7 @@ import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigDepot;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao; import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand; import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand;
@ -756,4 +758,81 @@ public class StorageManagerImplTest {
String failureReason = storageManagerImpl.getStoragePoolMountFailureReason(error); String failureReason = storageManagerImpl.getStoragePoolMountFailureReason(error);
Assert.assertEquals(failureReason, "An incorrect mount option was specified"); Assert.assertEquals(failureReason, "An incorrect mount option was specified");
} }
private void overrideDefaultConfigValue(final ConfigKey configKey, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
Field f = ConfigKey.class.getDeclaredField(name);
f.setAccessible(true);
f.set(configKey, o);
}
private Long testCheckPoolforSpaceForResizeSetup(StoragePoolVO pool, Long allocatedSizeWithTemplate) {
Long poolId = 10L;
Long zoneId = 2L;
Long capacityBytes = (long) (allocatedSizeWithTemplate / Double.valueOf(CapacityManager.StorageAllocatedCapacityDisableThreshold.defaultValue())
/ Double.valueOf(CapacityManager.StorageOverprovisioningFactor.defaultValue()));
Long maxAllocatedSizeForResize = (long) (capacityBytes * Double.valueOf(CapacityManager.StorageOverprovisioningFactor.defaultValue())
* Double.valueOf(CapacityManager.StorageAllocatedCapacityDisableThresholdForVolumeSize.defaultValue()));
System.out.println("maxAllocatedSizeForResize = " + maxAllocatedSizeForResize);
System.out.println("allocatedSizeWithTemplate = " + allocatedSizeWithTemplate);
Mockito.when(pool.getId()).thenReturn(poolId);
Mockito.when(pool.getCapacityBytes()).thenReturn(capacityBytes);
Mockito.when(pool.getDataCenterId()).thenReturn(zoneId);
Mockito.when(storagePoolDao.findById(poolId)).thenReturn(pool);
Mockito.when(pool.getPoolType()).thenReturn(Storage.StoragePoolType.NetworkFilesystem);
return maxAllocatedSizeForResize - allocatedSizeWithTemplate;
}
@Test
public void testCheckPoolforSpaceForResize1() {
StoragePoolVO pool = Mockito.mock(StoragePoolVO.class);
Long allocatedSizeWithTemplate = 100L * 1024 * 1024 * 1024;
Long maxAskingSize = testCheckPoolforSpaceForResizeSetup(pool, allocatedSizeWithTemplate);
Long totalAskingSize = maxAskingSize / 2;
boolean result = storageManagerImpl.checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize, false);
Assert.assertFalse(result);
}
@Test
public void testCheckPoolforSpaceForResize2() {
StoragePoolVO pool = Mockito.mock(StoragePoolVO.class);
Long allocatedSizeWithTemplate = 100L * 1024 * 1024 * 1024;
Long maxAskingSize = testCheckPoolforSpaceForResizeSetup(pool, allocatedSizeWithTemplate);
Long totalAskingSize = maxAskingSize / 2;
boolean result = storageManagerImpl.checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize, true);
Assert.assertFalse(result);
}
@Test
public void testCheckPoolforSpaceForResize3() throws NoSuchFieldException, IllegalAccessException {
StoragePoolVO pool = Mockito.mock(StoragePoolVO.class);
Long allocatedSizeWithTemplate = 100L * 1024 * 1024 * 1024;
Long maxAskingSize = testCheckPoolforSpaceForResizeSetup(pool, allocatedSizeWithTemplate);
Long totalAskingSize = maxAskingSize + 1;
overrideDefaultConfigValue(StorageManagerImpl.AllowVolumeReSizeBeyondAllocation, "_defaultValue", "true");
boolean result = storageManagerImpl.checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize, true);
Assert.assertFalse(result);
}
@Test
public void testCheckPoolforSpaceForResize4() throws NoSuchFieldException, IllegalAccessException {
StoragePoolVO pool = Mockito.mock(StoragePoolVO.class);
Long allocatedSizeWithTemplate = 100L * 1024 * 1024 * 1024;
Long maxAskingSize = testCheckPoolforSpaceForResizeSetup(pool, allocatedSizeWithTemplate);
Long totalAskingSize = maxAskingSize / 2;
overrideDefaultConfigValue(StorageManagerImpl.AllowVolumeReSizeBeyondAllocation, "_defaultValue", "true");
boolean result = storageManagerImpl.checkPoolforSpace(pool, allocatedSizeWithTemplate, totalAskingSize, true);
Assert.assertTrue(result);
}
} }

View File

@ -19,10 +19,13 @@ package com.cloud.storage;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -38,14 +41,17 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import com.cloud.server.ManagementService;
import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.command.user.volume.CheckAndRepairVolumeCmd; import org.apache.cloudstack.api.command.user.volume.CheckAndRepairVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.cloudstack.backup.dao.BackupDao; import org.apache.cloudstack.backup.dao.BackupDao;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
@ -85,6 +91,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.api.query.dao.ServiceOfferingJoinDao; import com.cloud.api.query.dao.ServiceOfferingJoinDao;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource; import com.cloud.configuration.Resource;
import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVO;
@ -210,6 +217,8 @@ public class VolumeApiServiceImplTest {
private StoragePool storagePoolMock; private StoragePool storagePoolMock;
private long storagePoolMockId = 1; private long storagePoolMockId = 1;
@Mock @Mock
private DiskOfferingVO diskOfferingMock;
@Mock
private DiskOfferingVO newDiskOfferingMock; private DiskOfferingVO newDiskOfferingMock;
@Mock @Mock
@ -238,10 +247,20 @@ public class VolumeApiServiceImplTest {
@Mock @Mock
private StorageManager storageMgr; private StorageManager storageMgr;
@Mock
private ConfigurationManager _configMgr;
@Mock
private VolumeOrchestrationService _volumeMgr;
@Mock
private ManagementService managementService;
private long accountMockId = 456l; private long accountMockId = 456l;
private long volumeMockId = 12313l; private long volumeMockId = 12313l;
private long vmInstanceMockId = 1123l; private long vmInstanceMockId = 1123l;
private long volumeSizeMock = 456789921939l; private long volumeSizeMock = 456789921939l;
private long newVolumeSizeMock = 456789930000l;
private static long imageStoreId = 10L; private static long imageStoreId = 10L;
private String projectMockUuid = "projectUuid"; private String projectMockUuid = "projectUuid";
@ -250,6 +269,7 @@ public class VolumeApiServiceImplTest {
private long projectMockAccountId = 132329390L; private long projectMockAccountId = 132329390L;
private long diskOfferingMockId = 100203L; private long diskOfferingMockId = 100203L;
private long newDiskOfferingMockId = 100204L;
private long offeringMockId = 31902L; private long offeringMockId = 31902L;
@ -1820,4 +1840,92 @@ public class VolumeApiServiceImplTest {
volumeApiServiceImpl.validationsForCheckVolumeOperation(volume); volumeApiServiceImpl.validationsForCheckVolumeOperation(volume);
} }
private void testResizeVolumeSetup() throws ExecutionException, InterruptedException {
Long poolId = 11L;
when(volumeDaoMock.findById(volumeMockId)).thenReturn(volumeVoMock);
when(volumeVoMock.getId()).thenReturn(volumeMockId);
when(volumeDaoMock.getHypervisorType(volumeMockId)).thenReturn(HypervisorType.KVM);
when(volumeVoMock.getState()).thenReturn(Volume.State.Ready);
when(volumeVoMock.getDiskOfferingId()).thenReturn(diskOfferingMockId);
when(_diskOfferingDao.findById(diskOfferingMockId)).thenReturn(diskOfferingMock);
when(_diskOfferingDao.findById(newDiskOfferingMockId)).thenReturn(newDiskOfferingMock);
when(newDiskOfferingMock.getRemoved()).thenReturn(null);
when(diskOfferingMock.getDiskSizeStrictness()).thenReturn(false);
when(newDiskOfferingMock.getDiskSizeStrictness()).thenReturn(false);
when(volumeVoMock.getInstanceId()).thenReturn(null);
when(volumeVoMock.getVolumeType()).thenReturn(Type.DATADISK);
when(newDiskOfferingMock.getDiskSize()).thenReturn(newVolumeSizeMock);
VolumeInfo volInfo = Mockito.mock(VolumeInfo.class);
when(volumeDataFactoryMock.getVolume(volumeMockId)).thenReturn(volInfo);
DataStore dataStore = Mockito.mock(DataStore.class);
when((volInfo.getDataStore())).thenReturn(dataStore);
when(volumeVoMock.getPoolId()).thenReturn(poolId);
StoragePoolVO storagePool = Mockito.mock(StoragePoolVO.class);
when(primaryDataStoreDaoMock.findById(poolId)).thenReturn(storagePool);
Mockito.lenient().doReturn(asyncCallFutureVolumeapiResultMock).when(volumeServiceMock).resize(any(VolumeInfo.class));
Mockito.doReturn(Mockito.mock(VolumeApiResult.class)).when(asyncCallFutureVolumeapiResultMock).get();
}
@Test
public void testResizeVolumeWithEnoughCapacity() throws ResourceAllocationException, ExecutionException, InterruptedException {
ResizeVolumeCmd cmd = new ResizeVolumeCmd();
ReflectionTestUtils.setField(cmd, "id", volumeMockId);
ReflectionTestUtils.setField(cmd, "newDiskOfferingId", newDiskOfferingMockId);
testResizeVolumeSetup();
when(storageMgr.storagePoolHasEnoughSpaceForResize(any(), nullable(Long.class), nullable(Long.class))).thenReturn(true);
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
volumeApiServiceImpl.resizeVolume(cmd);
verify(volumeServiceMock).resize(any(VolumeInfo.class));
}
}
@Test
public void testResizeVolumeWithoutEnoughCapacity() throws ResourceAllocationException, ExecutionException, InterruptedException {
ResizeVolumeCmd cmd = new ResizeVolumeCmd();
ReflectionTestUtils.setField(cmd, "id", volumeMockId);
ReflectionTestUtils.setField(cmd, "newDiskOfferingId", newDiskOfferingMockId);
ReflectionTestUtils.setField(cmd, "autoMigrate", true);
testResizeVolumeSetup();
when(storageMgr.storagePoolHasEnoughSpaceForResize(any(), nullable(Long.class), nullable(Long.class))).thenReturn(false).thenReturn(true);
StoragePoolVO suitableStoragePool = Mockito.mock(StoragePoolVO.class);
Pair<List<? extends StoragePool>, List<? extends StoragePool>> poolsPair = new Pair<>(Arrays.asList(suitableStoragePool), Arrays.asList(suitableStoragePool));
when(managementService.listStoragePoolsForSystemMigrationOfVolume(anyLong(), anyLong(), anyLong(), anyLong(), anyLong(), anyBoolean(), anyBoolean())).thenReturn(poolsPair);
doReturn(volumeInfoMock).when(volumeApiServiceImpl).migrateVolume(any());
when(volumeInfoMock.getId()).thenReturn(volumeMockId);
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
volumeApiServiceImpl.resizeVolume(cmd);
verify(volumeApiServiceImpl).migrateVolume(any());
verify(volumeServiceMock).resize(any(VolumeInfo.class));
}
}
@Test
public void testResizeVolumeInAllocateState() throws ResourceAllocationException, ExecutionException, InterruptedException {
ResizeVolumeCmd cmd = new ResizeVolumeCmd();
ReflectionTestUtils.setField(cmd, "id", volumeMockId);
ReflectionTestUtils.setField(cmd, "newDiskOfferingId", newDiskOfferingMockId);
testResizeVolumeSetup();
when(volumeVoMock.getState()).thenReturn(Volume.State.Allocated);
try (MockedStatic<UsageEventUtils> ignored = Mockito.mockStatic(UsageEventUtils.class)) {
volumeApiServiceImpl.resizeVolume(cmd);
verify(volumeServiceMock, times(0)).resize(any(VolumeInfo.class));
}
}
} }

View File

@ -26,7 +26,9 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.cloud.event.ActionEventUtils;
import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.SecurityChecker.AccessType;
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.DeleteUserCmd;
import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity;
@ -90,6 +92,9 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
@Mock @Mock
private UpdateUserCmd UpdateUserCmdMock; private UpdateUserCmd UpdateUserCmdMock;
@Mock
private UpdateAccountCmd UpdateAccountCmdMock;
private long userVoIdMock = 111l; private long userVoIdMock = 111l;
@Mock @Mock
private UserVO userVoMock; private UserVO userVoMock;
@ -507,6 +512,46 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
Mockito.verify(userVoMock).setSecretKey(secretKey); Mockito.verify(userVoMock).setSecretKey(secretKey);
} }
@Test
public void validateAndUpdatUserApiKeyAccess() {
Mockito.doReturn("Enabled").when(UpdateUserCmdMock).getApiKeyAccess();
try (MockedStatic<ActionEventUtils> eventUtils = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
Mockito.anyLong(),
Mockito.anyString(), Mockito.anyString(),
Mockito.anyLong(), Mockito.anyString())).thenReturn(1L);
accountManagerImpl.validateAndUpdateUserApiKeyAccess(UpdateUserCmdMock, userVoMock);
}
Mockito.verify(userVoMock).setApiKeyAccess(true);
}
@Test(expected = InvalidParameterValueException.class)
public void validateAndUpdatUserApiKeyAccessInvalidParameter() {
Mockito.doReturn("False").when(UpdateUserCmdMock).getApiKeyAccess();
accountManagerImpl.validateAndUpdateUserApiKeyAccess(UpdateUserCmdMock, userVoMock);
}
@Test
public void validateAndUpdatAccountApiKeyAccess() {
Mockito.doReturn("Inherit").when(UpdateAccountCmdMock).getApiKeyAccess();
try (MockedStatic<ActionEventUtils> eventUtils = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
Mockito.anyLong(),
Mockito.anyString(), Mockito.anyString(),
Mockito.anyLong(), Mockito.anyString())).thenReturn(1L);
accountManagerImpl.validateAndUpdateAccountApiKeyAccess(UpdateAccountCmdMock, accountVoMock);
}
Mockito.verify(accountVoMock).setApiKeyAccess(null);
}
@Test(expected = InvalidParameterValueException.class)
public void validateAndUpdatAccountApiKeyAccessInvalidParameter() {
Mockito.doReturn("False").when(UpdateAccountCmdMock).getApiKeyAccess();
accountManagerImpl.validateAndUpdateAccountApiKeyAccess(UpdateAccountCmdMock, accountVoMock);
}
@Test(expected = CloudRuntimeException.class) @Test(expected = CloudRuntimeException.class)
public void retrieveAndValidateAccountTestAccountNotFound() { public void retrieveAndValidateAccountTestAccountNotFound() {
Mockito.doReturn(accountMockId).when(userVoMock).getAccountId(); Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();

View File

@ -450,12 +450,12 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco
} }
@Override @Override
public Map<String, String> getKeys(GetUserKeysCmd cmd) { public Pair<Boolean, Map<String, String>> getKeys(GetUserKeysCmd cmd) {
return null; return null;
} }
@Override @Override
public Map<String, String> getKeys(Long userId) { public Pair<Boolean, Map<String, String>> getKeys(Long userId) {
return null; return null;
} }

View File

@ -635,7 +635,7 @@ public class UserVmManagerImplTest {
int expectedExceptionCounter = hypervisorTypeArray.length - 5; int expectedExceptionCounter = hypervisorTypeArray.length - 5;
for(int i = 0; i < hypervisorTypeArray.length; i++) { for(int i = 0; i < hypervisorTypeArray.length; i++) {
if (UserVmManagerImpl.ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS.contains(hypervisorTypeArray[i])) { if (hypervisorTypeArray[i].isFunctionalitySupported(Hypervisor.HypervisorType.Functionality.RootDiskSizeOverride)) {
userVmManagerImpl.verifyIfHypervisorSupportsRootdiskSizeOverride(hypervisorTypeArray[i]); userVmManagerImpl.verifyIfHypervisorSupportsRootdiskSizeOverride(hypervisorTypeArray[i]);
} else { } else {
try { try {

View File

@ -136,7 +136,6 @@ public class VMSnapshotManagerTest {
VMSnapshotDetailsDao _vmSnapshotDetailsDao; VMSnapshotDetailsDao _vmSnapshotDetailsDao;
@Mock @Mock
UserVmManager _userVmManager; UserVmManager _userVmManager;
int _vmSnapshotMax = 10;
private static final long TEST_VM_ID = 3L; private static final long TEST_VM_ID = 3L;
private static final long SERVICE_OFFERING_ID = 1L; private static final long SERVICE_OFFERING_ID = 1L;
@ -194,8 +193,6 @@ public class VMSnapshotManagerTest {
doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class));
_vmSnapshotMgr._vmSnapshotMax = _vmSnapshotMax;
_vmSnapshotMgr._serviceOfferingDao = _serviceOfferingDao; _vmSnapshotMgr._serviceOfferingDao = _serviceOfferingDao;
_vmSnapshotMgr._userVmDetailsDao = _userVmDetailsDao; _vmSnapshotMgr._userVmDetailsDao = _userVmDetailsDao;
_vmSnapshotMgr._vmSnapshotDetailsDao = _vmSnapshotDetailsDao; _vmSnapshotMgr._vmSnapshotDetailsDao = _vmSnapshotDetailsDao;

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@
"label.accesskey": "Access key", "label.accesskey": "Access key",
"label.access.key": "Access key", "label.access.key": "Access key",
"label.secret.key": "Secret key", "label.secret.key": "Secret key",
"label.apikeyaccess": "Api Key Access",
"label.account": "Account", "label.account": "Account",
"label.account.and.security.group": "Account - security group", "label.account.and.security.group": "Account - security group",
"label.account.id": "Account ID", "label.account.id": "Account ID",
@ -882,6 +883,7 @@
"label.edge": "Edge", "label.edge": "Edge",
"label.edge.zone": "Edge Zone", "label.edge.zone": "Edge Zone",
"label.edit": "Edit", "label.edit": "Edit",
"label.edit.account": "Edit Account",
"label.edit.acl.list": "Edit ACL list", "label.edit.acl.list": "Edit ACL list",
"label.edit.acl.rule": "Edit ACL rule", "label.edit.acl.rule": "Edit ACL rule",
"label.edit.autoscale.vmprofile": "Edit AutoScale Instance Profile", "label.edit.autoscale.vmprofile": "Edit AutoScale Instance Profile",
@ -1291,6 +1293,7 @@
"label.l3gatewayserviceuuid": "L3 Gateway Service UUID", "label.l3gatewayserviceuuid": "L3 Gateway Service UUID",
"label.label": "Label", "label.label": "Label",
"label.last.updated": "Last update", "label.last.updated": "Last update",
"label.lastupdated": "Last update",
"label.lastannotated": "Last annotation date", "label.lastannotated": "Last annotation date",
"label.lastheartbeat": "Last heartbeat", "label.lastheartbeat": "Last heartbeat",
"label.lastsuccessfuljob": "Last successful job", "label.lastsuccessfuljob": "Last successful job",
@ -1380,6 +1383,7 @@
"label.management.ips": "Management IP addresses", "label.management.ips": "Management IP addresses",
"label.management.server": "Management server", "label.management.server": "Management server",
"label.management.servers": "Management servers", "label.management.servers": "Management servers",
"label.management.server.peers": "Peers",
"label.managementservers": "Number of management servers", "label.managementservers": "Number of management servers",
"label.matchall": "Match all", "label.matchall": "Match all",
"label.max": "Max.", "label.max": "Max.",
@ -1668,6 +1672,13 @@
"label.payload": "Payload", "label.payload": "Payload",
"label.payloadurl": "Payload URL", "label.payloadurl": "Payload URL",
"label.pcidevice": "GPU", "label.pcidevice": "GPU",
"label.peername": "Management Server",
"label.peermsid": "Management Server Node ID",
"label.peerrunid": "Process Timestamp",
"label.peerserviceip": "Management IP",
"label.peerserviceport": "Service Port",
"label.peerstate": "Peer State",
"label.peerstate.lastupdated": "Peer State Updated Time",
"label.pending.jobs": "Pending Jobs", "label.pending.jobs": "Pending Jobs",
"label.per.account": "Per Account", "label.per.account": "Per Account",
"label.per.zone": "Per zone", "label.per.zone": "Per zone",
@ -2036,7 +2047,7 @@
"label.service.connectivity.distributedroutercapabilitycheckbox": "Distributed router", "label.service.connectivity.distributedroutercapabilitycheckbox": "Distributed router",
"label.service.connectivity.regionlevelvpccapabilitycheckbox": "Region level VPC", "label.service.connectivity.regionlevelvpccapabilitycheckbox": "Region level VPC",
"label.service.group": "Service group", "label.service.group": "Service group",
"label.serviceip": "Service IP", "label.serviceip": "Management IP",
"label.service.lb.elasticlbcheckbox": "Elastic LB", "label.service.lb.elasticlbcheckbox": "Elastic LB",
"label.service.lb.inlinemodedropdown": "Mode", "label.service.lb.inlinemodedropdown": "Mode",
"label.service.lb.lbisolationdropdown": "LB isolation", "label.service.lb.lbisolationdropdown": "LB isolation",
@ -2151,6 +2162,7 @@
"label.startport": "Start port", "label.startport": "Start port",
"label.startquota": "Quota value", "label.startquota": "Quota value",
"label.state": "State", "label.state": "State",
"label.state.reported": "Reported State",
"label.staticnat": "Static NAT", "label.staticnat": "Static NAT",
"label.static": "Static", "label.static": "Static",
"label.static.routes": "Static routes", "label.static.routes": "Static routes",
@ -3540,6 +3552,7 @@
"message.success.scale.kubernetes": "Successfully scaled Kubernetes cluster", "message.success.scale.kubernetes": "Successfully scaled Kubernetes cluster",
"message.success.unmanage.instance": "Successfully unmanaged Instance", "message.success.unmanage.instance": "Successfully unmanaged Instance",
"message.success.unmanage.volume": "Successfully unmanaged Volume", "message.success.unmanage.volume": "Successfully unmanaged Volume",
"message.success.update.account": "Successfully updated Account",
"message.success.update.bgp.peer": "Successfully updated BGP peer", "message.success.update.bgp.peer": "Successfully updated BGP peer",
"message.success.update.bucket": "Successfully updated bucket", "message.success.update.bucket": "Successfully updated bucket",
"message.success.update.condition": "Successfully updated condition", "message.success.update.condition": "Successfully updated condition",

View File

@ -733,8 +733,18 @@
</div> </div>
</div> </div>
<div class="account-center-tags" v-if="showKeys"> <div class="account-center-tags" v-if="showKeys || resource.apikeyaccess">
<a-divider/> <a-divider/>
</div>
<div class="account-center-tags" v-if="resource.apikeyaccess && resource.account">
<div class="resource-detail-item">
<div class="resource-detail-item__label">{{ $t('label.apikeyaccess') }}</div>
<div class="resource-detail-item__details">
<status class="status" :text="resource.apikeyaccess" displayText/>
</div>
</div>
</div>
<div class="account-center-tags" v-if="showKeys">
<div class="user-keys"> <div class="user-keys">
<key-outlined /> <key-outlined />
<strong> <strong>
@ -1083,6 +1093,9 @@ export default {
api('getUserKeys', { id: this.resource.id }).then(json => { api('getUserKeys', { id: this.resource.id }).then(json => {
this.showKeys = true this.showKeys = true
this.newResource.secretkey = json.getuserkeysresponse.userkeys.secretkey this.newResource.secretkey = json.getuserkeysresponse.userkeys.secretkey
if (!this.isAdmin()) {
this.newResource.apikeyaccess = json.getuserkeysresponse.userkeys.apikeyaccess ? 'Enabled' : 'Disabled'
}
this.$emit('change-resource', this.newResource) this.$emit('change-resource', this.newResource)
}) })
}, },
@ -1113,6 +1126,9 @@ export default {
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account) || (this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account) ||
(this.resource.project && this.resource.projectid === this.$store.getters.project.id) (this.resource.project && this.resource.projectid === this.$store.getters.project.id)
}, },
isAdmin () {
return ['Admin'].includes(this.$store.getters.userInfo.roletype)
},
showInput () { showInput () {
this.inputVisible = true this.inputVisible = true
this.$nextTick(function () { this.$nextTick(function () {

View File

@ -311,7 +311,7 @@ export default {
type = 'list' type = 'list'
} else if (item === 'tags') { } else if (item === 'tags') {
type = 'tag' type = 'tag'
} else if (item === 'resourcetype') { } else if (['resourcetype', 'apikeyaccess'].includes(item)) {
type = 'autocomplete' type = 'autocomplete'
} else if (item === 'isencrypted') { } else if (item === 'isencrypted') {
type = 'boolean' type = 'boolean'
@ -424,6 +424,17 @@ export default {
] ]
this.fields[resourceTypeIndex].loading = false this.fields[resourceTypeIndex].loading = false
} }
if (arrayField.includes('apikeyaccess')) {
const apiKeyAccessIndex = this.fields.findIndex(item => item.name === 'apikeyaccess')
this.fields[apiKeyAccessIndex].loading = true
this.fields[apiKeyAccessIndex].opts = [
{ value: 'Disabled' },
{ value: 'Enabled' },
{ value: 'Inherit' }
]
this.fields[apiKeyAccessIndex].loading = false
}
}, },
async fetchDynamicFieldData (arrayField, searchKeyword) { async fetchDynamicFieldData (arrayField, searchKeyword) {
const promises = [] const promises = []

View File

@ -24,9 +24,15 @@ export default {
icon: 'team-outlined', icon: 'team-outlined',
docHelp: 'adminguide/accounts.html', docHelp: 'adminguide/accounts.html',
permission: ['listAccounts'], permission: ['listAccounts'],
searchFilters: ['name', 'accounttype', 'domainid'], searchFilters: () => {
var filters = ['name', 'accounttype', 'domainid']
if (store.getters.userInfo.roletype === 'Admin') {
filters.push('apikeyaccess')
}
return filters
},
columns: ['name', 'state', 'rolename', 'roletype', 'domainpath'], columns: ['name', 'state', 'rolename', 'roletype', 'domainpath'],
details: ['name', 'id', 'rolename', 'roletype', 'domainpath', 'networkdomain', 'iptotal', 'vmtotal', 'volumetotal', 'receivedbytes', 'sentbytes', 'created'], details: ['name', 'id', 'rolename', 'roletype', 'domainpath', 'networkdomain', 'apikeyaccess', 'iptotal', 'vmtotal', 'volumetotal', 'receivedbytes', 'sentbytes', 'created'],
related: [{ related: [{
name: 'accountuser', name: 'accountuser',
title: 'label.users', title: 'label.users',
@ -116,15 +122,8 @@ export default {
icon: 'edit-outlined', icon: 'edit-outlined',
label: 'label.action.edit.account', label: 'label.action.edit.account',
dataView: true, dataView: true,
args: ['newname', 'account', 'domainid', 'networkdomain', 'roleid'], popup: true,
mapping: { component: shallowRef(defineAsyncComponent(() => import('@/views/iam/EditAccount.vue')))
account: {
value: (record) => { return record.name }
},
domainid: {
value: (record) => { return record.domainid }
}
}
}, },
{ {
api: 'updateResourceCount', api: 'updateResourceCount',

View File

@ -43,6 +43,10 @@ export default {
name: 'pending.jobs', name: 'pending.jobs',
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/AsyncJobsTab.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/views/infra/AsyncJobsTab.vue')))
}, },
{
name: 'management.server.peers',
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/ManagementServerPeerTab.vue')))
},
{ {
name: 'comments', name: 'comments',
component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue')))

Some files were not shown because too many files have changed in this diff Show More