This commit is contained in:
vishesh92 2026-05-08 13:42:30 +05:30
parent 7fd6b6f994
commit f909d494a0
No known key found for this signature in database
GPG Key ID: 4E395186CBFA790B
30 changed files with 226 additions and 308 deletions

View File

@ -16,23 +16,21 @@
// under the License.
package org.apache.cloudstack.api.command.user.schedule;
import java.util.Date;
import java.util.Map;
import javax.inject.Inject;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.commons.lang3.EnumUtils;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.TaggedResources;
import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
import org.apache.commons.lang3.EnumUtils;
import javax.inject.Inject;
import java.util.Date;
import java.util.Map;
@APICommand(name = "createResourceSchedule", description = "Create Resource Schedule", responseObject = ResourceScheduleResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.23.0",
@ -72,8 +70,12 @@ public class CreateResourceScheduleCmd extends BaseCmd {
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, required = false, description = "Map of (key/value pairs) details for the schedule.")
private Map details;
public String getResourceType() {
return resourceType;
public ApiCommandResourceType getResourceType() {
ApiCommandResourceType type = EnumUtils.getEnumIgnoreCase(ApiCommandResourceType.class, resourceType);
if (type == null) {
throw new InvalidParameterValueException("Unknown resource type: " + resourceType);
}
return type;
}
public String getResourceId() {
@ -112,20 +114,12 @@ public class CreateResourceScheduleCmd extends BaseCmd {
}
public Map<String, String> getDetails() {
Map<String, String> detailsMap = null;
if (details != null && !details.isEmpty()) {
detailsMap = TaggedResources.parseKeyValueMap(details, true);
}
return detailsMap;
return convertDetailsToMap(details);
}
@Override
public void execute() {
ApiCommandResourceType type = EnumUtils.getEnumIgnoreCase(ApiCommandResourceType.class, getResourceType());
if (type == null) {
throw new InvalidParameterValueException("Unknown resource type: " + getResourceType());
}
ResourceScheduleResponse response = resourceScheduleManager.createSchedule(type, getResourceId(),
ResourceScheduleResponse response = resourceScheduleManager.createSchedule(getResourceType(), getResourceId(),
getDescription(), getSchedule(), getTimeZone(), getAction(), getStartDate(), getEndDate(), getEnabled(), getDetails());
response.setResponseName(getCommandName());
setResponseObject(response);

View File

@ -16,15 +16,10 @@
// under the License.
package org.apache.cloudstack.api.command.user.schedule;
import java.util.List;
import javax.inject.Inject;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.commons.lang3.EnumUtils;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
@ -32,6 +27,10 @@ import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
import org.apache.commons.lang3.EnumUtils;
import javax.inject.Inject;
import java.util.List;
@APICommand(name = "deleteResourceSchedule", description = "Delete Resource Schedule", responseObject = SuccessResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.23.0",
@ -53,8 +52,12 @@ public class DeleteResourceScheduleCmd extends BaseCmd {
@Parameter(name = ApiConstants.IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = ResourceScheduleResponse.class, required = false, description = "comma separated list of schedule ids to be deleted")
private List<Long> ids;
public String getResourceType() {
return resourceType;
public ApiCommandResourceType getResourceType() {
ApiCommandResourceType type = EnumUtils.getEnumIgnoreCase(ApiCommandResourceType.class, resourceType);
if (type == null) {
throw new InvalidParameterValueException("Unknown resource type: " + resourceType);
}
return type;
}
public String getResourceId() {
@ -71,11 +74,7 @@ public class DeleteResourceScheduleCmd extends BaseCmd {
@Override
public void execute() {
ApiCommandResourceType type = EnumUtils.getEnumIgnoreCase(ApiCommandResourceType.class, getResourceType());
if (type == null) {
throw new InvalidParameterValueException("Unknown resource type: " + getResourceType());
}
resourceScheduleManager.removeSchedule(type, getResourceId(), getId(), getIds());
resourceScheduleManager.removeSchedule(getResourceType(), getResourceId(), getId(), getIds());
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
}

View File

@ -16,21 +16,20 @@
// under the License.
package org.apache.cloudstack.api.command.user.schedule;
import java.util.List;
import javax.inject.Inject;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.commons.lang3.EnumUtils;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
import org.apache.commons.lang3.EnumUtils;
import javax.inject.Inject;
import java.util.List;
@APICommand(name = "listResourceSchedule", description = "List Resource Schedules", responseObject = ResourceScheduleResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.23.0",
@ -66,8 +65,12 @@ public class ListResourceScheduleCmd extends BaseListCmd {
return ids;
}
public String getResourceType() {
return resourceType;
public ApiCommandResourceType getResourceType() {
ApiCommandResourceType type = EnumUtils.getEnumIgnoreCase(ApiCommandResourceType.class, resourceType);
if (type == null) {
throw new InvalidParameterValueException("Unknown resource type: " + resourceType);
}
return type;
}
public String getResourceId() {
@ -84,14 +87,10 @@ public class ListResourceScheduleCmd extends BaseListCmd {
@Override
public void execute() {
ApiCommandResourceType type = null;
if (getResourceType() != null) {
type = EnumUtils.getEnumIgnoreCase(ApiCommandResourceType.class, getResourceType());
if (type == null) {
throw new InvalidParameterValueException("Unknown resource type: " + getResourceType());
}
}
ListResponse<ResourceScheduleResponse> response = resourceScheduleManager.listSchedule(getId(), getIds(), type, getResourceId(), getAction(), getEnabled(), getStartIndex(), getPageSizeVal());
ListResponse<ResourceScheduleResponse> response = resourceScheduleManager.listSchedule(
getId(), getIds(), getResourceType(), getResourceId(), getAction(), getEnabled(),
getStartIndex(), getPageSizeVal()
);
response.setResponseName(getCommandName());
setResponseObject(response);
}

View File

@ -16,21 +16,19 @@
// under the License.
package org.apache.cloudstack.api.command.user.schedule;
import java.util.Date;
import java.util.Map;
import javax.inject.Inject;
import org.apache.cloudstack.acl.RoleType;
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.TaggedResources;
import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
import javax.inject.Inject;
import java.util.Date;
import java.util.Map;
@APICommand(name = "updateResourceSchedule", description = "Update Resource Schedule", responseObject = ResourceScheduleResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.23.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
@ -92,11 +90,7 @@ public class UpdateResourceScheduleCmd extends BaseCmd {
}
public Map<String, String> getDetails() {
Map<String, String> detailsMap = null;
if (details != null && !details.isEmpty()) {
detailsMap = TaggedResources.parseKeyValueMap(details, true);
}
return detailsMap;
return convertDetailsToMap(details);
}
@Override

View File

@ -22,6 +22,7 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
@ -29,9 +30,6 @@ import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VMScheduleResponse;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
import org.apache.cloudstack.schedule.vm.VMScheduleAction;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.commons.lang3.EnumUtils;
import javax.inject.Inject;
import java.util.Date;
@ -95,9 +93,9 @@ public class CreateVMScheduleCmd extends BaseCmd {
description = "Enable Instance schedule. Defaults to true")
private Boolean enabled;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
/// //////////////////////////////////////////////////
/// //////////////// Accessors ///////////////////////
/// //////////////////////////////////////////////////
public Long getVmId() {
return vmId;
@ -134,26 +132,17 @@ public class CreateVMScheduleCmd extends BaseCmd {
return enabled;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
/// //////////////////////////////////////////////////
/// //////////// API Implementation///////////////////
/// //////////////////////////////////////////////////
@Override
public void execute() {
String actionStr = null;
if (getAction() != null) {
VMScheduleAction vmAction = EnumUtils.getEnumIgnoreCase(VMScheduleAction.class, getAction());
if (vmAction == null) {
throw new InvalidParameterValueException(String.format("Invalid value for action: %s", getAction()));
}
actionStr = vmAction.name();
}
String resourceIdStr = getVmId() != null ? String.valueOf(getVmId()) : null;
ResourceScheduleResponse scheduleResponse = resourceScheduleManager.createSchedule(
ApiCommandResourceType.VirtualMachine,
resourceIdStr, getDescription(), getSchedule(), getTimeZone(), actionStr,
resourceIdStr, getDescription(), getSchedule(), getTimeZone(), getAction(),
getStartDate(), getEndDate(), getEnabled(), null);
VMScheduleResponse response = new VMScheduleResponse(scheduleResponse);
response.setResponseName(getCommandName());

View File

@ -22,6 +22,7 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
@ -31,7 +32,6 @@ import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VMScheduleResponse;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
import org.apache.cloudstack.api.ApiCommandResourceType;
import javax.inject.Inject;
import java.util.Collections;
@ -50,12 +50,14 @@ public class DeleteVMScheduleCmd extends BaseCmd {
required = true,
description = "ID of Instance")
private Long vmId;
@Parameter(name = ApiConstants.ID,
type = CommandType.UUID,
entityType = VMScheduleResponse.class,
required = false,
description = "ID of Instance schedule")
private Long id;
@Parameter(name = ApiConstants.IDS,
type = CommandType.LIST,
collectionType = CommandType.UUID,
@ -64,9 +66,9 @@ public class DeleteVMScheduleCmd extends BaseCmd {
description = "IDs of Instance schedule")
private List<Long> ids;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
/// //////////////////////////////////////////////////
/// //////////////// Accessors ///////////////////////
/// //////////////////////////////////////////////////
public Long getId() {
return id;
@ -83,9 +85,9 @@ public class DeleteVMScheduleCmd extends BaseCmd {
return vmId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
/// //////////////////////////////////////////////////
/// //////////// API Implementation///////////////////
/// //////////////////////////////////////////////////
@Override
public void execute() {

View File

@ -20,6 +20,7 @@ package org.apache.cloudstack.api.command.user.vm;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
@ -28,10 +29,6 @@ import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VMScheduleResponse;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
import org.apache.cloudstack.schedule.vm.VMScheduleAction;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.commons.lang3.EnumUtils;
import com.cloud.exception.InvalidParameterValueException;
import javax.inject.Inject;
import java.util.ArrayList;
@ -70,9 +67,9 @@ public class ListVMScheduleCmd extends BaseListCmd {
description = "ID of Instance schedule")
private Boolean enabled;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
/// //////////////////////////////////////////////////
/// //////////////// Accessors ///////////////////////
/// //////////////////////////////////////////////////
public Long getVmId() {
return vmId;
@ -90,24 +87,18 @@ public class ListVMScheduleCmd extends BaseListCmd {
return enabled;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
/// //////////////////////////////////////////////////
/// //////////// API Implementation///////////////////
/// //////////////////////////////////////////////////
@Override
public void execute() {
String actionStr = null;
if (getAction() != null) {
VMScheduleAction vmAction = EnumUtils.getEnumIgnoreCase(VMScheduleAction.class, getAction());
if (vmAction == null) {
throw new InvalidParameterValueException("Invalid value for action: " + getAction());
}
actionStr = vmAction.name();
}
String resourceIdStr = getVmId() != null ? String.valueOf(getVmId()) : null;
ListResponse<ResourceScheduleResponse> scheduleResponse = resourceScheduleManager.listSchedule(
getId(), null, ApiCommandResourceType.VirtualMachine, resourceIdStr, actionStr, getEnabled(), getStartIndex(), getPageSizeVal());
getId(), null, ApiCommandResourceType.VirtualMachine, resourceIdStr, getAction(), getEnabled(),
getStartIndex(), getPageSizeVal()
);
List<VMScheduleResponse> vmScheduleResponses = new ArrayList<>();
for (ResourceScheduleResponse resourceScheduleResponse : scheduleResponse.getResponses()) {
vmScheduleResponses.add(new VMScheduleResponse(resourceScheduleResponse));

View File

@ -22,12 +22,12 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.api.response.VMScheduleResponse;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.schedule.ResourceSchedule;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
@ -86,9 +86,9 @@ public class UpdateVMScheduleCmd extends BaseCmd {
description = "Enable Instance schedule")
private Boolean enabled;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
/// //////////////////////////////////////////////////
/// //////////////// Accessors ///////////////////////
/// //////////////////////////////////////////////////
public Long getId() {
return id;
@ -118,9 +118,9 @@ public class UpdateVMScheduleCmd extends BaseCmd {
return enabled;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
/// //////////////////////////////////////////////////
/// //////////// API Implementation///////////////////
/// //////////////////////////////////////////////////
@Override
public void execute() {
@ -138,6 +138,9 @@ public class UpdateVMScheduleCmd extends BaseCmd {
throw new InvalidParameterValueException(String.format("Unable to find VM schedule by id=%d", getId()));
}
VirtualMachine vm = _entityMgr.findById(VirtualMachine.class, schedule.getResourceId());
if (vm == null) {
throw new InvalidParameterValueException(String.format("Unable to find VM schedule by id=%d", getId()));
}
return vm.getAccountId();
}
}

View File

@ -119,5 +119,7 @@ public class VMScheduleResponse extends BaseResponse {
this.endDate = endDate;
}
public void setCreated(Date created) { this.created = created; }
public void setCreated(Date created) {
this.created = created;
}
}

View File

@ -33,10 +33,8 @@ public interface ResourceSchedule extends Identity, InternalIdentity {
* and {@link #getEventType()} without knowing the concrete type.
*/
interface Action {
/** Enum constant name (START, STOP, SCALE_UP, …). */
String name();
/** CloudStack event type string used for audit / quota attribution. */
String getEventType();
}
@ -50,7 +48,6 @@ public interface ResourceSchedule extends Identity, InternalIdentity {
String getTimeZone();
/** Returns the raw action name stored in the DB (e.g. "START", "SCALE_UP"). */
String getActionName();
boolean getEnabled();

View File

@ -18,26 +18,26 @@
*/
package org.apache.cloudstack.schedule;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.ResourceScheduleResponse;
public interface ResourceScheduleManager {
ResourceScheduleResponse createSchedule(ApiCommandResourceType resourceType, String resourceUuid, String description,
String schedule, String timeZone, String action, Date startDate, Date endDate,
boolean enabled, Map<String, String> details);
ResourceScheduleResponse createSchedule(ApiCommandResourceType resourceType, String resourceUuid,
String description, String schedule, String timeZone, String action,
Date startDate, Date endDate, boolean enabled, Map<String, String> details);
ResourceScheduleResponse updateSchedule(Long id, String description, String schedule,
String timeZone, Date startDate, Date endDate, Boolean enabled, Map<String, String> details);
ResourceScheduleResponse updateSchedule(Long id, String description, String schedule, String timeZone,
Date startDate, Date endDate, Boolean enabled, Map<String, String> details);
ListResponse<ResourceScheduleResponse> listSchedule(Long id, List<Long> ids, ApiCommandResourceType resourceType,
String resourceUuid, String action, Boolean enabled, Long startIndex, Long pageSize);
String resourceUuid, String action, Boolean enabled,
Long startIndex, Long pageSize);
Long removeSchedule(ApiCommandResourceType resourceType, String resourceUuid, Long id, List<Long> ids);

View File

@ -36,8 +36,10 @@ import org.mockito.MockitoAnnotations;
public class CreateVMScheduleCmdTest {
@Mock
public ResourceScheduleManager resourceScheduleManager;
@Mock
public EntityManager entityManager;
@InjectMocks
private CreateVMScheduleCmd createVMScheduleCmd = new CreateVMScheduleCmd();

View File

@ -36,6 +36,7 @@ import org.mockito.MockitoAnnotations;
public class DeleteVMScheduleCmdTest {
@Mock
public ResourceScheduleManager resourceScheduleManager;
@Mock
public EntityManager entityManager;

View File

@ -38,6 +38,7 @@ import java.util.Collections;
public class ListVMScheduleCmdTest {
@Mock
public ResourceScheduleManager resourceScheduleManager;
@InjectMocks
private ListVMScheduleCmd listVMScheduleCmd = new ListVMScheduleCmd();
private AutoCloseable closeable;

View File

@ -21,9 +21,9 @@ package org.apache.cloudstack.api.command.user.vm;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.utils.db.EntityManager;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.api.response.VMScheduleResponse;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.schedule.ResourceSchedule;
import org.apache.cloudstack.schedule.ResourceScheduleManager;
import org.junit.After;
@ -38,8 +38,10 @@ import org.mockito.MockitoAnnotations;
public class UpdateVMScheduleCmdTest {
@Mock
public ResourceScheduleManager resourceScheduleManager;
@Mock
public EntityManager entityManager;
@InjectMocks
private UpdateVMScheduleCmd updateVMScheduleCmd = new UpdateVMScheduleCmd();

View File

@ -16,6 +16,8 @@
// under the License.
package org.apache.cloudstack.schedule;
import org.apache.cloudstack.api.ResourceDetail;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
@ -23,8 +25,6 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.apache.cloudstack.api.ResourceDetail;
@Entity
@Table(name = "resource_schedule_details")
public class ResourceScheduleDetailVO implements ResourceDetail {

View File

@ -89,7 +89,7 @@ public class ResourceScheduleVO implements ResourceSchedule {
}
public ResourceScheduleVO(ApiCommandResourceType resourceType, long resourceId, String description, String schedule,
String timeZone, String action, Date startDate, Date endDate, boolean enabled) {
String timeZone, String action, Date startDate, Date endDate, boolean enabled) {
uuid = UUID.randomUUID().toString();
this.resourceType = resourceType;
this.resourceId = resourceId;

View File

@ -34,7 +34,7 @@ public interface ResourceScheduleDao extends GenericDao<ResourceScheduleVO, Long
long removeAllSchedulesForResource(ApiCommandResourceType resourceType, long resourceId);
Pair<List<ResourceScheduleVO>, Integer> searchAndCount(List<Long> ids, ApiCommandResourceType resourceType, Long resourceId,
String action, Boolean enabled, Long offset, Long limit);
String action, Boolean enabled, Long offset, Long limit);
SearchCriteria<ResourceScheduleVO> getSearchCriteriaForResource(ApiCommandResourceType resourceType, long resourceId);
}

View File

@ -26,6 +26,7 @@ import com.cloud.utils.db.SearchCriteria;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.schedule.ResourceScheduleVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import java.util.Date;
@ -35,9 +36,7 @@ import java.util.List;
public class ResourceScheduleDaoImpl extends GenericDaoBase<ResourceScheduleVO, Long> implements ResourceScheduleDao {
private final SearchBuilder<ResourceScheduleVO> activeScheduleSearch;
private final SearchBuilder<ResourceScheduleVO> scheduleSearchByResourceAndIds;
private final SearchBuilder<ResourceScheduleVO> scheduleSearchByResource;
private final SearchBuilder<ResourceScheduleVO> scheduleSearch;
private final SearchBuilder<ResourceScheduleVO> allSearch;
static final String RESOURCE_TYPE = "resourceType";
static final String RESOURCE_ID = "resourceId";
@ -53,24 +52,13 @@ public class ResourceScheduleDaoImpl extends GenericDaoBase<ResourceScheduleVO,
activeScheduleSearch.cp();
activeScheduleSearch.done();
scheduleSearchByResourceAndIds = createSearchBuilder();
scheduleSearchByResourceAndIds.and(ApiConstants.ID, scheduleSearchByResourceAndIds.entity().getId(), SearchCriteria.Op.IN);
scheduleSearchByResourceAndIds.and(RESOURCE_TYPE, scheduleSearchByResourceAndIds.entity().getResourceType(), SearchCriteria.Op.EQ);
scheduleSearchByResourceAndIds.and(RESOURCE_ID, scheduleSearchByResourceAndIds.entity().getResourceId(), SearchCriteria.Op.EQ);
scheduleSearchByResourceAndIds.done();
scheduleSearchByResource = createSearchBuilder();
scheduleSearchByResource.and(RESOURCE_TYPE, scheduleSearchByResource.entity().getResourceType(), SearchCriteria.Op.EQ);
scheduleSearchByResource.and(RESOURCE_ID, scheduleSearchByResource.entity().getResourceId(), SearchCriteria.Op.EQ);
scheduleSearchByResource.done();
scheduleSearch = createSearchBuilder();
scheduleSearch.and(ApiConstants.ID, scheduleSearch.entity().getId(), SearchCriteria.Op.IN);
scheduleSearch.and(RESOURCE_TYPE, scheduleSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
scheduleSearch.and(RESOURCE_ID, scheduleSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
scheduleSearch.and(ApiConstants.ACTION, scheduleSearch.entity().getActionName(), SearchCriteria.Op.EQ);
scheduleSearch.and(ApiConstants.ENABLED, scheduleSearch.entity().getEnabled(), SearchCriteria.Op.EQ);
scheduleSearch.done();
allSearch = createSearchBuilder();
allSearch.and(ApiConstants.ID, allSearch.entity().getId(), SearchCriteria.Op.IN);
allSearch.and(RESOURCE_TYPE, allSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
allSearch.and(RESOURCE_ID, allSearch.entity().getResourceId(), SearchCriteria.Op.EQ);
allSearch.and(ApiConstants.ACTION, allSearch.entity().getActionName(), SearchCriteria.Op.EQ);
allSearch.and(ApiConstants.ENABLED, allSearch.entity().getEnabled(), SearchCriteria.Op.EQ);
allSearch.done();
}
@Override
@ -84,8 +72,10 @@ public class ResourceScheduleDaoImpl extends GenericDaoBase<ResourceScheduleVO,
@Override
public long removeSchedulesForResourceAndIds(ApiCommandResourceType resourceType, long resourceId, List<Long> ids) {
SearchCriteria<ResourceScheduleVO> sc = scheduleSearchByResourceAndIds.create();
sc.setParameters(ApiConstants.ID, ids.toArray());
SearchCriteria<ResourceScheduleVO> sc = allSearch.create();
if (CollectionUtils.isNotEmpty(ids)) {
sc.setParameters(ApiConstants.ID, ids.toArray());
}
sc.setParameters(RESOURCE_TYPE, resourceType);
sc.setParameters(RESOURCE_ID, resourceId);
return remove(sc);
@ -93,7 +83,7 @@ public class ResourceScheduleDaoImpl extends GenericDaoBase<ResourceScheduleVO,
@Override
public long removeAllSchedulesForResource(ApiCommandResourceType resourceType, long resourceId) {
SearchCriteria<ResourceScheduleVO> sc = scheduleSearchByResource.create();
SearchCriteria<ResourceScheduleVO> sc = allSearch.create();
sc.setParameters(RESOURCE_TYPE, resourceType);
sc.setParameters(RESOURCE_ID, resourceId);
return remove(sc);
@ -101,9 +91,9 @@ public class ResourceScheduleDaoImpl extends GenericDaoBase<ResourceScheduleVO,
@Override
public Pair<List<ResourceScheduleVO>, Integer> searchAndCount(List<Long> ids, ApiCommandResourceType resourceType, Long resourceId,
String action, Boolean enabled, Long offset, Long limit) {
SearchCriteria<ResourceScheduleVO> sc = scheduleSearch.create();
if (ids != null && !ids.isEmpty()) {
String action, Boolean enabled, Long offset, Long limit) {
SearchCriteria<ResourceScheduleVO> sc = allSearch.create();
if (CollectionUtils.isNotEmpty(ids)) {
sc.setParameters(ApiConstants.ID, ids.toArray());
}
sc.setParametersIfNotNull(ApiConstants.ENABLED, enabled);
@ -116,7 +106,7 @@ public class ResourceScheduleDaoImpl extends GenericDaoBase<ResourceScheduleVO,
@Override
public SearchCriteria<ResourceScheduleVO> getSearchCriteriaForResource(ApiCommandResourceType resourceType, long resourceId) {
SearchCriteria<ResourceScheduleVO> sc = scheduleSearchByResource.create();
SearchCriteria<ResourceScheduleVO> sc = allSearch.create();
sc.setParameters(RESOURCE_TYPE, resourceType);
sc.setParameters(RESOURCE_ID, resourceId);
return sc;

View File

@ -16,10 +16,9 @@
// under the License.
package org.apache.cloudstack.schedule.dao;
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.resourcedetail.ResourceDetailsDao;
import org.apache.cloudstack.schedule.ResourceScheduleDetailVO;
import com.cloud.utils.db.GenericDao;
public interface ResourceScheduleDetailsDao extends GenericDao<ResourceScheduleDetailVO, Long>, ResourceDetailsDao<ResourceScheduleDetailVO> {
}

View File

@ -39,8 +39,8 @@ public class ResourceScheduledJobDaoImpl extends GenericDaoBase<ResourceSchedule
private final SearchBuilder<ResourceScheduledJobVO> expungeJobForScheduleSearch;
private final SearchBuilder<ResourceScheduledJobVO> scheduleAndTimestampSearch;
static final String SCHEDULED_TIMESTAMP = "scheduled_timestamp";
static final String SCHEDULE_ID = "schedule_id";
static final String SCHEDULED_TIMESTAMP = "scheduledTimestamp";
static final String SCHEDULE_ID = "scheduleId";
static final String RESOURCE_TYPE = "resourceType";
public ResourceScheduledJobDaoImpl() {

View File

@ -1,28 +0,0 @@
/*
* 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.vm.schedule.dao;
import org.apache.cloudstack.schedule.dao.ResourceScheduleDao;
/**
* @deprecated Use {@link ResourceScheduleDao} directly.
*/
@Deprecated
public interface VMScheduleDao extends ResourceScheduleDao {
}

View File

@ -1,28 +0,0 @@
/*
* 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.vm.schedule.dao;
import org.apache.cloudstack.schedule.dao.ResourceScheduledJobDao;
/**
* @deprecated Use {@link ResourceScheduledJobDao} directly.
*/
@Deprecated
public interface VMScheduledJobDao extends ResourceScheduledJobDao {
}

View File

@ -183,3 +183,6 @@ CREATE TABLE IF NOT EXISTS `cloud`.`resource_schedule_details` (
UPDATE `cloud`.`event` SET `type` = 'SCHEDULE.CREATE' WHERE `type` = 'VM.SCHEDULE.CREATE';
UPDATE `cloud`.`event` SET `type` = 'SCHEDULE.UPDATE' WHERE `type` = 'VM.SCHEDULE.UPDATE';
UPDATE `cloud`.`event` SET `type` = 'SCHEDULE.DELETE' WHERE `type` = 'VM.SCHEDULE.DELETE';
-- Step 5: Rename the global configuration key for the scheduler
UPDATE `cloud`.`configuration` SET name='scheduler.jobs.expire.interval' WHERE name='vmscheduler.jobs.expire.interval';

View File

@ -36,6 +36,7 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
import org.apache.cloudstack.schedule.dao.ResourceScheduleDao;
import org.apache.cloudstack.schedule.dao.ResourceScheduledJobDao;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.scheduling.support.CronExpression;
@ -66,8 +67,10 @@ public abstract class BaseScheduleWorker extends ManagerBase {
@Inject
protected ResourceScheduleDao resourceScheduleDao;
@Inject
protected ResourceScheduledJobDao resourceScheduledJobDao;
@Inject
protected AsyncJobManager asyncJobManager;
@ -83,10 +86,14 @@ public abstract class BaseScheduleWorker extends ManagerBase {
asyncJobDispatcher = dispatcher;
}
/** The API resource type this worker handles (e.g. {@code ApiCommandResourceType.VirtualMachine}). */
/**
* The API resource type this worker handles (e.g. {@code ApiCommandResourceType.VirtualMachine}).
*/
public abstract ApiCommandResourceType getApiResourceType();
/** Convenience method returning {@code getApiResourceType().name()} for use in DAO queries, locks, and logging. */
/**
* Convenience method returning {@code getApiResourceType().name()} for use in DAO queries, locks, and logging.
*/
protected final String getResourceTypeName() {
return getApiResourceType().name();
}
@ -258,7 +265,7 @@ public abstract class BaseScheduleWorker extends ManagerBase {
}
public void removeScheduledJobs(List<Long> scheduleIds) {
if (scheduleIds == null || scheduleIds.isEmpty()) {
if (CollectionUtils.isEmpty(scheduleIds)) {
return;
}
int removed = resourceScheduledJobDao.expungeJobsForSchedules(scheduleIds, new Date());
@ -312,7 +319,7 @@ public abstract class BaseScheduleWorker extends ManagerBase {
}
private void logSkippedJobs(Map<Long, ResourceScheduledJobVO> executed,
Map<Long, List<ResourceScheduledJobVO>> skipped) {
Map<Long, List<ResourceScheduledJobVO>> skipped) {
for (Map.Entry<Long, List<ResourceScheduledJobVO>> entry : skipped.entrySet()) {
long resourceId = entry.getKey();
ResourceScheduledJobVO running = executed.get(resourceId);
@ -333,16 +340,18 @@ public abstract class BaseScheduleWorker extends ManagerBase {
// Subclass helpers
// -------------------------------------------------------------------------
/** Returns true when the given resource ID is valid and eligible for scheduling. */
public abstract boolean isResourceValid(long resourceId);
/** Returns the account that owns the given resource (for ACL / event attribution). */
public abstract long getEntityOwnerId(long resourceId);
/** Parses an action string into the resource-type-specific typed action constant. Throws InvalidParameterValueException for unknown values. */
/**
* Parses an action string into the resource-type-specific typed action constant. Throws InvalidParameterValueException for unknown values.
*/
public abstract ResourceSchedule.Action parseAction(String action);
/** Validates action-specific detail parameters. Throws InvalidParameterValueException on failure. */
/**
* Validates action-specific detail parameters. Throws InvalidParameterValueException on failure.
*/
public abstract void validateDetails(ResourceSchedule.Action action, Map<String, String> details);
/**

View File

@ -16,19 +16,21 @@
// under the License.
package org.apache.cloudstack.schedule;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.api.query.MutualExclusiveIdsManagerBase;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.user.AccountManager;
import com.cloud.utils.DateUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.PluggableService;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
import org.apache.cloudstack.api.command.user.schedule.CreateResourceScheduleCmd;
import org.apache.cloudstack.api.command.user.schedule.DeleteResourceScheduleCmd;
import org.apache.cloudstack.api.command.user.schedule.ListResourceScheduleCmd;
@ -42,36 +44,36 @@ import org.apache.cloudstack.api.response.ResourceScheduleResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.schedule.dao.ResourceScheduleDetailsDao;
import org.apache.cloudstack.schedule.dao.ResourceScheduleDao;
import org.apache.cloudstack.schedule.dao.ResourceScheduleDetailsDao;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.support.CronExpression;
import com.cloud.api.query.MutualExclusiveIdsManagerBase;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.user.AccountManager;
import com.cloud.utils.DateUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.PluggableService;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.InternalIdentity;
import org.apache.cloudstack.api.Identity;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
import java.util.stream.Collectors;
public class ResourceScheduleManagerImpl extends MutualExclusiveIdsManagerBase implements ResourceScheduleManager, PluggableService, Configurable {
@Inject
private ResourceScheduleDao resourceScheduleDao;
@Inject
private ResourceScheduleDetailsDao resourceScheduleDetailsDao;
@Inject
private AccountManager accountManager;
@Inject
private EntityManager entityManager;
@ -120,7 +122,7 @@ public class ResourceScheduleManagerImpl extends MutualExclusiveIdsManagerBase i
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {
return new ConfigKey<?>[]{
BaseScheduleWorker.ScheduledJobExpireInterval
};
}
@ -254,33 +256,19 @@ public class ResourceScheduleManagerImpl extends MutualExclusiveIdsManagerBase i
public ListResponse<ResourceScheduleResponse> listSchedule(Long id, List<Long> ids, ApiCommandResourceType resourceType,
String resourceUuid, String action, Boolean enabled,
Long startIndex, Long pageSize) {
List<Long> scheduleIds = getIdsListFromCmd(id, ids);
if (!scheduleIds.isEmpty() && resourceType == null) {
throw new InvalidParameterValueException("resourcetype is required when filtering by id or ids");
Long internalResourceId = null;
BaseScheduleWorker worker = getWorker(resourceType);
if (StringUtils.isBlank(resourceUuid)) {
throw new InvalidParameterValueException("Resource ID must be specified");
} else {
internalResourceId = resolveResourceId(resourceUuid, worker.getApiResourceType().getAssociatedClass());
long ownerId = worker.getEntityOwnerId(internalResourceId);
accountManager.checkAccess(CallContext.current().getCallingAccount(), null, false, accountManager.getAccount(ownerId));
}
Long internalResourceId = null;
if (resourceType != null) {
BaseScheduleWorker worker = getWorker(resourceType);
if (StringUtils.isNotBlank(resourceUuid)) {
internalResourceId = resolveResourceId(resourceUuid, worker.getApiResourceType().getAssociatedClass());
long ownerId = worker.getEntityOwnerId(internalResourceId);
accountManager.checkAccess(CallContext.current().getCallingAccount(), null, false, accountManager.getAccount(ownerId));
}
for (Long schedId : scheduleIds) {
ResourceScheduleVO scheduleVO = resourceScheduleDao.findById(schedId);
if (scheduleVO == null) {
throw new InvalidParameterValueException("Schedule " + schedId + " not found");
}
if (!resourceType.equals(scheduleVO.getResourceType())) {
throw new InvalidParameterValueException("Schedule " + schedId + " is not of resource type " + resourceType);
}
long ownerId = worker.getEntityOwnerId(scheduleVO.getResourceId());
accountManager.checkAccess(CallContext.current().getCallingAccount(), null, false, accountManager.getAccount(ownerId));
}
if (action != null) {
action = worker.parseAction(action).name();
}
List<Long> scheduleIds = getIdsListFromCmd(id, ids);
if (action != null) {
action = worker.parseAction(action).name();
}
Pair<List<ResourceScheduleVO>, Integer> result = resourceScheduleDao.searchAndCount(
@ -442,22 +430,15 @@ public class ResourceScheduleManagerImpl extends MutualExclusiveIdsManagerBase i
accountManager.checkAccess(CallContext.current().getCallingAccount(), null, false, accountManager.getAccount(ownerId));
List<Long> ids = getIdsListFromCmd(id, idsList);
if (ids.isEmpty()) {
throw new InvalidParameterValueException("Either id or ids parameter must be specified");
}
Pair<List<ResourceScheduleVO>, Integer> result = resourceScheduleDao.searchAndCount(ids, resourceType, internalResourceId, null, null, null, null);
List<ResourceScheduleVO> schedulesToRemove = result.first();
List<Long> scheduleIdsToRemove = schedulesToRemove.stream().map(ResourceScheduleVO::getId).collect(Collectors.toList());
return Transaction.execute((TransactionCallback<Long>) status -> {
worker.removeScheduledJobs(ids);
for (Long schedId : ids) {
resourceScheduleDetailsDao.removeDetails(schedId);
}
worker.removeScheduledJobs(scheduleIdsToRemove);
CallContext.current().setEventResourceId(internalResourceId);
CallContext.current().setEventResourceType(worker.getApiResourceType());
return resourceScheduleDao.removeSchedulesForResourceAndIds(
resourceType, internalResourceId, ids);
return resourceScheduleDao.removeSchedulesForResourceAndIds(resourceType, internalResourceId, scheduleIdsToRemove);
});
}
}

View File

@ -63,16 +63,15 @@ public class VMScheduleWorker extends BaseScheduleWorker {
public VMScheduleAction parseAction(String actionName) {
VMScheduleAction action = EnumUtils.getEnumIgnoreCase(VMScheduleAction.class, actionName);
if (action == null) {
throw new InvalidParameterValueException("Invalid action for VirtualMachine schedule: " + actionName +
". Supported actions: " + Arrays.toString(VMScheduleAction.values()));
throw new InvalidParameterValueException(String.format(
"Invalid action for VirtualMachine schedule: %s. Supported actions: %s",
actionName, Arrays.toString(VMScheduleAction.values())));
}
return action;
}
@Override
public void validateDetails(ResourceSchedule.Action action, Map<String, String> details) {
// No special details required/validated for VM schedules right now.
}
public void validateDetails(ResourceSchedule.Action action, Map<String, String> details) {}
@Override
protected Long processJob(ResourceScheduledJobVO job) {
@ -88,7 +87,7 @@ public class VMScheduleWorker extends BaseScheduleWorker {
return null;
}
VMScheduleAction action = VMScheduleAction.valueOf(job.getActionName());
VMScheduleAction action = parseAction(job.getActionName());
final long eventId = ActionEventUtils.onCompletedActionEvent(
User.UID_SYSTEM, vm.getAccountId(), null,
action.getEventType(), true,
@ -97,11 +96,16 @@ public class VMScheduleWorker extends BaseScheduleWorker {
if (vm.getState() == VirtualMachine.State.Running) {
switch (action) {
case STOP: return submitStopVMJob(vm, false, eventId);
case FORCE_STOP: return submitStopVMJob(vm, true, eventId);
case REBOOT: return submitRebootVMJob(vm, false, eventId);
case FORCE_REBOOT: return submitRebootVMJob(vm, true, eventId);
default: break;
case STOP:
return submitStopVMJob(vm, false, eventId);
case FORCE_STOP:
return submitStopVMJob(vm, true, eventId);
case REBOOT:
return submitRebootVMJob(vm, false, eventId);
case FORCE_REBOOT:
return submitRebootVMJob(vm, true, eventId);
default:
break;
}
} else if (vm.getState() == VirtualMachine.State.Stopped && action == VMScheduleAction.START) {
return submitStartVMJob(vm, eventId);

View File

@ -260,6 +260,17 @@ public class ResourceScheduleManagerImplTest {
Mockito.when(resourceScheduleDao.removeSchedulesForResourceAndIds(
Mockito.any(), Mockito.anyLong(), Mockito.anyList())).thenReturn(1L);
ResourceScheduleVO schedule1 = Mockito.mock(ResourceScheduleVO.class);
ResourceScheduleVO schedule2 = Mockito.mock(ResourceScheduleVO.class);
List<ResourceScheduleVO> scheduleList = new ArrayList<>();
scheduleList.add(schedule1);
scheduleList.add(schedule2);
Mockito.when(resourceScheduleDao.searchAndCount(
Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(),
Mockito.any(), Mockito.any(), Mockito.any())
).thenReturn(new Pair<>(scheduleList, scheduleList.size()));
Long rowsRemoved = resourceScheduleManager.removeSchedule(
ApiCommandResourceType.VirtualMachine, "1", 10L, null);

View File

@ -89,9 +89,9 @@ public class VMScheduleWorkerTest {
closeable = MockitoAnnotations.openMocks(this);
actionEventUtilsMocked = Mockito.mockStatic(ActionEventUtils.class);
Mockito.when(ActionEventUtils.onScheduledActionEvent(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(),
Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyBoolean(),
Mockito.anyLong()))
.thenReturn(1L);
Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyBoolean(),
Mockito.anyLong()))
.thenReturn(1L);
Mockito.when(ActionEventUtils.onCompletedActionEvent(Mockito.anyLong(), Mockito.anyLong(), Mockito.any(),
Mockito.anyString(), Mockito.anyBoolean(),
Mockito.anyString(),

View File

@ -238,6 +238,7 @@ known_categories = {
'removeQuarantinedIp': 'IP Quarantine',
'Shutdown': 'Maintenance',
'Maintenance': 'Maintenance',
'ResourceSchedule': 'Resource Schedule',
'addObjectStoragePool': 'Object Store',
'listObjectStoragePools': 'Object Store',
'deleteObjectStoragePool': 'Object Store',