Orchestrated VM Scheduler - #7289
Conversation
| RoleType[] authorized() default {}; | ||
|
|
||
| Class<?>[] entityType() default {}; | ||
|
|
There was a problem hiding this comment.
nit - unnecessary change, you may want to use git add -p to check what's being commited.
There was a problem hiding this comment.
nit - still see newline changes in APICommand
|
|
||
| --- Create table for Virtual Machine Schedule Entity | ||
|
|
||
| CREATE TABLE IF NOT EXISTS `cloud`.`vm_schedule` ( |
There was a problem hiding this comment.
note - after 4.18 is released, this would need to be moved to a new sql upgrade path (4.18->4.19)
There was a problem hiding this comment.
To move the DB update code to the 4.18 -> 4.19 update script, @rahulbcn27 !
|
@rahulbcn27 |
|
@rahulbcn27 |
|
This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch. |
Codecov Report
@@ Coverage Diff @@
## main #7289 +/- ##
============================================
- Coverage 12.68% 12.67% -0.02%
Complexity 8656 8656
============================================
Files 2718 2721 +3
Lines 256172 256534 +362
Branches 39926 39972 +46
============================================
Hits 32504 32504
- Misses 219534 219896 +362
Partials 4134 4134
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
|
@rahulbcn27, please, add a description to the PR explaining the proposal. |
| @Override | ||
| public String getCommandName() { | ||
| return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; | ||
| } |
There was a problem hiding this comment.
Since PR #7022, BaseCmd implements API name in lowercase + suffix 'response' as default behavior of method getCommandName; therefore, it is not necessary to override the method.
There was a problem hiding this comment.
will you remove this call, as @GutoVeronezi advises @rahulbcn27 ?
| requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, | ||
| authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) | ||
| public class CreateVMScheduleCmd extends BaseAsyncCreateCmd { | ||
| public static final String APINAME = "createVMSchedule"; |
There was a problem hiding this comment.
Following the behavior in other API classes, we can remove this property and hardcode the API name right in the APICommand annotation. The same applies to the other API commands being introduced.
There was a problem hiding this comment.
I haven't been following generic changes wrt API implementation if there's a new pattern we should use that. @GutoVeronezi if there's a new agreed policy feel free to raise a PR to https://github.com/shapeblue/hackerbook/blob/main/hack/api.md and discuss on dev@ML (if not already discussed). Thanks.
There was a problem hiding this comment.
@rohityadavcloud ,
there was a PR merged into 4.18 #7022
@rahulbcn27 please use the new format as @DaanHoogland @GutoVeronezi advised
…into FR-Schedule
yadvr
left a comment
There was a problem hiding this comment.
Left some remarks thanks @rahulbcn27
| start, stop, forcestop, reboot | ||
| } | ||
|
|
||
| public String getUuid(); |
There was a problem hiding this comment.
Is this necesasry if VMSchedule extends Identity and InternalIdentity?
There was a problem hiding this comment.
Don't think getUuid needs to be defined if you are extending Identity
| RoleType[] authorized() default {}; | ||
|
|
||
| Class<?>[] entityType() default {}; | ||
|
|
There was a problem hiding this comment.
nit - still see newline changes in APICommand
| public static final String PRIVATE_MTU = "privatemtu"; | ||
| public static final String MTU = "mtu"; | ||
| public static final String LIST_APIS = "listApis"; | ||
| public static final String VM_SCHEDULE_DESCRIPTION = "description"; |
There was a problem hiding this comment.
VM_ prefix isn't necessary unless the parameter is specifically for VM Schedule feature, this for example can simply be description (it's possible the DESCRIPTION param already exists that you can simply reuse).
There was a problem hiding this comment.
I don´t see this fixed yet.
There was a problem hiding this comment.
@rahulbcn27 as others mentioned you can use existing constants instead of defining new ones
| public static final String VM_SCHEDULE_TIMEZONE = "timezone"; | ||
| public static final String VM_SCHEDULE_ID = "vmscheduleid"; | ||
|
|
||
| public static final String VM_SCHEDULE_IDS = "vmscheduleids"; |
There was a problem hiding this comment.
suggestion - such a param name isn't necessary when called for an API that's related to VM Schedule, however, this can be useful if the params are not used with VM Scheduler APIs.
|
|
||
| public interface VMScheduleDao extends GenericDao<VMScheduleVO, Long> { | ||
|
|
||
| List<VMScheduleVO> findByVm(Long vmId); |
There was a problem hiding this comment.
suggestion - a helper method to find the next schedule action based on current time could be useful
There was a problem hiding this comment.
Did it next commit change.
|
|
||
| --- Create table for Virtual Machine Schedule Entity | ||
|
|
||
| CREATE TABLE IF NOT EXISTS `cloud`.`vm_schedule` ( |
|
@blueorangutan package |
|
@shwstppr a Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
|
Packaging result: ✖️ el7 ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 5793 |
|
@blueorangutan package |
1 similar comment
|
@blueorangutan package |
|
@rohityadavcloud a Jenkins job has been kicked to build packages. It will be bundled with SystemVM template(s). I'll keep you posted as I make progress. |
|
Packaging result: ✖️ el7 ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 5797 |
|
@blueorangutan package |
|
@weizhouapache a Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
|
Packaging result: ✖️ el7 ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 5798 |
DaanHoogland
left a comment
There was a problem hiding this comment.
generally looks good, some points of polishing, and it does not packages at the moment (might be environmental)
| Map<String,String> Tag = new HashMap<>(); | ||
| if (!vmSchedule.getTag().isEmpty()) { | ||
| Tag.put("ScheduleMessage", vmSchedule.getTag()); | ||
| Tag.put("ScheduleMessage" + currentTimestamp, vmSchedule.getTag()); |
There was a problem hiding this comment.
not a code comment but more of a functional comment; I would not use tags for this but annotations/comments.
| public static final String PRIVATE_MTU = "privatemtu"; | ||
| public static final String MTU = "mtu"; | ||
| public static final String LIST_APIS = "listApis"; | ||
| public static final String VM_SCHEDULE_DESCRIPTION = "description"; |
There was a problem hiding this comment.
I don´t see this fixed yet.
| @Override | ||
| public String getCommandName() { | ||
| return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; | ||
| } |
There was a problem hiding this comment.
will you remove this call, as @GutoVeronezi advises @rahulbcn27 ?
| import org.apache.cloudstack.api.response.VMScheduleResponse; | ||
| import org.apache.log4j.Logger; | ||
|
|
||
| @APICommand(name = DisableVMScheduleCmd.APINAME, description = "Updates a VM Schedule", responseObject = SuccessResponse.class, |
There was a problem hiding this comment.
I do not see an indetation problem here.
| String displayTime = DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, currentTimestamp); | ||
| LOGGER.debug("VM poll is being called at " + displayTime); | ||
|
|
||
| final List<VMScheduleVO> vmsToBeExecuted = vmScheduleDao.listAll(); |
There was a problem hiding this comment.
This list can become very long, should we have a more precise search method for this? i.e. all schedules to perform in the near future?
| if (vmInstance.getState() == VirtualMachine.State.Running) { | ||
| LOGGER.debug("Virtual Machine is already running" + vmInstance.getId()); | ||
| break; | ||
| } | ||
| final Long eventStartId = ActionEventUtils.onScheduledActionEvent(User.UID_SYSTEM, vmInstance.getAccountId(), | ||
| EventTypes.EVENT_VM_START, "Starting a VM for VM ID:" + vmInstance.getUuid(), | ||
| vmInstance.getId(), ApiCommandResourceType.VirtualMachine.toString(), | ||
| true, 0); | ||
| vmManager.start(vmInstance.getUuid(), params); | ||
| vmTag = setVMTag(vmSchedule); | ||
| createTagForVMInstance(vmTag, vmInstance); | ||
| if (CallContext.current().getCallingUser().getEmail() != null) { | ||
| String subject = "VM START"; | ||
| String message = "VM started on " + vmSchedule.getScheduleType() + " at " + vmSchedule.getSchedule(); | ||
| alertManager.sendAlert(AlertManager.AlertType.ALERT_TYPE_VM_START, vmInstance.getDataCenterId(), | ||
| vmInstance.getPodIdToDeployIn(),subject,message); | ||
| } | ||
| jobId = setAsyncJobForVMSchedule(vmInstance, eventStartId); |
There was a problem hiding this comment.
I would like to see these blocks in separate methods for each type of action.
| @classmethod | ||
| def tearDownClass(cls): | ||
| try: | ||
| cleanup_resources(cls.apiclient, cls.cleanup) | ||
| except Exception as e: | ||
| raise Exception("Warning: Exception during cleanup : %s" % e) |
There was a problem hiding this comment.
| @classmethod | |
| def tearDownClass(cls): | |
| try: | |
| cleanup_resources(cls.apiclient, cls.cleanup) | |
| except Exception as e: | |
| raise Exception("Warning: Exception during cleanup : %s" % e) | |
| @classmethod | |
| def tearDownClass(cls): | |
| super(TestVmSchedule, cls).tearDownClass() |
| serviceofferingid=cls.service_offering.id, | ||
| mode=cls.zone.networktype | ||
| ) | ||
| # cls.cleanup.append(cls.virtual_machine) |
There was a problem hiding this comment.
why code in comment? take it our or uncomment, I'd say
| def tearDown(self): | ||
| try: | ||
| cleanup_resources(self.apiclient, self.cleanup) | ||
| except Exception as e: | ||
| raise Exception("Warning: Exception during cleanup : %s" % e) |
There was a problem hiding this comment.
| def tearDown(self): | |
| try: | |
| cleanup_resources(self.apiclient, self.cleanup) | |
| except Exception as e: | |
| raise Exception("Warning: Exception during cleanup : %s" % e) | |
| def tearDown(self): | |
| super(TestVmSchedule, self).tearDown() |
| <target> | ||
| <copy overwrite="true" todir="${basedir}/target/transformed"> | ||
| <fileset dir="${basedir}/conf"> | ||
| <include name="*.in" /> | ||
| </fileset> | ||
| <globmapper from="*.in" to="*" /> | ||
| <filterchain> | ||
| <filterreader classname="org.apache.tools.ant.filters.ReplaceTokens"> | ||
| <param type="propertiesfile" value="${cs.replace.properties}" /> | ||
| </filterreader> | ||
| </filterchain> | ||
| </copy> | ||
| </target> |
There was a problem hiding this comment.
why does this need removing?
| response.success, | ||
| True, | ||
| "VM schedule is not removed " | ||
| "check the response action of vm schedule is start!" |
There was a problem hiding this comment.
your comment here is "minor change ..." but you remove 4 test cases. Is that on purpose?
|
@blueorangutan package |
|
@rohityadavcloud a Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
|
SonarCloud Quality Gate failed. |
| requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0", | ||
| authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) | ||
| public class DisableVMScheduleCmd extends BaseAsyncCmd { | ||
| public static final String APINAME = "disableVMSchedule"; |
There was a problem hiding this comment.
Do we really need three APIs - update, enable and disable?
Would it be better if the update API handles state change as well?
| quickViewEnabled () { | ||
| return new RegExp(['/vm', '/kubernetes', '/ssh', '/userdata', '/vmgroup', '/affinitygroup', '/autoscalevmgroup', | ||
| '/volume', '/snapshot', '/vmsnapshot', '/backup', | ||
| '/volume', '/snapshot', '/vmsnapshot', '/backup', '/schedule', |
There was a problem hiding this comment.
| '/volume', '/snapshot', '/vmsnapshot', '/backup', '/schedule', | |
| '/volume', '/snapshot', '/vmsnapshot', '/backup', '/vmschedule', |
| enableGroupAction () { | ||
| return ['vm', 'alert', 'vmgroup', 'ssh', 'userdata', 'affinitygroup', 'autoscalevmgroup', 'volume', 'snapshot', | ||
| 'vmsnapshot', 'guestnetwork', 'vpc', 'publicip', 'vpnuser', 'vpncustomergateway', | ||
| 'vmsnapshot', 'schedule', 'guestnetwork', 'vpc', 'publicip', 'vpnuser', 'vpncustomergateway', |
There was a problem hiding this comment.
| 'vmsnapshot', 'schedule', 'guestnetwork', 'vpc', 'publicip', 'vpnuser', 'vpncustomergateway', | |
| 'vmsnapshot', 'vmschedule', 'guestnetwork', 'vpc', 'publicip', 'vpnuser', 'vpncustomergateway', |
| }, | ||
| generateHumanReadableEntityType (record) { | ||
| switch (record.entitytype) { | ||
| case 'VMSCHEDULE' : return 'schedule' |
There was a problem hiding this comment.
| case 'VMSCHEDULE' : return 'schedule' | |
| case 'VMSCHEDULE' : return 'VM Schedule' |
| }, | ||
| entityTypeToPath (entitytype) { | ||
| switch (entitytype) { | ||
| case 'VMSCHEDULE' : return 'schedule' |
There was a problem hiding this comment.
| case 'VMSCHEDULE' : return 'schedule' | |
| case 'VMSCHEDULE' : return 'vmschedule' |
| // specific language governing permissions and limitations | ||
| // under the License. | ||
|
|
||
| <template> |
There was a problem hiding this comment.
This UI element can be further improved for generic use.
List of actions can be passed as property. This may take some work
| "start", | ||
| "check the response action of vm schedule is start!" | ||
| ) | ||
| return |
There was a problem hiding this comment.
May cover other APIs - update, enable, disable, delete
| import java.util.concurrent.ScheduledExecutorService; | ||
| import java.util.concurrent.TimeUnit; | ||
|
|
||
| public class VMScheduleManagerImpl extends ManagerBase implements VMScheduleManager, Configurable, PluggableService { |
There was a problem hiding this comment.
Are there any unit tests for this class?
| requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, | ||
| authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) | ||
| public class CreateVMScheduleCmd extends BaseAsyncCreateCmd { | ||
| public static final String APINAME = "createVMSchedule"; |
There was a problem hiding this comment.
@rohityadavcloud ,
there was a PR merged into 4.18 #7022
@rahulbcn27 please use the new format as @DaanHoogland @GutoVeronezi advised
|
|
||
| @Override | ||
| public long getEntityOwnerId() { | ||
| return Account.ACCOUNT_ID_SYSTEM; |
There was a problem hiding this comment.
the value would be the id of caller or owner
(the same issue in other APIs)
| final AsyncJobVO asyncJob = asyncJobManager.getAsyncJob(asyncJobId); | ||
| switch (asyncJob.getStatus()) { | ||
| case SUCCEEDED: | ||
| case FAILED: |
There was a problem hiding this comment.
may add "case CANCELLED" as well
| for (final VMScheduleVO vmSchedule : vmsToBeExecuted) { | ||
| final long timeDifference = DateUtil.getTimeDifference(vmSchedule.getScheduledTimestamp(), currentTimestamp); | ||
|
|
||
| if (timeDifference <= 1) { |
There was a problem hiding this comment.
@rahulbcn27
can you explain what this check does if (timeDifference <= 1)?
should VMSchedulerInterval.value() be used here ?
There was a problem hiding this comment.
it is used to check the condition in which time difference between scheduledtimestamp and currentimestamp is mininum <
1 min so that action can be performed on action.
|
|
||
| private Map<String, String> setVMTag(VMScheduleVO vmSchedule) { | ||
| Map<String,String> Tag = new HashMap<>(); | ||
| if (!vmSchedule.getTag().isEmpty()) { |
There was a problem hiding this comment.
might getTag be null ? if so, NPE will be thrown
can use CollectionUtils instead
| return jobId; | ||
| } | ||
|
|
||
| private Long performActionOnVM(String action, VMInstanceVO vmInstance, VMScheduleVO vmSchedule) throws ResourceUnavailableException, InsufficientCapacityException { |
|
Discussed with Rahul and passed some feedback. We'll revisiting this with another iteration in future. |








Description
This PR is for feature Orchestrated VM Scheduler where action is scheduled on VM in given period time. A new VM Schedule
festure is implemented to ochestrate stop/start on VMs.
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?