Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,7 @@ public class ApiConstants {
public static final String SCHEDULED = "scheduled";
public static final String SCHEDULED_DATE = "scheduleddate";
public static final String BACKUP_PROVIDER = "backupprovider";
public static final String MAX_SCHEDULES = "maxschedules";

/**
* This enum specifies IO Drivers, each option controls specific policies on I/O.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@APICommand(name = "importBackupOffering",
Expand Down Expand Up @@ -90,6 +92,11 @@ public class ImportBackupOfferingCmd extends BaseAsyncCmd {
since = "4.23.0")
private List<Long> domainIds;

@Parameter(name = ApiConstants.MAX_SCHEDULES, type = CommandType.MAP,
description = "Maximum number of schedules, values lower than 0 disable the limit. By default, all allowed schedule types have a limit of 1. Accepts a map of " +
"schedule type to maximum amount. Example: maxschedules[0].DAILY=2&maxschedules[0].WEEKLY=5. Please note that all values should be on the same index ('0').")
private Map maxSchedules;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -123,6 +130,13 @@ public List<Long> getDomainIds() {
return domainIds;
}

public Map<String, String> getMaxSchedules() {
if (MapUtils.isEmpty(maxSchedules)) {
return null;
}
return (Map<String, String>)maxSchedules.values().iterator().next();
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import org.apache.cloudstack.backup.BackupOffering;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import com.cloud.exception.InvalidParameterValueException;
Expand All @@ -40,6 +42,8 @@
import java.util.List;
import java.util.function.LongFunction;

import java.util.Map;

@APICommand(name = "updateBackupOffering", description = "Updates a backup offering.", responseObject = BackupOfferingResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.16.0")
public class UpdateBackupOfferingCmd extends BaseCmd implements DomainAndZoneIdResolver {
Expand Down Expand Up @@ -69,6 +73,11 @@ public class UpdateBackupOfferingCmd extends BaseCmd implements DomainAndZoneIdR
length = 4096)
private String domainIds;

@Parameter(name = ApiConstants.MAX_SCHEDULES, type = CommandType.MAP,
description = "Maximum number of schedules, values lower than 0 disable the limit. By default, all allowed schedule types have a limit of 1. Accepts a map of " +
"schedule type to maximum amount. Example: maxschedules[0].DAILY=2&maxschedules[0].WEEKLY=5. Please note that all values should be on the same index ('0').")
private Map maxSchedules;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand All @@ -88,13 +97,20 @@ public Boolean getAllowUserDrivenBackups() {
return allowUserDrivenBackups;
}

public Map<String, String> getMaxSchedules() {
if (MapUtils.isEmpty(maxSchedules)) {
return null;
}
return (Map<String, String>)maxSchedules.values().iterator().next();
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public void execute() {
try {
if (StringUtils.isAllEmpty(getName(), getDescription()) && getAllowUserDrivenBackups() == null && CollectionUtils.isEmpty(getDomainIds())) {
if (StringUtils.isAllEmpty(getName(), getDescription()) && getAllowUserDrivenBackups() == null && CollectionUtils.isEmpty(getDomainIds()) && ObjectUtils.allNull(getAllowUserDrivenBackups(), getMaxSchedules())) {
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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@
import org.apache.cloudstack.backup.Backup;
import org.apache.cloudstack.backup.BackupManager;
import org.apache.cloudstack.backup.BackupOffering;

import org.apache.commons.collections4.MapUtils;

import javax.inject.Inject;
import java.util.List;
import java.util.Map;

@APICommand(name = "createBackupOffering", description = "Creates a backup offering", responseObject = BackupOfferingResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin}, since = "4.23.0")
Expand Down Expand Up @@ -92,6 +93,11 @@ public class CreateBackupOfferingCmd extends BaseCmd {
description = "Restrict the backup offering to the Domains identified by these IDs.")
private List<Long> domainIds;

@Parameter(name = ApiConstants.MAX_SCHEDULES, type = CommandType.MAP,
description = "Maximum number of schedules, values lower than 0 disable the limit. By default, all allowed schedule types have a limit of 1. Accepts a map of " +
"schedule type to maximum amount. Example: maxschedules[0].DAILY=2&maxschedules[0].WEEKLY=5. Please note that all values should be on the same index ('0').")
private Map maxSchedules;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -166,6 +172,13 @@ public Boolean getUserDrivenBackups() {
return userDrivenBackups;
}

public Map<String, String> getMaxSchedules() {
if (MapUtils.isEmpty(maxSchedules)) {
return null;
}
return (Map<String, String>)maxSchedules.values().iterator().next();
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
public class CreateBackupScheduleCmd extends BaseCmd {

@Inject
private BackupManager backupManager;
protected BackupManager backupManager;

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
Expand Down Expand Up @@ -92,7 +92,7 @@ public class CreateBackupScheduleCmd extends BaseCmd {
type = CommandType.BOOLEAN,
description = ApiConstants.PARAMETER_DESCRIPTION_ISOLATED_BACKUPS,
since = "4.23.0")
private boolean isolated;
private Boolean isolated;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
Expand All @@ -118,11 +118,11 @@ public Integer getMaxBackups() {
return maxBackups;
}

public Boolean getQuiesceVM() {
public Boolean isQuiesceVM() {
return quiesceVM;
}

public boolean isIsolated() {
public Boolean isIsolated() {
return isolated;
}

Expand Down Expand Up @@ -160,4 +160,17 @@ public Long getApiResourceId() {
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.VirtualMachine;
}

public CreateBackupScheduleCmd() {
}

public CreateBackupScheduleCmd(UpdateBackupScheduleCmd that) {
this.maxBackups = that.getMaxBackups();
this.schedule = that.getSchedule();
this.intervalType = that.intervalType;
this.quiesceVM = that.isQuiesceVm();
this.isolated = that.isIsolated();
this.vmId = that.getVmId();
this.timezone = that.getTimezone();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,144 @@

package org.apache.cloudstack.api.command.user.backup;

import com.cloud.utils.DateUtil;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.api.response.BackupScheduleResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.backup.BackupManager;
import org.apache.cloudstack.backup.BackupSchedule;
import org.apache.cloudstack.context.CallContext;

import javax.inject.Inject;

@APICommand(name = "updateBackupSchedule",
description = "Updates a User-defined Instance backup schedule",
responseObject = BackupResponse.class, since = "4.14.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class UpdateBackupScheduleCmd extends CreateBackupScheduleCmd {
public class UpdateBackupScheduleCmd extends BaseCmd {

@Inject
protected BackupManager backupManager;

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////

@Parameter(name = ApiConstants.ID,
type = CommandType.UUID,
entityType = BackupScheduleResponse.class,
required = false,
description = "ID of the schedule which should be updated. This parameter takes precedence over the virtualmachineid parameter.")
private Long id;

@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID,
type = CommandType.UUID,
entityType = UserVmResponse.class,
required = false,
description = "ID of the VM for which schedule is to be defined")
private Long vmId;

@Parameter(name = ApiConstants.INTERVAL_TYPE,
type = CommandType.STRING,
required = false,
description = "valid values are HOURLY, DAILY, WEEKLY, and MONTHLY")
protected String intervalType;

@Parameter(name = ApiConstants.SCHEDULE,
type = CommandType.STRING,
required = false,
description = "custom backup schedule, the format is:"
+ "for HOURLY MM*, for DAILY MM:HH*, for WEEKLY MM:HH:DD (1-7)*, for MONTHLY MM:HH:DD (1-28)")
private String schedule;

@Parameter(name = ApiConstants.TIMEZONE,
type = CommandType.STRING,
required = false,
description = "Specifies a timezone for this command. For more information on the timezone parameter, see TimeZone Format.")
private String timezone;

@Parameter(name = ApiConstants.VM_SNAPSHOT_QUIESCEVM,
type = CommandType.BOOLEAN,
description = "Whether the VM's file systems should be frozen for the scheduled backups. Currently only supported for the KNIB backup provider.")
private Boolean quiesceVm;

@Parameter(name = ApiConstants.MAX_BACKUPS, type = CommandType.INTEGER,
description = ApiConstants.PARAMETER_DESCRIPTION_MAX_BACKUPS, since = "4.24.0")
private Integer maxBackups;

@Parameter(name = ApiConstants.ISOLATED,
type = CommandType.BOOLEAN,
description = ApiConstants.PARAMETER_DESCRIPTION_ISOLATED_BACKUPS,
since = "4.24.0")
private Boolean isolated;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////

public Long getId() {
return id;
}

public Long getVmId() {
return vmId;
}

public DateUtil.IntervalType getIntervalType() {
return DateUtil.IntervalType.getIntervalType(intervalType);
}

public String getSchedule() {
return schedule;
}

public String getTimezone() {
return timezone;
}

public Boolean isQuiesceVm() {
return quiesceVm;
}

public Integer getMaxBackups() {
return maxBackups;
}

public Boolean isIsolated() {
return isolated;
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

@Override
public void execute() throws ServerApiException {
try {
BackupSchedule schedule = backupManager.configureBackupSchedule(this);

if (schedule != null) {
BackupScheduleResponse response = _responseGenerator.createBackupScheduleResponse(schedule);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new CloudRuntimeException("Error while updating backup schedule of VM.");
}
} catch (Exception e) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}

@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccount().getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
import org.apache.cloudstack.api.command.user.backup.ListBackupsCmd;
import org.apache.cloudstack.api.command.user.backup.CreateBackupOfferingCmd;
import org.apache.cloudstack.api.command.user.backup.UpdateBackupScheduleCmd;
import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
Expand Down Expand Up @@ -187,6 +188,13 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
*/
BackupSchedule configureBackupSchedule(CreateBackupScheduleCmd cmd);

/**
* Updates a VM backup schedule
* @param cmd
* @return the updated backup schedule
*/
BackupSchedule configureBackupSchedule(UpdateBackupScheduleCmd cmd);

/**
* Lists VM backup schedule for a VM
* @param vmId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public void setQuiesceVM(Boolean quiesceVM) {
}

public Boolean getQuiesceVM() {
return quiesceVM;
return this.quiesceVM;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
public interface BackupScheduleDao extends GenericDao<BackupScheduleVO, Long> {
List<BackupScheduleVO> listByVM(Long vmId);

BackupScheduleVO findByVMAndIntervalType(Long vmId, DateUtil.IntervalType intervalType);
List<BackupScheduleVO> listByVMAndIntervalType(Long vmId, DateUtil.IntervalType intervalType);

List<BackupScheduleVO> getSchedulesToExecute(Date currentTimestamp);
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ public List<BackupScheduleVO> listByVM(Long vmId) {
}

@Override
public BackupScheduleVO findByVMAndIntervalType(Long vmId, DateUtil.IntervalType intervalType) {
public List<BackupScheduleVO> listByVMAndIntervalType(Long vmId, DateUtil.IntervalType intervalType) {
SearchCriteria<BackupScheduleVO> sc = backupScheduleSearch.create();
sc.setParameters("vm_id", vmId);
sc.setParameters("interval_type", intervalType.ordinal());
return findOneBy(sc);
return listBy(sc);
}

@Override
Expand Down
Loading
Loading