@@ -527,13 +527,24 @@ async def delete_system_credential(
527527
528528# Scheduler endpoints for host monitoring
529529class SchedulerStatus (BaseModel ):
530+ enabled : bool
531+ interval_minutes : int
530532 status : str # "running", "stopped", "error"
531- jobs : List [dict ] = []
533+ jobs : Optional [ List [dict ] ] = []
532534 uptime : Optional [str ] = None
533535
534536
535- # Global scheduler instance
537+ class SchedulerStartRequest (BaseModel ):
538+ interval_minutes : int = 5
539+
540+
541+ class SchedulerUpdateRequest (BaseModel ):
542+ interval_minutes : int
543+
544+
545+ # Global scheduler instance and settings
536546_scheduler = None
547+ _scheduler_interval = 5 # Default 5 minutes
537548
538549
539550def get_scheduler ():
@@ -555,6 +566,8 @@ async def get_scheduler_status(
555566
556567 if scheduler is None :
557568 return SchedulerStatus (
569+ enabled = False ,
570+ interval_minutes = _scheduler_interval ,
558571 status = "error" ,
559572 jobs = [],
560573 uptime = None
@@ -575,12 +588,16 @@ async def get_scheduler_status(
575588 logger .warning (f"Failed to get job info: { e } " )
576589
577590 return SchedulerStatus (
591+ enabled = True ,
592+ interval_minutes = _scheduler_interval ,
578593 status = "running" ,
579594 jobs = jobs_info ,
580595 uptime = "Running"
581596 )
582597 else :
583598 return SchedulerStatus (
599+ enabled = False ,
600+ interval_minutes = _scheduler_interval ,
584601 status = "stopped" ,
585602 jobs = [],
586603 uptime = None
@@ -589,6 +606,8 @@ async def get_scheduler_status(
589606 except Exception as e :
590607 logger .error (f"Failed to get scheduler status: { e } " )
591608 return SchedulerStatus (
609+ enabled = False ,
610+ interval_minutes = _scheduler_interval ,
592611 status = "error" ,
593612 jobs = [],
594613 uptime = None
@@ -598,11 +617,13 @@ async def get_scheduler_status(
598617@router .post ("/scheduler/start" )
599618@require_permission (Permission .SYSTEM_MAINTENANCE )
600619async def start_scheduler (
620+ request : SchedulerStartRequest ,
601621 current_user : dict = Depends (get_current_user )
602622):
603623 """Start the monitoring scheduler"""
604624 try :
605- global _scheduler
625+ global _scheduler , _scheduler_interval
626+ _scheduler_interval = request .interval_minutes
606627 scheduler = get_scheduler ()
607628
608629 if scheduler is None :
@@ -618,11 +639,31 @@ async def start_scheduler(
618639
619640 if not scheduler .running :
620641 scheduler .start ()
621- logger .info (f"Host monitoring scheduler started by user { current_user .get ('username' , 'unknown' )} " )
642+
643+ # Configure the monitoring job with the requested interval
644+ from ..tasks .monitoring_tasks import periodic_host_monitoring
645+
646+ # Remove any existing job first
647+ for job in scheduler .get_jobs ():
648+ if job .id == "host_monitoring" :
649+ scheduler .remove_job (job .id )
650+
651+ # Add the job with the specified interval
652+ scheduler .add_job (
653+ periodic_host_monitoring ,
654+ 'interval' ,
655+ minutes = _scheduler_interval ,
656+ id = 'host_monitoring' ,
657+ name = 'Host Monitoring Task' ,
658+ replace_existing = True
659+ )
660+
661+ logger .info (f"Host monitoring scheduler started with { _scheduler_interval } minute interval by user { current_user .get ('username' , 'unknown' )} " )
622662
623663 return {
624664 "message" : "Scheduler started successfully" ,
625- "status" : "running"
665+ "status" : "running" ,
666+ "interval_minutes" : _scheduler_interval
626667 }
627668 else :
628669 return {
@@ -675,6 +716,53 @@ async def stop_scheduler(
675716 )
676717
677718
719+ @router .put ("/scheduler" )
720+ @require_permission (Permission .SYSTEM_MAINTENANCE )
721+ async def update_scheduler (
722+ request : SchedulerUpdateRequest ,
723+ current_user : dict = Depends (get_current_user )
724+ ):
725+ """Update scheduler settings"""
726+ try :
727+ global _scheduler_interval
728+ _scheduler_interval = request .interval_minutes
729+
730+ scheduler = get_scheduler ()
731+
732+ # If scheduler is running, we need to reschedule the job with the new interval
733+ if scheduler and scheduler .running :
734+ # Remove existing jobs
735+ for job in scheduler .get_jobs ():
736+ if job .id == "host_monitoring" :
737+ scheduler .remove_job (job .id )
738+
739+ # Add new job with updated interval
740+ from ..tasks .monitoring_tasks import periodic_host_monitoring
741+ scheduler .add_job (
742+ periodic_host_monitoring ,
743+ 'interval' ,
744+ minutes = _scheduler_interval ,
745+ id = 'host_monitoring' ,
746+ name = 'Host Monitoring Task' ,
747+ replace_existing = True
748+ )
749+
750+ logger .info (f"Scheduler interval updated to { _scheduler_interval } minutes by user { current_user .get ('username' , 'unknown' )} " )
751+
752+ return {
753+ "message" : f"Scheduler interval updated to { _scheduler_interval } minutes" ,
754+ "interval_minutes" : _scheduler_interval ,
755+ "status" : "running" if scheduler and scheduler .running else "stopped"
756+ }
757+
758+ except Exception as e :
759+ logger .error (f"Failed to update scheduler: { e } " )
760+ raise HTTPException (
761+ status_code = status .HTTP_500_INTERNAL_SERVER_ERROR ,
762+ detail = f"Failed to update scheduler: { str (e )} "
763+ )
764+
765+
678766async def restore_scheduler_state ():
679767 """Restore scheduler state from database on startup"""
680768 try :
0 commit comments