mirror of https://github.com/apache/cloudstack.git
Compare commits
39 Commits
b55e0466dd
...
47d46a640b
| Author | SHA1 | Date |
|---|---|---|
|
|
47d46a640b | |
|
|
420bf6dff8 | |
|
|
b1f870ae83 | |
|
|
036489b288 | |
|
|
1b0a036a5b | |
|
|
e2f4ed9dcf | |
|
|
8db7cab7ba | |
|
|
496bc0329c | |
|
|
cf36fb0000 | |
|
|
da518e9036 | |
|
|
03d24ff851 | |
|
|
2a6ce0c8a8 | |
|
|
04b58acdd6 | |
|
|
3828a3b744 | |
|
|
42f1e19362 | |
|
|
8b2f1f19c2 | |
|
|
a4b1a27c7d | |
|
|
002d9768b2 | |
|
|
76e6de7f90 | |
|
|
b31c2f4cae | |
|
|
a566af35f5 | |
|
|
f1f779a08d | |
|
|
aba3285c3c | |
|
|
507c4cd128 | |
|
|
b5fd39fca0 | |
|
|
5c1f9315ce | |
|
|
6a324da27a | |
|
|
b8ed34e2a8 | |
|
|
9e86fdf1b6 | |
|
|
538578366a | |
|
|
031fbf43d4 | |
|
|
8627c60b95 | |
|
|
8dcfc7c767 | |
|
|
2b373a4659 | |
|
|
c7cfeb5caa | |
|
|
0e6d2d986b | |
|
|
db1c7d678c | |
|
|
2399edd380 | |
|
|
04875f1517 |
|
|
@ -503,6 +503,7 @@ public class EventTypes {
|
|||
public static final String EVENT_S2S_VPN_CUSTOMER_GATEWAY_CREATE = "VPN.S2S.CUSTOMER.GATEWAY.CREATE";
|
||||
public static final String EVENT_S2S_VPN_CUSTOMER_GATEWAY_DELETE = "VPN.S2S.CUSTOMER.GATEWAY.DELETE";
|
||||
public static final String EVENT_S2S_VPN_CUSTOMER_GATEWAY_UPDATE = "VPN.S2S.CUSTOMER.GATEWAY.UPDATE";
|
||||
public static final String EVENT_S2S_VPN_GATEWAY_OBSOLETE_PARAMS = "VPN.S2S.GATEWAY.OBSOLETE.PARAMS";
|
||||
public static final String EVENT_S2S_VPN_CONNECTION_CREATE = "VPN.S2S.CONNECTION.CREATE";
|
||||
public static final String EVENT_S2S_VPN_CONNECTION_DELETE = "VPN.S2S.CONNECTION.DELETE";
|
||||
public static final String EVENT_S2S_VPN_CONNECTION_RESET = "VPN.S2S.CONNECTION.RESET";
|
||||
|
|
@ -1151,6 +1152,7 @@ public class EventTypes {
|
|||
entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_CREATE, Site2SiteCustomerGateway.class);
|
||||
entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_DELETE, Site2SiteCustomerGateway.class);
|
||||
entityEventDetails.put(EVENT_S2S_VPN_CUSTOMER_GATEWAY_UPDATE, Site2SiteCustomerGateway.class);
|
||||
entityEventDetails.put(EVENT_S2S_VPN_GATEWAY_OBSOLETE_PARAMS, Site2SiteCustomerGateway.class);
|
||||
entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_CREATE, Site2SiteVpnConnection.class);
|
||||
entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_DELETE, Site2SiteVpnConnection.class);
|
||||
entityEventDetails.put(EVENT_S2S_VPN_CONNECTION_RESET, Site2SiteVpnConnection.class);
|
||||
|
|
|
|||
|
|
@ -125,6 +125,10 @@ public interface NetworkModel {
|
|||
*/
|
||||
String getNextAvailableMacAddressInNetwork(long networkConfigurationId) throws InsufficientAddressCapacityException;
|
||||
|
||||
String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException;
|
||||
|
||||
boolean isMACUnique(String mac, long networkId);
|
||||
|
||||
PublicIpAddress getPublicIpAddress(long ipAddressId);
|
||||
|
||||
List<? extends Vlan> listPodVlans(long podId);
|
||||
|
|
@ -364,4 +368,8 @@ public interface NetworkModel {
|
|||
|
||||
boolean checkSecurityGroupSupportForNetwork(Account account, DataCenter zone, List<Long> networkIds,
|
||||
List<Long> securityGroupsIds);
|
||||
|
||||
default long getMacIdentifier(Long dataCenterId) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import com.cloud.offering.DiskOffering;
|
|||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
|
||||
public interface AccountService {
|
||||
|
||||
|
|
@ -115,6 +116,8 @@ public interface AccountService {
|
|||
|
||||
void checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException;
|
||||
|
||||
void checkAccess(Account account, BackupOffering bof) throws PermissionDeniedException;
|
||||
|
||||
void checkAccess(User user, ControlledEntity entity);
|
||||
|
||||
void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) throws PermissionDeniedException;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import com.cloud.user.Account;
|
|||
import com.cloud.user.User;
|
||||
import com.cloud.utils.component.Adapter;
|
||||
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
|
||||
/**
|
||||
* SecurityChecker checks the ownership and access control to objects within
|
||||
*/
|
||||
|
|
@ -145,4 +147,6 @@ public interface SecurityChecker extends Adapter {
|
|||
boolean checkAccess(Account account, NetworkOffering nof, DataCenter zone) throws PermissionDeniedException;
|
||||
|
||||
boolean checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException;
|
||||
|
||||
boolean checkAccess(Account account, BackupOffering bof) throws PermissionDeniedException;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ public interface AlertService {
|
|||
public static final AlertType ALERT_TYPE_VR_PUBLIC_IFACE_MTU = new AlertType((short)32, "ALERT.VR.PUBLIC.IFACE.MTU", true);
|
||||
public static final AlertType ALERT_TYPE_VR_PRIVATE_IFACE_MTU = new AlertType((short)32, "ALERT.VR.PRIVATE.IFACE.MTU", true);
|
||||
public static final AlertType ALERT_TYPE_EXTENSION_PATH_NOT_READY = new AlertType((short)33, "ALERT.TYPE.EXTENSION.PATH.NOT.READY", true);
|
||||
public static final AlertType ALERT_TYPE_VPN_GATEWAY_OBSOLETE_PARAMETERS = new AlertType((short)34, "ALERT.S2S.VPN.GATEWAY.OBSOLETE.PARAMETERS", true);
|
||||
public static final AlertType ALERT_TYPE_BACKUP_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_BACKUP_STORAGE, "ALERT.STORAGE.BACKUP", true);
|
||||
public static final AlertType ALERT_TYPE_OBJECT_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_OBJECT_STORAGE, "ALERT.STORAGE.OBJECT", true);
|
||||
|
||||
|
|
|
|||
|
|
@ -1216,6 +1216,7 @@ public class ApiConstants {
|
|||
public static final String DOCKER_REGISTRY_EMAIL = "dockerregistryemail";
|
||||
public static final String ISO_NAME = "isoname";
|
||||
public static final String ISO_STATE = "isostate";
|
||||
public static final String ISO_URL = "isourl";
|
||||
public static final String SEMANTIC_VERSION = "semanticversion";
|
||||
public static final String KUBERNETES_VERSION_ID = "kubernetesversionid";
|
||||
public static final String KUBERNETES_VERSION_NAME = "kubernetesversionname";
|
||||
|
|
@ -1364,6 +1365,10 @@ public class ApiConstants {
|
|||
|
||||
public static final String RECURSIVE_DOMAINS = "recursivedomains";
|
||||
|
||||
public static final String VPN_CUSTOMER_GATEWAY_PARAMETERS = "vpncustomergatewayparameters";
|
||||
public static final String OBSOLETE_PARAMETERS = "obsoleteparameters";
|
||||
public static final String EXCLUDED_PARAMETERS = "excludedparameters";
|
||||
|
||||
/**
|
||||
* This enum specifies IO Drivers, each option controls specific policies on I/O.
|
||||
* Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0).
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import org.apache.cloudstack.api.response.ListResponse;
|
|||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
||||
public abstract class BaseBackupListCmd extends BaseListCmd {
|
||||
public abstract class BaseBackupListCmd extends BaseListAccountResourcesCmd {
|
||||
|
||||
protected void setupResponseBackupOfferingsList(final List<BackupOffering> offerings, final Integer count) {
|
||||
final ListResponse<BackupOfferingResponse> response = new ListResponse<>();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import org.apache.cloudstack.api.BaseCmd;
|
|||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.BackupOfferingResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||
import org.apache.cloudstack.backup.BackupManager;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
|
|
@ -40,6 +41,11 @@ import com.cloud.exception.NetworkRuleConflictException;
|
|||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@APICommand(name = "importBackupOffering",
|
||||
description = "Imports a backup offering using a backup provider",
|
||||
|
|
@ -76,6 +82,13 @@ public class ImportBackupOfferingCmd extends BaseAsyncCmd {
|
|||
description = "Whether users are allowed to create adhoc backups and backup schedules", required = true)
|
||||
private Boolean userDrivenBackups;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID,
|
||||
type = CommandType.LIST,
|
||||
collectionType = CommandType.UUID,
|
||||
entityType = DomainResponse.class,
|
||||
description = "the ID of the containing domain(s), null for public offerings")
|
||||
private List<Long> domainIds;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -100,6 +113,15 @@ public class ImportBackupOfferingCmd extends BaseAsyncCmd {
|
|||
return userDrivenBackups == null ? false : userDrivenBackups;
|
||||
}
|
||||
|
||||
public List<Long> getDomainIds() {
|
||||
if (CollectionUtils.isNotEmpty(domainIds)) {
|
||||
Set<Long> set = new LinkedHashSet<>(domainIds);
|
||||
domainIds.clear();
|
||||
domainIds.addAll(set);
|
||||
}
|
||||
return domainIds;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -25,19 +25,24 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
|
||||
import org.apache.cloudstack.api.response.BackupOfferingResponse;
|
||||
import org.apache.cloudstack.backup.BackupManager;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
@APICommand(name = "updateBackupOffering", description = "Updates a backup offering.", responseObject = BackupOfferingResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.16.0")
|
||||
public class UpdateBackupOfferingCmd extends BaseCmd {
|
||||
public class UpdateBackupOfferingCmd extends BaseCmd implements DomainAndZoneIdResolver {
|
||||
|
||||
@Inject
|
||||
private BackupManager backupManager;
|
||||
|
|
@ -57,6 +62,13 @@ public class UpdateBackupOfferingCmd extends BaseCmd {
|
|||
@Parameter(name = ApiConstants.ALLOW_USER_DRIVEN_BACKUPS, type = CommandType.BOOLEAN, description = "Whether to allow user driven backups or not")
|
||||
private Boolean allowUserDrivenBackups;
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID,
|
||||
type = CommandType.STRING,
|
||||
description = "the ID of the containing domain(s) as comma separated string, public for public offerings",
|
||||
since = "4.23.0",
|
||||
length = 4096)
|
||||
private String domainIds;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -82,7 +94,7 @@ public class UpdateBackupOfferingCmd extends BaseCmd {
|
|||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
if (StringUtils.isAllEmpty(getName(), getDescription()) && getAllowUserDrivenBackups() == null) {
|
||||
if (StringUtils.isAllEmpty(getName(), getDescription()) && getAllowUserDrivenBackups() == null && CollectionUtils.isEmpty(getDomainIds())) {
|
||||
throw new InvalidParameterValueException(String.format("Can't update Backup Offering [id: %s] because there are no parameters to be updated, at least one of the",
|
||||
"following should be informed: name, description or allowUserDrivenBackups.", id));
|
||||
}
|
||||
|
|
@ -103,6 +115,18 @@ public class UpdateBackupOfferingCmd extends BaseCmd {
|
|||
}
|
||||
}
|
||||
|
||||
public List<Long> getDomainIds() {
|
||||
// backupManager may be null in unit tests where the command is spied without injection.
|
||||
// Avoid creating a method reference to a null receiver which causes NPE. When backupManager
|
||||
// is null, pass null as the defaultDomainsProvider so resolveDomainIds will simply return
|
||||
// an empty list or parse the explicit domainIds string.
|
||||
LongFunction<List<Long>> defaultDomainsProvider = null;
|
||||
if (backupManager != null) {
|
||||
defaultDomainsProvider = backupManager::getBackupOfferingDomains;
|
||||
}
|
||||
return resolveDomainIds(domainIds, id, defaultDomainsProvider, "backup offering");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.network;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
|
|
@ -26,18 +25,16 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
|
||||
import org.apache.cloudstack.api.response.NetworkOfferingResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "updateNetworkOffering", description = "Updates a network offering.", responseObject = NetworkOfferingResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class UpdateNetworkOfferingCmd extends BaseCmd {
|
||||
public class UpdateNetworkOfferingCmd extends BaseCmd implements DomainAndZoneIdResolver {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
|
|
@ -129,63 +126,11 @@ public class UpdateNetworkOfferingCmd extends BaseCmd {
|
|||
}
|
||||
|
||||
public List<Long> getDomainIds() {
|
||||
List<Long> validDomainIds = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(domainIds)) {
|
||||
if (domainIds.contains(",")) {
|
||||
String[] domains = domainIds.split(",");
|
||||
for (String domain : domains) {
|
||||
Domain validDomain = _entityMgr.findByUuid(Domain.class, domain.trim());
|
||||
if (validDomain != null) {
|
||||
validDomainIds.add(validDomain.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create network offering because invalid domain has been specified.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
domainIds = domainIds.trim();
|
||||
if (!domainIds.matches("public")) {
|
||||
Domain validDomain = _entityMgr.findByUuid(Domain.class, domainIds.trim());
|
||||
if (validDomain != null) {
|
||||
validDomainIds.add(validDomain.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create network offering because invalid domain has been specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validDomainIds.addAll(_configService.getNetworkOfferingDomains(id));
|
||||
}
|
||||
return validDomainIds;
|
||||
return resolveDomainIds(domainIds, id, _configService::getNetworkOfferingDomains, "network offering");
|
||||
}
|
||||
|
||||
public List<Long> getZoneIds() {
|
||||
List<Long> validZoneIds = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(zoneIds)) {
|
||||
if (zoneIds.contains(",")) {
|
||||
String[] zones = zoneIds.split(",");
|
||||
for (String zone : zones) {
|
||||
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zone.trim());
|
||||
if (validZone != null) {
|
||||
validZoneIds.add(validZone.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create network offering because invalid zone has been specified.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zoneIds = zoneIds.trim();
|
||||
if (!zoneIds.matches("all")) {
|
||||
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zoneIds.trim());
|
||||
if (validZone != null) {
|
||||
validZoneIds.add(validZone.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create network offering because invalid zone has been specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validZoneIds.addAll(_configService.getNetworkOfferingZones(id));
|
||||
}
|
||||
return validZoneIds;
|
||||
return resolveZoneIds(zoneIds, id, _configService::getNetworkOfferingZones, "network offering");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.offering;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.offering.DiskOffering.State;
|
||||
|
|
@ -27,19 +26,18 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
|
||||
import org.apache.cloudstack.api.response.DiskOfferingResponse;
|
||||
import org.apache.commons.lang3.EnumUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "updateDiskOffering", description = "Updates a disk offering.", responseObject = DiskOfferingResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class UpdateDiskOfferingCmd extends BaseCmd {
|
||||
public class UpdateDiskOfferingCmd extends BaseCmd implements DomainAndZoneIdResolver {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
|
|
@ -151,63 +149,11 @@ public class UpdateDiskOfferingCmd extends BaseCmd {
|
|||
}
|
||||
|
||||
public List<Long> getDomainIds() {
|
||||
List<Long> validDomainIds = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(domainIds)) {
|
||||
if (domainIds.contains(",")) {
|
||||
String[] domains = domainIds.split(",");
|
||||
for (String domain : domains) {
|
||||
Domain validDomain = _entityMgr.findByUuid(Domain.class, domain.trim());
|
||||
if (validDomain != null) {
|
||||
validDomainIds.add(validDomain.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create disk offering because invalid domain has been specified.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
domainIds = domainIds.trim();
|
||||
if (!domainIds.matches("public")) {
|
||||
Domain validDomain = _entityMgr.findByUuid(Domain.class, domainIds.trim());
|
||||
if (validDomain != null) {
|
||||
validDomainIds.add(validDomain.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create disk offering because invalid domain has been specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validDomainIds.addAll(_configService.getDiskOfferingDomains(id));
|
||||
}
|
||||
return validDomainIds;
|
||||
return resolveDomainIds(domainIds, id, _configService::getDiskOfferingDomains, "disk offering");
|
||||
}
|
||||
|
||||
public List<Long> getZoneIds() {
|
||||
List<Long> validZoneIds = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(zoneIds)) {
|
||||
if (zoneIds.contains(",")) {
|
||||
String[] zones = zoneIds.split(",");
|
||||
for (String zone : zones) {
|
||||
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zone.trim());
|
||||
if (validZone != null) {
|
||||
validZoneIds.add(validZone.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create disk offering because invalid zone has been specified.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zoneIds = zoneIds.trim();
|
||||
if (!zoneIds.matches("all")) {
|
||||
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zoneIds.trim());
|
||||
if (validZone != null) {
|
||||
validZoneIds.add(validZone.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create disk offering because invalid zone has been specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validZoneIds.addAll(_configService.getDiskOfferingZones(id));
|
||||
}
|
||||
return validZoneIds;
|
||||
return resolveZoneIds(zoneIds, id, _configService::getDiskOfferingZones, "disk offering");
|
||||
}
|
||||
|
||||
public String getTags() {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.offering;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -28,19 +27,18 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
|
||||
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
|
||||
import org.apache.commons.lang3.EnumUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "updateServiceOffering", description = "Updates a service offering.", responseObject = ServiceOfferingResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class UpdateServiceOfferingCmd extends BaseCmd {
|
||||
public class UpdateServiceOfferingCmd extends BaseCmd implements DomainAndZoneIdResolver {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
|
|
@ -130,63 +128,11 @@ public class UpdateServiceOfferingCmd extends BaseCmd {
|
|||
}
|
||||
|
||||
public List<Long> getDomainIds() {
|
||||
List<Long> validDomainIds = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(domainIds)) {
|
||||
if (domainIds.contains(",")) {
|
||||
String[] domains = domainIds.split(",");
|
||||
for (String domain : domains) {
|
||||
Domain validDomain = _entityMgr.findByUuid(Domain.class, domain.trim());
|
||||
if (validDomain != null) {
|
||||
validDomainIds.add(validDomain.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create service offering because invalid domain has been specified.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
domainIds = domainIds.trim();
|
||||
if (!domainIds.matches("public")) {
|
||||
Domain validDomain = _entityMgr.findByUuid(Domain.class, domainIds.trim());
|
||||
if (validDomain != null) {
|
||||
validDomainIds.add(validDomain.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create service offering because invalid domain has been specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validDomainIds.addAll(_configService.getServiceOfferingDomains(id));
|
||||
}
|
||||
return validDomainIds;
|
||||
return resolveDomainIds(domainIds, id, _configService::getServiceOfferingDomains, "service offering");
|
||||
}
|
||||
|
||||
public List<Long> getZoneIds() {
|
||||
List<Long> validZoneIds = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(zoneIds)) {
|
||||
if (zoneIds.contains(",")) {
|
||||
String[] zones = zoneIds.split(",");
|
||||
for (String zone : zones) {
|
||||
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zone.trim());
|
||||
if (validZone != null) {
|
||||
validZoneIds.add(validZone.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create service offering because invalid zone has been specified.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zoneIds = zoneIds.trim();
|
||||
if (!zoneIds.matches("all")) {
|
||||
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zoneIds.trim());
|
||||
if (validZone != null) {
|
||||
validZoneIds.add(validZone.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create service offering because invalid zone has been specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validZoneIds.addAll(_configService.getServiceOfferingZones(id));
|
||||
}
|
||||
return validZoneIds;
|
||||
return resolveZoneIds(zoneIds, id, _configService::getServiceOfferingZones, "service offering");
|
||||
}
|
||||
|
||||
public String getStorageTags() {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.vpc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
|
|
@ -26,19 +25,16 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
|
||||
import org.apache.cloudstack.api.response.VpcOfferingResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.network.vpc.VpcOffering;
|
||||
import com.cloud.user.Account;
|
||||
|
||||
@APICommand(name = "updateVPCOffering", description = "Updates VPC offering", responseObject = VpcOfferingResponse.class,
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class UpdateVPCOfferingCmd extends BaseAsyncCmd {
|
||||
public class UpdateVPCOfferingCmd extends BaseAsyncCmd implements DomainAndZoneIdResolver {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
|
|
@ -92,63 +88,11 @@ public class UpdateVPCOfferingCmd extends BaseAsyncCmd {
|
|||
}
|
||||
|
||||
public List<Long> getDomainIds() {
|
||||
List<Long> validDomainIds = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(domainIds)) {
|
||||
if (domainIds.contains(",")) {
|
||||
String[] domains = domainIds.split(",");
|
||||
for (String domain : domains) {
|
||||
Domain validDomain = _entityMgr.findByUuid(Domain.class, domain.trim());
|
||||
if (validDomain != null) {
|
||||
validDomainIds.add(validDomain.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create VPC offering because invalid domain has been specified.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
domainIds = domainIds.trim();
|
||||
if (!domainIds.matches("public")) {
|
||||
Domain validDomain = _entityMgr.findByUuid(Domain.class, domainIds.trim());
|
||||
if (validDomain != null) {
|
||||
validDomainIds.add(validDomain.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create VPC offering because invalid domain has been specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validDomainIds.addAll(_vpcProvSvc.getVpcOfferingDomains(id));
|
||||
}
|
||||
return validDomainIds;
|
||||
return resolveDomainIds(domainIds, id, _vpcProvSvc::getVpcOfferingDomains, "VPC offering");
|
||||
}
|
||||
|
||||
public List<Long> getZoneIds() {
|
||||
List<Long> validZoneIds = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(zoneIds)) {
|
||||
if (zoneIds.contains(",")) {
|
||||
String[] zones = zoneIds.split(",");
|
||||
for (String zone : zones) {
|
||||
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zone.trim());
|
||||
if (validZone != null) {
|
||||
validZoneIds.add(validZone.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create VPC offering because invalid zone has been specified.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zoneIds = zoneIds.trim();
|
||||
if (!zoneIds.matches("all")) {
|
||||
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zoneIds.trim());
|
||||
if (validZone != null) {
|
||||
validZoneIds.add(validZone.getId());
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Failed to create VPC offering because invalid zone has been specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
validZoneIds.addAll(_vpcProvSvc.getVpcOfferingZones(id));
|
||||
}
|
||||
return validZoneIds;
|
||||
return resolveZoneIds(zoneIds, id, _vpcProvSvc::getVpcOfferingZones, "VPC offering");
|
||||
}
|
||||
|
||||
public Integer getSortKey() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command.offering;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Helper for commands that accept a domainIds or zoneIds string and need to
|
||||
* resolve them to lists of IDs, falling back to an offering-specific
|
||||
* default provider.
|
||||
*/
|
||||
public interface DomainAndZoneIdResolver {
|
||||
/**
|
||||
* Parse the provided domainIds string and return a list of domain IDs.
|
||||
* If domainIds is empty, the defaultDomainsProvider will be invoked with the
|
||||
* provided resource id to obtain the current domains.
|
||||
*/
|
||||
default List<Long> resolveDomainIds(final String domainIds, final Long id, final LongFunction<List<Long>> defaultDomainsProvider, final String resourceTypeName) {
|
||||
final List<Long> validDomainIds = new ArrayList<>();
|
||||
final BaseCmd base = (BaseCmd) this;
|
||||
final Logger logger = LogManager.getLogger(base.getClass());
|
||||
|
||||
if (StringUtils.isEmpty(domainIds)) {
|
||||
if (defaultDomainsProvider != null) {
|
||||
final List<Long> defaults = defaultDomainsProvider.apply(id);
|
||||
if (defaults != null) {
|
||||
validDomainIds.addAll(defaults);
|
||||
}
|
||||
}
|
||||
return validDomainIds;
|
||||
}
|
||||
|
||||
final String[] domains = domainIds.split(",");
|
||||
final String type = (resourceTypeName == null || resourceTypeName.isEmpty()) ? "offering" : resourceTypeName;
|
||||
for (String domain : domains) {
|
||||
final String trimmed = domain == null ? "" : domain.trim();
|
||||
if (trimmed.isEmpty() || "public".equalsIgnoreCase(trimmed)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Domain validDomain = base._entityMgr.findByUuid(Domain.class, trimmed);
|
||||
if (validDomain == null) {
|
||||
logger.warn("Invalid domain specified for {}", type);
|
||||
throw new InvalidParameterValueException("Failed to create " + type + " because invalid domain has been specified.");
|
||||
}
|
||||
validDomainIds.add(validDomain.getId());
|
||||
}
|
||||
|
||||
return validDomainIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the provided zoneIds string and return a list of zone IDs.
|
||||
* If zoneIds is empty, the defaultZonesProvider will be invoked with the
|
||||
* provided resource id to obtain the current zones.
|
||||
*/
|
||||
default List<Long> resolveZoneIds(final String zoneIds, final Long id, final LongFunction<List<Long>> defaultZonesProvider, final String resourceTypeName) {
|
||||
final List<Long> validZoneIds = new ArrayList<>();
|
||||
final BaseCmd base = (BaseCmd) this;
|
||||
final Logger logger = LogManager.getLogger(base.getClass());
|
||||
|
||||
if (StringUtils.isEmpty(zoneIds)) {
|
||||
if (defaultZonesProvider != null) {
|
||||
final List<Long> defaults = defaultZonesProvider.apply(id);
|
||||
if (defaults != null) {
|
||||
validZoneIds.addAll(defaults);
|
||||
}
|
||||
}
|
||||
return validZoneIds;
|
||||
}
|
||||
|
||||
final String[] zones = zoneIds.split(",");
|
||||
final String type = (resourceTypeName == null || resourceTypeName.isEmpty()) ? "offering" : resourceTypeName;
|
||||
for (String zone : zones) {
|
||||
final String trimmed = zone == null ? "" : zone.trim();
|
||||
if (trimmed.isEmpty() || "all".equalsIgnoreCase(trimmed)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final DataCenter validZone = base._entityMgr.findByUuid(DataCenter.class, trimmed);
|
||||
if (validZone == null) {
|
||||
logger.warn("Invalid zone specified for {}: {}", type, trimmed);
|
||||
throw new InvalidParameterValueException("Failed to create " + type + " because invalid zone has been specified.");
|
||||
}
|
||||
validZoneIds.add(validZone.getId());
|
||||
}
|
||||
|
||||
return validZoneIds;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,9 @@ import java.util.Map;
|
|||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.CapabilitiesResponse;
|
||||
import org.apache.cloudstack.api.response.DomainResponse;
|
||||
import org.apache.cloudstack.config.ApiServiceConfiguration;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
|
@ -30,12 +32,22 @@ import com.cloud.user.Account;
|
|||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class ListCapabilitiesCmd extends BaseCmd {
|
||||
|
||||
@Parameter(name = ApiConstants.DOMAIN_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = DomainResponse.class,
|
||||
description = "the domain for listing capabilities.",
|
||||
since = "4.23.0")
|
||||
private Long domainId;
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
|
||||
public Long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Map<String, Object> capabilities = _mgr.listCapabilities(this);
|
||||
|
|
@ -76,6 +88,10 @@ public class ListCapabilitiesCmd extends BaseCmd {
|
|||
response.setExtensionsPath((String)capabilities.get(ApiConstants.EXTENSIONS_PATH));
|
||||
response.setDynamicScalingEnabled((Boolean) capabilities.get(ApiConstants.DYNAMIC_SCALING_ENABLED));
|
||||
response.setAdditionalConfigEnabled((Boolean) capabilities.get(ApiConstants.ADDITONAL_CONFIG_ENABLED));
|
||||
if (capabilities.containsKey(ApiConstants.VPN_CUSTOMER_GATEWAY_PARAMETERS)) {
|
||||
Map<String, Object> vpnCustomerGatewayParameters = (Map<String, Object>) capabilities.get(ApiConstants.VPN_CUSTOMER_GATEWAY_PARAMETERS);
|
||||
response.setVpnCustomerGatewayParameters(vpnCustomerGatewayParameters);
|
||||
}
|
||||
response.setObjectName("capability");
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
|
|
|
|||
|
|
@ -61,6 +61,16 @@ public class BackupOfferingResponse extends BaseResponse {
|
|||
@Param(description = "Zone name")
|
||||
private String zoneName;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN_ID)
|
||||
@Param(description = "the domain ID(s) this backup offering belongs to.",
|
||||
since = "4.23.0")
|
||||
private String domainId;
|
||||
|
||||
@SerializedName(ApiConstants.DOMAIN)
|
||||
@Param(description = "the domain name(s) this backup offering belongs to.",
|
||||
since = "4.23.0")
|
||||
private String domain;
|
||||
|
||||
@SerializedName(ApiConstants.CROSS_ZONE_INSTANCE_CREATION)
|
||||
@Param(description = "the backups with this offering can be used to create Instances on all Zones", since = "4.22.0")
|
||||
private Boolean crossZoneInstanceCreation;
|
||||
|
|
@ -108,4 +118,13 @@ public class BackupOfferingResponse extends BaseResponse {
|
|||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public void setDomainId(String domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
public void setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
// under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
|
@ -153,6 +155,10 @@ public class CapabilitiesResponse extends BaseResponse {
|
|||
@Param(description = "true if additional configurations or extraconfig can be passed to Instances", since = "4.20.2")
|
||||
private Boolean additionalConfigEnabled;
|
||||
|
||||
@SerializedName(ApiConstants.VPN_CUSTOMER_GATEWAY_PARAMETERS)
|
||||
@Param(description = "Excluded and obsolete VPN customer gateway cryptographic parameters")
|
||||
private Map<String, Object> vpnCustomerGatewayParameters;
|
||||
|
||||
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
|
||||
this.securityGroupsEnabled = securityGroupsEnabled;
|
||||
}
|
||||
|
|
@ -280,4 +286,8 @@ public class CapabilitiesResponse extends BaseResponse {
|
|||
public void setAdditionalConfigEnabled(Boolean additionalConfigEnabled) {
|
||||
this.additionalConfigEnabled = additionalConfigEnabled;
|
||||
}
|
||||
|
||||
public void setVpnCustomerGatewayParameters(Map<String, Object> vpnCustomerGatewayParameters) {
|
||||
this.vpnCustomerGatewayParameters = vpnCustomerGatewayParameters;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,14 @@ public class Site2SiteCustomerGatewayResponse extends BaseResponseWithAnnotation
|
|||
@Param(description = "Which IKE Version to use, one of ike (autoselect), IKEv1, or IKEv2. Defaults to ike")
|
||||
private String ikeVersion;
|
||||
|
||||
@SerializedName(ApiConstants.OBSOLETE_PARAMETERS)
|
||||
@Param(description = "Contains the list of obsolete/insecure cryptographic parameters that the vpn customer gateway is using.", since = "4.23.0")
|
||||
private String obsoleteParameters;
|
||||
|
||||
@SerializedName(ApiConstants.EXCLUDED_PARAMETERS)
|
||||
@Param(description = "Contains the list of excluded/not allowed cryptographic parameters that the vpn customer gateway is using.", since = "4.23.0")
|
||||
private String excludedParameters;
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
|
@ -202,4 +210,12 @@ public class Site2SiteCustomerGatewayResponse extends BaseResponseWithAnnotation
|
|||
this.domainPath = domainPath;
|
||||
}
|
||||
|
||||
public void setContainsObsoleteParameters(String obsoleteParameters) {
|
||||
this.obsoleteParameters = obsoleteParameters;
|
||||
}
|
||||
|
||||
public void setContainsExcludedParameters(String excludedParameters) {
|
||||
this.excludedParameters = excludedParameters;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,6 +136,8 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
|
|||
*/
|
||||
BackupOffering importBackupOffering(final ImportBackupOfferingCmd cmd);
|
||||
|
||||
List<Long> getBackupOfferingDomains(final Long offeringId);
|
||||
|
||||
/**
|
||||
* List backup offerings
|
||||
* @param ListBackupOfferingsCmd API cmd
|
||||
|
|
|
|||
|
|
@ -0,0 +1,149 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command.offering;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.LongFunction;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DomainAndZoneIdResolverTest {
|
||||
static class TestCmd extends BaseCmd implements DomainAndZoneIdResolver {
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
|
||||
// No implementation needed for tests
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return 1L;
|
||||
}
|
||||
}
|
||||
|
||||
private void setEntityMgr(final BaseCmd cmd, final EntityManager entityMgr) throws Exception {
|
||||
Field f = BaseCmd.class.getDeclaredField("_entityMgr");
|
||||
f.setAccessible(true);
|
||||
f.set(cmd, entityMgr);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveDomainIds_usesDefaultProviderWhenEmpty() {
|
||||
TestCmd cmd = new TestCmd();
|
||||
|
||||
final LongFunction<List<Long>> defaultsProvider = id -> Arrays.asList(100L, 200L);
|
||||
|
||||
List<Long> result = cmd.resolveDomainIds("", 42L, defaultsProvider, "offering");
|
||||
Assert.assertEquals(Arrays.asList(100L, 200L), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveDomainIds_resolvesValidUuids() throws Exception {
|
||||
TestCmd cmd = new TestCmd();
|
||||
|
||||
EntityManager em = mock(EntityManager.class);
|
||||
setEntityMgr(cmd, em);
|
||||
|
||||
Domain d1 = mock(Domain.class);
|
||||
when(d1.getId()).thenReturn(10L);
|
||||
Domain d2 = mock(Domain.class);
|
||||
when(d2.getId()).thenReturn(20L);
|
||||
|
||||
when(em.findByUuid(Domain.class, "uuid1")).thenReturn(d1);
|
||||
when(em.findByUuid(Domain.class, "uuid2")).thenReturn(d2);
|
||||
|
||||
List<Long> ids = cmd.resolveDomainIds("uuid1, public, uuid2", null, null, "template");
|
||||
Assert.assertEquals(Arrays.asList(10L, 20L), ids);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveDomainIds_invalidUuid_throws() throws Exception {
|
||||
TestCmd cmd = new TestCmd();
|
||||
|
||||
EntityManager em = mock(EntityManager.class);
|
||||
setEntityMgr(cmd, em);
|
||||
|
||||
when(em.findByUuid(Domain.class, "bad-uuid")).thenReturn(null);
|
||||
|
||||
Assert.assertThrows(InvalidParameterValueException.class,
|
||||
() -> cmd.resolveDomainIds("bad-uuid", null, null, "offering"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveZoneIds_usesDefaultProviderWhenEmpty() {
|
||||
TestCmd cmd = new TestCmd();
|
||||
|
||||
final LongFunction<List<Long>> defaultsProvider = id -> Collections.singletonList(300L);
|
||||
|
||||
List<Long> result = cmd.resolveZoneIds("", 99L, defaultsProvider, "offering");
|
||||
Assert.assertEquals(Collections.singletonList(300L), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveZoneIds_resolvesValidUuids() throws Exception {
|
||||
TestCmd cmd = new TestCmd();
|
||||
|
||||
EntityManager em = mock(EntityManager.class);
|
||||
setEntityMgr(cmd, em);
|
||||
|
||||
DataCenter z1 = mock(DataCenter.class);
|
||||
when(z1.getId()).thenReturn(30L);
|
||||
DataCenter z2 = mock(DataCenter.class);
|
||||
when(z2.getId()).thenReturn(40L);
|
||||
|
||||
when(em.findByUuid(DataCenter.class, "zone-1")).thenReturn(z1);
|
||||
when(em.findByUuid(DataCenter.class, "zone-2")).thenReturn(z2);
|
||||
|
||||
List<Long> ids = cmd.resolveZoneIds("zone-1, all, zone-2", null, null, "service");
|
||||
Assert.assertEquals(Arrays.asList(30L, 40L), ids);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveZoneIds_invalidUuid_throws() throws Exception {
|
||||
TestCmd cmd = new TestCmd();
|
||||
|
||||
EntityManager em = mock(EntityManager.class);
|
||||
setEntityMgr(cmd, em);
|
||||
|
||||
when(em.findByUuid(DataCenter.class, "bad-zone")).thenReturn(null);
|
||||
|
||||
Assert.assertThrows(InvalidParameterValueException.class,
|
||||
() -> cmd.resolveZoneIds("bad-zone", null, null, "offering"));
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,8 @@ public interface SnapshotDataFactory {
|
|||
|
||||
SnapshotInfo getSnapshot(long snapshotId, long storeId, DataStoreRole role);
|
||||
|
||||
SnapshotInfo getSnapshotIncludingRemoved(long snapshotId, long storeId, DataStoreRole role);
|
||||
|
||||
SnapshotInfo getSnapshotWithRoleAndZone(long snapshotId, DataStoreRole role, long zoneId);
|
||||
|
||||
SnapshotInfo getSnapshotOnPrimaryStore(long snapshotId);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,11 @@ public class PublicIp implements PublicIpAddress {
|
|||
}
|
||||
|
||||
public static PublicIp createFromAddrAndVlan(IPAddressVO addr, VlanVO vlan) {
|
||||
return new PublicIp(addr, vlan, NetUtils.createSequenceBasedMacAddress(addr.getMacAddress(), NetworkModel.MACIdentifier.value()));
|
||||
long macIdentifier = NetworkModel.MACIdentifier.valueIn(addr.getDataCenterId());
|
||||
if (macIdentifier == 0) {
|
||||
macIdentifier = addr.getDataCenterId();
|
||||
}
|
||||
return new PublicIp(addr, vlan, NetUtils.createSequenceBasedMacAddress(addr.getMacAddress(), macIdentifier));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -279,5 +283,4 @@ public class PublicIp implements PublicIpAddress {
|
|||
public boolean isForRouter() {
|
||||
return _addr.isForRouter();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3053,7 +3053,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
}
|
||||
|
||||
protected void migrate(final VMInstanceVO vm, final long srcHostId, final DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException {
|
||||
logger.info("Migrating {} to {}", vm, dest);
|
||||
logger.info("Start preparing migration of the VM: {} to {}", vm, dest);
|
||||
final long dstHostId = dest.getHost().getId();
|
||||
final Host fromHost = _hostDao.findById(srcHostId);
|
||||
if (fromHost == null) {
|
||||
|
|
@ -3118,9 +3118,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
if (pfma == null || !pfma.getResult()) {
|
||||
final String details = pfma != null ? pfma.getDetails() : "null answer returned";
|
||||
final String msg = "Unable to prepare for migration due to " + details;
|
||||
logger.error("Failed to prepare destination host {} for migration of VM {} : {}", dstHostId, vm.getInstanceName(), details);
|
||||
pfma = null;
|
||||
throw new AgentUnavailableException(msg, dstHostId);
|
||||
}
|
||||
logger.debug("Successfully prepared destination host {} for migration of VM {} ", dstHostId, vm.getInstanceName());
|
||||
} catch (final OperationTimedoutException e1) {
|
||||
throw new AgentUnavailableException("Operation timed out", dstHostId);
|
||||
} finally {
|
||||
|
|
@ -3141,18 +3143,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
volumeMgr.release(vm.getId(), dstHostId);
|
||||
}
|
||||
|
||||
logger.info("Migration cancelled because state has changed: {}", vm);
|
||||
throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
|
||||
String msg = "Migration cancelled because state has changed: " + vm;
|
||||
logger.warn(msg);
|
||||
throw new ConcurrentOperationException(msg);
|
||||
}
|
||||
} catch (final NoTransitionException e1) {
|
||||
_networkMgr.rollbackNicForMigration(vmSrc, profile);
|
||||
volumeMgr.release(vm.getId(), dstHostId);
|
||||
logger.info("Migration cancelled because {}", e1.getMessage());
|
||||
String msg = String.format("Migration cancelled for VM %s due to state transition failure: %s",
|
||||
vm.getInstanceName(), e1.getMessage());
|
||||
logger.warn(msg, e1);
|
||||
throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
|
||||
} catch (final CloudRuntimeException e2) {
|
||||
_networkMgr.rollbackNicForMigration(vmSrc, profile);
|
||||
volumeMgr.release(vm.getId(), dstHostId);
|
||||
logger.info("Migration cancelled because {}", e2.getMessage());
|
||||
String msg = String.format("Migration cancelled for VM %s due to runtime exception: %s",
|
||||
vm.getInstanceName(), e2.getMessage());
|
||||
logger.error(msg, e2);
|
||||
work.setStep(Step.Done);
|
||||
_workDao.update(work.getId(), work);
|
||||
try {
|
||||
|
|
@ -3172,8 +3179,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
final Answer ma = _agentMgr.send(vm.getLastHostId(), mc);
|
||||
if (ma == null || !ma.getResult()) {
|
||||
final String details = ma != null ? ma.getDetails() : "null answer returned";
|
||||
String msg = String.format("Migration command failed for VM %s on source host id=%s to destination host %s: %s",
|
||||
vm.getInstanceName(), vm.getLastHostId(), dstHostId, details);
|
||||
logger.error(msg);
|
||||
throw new CloudRuntimeException(details);
|
||||
}
|
||||
logger.info("Migration command successful for VM {}", vm.getInstanceName());
|
||||
} catch (final OperationTimedoutException e) {
|
||||
boolean success = false;
|
||||
if (HypervisorType.KVM.equals(vm.getHypervisorType())) {
|
||||
|
|
@ -3210,7 +3221,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
|
||||
try {
|
||||
if (!checkVmOnHost(vm, dstHostId)) {
|
||||
logger.error("Unable to complete migration for {}", vm);
|
||||
logger.error("Migration verification failed for VM {} : VM not found on destination host {} ", vm.getInstanceName(), dstHostId);
|
||||
try {
|
||||
_agentMgr.send(srcHostId, new Commands(cleanup(vm, dpdkInterfaceMapping)), null);
|
||||
} catch (final AgentUnavailableException e) {
|
||||
|
|
@ -3225,7 +3236,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
migrated = true;
|
||||
} finally {
|
||||
if (!migrated) {
|
||||
logger.info("Migration was unsuccessful. Cleaning up: {}", vm);
|
||||
logger.info("Migration was unsuccessful. Cleaning up: {}", vm);
|
||||
_networkMgr.rollbackNicForMigration(vmSrc, profile);
|
||||
volumeMgr.release(vm.getId(), dstHostId);
|
||||
// deallocate GPU devices for the VM on the destination host
|
||||
|
|
@ -3237,7 +3248,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
try {
|
||||
_agentMgr.send(dstHostId, new Commands(cleanup(vm, dpdkInterfaceMapping)), null);
|
||||
} catch (final AgentUnavailableException ae) {
|
||||
logger.warn("Looks like the destination Host is unavailable for cleanup", ae);
|
||||
logger.warn("Destination host {} unavailable for cleanup after failed migration of VM {}", dstHostId, vm.getInstanceName(), ae);
|
||||
}
|
||||
_networkMgr.setHypervisorHostname(profile, dest, false);
|
||||
try {
|
||||
|
|
@ -3246,6 +3257,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
logger.warn(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
logger.info("Migration completed successfully for VM %s" + vm);
|
||||
_networkMgr.commitNicForMigration(vmSrc, profile);
|
||||
volumeMgr.release(vm.getId(), srcHostId);
|
||||
// deallocate GPU devices for the VM on the src host after migration is complete
|
||||
|
|
@ -3276,6 +3288,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
migrateCommand.setVlanToPersistenceMap(vlanToPersistenceMap);
|
||||
}
|
||||
|
||||
logger.debug("Setting auto convergence to: {}", StorageManager.KvmAutoConvergence.value());
|
||||
migrateCommand.setAutoConvergence(StorageManager.KvmAutoConvergence.value());
|
||||
migrateCommand.setHostGuid(destination.getHost().getGuid());
|
||||
|
||||
|
|
|
|||
|
|
@ -1283,7 +1283,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
nicProfile.setIPv4Gateway(ipv4Gateway);
|
||||
nicProfile.setIPv4Netmask(ipv4Netmask);
|
||||
|
||||
if (nicProfile.getMacAddress() == null) {
|
||||
if (nicProfile.getMacAddress() == null || !_networkModel.isMACUnique(nicProfile.getMacAddress(), network.getId())) {
|
||||
try {
|
||||
String macAddress = _networkModel.getNextAvailableMacAddressInNetwork(network.getId());
|
||||
nicProfile.setMacAddress(macAddress);
|
||||
|
|
|
|||
|
|
@ -396,6 +396,7 @@ public class NetworkOrchestratorTest extends TestCase {
|
|||
when(testOrchestrator._ipAddressDao.acquireInLockTable(Mockito.anyLong())).thenReturn(ipVoSpy);
|
||||
when(testOrchestrator._ipAddressDao.update(Mockito.anyLong(), Mockito.any(IPAddressVO.class))).thenReturn(true);
|
||||
when(testOrchestrator._ipAddressDao.releaseFromLockTable(Mockito.anyLong())).thenReturn(true);
|
||||
when(testOrchestrator._networkModel.isMACUnique(Mockito.anyString(), Mockito.anyLong())).thenReturn(true);
|
||||
try {
|
||||
when(testOrchestrator._networkModel.getNextAvailableMacAddressInNetwork(Mockito.anyLong())).thenReturn(macAddress);
|
||||
} catch (InsufficientAddressCapacityException e) {
|
||||
|
|
|
|||
|
|
@ -462,8 +462,8 @@ public class NetworkDaoImpl extends GenericDaoBase<NetworkVO, Long>implements Ne
|
|||
public String getNextAvailableMacAddress(final long networkConfigId, Integer zoneMacIdentifier) {
|
||||
final SequenceFetcher fetch = SequenceFetcher.getInstance();
|
||||
long seq = fetch.getNextSequence(Long.class, _tgMacAddress, networkConfigId);
|
||||
if(zoneMacIdentifier != null && zoneMacIdentifier.intValue() != 0 ){
|
||||
seq = seq | _prefix << 40 | (long)zoneMacIdentifier << 32 | networkConfigId << 16 & 0x00000000ffff0000l;
|
||||
if (zoneMacIdentifier != null && zoneMacIdentifier != 0) {
|
||||
seq = seq | _prefix << 40 | (long)zoneMacIdentifier << 32 | networkConfigId << 16 & 0x00000000ffff0000L;
|
||||
}
|
||||
return NetUtils.long2Mac(seq);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ public interface SnapshotDao extends GenericDao<SnapshotVO, Long>, StateDao<Snap
|
|||
|
||||
List<SnapshotVO> listAllByStatus(Snapshot.State... status);
|
||||
|
||||
List<SnapshotVO> listAllByStatusIncludingRemoved(Snapshot.State... status);
|
||||
|
||||
void updateVolumeIds(long oldVolId, long newVolId);
|
||||
|
||||
List<SnapshotVO> listByStatusNotIn(long volumeId, Snapshot.State... status);
|
||||
|
|
|
|||
|
|
@ -265,6 +265,13 @@ public class SnapshotDaoImpl extends GenericDaoBase<SnapshotVO, Long> implements
|
|||
return listBy(sc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotVO> listAllByStatusIncludingRemoved(Snapshot.State... status) {
|
||||
SearchCriteria<SnapshotVO> sc = StatusSearch.create();
|
||||
sc.setParameters("status", (Object[])status);
|
||||
return listIncludingRemovedBy(sc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotVO> listByIds(Object... ids) {
|
||||
SearchCriteria<SnapshotVO> sc = snapshotIdsSearch.create();
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
private static final String DELETE_ALL = "DELETE FROM cloud_usage";
|
||||
private static final String DELETE_ALL_BY_ACCOUNTID = "DELETE FROM cloud_usage WHERE account_id = ?";
|
||||
private static final String DELETE_ALL_BY_INTERVAL = "DELETE FROM cloud_usage WHERE end_date < DATE_SUB(CURRENT_DATE(), INTERVAL ? DAY)";
|
||||
private static final String INSERT_ACCOUNT = "INSERT INTO cloud_usage.account (id, account_name, type, role_id, domain_id, removed, cleanup_needed) VALUES (?,?,?,?,?,?,?)";
|
||||
private static final String INSERT_ACCOUNT = "INSERT INTO cloud_usage.account (id, account_name, uuid, type, role_id, domain_id, removed, cleanup_needed) VALUES (?,?,?,?,?,?,?,?)";
|
||||
private static final String INSERT_USER_STATS = "INSERT INTO cloud_usage.user_statistics (id, data_center_id, account_id, public_ip_address, device_id, device_type, network_id, net_bytes_received,"
|
||||
+ " net_bytes_sent, current_bytes_received, current_bytes_sent, agg_bytes_received, agg_bytes_sent) VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?)";
|
||||
|
||||
|
|
@ -129,25 +129,26 @@ public class UsageDaoImpl extends GenericDaoBase<UsageVO, Long> implements Usage
|
|||
for (AccountVO acct : accounts) {
|
||||
pstmt.setLong(1, acct.getId());
|
||||
pstmt.setString(2, acct.getAccountName());
|
||||
pstmt.setInt(3, acct.getType().ordinal());
|
||||
pstmt.setString(3, acct.getUuid());
|
||||
pstmt.setInt(4, acct.getType().ordinal());
|
||||
|
||||
//prevent autoboxing NPE by defaulting to User role
|
||||
if(acct.getRoleId() == null){
|
||||
pstmt.setLong(4, RoleType.User.getId());
|
||||
pstmt.setLong(5, RoleType.User.getId());
|
||||
}else{
|
||||
pstmt.setLong(4, acct.getRoleId());
|
||||
pstmt.setLong(5, acct.getRoleId());
|
||||
}
|
||||
|
||||
pstmt.setLong(5, acct.getDomainId());
|
||||
pstmt.setLong(6, acct.getDomainId());
|
||||
|
||||
Date removed = acct.getRemoved();
|
||||
if (removed == null) {
|
||||
pstmt.setString(6, null);
|
||||
pstmt.setString(7, null);
|
||||
} else {
|
||||
pstmt.setString(6, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), acct.getRemoved()));
|
||||
pstmt.setString(7, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), acct.getRemoved()));
|
||||
}
|
||||
|
||||
pstmt.setBoolean(7, acct.getNeedsCleanup());
|
||||
pstmt.setBoolean(8, acct.getNeedsCleanup());
|
||||
|
||||
pstmt.addBatch();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ public interface NicDao extends GenericDao<NicVO, Long> {
|
|||
|
||||
List<NicVO> listByVmIdAndKeyword(long instanceId, String keyword);
|
||||
|
||||
NicVO findByMacAddress(String macAddress);
|
||||
NicVO findByMacAddress(String macAddress, long networkId);
|
||||
|
||||
NicVO findByNetworkIdAndMacAddressIncludingRemoved(long networkId, String mac);
|
||||
|
||||
|
|
|
|||
|
|
@ -420,9 +420,10 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
|
|||
}
|
||||
|
||||
@Override
|
||||
public NicVO findByMacAddress(String macAddress) {
|
||||
public NicVO findByMacAddress(String macAddress, long networkId) {
|
||||
SearchCriteria<NicVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("macAddress", macAddress);
|
||||
sc.setParameters("network", networkId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
// 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.backup;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.cloudstack.api.ResourceDetail;
|
||||
|
||||
@Entity
|
||||
@Table(name = "backup_offering_details")
|
||||
public class BackupOfferingDetailsVO implements ResourceDetail {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private long id;
|
||||
|
||||
@Column(name = "backup_offering_id")
|
||||
private long resourceId;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "value")
|
||||
private String value;
|
||||
|
||||
@Column(name = "display")
|
||||
private boolean display = true;
|
||||
|
||||
protected BackupOfferingDetailsVO() {
|
||||
}
|
||||
|
||||
public BackupOfferingDetailsVO(long backupOfferingId, String name, String value, boolean display) {
|
||||
this.resourceId = backupOfferingId;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public void setResourceId(long backupOfferingId) {
|
||||
this.resourceId = backupOfferingId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
return display;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.apache.cloudstack.backup;
|
||||
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -131,4 +133,9 @@ public class BackupOfferingVO implements BackupOffering {
|
|||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Backup offering %s.", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "name", "uuid"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ package org.apache.cloudstack.backup.dao;
|
|||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import org.apache.cloudstack.api.response.BackupOfferingResponse;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.backup.BackupOfferingVO;
|
||||
|
|
@ -30,10 +32,16 @@ import com.cloud.utils.db.GenericDaoBase;
|
|||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BackupOfferingDaoImpl extends GenericDaoBase<BackupOfferingVO, Long> implements BackupOfferingDao {
|
||||
|
||||
@Inject
|
||||
DataCenterDao dataCenterDao;
|
||||
@Inject
|
||||
BackupOfferingDetailsDao backupOfferingDetailsDao;
|
||||
@Inject
|
||||
DomainDao domainDao;
|
||||
|
||||
private SearchBuilder<BackupOfferingVO> backupPoliciesSearch;
|
||||
|
||||
|
|
@ -51,8 +59,9 @@ public class BackupOfferingDaoImpl extends GenericDaoBase<BackupOfferingVO, Long
|
|||
|
||||
@Override
|
||||
public BackupOfferingResponse newBackupOfferingResponse(BackupOffering offering, Boolean crossZoneInstanceCreation) {
|
||||
DataCenterVO zone = dataCenterDao.findById(offering.getZoneId());
|
||||
|
||||
DataCenterVO zone = dataCenterDao.findById(offering.getZoneId());
|
||||
List<Long> domainIds = backupOfferingDetailsDao.findDomainIds(offering.getId());
|
||||
BackupOfferingResponse response = new BackupOfferingResponse();
|
||||
response.setId(offering.getUuid());
|
||||
response.setName(offering.getName());
|
||||
|
|
@ -64,6 +73,18 @@ public class BackupOfferingDaoImpl extends GenericDaoBase<BackupOfferingVO, Long
|
|||
response.setZoneId(zone.getUuid());
|
||||
response.setZoneName(zone.getName());
|
||||
}
|
||||
if (domainIds != null && !domainIds.isEmpty()) {
|
||||
String domainUUIDs = domainIds.stream().map(Long::valueOf).map(domainId -> {
|
||||
DomainVO domain = domainDao.findById(domainId);
|
||||
return domain != null ? domain.getUuid() : "";
|
||||
}).filter(name -> !name.isEmpty()).reduce((a, b) -> a + "," + b).orElse("");
|
||||
String domainNames = domainIds.stream().map(Long::valueOf).map(domainId -> {
|
||||
DomainVO domain = domainDao.findById(domainId);
|
||||
return domain != null ? domain.getName() : "";
|
||||
}).filter(name -> !name.isEmpty()).reduce((a, b) -> a + "," + b).orElse("");
|
||||
response.setDomain(domainNames);
|
||||
response.setDomainId(domainUUIDs);
|
||||
}
|
||||
if (crossZoneInstanceCreation) {
|
||||
response.setCrossZoneInstanceCreation(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
// 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.backup.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.backup.BackupOfferingDetailsVO;
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface BackupOfferingDetailsDao extends GenericDao<BackupOfferingDetailsVO, Long>, ResourceDetailsDao<BackupOfferingDetailsVO> {
|
||||
List<Long> findDomainIds(final long resourceId);
|
||||
List<Long> findZoneIds(final long resourceId);
|
||||
String getDetail(Long backupOfferingId, String key);
|
||||
List<Long> findOfferingIdsByDomainIds(List<Long> domainIds);
|
||||
void updateBackupOfferingDomainIdsDetail(long backupOfferingId, List<Long> filteredDomainIds);
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// 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.backup.dao;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.backup.BackupOfferingDetailsVO;
|
||||
import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class BackupOfferingDetailsDaoImpl extends ResourceDetailsDaoBase<BackupOfferingDetailsVO> implements BackupOfferingDetailsDao {
|
||||
|
||||
@Override
|
||||
public void addDetail(long resourceId, String key, String value, boolean display) {
|
||||
super.addDetail(new BackupOfferingDetailsVO(resourceId, key, value, display));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> findDomainIds(long resourceId) {
|
||||
final List<Long> domainIds = new ArrayList<>();
|
||||
for (final BackupOfferingDetailsVO detail: findDetails(resourceId, ApiConstants.DOMAIN_ID)) {
|
||||
final Long domainId = Long.valueOf(detail.getValue());
|
||||
if (domainId > 0) {
|
||||
domainIds.add(domainId);
|
||||
}
|
||||
}
|
||||
return domainIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> findZoneIds(long resourceId) {
|
||||
final List<Long> zoneIds = new ArrayList<>();
|
||||
for (final BackupOfferingDetailsVO detail: findDetails(resourceId, ApiConstants.ZONE_ID)) {
|
||||
final Long zoneId = Long.valueOf(detail.getValue());
|
||||
if (zoneId > 0) {
|
||||
zoneIds.add(zoneId);
|
||||
}
|
||||
}
|
||||
return zoneIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetail(Long backupOfferingId, String key) {
|
||||
String detailValue = null;
|
||||
BackupOfferingDetailsVO backupOfferingDetail = findDetail(backupOfferingId, key);
|
||||
if (backupOfferingDetail != null) {
|
||||
detailValue = backupOfferingDetail.getValue();
|
||||
}
|
||||
return detailValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> findOfferingIdsByDomainIds(List<Long> domainIds) {
|
||||
Object[] dIds = domainIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList()).toArray();
|
||||
return findResourceIdsByNameAndValueIn("domainid", dIds);
|
||||
}
|
||||
|
||||
@DB
|
||||
@Override
|
||||
public void updateBackupOfferingDomainIdsDetail(long backupOfferingId, List<Long> filteredDomainIds) {
|
||||
SearchBuilder<BackupOfferingDetailsVO> sb = createSearchBuilder();
|
||||
List<BackupOfferingDetailsVO> detailsVO = new ArrayList<>();
|
||||
sb.and("offeringId", sb.entity().getResourceId(), SearchCriteria.Op.EQ);
|
||||
sb.and("detailName", sb.entity().getName(), SearchCriteria.Op.EQ);
|
||||
sb.done();
|
||||
SearchCriteria<BackupOfferingDetailsVO> sc = sb.create();
|
||||
sc.setParameters("offeringId", String.valueOf(backupOfferingId));
|
||||
sc.setParameters("detailName", ApiConstants.DOMAIN_ID);
|
||||
remove(sc);
|
||||
for (Long domainId : filteredDomainIds) {
|
||||
detailsVO.add(new BackupOfferingDetailsVO(backupOfferingId, ApiConstants.DOMAIN_ID, String.valueOf(domainId), false));
|
||||
}
|
||||
if (!detailsVO.isEmpty()) {
|
||||
for (BackupOfferingDetailsVO detailVO : detailsVO) {
|
||||
persist(detailVO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -76,6 +76,8 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
|
|||
|
||||
List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId);
|
||||
|
||||
List<SnapshotDataStoreVO> findBySnapshotIdWithNonDestroyedState(long snapshotId);
|
||||
|
||||
void duplicateCacheRecordsOnRegionStore(long storeId);
|
||||
|
||||
// delete the snapshot entry on primary data store to make sure that next snapshot will be full snapshot
|
||||
|
|
|
|||
|
|
@ -464,6 +464,13 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
|
|||
|
||||
@Override
|
||||
public List<SnapshotDataStoreVO> findBySnapshotId(long snapshotId) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = searchFilteringStoreIdEqStateEqStoreRoleEqIdEqUpdateCountEqSnapshotIdEqVolumeIdEq.create();
|
||||
sc.setParameters(SNAPSHOT_ID, snapshotId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotDataStoreVO> findBySnapshotIdWithNonDestroyedState(long snapshotId) {
|
||||
SearchCriteria<SnapshotDataStoreVO> sc = idStateNinSearch.create();
|
||||
sc.setParameters(SNAPSHOT_ID, snapshotId);
|
||||
sc.setParameters(STATE, State.Destroyed.name());
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
<bean id="NetworkDaoImpl" class="org.apache.cloudstack.quota.dao.NetworkDaoImpl" />
|
||||
<bean id="VpcDaoImpl" class="org.apache.cloudstack.quota.dao.VpcDaoImpl" />
|
||||
<bean id="volumeDaoImpl" class="com.cloud.storage.dao.VolumeDaoImpl" />
|
||||
<bean id="reservationDao" class="org.apache.cloudstack.reservation.dao.ReservationDaoImpl" />
|
||||
<bean id="reservationDao" class="org.apache.cloudstack.reservation.dao.ReservationDaoImpl" />
|
||||
<bean id="backupOfferingDaoImpl" class="org.apache.cloudstack.backup.dao.BackupOfferingDaoImpl" />
|
||||
<bean id="backupOfferingDetailsDaoImpl" class="org.apache.cloudstack.backup.dao.BackupOfferingDetailsDaoImpl" />
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,16 @@
|
|||
-- Schema upgrade from 4.22.1.0 to 4.23.0.0
|
||||
--;
|
||||
|
||||
CREATE TABLE `cloud`.`backup_offering_details` (
|
||||
`id` bigint unsigned NOT NULL auto_increment,
|
||||
`backup_offering_id` bigint unsigned NOT NULL COMMENT 'Backup offering id',
|
||||
`name` varchar(255) NOT NULL,
|
||||
`value` varchar(1024) NOT NULL,
|
||||
`display` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Should detail be displayed to the end user',
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `fk_offering_details__backup_offering_id` FOREIGN KEY `fk_offering_details__backup_offering_id`(`backup_offering_id`) REFERENCES `backup_offering`(`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Update value to random for the config 'vm.allocation.algorithm' or 'volume.allocation.algorithm' if configured as userconcentratedpod_random
|
||||
-- Update value to firstfit for the config 'vm.allocation.algorithm' or 'volume.allocation.algorithm' if configured as userconcentratedpod_firstfit
|
||||
UPDATE `cloud`.`configuration` SET value='random' WHERE name IN ('vm.allocation.algorithm', 'volume.allocation.algorithm') AND value='userconcentratedpod_random';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,251 @@
|
|||
// 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.backup.dao;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.backup.BackupOfferingDetailsVO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BackupOfferingDetailsDaoImplTest {
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
private BackupOfferingDetailsDaoImpl backupOfferingDetailsDao;
|
||||
|
||||
private static final long RESOURCE_ID = 1L;
|
||||
private static final long OFFERING_ID = 100L;
|
||||
private static final String TEST_KEY = "testKey";
|
||||
private static final String TEST_VALUE = "testValue";
|
||||
|
||||
@Test
|
||||
public void testAddDetail() {
|
||||
BackupOfferingDetailsVO detailVO = new BackupOfferingDetailsVO(RESOURCE_ID, TEST_KEY, TEST_VALUE, true);
|
||||
|
||||
Assert.assertEquals("Resource ID should match", RESOURCE_ID, detailVO.getResourceId());
|
||||
Assert.assertEquals("Detail name/key should match", TEST_KEY, detailVO.getName());
|
||||
Assert.assertEquals("Detail value should match", TEST_VALUE, detailVO.getValue());
|
||||
Assert.assertTrue("Display flag should be true", detailVO.isDisplay());
|
||||
|
||||
BackupOfferingDetailsVO detailVOHidden = new BackupOfferingDetailsVO(RESOURCE_ID, "hiddenKey", "hiddenValue", false);
|
||||
Assert.assertFalse("Display flag should be false", detailVOHidden.isDisplay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindDomainIdsWithMultipleDomains() {
|
||||
List<BackupOfferingDetailsVO> mockDetails = Arrays.asList(
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.DOMAIN_ID, "1", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.DOMAIN_ID, "2", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.DOMAIN_ID, "3", false)
|
||||
);
|
||||
|
||||
Mockito.doReturn(mockDetails).when(backupOfferingDetailsDao)
|
||||
.findDetails(RESOURCE_ID, ApiConstants.DOMAIN_ID);
|
||||
|
||||
List<Long> domainIds = backupOfferingDetailsDao.findDomainIds(RESOURCE_ID);
|
||||
|
||||
Assert.assertNotNull(domainIds);
|
||||
Assert.assertEquals(3, domainIds.size());
|
||||
Assert.assertEquals(Arrays.asList(1L, 2L, 3L), domainIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindDomainIdsWithEmptyList() {
|
||||
Mockito.doReturn(Collections.emptyList()).when(backupOfferingDetailsDao)
|
||||
.findDetails(RESOURCE_ID, ApiConstants.DOMAIN_ID);
|
||||
|
||||
List<Long> domainIds = backupOfferingDetailsDao.findDomainIds(RESOURCE_ID);
|
||||
|
||||
Assert.assertNotNull(domainIds);
|
||||
Assert.assertTrue(domainIds.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindDomainIdsExcludesZeroOrNegativeValues() {
|
||||
List<BackupOfferingDetailsVO> mockDetails = Arrays.asList(
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.DOMAIN_ID, "1", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.DOMAIN_ID, "0", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.DOMAIN_ID, "-1", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.DOMAIN_ID, "2", false)
|
||||
);
|
||||
|
||||
Mockito.doReturn(mockDetails).when(backupOfferingDetailsDao)
|
||||
.findDetails(RESOURCE_ID, ApiConstants.DOMAIN_ID);
|
||||
|
||||
List<Long> domainIds = backupOfferingDetailsDao.findDomainIds(RESOURCE_ID);
|
||||
|
||||
Assert.assertNotNull(domainIds);
|
||||
Assert.assertEquals(2, domainIds.size());
|
||||
Assert.assertEquals(Arrays.asList(1L, 2L), domainIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindZoneIdsWithMultipleZones() {
|
||||
List<BackupOfferingDetailsVO> mockDetails = Arrays.asList(
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.ZONE_ID, "10", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.ZONE_ID, "20", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.ZONE_ID, "30", false)
|
||||
);
|
||||
|
||||
Mockito.doReturn(mockDetails).when(backupOfferingDetailsDao)
|
||||
.findDetails(RESOURCE_ID, ApiConstants.ZONE_ID);
|
||||
|
||||
List<Long> zoneIds = backupOfferingDetailsDao.findZoneIds(RESOURCE_ID);
|
||||
|
||||
Assert.assertNotNull(zoneIds);
|
||||
Assert.assertEquals(3, zoneIds.size());
|
||||
Assert.assertEquals(Arrays.asList(10L, 20L, 30L), zoneIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindZoneIdsWithEmptyList() {
|
||||
Mockito.doReturn(Collections.emptyList()).when(backupOfferingDetailsDao)
|
||||
.findDetails(RESOURCE_ID, ApiConstants.ZONE_ID);
|
||||
|
||||
List<Long> zoneIds = backupOfferingDetailsDao.findZoneIds(RESOURCE_ID);
|
||||
|
||||
Assert.assertNotNull(zoneIds);
|
||||
Assert.assertTrue(zoneIds.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindZoneIdsExcludesZeroOrNegativeValues() {
|
||||
List<BackupOfferingDetailsVO> mockDetails = Arrays.asList(
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.ZONE_ID, "10", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.ZONE_ID, "0", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.ZONE_ID, "-5", false),
|
||||
createDetailVO(RESOURCE_ID, ApiConstants.ZONE_ID, "20", false)
|
||||
);
|
||||
|
||||
Mockito.doReturn(mockDetails).when(backupOfferingDetailsDao)
|
||||
.findDetails(RESOURCE_ID, ApiConstants.ZONE_ID);
|
||||
|
||||
List<Long> zoneIds = backupOfferingDetailsDao.findZoneIds(RESOURCE_ID);
|
||||
|
||||
Assert.assertNotNull(zoneIds);
|
||||
Assert.assertEquals(2, zoneIds.size());
|
||||
Assert.assertEquals(Arrays.asList(10L, 20L), zoneIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDetailWhenDetailExists() {
|
||||
BackupOfferingDetailsVO mockDetail = createDetailVO(OFFERING_ID, TEST_KEY, TEST_VALUE, true);
|
||||
|
||||
Mockito.doReturn(mockDetail).when(backupOfferingDetailsDao)
|
||||
.findDetail(OFFERING_ID, TEST_KEY);
|
||||
|
||||
String detailValue = backupOfferingDetailsDao.getDetail(OFFERING_ID, TEST_KEY);
|
||||
|
||||
Assert.assertNotNull(detailValue);
|
||||
Assert.assertEquals(TEST_VALUE, detailValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDetailWhenDetailDoesNotExist() {
|
||||
Mockito.doReturn(null).when(backupOfferingDetailsDao)
|
||||
.findDetail(OFFERING_ID, TEST_KEY);
|
||||
|
||||
String detailValue = backupOfferingDetailsDao.getDetail(OFFERING_ID, TEST_KEY);
|
||||
|
||||
Assert.assertNull(detailValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOfferingIdsByDomainIds() {
|
||||
List<Long> domainIds = Arrays.asList(1L, 2L, 3L);
|
||||
List<Long> expectedOfferingIds = Arrays.asList(100L, 101L, 102L);
|
||||
|
||||
Mockito.doReturn(expectedOfferingIds).when(backupOfferingDetailsDao)
|
||||
.findResourceIdsByNameAndValueIn(Mockito.eq("domainid"), Mockito.any(Object[].class));
|
||||
|
||||
List<Long> offeringIds = backupOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds);
|
||||
|
||||
Assert.assertNotNull(offeringIds);
|
||||
Assert.assertEquals(expectedOfferingIds, offeringIds);
|
||||
Mockito.verify(backupOfferingDetailsDao).findResourceIdsByNameAndValueIn(
|
||||
Mockito.eq("domainid"), Mockito.any(Object[].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOfferingIdsByDomainIdsWithEmptyList() {
|
||||
List<Long> domainIds = Collections.emptyList();
|
||||
List<Long> expectedOfferingIds = Collections.emptyList();
|
||||
|
||||
Mockito.doReturn(expectedOfferingIds).when(backupOfferingDetailsDao)
|
||||
.findResourceIdsByNameAndValueIn(Mockito.eq("domainid"), Mockito.any(Object[].class));
|
||||
|
||||
List<Long> offeringIds = backupOfferingDetailsDao.findOfferingIdsByDomainIds(domainIds);
|
||||
|
||||
Assert.assertNotNull(offeringIds);
|
||||
Assert.assertTrue(offeringIds.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUpdateBackupOfferingDomainIdsDetail() {
|
||||
List<Long> newDomainIds = Arrays.asList(1L, 2L, 3L);
|
||||
|
||||
Mockito.doReturn(0).when(backupOfferingDetailsDao).remove(Mockito.any(SearchCriteria.class));
|
||||
Mockito.doReturn(null).when(backupOfferingDetailsDao).persist(Mockito.any(BackupOfferingDetailsVO.class));
|
||||
|
||||
backupOfferingDetailsDao.updateBackupOfferingDomainIdsDetail(OFFERING_ID, newDomainIds);
|
||||
|
||||
Mockito.verify(backupOfferingDetailsDao, Mockito.times(3)).persist(Mockito.any(BackupOfferingDetailsVO.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUpdateBackupOfferingDomainIdsDetailWithEmptyList() {
|
||||
List<Long> emptyDomainIds = Collections.emptyList();
|
||||
|
||||
Mockito.doReturn(0).when(backupOfferingDetailsDao).remove(Mockito.any(SearchCriteria.class));
|
||||
|
||||
backupOfferingDetailsDao.updateBackupOfferingDomainIdsDetail(OFFERING_ID, emptyDomainIds);
|
||||
|
||||
Mockito.verify(backupOfferingDetailsDao, Mockito.never()).persist(Mockito.any(BackupOfferingDetailsVO.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testUpdateBackupOfferingDomainIdsDetailWithSingleDomain() {
|
||||
List<Long> singleDomainId = Collections.singletonList(5L);
|
||||
|
||||
Mockito.doReturn(0).when(backupOfferingDetailsDao).remove(Mockito.any(SearchCriteria.class));
|
||||
Mockito.doReturn(null).when(backupOfferingDetailsDao).persist(Mockito.any(BackupOfferingDetailsVO.class));
|
||||
|
||||
backupOfferingDetailsDao.updateBackupOfferingDomainIdsDetail(OFFERING_ID, singleDomainId);
|
||||
|
||||
Mockito.verify(backupOfferingDetailsDao, Mockito.times(1)).persist(Mockito.any(BackupOfferingDetailsVO.class));
|
||||
}
|
||||
|
||||
private BackupOfferingDetailsVO createDetailVO(long resourceId, String name, String value, boolean display) {
|
||||
return new BackupOfferingDetailsVO(resourceId, name, value, display);
|
||||
}
|
||||
}
|
||||
|
|
@ -303,7 +303,7 @@ public class DefaultSnapshotStrategy extends SnapshotStrategyBase {
|
|||
}
|
||||
|
||||
if (Snapshot.State.Error.equals(snapshotVO.getState())) {
|
||||
List<SnapshotDataStoreVO> storeRefs = snapshotStoreDao.findBySnapshotId(snapshotId);
|
||||
List<SnapshotDataStoreVO> storeRefs = snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
|
||||
List<Long> deletedRefs = new ArrayList<>();
|
||||
for (SnapshotDataStoreVO ref : storeRefs) {
|
||||
boolean refZoneIdMatch = false;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
|
|||
if (snapshot == null) { //snapshot may have been removed;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<SnapshotDataStoreVO> allSnapshotsAndDataStore = snapshotStoreDao.findBySnapshotId(snapshotId);
|
||||
List<SnapshotDataStoreVO> allSnapshotsAndDataStore = snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
|
||||
if (CollectionUtils.isEmpty(allSnapshotsAndDataStore)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
|
@ -118,7 +118,23 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
|
|||
if (snapshot == null) {
|
||||
return null;
|
||||
}
|
||||
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(role, storeId, snapshotId);
|
||||
return getSnapshotOnStore(snapshot, storeId, role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SnapshotInfo getSnapshotIncludingRemoved(long snapshotId, long storeId, DataStoreRole role) {
|
||||
SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId);
|
||||
if (snapshot == null) {
|
||||
return null;
|
||||
}
|
||||
return getSnapshotOnStore(snapshot, storeId, role);
|
||||
}
|
||||
|
||||
private SnapshotInfo getSnapshotOnStore(SnapshotVO snapshot, long storeId, DataStoreRole role) {
|
||||
if (snapshot == null) {
|
||||
return null;
|
||||
}
|
||||
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findByStoreSnapshot(role, storeId, snapshot.getId());
|
||||
if (snapshotStore == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -207,7 +223,7 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
|
|||
|
||||
@Override
|
||||
public void updateOperationFailed(long snapshotId) throws NoTransitionException {
|
||||
List<SnapshotDataStoreVO> snapshotStoreRefs = snapshotStoreDao.findBySnapshotId(snapshotId);
|
||||
List<SnapshotDataStoreVO> snapshotStoreRefs = snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
|
||||
for (SnapshotDataStoreVO snapshotStoreRef : snapshotStoreRefs) {
|
||||
SnapshotInfo snapshotInfo = getSnapshot(snapshotStoreRef.getSnapshotId(), snapshotStoreRef.getDataStoreId(), snapshotStoreRef.getRole());
|
||||
if (snapshotInfo != null) {
|
||||
|
|
|
|||
|
|
@ -474,8 +474,7 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
if (res.isFailed()) {
|
||||
throw new CloudRuntimeException(res.getResult());
|
||||
}
|
||||
SnapshotInfo destSnapshot = res.getSnapshot();
|
||||
return destSnapshot;
|
||||
return res.getSnapshot();
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("failed copy snapshot", e);
|
||||
throw new CloudRuntimeException("Failed to copy snapshot", e);
|
||||
|
|
@ -483,7 +482,6 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
logger.debug("Failed to copy snapshot", e);
|
||||
throw new CloudRuntimeException("Failed to copy snapshot", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CopyCommandResult> callback, CopySnapshotContext<CommandResult> context) {
|
||||
|
|
@ -571,7 +569,6 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
}
|
||||
|
||||
protected Void deleteSnapshotCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> callback, DeleteSnapshotContext<CommandResult> context) {
|
||||
|
||||
CommandResult result = callback.getResult();
|
||||
AsyncCallFuture<SnapshotResult> future = context.future;
|
||||
SnapshotInfo snapshot = context.snapshot;
|
||||
|
|
@ -729,7 +726,7 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
|
||||
if (snapshot != null) {
|
||||
if (snapshot.getState() != Snapshot.State.BackedUp) {
|
||||
List<SnapshotDataStoreVO> snapshotDataStoreVOs = _snapshotStoreDao.findBySnapshotId(snapshotId);
|
||||
List<SnapshotDataStoreVO> snapshotDataStoreVOs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
|
||||
for (SnapshotDataStoreVO snapshotDataStoreVO : snapshotDataStoreVOs) {
|
||||
logger.debug("Remove snapshot {}, status {} on snapshot_store_ref table with id: {}", snapshot, snapshotDataStoreVO.getState(), snapshotDataStoreVO.getId());
|
||||
|
||||
|
|
@ -834,7 +831,6 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
SnapshotObject srcSnapshot = (SnapshotObject)snapshot;
|
||||
srcSnapshot.processEvent(Event.DestroyRequested);
|
||||
srcSnapshot.processEvent(Event.OperationSucceeded);
|
||||
|
||||
srcSnapshot.processEvent(Snapshot.Event.OperationFailed);
|
||||
|
||||
_snapshotDetailsDao.removeDetail(srcSnapshot.getId(), AsyncJob.Constants.MS_ID);
|
||||
|
|
@ -845,7 +841,6 @@ public class SnapshotServiceImpl implements SnapshotService {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -541,7 +541,6 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
|||
logger.warn("Failed to clean up snapshot '" + snapshot.getId() + "' on primary storage: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private VMSnapshot takeHypervisorSnapshot(VolumeInfo volumeInfo) {
|
||||
|
|
|
|||
|
|
@ -109,6 +109,9 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
|
|||
stateMachines.addTransition(State.Destroying, Event.DestroyRequested, State.Destroying);
|
||||
stateMachines.addTransition(State.Destroying, Event.OperationSucceeded, State.Destroyed);
|
||||
stateMachines.addTransition(State.Destroying, Event.OperationFailed, State.Destroying);
|
||||
stateMachines.addTransition(State.Destroyed, Event.DestroyRequested, State.Destroyed);
|
||||
stateMachines.addTransition(State.Destroyed, Event.OperationSucceeded, State.Destroyed);
|
||||
stateMachines.addTransition(State.Destroyed, Event.OperationFailed, State.Destroyed);
|
||||
stateMachines.addTransition(State.Failed, Event.DestroyRequested, State.Destroying);
|
||||
// TODO: further investigate why an extra event is sent when it is
|
||||
// already Ready for DownloadListener
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public class ConfigKeyScheduledExecutionWrapper implements Runnable {
|
|||
this.unit = unit;
|
||||
}
|
||||
|
||||
protected ConfigKeyScheduledExecutionWrapper(ScheduledExecutorService executorService, Runnable command,
|
||||
public ConfigKeyScheduledExecutionWrapper(ScheduledExecutorService executorService, Runnable command,
|
||||
ConfigKey<?> configKey, int enableIntervalSeconds, TimeUnit unit) {
|
||||
validateArgs(executorService, command, configKey);
|
||||
this.executorService = executorService;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,31 @@
|
|||
<artifactId>java-linstor</artifactId>
|
||||
<version>${cs.java-linstor.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${cs.jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${cs.jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${cs.jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${cs.jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-jaxb-annotations</artifactId>
|
||||
<version>${cs.jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
final String target = command.getDestinationIp();
|
||||
xmlDesc = dm.getXMLDesc(xmlFlag);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("VM [%s] with XML configuration [%s] will be migrated to host [%s].", vmName, xmlDesc, target));
|
||||
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, maskSensitiveInfoInXML(xmlDesc), target);
|
||||
}
|
||||
|
||||
// Limit the VNC password in case the length is greater than 8 characters
|
||||
|
|
@ -178,7 +178,7 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
logger.debug(String.format("Editing mount path of ISO from %s to %s", oldIsoVolumePath, newIsoVolumePath));
|
||||
xmlDesc = replaceDiskSourceFile(xmlDesc, newIsoVolumePath, vmName);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Replaced disk mount point [%s] with [%s] in Instance [%s] XML configuration. New XML configuration is [%s].", oldIsoVolumePath, newIsoVolumePath, vmName, xmlDesc));
|
||||
logger.debug("Replaced disk mount point {} with {} in Instance {} XML configuration. New XML configuration is {}.", oldIsoVolumePath, newIsoVolumePath, vmName, maskSensitiveInfoInXML(xmlDesc));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,11 +209,11 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
|
||||
if (migrateStorage) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Changing VM [%s] volumes during migration to host: [%s].", vmName, target));
|
||||
logger.debug("Changing VM {} volumes during migration to host: {}.", vmName, target);
|
||||
}
|
||||
xmlDesc = replaceStorage(xmlDesc, mapMigrateStorage, migrateStorageManaged);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Changed VM [%s] XML configuration of used storage. New XML configuration is [%s].", vmName, xmlDesc));
|
||||
logger.debug("Changed VM {} XML configuration of used storage. New XML configuration is {}.", vmName, maskSensitiveInfoInXML(xmlDesc));
|
||||
}
|
||||
migrateDiskLabels = getMigrateStorageDeviceLabels(disks, mapMigrateStorage);
|
||||
}
|
||||
|
|
@ -221,11 +221,11 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
Map<String, DpdkTO> dpdkPortsMapping = command.getDpdkInterfaceMapping();
|
||||
if (MapUtils.isNotEmpty(dpdkPortsMapping)) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Changing VM [%s] DPDK interfaces during migration to host: [%s].", vmName, target));
|
||||
logger.trace("Changing VM {} DPDK interfaces during migration to host: {}.", vmName, target);
|
||||
}
|
||||
xmlDesc = replaceDpdkInterfaces(xmlDesc, dpdkPortsMapping);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Changed VM [%s] XML configuration of DPDK interfaces. New XML configuration is [%s].", vmName, xmlDesc));
|
||||
logger.debug("Changed VM {} XML configuration of DPDK interfaces. New XML configuration is {}.", vmName, maskSensitiveInfoInXML(xmlDesc));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
}
|
||||
|
||||
//run migration in thread so we can monitor it
|
||||
logger.info(String.format("Starting live migration of instance [%s] to destination host [%s] having the final XML configuration: [%s].", vmName, dconn.getURI(), xmlDesc));
|
||||
logger.info("Starting live migration of instance {} to destination host {} having the final XML configuration: {}.", vmName, dconn.getURI(), maskSensitiveInfoInXML(xmlDesc));
|
||||
final ExecutorService executor = Executors.newFixedThreadPool(1);
|
||||
boolean migrateNonSharedInc = command.isMigrateNonSharedInc() && !migrateStorageManaged;
|
||||
|
||||
|
|
@ -256,20 +256,21 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
final Future<Domain> migrateThread = executor.submit(worker);
|
||||
executor.shutdown();
|
||||
long sleeptime = 0;
|
||||
final int migrateDowntime = libvirtComputingResource.getMigrateDowntime();
|
||||
boolean isMigrateDowntimeSet = false;
|
||||
|
||||
while (!executor.isTerminated()) {
|
||||
Thread.sleep(100);
|
||||
sleeptime += 100;
|
||||
if (sleeptime == 1000) { // wait 1s before attempting to set downtime on migration, since I don't know of a VIR_DOMAIN_MIGRATING state
|
||||
final int migrateDowntime = libvirtComputingResource.getMigrateDowntime();
|
||||
if (migrateDowntime > 0 ) {
|
||||
try {
|
||||
final int setDowntime = dm.migrateSetMaxDowntime(migrateDowntime);
|
||||
if (setDowntime == 0 ) {
|
||||
logger.debug("Set max downtime for migration of " + vmName + " to " + String.valueOf(migrateDowntime) + "ms");
|
||||
}
|
||||
} catch (final LibvirtException e) {
|
||||
logger.debug("Failed to set max downtime for migration, perhaps migration completed? Error: " + e.getMessage());
|
||||
if (!isMigrateDowntimeSet && migrateDowntime > 0 && sleeptime >= 1000) { // wait 1s before attempting to set downtime on migration, since I don't know of a VIR_DOMAIN_MIGRATING state
|
||||
try {
|
||||
final int setDowntime = dm.migrateSetMaxDowntime(migrateDowntime);
|
||||
if (setDowntime == 0 ) {
|
||||
isMigrateDowntimeSet = true;
|
||||
logger.debug("Set max downtime for migration of " + vmName + " to " + String.valueOf(migrateDowntime) + "ms");
|
||||
}
|
||||
} catch (final LibvirtException e) {
|
||||
logger.debug("Failed to set max downtime for migration, perhaps migration completed? Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
if (sleeptime % 1000 == 0) {
|
||||
|
|
@ -278,17 +279,20 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
|
||||
// abort the vm migration if the job is executed more than vm.migrate.wait
|
||||
final int migrateWait = libvirtComputingResource.getMigrateWait();
|
||||
logger.info("vm.migrate.wait value set to: {}for VM: {}", migrateWait, vmName);
|
||||
if (migrateWait > 0 && sleeptime > migrateWait * 1000) {
|
||||
DomainState state = null;
|
||||
try {
|
||||
state = dm.getInfo().state;
|
||||
logger.info("VM domain state when trying to abort migration : {}", state);
|
||||
} catch (final LibvirtException e) {
|
||||
logger.info("Couldn't get VM domain state after " + sleeptime + "ms: " + e.getMessage());
|
||||
}
|
||||
if (state != null && state == DomainState.VIR_DOMAIN_RUNNING) {
|
||||
if (state != null && (state == DomainState.VIR_DOMAIN_RUNNING || state == DomainState.VIR_DOMAIN_PAUSED)) {
|
||||
try {
|
||||
DomainJobInfo job = dm.getJobInfo();
|
||||
logger.info(String.format("Aborting migration of VM [%s] with domain job [%s] due to time out after %d seconds.", vmName, job, migrateWait));
|
||||
logger.warn("Aborting migration of VM {} with domain job [{}] due to timeout after {} seconds. " +
|
||||
"Job stats: data processed={} bytes, data remaining={} bytes", vmName, job, migrateWait, job.getDataProcessed(), job.getDataRemaining());
|
||||
dm.abortJob();
|
||||
result = String.format("Migration of VM [%s] was cancelled by CloudStack due to time out after %d seconds.", vmName, migrateWait);
|
||||
commandState = Command.State.FAILED;
|
||||
|
|
@ -303,10 +307,12 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
|
||||
// pause vm if we meet the vm.migrate.pauseafter threshold and not already paused
|
||||
final int migratePauseAfter = libvirtComputingResource.getMigratePauseAfter();
|
||||
logger.info("vm.migrate.pauseafter value set to: {} for VM: {}", migratePauseAfter, vmName);
|
||||
if (migratePauseAfter > 0 && sleeptime > migratePauseAfter) {
|
||||
DomainState state = null;
|
||||
try {
|
||||
state = dm.getInfo().state;
|
||||
logger.info("VM domain state when trying to pause VM for migration: {}", state);
|
||||
} catch (final LibvirtException e) {
|
||||
logger.info("Couldn't get VM domain state after " + sleeptime + "ms: " + e.getMessage());
|
||||
}
|
||||
|
|
@ -329,6 +335,7 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Cleaning the disks of VM [%s] in the source pool after VM migration finished.", vmName));
|
||||
}
|
||||
resumeDomainIfPaused(destDomain, vmName);
|
||||
deleteOrDisconnectDisksOnSourcePool(libvirtComputingResource, migrateDiskInfoList, disks);
|
||||
libvirtComputingResource.cleanOldSecretsByDiskDef(conn, disks);
|
||||
}
|
||||
|
|
@ -381,6 +388,7 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
}
|
||||
|
||||
if (result == null) {
|
||||
logger.info("Post-migration cleanup for VM {}: ", vmName);
|
||||
libvirtComputingResource.destroyNetworkRulesForVM(conn, vmName);
|
||||
for (final InterfaceDef iface : ifaces) {
|
||||
String vlanId = libvirtComputingResource.getVlanIdFromBridgeName(iface.getBrName());
|
||||
|
|
@ -394,6 +402,7 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
commandState = Command.State.COMPLETED;
|
||||
libvirtComputingResource.createOrUpdateLogFileForCommand(command, commandState);
|
||||
} else if (commandState == null) {
|
||||
logger.error("Migration of VM {} failed with result: {}", vmName, result);
|
||||
commandState = Command.State.FAILED;
|
||||
libvirtComputingResource.createOrUpdateLogFileForCommand(command, commandState);
|
||||
}
|
||||
|
|
@ -401,6 +410,28 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
return new MigrateAnswer(command, result == null, result, null);
|
||||
}
|
||||
|
||||
private DomainState getDestDomainState(Domain destDomain, String vmName) {
|
||||
DomainState dmState = null;
|
||||
try {
|
||||
dmState = destDomain.getInfo().state;
|
||||
} catch (final LibvirtException e) {
|
||||
logger.info("Failed to get domain state for VM: " + vmName + " due to: " + e.getMessage());
|
||||
}
|
||||
return dmState;
|
||||
}
|
||||
|
||||
private void resumeDomainIfPaused(Domain destDomain, String vmName) {
|
||||
DomainState dmState = getDestDomainState(destDomain, vmName);
|
||||
if (dmState == DomainState.VIR_DOMAIN_PAUSED) {
|
||||
logger.info("Resuming VM " + vmName + " on destination after migration");
|
||||
try {
|
||||
destDomain.resume();
|
||||
} catch (final Exception e) {
|
||||
logger.error("Failed to resume vm " + vmName + " on destination after migration due to : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the disk labels (vda, vdb...) of the disks mapped for migration on mapMigrateStorage.
|
||||
* @param diskDefinitions list of all the disksDefinitions of the VM.
|
||||
|
|
@ -708,9 +739,7 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
graphElem = graphElem.replaceAll("passwd='([^\\s]+)'", "passwd='" + vncPassword + "'");
|
||||
}
|
||||
xmlDesc = xmlDesc.replaceAll(GRAPHICS_ELEM_START + CONTENTS_WILDCARD + GRAPHICS_ELEM_END, graphElem);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Replaced the VNC IP address [%s] with [%s] in VM [%s].", originalGraphElem, graphElem, vmName));
|
||||
}
|
||||
logger.debug("Replaced the VNC IP address {} with {} in VM {}.", maskSensitiveInfoInXML(originalGraphElem), maskSensitiveInfoInXML(graphElem), vmName);
|
||||
}
|
||||
}
|
||||
return xmlDesc;
|
||||
|
|
@ -1029,4 +1058,10 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper<MigrateCo
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String maskSensitiveInfoInXML(String xmlDesc) {
|
||||
if (xmlDesc == null) return null;
|
||||
return xmlDesc.replaceAll("(graphics\\s+[^>]*type=['\"]vnc['\"][^>]*passwd=['\"])([^'\"]*)(['\"])",
|
||||
"$1*****$3");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ public final class LibvirtPrepareForMigrationCommandWrapper extends CommandWrapp
|
|||
final VirtualMachineTO vm = command.getVirtualMachine();
|
||||
|
||||
if (command.isRollback()) {
|
||||
logger.info("Handling rollback for PrepareForMigration of VM {}", vm.getName());
|
||||
return handleRollback(command, libvirtComputingResource);
|
||||
}
|
||||
|
||||
|
|
@ -83,6 +84,7 @@ public final class LibvirtPrepareForMigrationCommandWrapper extends CommandWrapp
|
|||
if (interfaceDef != null && interfaceDef.getNetType() == GuestNetType.VHOSTUSER) {
|
||||
DpdkTO to = new DpdkTO(interfaceDef.getDpdkOvsPath(), interfaceDef.getDpdkSourcePort(), interfaceDef.getInterfaceMode());
|
||||
dpdkInterfaceMapping.put(nic.getMac(), to);
|
||||
logger.debug("Configured DPDK interface for VM {}", vm.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,6 +124,7 @@ public final class LibvirtPrepareForMigrationCommandWrapper extends CommandWrapp
|
|||
return new PrepareForMigrationAnswer(command, "failed to connect physical disks to host");
|
||||
}
|
||||
|
||||
logger.info("Successfully prepared destination host for migration of VM {}", vm.getName());
|
||||
return createPrepareForMigrationAnswer(command, dpdkInterfaceMapping, libvirtComputingResource, vm);
|
||||
} catch (final LibvirtException | CloudRuntimeException | InternalErrorException | URISyntaxException e) {
|
||||
if (MapUtils.isNotEmpty(dpdkInterfaceMapping)) {
|
||||
|
|
@ -157,6 +160,7 @@ public final class LibvirtPrepareForMigrationCommandWrapper extends CommandWrapp
|
|||
KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
|
||||
VirtualMachineTO vmTO = command.getVirtualMachine();
|
||||
|
||||
logger.info("Rolling back PrepareForMigration for VM {}: disconnecting physical disks", vmTO.getName());
|
||||
if (!storagePoolMgr.disconnectPhysicalDisksViaVmSpec(vmTO)) {
|
||||
return new PrepareForMigrationAnswer(command, "failed to disconnect physical disks from host");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,8 +84,9 @@ public final class LibvirtStartCommandWrapper extends CommandWrapper<StartComman
|
|||
}
|
||||
|
||||
libvirtComputingResource.createVifs(vmSpec, vm);
|
||||
|
||||
logger.debug("starting " + vmName + ": " + vm.toString());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Starting {} : {}", vmName, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(vm.toString()));
|
||||
}
|
||||
String vmInitialSpecification = vm.toString();
|
||||
String vmFinalSpecification = performXmlTransformHook(vmInitialSpecification, libvirtComputingResource);
|
||||
libvirtComputingResource.startVM(conn, vmName, vmFinalSpecification);
|
||||
|
|
|
|||
|
|
@ -658,7 +658,7 @@ public class LibvirtMigrateCommandWrapperTest {
|
|||
@Test
|
||||
public void testReplaceIpForVNCInDescFile() {
|
||||
final String targetIp = "192.168.22.21";
|
||||
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(fullfile, targetIp, null, "");
|
||||
final String result = libvirtMigrateCmdWrapper.replaceIpForVNCInDescFileAndNormalizePassword(fullfile, targetIp, "vncSecretPwd", "");
|
||||
assertEquals("transformation does not live up to expectation:\n" + result, targetfile, result);
|
||||
}
|
||||
|
||||
|
|
@ -1089,6 +1089,30 @@ public class LibvirtMigrateCommandWrapperTest {
|
|||
Assert.assertTrue(finalXml.contains(newIsoVolumePath));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaskVncPwdDomain() {
|
||||
// Test case 1: Single quotes
|
||||
String xml1 = "<graphics type='vnc' port='5900' passwd='secret123'/>";
|
||||
String expected1 = "<graphics type='vnc' port='5900' passwd='*****'/>";
|
||||
assertEquals(expected1, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml1));
|
||||
|
||||
// Test case 2: Double quotes
|
||||
String xml2 = "<graphics type=\"vnc\" port=\"5901\" passwd=\"mypassword\"/>";
|
||||
String expected2 = "<graphics type=\"vnc\" port=\"5901\" passwd=\"*****\"/>";
|
||||
assertEquals(expected2, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml2));
|
||||
|
||||
// Test case 3: Non-VNC graphics (should remain unchanged)
|
||||
String xml3 = "<graphics type='spice' port='5902' passwd='notvnc'/>";
|
||||
assertEquals(xml3, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml3));
|
||||
|
||||
// Test case 4: Multiple VNC entries in one string
|
||||
String xml4 = "<graphics type='vnc' port='5900' passwd='a'/>\n" +
|
||||
"<graphics type='vnc' port='5901' passwd='b'/>";
|
||||
String expected4 = "<graphics type='vnc' port='5900' passwd='*****'/>\n" +
|
||||
"<graphics type='vnc' port='5901' passwd='*****'/>";
|
||||
assertEquals(expected4, LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateGpuDevicesIfNeededTestNoGpuDevice() throws Exception {
|
||||
Mockito.doReturn(virtualMachineTOMock).when(migrateCommandMock).getVirtualMachine();
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ sonar.projectVersion=1.0
|
|||
sonar.sources=src
|
||||
sonar.binaries=target/classes
|
||||
|
||||
# Exclussions
|
||||
# Exclusions
|
||||
sonar.exclusions=**/*Test.java
|
||||
|
||||
# Language
|
||||
|
|
|
|||
|
|
@ -1383,8 +1383,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
|
|||
}
|
||||
|
||||
totalAdditionalVms += additional;
|
||||
long effectiveCpu = (long) so.getCpu() * so.getSpeed();
|
||||
totalAdditionalCpuUnits += effectiveCpu * additional;
|
||||
totalAdditionalCpuUnits += so.getCpu() * additional;
|
||||
totalAdditionalRamMb += so.getRamSize() * additional;
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ import org.apache.cloudstack.api.response.GetUploadParamsResponse;
|
|||
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.cloud.api.query.dao.TemplateJoinDao;
|
||||
|
|
@ -57,6 +60,7 @@ import com.cloud.storage.dao.VMTemplateDao;
|
|||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
import com.cloud.template.TemplateApiService;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
|
|
@ -84,12 +88,14 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||
@Inject
|
||||
private DataCenterDao dataCenterDao;
|
||||
@Inject
|
||||
private ImageStoreDao imageStoreDao;
|
||||
@Inject
|
||||
private TemplateApiService templateService;
|
||||
|
||||
public static final String MINIMUN_AUTOSCALER_SUPPORTED_VERSION = "1.15.0";
|
||||
|
||||
protected void updateTemplateDetailsInKubernetesSupportedVersionResponse(
|
||||
final KubernetesSupportedVersion kubernetesSupportedVersion, KubernetesSupportedVersionResponse response) {
|
||||
final KubernetesSupportedVersion kubernetesSupportedVersion, KubernetesSupportedVersionResponse response, boolean isRootAdmin) {
|
||||
TemplateJoinVO template = templateJoinDao.findById(kubernetesSupportedVersion.getIsoId());
|
||||
if (template == null) {
|
||||
return;
|
||||
|
|
@ -99,11 +105,14 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||
if (template.getState() != null) {
|
||||
response.setIsoState(template.getState().toString());
|
||||
}
|
||||
if (isRootAdmin) {
|
||||
response.setIsoUrl(template.getUrl());
|
||||
}
|
||||
response.setIsoArch(template.getArch().getType());
|
||||
response.setDirectDownload(template.isDirectDownload());
|
||||
}
|
||||
|
||||
private KubernetesSupportedVersionResponse createKubernetesSupportedVersionResponse(final KubernetesSupportedVersion kubernetesSupportedVersion) {
|
||||
private KubernetesSupportedVersionResponse createKubernetesSupportedVersionResponse(final KubernetesSupportedVersion kubernetesSupportedVersion, boolean isRootAdmin) {
|
||||
KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse();
|
||||
response.setObjectName("kubernetessupportedversion");
|
||||
response.setId(kubernetesSupportedVersion.getUuid());
|
||||
|
|
@ -122,7 +131,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||
response.setSupportsHA(compareSemanticVersions(kubernetesSupportedVersion.getSemanticVersion(),
|
||||
KubernetesClusterService.MIN_KUBERNETES_VERSION_HA_SUPPORT)>=0);
|
||||
response.setSupportsAutoscaling(versionSupportsAutoscaling(kubernetesSupportedVersion));
|
||||
updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, response);
|
||||
updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, response, isRootAdmin);
|
||||
response.setCreated(kubernetesSupportedVersion.getCreated());
|
||||
return response;
|
||||
}
|
||||
|
|
@ -130,8 +139,11 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||
private ListResponse<KubernetesSupportedVersionResponse> createKubernetesSupportedVersionListResponse(
|
||||
List<KubernetesSupportedVersionVO> versions, Integer count) {
|
||||
List<KubernetesSupportedVersionResponse> responseList = new ArrayList<>();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
boolean isRootAdmin = accountManager.isRootAdmin(caller.getId());
|
||||
|
||||
for (KubernetesSupportedVersionVO version : versions) {
|
||||
responseList.add(createKubernetesSupportedVersionResponse(version));
|
||||
responseList.add(createKubernetesSupportedVersionResponse(version, isRootAdmin));
|
||||
}
|
||||
ListResponse<KubernetesSupportedVersionResponse> response = new ListResponse<>();
|
||||
response.setResponses(responseList, count);
|
||||
|
|
@ -347,6 +359,32 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||
return createKubernetesSupportedVersionListResponse(versions, versionsAndCount.second());
|
||||
}
|
||||
|
||||
private void validateImageStoreForZone(Long zoneId, boolean directDownload) {
|
||||
if (directDownload) {
|
||||
return;
|
||||
}
|
||||
if (zoneId != null) {
|
||||
List<ImageStoreVO> imageStores = imageStoreDao.listStoresByZoneId(zoneId);
|
||||
if (CollectionUtils.isEmpty(imageStores)) {
|
||||
DataCenterVO zone = dataCenterDao.findById(zoneId);
|
||||
String zoneName = zone != null ? zone.getName() : String.valueOf(zoneId);
|
||||
throw new InvalidParameterValueException(String.format("Unable to register Kubernetes version ISO. No image store available in zone: %s", zoneName));
|
||||
}
|
||||
} else {
|
||||
List<DataCenterVO> zones = dataCenterDao.listAllZones();
|
||||
List<String> zonesWithoutStorage = new ArrayList<>();
|
||||
for (DataCenterVO zone : zones) {
|
||||
List<ImageStoreVO> imageStores = imageStoreDao.listStoresByZoneId(zone.getId());
|
||||
if (CollectionUtils.isEmpty(imageStores)) {
|
||||
zonesWithoutStorage.add(zone.getName());
|
||||
}
|
||||
}
|
||||
if (!zonesWithoutStorage.isEmpty()) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to register Kubernetes version ISO for all zones. The following zones have no image store: %s", String.join(", ", zonesWithoutStorage)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateKubernetesSupportedVersion(Long zoneId, String semanticVersion, Integer minimumCpu,
|
||||
Integer minimumRamSize, boolean isDirectDownload) {
|
||||
if (minimumCpu == null || minimumCpu < KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU) {
|
||||
|
|
@ -398,6 +436,8 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||
}
|
||||
}
|
||||
|
||||
validateImageStoreForZone(zoneId, isDirectDownload);
|
||||
|
||||
VMTemplateVO template = null;
|
||||
try {
|
||||
VirtualMachineTemplate vmTemplate = registerKubernetesVersionIso(zoneId, name, isoUrl, isoChecksum, isDirectDownload, arch);
|
||||
|
|
@ -411,7 +451,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||
supportedVersionVO = kubernetesSupportedVersionDao.persist(supportedVersionVO);
|
||||
CallContext.current().putContextParameter(KubernetesSupportedVersion.class, supportedVersionVO.getUuid());
|
||||
|
||||
return createKubernetesSupportedVersionResponse(supportedVersionVO);
|
||||
return createKubernetesSupportedVersionResponse(supportedVersionVO, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -496,7 +536,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||
}
|
||||
version = kubernetesSupportedVersionDao.findById(versionId);
|
||||
}
|
||||
return createKubernetesSupportedVersionResponse(version);
|
||||
return createKubernetesSupportedVersionResponse(version, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ public class KubernetesSupportedVersionResponse extends BaseResponse {
|
|||
@Param(description = "The name of the binaries ISO for Kubernetes supported version")
|
||||
private String isoName;
|
||||
|
||||
@SerializedName(ApiConstants.ISO_URL)
|
||||
@Param(description = "the URL of the binaries ISO for Kubernetes supported version")
|
||||
private String isoUrl;
|
||||
|
||||
@SerializedName(ApiConstants.ISO_STATE)
|
||||
@Param(description = "The state of the binaries ISO for Kubernetes supported version")
|
||||
private String isoState;
|
||||
|
|
@ -134,6 +138,14 @@ public class KubernetesSupportedVersionResponse extends BaseResponse {
|
|||
this.isoName = isoName;
|
||||
}
|
||||
|
||||
public String getIsoUrl() {
|
||||
return isoUrl;
|
||||
}
|
||||
|
||||
public void setIsoUrl(String isoUrl) {
|
||||
this.isoUrl = isoUrl;
|
||||
}
|
||||
|
||||
public String getIsoState() {
|
||||
return isoState;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,15 @@
|
|||
// under the License.
|
||||
package com.cloud.kubernetes.version;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -32,6 +37,9 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||
import com.cloud.api.query.dao.TemplateJoinDao;
|
||||
import com.cloud.api.query.vo.TemplateJoinVO;
|
||||
import com.cloud.cpu.CPU;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class KubernetesVersionManagerImplTest {
|
||||
|
|
@ -39,6 +47,12 @@ public class KubernetesVersionManagerImplTest {
|
|||
@Mock
|
||||
TemplateJoinDao templateJoinDao;
|
||||
|
||||
@Mock
|
||||
ImageStoreDao imageStoreDao;
|
||||
|
||||
@Mock
|
||||
DataCenterDao dataCenterDao;
|
||||
|
||||
@InjectMocks
|
||||
KubernetesVersionManagerImpl kubernetesVersionManager = new KubernetesVersionManagerImpl();
|
||||
|
||||
|
|
@ -48,7 +62,7 @@ public class KubernetesVersionManagerImplTest {
|
|||
Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L);
|
||||
KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse();
|
||||
kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion,
|
||||
response);
|
||||
response, true);
|
||||
Assert.assertNull(ReflectionTestUtils.getField(response, "isoId"));
|
||||
}
|
||||
|
||||
|
|
@ -63,13 +77,71 @@ public class KubernetesVersionManagerImplTest {
|
|||
Mockito.when(templateJoinVO.getUuid()).thenReturn(uuid);
|
||||
Mockito.when(templateJoinDao.findById(1L)).thenReturn(templateJoinVO);
|
||||
kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion,
|
||||
response);
|
||||
response, true);
|
||||
Assert.assertEquals(uuid, ReflectionTestUtils.getField(response, "isoId"));
|
||||
Assert.assertNull(ReflectionTestUtils.getField(response, "isoState"));
|
||||
ObjectInDataStoreStateMachine.State state = ObjectInDataStoreStateMachine.State.Ready;
|
||||
Mockito.when(templateJoinVO.getState()).thenReturn(state);
|
||||
kubernetesVersionManager.updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion,
|
||||
response);
|
||||
response, true);
|
||||
Assert.assertEquals(state.toString(), ReflectionTestUtils.getField(response, "isoState"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateImageStoreForZoneWithDirectDownload() {
|
||||
ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", 1L, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateImageStoreForZoneWithValidZone() {
|
||||
Long zoneId = 1L;
|
||||
List<ImageStoreVO> imageStores = Collections.singletonList(Mockito.mock(ImageStoreVO.class));
|
||||
Mockito.when(imageStoreDao.listStoresByZoneId(zoneId)).thenReturn(imageStores);
|
||||
|
||||
ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", zoneId, false);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testValidateImageStoreForZoneWithNoImageStore() {
|
||||
Long zoneId = 1L;
|
||||
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
|
||||
Mockito.when(zone.getName()).thenReturn("test-zone");
|
||||
Mockito.when(dataCenterDao.findById(zoneId)).thenReturn(zone);
|
||||
Mockito.when(imageStoreDao.listStoresByZoneId(zoneId)).thenReturn(Collections.emptyList());
|
||||
|
||||
ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", zoneId, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateImageStoreForAllZonesWithAllValid() {
|
||||
DataCenterVO zone1 = Mockito.mock(DataCenterVO.class);
|
||||
Mockito.when(zone1.getId()).thenReturn(1L);
|
||||
DataCenterVO zone2 = Mockito.mock(DataCenterVO.class);
|
||||
Mockito.when(zone2.getId()).thenReturn(2L);
|
||||
List<DataCenterVO> zones = Arrays.asList(zone1, zone2);
|
||||
Mockito.when(dataCenterDao.listAllZones()).thenReturn(zones);
|
||||
|
||||
List<ImageStoreVO> imageStores = Collections.singletonList(Mockito.mock(ImageStoreVO.class));
|
||||
Mockito.when(imageStoreDao.listStoresByZoneId(1L)).thenReturn(imageStores);
|
||||
Mockito.when(imageStoreDao.listStoresByZoneId(2L)).thenReturn(imageStores);
|
||||
|
||||
ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", (Long) null, false);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testValidateImageStoreForAllZonesWithSomeMissingStorage() {
|
||||
DataCenterVO zone1 = Mockito.mock(DataCenterVO.class);
|
||||
Mockito.when(zone1.getId()).thenReturn(1L);
|
||||
DataCenterVO zone2 = Mockito.mock(DataCenterVO.class);
|
||||
Mockito.when(zone2.getId()).thenReturn(2L);
|
||||
Mockito.when(zone2.getName()).thenReturn("zone-without-storage");
|
||||
List<DataCenterVO> zones = Arrays.asList(zone1, zone2);
|
||||
Mockito.when(dataCenterDao.listAllZones()).thenReturn(zones);
|
||||
|
||||
List<ImageStoreVO> imageStores = Collections.singletonList(Mockito.mock(ImageStoreVO.class));
|
||||
Mockito.when(imageStoreDao.listStoresByZoneId(1L)).thenReturn(imageStores);
|
||||
Mockito.when(imageStoreDao.listStoresByZoneId(2L)).thenReturn(Collections.emptyList());
|
||||
|
||||
ReflectionTestUtils.invokeMethod(kubernetesVersionManager, "validateImageStoreForZone", (Long) null, false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
|
||||
package com.cloud.kubernetes.version;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
|
@ -25,6 +28,11 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
|
||||
import com.cloud.cpu.CPU;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserVO;
|
||||
import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd;
|
||||
import org.apache.cloudstack.api.command.admin.kubernetes.version.DeleteKubernetesSupportedVersionCmd;
|
||||
import org.apache.cloudstack.api.command.admin.kubernetes.version.UpdateKubernetesSupportedVersionCmd;
|
||||
|
|
@ -63,11 +71,6 @@ import com.cloud.storage.VMTemplateVO;
|
|||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.template.TemplateApiService;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ComponentContext;
|
||||
import com.cloud.utils.db.Filter;
|
||||
|
|
@ -75,6 +78,9 @@ import com.cloud.utils.db.SearchBuilder;
|
|||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class KubernetesVersionServiceTest {
|
||||
|
||||
|
|
@ -94,7 +100,11 @@ public class KubernetesVersionServiceTest {
|
|||
@Mock
|
||||
private DataCenterDao dataCenterDao;
|
||||
@Mock
|
||||
private ImageStoreDao imageStoreDao;
|
||||
@Mock
|
||||
private TemplateApiService templateService;
|
||||
@Mock
|
||||
private Account accountMock;
|
||||
|
||||
AutoCloseable closeable;
|
||||
|
||||
|
|
@ -123,7 +133,12 @@ public class KubernetesVersionServiceTest {
|
|||
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
|
||||
when(dataCenterDao.findById(Mockito.anyLong())).thenReturn(zone);
|
||||
|
||||
List<ImageStoreVO> imageStores = new ArrayList<>();
|
||||
imageStores.add(Mockito.mock(ImageStoreVO.class));
|
||||
when(imageStoreDao.listStoresByZoneId(Mockito.anyLong())).thenReturn(imageStores);
|
||||
|
||||
TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class);
|
||||
when(templateJoinVO.getUrl()).thenReturn("https://download.cloudstack.com");
|
||||
when(templateJoinVO.getState()).thenReturn(ObjectInDataStoreStateMachine.State.Ready);
|
||||
when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault());
|
||||
when(templateJoinDao.findById(Mockito.anyLong())).thenReturn(templateJoinVO);
|
||||
|
|
@ -140,19 +155,66 @@ public class KubernetesVersionServiceTest {
|
|||
|
||||
@Test
|
||||
public void listKubernetesSupportedVersionsTest() {
|
||||
ListKubernetesSupportedVersionsCmd cmd = Mockito.mock(ListKubernetesSupportedVersionsCmd.class);
|
||||
List<KubernetesSupportedVersionVO> versionVOs = new ArrayList<>();
|
||||
KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class);
|
||||
when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION);
|
||||
versionVOs.add(versionVO);
|
||||
when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO);
|
||||
when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(SearchCriteria.class),
|
||||
Mockito.any(Filter.class))).thenReturn(new Pair<>(versionVOs, versionVOs.size()));
|
||||
ListResponse<KubernetesSupportedVersionResponse> versionsResponse =
|
||||
kubernetesVersionService.listKubernetesSupportedVersions(cmd);
|
||||
Assert.assertEquals(versionVOs.size(), versionsResponse.getCount().intValue());
|
||||
Assert.assertTrue(CollectionUtils.isNotEmpty(versionsResponse.getResponses()));
|
||||
Assert.assertEquals(versionVOs.size(), versionsResponse.getResponses().size());
|
||||
CallContext callContextMock = Mockito.mock(CallContext.class);
|
||||
try (MockedStatic<CallContext> callContextMockedStatic = Mockito.mockStatic(CallContext.class)) {
|
||||
callContextMockedStatic.when(CallContext::current).thenReturn(callContextMock);
|
||||
final SearchCriteria<KubernetesSupportedVersionVO> versionSearchCriteria = Mockito.mock(SearchCriteria.class);
|
||||
when(callContextMock.getCallingAccount()).thenReturn(accountMock);
|
||||
ListKubernetesSupportedVersionsCmd cmd = Mockito.mock(ListKubernetesSupportedVersionsCmd.class);
|
||||
List<KubernetesSupportedVersionVO> versionVOs = new ArrayList<>();
|
||||
KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class);
|
||||
when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION);
|
||||
versionVOs.add(versionVO);
|
||||
when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO);
|
||||
when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(), Mockito.any(Filter.class)))
|
||||
.thenReturn(new Pair<>(versionVOs, versionVOs.size()));
|
||||
ListResponse<KubernetesSupportedVersionResponse> versionsResponse =
|
||||
kubernetesVersionService.listKubernetesSupportedVersions(cmd);
|
||||
Assert.assertEquals(versionVOs.size(), versionsResponse.getCount().intValue());
|
||||
Assert.assertTrue(CollectionUtils.isNotEmpty(versionsResponse.getResponses()));
|
||||
Assert.assertEquals(versionVOs.size(), versionsResponse.getResponses().size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listKubernetesSupportedVersionsTestWhenAdmin() {
|
||||
CallContext callContextMock = Mockito.mock(CallContext.class);
|
||||
try (MockedStatic<CallContext> callContextMockedStatic = Mockito.mockStatic(CallContext.class)) {
|
||||
callContextMockedStatic.when(CallContext::current).thenReturn(callContextMock);
|
||||
ListKubernetesSupportedVersionsCmd cmd = Mockito.mock(ListKubernetesSupportedVersionsCmd.class);
|
||||
List<KubernetesSupportedVersionVO> versionVOs = new ArrayList<>();
|
||||
KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class);
|
||||
when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION);
|
||||
versionVOs.add(versionVO);
|
||||
when(callContextMock.getCallingAccount()).thenReturn(accountMock);
|
||||
when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO);
|
||||
when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(), Mockito.any(Filter.class)))
|
||||
.thenReturn(new Pair<>(versionVOs, versionVOs.size()));
|
||||
when(accountManager.isRootAdmin(anyLong())).thenReturn(true);
|
||||
ListResponse<KubernetesSupportedVersionResponse> response = kubernetesVersionService.listKubernetesSupportedVersions(cmd);
|
||||
assertNotNull(response.getResponses().get(0).getIsoUrl());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listKubernetesSupportedVersionsTestWhenOtherUser() {
|
||||
CallContext callContextMock = Mockito.mock(CallContext.class);
|
||||
try (MockedStatic<CallContext> callContextMockedStatic = Mockito.mockStatic(CallContext.class)) {
|
||||
callContextMockedStatic.when(CallContext::current).thenReturn(callContextMock);
|
||||
ListKubernetesSupportedVersionsCmd cmd = Mockito.mock(ListKubernetesSupportedVersionsCmd.class);
|
||||
List<KubernetesSupportedVersionVO> versionVOs = new ArrayList<>();
|
||||
KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class);
|
||||
when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION);
|
||||
versionVOs.add(versionVO);
|
||||
when(callContextMock.getCallingAccount()).thenReturn(accountMock);
|
||||
when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO);
|
||||
when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(), Mockito.any(Filter.class)))
|
||||
.thenReturn(new Pair<>(versionVOs, versionVOs.size()));
|
||||
when(accountManager.isRootAdmin(anyLong())).thenReturn(false);
|
||||
when(accountMock.getId()).thenReturn(2L);
|
||||
ListResponse<KubernetesSupportedVersionResponse> response = kubernetesVersionService.listKubernetesSupportedVersions(cmd);
|
||||
assertNull(response.getResponses().get(0).getIsoUrl());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
|
|
@ -224,7 +286,6 @@ public class KubernetesVersionServiceTest {
|
|||
mockedComponentContext.when(() -> ComponentContext.inject(Mockito.any(RegisterIsoCmd.class))).thenReturn(
|
||||
new RegisterIsoCmd());
|
||||
mockedCallContext.when(CallContext::current).thenReturn(callContext);
|
||||
|
||||
when(templateService.registerIso(Mockito.any(RegisterIsoCmd.class))).thenReturn(
|
||||
Mockito.mock(VirtualMachineTemplate.class));
|
||||
VMTemplateVO templateVO = Mockito.mock(VMTemplateVO.class);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
|
|||
import org.apache.cloudstack.api.command.admin.user.MoveUserCmd;
|
||||
import org.apache.cloudstack.api.response.UserTwoFactorAuthenticationSetupResponse;
|
||||
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
|
|
@ -491,6 +492,11 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
|
|||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAccess(Account account, BackupOffering bof) throws PermissionDeniedException {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Boolean, Map<String, String>> getKeys(GetUserKeysCmd cmd){
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ public class CephObjectStoreDriverImpl extends BaseObjectStoreDriverImpl {
|
|||
new AWSStaticCredentialsProvider(
|
||||
new BasicAWSCredentials(accessKey, secretKey)))
|
||||
.withEndpointConfiguration(
|
||||
new AwsClientBuilder.EndpointConfiguration(url, null))
|
||||
new AwsClientBuilder.EndpointConfiguration(url, "us-east-1"))
|
||||
.build();
|
||||
|
||||
if (client == null) {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ import com.cloud.api.storage.LinstorBackupSnapshotCommand;
|
|||
import com.cloud.api.storage.LinstorRevertBackupSnapshotCommand;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.resource.ResourceState;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
|
|
@ -922,9 +924,10 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
|||
_backupsnapshotwait,
|
||||
VirtualMachineManager.ExecuteInSequence.value());
|
||||
|
||||
Optional<RemoteHostEndPoint> optEP = getDiskfullEP(linstorApi, rscName);
|
||||
final StoragePool pool = (StoragePool) volumeInfo.getDataStore();
|
||||
Optional<RemoteHostEndPoint> optEP = getDiskfullEP(linstorApi, pool, rscName);
|
||||
if (optEP.isEmpty()) {
|
||||
optEP = getLinstorEP(linstorApi, rscName);
|
||||
optEP = getLinstorEP(linstorApi, pool, rscName);
|
||||
}
|
||||
|
||||
if (optEP.isPresent()) {
|
||||
|
|
@ -1064,13 +1067,29 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
|||
Answer answer = copyVolume(srcData, dstData);
|
||||
res = new CopyCommandResult(null, answer);
|
||||
} else {
|
||||
Answer answer = new Answer(null, false, "noimpl");
|
||||
res = new CopyCommandResult(null, answer);
|
||||
res.setResult("Not implemented yet");
|
||||
throw new CloudRuntimeException("Not implemented for Linstor primary storage.");
|
||||
}
|
||||
callback.complete(res);
|
||||
}
|
||||
|
||||
private Host getEnabledClusterHost(StoragePool storagePool, List<String> linstorNodeNames) {
|
||||
List<HostVO> csHosts;
|
||||
if (storagePool.getClusterId() != null) {
|
||||
csHosts = _hostDao.findByClusterId(storagePool.getClusterId());
|
||||
} else {
|
||||
csHosts = _hostDao.findByDataCenterId(storagePool.getDataCenterId());
|
||||
}
|
||||
Collections.shuffle(csHosts); // so we do not always pick the same host for operations
|
||||
for (HostVO host : csHosts) {
|
||||
if (host.getResourceState() == ResourceState.Enabled &&
|
||||
host.getStatus() == Status.Up &&
|
||||
linstorNodeNames.contains(host.getName())) {
|
||||
return host;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to get a Linstor cloudstack end point, that is at least diskless.
|
||||
*
|
||||
|
|
@ -1079,47 +1098,37 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
|||
* @return Optional RemoteHostEndPoint if one could get found.
|
||||
* @throws ApiException
|
||||
*/
|
||||
private Optional<RemoteHostEndPoint> getLinstorEP(DevelopersApi api, String rscName) throws ApiException {
|
||||
private Optional<RemoteHostEndPoint> getLinstorEP(DevelopersApi api, StoragePool storagePool, String rscName)
|
||||
throws ApiException {
|
||||
List<String> linstorNodeNames = LinstorUtil.getLinstorNodeNames(api);
|
||||
Collections.shuffle(linstorNodeNames); // do not always pick the first linstor node
|
||||
|
||||
Host host = null;
|
||||
for (String nodeName : linstorNodeNames) {
|
||||
host = _hostDao.findByName(nodeName);
|
||||
if (host != null && host.getResourceState() == ResourceState.Enabled) {
|
||||
logger.info(String.format("Linstor: Make resource %s available on node %s ...", rscName, nodeName));
|
||||
ApiCallRcList answers = api.resourceMakeAvailableOnNode(rscName, nodeName, new ResourceMakeAvailable());
|
||||
if (!answers.hasError()) {
|
||||
break; // found working host
|
||||
} else {
|
||||
logger.error(
|
||||
String.format("Linstor: Unable to make resource %s on node %s available: %s",
|
||||
rscName,
|
||||
nodeName,
|
||||
LinstorUtil.getBestErrorMessage(answers)));
|
||||
}
|
||||
Host host = getEnabledClusterHost(storagePool, linstorNodeNames);
|
||||
if (host != null) {
|
||||
logger.info("Linstor: Make resource {} available on node {} ...", rscName, host.getName());
|
||||
ApiCallRcList answers = api.resourceMakeAvailableOnNode(
|
||||
rscName, host.getName(), new ResourceMakeAvailable());
|
||||
if (answers.hasError()) {
|
||||
logger.error("Linstor: Unable to make resource {} on node {} available: {}",
|
||||
rscName, host.getName(), LinstorUtil.getBestErrorMessage(answers));
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
|
||||
}
|
||||
}
|
||||
|
||||
if (host == null)
|
||||
{
|
||||
logger.error("Linstor: Couldn't create a resource on any cloudstack host.");
|
||||
return Optional.empty();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
|
||||
}
|
||||
logger.error("Linstor: Couldn't create a resource on any cloudstack host.");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<RemoteHostEndPoint> getDiskfullEP(DevelopersApi api, String rscName) throws ApiException {
|
||||
private Optional<RemoteHostEndPoint> getDiskfullEP(DevelopersApi api, StoragePool storagePool, String rscName)
|
||||
throws ApiException {
|
||||
List<com.linbit.linstor.api.model.StoragePool> linSPs = LinstorUtil.getDiskfulStoragePools(api, rscName);
|
||||
if (linSPs != null) {
|
||||
for (com.linbit.linstor.api.model.StoragePool sp : linSPs) {
|
||||
Host host = _hostDao.findByName(sp.getNodeName());
|
||||
if (host != null && host.getResourceState() == ResourceState.Enabled) {
|
||||
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
|
||||
}
|
||||
List<String> linstorNodeNames = linSPs.stream()
|
||||
.map(com.linbit.linstor.api.model.StoragePool::getNodeName)
|
||||
.collect(Collectors.toList());
|
||||
Host host = getEnabledClusterHost(storagePool, linstorNodeNames);
|
||||
if (host != null) {
|
||||
return Optional.of(RemoteHostEndPoint.getHypervisorHostEndPoint(host));
|
||||
}
|
||||
}
|
||||
logger.error("Linstor: No diskfull host found.");
|
||||
|
|
@ -1200,12 +1209,12 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
|||
VirtualMachineManager.ExecuteInSequence.value());
|
||||
|
||||
try {
|
||||
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, rscName);
|
||||
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, pool, rscName);
|
||||
if (optEP.isPresent()) {
|
||||
answer = optEP.get().sendMessage(cmd);
|
||||
} else {
|
||||
answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint.");
|
||||
deleteResourceDefinition(pool, rscName);
|
||||
throw new CloudRuntimeException("Unable to get matching Linstor endpoint.");
|
||||
}
|
||||
} catch (ApiException exc) {
|
||||
logger.error("copy template failed: ", exc);
|
||||
|
|
@ -1242,12 +1251,12 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
|||
Answer answer;
|
||||
|
||||
try {
|
||||
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, rscName);
|
||||
Optional<RemoteHostEndPoint> optEP = getLinstorEP(api, pool, rscName);
|
||||
if (optEP.isPresent()) {
|
||||
answer = optEP.get().sendMessage(cmd);
|
||||
}
|
||||
else {
|
||||
answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint.");
|
||||
throw new CloudRuntimeException("Unable to get matching Linstor endpoint.");
|
||||
}
|
||||
} catch (ApiException exc) {
|
||||
logger.error("copy volume failed: ", exc);
|
||||
|
|
@ -1280,14 +1289,14 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
|||
try {
|
||||
String devName = restoreResourceFromSnapshot(api, pool, rscName, snapshotName, restoreName);
|
||||
|
||||
Optional<RemoteHostEndPoint> optEPAny = getLinstorEP(api, restoreName);
|
||||
Optional<RemoteHostEndPoint> optEPAny = getLinstorEP(api, pool, restoreName);
|
||||
if (optEPAny.isPresent()) {
|
||||
// patch the src device path to the temporary linstor resource
|
||||
snapshotObject.setPath(devName);
|
||||
origCmd.setSrcTO(snapshotObject.getTO());
|
||||
answer = optEPAny.get().sendMessage(origCmd);
|
||||
} else{
|
||||
answer = new Answer(origCmd, false, "Unable to get matching Linstor endpoint.");
|
||||
} else {
|
||||
throw new CloudRuntimeException("Unable to get matching Linstor endpoint.");
|
||||
}
|
||||
} finally {
|
||||
// delete the temporary resource, noop if already gone
|
||||
|
|
@ -1349,7 +1358,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
|
|||
VirtualMachineManager.ExecuteInSequence.value());
|
||||
cmd.setOptions(options);
|
||||
|
||||
Optional<RemoteHostEndPoint> optEP = getDiskfullEP(api, rscName);
|
||||
Optional<RemoteHostEndPoint> optEP = getDiskfullEP(api, pool, rscName);
|
||||
Answer answer;
|
||||
if (optEP.isPresent()) {
|
||||
answer = optEP.get().sendMessage(cmd);
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public class StorPoolHelper {
|
|||
if (snapshotDetails != null) {
|
||||
return StorPoolStorageAdaptor.getVolumeNameFromPath(snapshotDetails.getValue(), true);
|
||||
} else {
|
||||
List<SnapshotDataStoreVO> snapshots = snapshotStoreDao.findBySnapshotId(snapshotId);
|
||||
List<SnapshotDataStoreVO> snapshots = snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
|
||||
if (!CollectionUtils.isEmpty(snapshots)) {
|
||||
for (SnapshotDataStoreVO snapshotDataStoreVO : snapshots) {
|
||||
String name = StorPoolStorageAdaptor.getVolumeNameFromPath(snapshotDataStoreVO.getInstallPath(), true);
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ public class StorPoolSnapshotStrategy implements SnapshotStrategy {
|
|||
}
|
||||
|
||||
protected boolean areLastSnapshotRef(long snapshotId) {
|
||||
List<SnapshotDataStoreVO> snapshotStoreRefs = _snapshotStoreDao.findBySnapshotId(snapshotId);
|
||||
List<SnapshotDataStoreVO> snapshotStoreRefs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
|
||||
if (CollectionUtils.isEmpty(snapshotStoreRefs) || snapshotStoreRefs.size() == 1) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -343,7 +343,7 @@ public class StorPoolSnapshotStrategy implements SnapshotStrategy {
|
|||
}
|
||||
|
||||
if (Snapshot.State.Error.equals(snapshotVO.getState())) {
|
||||
List<SnapshotDataStoreVO> storeRefs = _snapshotStoreDao.findBySnapshotId(snapshotId);
|
||||
List<SnapshotDataStoreVO> storeRefs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
|
||||
List<Long> deletedRefs = new ArrayList<>();
|
||||
for (SnapshotDataStoreVO ref : storeRefs) {
|
||||
boolean refZoneIdMatch = false;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
</parent>
|
||||
|
||||
<properties>
|
||||
<ads.version>2.0.0.AM25</ads.version>
|
||||
<ads.version>2.0.0.AM27</ads.version>
|
||||
<ldap-maven.version>1.3.2</ldap-maven.version>
|
||||
<ldapunit.version>1.1.3</ldapunit.version>
|
||||
<groovy.version>1.1-groovy-2.4</groovy.version>
|
||||
|
|
|
|||
16
pom.xml
16
pom.xml
|
|
@ -53,6 +53,8 @@
|
|||
<project.systemvm.template.version>4.22.0.0</project.systemvm.template.version>
|
||||
<sonar.organization>apache</sonar.organization>
|
||||
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
|
||||
<sonar.exclusions>engine/schema/src/main/java/org/apache/cloudstack/backup/BackupOfferingDetailsVO.java</sonar.exclusions>
|
||||
<sonar.exclusions>api/src/main/java/org/apache/cloudstack/api/response/BackupOfferingResponse.java</sonar.exclusions>
|
||||
|
||||
<!-- Build properties -->
|
||||
<cs.jdk.version>11</cs.jdk.version>
|
||||
|
|
@ -87,7 +89,7 @@
|
|||
<cs.log4j.extras.version>1.2.17</cs.log4j.extras.version>
|
||||
|
||||
<!-- Apache Commons versions -->
|
||||
<cs.codec.version>1.15</cs.codec.version>
|
||||
<cs.codec.version>1.20.0</cs.codec.version>
|
||||
<cs.commons-cli.version>1.5.0</cs.commons-cli.version>
|
||||
<cs.commons-collections.version>4.4</cs.commons-collections.version>
|
||||
<cs.commons-compress.version>1.26.0</cs.commons-compress.version>
|
||||
|
|
@ -188,6 +190,7 @@
|
|||
<org.springframework.version>5.3.26</org.springframework.version>
|
||||
<cs.ini.version>0.5.4</cs.ini.version>
|
||||
<cs.caffeine.version>3.1.7</cs.caffeine.version>
|
||||
<cs.protobuf.version>3.25.5</cs.protobuf.version>
|
||||
</properties>
|
||||
|
||||
<distributionManagement>
|
||||
|
|
@ -730,6 +733,17 @@
|
|||
<artifactId>xml-apis</artifactId>
|
||||
<version>2.0.2</version>
|
||||
</dependency>
|
||||
<!-- enforced protobuf version here as mysql-connector-java is pulling older version (3.19.3) -->
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>${cs.protobuf.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
<version>${cs.protobuf.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.linbit.linstor.api</groupId>
|
||||
<artifactId>java-linstor</artifactId>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import org.apache.cloudstack.query.QueryService;
|
|||
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDetailsDao;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DedicatedResourceVO;
|
||||
import com.cloud.dc.dao.DedicatedResourceDao;
|
||||
|
|
@ -70,6 +72,8 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
|
|||
@Inject
|
||||
DomainDao _domainDao;
|
||||
@Inject
|
||||
BackupOfferingDetailsDao backupOfferingDetailsDao;
|
||||
@Inject
|
||||
AccountDao _accountDao;
|
||||
@Inject
|
||||
LaunchPermissionDao _launchPermissionDao;
|
||||
|
|
@ -474,6 +478,35 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
|
|||
return hasAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAccess(Account account, BackupOffering backupOffering) throws PermissionDeniedException {
|
||||
boolean hasAccess = false;
|
||||
if (account == null || backupOffering == null) {
|
||||
hasAccess = true;
|
||||
} else {
|
||||
if (_accountService.isRootAdmin(account.getId())) {
|
||||
hasAccess = true;
|
||||
}
|
||||
else if (_accountService.isNormalUser(account.getId())
|
||||
|| account.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN
|
||||
|| _accountService.isDomainAdmin(account.getId())
|
||||
|| account.getType() == Account.Type.PROJECT) {
|
||||
final List<Long> boDomainIds = backupOfferingDetailsDao.findDomainIds(backupOffering.getId());
|
||||
if (boDomainIds.isEmpty()) {
|
||||
hasAccess = true;
|
||||
} else {
|
||||
for (Long domainId : boDomainIds) {
|
||||
if (_domainDao.isChildDomain(domainId, account.getDomainId())) {
|
||||
hasAccess = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAccess(Account account, DataCenter zone) throws PermissionDeniedException {
|
||||
if (account == null || zone.getDomainId() == null) {//public zone
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
|
|||
, AlertType.ALERT_TYPE_OOBM_AUTH_ERROR
|
||||
, AlertType.ALERT_TYPE_HA_ACTION
|
||||
, AlertType.ALERT_TYPE_CA_CERT
|
||||
, AlertType.ALERT_TYPE_EXTENSION_PATH_NOT_READY);
|
||||
, AlertType.ALERT_TYPE_EXTENSION_PATH_NOT_READY
|
||||
, AlertType.ALERT_TYPE_VPN_GATEWAY_OBSOLETE_PARAMETERS);
|
||||
|
||||
private static final long INITIAL_CAPACITY_CHECK_DELAY = 30L * 1000L; // Thirty seconds expressed in milliseconds.
|
||||
|
||||
|
|
@ -313,13 +314,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
|
|||
Math.min(CapacityManager.CapacityCalculateWorkers.value(), hostIds.size())));
|
||||
for (Long hostId : hostIds) {
|
||||
futures.put(hostId, executorService.submit(() -> {
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
final HostVO host = hostDao.findById(hostId);
|
||||
_capacityMgr.updateCapacityForHost(host);
|
||||
}
|
||||
});
|
||||
final HostVO host = hostDao.findById(hostId);
|
||||
_capacityMgr.updateCapacityForHost(host);
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import com.cloud.dc.dao.ASNumberRangeDao;
|
|||
import com.cloud.dc.dao.VlanDetailsDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.network.vpc.VpcGateway;
|
||||
import com.cloud.network.vpn.Site2SiteVpnManager;
|
||||
import com.cloud.storage.BucketVO;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
|
|
@ -528,6 +529,8 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
@Inject
|
||||
RoutedIpv4Manager routedIpv4Manager;
|
||||
@Inject
|
||||
Site2SiteVpnManager site2SiteVpnManager;
|
||||
@Inject
|
||||
ResourceIconManager resourceIconManager;
|
||||
|
||||
public static String getPrettyDomainPath(String path) {
|
||||
|
|
@ -3884,6 +3887,16 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
response.setRemoved(result.getRemoved());
|
||||
response.setIkeVersion(result.getIkeVersion());
|
||||
response.setSplitConnections(result.getSplitConnections());
|
||||
|
||||
Set<String> obsoleteParameters = site2SiteVpnManager.getObsoleteVpnGatewayParameters(result);
|
||||
if (CollectionUtils.isNotEmpty(obsoleteParameters)) {
|
||||
response.setContainsObsoleteParameters(obsoleteParameters.toString());
|
||||
}
|
||||
Set<String> excludedParameters = site2SiteVpnManager.getExcludedVpnGatewayParameters(result);
|
||||
if (CollectionUtils.isNotEmpty(excludedParameters)) {
|
||||
response.setContainsExcludedParameters(excludedParameters.toString());
|
||||
}
|
||||
|
||||
response.setObjectName("vpncustomergateway");
|
||||
response.setHasAnnotation(annotationDao.hasAnnotations(result.getUuid(), AnnotationService.EntityType.VPN_CUSTOMER_GATEWAY.name(),
|
||||
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@ import java.util.stream.Collectors;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.consoleproxy.ConsoleProxyManager;
|
||||
import com.cloud.network.router.VirtualNetworkApplianceManager;
|
||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||
import com.cloud.utils.DomainHelper;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
|
|
@ -150,7 +155,6 @@ import com.cloud.api.query.vo.NetworkOfferingJoinVO;
|
|||
import com.cloud.capacity.CapacityManager;
|
||||
import com.cloud.capacity.dao.CapacityDao;
|
||||
import com.cloud.configuration.Resource.ResourceType;
|
||||
import com.cloud.consoleproxy.ConsoleProxyManager;
|
||||
import com.cloud.dc.AccountVlanMapVO;
|
||||
import com.cloud.dc.ClusterDetailsDao;
|
||||
import com.cloud.dc.ClusterDetailsVO;
|
||||
|
|
@ -245,7 +249,6 @@ import com.cloud.network.dao.UserIpv6AddressDao;
|
|||
import com.cloud.network.element.NetrisProviderVO;
|
||||
import com.cloud.network.element.NsxProviderVO;
|
||||
import com.cloud.network.netris.NetrisService;
|
||||
import com.cloud.network.router.VirtualNetworkApplianceManager;
|
||||
import com.cloud.network.rules.LoadBalancerContainer.Scheme;
|
||||
import com.cloud.network.vpc.VpcManager;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
|
|
@ -280,7 +283,6 @@ import com.cloud.storage.dao.DiskOfferingDao;
|
|||
import com.cloud.storage.dao.StoragePoolTagsDao;
|
||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||
import com.cloud.test.IPRangeConfig;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountDetailVO;
|
||||
|
|
@ -314,7 +316,6 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
|||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.NicIpAlias;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
import com.cloud.vm.dao.NicIpAliasDao;
|
||||
import com.cloud.vm.dao.NicIpAliasVO;
|
||||
|
|
@ -399,6 +400,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
ClusterDao _clusterDao;
|
||||
@Inject
|
||||
AlertManager _alertMgr;
|
||||
@Inject
|
||||
DomainHelper domainHelper;
|
||||
List<SecurityChecker> _secChecker;
|
||||
List<ExternalProvisioner> externalProvisioners;
|
||||
|
||||
|
|
@ -3519,7 +3522,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
final boolean isCustomized, final boolean encryptRoot, Long vgpuProfileId, Integer gpuCount, Boolean gpuDisplay, final boolean purgeResources, Integer leaseDuration, VMLeaseManager.ExpiryAction leaseExpiryAction) {
|
||||
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
|
||||
// Check if user exists in the system
|
||||
final User user = _userDao.findById(userId);
|
||||
|
|
@ -3908,7 +3911,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
final Account account = _accountDao.findById(user.getAccountId());
|
||||
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
Collections.sort(filteredDomainIds);
|
||||
|
||||
// avoid domain update of service offering if any instance is associated to it
|
||||
|
|
@ -4118,7 +4121,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
|
||||
// Check if user exists in the system
|
||||
final User user = _userDao.findById(userId);
|
||||
|
|
@ -4394,7 +4397,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
final Account account = _accountDao.findById(user.getAccountId());
|
||||
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
Collections.sort(filteredDomainIds);
|
||||
|
||||
List<Long> filteredZoneIds = new ArrayList<>();
|
||||
|
|
@ -7401,7 +7404,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
if (offering != null) {
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
List<NetworkOfferingDetailsVO> detailsVO = new ArrayList<>();
|
||||
for (Long domainId : filteredDomainIds) {
|
||||
detailsVO.add(new NetworkOfferingDetailsVO(offering.getId(), Detail.domainid, String.valueOf(domainId), false));
|
||||
|
|
@ -7867,7 +7870,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
}
|
||||
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
Collections.sort(filteredDomainIds);
|
||||
|
||||
List<Long> filteredZoneIds = new ArrayList<>();
|
||||
|
|
@ -8434,30 +8437,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
|||
return false;
|
||||
}
|
||||
|
||||
private List<Long> filterChildSubDomains(final List<Long> domainIds) {
|
||||
List<Long> filteredDomainIds = new ArrayList<>();
|
||||
if (domainIds != null) {
|
||||
filteredDomainIds.addAll(domainIds);
|
||||
}
|
||||
if (filteredDomainIds.size() > 1) {
|
||||
for (int i = filteredDomainIds.size() - 1; i >= 1; i--) {
|
||||
long first = filteredDomainIds.get(i);
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
long second = filteredDomainIds.get(j);
|
||||
if (_domainDao.isChildDomain(filteredDomainIds.get(i), filteredDomainIds.get(j))) {
|
||||
filteredDomainIds.remove(j);
|
||||
i--;
|
||||
}
|
||||
if (_domainDao.isChildDomain(filteredDomainIds.get(j), filteredDomainIds.get(i))) {
|
||||
filteredDomainIds.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredDomainIds;
|
||||
}
|
||||
|
||||
protected void validateCacheMode(String cacheMode){
|
||||
if(cacheMode != null &&
|
||||
!Enums.getIfPresent(DiskOffering.DiskCacheMode.class,
|
||||
|
|
|
|||
|
|
@ -2409,7 +2409,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
|||
nic.setBroadcastUri(BroadcastDomainType.Vlan.toUri(ip.getVlanTag()));
|
||||
nic.setFormat(AddressFormat.Ip4);
|
||||
nic.setReservationId(String.valueOf(ip.getVlanTag()));
|
||||
if(nic.getMacAddress() == null) {
|
||||
if (nic.getMacAddress() == null) {
|
||||
nic.setMacAddress(ip.getMacAddress());
|
||||
}
|
||||
}
|
||||
|
|
@ -2460,7 +2460,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
|||
|
||||
nic.setBroadcastUri(network.getBroadcastUri());
|
||||
nic.setFormat(AddressFormat.Ip4);
|
||||
if(nic.getMacAddress() == null) {
|
||||
if (nic.getMacAddress() == null || !_networkModel.isMACUnique(nic.getMacAddress(), network.getId())) {
|
||||
nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ public class Ipv6AddressManagerImpl extends ManagerBase implements Ipv6AddressMa
|
|||
if (nic.getBroadCastUri() == null) {
|
||||
nic.setBroadcastUri(network.getBroadcastUri());
|
||||
}
|
||||
if (nic.getMacAddress() == null) {
|
||||
if (nic.getMacAddress() == null || !_networkModel.isMACUnique(nic.getMacAddress(), network.getId())) {
|
||||
nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -594,22 +594,34 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
|
|||
@Override
|
||||
public String getNextAvailableMacAddressInNetwork(long networkId) throws InsufficientAddressCapacityException {
|
||||
NetworkVO network = _networksDao.findById(networkId);
|
||||
Integer zoneIdentifier = MACIdentifier.value();
|
||||
if (zoneIdentifier.intValue() == 0) {
|
||||
zoneIdentifier = Long.valueOf(network.getDataCenterId()).intValue();
|
||||
if (network == null) {
|
||||
throw new CloudRuntimeException("Could not find network with id " + networkId);
|
||||
}
|
||||
|
||||
Integer zoneMacIdentifier = Long.valueOf(getMacIdentifier(network.getDataCenterId())).intValue();
|
||||
String mac;
|
||||
do {
|
||||
mac = _networksDao.getNextAvailableMacAddress(networkId, zoneIdentifier);
|
||||
mac = _networksDao.getNextAvailableMacAddress(networkId, zoneMacIdentifier);
|
||||
if (mac == null) {
|
||||
throw new InsufficientAddressCapacityException("Unable to create another mac address", Network.class, networkId);
|
||||
}
|
||||
} while(! isMACUnique(mac));
|
||||
} while (!isMACUnique(mac, networkId));
|
||||
return mac;
|
||||
}
|
||||
|
||||
private boolean isMACUnique(String mac) {
|
||||
return (_nicDao.findByMacAddress(mac) == null);
|
||||
@Override
|
||||
public String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException {
|
||||
String macAddressStr = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(macAddress, getMacIdentifier(datacenterId)));
|
||||
if (!isMACUnique(macAddressStr, networkId)) {
|
||||
macAddressStr = getNextAvailableMacAddressInNetwork(networkId);
|
||||
}
|
||||
return macAddressStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMACUnique(String mac, long networkId) {
|
||||
return (_nicDao.findByMacAddress(mac, networkId) == null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2818,4 +2830,18 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMacIdentifier(Long dataCenterId) {
|
||||
long macAddress = 0;
|
||||
if (dataCenterId == null) {
|
||||
macAddress = NetworkModel.MACIdentifier.value();
|
||||
} else {
|
||||
macAddress = NetworkModel.MACIdentifier.valueIn(dataCenterId);
|
||||
if (macAddress == 0) {
|
||||
macAddress = dataCenterId;
|
||||
}
|
||||
}
|
||||
return macAddress;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
|
|||
allocateDirectIp(nic, network, vm, dc, nic.getRequestedIPv4(), nic.getRequestedIPv6());
|
||||
nic.setReservationStrategy(ReservationStrategy.Create);
|
||||
|
||||
if (nic.getMacAddress() == null) {
|
||||
if (nic.getMacAddress() == null || !_networkModel.isMACUnique(nic.getMacAddress(), network.getId())) {
|
||||
nic.setMacAddress(_networkModel.getNextAvailableMacAddressInNetwork(network.getId()));
|
||||
if (nic.getMacAddress() == null) {
|
||||
throw new InsufficientAddressCapacityException("Unable to allocate more mac addresses", Network.class, network.getId());
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru {
|
|||
DataCenterDao _dcDao;
|
||||
@Inject
|
||||
StorageNetworkManager _sNwMgr;
|
||||
@Inject
|
||||
NetworkModel _networkModel;
|
||||
|
||||
Random _rand = new Random(System.currentTimeMillis());
|
||||
|
||||
|
|
@ -131,7 +133,8 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru {
|
|||
Integer vlan = result.getVlan();
|
||||
|
||||
nic.setIPv4Address(result.getIpAddress());
|
||||
nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(result.getMacAddress(), NetworkModel.MACIdentifier.value())));
|
||||
String macAddress = _networkModel.getUniqueMacAddress(result.getMacAddress(), config.getId(), dest.getDataCenter().getId());
|
||||
nic.setMacAddress(macAddress);
|
||||
nic.setIPv4Gateway(pod.getGateway());
|
||||
nic.setFormat(AddressFormat.Ip4);
|
||||
String netmask = NetUtils.getCidrNetmask(pod.getCidrSize());
|
||||
|
|
|
|||
|
|
@ -189,8 +189,12 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
|
|||
PrivateIpVO ipVO = _privateIpDao.allocateIpAddress(network.getDataCenterId(), network.getId(), null);
|
||||
String vlanTag = BroadcastDomainType.getValue(network.getBroadcastUri());
|
||||
String netmask = NetUtils.getCidrNetmask(network.getCidr());
|
||||
String macAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), networkModel.getMacIdentifier(network.getDataCenterId())));
|
||||
if (!networkModel.isMACUnique(macAddress, network.getId())) {
|
||||
macAddress = networkModel.getNextAvailableMacAddressInNetwork(network.getId());
|
||||
}
|
||||
PrivateIpAddress ip =
|
||||
new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value())));
|
||||
new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, macAddress);
|
||||
|
||||
nic.setIPv4Address(ip.getIpAddress());
|
||||
nic.setIPv4Gateway(ip.getGateway());
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import com.cloud.network.dao.NetworkDao;
|
|||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.Nic.ReservationStrategy;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.ReservationContext;
|
||||
|
|
@ -47,6 +46,8 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu
|
|||
@Inject
|
||||
StorageNetworkManager _sNwMgr;
|
||||
@Inject
|
||||
NetworkModel _networkModel;
|
||||
@Inject
|
||||
NetworkDao _nwDao;
|
||||
|
||||
protected StorageNetworkGuru() {
|
||||
|
|
@ -130,7 +131,8 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu
|
|||
|
||||
vlan = ip.getVlan();
|
||||
nic.setIPv4Address(ip.getIpAddress());
|
||||
nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ip.getMac(), NetworkModel.MACIdentifier.value())));
|
||||
String macAddress = _networkModel.getUniqueMacAddress(ip.getMac(), network.getId(), dest.getDataCenter().getId());
|
||||
nic.setMacAddress(macAddress);
|
||||
nic.setFormat(AddressFormat.Ip4);
|
||||
nic.setIPv4Netmask(ip.getNetmask());
|
||||
nic.setBroadcastType(BroadcastDomainType.Storage);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
// under the License.
|
||||
package com.cloud.network.router;
|
||||
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
|
||||
|
||||
import com.cloud.network.Network;
|
||||
|
|
@ -24,7 +25,7 @@ import com.cloud.vm.NicProfile;
|
|||
|
||||
public interface NicProfileHelper {
|
||||
|
||||
public abstract NicProfile createPrivateNicProfileForGateway(final VpcGateway privateGateway, final VirtualRouter router);
|
||||
public abstract NicProfile createPrivateNicProfileForGateway(final VpcGateway privateGateway, final VirtualRouter router) throws InsufficientAddressCapacityException;
|
||||
|
||||
public abstract NicProfile createGuestNicProfileForVpcRouter(final RouterDeploymentDefinition vpcRouterDeploymentDefinition,
|
||||
Network guestNetwork);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import java.net.URI;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import com.cloud.vm.NicVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
|
||||
|
|
@ -61,7 +62,7 @@ public class NicProfileHelperImpl implements NicProfileHelper {
|
|||
|
||||
@Override
|
||||
@DB
|
||||
public NicProfile createPrivateNicProfileForGateway(final VpcGateway privateGateway, final VirtualRouter router) {
|
||||
public NicProfile createPrivateNicProfileForGateway(final VpcGateway privateGateway, final VirtualRouter router) throws InsufficientAddressCapacityException {
|
||||
final Network privateNetwork = _networkModel.getNetwork(privateGateway.getNetworkId());
|
||||
|
||||
PrivateIpVO ipVO = _privateIpDao.allocateIpAddress(privateNetwork.getDataCenterId(), privateNetwork.getId(), privateGateway.getIp4Address());
|
||||
|
|
@ -90,14 +91,14 @@ public class NicProfileHelperImpl implements NicProfileHelper {
|
|||
privateNicProfile.setDeviceId(null);
|
||||
|
||||
if (router.getIsRedundantRouter()) {
|
||||
String newMacAddress = NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value()));
|
||||
privateNicProfile.setMacAddress(newMacAddress);
|
||||
String newMacAddress = _networkModel.getUniqueMacAddress(ipVO.getMacAddress(), privateNetwork.getId(), privateNetwork.getDataCenterId());
|
||||
privateNicProfile.setMacAddress(newMacAddress);
|
||||
}
|
||||
} else {
|
||||
final String netmask = NetUtils.getCidrNetmask(privateNetwork.getCidr());
|
||||
String newMacAddress = _networkModel.getUniqueMacAddress(ipVO.getMacAddress(), privateNetwork.getId(), privateNetwork.getDataCenterId());
|
||||
final PrivateIpAddress ip =
|
||||
new PrivateIpAddress(ipVO, privateNetwork.getBroadcastUri().toString(), privateNetwork.getGateway(), netmask,
|
||||
NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ipVO.getMacAddress(), NetworkModel.MACIdentifier.value())));
|
||||
new PrivateIpAddress(ipVO, privateNetwork.getBroadcastUri().toString(), privateNetwork.getGateway(), netmask, newMacAddress);
|
||||
|
||||
final URI netUri = BroadcastDomainType.fromString(ip.getBroadcastUri());
|
||||
privateNicProfile.setIPv4Address(ip.getIpAddress());
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ import com.cloud.network.element.NetworkACLServiceProvider;
|
|||
import com.cloud.network.element.NsxProviderVO;
|
||||
import com.cloud.network.rules.RulesManager;
|
||||
import com.cloud.network.vpn.RemoteAccessVpnService;
|
||||
import com.cloud.utils.DomainHelper;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
|
|
@ -285,6 +286,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
@Inject
|
||||
DomainDao domainDao;
|
||||
@Inject
|
||||
DomainHelper domainHelper;
|
||||
@Inject
|
||||
private AnnotationDao annotationDao;
|
||||
@Inject
|
||||
NetworkOfferingDao _networkOfferingDao;
|
||||
|
|
@ -636,7 +639,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
}
|
||||
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
|
||||
final Map<Network.Service, Set<Network.Provider>> svcProviderMap = new HashMap<Network.Service, Set<Network.Provider>>();
|
||||
final Set<Network.Provider> defaultProviders = new HashSet<Network.Provider>();
|
||||
|
|
@ -1118,7 +1121,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
|
||||
|
||||
// Filter child domains when both parent and child domains are present
|
||||
List<Long> filteredDomainIds = filterChildSubDomains(domainIds);
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
Collections.sort(filteredDomainIds);
|
||||
|
||||
List<Long> filteredZoneIds = new ArrayList<>();
|
||||
|
|
@ -3658,30 +3661,6 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
return _ntwkMgr.areRoutersRunning(routerDao.listByVpcId(vpc.getId()));
|
||||
}
|
||||
|
||||
private List<Long> filterChildSubDomains(final List<Long> domainIds) {
|
||||
List<Long> filteredDomainIds = new ArrayList<>();
|
||||
if (domainIds != null) {
|
||||
filteredDomainIds.addAll(domainIds);
|
||||
}
|
||||
if (filteredDomainIds.size() > 1) {
|
||||
for (int i = filteredDomainIds.size() - 1; i >= 1; i--) {
|
||||
long first = filteredDomainIds.get(i);
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
long second = filteredDomainIds.get(j);
|
||||
if (domainDao.isChildDomain(filteredDomainIds.get(i), filteredDomainIds.get(j))) {
|
||||
filteredDomainIds.remove(j);
|
||||
i--;
|
||||
}
|
||||
if (domainDao.isChildDomain(filteredDomainIds.get(j), filteredDomainIds.get(i))) {
|
||||
filteredDomainIds.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredDomainIds;
|
||||
}
|
||||
|
||||
protected boolean isGlobalAcl(Long aclVpcId) {
|
||||
return aclVpcId != null && aclVpcId == 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,17 @@
|
|||
package com.cloud.network.vpn;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.cloud.network.Site2SiteCustomerGateway;
|
||||
import com.cloud.network.dao.Site2SiteVpnConnectionVO;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
|
||||
public interface Site2SiteVpnManager extends Site2SiteVpnService {
|
||||
Set<String> getExcludedVpnGatewayParameters(Site2SiteCustomerGateway customerGw);
|
||||
|
||||
Set<String> getObsoleteVpnGatewayParameters(Site2SiteCustomerGateway customerGw);
|
||||
|
||||
boolean cleanupVpnConnectionByVpc(long vpcId);
|
||||
|
||||
boolean cleanupVpnGatewayByVpc(long vpcId);
|
||||
|
|
|
|||
|
|
@ -17,15 +17,22 @@
|
|||
package com.cloud.network.vpn;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.framework.config.Configurable;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import org.apache.cloudstack.alert.AlertService;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
import org.apache.cloudstack.api.command.user.vpn.CreateVpnConnectionCmd;
|
||||
|
|
@ -41,9 +48,16 @@ import org.apache.cloudstack.api.command.user.vpn.ResetVpnConnectionCmd;
|
|||
import org.apache.cloudstack.api.command.user.vpn.UpdateVpnCustomerGatewayCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.ConfigKeyScheduledExecutionWrapper;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.event.ActionEvent;
|
||||
import com.cloud.event.ActionEventUtils;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
|
|
@ -72,9 +86,11 @@ import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
|
|||
import com.cloud.projects.Project.ListProjectResourcesCriteria;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.utils.db.DB;
|
||||
|
|
@ -88,7 +104,52 @@ import com.cloud.vm.DomainRouterVO;
|
|||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
|
||||
@Component
|
||||
public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpnManager {
|
||||
public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpnManager, Configurable {
|
||||
|
||||
// Configuration keys for VPN gateway cryptographic parameter controls
|
||||
public static final ConfigKey<String> VpnCustomerGatewayExcludedEncryptionAlgorithms = new ConfigKey<String>(
|
||||
ConfigKey.CATEGORY_NETWORK, String.class, "vpn.customer.gateway.excluded.encryption.algorithms", "",
|
||||
"Comma-separated list of encryption algorithms that are excluded and cannot be selected by end users for VPN Customer Gateways." +
|
||||
"Applies to both IKE and ESP phases. Allowed values are aes128, aes192 and aes256 and 3des.",
|
||||
true, ConfigKey.Scope.Domain);
|
||||
public static final ConfigKey<String> VpnCustomerGatewayExcludedHashingAlgorithms = new ConfigKey<String>(
|
||||
ConfigKey.CATEGORY_NETWORK, String.class, "vpn.customer.gateway.excluded.hashing.algorithms", "",
|
||||
"Comma-separated list of hashing algorithms that are excluded and cannot be selected by end users for VPN Customer Gateways." +
|
||||
"Applies to both IKE and ESP phases. Allowed values are sha1, sha256, sha384 and sha512 and md5.",
|
||||
true, ConfigKey.Scope.Domain);
|
||||
public static final ConfigKey<String> VpnCustomerGatewayExcludedIkeVersions = new ConfigKey<String>(
|
||||
ConfigKey.CATEGORY_NETWORK, String.class, "vpn.customer.gateway.excluded.ike.versions", "",
|
||||
"Comma-separated list of IKE versions that are excluded and cannot be selected by end users for VPN Customer Gateways. Allowed values are ikev, ikev1 and ikev2.",
|
||||
true, ConfigKey.Scope.Domain);
|
||||
public static final ConfigKey<String> VpnCustomerGatewayExcludedDhGroup = new ConfigKey<String>(
|
||||
ConfigKey.CATEGORY_NETWORK, String.class, "vpn.customer.gateway.excluded.dh.group", "",
|
||||
"Comma-separated list of Diffie-Hellman groups that are excluded and cannot be selected by end users for VPN Customer Gateways." +
|
||||
"Applies to both IKE and ESP phases. Allowed values are modp1024, modp1536, modp2048, modp3072, modp4096, modp6144 and modp8192.",
|
||||
true, ConfigKey.Scope.Domain);
|
||||
public static final ConfigKey<String> VpnCustomerGatewayObsoleteEncryptionAlgorithms = new ConfigKey<String>(
|
||||
ConfigKey.CATEGORY_NETWORK, String.class, "vpn.customer.gateway.obsolete.encryption.algorithms", "",
|
||||
"Comma-separated list of encryption algorithms that are marked as obsolete/insecure for VPN Customer Gateways." +
|
||||
"Applies to both IKE and ESP phases. Allowed values are aes128, aes192 and aes256 and 3des.",
|
||||
true, ConfigKey.Scope.Domain);
|
||||
public static final ConfigKey<String> VpnCustomerGatewayObsoleteHashingAlgorithms = new ConfigKey<String>(
|
||||
ConfigKey.CATEGORY_NETWORK, String.class, "vpn.customer.gateway.obsolete.hashing.algorithms", "",
|
||||
"Comma-separated list of hashing algorithms that are marked as obsolete/insecure for VPN Customer Gateways." +
|
||||
"Applies to both IKE and ESP phases. Allowed values are sha1, sha256, sha384 and sha512 and md5.",
|
||||
true, ConfigKey.Scope.Domain);
|
||||
public static final ConfigKey<String> VpnCustomerGatewayObsoleteIkeVersions = new ConfigKey<String>(
|
||||
ConfigKey.CATEGORY_NETWORK, String.class, "vpn.customer.gateway.obsolete.ike.versions", "",
|
||||
"Comma-separated list of IKE versions that are marked as obsolete/insecure for VPN Customer Gateways. Allowed values are ikev, ikev1 and ikev2.",
|
||||
true, ConfigKey.Scope.Domain);
|
||||
public static final ConfigKey<String> VpnCustomerGatewayObsoleteDhGroup = new ConfigKey<String>(
|
||||
ConfigKey.CATEGORY_NETWORK, String.class, "vpn.customer.gateway.obsolete.dh.group", "",
|
||||
"Comma-separated list of Diffie-Hellman groups that are marked as obsolete/insecure for VPN Customer Gateways." +
|
||||
"Applies to both IKE and ESP phases. Allowed values are modp1024, modp1536, modp2048, modp3072, modp4096, modp6144 and modp8192.",
|
||||
true, ConfigKey.Scope.Domain);
|
||||
public static final ConfigKey<Long> VpnCustomerGatewayObsoleteCheckInterval = new ConfigKey<Long>(
|
||||
ConfigKey.CATEGORY_NETWORK, Long.class, "vpn.customer.gateway.obsolete.check.interval", "0",
|
||||
"Interval in hours to periodically check VPN customer gateways for obsolete/excluded parameters and generate events and alerts. " +
|
||||
"Set to 0 to disable. Default: 0 (disabled).",
|
||||
true, ConfigKey.Scope.Global);
|
||||
|
||||
List<Site2SiteVpnServiceProvider> _s2sProviders;
|
||||
@Inject
|
||||
|
|
@ -117,9 +178,12 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
private IpAddressManager ipAddressManager;
|
||||
@Inject
|
||||
private VpcManager vpcManager;
|
||||
@Inject
|
||||
private AlertManager _alertMgr;
|
||||
|
||||
int _connLimit;
|
||||
int _subnetsLimit;
|
||||
private ScheduledExecutorService _vpnCheckExecutor;
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
|
|
@ -127,6 +191,7 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
_connLimit = NumbersUtil.parseInt(configs.get(Config.Site2SiteVpnConnectionPerVpnGatewayLimit.key()), 4);
|
||||
_subnetsLimit = NumbersUtil.parseInt(configs.get(Config.Site2SiteVpnSubnetsPerCustomerGatewayLimit.key()), 10);
|
||||
assert (_s2sProviders.iterator().hasNext()) : "Did not get injected with a list of S2S providers!";
|
||||
_vpnCheckExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpnCustomerGateway-ExcludedAndObsoleteCheck"));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +211,7 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
}
|
||||
Site2SiteVpnGatewayVO gws = _vpnGatewayDao.findByVpcId(vpcId);
|
||||
if (gws != null) {
|
||||
throw new InvalidParameterValueException(String.format("The VPN gateway of VPC %s already existed!", vpc));
|
||||
throw new InvalidParameterValueException(String.format("The VPN gateway of VPC %s already exists!", vpc));
|
||||
}
|
||||
|
||||
IPAddressVO requestedIp = _ipAddressDao.findById(cmd.getIpAddressId());
|
||||
|
|
@ -187,6 +252,113 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
}
|
||||
}
|
||||
|
||||
private void validateVpnCryptographicParameters(String ikePolicy, String espPolicy, String ikeVersion, Long domainId) {
|
||||
String excludedEncryption = VpnCustomerGatewayExcludedEncryptionAlgorithms.valueIn(domainId);
|
||||
String excludedHashing = VpnCustomerGatewayExcludedHashingAlgorithms.valueIn(domainId);
|
||||
String excludedIkeVersions = VpnCustomerGatewayExcludedIkeVersions.valueIn(domainId);
|
||||
String excludedDhGroup = VpnCustomerGatewayExcludedDhGroup.valueIn(domainId);
|
||||
|
||||
Set<String> excludedParameters = getVpnGatewayParametersInBlockedList(ikePolicy, espPolicy, ikeVersion,
|
||||
excludedEncryption, excludedHashing, excludedIkeVersions, excludedDhGroup);
|
||||
if (!excludedParameters.isEmpty()) {
|
||||
throw new InvalidParameterValueException("The following excluded cryptographic parameter(s) cannot be used in a VPN Customer Gateway: " + excludedParameters.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getExcludedVpnGatewayParameters(Site2SiteCustomerGateway customerGw) {
|
||||
Long domainId = customerGw.getDomainId();
|
||||
String excludedEncryption = VpnCustomerGatewayExcludedEncryptionAlgorithms.valueIn(domainId);
|
||||
String excludedHashing = VpnCustomerGatewayExcludedHashingAlgorithms.valueIn(domainId);
|
||||
String excludedIkeVersions = VpnCustomerGatewayExcludedIkeVersions.valueIn(domainId);
|
||||
String excludedDhGroup = VpnCustomerGatewayExcludedDhGroup.valueIn(domainId);
|
||||
|
||||
return getVpnGatewayParametersInBlockedList(customerGw.getIkePolicy(), customerGw.getEspPolicy(), customerGw.getIkeVersion(),
|
||||
excludedEncryption, excludedHashing, excludedIkeVersions, excludedDhGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getObsoleteVpnGatewayParameters(Site2SiteCustomerGateway customerGw) {
|
||||
Long domainId = customerGw.getDomainId();
|
||||
String obsoleteEncryption = VpnCustomerGatewayObsoleteEncryptionAlgorithms.valueIn(domainId);
|
||||
String obsoleteHashing = VpnCustomerGatewayObsoleteHashingAlgorithms.valueIn(domainId);
|
||||
String obsoleteIkeVersions = VpnCustomerGatewayObsoleteIkeVersions.valueIn(domainId);
|
||||
String obsoleteDhGroup = VpnCustomerGatewayObsoleteDhGroup.valueIn(domainId);
|
||||
|
||||
return getVpnGatewayParametersInBlockedList(customerGw.getIkePolicy(), customerGw.getEspPolicy(), customerGw.getIkeVersion(),
|
||||
obsoleteEncryption, obsoleteHashing, obsoleteIkeVersions, obsoleteDhGroup);
|
||||
}
|
||||
|
||||
private Set<String> getVpnGatewayParametersInBlockedList(String ikePolicy, String espPolicy, String ikeVersion,
|
||||
String blockedEncryptionList, String blockedHashingList,
|
||||
String blockedIkeVersionList, String blockedDhGroupList) {
|
||||
|
||||
Set<String> blockedParameters = new HashSet<>();
|
||||
if (StringUtils.isEmpty(blockedEncryptionList)
|
||||
&& StringUtils.isEmpty(blockedHashingList)
|
||||
&& StringUtils.isEmpty(blockedIkeVersionList)
|
||||
&& StringUtils.isEmpty(blockedDhGroupList)) {
|
||||
return blockedParameters;
|
||||
}
|
||||
|
||||
if (isParameterInList(ikeVersion, blockedIkeVersionList)) {
|
||||
blockedParameters.add(ikeVersion);
|
||||
}
|
||||
|
||||
Set<String> ikePolicyResult = getVpnGatewayPolicyParametersInBlockedList(ikePolicy, "IKE", blockedEncryptionList, blockedHashingList, blockedDhGroupList);
|
||||
if (CollectionUtils.isNotEmpty(ikePolicyResult)) {
|
||||
blockedParameters.addAll(ikePolicyResult);
|
||||
}
|
||||
|
||||
Set<String> espPolicyResult = getVpnGatewayPolicyParametersInBlockedList(espPolicy, "ESP", blockedEncryptionList, blockedHashingList, blockedDhGroupList);
|
||||
if (CollectionUtils.isNotEmpty(espPolicyResult)) {
|
||||
blockedParameters.addAll(espPolicyResult);
|
||||
}
|
||||
|
||||
return blockedParameters;
|
||||
}
|
||||
|
||||
private Set<String> getVpnGatewayPolicyParametersInBlockedList(String policy, String policyType, String blockedEncryptionList, String blockedHashingList, String blockedDhGroupList) {
|
||||
|
||||
String trimmedPolicy = policy.trim();
|
||||
String cipherHash = trimmedPolicy.split(";")[0];
|
||||
String[] parts = cipherHash.split("-");
|
||||
|
||||
String encryption = parts[0].trim();
|
||||
String hashing = parts.length > 1 ? parts[1].trim() : "";
|
||||
|
||||
Set<String> blockedParameters = new HashSet<>();
|
||||
if (isParameterInList(encryption, blockedEncryptionList)) {
|
||||
blockedParameters.add(encryption);
|
||||
}
|
||||
|
||||
if (isParameterInList(hashing, blockedHashingList)) {
|
||||
blockedParameters.add(hashing);
|
||||
}
|
||||
|
||||
if (!trimmedPolicy.equals(cipherHash)) {
|
||||
String dhGroup = trimmedPolicy.split(";")[1].trim();
|
||||
if (isParameterInList(dhGroup, blockedDhGroupList)) {
|
||||
blockedParameters.add(dhGroup);
|
||||
}
|
||||
}
|
||||
return blockedParameters;
|
||||
}
|
||||
|
||||
private boolean isParameterInList(String parameter, String list) {
|
||||
if (StringUtils.isEmpty(list) || StringUtils.isEmpty(parameter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] entries = list.split(",");
|
||||
for (String item : entries) {
|
||||
if (item != null && item.trim().equalsIgnoreCase(parameter.trim())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void checkCustomerGatewayCidrList(String guestCidrList) {
|
||||
String[] cidrList = guestCidrList.split(",");
|
||||
if (cidrList.length > _subnetsLimit) {
|
||||
|
|
@ -235,6 +407,13 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
if (!NetUtils.isValidS2SVpnPolicy("esp", espPolicy)) {
|
||||
throw new InvalidParameterValueException("The customer gateway ESP policy " + espPolicy + " is invalid!");
|
||||
}
|
||||
|
||||
String ikeVersion = cmd.getIkeVersion();
|
||||
if (ikeVersion == null) {
|
||||
ikeVersion = "ike";
|
||||
}
|
||||
validateVpnCryptographicParameters(ikePolicy, espPolicy, ikeVersion, owner.getDomainId());
|
||||
|
||||
Long ikeLifetime = cmd.getIkeLifetime();
|
||||
if (ikeLifetime == null) {
|
||||
// Default value of lifetime is 1 day
|
||||
|
|
@ -264,7 +443,7 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
|
||||
long accountId = owner.getAccountId();
|
||||
if (_customerGatewayDao.findByNameAndAccountId(name, accountId) != null) {
|
||||
throw new InvalidParameterValueException("The customer gateway with name " + name + " already existed!");
|
||||
throw new InvalidParameterValueException("The customer gateway with name " + name + " already exists!");
|
||||
}
|
||||
|
||||
Boolean splitConnections = cmd.getSplitConnections();
|
||||
|
|
@ -272,11 +451,6 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
splitConnections = false;
|
||||
}
|
||||
|
||||
String ikeVersion = cmd.getIkeVersion();
|
||||
if (ikeVersion == null) {
|
||||
ikeVersion = "ike";
|
||||
}
|
||||
|
||||
checkCustomerGatewayCidrList(peerCidrList);
|
||||
|
||||
Site2SiteCustomerGatewayVO gw =
|
||||
|
|
@ -374,7 +548,7 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
|
||||
private void validateVpnConnectionDoesntExist(Site2SiteCustomerGateway customerGateway, Site2SiteVpnGateway vpnGateway) {
|
||||
if (_vpnConnectionDao.findByVpnGatewayIdAndCustomerGatewayId(vpnGateway.getId(), customerGateway.getId()) != null) {
|
||||
throw new InvalidParameterValueException(String.format("The vpn connection with customer gateway %s and vpn gateway %s already existed!", customerGateway, vpnGateway));
|
||||
throw new InvalidParameterValueException(String.format("The vpn connection with customer gateway %s and vpn gateway %s already exists!", customerGateway, vpnGateway));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -521,6 +695,10 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
if (!NetUtils.isValidS2SVpnPolicy("esp", espPolicy)) {
|
||||
throw new InvalidParameterValueException("The customer gateway ESP policy" + espPolicy + " is invalid!");
|
||||
}
|
||||
|
||||
String ikeVersion = cmd.getIkeVersion();
|
||||
validateVpnCryptographicParameters(ikePolicy, espPolicy, ikeVersion, gw.getDomainId());
|
||||
|
||||
Long ikeLifetime = cmd.getIkeLifetime();
|
||||
if (ikeLifetime == null) {
|
||||
// Default value of lifetime is 1 day
|
||||
|
|
@ -550,14 +728,12 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
|
||||
Boolean splitConnections = cmd.getSplitConnections();
|
||||
|
||||
String ikeVersion = cmd.getIkeVersion();
|
||||
|
||||
checkCustomerGatewayCidrList(guestCidrList);
|
||||
|
||||
long accountId = gw.getAccountId();
|
||||
Site2SiteCustomerGatewayVO existedGw = _customerGatewayDao.findByNameAndAccountId(name, accountId);
|
||||
if (existedGw != null && existedGw.getId() != gw.getId()) {
|
||||
throw new InvalidParameterValueException("The customer gateway with name " + name + " already existed!");
|
||||
throw new InvalidParameterValueException("The customer gateway with name " + name + " already exists!");
|
||||
}
|
||||
|
||||
gw.setName(name);
|
||||
|
|
@ -977,4 +1153,83 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
|||
return _vpnGatewayDao.findById(id);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
ConfigKeyScheduledExecutionWrapper runner = new ConfigKeyScheduledExecutionWrapper(
|
||||
_vpnCheckExecutor,
|
||||
new CheckVpnCustomerGatewayObsoleteParametersTask(),
|
||||
VpnCustomerGatewayObsoleteCheckInterval,
|
||||
3600,
|
||||
TimeUnit.HOURS);
|
||||
runner.start();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
if (_vpnCheckExecutor != null) {
|
||||
_vpnCheckExecutor.shutdownNow();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigComponentName() {
|
||||
return Site2SiteVpnManager.class.getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] { VpnCustomerGatewayExcludedEncryptionAlgorithms, VpnCustomerGatewayExcludedHashingAlgorithms,
|
||||
VpnCustomerGatewayExcludedIkeVersions, VpnCustomerGatewayExcludedDhGroup, VpnCustomerGatewayObsoleteEncryptionAlgorithms,
|
||||
VpnCustomerGatewayObsoleteHashingAlgorithms, VpnCustomerGatewayObsoleteIkeVersions, VpnCustomerGatewayObsoleteDhGroup,
|
||||
VpnCustomerGatewayObsoleteCheckInterval};
|
||||
}
|
||||
|
||||
protected class CheckVpnCustomerGatewayObsoleteParametersTask extends ManagedContextRunnable {
|
||||
|
||||
@Override
|
||||
protected void runInContext() {
|
||||
List<Site2SiteCustomerGatewayVO> allGateways = _customerGatewayDao.listAll();
|
||||
int obsoleteCount = 0;
|
||||
int excludedCount = 0;
|
||||
|
||||
for (Site2SiteCustomerGatewayVO gateway : allGateways) {
|
||||
Set<String> excludedParameters = getExcludedVpnGatewayParameters(gateway);
|
||||
Set<String> obsoleteParameters = getObsoleteVpnGatewayParameters(gateway);
|
||||
|
||||
List<String> message = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(excludedParameters)) {
|
||||
excludedCount++;
|
||||
message.add("excluded parameter(s) " + excludedParameters.toString());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(obsoleteParameters)) {
|
||||
obsoleteCount++;
|
||||
message.add("obsolete parameter(s) " + obsoleteParameters.toString());
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(message)) {
|
||||
Account account = _accountDao.findById(gateway.getAccountId());
|
||||
String description = String.format("VPN customer gateway '%s' (Account: %s) contains %s.",
|
||||
gateway.getName(), account.getAccountName(), String.join(" and ", message));
|
||||
ActionEventUtils.onActionEvent(User.UID_SYSTEM, gateway.getAccountId(), gateway.getDomainId(),
|
||||
EventTypes.EVENT_S2S_VPN_GATEWAY_OBSOLETE_PARAMS, description,
|
||||
gateway.getId(), Site2SiteCustomerGateway.class.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
List<String> message = new ArrayList<>();
|
||||
if (excludedCount > 0) {
|
||||
message.add("excluded parameters: " + excludedCount);
|
||||
}
|
||||
if (obsoleteCount > 0) {
|
||||
message.add("obsolete parameters: " + obsoleteCount);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(message)) {
|
||||
String subject = String.format("VPN customer gateways using " + String.join(", ", message));
|
||||
_alertMgr.sendAlert(AlertService.AlertType.ALERT_TYPE_VPN_GATEWAY_OBSOLETE_PARAMETERS, 0L, 0L, subject, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -720,6 +720,7 @@ import com.cloud.deploy.DeploymentPlan;
|
|||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.deploy.DeploymentPlanningManager;
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import com.cloud.event.ActionEvent;
|
||||
|
|
@ -761,6 +762,7 @@ import com.cloud.network.IpAddressManagerImpl;
|
|||
import com.cloud.network.Network;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.vpn.Site2SiteVpnManagerImpl;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.LoadBalancerDao;
|
||||
|
|
@ -4778,6 +4780,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
final Map<String, Object> capabilities = new HashMap<>();
|
||||
|
||||
final Account caller = getCaller();
|
||||
Long domainId = cmd.getDomainId();
|
||||
if (domainId == null) {
|
||||
domainId = caller.getDomainId();
|
||||
} else {
|
||||
Domain domain = _domainDao.findById(domainId);
|
||||
_accountService.checkAccess(caller, domain);
|
||||
}
|
||||
|
||||
final boolean isCallerRootAdmin = _accountService.isRootAdmin(caller.getId());
|
||||
final boolean isCallerAdmin = isCallerRootAdmin || _accountService.isAdmin(caller.getId());
|
||||
boolean securityGroupsEnabled = false;
|
||||
|
|
@ -4812,7 +4822,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
final boolean allowUserExpungeRecoverVolume = (VolumeApiServiceImpl.AllowUserExpungeRecoverVolume.valueIn(caller.getId()) | isCallerAdmin);
|
||||
final boolean allowUserForceStopVM = (UserVmManager.AllowUserForceStopVm.valueIn(caller.getId()) | isCallerAdmin);
|
||||
|
||||
final boolean allowUserViewAllDomainAccounts = (QueryService.AllowUserViewAllDomainAccounts.valueIn(caller.getDomainId()));
|
||||
final boolean allowUserViewAllDomainAccounts = (QueryService.AllowUserViewAllDomainAccounts.valueIn(domainId));
|
||||
|
||||
final boolean kubernetesServiceEnabled = Boolean.parseBoolean(_configDao.getValue("cloud.kubernetes.service.enabled"));
|
||||
final boolean kubernetesClusterExperimentalFeaturesEnabled = Boolean.parseBoolean(_configDao.getValue("cloud.kubernetes.cluster.experimental.features.enabled"));
|
||||
|
|
@ -4865,9 +4875,53 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||
}
|
||||
capabilities.put(ApiConstants.ADDITONAL_CONFIG_ENABLED, UserVmManager.EnableAdditionalVmConfig.valueIn(caller.getId()));
|
||||
|
||||
Map<String, Object> vpnParams = getVpnCustomerGatewayParameters(domainId);
|
||||
if (!vpnParams.isEmpty()) {
|
||||
capabilities.put(ApiConstants.VPN_CUSTOMER_GATEWAY_PARAMETERS, vpnParams);
|
||||
}
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
private Map<String, Object> getVpnCustomerGatewayParameters(Long domainId) {
|
||||
Map<String, Object> vpnParams = new HashMap<>();
|
||||
|
||||
String excludedEncryption = Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms.valueIn(domainId);
|
||||
String excludedHashing = Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms.valueIn(domainId);
|
||||
String excludedIkeVersions = Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions.valueIn(domainId);
|
||||
String excludedDhGroup = Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup.valueIn(domainId);
|
||||
String obsoleteEncryption = Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteEncryptionAlgorithms.valueIn(domainId);
|
||||
String obsoleteHashing = Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteHashingAlgorithms.valueIn(domainId);
|
||||
String obsoleteIkeVersions = Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteIkeVersions.valueIn(domainId);
|
||||
String obsoleteDhGroup = Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteDhGroup.valueIn(domainId);
|
||||
|
||||
if (!excludedEncryption.isEmpty()) {
|
||||
vpnParams.put("excludedencryptionalgorithms", excludedEncryption);
|
||||
}
|
||||
if (!obsoleteEncryption.isEmpty()) {
|
||||
vpnParams.put("obsoleteencryptionalgorithms", obsoleteEncryption);
|
||||
}
|
||||
if (!excludedHashing.isEmpty()) {
|
||||
vpnParams.put("excludedhashingalgorithms", excludedHashing);
|
||||
}
|
||||
if (!obsoleteHashing.isEmpty()) {
|
||||
vpnParams.put("obsoletehashingalgorithms", obsoleteHashing);
|
||||
}
|
||||
if (!excludedIkeVersions.isEmpty()) {
|
||||
vpnParams.put("excludedikeversions", excludedIkeVersions);
|
||||
}
|
||||
if (!obsoleteIkeVersions.isEmpty()) {
|
||||
vpnParams.put("obsoleteikeversions", obsoleteIkeVersions);
|
||||
}
|
||||
if (!excludedDhGroup.isEmpty()) {
|
||||
vpnParams.put("excludeddhgroups", excludedDhGroup);
|
||||
}
|
||||
if (!obsoleteDhGroup.isEmpty()) {
|
||||
vpnParams.put("obsoletedhgroups", obsoleteDhGroup);
|
||||
}
|
||||
return vpnParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuestOSVO getGuestOs(final Long guestOsId) {
|
||||
return _guestOSDao.findById(guestOsId);
|
||||
|
|
|
|||
|
|
@ -1801,14 +1801,18 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
|
||||
protected String getStoragePoolNonDestroyedVolumesLog(long storagePoolId) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<VolumeVO> nonDestroyedVols = volumeDao.findByPoolId(storagePoolId, null).stream().filter(vol -> vol.getState() != Volume.State.Destroy).collect(Collectors.toList());
|
||||
List<VolumeVO> nonDestroyedVols = volumeDao.findByPoolId(storagePoolId, null);
|
||||
VMInstanceVO volInstance;
|
||||
List<String> logMessageInfo = new ArrayList<>();
|
||||
|
||||
sb.append("[");
|
||||
for (VolumeVO vol : nonDestroyedVols) {
|
||||
volInstance = _vmInstanceDao.findById(vol.getInstanceId());
|
||||
logMessageInfo.add(String.format("Volume [%s] (attached to VM [%s])", vol.getUuid(), volInstance.getUuid()));
|
||||
if (volInstance != null) {
|
||||
logMessageInfo.add(String.format("Volume [%s] (attached to VM [%s])", vol.getUuid(), volInstance.getUuid()));
|
||||
} else {
|
||||
logMessageInfo.add(String.format("Volume [%s]", vol.getUuid()));
|
||||
}
|
||||
}
|
||||
sb.append(String.join(", ", logMessageInfo));
|
||||
sb.append("]");
|
||||
|
|
@ -2110,41 +2114,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
}
|
||||
}
|
||||
|
||||
//destroy snapshots in destroying state in snapshot_store_ref
|
||||
List<SnapshotDataStoreVO> ssSnapshots = _snapshotStoreDao.listByState(ObjectInDataStoreStateMachine.State.Destroying);
|
||||
for (SnapshotDataStoreVO snapshotDataStoreVO : ssSnapshots) {
|
||||
String snapshotUuid = null;
|
||||
SnapshotVO snapshot = null;
|
||||
final String storeRole = snapshotDataStoreVO.getRole().toString().toLowerCase();
|
||||
if (logger.isDebugEnabled()) {
|
||||
snapshot = _snapshotDao.findById(snapshotDataStoreVO.getSnapshotId());
|
||||
if (snapshot == null) {
|
||||
logger.warn(String.format("Did not find snapshot [ID: %d] for which store reference is in destroying state; therefore, it cannot be destroyed.", snapshotDataStoreVO.getSnapshotId()));
|
||||
continue;
|
||||
}
|
||||
snapshotUuid = snapshot.getUuid();
|
||||
}
|
||||
|
||||
try {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Verifying if snapshot [%s] is in destroying state in %s data store ID: %d.", snapshotUuid, storeRole, snapshotDataStoreVO.getDataStoreId()));
|
||||
}
|
||||
SnapshotInfo snapshotInfo = snapshotFactory.getSnapshot(snapshotDataStoreVO.getSnapshotId(), snapshotDataStoreVO.getDataStoreId(), snapshotDataStoreVO.getRole());
|
||||
if (snapshotInfo != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Snapshot [%s] in destroying state found in %s data store [%s]; therefore, it will be destroyed.", snapshotUuid, storeRole, snapshotInfo.getDataStore().getUuid()));
|
||||
}
|
||||
_snapshotService.deleteSnapshot(snapshotInfo);
|
||||
} else if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Did not find snapshot [%s] in destroying state in %s data store ID: %d.", snapshotUuid, storeRole, snapshotDataStoreVO.getDataStoreId()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to delete snapshot [{}] from storage due to: [{}].", snapshot, e.getMessage());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to delete snapshot [{}] from storage.", snapshot, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanupSnapshotsFromStoreRefInDestroyingState();
|
||||
cleanupSecondaryStorage(recurring);
|
||||
|
||||
List<VolumeVO> vols = volumeDao.listVolumesToBeDestroyed(new Date(System.currentTimeMillis() - ((long)StorageCleanupDelay.value() << 10)));
|
||||
|
|
@ -2184,20 +2154,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
}
|
||||
}
|
||||
|
||||
// remove snapshots in Error state
|
||||
List<SnapshotVO> snapshots = _snapshotDao.listAllByStatus(Snapshot.State.Error);
|
||||
for (SnapshotVO snapshotVO : snapshots) {
|
||||
try {
|
||||
List<SnapshotDataStoreVO> storeRefs = _snapshotStoreDao.findBySnapshotId(snapshotVO.getId());
|
||||
for (SnapshotDataStoreVO ref : storeRefs) {
|
||||
_snapshotStoreDao.expunge(ref.getId());
|
||||
}
|
||||
_snapshotDao.expunge(snapshotVO.getId());
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to destroy snapshot [{}] due to: [{}].", snapshotVO, e.getMessage());
|
||||
logger.debug("Unable to destroy snapshot [{}].", snapshotVO, e);
|
||||
}
|
||||
}
|
||||
removeSnapshotsInErrorStatus();
|
||||
|
||||
// destroy uploaded volumes in abandoned/error state
|
||||
List<VolumeDataStoreVO> volumeDataStores = _volumeDataStoreDao.listByVolumeState(Volume.State.UploadError, Volume.State.UploadAbandoned);
|
||||
|
|
@ -2298,6 +2255,56 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||
}
|
||||
}
|
||||
|
||||
private void cleanupSnapshotsFromStoreRefInDestroyingState() {
|
||||
List<SnapshotDataStoreVO> storeRefSnapshotsInDestroyingState = _snapshotStoreDao.listByState(ObjectInDataStoreStateMachine.State.Destroying);
|
||||
for (SnapshotDataStoreVO snapshotDataStoreVO : storeRefSnapshotsInDestroyingState) {
|
||||
SnapshotVO snapshot = _snapshotDao.findById(snapshotDataStoreVO.getSnapshotId());
|
||||
if (snapshot == null) {
|
||||
logger.warn("Did not find snapshot [ID: {}] for which store reference is in destroying state; therefore, it cannot be destroyed.", snapshotDataStoreVO.getSnapshotId());
|
||||
continue;
|
||||
}
|
||||
deleteSnapshot(snapshot, snapshotDataStoreVO);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteSnapshot(SnapshotVO snapshot, SnapshotDataStoreVO snapshotDataStoreVO) {
|
||||
if (snapshot == null || snapshotDataStoreVO == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final String snapshotUuid = snapshot.getUuid();
|
||||
final String storeRole = snapshotDataStoreVO.getRole().toString().toLowerCase();
|
||||
logger.debug("Snapshot [{}] is in {} state on {} data store ID: {}.", snapshotUuid, snapshotDataStoreVO.getState(), storeRole, snapshotDataStoreVO.getDataStoreId());
|
||||
SnapshotInfo snapshotInfo = snapshotFactory.getSnapshotIncludingRemoved(snapshotDataStoreVO.getSnapshotId(), snapshotDataStoreVO.getDataStoreId(), snapshotDataStoreVO.getRole());
|
||||
if (snapshotInfo != null) {
|
||||
logger.debug("Snapshot [{}] in {} state found on {} data store [{}], it will be deleted.", snapshotUuid, snapshotDataStoreVO.getState(), storeRole, snapshotInfo.getDataStore().getUuid());
|
||||
_snapshotService.deleteSnapshot(snapshotInfo);
|
||||
} else {
|
||||
logger.debug("Did not find snapshot [{}] in {} state on {} data store ID: {}.", snapshotUuid, snapshotDataStoreVO.getState(), storeRole, snapshotDataStoreVO.getDataStoreId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to delete snapshot [{}] from storage due to: [{}].", snapshot, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSnapshotsInErrorStatus() {
|
||||
List<SnapshotVO> snapshotsInErrorStatus = _snapshotDao.listAllByStatusIncludingRemoved(Snapshot.State.Error);
|
||||
for (SnapshotVO snapshotVO : snapshotsInErrorStatus) {
|
||||
try {
|
||||
List<SnapshotDataStoreVO> storeRefSnapshotsInErrorStatus = _snapshotStoreDao.findBySnapshotId(snapshotVO.getId());
|
||||
for (SnapshotDataStoreVO snapshotDataStoreVO : storeRefSnapshotsInErrorStatus) {
|
||||
deleteSnapshot(snapshotVO, snapshotDataStoreVO);
|
||||
_snapshotStoreDao.expunge(snapshotDataStoreVO.getId());
|
||||
}
|
||||
_snapshotDao.expunge(snapshotVO.getId());
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to destroy snapshot [{}] due to: [{}].", snapshotVO, e.getMessage());
|
||||
logger.debug("Unable to destroy snapshot [{}].", snapshotVO, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isVolumeSuspectedDestroyDuplicateOfVmVolume(VolumeVO gcVolume) {
|
||||
if (gcVolume.getPath() == null) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.cloud.exception.StorageConflictException;
|
|||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.Profiler;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
|
||||
|
|
@ -200,12 +201,13 @@ public class StoragePoolMonitor implements Listener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean processDisconnect(long agentId, Status state) {
|
||||
public boolean processDisconnect(long agentId, Status state) {
|
||||
return processDisconnect(agentId, null, null, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean processDisconnect(long agentId, String uuid, String name, Status state) {
|
||||
public boolean processDisconnect(long agentId, String uuid, String name, Status state) {
|
||||
logger.debug("Starting disconnect for Agent [id: {}, uuid: {}, name: {}]", agentId, uuid, name);
|
||||
Host host = _storageManager.getHost(agentId);
|
||||
if (host == null) {
|
||||
logger.warn("Agent [id: {}, uuid: {}, name: {}] not found, not disconnecting pools", agentId, uuid, name);
|
||||
|
|
@ -213,38 +215,52 @@ public class StoragePoolMonitor implements Listener {
|
|||
}
|
||||
|
||||
if (host.getType() != Host.Type.Routing) {
|
||||
logger.debug("Host [id: {}, uuid: {}, name: {}] is not of type {}, skip", agentId, uuid, name, Host.Type.Routing);
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.debug("Looking for connected Storage Pools for Host [id: {}, uuid: {}, name: {}]", agentId, uuid, name);
|
||||
List<StoragePoolHostVO> storagePoolHosts = _storageManager.findStoragePoolsConnectedToHost(host.getId());
|
||||
if (storagePoolHosts == null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No pools to disconnect for host: {}", host);
|
||||
}
|
||||
logger.debug("No pools to disconnect for host: {}", host);
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.debug("Found {} pools to disconnect for host: {}", storagePoolHosts.size(), host);
|
||||
boolean disconnectResult = true;
|
||||
for (StoragePoolHostVO storagePoolHost : storagePoolHosts) {
|
||||
int storagePoolHostsSize = storagePoolHosts.size();
|
||||
for (int i = 0; i < storagePoolHostsSize; i++) {
|
||||
StoragePoolHostVO storagePoolHost = storagePoolHosts.get(i);
|
||||
logger.debug("Processing disconnect from Storage Pool {} ({} of {}) for host: {}", storagePoolHost.getPoolId(), i, storagePoolHostsSize, host);
|
||||
StoragePoolVO pool = _poolDao.findById(storagePoolHost.getPoolId());
|
||||
if (pool == null) {
|
||||
logger.debug("No Storage Pool found with id {} ({} of {}) for host: {}", storagePoolHost.getPoolId(), i, storagePoolHostsSize, host);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pool.isShared()) {
|
||||
logger.debug("Storage Pool {} ({}) ({} of {}) is not shared for host: {}, ignore disconnect", pool.getName(), pool.getUuid(), i, storagePoolHostsSize, host);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle only PowerFlex pool for now, not to impact other pools behavior
|
||||
if (pool.getPoolType() != StoragePoolType.PowerFlex) {
|
||||
logger.debug("Storage Pool {} ({}) ({} of {}) is not of type {} for host: {}, ignore disconnect", pool.getName(), pool.getUuid(), i, storagePoolHostsSize, pool.getPoolType(), host);
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.debug("Sending disconnect to Storage Pool {} ({}) ({} of {}) for host: {}", pool.getName(), pool.getUuid(), i, storagePoolHostsSize, host);
|
||||
Profiler disconnectProfiler = new Profiler();
|
||||
try {
|
||||
disconnectProfiler.start();
|
||||
_storageManager.disconnectHostFromSharedPool(host, pool);
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to disconnect host {} from storage pool {} due to {}", host, pool, e.toString());
|
||||
disconnectResult = false;
|
||||
} finally {
|
||||
disconnectProfiler.stop();
|
||||
long disconnectDuration = disconnectProfiler.getDurationInMillis() / 1000;
|
||||
logger.debug("Finished disconnect with result {} from Storage Pool {} ({}) ({} of {}) for host: {}, duration: {} secs", disconnectResult, pool.getName(), pool.getUuid(), i, storagePoolHostsSize, host, disconnectDuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -843,7 +843,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
|
||||
protected Pair<List<SnapshotDataStoreVO>, List<Long>> getStoreRefsAndZonesForSnapshotDelete(long snapshotId, Long zoneId) {
|
||||
List<SnapshotDataStoreVO> snapshotStoreRefs = new ArrayList<>();
|
||||
List<SnapshotDataStoreVO> allSnapshotStoreRefs = _snapshotStoreDao.findBySnapshotId(snapshotId);
|
||||
List<SnapshotDataStoreVO> allSnapshotStoreRefs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId);
|
||||
List<Long> zoneIds = new ArrayList<>();
|
||||
if (zoneId != null) {
|
||||
DataCenterVO zone = dataCenterDao.findById(zoneId);
|
||||
|
|
@ -1782,23 +1782,23 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
if (asyncBackup) {
|
||||
backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, snapshotBackupRetries - 1, snapshotStrategy, zoneIds, poolIds), 0, TimeUnit.SECONDS);
|
||||
} else {
|
||||
SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary);
|
||||
if (backupedSnapshot != null) {
|
||||
SnapshotInfo backedUpSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary);
|
||||
if (backedUpSnapshot != null) {
|
||||
snapshotStrategy.postSnapshotCreation(snapshotOnPrimary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class BackupSnapshotTask extends ManagedContextRunnable {
|
||||
SnapshotInfo snapshot;
|
||||
SnapshotInfo snapshotOnPrimary;
|
||||
int attempts;
|
||||
SnapshotStrategy snapshotStrategy;
|
||||
|
||||
List<Long> zoneIds;
|
||||
List<Long> poolIds;
|
||||
|
||||
public BackupSnapshotTask(SnapshotInfo snap, int maxRetries, SnapshotStrategy strategy, List<Long> zoneIds, List<Long> poolIds) {
|
||||
snapshot = snap;
|
||||
public BackupSnapshotTask(SnapshotInfo snapshot, int maxRetries, SnapshotStrategy strategy, List<Long> zoneIds, List<Long> poolIds) {
|
||||
snapshotOnPrimary = snapshot;
|
||||
attempts = maxRetries;
|
||||
snapshotStrategy = strategy;
|
||||
this.zoneIds = zoneIds;
|
||||
|
|
@ -1810,17 +1810,16 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
try {
|
||||
logger.debug("Value of attempts is " + (snapshotBackupRetries - attempts));
|
||||
if (Boolean.TRUE.equals(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value()) && CollectionUtils.isEmpty(poolIds)) {
|
||||
SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshot);
|
||||
|
||||
SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary);
|
||||
if (backupedSnapshot != null) {
|
||||
snapshotStrategy.postSnapshotCreation(snapshot);
|
||||
copyNewSnapshotToZones(snapshot.getId(), snapshot.getDataCenterId(), zoneIds);
|
||||
snapshotStrategy.postSnapshotCreation(snapshotOnPrimary);
|
||||
copyNewSnapshotToZones(snapshotOnPrimary.getId(), snapshotOnPrimary.getDataCenterId(), zoneIds);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(poolIds)) {
|
||||
for (Long poolId: poolIds) {
|
||||
copySnapshotOnPool(snapshot, snapshotStrategy, poolId);
|
||||
copySnapshotOnPool(snapshotOnPrimary, snapshotStrategy, poolId);
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
|
|
@ -1830,11 +1829,11 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
|
||||
private void decriseBackupSnapshotAttempts() {
|
||||
if (attempts >= 0) {
|
||||
logger.debug("Backing up of snapshot failed, for snapshot {}, left with {} more attempts", snapshot, attempts);
|
||||
backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshot, --attempts, snapshotStrategy, zoneIds, poolIds), snapshotBackupRetryInterval, TimeUnit.SECONDS);
|
||||
logger.debug("Backing up of snapshot failed, for snapshot {}, left with {} more attempts", snapshotOnPrimary, attempts);
|
||||
backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, --attempts, snapshotStrategy, zoneIds, poolIds), snapshotBackupRetryInterval, TimeUnit.SECONDS);
|
||||
} else {
|
||||
logger.debug("Done with {} attempts in backing up of snapshot {}", snapshotBackupRetries, snapshot.getSnapshotVO());
|
||||
snapshotSrv.cleanupOnSnapshotBackupFailure(snapshot);
|
||||
logger.debug("Done with {} attempts in backing up of snapshot {}", snapshotBackupRetries, snapshotOnPrimary.getSnapshotVO());
|
||||
snapshotSrv.cleanupOnSnapshotBackupFailure(snapshotOnPrimary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2058,7 +2057,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
public void markVolumeSnapshotsAsDestroyed(Volume volume) {
|
||||
List<SnapshotVO> snapshots = _snapshotDao.listByVolumeId(volume.getId());
|
||||
for (SnapshotVO snapshot: snapshots) {
|
||||
List<SnapshotDataStoreVO> snapshotDataStoreVOs = _snapshotStoreDao.findBySnapshotId(snapshot.getId());
|
||||
List<SnapshotDataStoreVO> snapshotDataStoreVOs = _snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshot.getId());
|
||||
if (CollectionUtils.isEmpty(snapshotDataStoreVOs)) {
|
||||
snapshot.setState(Snapshot.State.Destroyed);
|
||||
_snapshotDao.update(snapshot.getId(), snapshot);
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ import org.apache.cloudstack.api.response.UserTwoFactorAuthenticationSetupRespon
|
|||
import org.apache.cloudstack.auth.UserAuthenticator;
|
||||
import org.apache.cloudstack.auth.UserAuthenticator.ActionOnFailedAuthentication;
|
||||
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
|
||||
import org.apache.cloudstack.backup.BackupOffering;
|
||||
import org.apache.cloudstack.config.ApiServiceConfiguration;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
|
|
@ -3574,6 +3575,21 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||
throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + vof);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAccess(Account account, BackupOffering bof) throws PermissionDeniedException {
|
||||
for (SecurityChecker checker : _securityCheckers) {
|
||||
if (checker.checkAccess(account, bof)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Access granted to " + account + " to " + bof + " by " + checker.getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assert false : "How can all of the security checkers pass on checking this caller?";
|
||||
throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + bof);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException {
|
||||
for (SecurityChecker checker : _securityCheckers) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
// 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.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
|
||||
@Component
|
||||
public class DomainHelper {
|
||||
|
||||
@Inject
|
||||
private DomainDao domainDao;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param domainIds List of domain IDs to filter
|
||||
* @return Filtered list containing only domains that are not descendants of other domains in the list
|
||||
*/
|
||||
public List<Long> filterChildSubDomains(final List<Long> domainIds) {
|
||||
if (domainIds == null || domainIds.size() <= 1) {
|
||||
return domainIds == null ? new ArrayList<>() : new ArrayList<>(domainIds);
|
||||
}
|
||||
|
||||
final List<Long> result = new ArrayList<>();
|
||||
for (final Long candidate : domainIds) {
|
||||
boolean isDescendant = false;
|
||||
for (final Long other : domainIds) {
|
||||
if (Objects.equals(candidate, other)) {
|
||||
continue;
|
||||
}
|
||||
if (domainDao.isChildDomain(other, candidate)) {
|
||||
isDescendant = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isDescendant) {
|
||||
result.add(candidate);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -7189,6 +7189,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw new CloudRuntimeException("Unable to find suitable destination to migrate VM " + vm.getInstanceName());
|
||||
}
|
||||
|
||||
logger.info("Starting migration of VM {} from host {} to host {} ", vm.getInstanceName(), srcHostId, dest.getHost().getId());
|
||||
collectVmDiskAndNetworkStatistics(vmId, State.Running);
|
||||
_itMgr.migrate(vm.getUuid(), srcHostId, dest);
|
||||
return findMigratedVm(vm.getId(), vm.getType());
|
||||
|
|
@ -7260,6 +7261,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
private DeployDestination checkVmMigrationDestination(VMInstanceVO vm, Host srcHost, Host destinationHost) throws VirtualMachineMigrationException {
|
||||
if (destinationHost == null) {
|
||||
logger.error("Destination host is null for migration of VM: {}", vm.getInstanceName());
|
||||
return null;
|
||||
}
|
||||
if (destinationHost.getId() == srcHost.getId()) {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import java.util.stream.Stream;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.utils.DomainHelper;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.InternalIdentity;
|
||||
|
|
@ -68,6 +69,7 @@ import org.apache.cloudstack.api.response.BackupResponse;
|
|||
import org.apache.cloudstack.backup.dao.BackupDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupDetailsDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDetailsDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
|
@ -81,12 +83,12 @@ import org.apache.cloudstack.poll.BackgroundPollTask;
|
|||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.amazonaws.util.CollectionUtils;
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.api.ApiDispatcher;
|
||||
import com.cloud.api.ApiGsonHelper;
|
||||
|
|
@ -184,6 +186,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
@Inject
|
||||
private BackupOfferingDao backupOfferingDao;
|
||||
@Inject
|
||||
private BackupOfferingDetailsDao backupOfferingDetailsDao;
|
||||
@Inject
|
||||
private VMInstanceDao vmInstanceDao;
|
||||
@Inject
|
||||
private AccountService accountService;
|
||||
|
|
@ -237,6 +241,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
private AlertManager alertManager;
|
||||
@Inject
|
||||
private GuestOSDao _guestOSDao;
|
||||
@Inject
|
||||
private DomainHelper domainHelper;
|
||||
|
||||
private AsyncJobDispatcher asyncJobDispatcher;
|
||||
private Timer backupTimer;
|
||||
|
|
@ -280,6 +286,20 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
throw new CloudRuntimeException("A backup offering with the same name already exists in this zone");
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(cmd.getDomainIds())) {
|
||||
for (final Long domainId: cmd.getDomainIds()) {
|
||||
if (domainDao.findById(domainId) == null) {
|
||||
throw new InvalidParameterValueException("Please specify a valid domain id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Account caller = CallContext.current().getCallingAccount();
|
||||
List<Long> filteredDomainIds = cmd.getDomainIds() == null ? new ArrayList<>() : new ArrayList<>(cmd.getDomainIds());
|
||||
if (filteredDomainIds.size() > 1) {
|
||||
filteredDomainIds = domainHelper.filterChildSubDomains(filteredDomainIds);
|
||||
}
|
||||
|
||||
final BackupProvider provider = getBackupProvider(cmd.getZoneId());
|
||||
if (!provider.isValidProviderOffering(cmd.getZoneId(), cmd.getExternalId())) {
|
||||
throw new CloudRuntimeException("Backup offering '" + cmd.getExternalId() + "' does not exist on provider " + provider.getName() + " on zone " + cmd.getZoneId());
|
||||
|
|
@ -292,15 +312,34 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
if (savedOffering == null) {
|
||||
throw new CloudRuntimeException("Unable to create backup offering: " + cmd.getExternalId() + ", name: " + cmd.getName());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(filteredDomainIds)) {
|
||||
List<BackupOfferingDetailsVO> detailsVOList = new ArrayList<>();
|
||||
for (Long domainId : filteredDomainIds) {
|
||||
detailsVOList.add(new BackupOfferingDetailsVO(savedOffering.getId(), ApiConstants.DOMAIN_ID, String.valueOf(domainId), false));
|
||||
}
|
||||
if (!detailsVOList.isEmpty()) {
|
||||
backupOfferingDetailsDao.saveDetails(detailsVOList);
|
||||
}
|
||||
}
|
||||
logger.debug("Successfully created backup offering " + cmd.getName() + " mapped to backup provider offering " + cmd.getExternalId());
|
||||
return savedOffering;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> getBackupOfferingDomains(Long offeringId) {
|
||||
final BackupOffering backupOffering = backupOfferingDao.findById(offeringId);
|
||||
if (backupOffering == null) {
|
||||
throw new InvalidParameterValueException("Unable to find backup offering for id: " + offeringId);
|
||||
}
|
||||
return backupOfferingDetailsDao.findDomainIds(offeringId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<List<BackupOffering>, Integer> listBackupOfferings(final ListBackupOfferingsCmd cmd) {
|
||||
final Long offeringId = cmd.getOfferingId();
|
||||
final Long zoneId = cmd.getZoneId();
|
||||
final String keyword = cmd.getKeyword();
|
||||
Long domainId = cmd.getDomainId();
|
||||
|
||||
if (offeringId != null) {
|
||||
BackupOfferingVO offering = backupOfferingDao.findById(offeringId);
|
||||
|
|
@ -314,8 +353,13 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
SearchBuilder<BackupOfferingVO> sb = backupOfferingDao.createSearchBuilder();
|
||||
sb.and("zone_id", sb.entity().getZoneId(), SearchCriteria.Op.EQ);
|
||||
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
|
||||
|
||||
CallContext ctx = CallContext.current();
|
||||
final Account caller = ctx.getCallingAccount();
|
||||
if (Account.Type.ADMIN != caller.getType() && domainId == null) {
|
||||
domainId = caller.getDomainId();
|
||||
}
|
||||
|
||||
if (Account.Type.NORMAL == caller.getType()) {
|
||||
sb.and("user_backups_allowed", sb.entity().isUserDrivenBackupAllowed(), SearchCriteria.Op.EQ);
|
||||
}
|
||||
|
|
@ -328,13 +372,36 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
if (keyword != null) {
|
||||
sc.setParameters("name", "%" + keyword + "%");
|
||||
}
|
||||
|
||||
if (Account.Type.NORMAL == caller.getType()) {
|
||||
sc.setParameters("user_backups_allowed", true);
|
||||
}
|
||||
|
||||
Pair<List<BackupOfferingVO>, Integer> result = backupOfferingDao.searchAndCount(sc, searchFilter);
|
||||
|
||||
if (domainId != null) {
|
||||
List<BackupOfferingVO> filteredOfferings = new ArrayList<>();
|
||||
for (BackupOfferingVO offering : result.first()) {
|
||||
List<Long> offeringDomains = backupOfferingDetailsDao.findDomainIds(offering.getId());
|
||||
if (offeringDomains.isEmpty() || offeringDomains.contains(domainId) || containsParentDomain(offeringDomains, domainId)) {
|
||||
filteredOfferings.add(offering);
|
||||
}
|
||||
}
|
||||
return new Pair<>(new ArrayList<>(filteredOfferings), filteredOfferings.size());
|
||||
}
|
||||
|
||||
return new Pair<>(new ArrayList<>(result.first()), result.second());
|
||||
}
|
||||
|
||||
private boolean containsParentDomain(List<Long> offeringDomains, Long domainId) {
|
||||
for (Long offeringDomainId : offeringDomains) {
|
||||
if (domainDao.isChildDomain(offeringDomainId, domainId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteBackupOffering(final Long offeringId) {
|
||||
final BackupOfferingVO offering = backupOfferingDao.findById(offeringId);
|
||||
|
|
@ -342,6 +409,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
throw new CloudRuntimeException("Could not find a backup offering with id: " + offeringId);
|
||||
}
|
||||
|
||||
accountManager.checkAccess(CallContext.current().getCallingAccount(), offering);
|
||||
|
||||
if (backupDao.listByOfferingId(offering.getId()).size() > 0) {
|
||||
throw new CloudRuntimeException("Backup Offering cannot be removed as it has backups associated with it.");
|
||||
}
|
||||
|
|
@ -452,6 +521,12 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
throw new CloudRuntimeException("Provided backup offering does not exist");
|
||||
}
|
||||
|
||||
Account owner = accountManager.getAccount(vm.getAccountId());
|
||||
if (owner == null) {
|
||||
throw new CloudRuntimeException("Unable to find the owner of the VM");
|
||||
}
|
||||
accountManager.checkAccess(owner, offering);
|
||||
|
||||
final BackupProvider backupProvider = getBackupProvider(offering.getProvider());
|
||||
if (backupProvider == null) {
|
||||
throw new CloudRuntimeException("Failed to get the backup provider for the zone, please contact the administrator");
|
||||
|
|
@ -762,10 +837,11 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
@ActionEvent(eventType = EventTypes.EVENT_VM_BACKUP_CREATE, eventDescription = "creating VM backup", async = true)
|
||||
public boolean createBackup(CreateBackupCmd cmd, Object job) throws ResourceAllocationException {
|
||||
Long vmId = cmd.getVmId();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
final VMInstanceVO vm = findVmById(vmId);
|
||||
validateBackupForZone(vm.getDataCenterId());
|
||||
accountManager.checkAccess(CallContext.current().getCallingAccount(), null, true, vm);
|
||||
accountManager.checkAccess(caller, null, true, vm);
|
||||
|
||||
if (vm.getBackupOfferingId() == null) {
|
||||
throw new CloudRuntimeException("VM has not backup offering configured, cannot create backup before assigning it to a backup offering");
|
||||
|
|
@ -1065,7 +1141,7 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
}
|
||||
|
||||
// This is done to handle historic backups if any with Veeam / Networker plugins
|
||||
List<Backup.VolumeInfo> backupVolumes = CollectionUtils.isNullOrEmpty(backup.getBackedUpVolumes()) ?
|
||||
List<Backup.VolumeInfo> backupVolumes = CollectionUtils.isEmpty(backup.getBackedUpVolumes()) ?
|
||||
vm.getBackupVolumeList() : backup.getBackedUpVolumes();
|
||||
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
|
||||
if (vmVolumes.size() != backupVolumes.size()) {
|
||||
|
|
@ -2112,11 +2188,15 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
String name = updateBackupOfferingCmd.getName();
|
||||
String description = updateBackupOfferingCmd.getDescription();
|
||||
Boolean allowUserDrivenBackups = updateBackupOfferingCmd.getAllowUserDrivenBackups();
|
||||
List<Long> domainIds = updateBackupOfferingCmd.getDomainIds();
|
||||
|
||||
BackupOfferingVO backupOfferingVO = backupOfferingDao.findById(id);
|
||||
if (backupOfferingVO == null) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to find Backup Offering with id: [%s].", id));
|
||||
}
|
||||
|
||||
accountManager.checkAccess(CallContext.current().getCallingAccount(), backupOfferingVO);
|
||||
|
||||
logger.debug("Trying to update Backup Offering {} to {}.",
|
||||
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(backupOfferingVO, "uuid", "name", "description", "userDrivenBackupAllowed"),
|
||||
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(updateBackupOfferingCmd, "name", "description", "allowUserDrivenBackups"));
|
||||
|
|
@ -2139,16 +2219,43 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
fields.add("allowUserDrivenBackups: " + allowUserDrivenBackups);
|
||||
}
|
||||
|
||||
if (!backupOfferingDao.update(id, offering)) {
|
||||
if (CollectionUtils.isNotEmpty(domainIds)) {
|
||||
for (final Long domainId: domainIds) {
|
||||
if (domainDao.findById(domainId) == null) {
|
||||
throw new InvalidParameterValueException("Please specify a valid domain id");
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Long> filteredDomainIds = domainHelper.filterChildSubDomains(domainIds);
|
||||
Collections.sort(filteredDomainIds);
|
||||
|
||||
boolean success = backupOfferingDao.update(id, offering);
|
||||
if (!success) {
|
||||
logger.warn(String.format("Couldn't update Backup offering (%s) with [%s].", backupOfferingVO, String.join(", ", fields)));
|
||||
}
|
||||
|
||||
if (success || fields.isEmpty()) {
|
||||
List<Long> existingDomainIds = backupOfferingDetailsDao.findDomainIds(id);
|
||||
Collections.sort(existingDomainIds);
|
||||
updateBackupOfferingDomainDetails(id, filteredDomainIds, existingDomainIds);
|
||||
}
|
||||
|
||||
BackupOfferingVO response = backupOfferingDao.findById(id);
|
||||
CallContext.current().setEventDetails(String.format("Backup Offering updated [%s].",
|
||||
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(response, "id", "name", "description", "userDrivenBackupAllowed", "externalId")));
|
||||
return response;
|
||||
}
|
||||
|
||||
private void updateBackupOfferingDomainDetails(Long id, List<Long> filteredDomainIds, List<Long> existingDomainIds) {
|
||||
if (existingDomainIds == null) {
|
||||
existingDomainIds = new ArrayList<>();
|
||||
}
|
||||
|
||||
if(!filteredDomainIds.equals(existingDomainIds)) {
|
||||
backupOfferingDetailsDao.updateBackupOfferingDomainIdsDetail(id, filteredDomainIds);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> getDetailsFromBackupDetails(Long backupId) {
|
||||
Map<String, String> details = backupDetailsDao.listDetailsKeyPairs(backupId, true);
|
||||
if (details == null) {
|
||||
|
|
@ -2270,7 +2377,7 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||
return;
|
||||
}
|
||||
List<Backup> backupsForVm = backupDao.listByVmIdAndOffering(vm.getDataCenterId(), vm.getId(), vm.getBackupOfferingId());
|
||||
if (org.apache.commons.collections.CollectionUtils.isEmpty(backupsForVm)) {
|
||||
if (CollectionUtils.isEmpty(backupsForVm)) {
|
||||
removeVMFromBackupOffering(vm.getId(), true);
|
||||
} else {
|
||||
throw new CloudRuntimeException(String.format("This Instance [uuid: %s, name: %s] has a "
|
||||
|
|
|
|||
|
|
@ -81,4 +81,6 @@
|
|||
|
||||
<bean id="DPDKHelper" class="com.cloud.hypervisor.kvm.dpdk.DpdkHelperImpl" />
|
||||
|
||||
<bean id="domainHelper" class="com.cloud.utils.DomainHelper" />
|
||||
|
||||
</beans>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ package com.cloud.acl;
|
|||
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.backup.BackupOfferingVO;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDetailsDao;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
|
|
@ -35,6 +38,8 @@ import com.cloud.user.AccountVO;
|
|||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.Ternary;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DomainCheckerTest {
|
||||
|
||||
|
|
@ -46,6 +51,8 @@ public class DomainCheckerTest {
|
|||
DomainDao _domainDao;
|
||||
@Mock
|
||||
ProjectManager _projectMgr;
|
||||
@Mock
|
||||
BackupOfferingDetailsDao backupOfferingDetailsDao;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
|
|
@ -163,4 +170,42 @@ public class DomainCheckerTest {
|
|||
domainChecker.validateCallerHasAccessToEntityOwner(caller, entity, SecurityChecker.AccessType.ListEntry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBackupOfferingAccessRootAdmin() {
|
||||
Account rootAdmin = Mockito.mock(Account.class);
|
||||
Mockito.when(rootAdmin.getId()).thenReturn(1L);
|
||||
BackupOfferingVO backupOfferingVO = Mockito.mock(BackupOfferingVO.class);
|
||||
Mockito.when(_accountService.isRootAdmin(rootAdmin.getId())).thenReturn(true);
|
||||
|
||||
boolean hasAccess = domainChecker.checkAccess(rootAdmin, backupOfferingVO);
|
||||
Assert.assertTrue(hasAccess);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBackupOfferingAccessDomainAdmin() {
|
||||
Account domainAdmin = Mockito.mock(Account.class);
|
||||
Mockito.when(domainAdmin.getId()).thenReturn(2L);
|
||||
BackupOfferingVO backupOfferingVO = Mockito.mock(BackupOfferingVO.class);
|
||||
AccountVO owner = Mockito.mock(AccountVO.class);
|
||||
Mockito.when(_accountService.isDomainAdmin(domainAdmin.getId())).thenReturn(true);
|
||||
Mockito.when(domainAdmin.getDomainId()).thenReturn(10L);
|
||||
Mockito.when(_domainDao.isChildDomain(100L, 10L)).thenReturn(true);
|
||||
Mockito.when(backupOfferingDetailsDao.findDomainIds(backupOfferingVO.getId())).thenReturn(Collections.singletonList(100L));
|
||||
|
||||
boolean hasAccess = domainChecker.checkAccess(domainAdmin, backupOfferingVO);
|
||||
Assert.assertTrue(hasAccess);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBackupOfferingAccessNoAccess() {
|
||||
Account normalUser = Mockito.mock(Account.class);
|
||||
Mockito.when(normalUser.getId()).thenReturn(3L);
|
||||
BackupOfferingVO backupOfferingVO = Mockito.mock(BackupOfferingVO.class);
|
||||
Mockito.when(_accountService.isRootAdmin(normalUser.getId())).thenReturn(false);
|
||||
Mockito.when(_accountService.isDomainAdmin(normalUser.getId())).thenReturn(false);
|
||||
|
||||
boolean hasAccess = domainChecker.checkAccess(normalUser, backupOfferingVO);
|
||||
Assert.assertFalse(hasAccess);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import com.cloud.storage.dao.VolumeDao;
|
|||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManagerImpl;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.utils.DomainHelper;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.EntityManager;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
|
@ -178,6 +179,8 @@ public class ConfigurationManagerImplTest {
|
|||
PrimaryDataStoreDao storagePoolDao;
|
||||
@Mock
|
||||
StoragePoolDetailsDao storagePoolDetailsDao;
|
||||
@Mock
|
||||
DomainHelper domainHelper;
|
||||
|
||||
DeleteZoneCmd deleteZoneCmd;
|
||||
CreateNetworkOfferingCmd createNetworkOfferingCmd;
|
||||
|
|
|
|||
|
|
@ -246,8 +246,10 @@ public class Ipv6AddressManagerTest {
|
|||
|
||||
Mockito.when(network.getIp6Cidr()).thenReturn("2001:db8:100::/64");
|
||||
Mockito.when(network.getIp6Gateway()).thenReturn("2001:db8:100::1");
|
||||
Mockito.when(network.getId()).thenReturn(1L);
|
||||
|
||||
Mockito.when(networkModel.getNetworkIp6Dns(network, dc)).thenReturn(new Pair<>("2001:db8::53:1", "2001:db8::53:2"));
|
||||
Mockito.when(networkModel.isMACUnique("1e:00:b1:00:0a:f6", 1L)).thenReturn(true);
|
||||
|
||||
String expected = "2001:db8:100:0:1c00:b1ff:fe00:af6";
|
||||
|
||||
|
|
|
|||
|
|
@ -129,6 +129,24 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel {
|
|||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.NetworkModel#getUniqueMacAddress(long, long, long)
|
||||
*/
|
||||
@Override
|
||||
public String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.NetworkModel#isMACUnique(String, long)
|
||||
*/
|
||||
@Override
|
||||
public boolean isMACUnique(String mac, long networkId) {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.NetworkModel#getPublicIpAddress(long)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,944 @@
|
|||
/*
|
||||
* 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.network.vpn;
|
||||
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.Site2SiteVpnConnection;
|
||||
import com.cloud.network.Site2SiteVpnConnection.State;
|
||||
import com.cloud.network.Site2SiteVpnGateway;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.Site2SiteCustomerGatewayDao;
|
||||
import com.cloud.network.dao.Site2SiteCustomerGatewayVO;
|
||||
import com.cloud.network.dao.Site2SiteVpnConnectionDao;
|
||||
import com.cloud.network.dao.Site2SiteVpnConnectionVO;
|
||||
import com.cloud.network.dao.Site2SiteVpnGatewayDao;
|
||||
import com.cloud.network.dao.Site2SiteVpnGatewayVO;
|
||||
import com.cloud.network.element.Site2SiteVpnServiceProvider;
|
||||
import com.cloud.network.vpc.VpcManager;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.network.vpc.dao.VpcDao;
|
||||
import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
import org.apache.cloudstack.api.command.user.vpn.CreateVpnConnectionCmd;
|
||||
import org.apache.cloudstack.api.command.user.vpn.CreateVpnCustomerGatewayCmd;
|
||||
import org.apache.cloudstack.api.command.user.vpn.CreateVpnGatewayCmd;
|
||||
import org.apache.cloudstack.api.command.user.vpn.DeleteVpnConnectionCmd;
|
||||
import org.apache.cloudstack.api.command.user.vpn.DeleteVpnCustomerGatewayCmd;
|
||||
import org.apache.cloudstack.api.command.user.vpn.DeleteVpnGatewayCmd;
|
||||
import org.apache.cloudstack.api.command.user.vpn.ResetVpnConnectionCmd;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
public class Site2SiteVpnManagerImplTest {
|
||||
|
||||
@Mock
|
||||
private Site2SiteCustomerGatewayDao _customerGatewayDao;
|
||||
@Mock
|
||||
private Site2SiteVpnGatewayDao _vpnGatewayDao;
|
||||
@Mock
|
||||
private Site2SiteVpnConnectionDao _vpnConnectionDao;
|
||||
@Mock
|
||||
private VpcDao _vpcDao;
|
||||
@Mock
|
||||
private IPAddressDao _ipAddressDao;
|
||||
@Mock
|
||||
private VpcManager _vpcMgr;
|
||||
@Mock
|
||||
private AccountManager _accountMgr;
|
||||
@Mock
|
||||
private AnnotationDao annotationDao;
|
||||
@Mock
|
||||
private List<Site2SiteVpnServiceProvider> _s2sProviders;
|
||||
@Mock
|
||||
VpcOfferingServiceMapDao vpcOfferingServiceMapDao;
|
||||
|
||||
@InjectMocks
|
||||
private Site2SiteVpnManagerImpl site2SiteVpnManager;
|
||||
|
||||
private AccountVO account;
|
||||
private UserVO user;
|
||||
private VpcVO vpc;
|
||||
private IPAddressVO ipAddress;
|
||||
private Site2SiteVpnGatewayVO vpnGateway;
|
||||
private Site2SiteCustomerGatewayVO customerGateway;
|
||||
private Site2SiteVpnConnectionVO vpnConnection;
|
||||
|
||||
private static final Long ACCOUNT_ID = 1L;
|
||||
private static final Long DOMAIN_ID = 2L;
|
||||
private static final Long VPC_ID = 3L;
|
||||
private static final Long VPN_GATEWAY_ID = 4L;
|
||||
private static final Long CUSTOMER_GATEWAY_ID = 5L;
|
||||
private static final Long VPN_CONNECTION_ID = 6L;
|
||||
private static final Long IP_ADDRESS_ID = 7L;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
account = new AccountVO("testaccount", DOMAIN_ID, "networkdomain", Account.Type.NORMAL, UUID.randomUUID().toString());
|
||||
account.setId(ACCOUNT_ID);
|
||||
user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone",
|
||||
UUID.randomUUID().toString(), User.Source.UNKNOWN);
|
||||
CallContext.register(user, account);
|
||||
|
||||
vpc = mock(VpcVO.class);
|
||||
when(vpc.getId()).thenReturn(VPC_ID);
|
||||
when(vpc.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(vpc.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
when(vpc.getCidr()).thenReturn("10.0.0.0/16");
|
||||
|
||||
ipAddress = mock(IPAddressVO.class);
|
||||
when(ipAddress.getId()).thenReturn(IP_ADDRESS_ID);
|
||||
when(ipAddress.getVpcId()).thenReturn(VPC_ID);
|
||||
|
||||
vpnGateway = mock(Site2SiteVpnGatewayVO.class);
|
||||
when(vpnGateway.getId()).thenReturn(VPN_GATEWAY_ID);
|
||||
when(vpnGateway.getVpcId()).thenReturn(VPC_ID);
|
||||
when(vpnGateway.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(vpnGateway.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
customerGateway = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(customerGateway.getId()).thenReturn(CUSTOMER_GATEWAY_ID);
|
||||
when(customerGateway.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(customerGateway.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
when(customerGateway.getGuestCidrList()).thenReturn("192.168.1.0/24");
|
||||
when(customerGateway.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(customerGateway.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(customerGateway.getIkeVersion()).thenReturn("ike");
|
||||
|
||||
vpnConnection = new Site2SiteVpnConnectionVO(ACCOUNT_ID, DOMAIN_ID, VPN_GATEWAY_ID, CUSTOMER_GATEWAY_ID, false);
|
||||
vpnConnection.setState(State.Pending);
|
||||
|
||||
when(_accountMgr.getAccount(ACCOUNT_ID)).thenReturn(account);
|
||||
doNothing().when(_accountMgr).checkAccess(any(Account.class), nullable(SecurityChecker.AccessType.class), anyBoolean(), any());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
resetConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions);
|
||||
resetConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms);
|
||||
resetConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms);
|
||||
resetConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup);
|
||||
resetConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteIkeVersions);
|
||||
resetConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteEncryptionAlgorithms);
|
||||
resetConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteHashingAlgorithms);
|
||||
resetConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteDhGroup);
|
||||
CallContext.unregister();
|
||||
}
|
||||
|
||||
private void setConfigKeyValue(ConfigKey<String> configKey, String value) {
|
||||
try {
|
||||
Field valueField = ConfigKey.class.getDeclaredField("_value");
|
||||
valueField.setAccessible(true);
|
||||
valueField.set(configKey, value);
|
||||
|
||||
Field dynamicField = ConfigKey.class.getDeclaredField("_isDynamic");
|
||||
dynamicField.setAccessible(true);
|
||||
dynamicField.setBoolean(configKey, false);
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
throw new RuntimeException("Failed to set ConfigKey value", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetConfigKeyValue(ConfigKey<String> configKey) {
|
||||
try {
|
||||
Field valueField = ConfigKey.class.getDeclaredField("_value");
|
||||
valueField.setAccessible(true);
|
||||
valueField.set(configKey, null);
|
||||
|
||||
Field dynamicField = ConfigKey.class.getDeclaredField("_isDynamic");
|
||||
dynamicField.setAccessible(true);
|
||||
dynamicField.setBoolean(configKey, true);
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
throw new RuntimeException("Failed to reset ConfigKey value", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateVpnGatewaySuccess() {
|
||||
CreateVpnGatewayCmd cmd = mock(CreateVpnGatewayCmd.class);
|
||||
when(cmd.getVpcId()).thenReturn(VPC_ID);
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
when(cmd.isDisplay()).thenReturn(true);
|
||||
|
||||
when(_vpcDao.findById(VPC_ID)).thenReturn(vpc);
|
||||
when(_vpnGatewayDao.findByVpcId(VPC_ID)).thenReturn(null);
|
||||
when(_ipAddressDao.listByAssociatedVpc(VPC_ID, true)).thenReturn(List.of(ipAddress));
|
||||
when(_vpnGatewayDao.persist(any(Site2SiteVpnGatewayVO.class))).thenReturn(vpnGateway);
|
||||
|
||||
Site2SiteVpnGateway result = site2SiteVpnManager.createVpnGateway(cmd);
|
||||
|
||||
assertNotNull(result);
|
||||
verify(_vpnGatewayDao).persist(any(Site2SiteVpnGatewayVO.class));
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateVpnGatewayInvalidVpc() {
|
||||
CreateVpnGatewayCmd cmd = mock(CreateVpnGatewayCmd.class);
|
||||
when(cmd.getVpcId()).thenReturn(VPC_ID);
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
when(_vpcDao.findById(VPC_ID)).thenReturn(null);
|
||||
|
||||
site2SiteVpnManager.createVpnGateway(cmd);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateVpnGatewayAlreadyExists() {
|
||||
CreateVpnGatewayCmd cmd = mock(CreateVpnGatewayCmd.class);
|
||||
when(cmd.getVpcId()).thenReturn(VPC_ID);
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
when(_vpcDao.findById(VPC_ID)).thenReturn(vpc);
|
||||
when(_vpnGatewayDao.findByVpcId(VPC_ID)).thenReturn(vpnGateway);
|
||||
|
||||
site2SiteVpnManager.createVpnGateway(cmd);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void testCreateVpnGatewayNoSourceNatIp() {
|
||||
CreateVpnGatewayCmd cmd = mock(CreateVpnGatewayCmd.class);
|
||||
when(cmd.getVpcId()).thenReturn(VPC_ID);
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
when(_vpcDao.findById(VPC_ID)).thenReturn(vpc);
|
||||
when(_vpnGatewayDao.findByVpcId(VPC_ID)).thenReturn(null);
|
||||
when(_ipAddressDao.listByAssociatedVpc(VPC_ID, true)).thenReturn(new ArrayList<>());
|
||||
|
||||
site2SiteVpnManager.createVpnGateway(cmd);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayInvalidIp() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getGatewayIp()).thenReturn("invalid-ip");
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("invalid-ip")).thenReturn(false);
|
||||
netUtilsMock.when(() -> NetUtils.verifyDomainName("invalid-ip")).thenReturn(false);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayInvalidCidrList() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
when(cmd.getGuestCidrList()).thenReturn("invalid-cidr");
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList("invalid-cidr")).thenReturn(false);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayInvalidIkePolicy() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
when(cmd.getGuestCidrList()).thenReturn("192.168.1.0/24");
|
||||
when(cmd.getIkePolicy()).thenReturn("invalid-policy");
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList("192.168.1.0/24")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("ike", "invalid-policy")).thenReturn(false);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayInvalidEspPolicy() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
when(cmd.getGuestCidrList()).thenReturn("192.168.1.0/24");
|
||||
when(cmd.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEspPolicy()).thenReturn("invalid-policy");
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList("192.168.1.0/24")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("ike", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("esp", "invalid-policy")).thenReturn(false);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayWithExcludedParameters() throws Exception {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getName()).thenReturn("test-gateway");
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
when(cmd.getGuestCidrList()).thenReturn("192.168.1.0/24");
|
||||
when(cmd.getIpsecPsk()).thenReturn("test-psk");
|
||||
when(cmd.getIkePolicy()).thenReturn("3des-sha256;modp2048");
|
||||
when(cmd.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getIkeVersion()).thenReturn("ike");
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms, "3des");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup, "");
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList("192.168.1.0/24")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("ike", "3des-sha256;modp2048")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("esp", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayDuplicateName() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getName()).thenReturn("test-gateway");
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
when(cmd.getGuestCidrList()).thenReturn("192.168.1.0/24");
|
||||
when(cmd.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList("192.168.1.0/24")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("ike", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("esp", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
|
||||
when(_customerGatewayDao.findByNameAndAccountId("test-gateway", ACCOUNT_ID)).thenReturn(customerGateway);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayInvalidIkeLifetime() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
when(cmd.getGuestCidrList()).thenReturn("192.168.1.0/24");
|
||||
when(cmd.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getIkeLifetime()).thenReturn(86401L);
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList("192.168.1.0/24")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("ike", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("esp", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayInvalidEspLifetime() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
when(cmd.getGuestCidrList()).thenReturn("192.168.1.0/24");
|
||||
when(cmd.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEspLifetime()).thenReturn(86401L);
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList("192.168.1.0/24")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("ike", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("esp", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayTooManySubnets() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
String tooManyCidrs = "192.168.1.0/24,192.168.2.0/24,192.168.3.0/24,192.168.4.0/24,192.168.5.0/24," +
|
||||
"192.168.6.0/24,192.168.7.0/24,192.168.8.0/24,192.168.9.0/24,192.168.10.0/24,192.168.11.0/24";
|
||||
when(cmd.getGuestCidrList()).thenReturn(tooManyCidrs);
|
||||
when(cmd.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList(tooManyCidrs)).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.getCleanIp4CidrList(tooManyCidrs)).thenReturn(tooManyCidrs);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("ike", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("esp", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateCustomerGatewayOverlappingSubnets() {
|
||||
CreateVpnCustomerGatewayCmd cmd = mock(CreateVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getGatewayIp()).thenReturn("1.2.3.4");
|
||||
when(cmd.getGuestCidrList()).thenReturn("192.168.1.0/24,192.168.1.0/25");
|
||||
when(cmd.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
String cidrList = "192.168.1.0/24,192.168.1.0/25";
|
||||
netUtilsMock.when(() -> NetUtils.isValidIp4("1.2.3.4")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidCidrList(cidrList)).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.getCleanIp4CidrList(cidrList)).thenReturn(cidrList);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("ike", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isValidS2SVpnPolicy("esp", "aes128-sha256;modp2048")).thenReturn(true);
|
||||
netUtilsMock.when(() -> NetUtils.isNetworksOverlap("192.168.1.0/24", "192.168.1.0/25")).thenReturn(true);
|
||||
|
||||
site2SiteVpnManager.createCustomerGateway(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateVpnConnectionCidrOverlapWithVpc() {
|
||||
CreateVpnConnectionCmd cmd = mock(CreateVpnConnectionCmd.class);
|
||||
when(cmd.getVpnGatewayId()).thenReturn(VPN_GATEWAY_ID);
|
||||
when(cmd.getCustomerGatewayId()).thenReturn(CUSTOMER_GATEWAY_ID);
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
Site2SiteCustomerGatewayVO customerGw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(customerGw.getGuestCidrList()).thenReturn("10.0.0.0/24");
|
||||
when(customerGw.getAccountId()).thenReturn(ACCOUNT_ID);
|
||||
when(customerGw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
when(_customerGatewayDao.findById(CUSTOMER_GATEWAY_ID)).thenReturn(customerGw);
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
when(_vpnConnectionDao.findByVpnGatewayIdAndCustomerGatewayId(VPN_GATEWAY_ID, CUSTOMER_GATEWAY_ID)).thenReturn(null);
|
||||
when(_vpnGatewayDao.findByVpcId(VPC_ID)).thenReturn(vpnGateway);
|
||||
when(_vpcDao.findById(VPC_ID)).thenReturn(vpc);
|
||||
|
||||
try (MockedStatic<NetUtils> netUtilsMock = Mockito.mockStatic(NetUtils.class)) {
|
||||
netUtilsMock.when(() -> NetUtils.isNetworksOverlap("10.0.0.0/16", "10.0.0.0/24")).thenReturn(true);
|
||||
|
||||
site2SiteVpnManager.createVpnConnection(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testCreateVpnConnectionExceedsLimit() {
|
||||
CreateVpnConnectionCmd cmd = mock(CreateVpnConnectionCmd.class);
|
||||
when(cmd.getVpnGatewayId()).thenReturn(VPN_GATEWAY_ID);
|
||||
when(cmd.getCustomerGatewayId()).thenReturn(CUSTOMER_GATEWAY_ID);
|
||||
when(cmd.getEntityOwnerId()).thenReturn(ACCOUNT_ID);
|
||||
|
||||
when(_customerGatewayDao.findById(CUSTOMER_GATEWAY_ID)).thenReturn(customerGateway);
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
when(_vpnConnectionDao.findByVpnGatewayIdAndCustomerGatewayId(VPN_GATEWAY_ID, CUSTOMER_GATEWAY_ID)).thenReturn(null);
|
||||
when(_vpnGatewayDao.findByVpcId(VPC_ID)).thenReturn(vpnGateway);
|
||||
when(_vpcDao.findById(VPC_ID)).thenReturn(vpc);
|
||||
|
||||
List<Site2SiteVpnConnectionVO> existingConns = new ArrayList<>();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
existingConns.add(mock(Site2SiteVpnConnectionVO.class));
|
||||
}
|
||||
when(_vpnConnectionDao.listByVpnGatewayId(VPN_GATEWAY_ID)).thenReturn(existingConns);
|
||||
|
||||
site2SiteVpnManager.createVpnConnection(cmd);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteCustomerGatewaySuccess() {
|
||||
DeleteVpnCustomerGatewayCmd cmd = mock(DeleteVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getId()).thenReturn(CUSTOMER_GATEWAY_ID);
|
||||
|
||||
when(_customerGatewayDao.findById(CUSTOMER_GATEWAY_ID)).thenReturn(customerGateway);
|
||||
when(_vpnConnectionDao.listByCustomerGatewayId(CUSTOMER_GATEWAY_ID)).thenReturn(new ArrayList<>());
|
||||
|
||||
boolean result = site2SiteVpnManager.deleteCustomerGateway(cmd);
|
||||
|
||||
assertTrue(result);
|
||||
verify(_customerGatewayDao).remove(CUSTOMER_GATEWAY_ID);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testDeleteCustomerGatewayWithConnections() {
|
||||
DeleteVpnCustomerGatewayCmd cmd = mock(DeleteVpnCustomerGatewayCmd.class);
|
||||
when(cmd.getId()).thenReturn(CUSTOMER_GATEWAY_ID);
|
||||
|
||||
when(_customerGatewayDao.findById(CUSTOMER_GATEWAY_ID)).thenReturn(customerGateway);
|
||||
when(_vpnConnectionDao.listByCustomerGatewayId(CUSTOMER_GATEWAY_ID)).thenReturn(List.of(vpnConnection));
|
||||
|
||||
site2SiteVpnManager.deleteCustomerGateway(cmd);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteVpnGatewaySuccess() {
|
||||
DeleteVpnGatewayCmd cmd = mock(DeleteVpnGatewayCmd.class);
|
||||
when(cmd.getId()).thenReturn(VPN_GATEWAY_ID);
|
||||
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
when(_vpnConnectionDao.listByVpnGatewayId(VPN_GATEWAY_ID)).thenReturn(new ArrayList<>());
|
||||
|
||||
boolean result = site2SiteVpnManager.deleteVpnGateway(cmd);
|
||||
|
||||
assertTrue(result);
|
||||
verify(_vpnGatewayDao).remove(VPN_GATEWAY_ID);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testDeleteVpnGatewayWithConnections() {
|
||||
DeleteVpnGatewayCmd cmd = mock(DeleteVpnGatewayCmd.class);
|
||||
when(cmd.getId()).thenReturn(VPN_GATEWAY_ID);
|
||||
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
when(_vpnConnectionDao.listByVpnGatewayId(VPN_GATEWAY_ID)).thenReturn(List.of(vpnConnection));
|
||||
|
||||
site2SiteVpnManager.deleteVpnGateway(cmd);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteVpnConnectionSuccess() throws ResourceUnavailableException {
|
||||
DeleteVpnConnectionCmd cmd = mock(DeleteVpnConnectionCmd.class);
|
||||
when(cmd.getId()).thenReturn(VPN_CONNECTION_ID);
|
||||
|
||||
when(_vpnConnectionDao.findById(VPN_CONNECTION_ID)).thenReturn(vpnConnection);
|
||||
vpnConnection.setState(State.Pending);
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
when(_vpcMgr.applyStaticRouteForVpcVpnIfNeeded(anyLong(), anyBoolean())).thenReturn(true);
|
||||
|
||||
boolean result = site2SiteVpnManager.deleteVpnConnection(cmd);
|
||||
|
||||
assertTrue(result);
|
||||
verify(_vpnConnectionDao).remove(VPN_CONNECTION_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartVpnConnectionSuccess() throws ResourceUnavailableException {
|
||||
when(_vpnConnectionDao.acquireInLockTable(VPN_CONNECTION_ID)).thenReturn(vpnConnection);
|
||||
vpnConnection.setState(State.Pending);
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
Site2SiteVpnServiceProvider provider = mock(Site2SiteVpnServiceProvider.class);
|
||||
when(provider.startSite2SiteVpn(any(Site2SiteVpnConnection.class))).thenReturn(true);
|
||||
when(_s2sProviders.iterator()).thenReturn(List.of(provider).iterator());
|
||||
when(_vpnConnectionDao.persist(any(Site2SiteVpnConnectionVO.class))).thenReturn(vpnConnection);
|
||||
when(_vpcMgr.applyStaticRouteForVpcVpnIfNeeded(anyLong(), anyBoolean())).thenReturn(true);
|
||||
|
||||
Site2SiteVpnConnection result = site2SiteVpnManager.startVpnConnection(VPN_CONNECTION_ID);
|
||||
|
||||
assertNotNull(result);
|
||||
verify(_vpnConnectionDao, org.mockito.Mockito.atLeastOnce()).persist(any(Site2SiteVpnConnectionVO.class));
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void testStartVpnConnectionWrongState() throws ResourceUnavailableException {
|
||||
when(_vpnConnectionDao.acquireInLockTable(VPN_CONNECTION_ID)).thenReturn(vpnConnection);
|
||||
vpnConnection.setState(State.Connected);
|
||||
|
||||
site2SiteVpnManager.startVpnConnection(VPN_CONNECTION_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResetVpnConnectionSuccess() throws ResourceUnavailableException {
|
||||
ResetVpnConnectionCmd cmd = mock(ResetVpnConnectionCmd.class);
|
||||
when(cmd.getId()).thenReturn(VPN_CONNECTION_ID);
|
||||
|
||||
when(_vpnConnectionDao.findById(VPN_CONNECTION_ID)).thenReturn(vpnConnection);
|
||||
vpnConnection.setState(State.Connected);
|
||||
when(_vpnConnectionDao.acquireInLockTable(VPN_CONNECTION_ID)).thenReturn(vpnConnection);
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
Site2SiteVpnServiceProvider provider = mock(Site2SiteVpnServiceProvider.class);
|
||||
when(provider.stopSite2SiteVpn(any(Site2SiteVpnConnection.class))).thenReturn(true);
|
||||
when(provider.startSite2SiteVpn(any(Site2SiteVpnConnection.class))).thenReturn(true);
|
||||
when(_s2sProviders.iterator()).thenReturn(List.of(provider).iterator());
|
||||
when(_vpnConnectionDao.persist(any(Site2SiteVpnConnectionVO.class))).thenReturn(vpnConnection);
|
||||
when(_vpcMgr.applyStaticRouteForVpcVpnIfNeeded(anyLong(), anyBoolean())).thenReturn(true);
|
||||
|
||||
Site2SiteVpnConnection result = site2SiteVpnManager.resetVpnConnection(cmd);
|
||||
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCleanupVpnConnectionByVpc() {
|
||||
when(_vpnConnectionDao.listByVpcId(VPC_ID)).thenReturn(List.of(vpnConnection));
|
||||
|
||||
boolean result = site2SiteVpnManager.cleanupVpnConnectionByVpc(VPC_ID);
|
||||
|
||||
assertTrue(result);
|
||||
verify(_vpnConnectionDao).remove(vpnConnection.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCleanupVpnGatewayByVpc() {
|
||||
when(_vpnGatewayDao.findByVpcId(VPC_ID)).thenReturn(vpnGateway);
|
||||
when(_vpnConnectionDao.listByVpnGatewayId(VPN_GATEWAY_ID)).thenReturn(new ArrayList<>());
|
||||
|
||||
boolean result = site2SiteVpnManager.cleanupVpnGatewayByVpc(VPC_ID);
|
||||
|
||||
assertTrue(result);
|
||||
verify(_vpnGatewayDao).remove(VPN_GATEWAY_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCleanupVpnGatewayByVpcNotFound() {
|
||||
when(_vpnGatewayDao.findByVpcId(VPC_ID)).thenReturn(null);
|
||||
|
||||
boolean result = site2SiteVpnManager.cleanupVpnGatewayByVpc(VPC_ID);
|
||||
|
||||
assertTrue(result);
|
||||
verify(_vpnGatewayDao, never()).remove(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConnectionsForRouter() {
|
||||
DomainRouterVO router = mock(DomainRouterVO.class);
|
||||
when(router.getVpcId()).thenReturn(VPC_ID);
|
||||
when(_vpnConnectionDao.listByVpcId(VPC_ID)).thenReturn(List.of(vpnConnection));
|
||||
|
||||
List<Site2SiteVpnConnectionVO> result = site2SiteVpnManager.getConnectionsForRouter(router);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetConnectionsForRouterNoVpc() {
|
||||
DomainRouterVO router = mock(DomainRouterVO.class);
|
||||
when(router.getVpcId()).thenReturn(null);
|
||||
|
||||
List<Site2SiteVpnConnectionVO> result = site2SiteVpnManager.getConnectionsForRouter(router);
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteCustomerGatewayByAccount() {
|
||||
when(_customerGatewayDao.listByAccountId(ACCOUNT_ID)).thenReturn(List.of(customerGateway));
|
||||
when(_vpnConnectionDao.listByCustomerGatewayId(CUSTOMER_GATEWAY_ID)).thenReturn(new ArrayList<>());
|
||||
|
||||
boolean result = site2SiteVpnManager.deleteCustomerGatewayByAccount(ACCOUNT_ID);
|
||||
|
||||
assertTrue(result);
|
||||
verify(_customerGatewayDao).remove(CUSTOMER_GATEWAY_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReconnectDisconnectedVpnByVpc() throws ResourceUnavailableException {
|
||||
Site2SiteVpnConnectionVO conn = mock(Site2SiteVpnConnectionVO.class);
|
||||
when(conn.getId()).thenReturn(VPN_CONNECTION_ID);
|
||||
when(conn.getState()).thenReturn(State.Disconnected);
|
||||
when(conn.getCustomerGatewayId()).thenReturn(CUSTOMER_GATEWAY_ID);
|
||||
when(conn.getVpnGatewayId()).thenReturn(VPN_GATEWAY_ID);
|
||||
when(_vpnConnectionDao.listByVpcId(VPC_ID)).thenReturn(List.of(conn));
|
||||
when(_customerGatewayDao.findById(CUSTOMER_GATEWAY_ID)).thenReturn(customerGateway);
|
||||
when(_vpnConnectionDao.acquireInLockTable(VPN_CONNECTION_ID)).thenReturn(conn);
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
Site2SiteVpnServiceProvider provider = mock(Site2SiteVpnServiceProvider.class);
|
||||
when(provider.startSite2SiteVpn(any(Site2SiteVpnConnection.class))).thenReturn(true);
|
||||
when(_s2sProviders.iterator()).thenReturn(List.of(provider).iterator());
|
||||
when(_vpnConnectionDao.persist(any(Site2SiteVpnConnectionVO.class))).thenReturn(conn);
|
||||
when(_vpcMgr.applyStaticRouteForVpcVpnIfNeeded(anyLong(), anyBoolean())).thenReturn(true);
|
||||
|
||||
site2SiteVpnManager.reconnectDisconnectedVpnByVpc(VPC_ID);
|
||||
|
||||
verify(_vpnConnectionDao, org.mockito.Mockito.atLeastOnce()).persist(any(Site2SiteVpnConnectionVO.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateVpnConnection() {
|
||||
when(_vpnConnectionDao.findById(VPN_CONNECTION_ID)).thenReturn(vpnConnection);
|
||||
when(_vpnConnectionDao.update(anyLong(), any(Site2SiteVpnConnectionVO.class))).thenReturn(true);
|
||||
when(_vpnConnectionDao.findById(VPN_CONNECTION_ID)).thenReturn(vpnConnection);
|
||||
|
||||
Site2SiteVpnConnection result = site2SiteVpnManager.updateVpnConnection(VPN_CONNECTION_ID, "custom-id", true);
|
||||
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateVpnGateway() {
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
when(_vpnGatewayDao.update(anyLong(), any(Site2SiteVpnGatewayVO.class))).thenReturn(true);
|
||||
when(_vpnGatewayDao.findById(VPN_GATEWAY_ID)).thenReturn(vpnGateway);
|
||||
|
||||
Site2SiteVpnGateway result = site2SiteVpnManager.updateVpnGateway(VPN_GATEWAY_ID, "custom-id", true);
|
||||
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsExcludedParametersWithExcludedIkeVersion() throws Exception {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ikev1");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions, "ikev1");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getExcludedVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect excluded IKE version", result.isEmpty());
|
||||
assertEquals("Should detect excluded IKE version", "[ikev1]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsExcludedParametersWithExcludedEncryption() throws Exception {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("3des-sha256;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms, "3des");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getExcludedVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect excluded encryption algorithm", result.isEmpty());
|
||||
assertEquals("Should detect excluded encryption algorithm", "[3des]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsExcludedParametersWithExcludedHashing() throws Exception {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-md5;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms, "aes128");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms, "md5");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getExcludedVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect excluded algorithms", result.isEmpty());
|
||||
assertEquals("Should detect excluded algorithms", "[aes128, md5]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsExcludedParametersWithExcludedDhGroup() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-sha256;modp1024");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup, "modp1024");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getExcludedVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect excluded DH group", result.isEmpty());
|
||||
assertEquals("Should detect excluded DH group", "[modp1024]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsExcludedParametersNoExcludedParameters() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getExcludedVpnGatewayParameters(gw);
|
||||
assertTrue("Should not detect excluded parameters when none are configured", result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsExcludedParametersWithExcludedEspPolicy() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("3des-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedEncryptionAlgorithms, "3des");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayExcludedDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getExcludedVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect excluded encryption in ESP policy", result.isEmpty());
|
||||
assertEquals("Should detect excluded encryption in ESP policy", "[3des]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsObsoleteParametersWithObsoleteIkeVersion() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ikev1");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteIkeVersions, "ikev1");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteEncryptionAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getObsoleteVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect obsolete IKE version", result.isEmpty());
|
||||
assertEquals("Should detect obsolete IKE version", "[ikev1]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsObsoleteParametersWithObsoleteEncryption() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("3des-sha256;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteEncryptionAlgorithms, "3des");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getObsoleteVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect obsolete encryption algorithm", result.isEmpty());
|
||||
assertEquals("Should detect obsolete encryption algorithm", "[3des]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsObsoleteParametersWithObsoleteHashing() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-md5;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteEncryptionAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteHashingAlgorithms, "md5");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getObsoleteVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect obsolete hashing algorithm", result.isEmpty());
|
||||
assertEquals("Should detect obsolete hashing algorithm", "[md5]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsObsoleteParametersWithObsoleteDhGroup() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-sha256;modp1024");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteEncryptionAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteDhGroup, "modp1024");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getObsoleteVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect obsolete DH group", result.isEmpty());
|
||||
assertEquals("Should detect obsolete DH group", "[modp1024]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsObsoleteParametersNoObsoleteParameters() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteEncryptionAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getObsoleteVpnGatewayParameters(gw);
|
||||
assertTrue("Should not detect obsolete parameters when none are configured", result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVpnGatewayContainsObsoleteParametersWithObsoleteEspPolicy() {
|
||||
Site2SiteCustomerGatewayVO gw = mock(Site2SiteCustomerGatewayVO.class);
|
||||
when(gw.getIkePolicy()).thenReturn("aes128-sha256;modp2048");
|
||||
when(gw.getEspPolicy()).thenReturn("3des-sha256;modp2048");
|
||||
when(gw.getIkeVersion()).thenReturn("ike");
|
||||
when(gw.getDomainId()).thenReturn(DOMAIN_ID);
|
||||
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteIkeVersions, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteEncryptionAlgorithms, "3des");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteHashingAlgorithms, "");
|
||||
setConfigKeyValue(Site2SiteVpnManagerImpl.VpnCustomerGatewayObsoleteDhGroup, "");
|
||||
|
||||
java.util.Set<String> result = site2SiteVpnManager.getObsoleteVpnGatewayParameters(gw);
|
||||
assertFalse("Should detect obsolete encryption in ESP policy", result.isEmpty());
|
||||
assertEquals("Should detect obsolete encryption in ESP policy", "[3des]", result.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -164,7 +164,7 @@ public class SnapshotManagerImplTest {
|
|||
Mockito.when(ref1.getDataStoreId()).thenReturn(2L);
|
||||
Mockito.when(ref1.getRole()).thenReturn(DataStoreRole.Image);
|
||||
List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref, ref1);
|
||||
Mockito.when(snapshotStoreDao.findBySnapshotId(snapshotId)).thenReturn(snapshotStoreList);
|
||||
Mockito.when(snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId)).thenReturn(snapshotStoreList);
|
||||
Mockito.when(dataStoreManager.getStoreZoneId(1L, DataStoreRole.Image)).thenReturn(100L);
|
||||
Mockito.when(dataStoreManager.getStoreZoneId(2L, DataStoreRole.Image)).thenReturn(101L);
|
||||
Pair<List<SnapshotDataStoreVO>, List<Long>> pair = snapshotManager.getStoreRefsAndZonesForSnapshotDelete(snapshotId, null);
|
||||
|
|
@ -189,7 +189,7 @@ public class SnapshotManagerImplTest {
|
|||
Mockito.when(ref2.getDataStoreId()).thenReturn(3L);
|
||||
Mockito.when(ref2.getRole()).thenReturn(DataStoreRole.Image);
|
||||
List<SnapshotDataStoreVO> snapshotStoreList = List.of(ref, ref1, ref2);
|
||||
Mockito.when(snapshotStoreDao.findBySnapshotId(snapshotId)).thenReturn(snapshotStoreList);
|
||||
Mockito.when(snapshotStoreDao.findBySnapshotIdWithNonDestroyedState(snapshotId)).thenReturn(snapshotStoreList);
|
||||
Mockito.when(dataStoreManager.getStoreZoneId(1L, DataStoreRole.Image)).thenReturn(zoneId);
|
||||
Mockito.when(dataStoreManager.getStoreZoneId(2L, DataStoreRole.Primary)).thenReturn(zoneId);
|
||||
Mockito.when(dataStoreManager.getStoreZoneId(3L, DataStoreRole.Image)).thenReturn(2L);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ import java.util.Map;
|
|||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.cloud.domain.Domain;
|
||||
import com.cloud.storage.dao.SnapshotPolicyDao;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
|
|
@ -3107,7 +3108,7 @@ public class UserVmManagerImplTest {
|
|||
|
||||
configureDoNothingForMethodsThatWeDoNotWantToTest();
|
||||
|
||||
doThrow(PermissionDeniedException.class).when(accountManager).checkAccess(Mockito.any(Account.class), Mockito.any());
|
||||
doThrow(PermissionDeniedException.class).when(accountManager).checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class));
|
||||
|
||||
Assert.assertThrows(PermissionDeniedException.class, () -> userVmManagerImpl.moveVmToUser(assignVmCmdMock));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,24 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel {
|
|||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.NetworkModel#getUniqueMacAddress(long, long, long)
|
||||
*/
|
||||
@Override
|
||||
public String getUniqueMacAddress(long macAddress, long networkId, long datacenterId) throws InsufficientAddressCapacityException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.NetworkModel#isMACUnique(String, long)
|
||||
*/
|
||||
@Override
|
||||
public boolean isMACUnique(String mac, long networkId) {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.NetworkModel#getPublicIpAddress(long)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import com.cloud.network.Site2SiteVpnConnection;
|
|||
import com.cloud.network.Site2SiteVpnGateway;
|
||||
import com.cloud.network.dao.Site2SiteVpnConnectionVO;
|
||||
import com.cloud.network.vpn.Site2SiteVpnManager;
|
||||
import com.cloud.network.vpn.Site2SiteVpnService;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
|
|
@ -41,11 +40,13 @@ import org.apache.cloudstack.api.command.user.vpn.UpdateVpnCustomerGatewayCmd;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
public class MockSite2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpnManager, Site2SiteVpnService {
|
||||
public class MockSite2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpnManager {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.vpn.Site2SiteVpnService#createVpnGateway(org.apache.cloudstack.api.commands.CreateVpnGatewayCmd)
|
||||
|
|
@ -275,4 +276,16 @@ public class MockSite2SiteVpnManagerImpl extends ManagerBase implements Site2Sit
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getExcludedVpnGatewayParameters(Site2SiteCustomerGateway customerGw) {
|
||||
// TODO Auto-generated method stub
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getObsoleteVpnGatewayParameters(Site2SiteCustomerGateway customerGw) {
|
||||
// TODO Auto-generated method stub
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import com.cloud.user.ResourceLimitService;
|
|||
import com.cloud.user.User;
|
||||
import com.cloud.user.dao.AccountDao;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.DomainHelper;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
|
@ -80,11 +81,13 @@ import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
|
|||
import org.apache.cloudstack.api.command.user.backup.CreateBackupCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.ListBackupOfferingsCmd;
|
||||
import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
|
||||
import org.apache.cloudstack.api.response.BackupResponse;
|
||||
import org.apache.cloudstack.backup.dao.BackupDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupDetailsDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupOfferingDetailsDao;
|
||||
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
|
@ -241,6 +244,12 @@ public class BackupManagerTest {
|
|||
@Mock
|
||||
private GuestOSDao _guestOSDao;
|
||||
|
||||
@Mock
|
||||
private BackupOfferingDetailsDao backupOfferingDetailsDao;
|
||||
|
||||
@Mock
|
||||
DomainHelper domainHelper;
|
||||
|
||||
private Gson gson;
|
||||
|
||||
private String[] hostPossibleValues = {"127.0.0.1", "hostname"};
|
||||
|
|
@ -352,6 +361,7 @@ public class BackupManagerTest {
|
|||
when(cmd.getName()).thenReturn("New name");
|
||||
when(cmd.getDescription()).thenReturn("New description");
|
||||
when(cmd.getAllowUserDrivenBackups()).thenReturn(true);
|
||||
when(backupOfferingDetailsDao.findDomainIds(id)).thenReturn(Collections.emptyList());
|
||||
|
||||
BackupOffering updated = backupManager.updateBackupOffering(cmd);
|
||||
assertEquals("New name", updated.getName());
|
||||
|
|
@ -1081,7 +1091,7 @@ public class BackupManagerTest {
|
|||
|
||||
assertEquals("root-disk-offering-uuid", VmDiskInfo.getDiskOffering().getUuid());
|
||||
assertEquals(Long.valueOf(5), VmDiskInfo.getSize());
|
||||
assertEquals(null, VmDiskInfo.getDeviceId());
|
||||
assertNull(VmDiskInfo.getDeviceId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1106,7 +1116,7 @@ public class BackupManagerTest {
|
|||
|
||||
assertEquals("Test Offering", result.getName());
|
||||
assertEquals("Test Description", result.getDescription());
|
||||
assertEquals(true, result.isUserDrivenBackupAllowed());
|
||||
assertTrue(result.isUserDrivenBackupAllowed());
|
||||
assertEquals("external-id", result.getExternalId());
|
||||
assertEquals("testbackupprovider", result.getProvider());
|
||||
}
|
||||
|
|
@ -1149,6 +1159,8 @@ public class BackupManagerTest {
|
|||
VMInstanceVO vm = mock(VMInstanceVO.class);
|
||||
when(vm.getId()).thenReturn(vmId);
|
||||
BackupOfferingVO offering = mock(BackupOfferingVO.class);
|
||||
Account owner = mock(Account.class);
|
||||
|
||||
|
||||
overrideBackupFrameworkConfigValue();
|
||||
|
||||
|
|
@ -1159,6 +1171,8 @@ public class BackupManagerTest {
|
|||
when(vm.getBackupOfferingId()).thenReturn(null);
|
||||
when(offering.getProvider()).thenReturn("testbackupprovider");
|
||||
when(backupProvider.assignVMToBackupOffering(vm, offering)).thenReturn(true);
|
||||
when(vm.getAccountId()).thenReturn(3L);
|
||||
when(accountManager.getAccount(vm.getAccountId())).thenReturn(owner);
|
||||
when(vmInstanceDao.update(1L, vm)).thenReturn(true);
|
||||
|
||||
try (MockedStatic<UsageEventUtils> ignored2 = Mockito.mockStatic(UsageEventUtils.class)) {
|
||||
|
|
@ -2156,4 +2170,352 @@ public class BackupManagerTest {
|
|||
verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
|
||||
verify(volumeDao, times(1)).findByInstance(vmId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBackupOfferingDomainsTestOfferingNotFound() {
|
||||
Long offeringId = 1L;
|
||||
when(backupOfferingDao.findById(offeringId)).thenReturn(null);
|
||||
|
||||
InvalidParameterValueException exception = Assert.assertThrows(InvalidParameterValueException.class,
|
||||
() -> backupManager.getBackupOfferingDomains(offeringId));
|
||||
assertEquals("Unable to find backup offering for id: " + offeringId, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBackupOfferingDomainsTestReturnsDomains() {
|
||||
Long offeringId = 1L;
|
||||
BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.findById(offeringId)).thenReturn(offering);
|
||||
when(backupOfferingDetailsDao.findDomainIds(offeringId)).thenReturn(List.of(10L, 20L));
|
||||
|
||||
List<Long> result = backupManager.getBackupOfferingDomains(offeringId);
|
||||
|
||||
assertEquals(2, result.size());
|
||||
assertTrue(result.contains(10L));
|
||||
assertTrue(result.contains(20L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateBackupOfferingThrowsWhenDomainIdInvalid() {
|
||||
Long id = 1234L;
|
||||
UpdateBackupOfferingCmd cmd = Mockito.spy(UpdateBackupOfferingCmd.class);
|
||||
when(cmd.getId()).thenReturn(id);
|
||||
when(cmd.getDomainIds()).thenReturn(List.of(99L));
|
||||
|
||||
when(domainDao.findById(99L)).thenReturn(null);
|
||||
|
||||
InvalidParameterValueException exception = Assert.assertThrows(InvalidParameterValueException.class,
|
||||
() -> backupManager.updateBackupOffering(cmd));
|
||||
assertEquals("Please specify a valid domain id", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateBackupOfferingPersistsDomainDetailsWhenProvided() {
|
||||
Long id = 1234L;
|
||||
Long domainId = 11L;
|
||||
UpdateBackupOfferingCmd cmd = Mockito.spy(UpdateBackupOfferingCmd.class);
|
||||
when(cmd.getId()).thenReturn(id);
|
||||
when(cmd.getDomainIds()).thenReturn(List.of(domainId));
|
||||
|
||||
DomainVO domain = Mockito.mock(DomainVO.class);
|
||||
when(domainDao.findById(domainId)).thenReturn(domain);
|
||||
|
||||
when(domainHelper.filterChildSubDomains(List.of(domainId))).thenReturn(new ArrayList<>(List.of(domainId)));
|
||||
when(backupOfferingDetailsDao.findDomainIds(id)).thenReturn(new ArrayList<>());
|
||||
|
||||
BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
|
||||
BackupOfferingVO offeringUpdate = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.findById(id)).thenReturn(offering);
|
||||
when(backupOfferingDao.createForUpdate(id)).thenReturn(offeringUpdate);
|
||||
when(backupOfferingDao.update(id, offeringUpdate)).thenReturn(true);
|
||||
|
||||
BackupOffering updated = backupManager.updateBackupOffering(cmd);
|
||||
|
||||
verify(backupOfferingDetailsDao, times(1)).updateBackupOfferingDomainIdsDetail(id, List.of(domainId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListBackupOfferingsWithDomainFilteringIncludesGlobalOfferings() {
|
||||
Long requestedDomainId = 3L;
|
||||
|
||||
ListBackupOfferingsCmd cmd =
|
||||
Mockito.mock(ListBackupOfferingsCmd.class);
|
||||
when(cmd.getOfferingId()).thenReturn(null);
|
||||
when(cmd.getDomainId()).thenReturn(requestedDomainId);
|
||||
when(cmd.getStartIndex()).thenReturn(0L);
|
||||
when(cmd.getPageSizeVal()).thenReturn(20L);
|
||||
|
||||
BackupOfferingVO globalOffering = createMockOffering(1L, "Global Offering");
|
||||
BackupOfferingVO domainOffering = createMockOffering(2L, "Domain Offering");
|
||||
|
||||
List<BackupOfferingVO> allOfferings = List.of(globalOffering, domainOffering);
|
||||
|
||||
SearchBuilder<BackupOfferingVO> sb = Mockito.mock(SearchBuilder.class);
|
||||
SearchCriteria<BackupOfferingVO> sc = Mockito.mock(SearchCriteria.class);
|
||||
BackupOfferingVO entityMock = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.createSearchBuilder()).thenReturn(sb);
|
||||
when(sb.entity()).thenReturn(entityMock);
|
||||
when(sb.and(Mockito.anyString(), Mockito.any(), Mockito.any(SearchCriteria.Op.class))).thenReturn(sb);
|
||||
when(sb.create()).thenReturn(sc);
|
||||
when(backupOfferingDao.searchAndCount(Mockito.any(), Mockito.any()))
|
||||
.thenReturn(new Pair<>(allOfferings, allOfferings.size()));
|
||||
|
||||
when(backupOfferingDetailsDao.findDomainIds(1L)).thenReturn(Collections.emptyList());
|
||||
when(backupOfferingDetailsDao.findDomainIds(2L)).thenReturn(List.of(2L));
|
||||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
when(account.getType()).thenReturn(Account.Type.NORMAL);
|
||||
|
||||
try (MockedStatic<CallContext> mockedCallContext = Mockito.mockStatic(CallContext.class)) {
|
||||
CallContext contextMock = Mockito.mock(CallContext.class);
|
||||
mockedCallContext.when(CallContext::current).thenReturn(contextMock);
|
||||
when(contextMock.getCallingAccount()).thenReturn(account);
|
||||
|
||||
Pair<List<BackupOffering>, Integer> result = backupManager.listBackupOfferings(cmd);
|
||||
|
||||
assertEquals(1, result.first().size());
|
||||
assertEquals("Global Offering", result.first().get(0).getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListBackupOfferingsWithDomainFilteringIncludesDirectDomainMapping() {
|
||||
Long requestedDomainId = 3L;
|
||||
|
||||
ListBackupOfferingsCmd cmd =
|
||||
Mockito.mock(ListBackupOfferingsCmd.class);
|
||||
when(cmd.getOfferingId()).thenReturn(null);
|
||||
when(cmd.getDomainId()).thenReturn(requestedDomainId);
|
||||
when(cmd.getStartIndex()).thenReturn(0L);
|
||||
when(cmd.getPageSizeVal()).thenReturn(20L);
|
||||
|
||||
BackupOfferingVO directDomainOffering = createMockOffering(1L, "Direct Domain Offering");
|
||||
BackupOfferingVO otherDomainOffering = createMockOffering(2L, "Other Domain Offering");
|
||||
|
||||
List<BackupOfferingVO> allOfferings = List.of(directDomainOffering, otherDomainOffering);
|
||||
|
||||
SearchBuilder<BackupOfferingVO> sb = Mockito.mock(SearchBuilder.class);
|
||||
SearchCriteria<BackupOfferingVO> sc = Mockito.mock(SearchCriteria.class);
|
||||
BackupOfferingVO entityMock = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.createSearchBuilder()).thenReturn(sb);
|
||||
when(sb.entity()).thenReturn(entityMock);
|
||||
when(sb.and(Mockito.anyString(), Mockito.any(), Mockito.any(SearchCriteria.Op.class))).thenReturn(sb);
|
||||
when(sb.create()).thenReturn(sc);
|
||||
when(backupOfferingDao.searchAndCount(Mockito.any(), Mockito.any()))
|
||||
.thenReturn(new Pair<>(allOfferings, allOfferings.size()));
|
||||
|
||||
when(backupOfferingDetailsDao.findDomainIds(1L)).thenReturn(List.of(requestedDomainId));
|
||||
when(backupOfferingDetailsDao.findDomainIds(2L)).thenReturn(List.of(5L));
|
||||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
when(account.getType()).thenReturn(Account.Type.NORMAL);
|
||||
|
||||
try (MockedStatic<CallContext> mockedCallContext = Mockito.mockStatic(CallContext.class)) {
|
||||
CallContext contextMock = Mockito.mock(CallContext.class);
|
||||
mockedCallContext.when(CallContext::current).thenReturn(contextMock);
|
||||
when(contextMock.getCallingAccount()).thenReturn(account);
|
||||
|
||||
Pair<List<BackupOffering>, Integer> result = backupManager.listBackupOfferings(cmd);
|
||||
|
||||
assertEquals(1, result.first().size());
|
||||
assertEquals("Direct Domain Offering", result.first().get(0).getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListBackupOfferingsWithDomainFilteringIncludesParentDomainOfferings() {
|
||||
Long parentDomainId = 1L;
|
||||
Long childDomainId = 3L;
|
||||
|
||||
ListBackupOfferingsCmd cmd =
|
||||
Mockito.mock(ListBackupOfferingsCmd.class);
|
||||
when(cmd.getOfferingId()).thenReturn(null);
|
||||
when(cmd.getDomainId()).thenReturn(childDomainId);
|
||||
when(cmd.getStartIndex()).thenReturn(0L);
|
||||
when(cmd.getPageSizeVal()).thenReturn(20L);
|
||||
|
||||
BackupOfferingVO parentDomainOffering = createMockOffering(1L, "Parent Domain Offering");
|
||||
BackupOfferingVO siblingDomainOffering = createMockOffering(2L, "Sibling Domain Offering");
|
||||
|
||||
List<BackupOfferingVO> allOfferings = List.of(parentDomainOffering, siblingDomainOffering);
|
||||
|
||||
SearchBuilder<BackupOfferingVO> sb = Mockito.mock(SearchBuilder.class);
|
||||
SearchCriteria<BackupOfferingVO> sc = Mockito.mock(SearchCriteria.class);
|
||||
BackupOfferingVO entityMock = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.createSearchBuilder()).thenReturn(sb);
|
||||
when(sb.entity()).thenReturn(entityMock);
|
||||
when(sb.and(Mockito.anyString(), Mockito.any(), Mockito.any(SearchCriteria.Op.class))).thenReturn(sb);
|
||||
when(sb.create()).thenReturn(sc);
|
||||
when(backupOfferingDao.searchAndCount(Mockito.any(), Mockito.any()))
|
||||
.thenReturn(new Pair<>(allOfferings, allOfferings.size()));
|
||||
|
||||
when(backupOfferingDetailsDao.findDomainIds(1L)).thenReturn(List.of(parentDomainId));
|
||||
when(backupOfferingDetailsDao.findDomainIds(2L)).thenReturn(List.of(4L));
|
||||
|
||||
when(domainDao.isChildDomain(parentDomainId, childDomainId)).thenReturn(true);
|
||||
when(domainDao.isChildDomain(4L, childDomainId)).thenReturn(false);
|
||||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
when(account.getType()).thenReturn(Account.Type.NORMAL);
|
||||
|
||||
try (MockedStatic<CallContext> mockedCallContext = Mockito.mockStatic(CallContext.class)) {
|
||||
CallContext contextMock = Mockito.mock(CallContext.class);
|
||||
mockedCallContext.when(CallContext::current).thenReturn(contextMock);
|
||||
when(contextMock.getCallingAccount()).thenReturn(account);
|
||||
|
||||
Pair<List<BackupOffering>, Integer> result = backupManager.listBackupOfferings(cmd);
|
||||
|
||||
assertEquals(1, result.first().size());
|
||||
assertEquals("Parent Domain Offering", result.first().get(0).getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListBackupOfferingsWithDomainFilteringExcludesSiblingDomainOfferings() {
|
||||
Long requestedDomainId = 3L;
|
||||
Long siblingDomainId = 4L;
|
||||
|
||||
ListBackupOfferingsCmd cmd =
|
||||
Mockito.mock(ListBackupOfferingsCmd.class);
|
||||
when(cmd.getOfferingId()).thenReturn(null);
|
||||
when(cmd.getDomainId()).thenReturn(requestedDomainId);
|
||||
when(cmd.getStartIndex()).thenReturn(0L);
|
||||
when(cmd.getPageSizeVal()).thenReturn(20L);
|
||||
|
||||
BackupOfferingVO siblingOffering = createMockOffering(1L, "Sibling Domain Offering");
|
||||
List<BackupOfferingVO> allOfferings = List.of(siblingOffering);
|
||||
|
||||
SearchBuilder<BackupOfferingVO> sb = Mockito.mock(SearchBuilder.class);
|
||||
SearchCriteria<BackupOfferingVO> sc = Mockito.mock(SearchCriteria.class);
|
||||
BackupOfferingVO entityMock = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.createSearchBuilder()).thenReturn(sb);
|
||||
when(sb.entity()).thenReturn(entityMock);
|
||||
when(sb.and(Mockito.anyString(), Mockito.any(), Mockito.any(SearchCriteria.Op.class))).thenReturn(sb);
|
||||
when(sb.create()).thenReturn(sc);
|
||||
when(backupOfferingDao.searchAndCount(Mockito.any(), Mockito.any()))
|
||||
.thenReturn(new Pair<>(allOfferings, allOfferings.size()));
|
||||
|
||||
when(backupOfferingDetailsDao.findDomainIds(1L)).thenReturn(List.of(siblingDomainId));
|
||||
when(domainDao.isChildDomain(siblingDomainId, requestedDomainId)).thenReturn(false);
|
||||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
when(account.getType()).thenReturn(Account.Type.NORMAL);
|
||||
|
||||
try (MockedStatic<CallContext> mockedCallContext = Mockito.mockStatic(CallContext.class)) {
|
||||
CallContext contextMock = Mockito.mock(CallContext.class);
|
||||
mockedCallContext.when(CallContext::current).thenReturn(contextMock);
|
||||
when(contextMock.getCallingAccount()).thenReturn(account);
|
||||
|
||||
Pair<List<BackupOffering>, Integer> result = backupManager.listBackupOfferings(cmd);
|
||||
|
||||
assertEquals(0, result.first().size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListBackupOfferingsWithDomainFilteringMultipleDomainMappings() {
|
||||
Long requestedDomainId = 5L;
|
||||
Long parentDomainId1 = 1L;
|
||||
Long parentDomainId2 = 2L;
|
||||
Long unrelatedDomainId = 8L;
|
||||
|
||||
ListBackupOfferingsCmd cmd =
|
||||
Mockito.mock(ListBackupOfferingsCmd.class);
|
||||
when(cmd.getOfferingId()).thenReturn(null);
|
||||
when(cmd.getDomainId()).thenReturn(requestedDomainId);
|
||||
when(cmd.getStartIndex()).thenReturn(0L);
|
||||
when(cmd.getPageSizeVal()).thenReturn(20L);
|
||||
|
||||
BackupOfferingVO multiDomainOffering = createMockOffering(1L, "Multi-Domain Offering");
|
||||
List<BackupOfferingVO> allOfferings = List.of(multiDomainOffering);
|
||||
|
||||
SearchBuilder<BackupOfferingVO> sb = Mockito.mock(SearchBuilder.class);
|
||||
SearchCriteria<BackupOfferingVO> sc = Mockito.mock(SearchCriteria.class);
|
||||
BackupOfferingVO entityMock = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.createSearchBuilder()).thenReturn(sb);
|
||||
when(sb.entity()).thenReturn(entityMock);
|
||||
when(sb.and(Mockito.anyString(), Mockito.any(), Mockito.any(SearchCriteria.Op.class))).thenReturn(sb);
|
||||
when(sb.create()).thenReturn(sc);
|
||||
when(backupOfferingDao.searchAndCount(Mockito.any(), Mockito.any()))
|
||||
.thenReturn(new Pair<>(allOfferings, allOfferings.size()));
|
||||
|
||||
when(backupOfferingDetailsDao.findDomainIds(1L))
|
||||
.thenReturn(List.of(parentDomainId1, unrelatedDomainId, parentDomainId2));
|
||||
|
||||
when(domainDao.isChildDomain(parentDomainId1, requestedDomainId)).thenReturn(false);
|
||||
when(domainDao.isChildDomain(unrelatedDomainId, requestedDomainId)).thenReturn(false);
|
||||
when(domainDao.isChildDomain(parentDomainId2, requestedDomainId)).thenReturn(true);
|
||||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
when(account.getType()).thenReturn(Account.Type.NORMAL);
|
||||
|
||||
try (MockedStatic<CallContext> mockedCallContext = Mockito.mockStatic(CallContext.class)) {
|
||||
CallContext contextMock = Mockito.mock(CallContext.class);
|
||||
mockedCallContext.when(CallContext::current).thenReturn(contextMock);
|
||||
when(contextMock.getCallingAccount()).thenReturn(account);
|
||||
|
||||
Pair<List<BackupOffering>, Integer> result = backupManager.listBackupOfferings(cmd);
|
||||
|
||||
assertEquals(1, result.first().size());
|
||||
assertEquals("Multi-Domain Offering", result.first().get(0).getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListBackupOfferingsNormalUserDefaultsToDomainFiltering() {
|
||||
Long userDomainId = 7L;
|
||||
|
||||
ListBackupOfferingsCmd cmd =
|
||||
Mockito.mock(ListBackupOfferingsCmd.class);
|
||||
when(cmd.getOfferingId()).thenReturn(null);
|
||||
when(cmd.getDomainId()).thenReturn(null); // User didn't pass domain filter
|
||||
when(cmd.getStartIndex()).thenReturn(0L);
|
||||
when(cmd.getPageSizeVal()).thenReturn(20L);
|
||||
|
||||
BackupOfferingVO globalOffering = createMockOffering(1L, "Global Offering");
|
||||
BackupOfferingVO userDomainOffering = createMockOffering(2L, "User Domain Offering");
|
||||
BackupOfferingVO otherDomainOffering = createMockOffering(3L, "Other Domain Offering");
|
||||
|
||||
List<BackupOfferingVO> allOfferings = List.of(globalOffering, userDomainOffering, otherDomainOffering);
|
||||
|
||||
SearchBuilder<BackupOfferingVO> sb = Mockito.mock(SearchBuilder.class);
|
||||
SearchCriteria<BackupOfferingVO> sc = Mockito.mock(SearchCriteria.class);
|
||||
BackupOfferingVO entityMock = Mockito.mock(BackupOfferingVO.class);
|
||||
when(backupOfferingDao.createSearchBuilder()).thenReturn(sb);
|
||||
when(sb.entity()).thenReturn(entityMock);
|
||||
when(sb.and(Mockito.anyString(), Mockito.any(), Mockito.any(SearchCriteria.Op.class))).thenReturn(sb);
|
||||
when(sb.create()).thenReturn(sc);
|
||||
when(backupOfferingDao.searchAndCount(Mockito.any(), Mockito.any()))
|
||||
.thenReturn(new Pair<>(allOfferings, allOfferings.size()));
|
||||
|
||||
when(backupOfferingDetailsDao.findDomainIds(1L)).thenReturn(Collections.emptyList()); // Global
|
||||
when(backupOfferingDetailsDao.findDomainIds(2L)).thenReturn(List.of(userDomainId)); // User's domain
|
||||
when(backupOfferingDetailsDao.findDomainIds(3L)).thenReturn(List.of(99L)); // Other domain
|
||||
|
||||
when(domainDao.isChildDomain(99L, userDomainId)).thenReturn(false);
|
||||
|
||||
Account account = Mockito.mock(Account.class);
|
||||
when(account.getType()).thenReturn(Account.Type.NORMAL);
|
||||
when(account.getDomainId()).thenReturn(userDomainId);
|
||||
|
||||
try (MockedStatic<CallContext> mockedCallContext = Mockito.mockStatic(CallContext.class)) {
|
||||
CallContext contextMock = Mockito.mock(CallContext.class);
|
||||
mockedCallContext.when(CallContext::current).thenReturn(contextMock);
|
||||
when(contextMock.getCallingAccount()).thenReturn(account);
|
||||
|
||||
Pair<List<BackupOffering>, Integer> result = backupManager.listBackupOfferings(cmd);
|
||||
|
||||
assertEquals(2, result.first().size());
|
||||
assertTrue(result.first().stream().anyMatch(o -> o.getName().equals("Global Offering")));
|
||||
assertTrue(result.first().stream().anyMatch(o -> o.getName().equals("User Domain Offering")));
|
||||
}
|
||||
}
|
||||
|
||||
private BackupOfferingVO createMockOffering(Long id, String name) {
|
||||
BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
|
||||
when(offering.getId()).thenReturn(id);
|
||||
when(offering.getName()).thenReturn(name);
|
||||
return offering;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue