rahulbcn27 commented on code in PR #7289:
URL: https://github.com/apache/cloudstack/pull/7289#discussion_r1151721539


##########
server/src/main/java/com/cloud/vm/schedule/VMScheduleManagerImpl.java:
##########
@@ -0,0 +1,598 @@
+// 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.vm.schedule;
+
+import com.cloud.alert.AlertManager;
+import com.cloud.api.ApiDispatcher;
+import com.cloud.api.ApiGsonHelper;
+import com.cloud.event.ActionEvent;
+import com.cloud.event.ActionEventUtils;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.server.ResourceTag;
+import com.cloud.user.User;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.ListUtils;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.component.PluggableService;
+import com.cloud.utils.concurrency.NamedThreadFactory;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GlobalLock;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionStatus;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineManager;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.vm.schedule.dao.VMScheduleDao;
+import org.apache.cloudstack.api.ApiCommandResourceType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.command.user.vmschedule.CreateVMScheduleCmd;
+import org.apache.cloudstack.api.command.user.vmschedule.ListVMScheduleCmd;
+import org.apache.cloudstack.api.command.user.vmschedule.UpdateVMScheduleCmd;
+import org.apache.cloudstack.api.command.user.vmschedule.DeleteVMScheduleCmd;
+import org.apache.cloudstack.api.command.user.vmschedule.EnableVMScheduleCmd;
+import org.apache.cloudstack.api.command.user.vmschedule.DisableVMScheduleCmd;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher;
+import org.apache.cloudstack.framework.jobs.AsyncJobManager;
+import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
+import org.apache.cloudstack.managed.context.ManagedContextTimerTask;
+import org.apache.cloudstack.poll.BackgroundPollManager;
+import org.apache.commons.collections.MapUtils;
+import org.apache.log4j.Logger;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.server.TaggedResourceService;
+
+import java.util.Date;
+import java.util.List;
+import java.util.TimerTask;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.TimeZone;
+import java.util.Collections;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class VMScheduleManagerImpl extends ManagerBase implements 
VMScheduleManager, Configurable, PluggableService {
+    public static final Logger LOGGER = 
Logger.getLogger(VMScheduleManagerImpl.class);
+
+    @Inject
+    private VMScheduleDao vmScheduleDao;
+
+    @Inject
+    private VirtualMachineManager vmManager;
+
+    @Inject
+    private BackgroundPollManager backgroundPollManager;
+
+    @Inject
+    private AsyncJobManager asyncJobManager;
+
+    @Inject
+    private VMInstanceDao vmInstanceDao;
+
+    @Inject
+    private ApiDispatcher apiDispatcher;
+
+    private AsyncJobDispatcher asyncJobDispatcher;
+
+    @Inject
+    public TaggedResourceService taggedResourceService;
+
+    private Date currentTimestamp;
+
+    @Inject
+    private AlertManager alertManager;
+
+    private ScheduledExecutorService backgroundPollTaskScheduler;
+
+    private volatile boolean isConfiguredAndStarted = false;
+
+    private static final ConfigKey<Boolean> EnableVMSchedulerInterval = new 
ConfigKey<>("Advanced", Boolean.class,
+            "vm.scheduler.enable", "false",
+            "Enable the VMScheduler Interval  to schedule tasks on VM.", 
false);
+
+    private static final ConfigKey<Integer> VMSchedulerInterval = new 
ConfigKey<>("Advanced", Integer.class,
+            "vm.scheduler.interval", "60",
+            "The interval at which VM Scheduler runs in milliseconds", false, 
EnableVMSchedulerInterval.key());
+
+    @Override
+    public boolean start() {
+        if (isConfiguredAndStarted) {
+            return true;
+        }
+        currentTimestamp = new Date();
+        for (final VMScheduleVO vmSchedule : vmScheduleDao.listAll()) {
+            scheduleNextVMJob(vmSchedule);
+        }
+        backgroundPollTaskScheduler = Executors.newScheduledThreadPool(100, 
new NamedThreadFactory("BackgroundTaskPollManager"));
+        final TimerTask vmPollTask = new ManagedContextTimerTask() {
+            @Override
+            protected void runInContext() {
+                try {
+                    poll(new Date());
+                } catch (final Throwable t) {
+                    LOGGER.warn("Catch throwable in vm scheduler ", t);
+                }
+            }
+        };
+        backgroundPollTaskScheduler.scheduleWithFixedDelay(vmPollTask, 
VMSchedulerInterval.value() * 1000L, VMSchedulerInterval.value() * 1000L, 
TimeUnit.MILLISECONDS);
+        isConfiguredAndStarted = true;
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        if (isConfiguredAndStarted) {
+            backgroundPollTaskScheduler.shutdown();
+        }
+        return true;
+    }
+
+    @Override
+    public String getConfigComponentName() {
+        return VMScheduleManager.class.getSimpleName();
+    }
+
+    @Override
+    public ConfigKey<?>[] getConfigKeys() {
+        return new ConfigKey<?>[] {
+                VMSchedulerInterval,
+                EnableVMSchedulerInterval
+        };
+    }
+
+    @Override
+    public boolean configure(final String name, final Map<String, Object> 
params) throws ConfigurationException {
+        return true;
+    }
+
+    @Override
+    public List<Class<?>> getCommands() {
+        final List<Class<?>> cmdList = new ArrayList<>();
+        cmdList.add(CreateVMScheduleCmd.class);
+        cmdList.add(ListVMScheduleCmd.class);
+        cmdList.add(UpdateVMScheduleCmd.class);
+        cmdList.add(DeleteVMScheduleCmd.class);
+        cmdList.add(EnableVMScheduleCmd.class);
+        cmdList.add(DisableVMScheduleCmd.class);
+        cmdList.add(UpdateVMScheduleCmd.class);
+        return cmdList;
+    }
+
+    @Override
+    public VMSchedule findVMSchedule(Long id) {
+        if (id == null || id < 1L) {
+            if (LOGGER.isTraceEnabled()) {
+                LOGGER.trace(String.format("VMSchedule ID is invalid [%s]", 
id));
+                return null;
+            }
+        }
+
+         VMSchedule vmSchedule = vmScheduleDao.findById(id);
+        if (vmSchedule == null) {
+            if (LOGGER.isTraceEnabled()) {
+                LOGGER.trace(String.format("VmSchedule ID not found [id=%s]", 
id));
+                return null;
+            }
+        }
+
+        return vmSchedule;
+    }
+
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VMSCHEDULE_CREATE, 
eventDescription = "creating vm schedule", async = true)
+    public VMSchedule createVMSchedule(CreateVMScheduleCmd cmd) {
+        VMSchedule.State state = VMSchedule.State.DISABLED;
+        final String action = cmd.getAction();
+        final Long vmId = cmd.getVmId();
+        String intervalType = cmd.getIntervalType();
+        String scheduleString = cmd.getSchedule();
+        String description = cmd.getDescription();
+        String tag = cmd.getTag();
+        TimeZone timeZone = TimeZone.getTimeZone(cmd.getTimezone());
+        Boolean enable = cmd.getEnable();
+
+        if (enable) {
+            state = VMSchedule.State.ENABLED;
+        }
+
+        if (intervalType.equals("hourly"))
+            intervalType = "HOURLY";
+
+        if (intervalType.equals("daily"))
+            intervalType = "DAILY";
+
+        if (intervalType.equals("weekly"))
+            intervalType = "WEEKLY";
+
+        if (intervalType.equals("monthly"))
+            intervalType = "MONTHLY";
+
+        if (description == null) {
+           description = action + " VM Instance with vmId:" + vmId + " " +  
intervalType + " at " + scheduleString;
+        }
+
+        if (tag == null) {
+            tag = String.format("VM " + cmd.getAction() + 
cmd.getIntervalType() + cmd.getSchedule());
+        }
+
+        if (timeZone == null) {
+            timeZone = TimeZone.getDefault();
+        }
+
+        if (intervalType == null) {
+            throw new CloudRuntimeException("Invalid interval type provided");
+        }
+
+        final String timezoneId = timeZone.getID();
+        if (!timezoneId.equals(cmd.getTimezone())) {
+            LOGGER.warn("Using timezone: " + timezoneId + " for running this 
schedule as an equivalent of " + cmd.getTimezone());
+        }
+
+        Date nextDateTime = null;
+        try {
+            nextDateTime = 
DateUtil.getNextRunTime(DateUtil.IntervalType.valueOf(intervalType), 
cmd.getSchedule(), timezoneId, null);
+        } catch (Exception e) {
+            throw new InvalidParameterValueException("Invalid schedule: " + 
cmd.getSchedule() + " for interval type: " + cmd.getIntervalType());
+        }
+
+        return vmScheduleDao.persist(new VMScheduleVO(vmId, description, 
action, intervalType, scheduleString,
+                timezoneId, nextDateTime, tag, state, 1L));
+    }
+
+    @Override
+    public List<VMSchedule> listVMSchedules(ListVMScheduleCmd cmd) {
+        if (cmd.getId() != null) {
+            VMSchedule vmSchedule = findVMSchedule(cmd.getId());
+            List<VMSchedule> arr = new ArrayList<>();
+            arr.add(vmSchedule);
+            return arr;
+        }
+
+        if (cmd.getVmId() != null) {
+            List<VMSchedule> vmSchedules = new ArrayList<>();
+            List<VMScheduleVO> vmScheduleVOS = 
vmScheduleDao.findByVm(cmd.getVmId());
+            for (VMScheduleVO vmSchedule : vmScheduleVOS) {
+                vmSchedules.add(vmSchedule);
+            }
+            return vmSchedules;
+        }
+
+        List<? extends VMScheduleVO> vmSchedules = vmScheduleDao.listAll();
+        return ListUtils.toListOfInterface(vmSchedules);
+    }
+
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VMSCHEDULE_DELETE, 
eventDescription = "deleting VM Schedule")
+    public boolean deleteVMSchedule(Long vmScheduleId) {
+        VMSchedule vmSchedule = vmScheduleDao.findById(vmScheduleId);
+        if (vmSchedule == null) {
+            throw new InvalidParameterValueException("unable to find the vm 
schedule with id " + vmScheduleId);
+        }
+
+        return vmScheduleDao.remove(vmSchedule.getId());
+    }
+
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VMSCHEDULE_ENABLE, 
eventDescription = "enable VM Schedule")
+    public boolean enableVMSchedule(Long vmScheduleId) {
+        VMScheduleVO vmSchedule = vmScheduleDao.findById(vmScheduleId);
+        if (vmSchedule == null) {
+            throw new InvalidParameterValueException("unable to find the vm 
schedule with id " + vmScheduleId);
+        }
+
+        vmSchedule.setState(VMSchedule.State.ENABLED);
+        return vmScheduleDao.update(vmSchedule.getId(), vmSchedule);
+    }
+
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VMSCHEDULE_DISABLE, 
eventDescription = "disable VM Schedule")
+    public boolean disableVMSchedule(Long vmScheduleId) {
+        VMScheduleVO vmSchedule = vmScheduleDao.findById(vmScheduleId);
+        if (vmSchedule == null) {
+            throw new InvalidParameterValueException("unable to find the vm 
schedule with id " + vmScheduleId);
+        }
+
+        vmSchedule.setState(VMSchedule.State.DISABLED);
+        return vmScheduleDao.update(vmSchedule.getId(), vmSchedule);
+    }
+
+    @Override
+    @ActionEvent(eventType = EventTypes.EVENT_VMSCHEDULE_UPDATE, 
eventDescription = "update VM Schedule")
+    public VMSchedule updateVMSchedule(UpdateVMScheduleCmd cmd) {
+        VMScheduleVO vmSchedule = vmScheduleDao.findById(cmd.getId());
+        if (vmSchedule == null) {
+            throw new InvalidParameterValueException("unable to find the vm 
schedule with id " + cmd.getId());
+        }
+        String description = cmd.getDescription();
+        String schedule = cmd.getSchedule();
+        String intervalType = cmd.getIntervalType();
+        String action = cmd.getAction();
+        String tag = cmd.getTag();
+        String timezone = cmd.getTimezone();
+
+        if (vmSchedule.getState() == VMSchedule.State.DISABLED) {
+            if (description != null)
+                vmSchedule.setDescription(description);
+            if(schedule != null)
+                vmSchedule.setSchedule(schedule);
+            if(intervalType != null)
+                vmSchedule.setScheduleType(intervalType);
+            if (action != null)
+                vmSchedule.setAction(action);
+            if (tag != null)
+                vmSchedule.setTag(tag);
+            if (timezone != null)
+                vmSchedule.setTimezone(timezone);
+
+            vmScheduleDao.update(vmSchedule.getId(), vmSchedule);
+        } else {
+            throw new InvalidParameterValueException("Disable the state of VM 
Schedule before updating it");
+        }
+        return vmSchedule;
+    }
+
+    public void poll(final Date timestamp) {
+        currentTimestamp = timestamp;
+        GlobalLock scanLock = GlobalLock.getInternLock("vm.poll");
+
+        try {
+            if (scanLock.lock(5)) {
+                try {
+                    checkStatusOfCurrentlyExecutingVMs();
+                } finally {
+                    scanLock.unlock();
+                }
+            }
+        } finally {
+            scanLock.releaseRef();
+        }
+
+        scanLock = GlobalLock.getInternLock("vm.poll");
+        try {
+            if (scanLock.lock(5)) {
+                try {
+                    scheduleVMs();
+                } finally {
+                    scanLock.unlock();
+                }
+            }
+        } finally {
+            scanLock.releaseRef();
+        }
+    }
+
+    @DB
+    public void scheduleVMs() {
+        String displayTime = 
DateUtil.displayDateInTimezone(DateUtil.GMT_TIMEZONE, currentTimestamp);
+        LOGGER.debug("VM poll is being called at " + displayTime);
+
+        final List<VMScheduleVO> vmsToBeExecuted = vmScheduleDao.listAll();
+        for (final VMScheduleVO vmSchedule : vmsToBeExecuted) {
+            final long timeDifference = 
DateUtil.getTimeDifference(vmSchedule.getScheduledTimestamp(), 
currentTimestamp);
+
+            if (timeDifference <= 1) {

Review 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.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to