diff --git a/plogical/cronUtil.py b/plogical/cronUtil.py index e6cec26ad..2a8796c56 100644 --- a/plogical/cronUtil.py +++ b/plogical/cronUtil.py @@ -139,6 +139,134 @@ class CronUtil: command = 'chmod 1730 /var/spool/cron/crontabs' ProcessUtilities.outputExecutioner(command) + @staticmethod + def suspendWebsiteCrons(externalApp): + """ + Suspend all cron jobs for a website by backing up and clearing the cron file. + This prevents cron jobs from running when a website is suspended. + """ + try: + if ProcessUtilities.decideDistro() == ProcessUtilities.centos or ProcessUtilities.decideDistro() == ProcessUtilities.cent8: + cronPath = "/var/spool/cron/" + externalApp + backupPath = "/var/spool/cron/" + externalApp + ".suspended" + else: + cronPath = "/var/spool/cron/crontabs/" + externalApp + backupPath = "/var/spool/cron/crontabs/" + externalApp + ".suspended" + + # Check if cron file exists + if not os.path.exists(cronPath): + print("1,None") # No cron file to suspend + return + + # Create backup of current cron jobs + try: + command = f'cp {cronPath} {backupPath}' + ProcessUtilities.executioner(command, 'root') + except Exception as e: + print(f"0,Warning: Could not backup cron file: {str(e)}") + + # Clear the cron file to suspend all jobs + try: + CronUtil.CronPrem(1) # Enable permissions + + # Create empty cron file or clear existing one + with open(cronPath, 'w') as f: + f.write('') # Empty file to disable all cron jobs + + # Set proper ownership + command = f'chown {externalApp}:{externalApp} {cronPath}' + ProcessUtilities.executioner(command, 'root') + + CronUtil.CronPrem(0) # Restore permissions + + print("1,Cron jobs suspended successfully") + + except Exception as e: + CronUtil.CronPrem(0) # Ensure permissions are restored + print(f"0,Failed to suspend cron jobs: {str(e)}") + + except Exception as e: + print(f"0,Error suspending cron jobs: {str(e)}") + + @staticmethod + def restoreWebsiteCrons(externalApp): + """ + Restore cron jobs for a website by restoring from backup file. + This restores cron jobs when a website is unsuspended. + """ + try: + if ProcessUtilities.decideDistro() == ProcessUtilities.centos or ProcessUtilities.decideDistro() == ProcessUtilities.cent8: + cronPath = "/var/spool/cron/" + externalApp + backupPath = "/var/spool/cron/" + externalApp + ".suspended" + else: + cronPath = "/var/spool/cron/crontabs/" + externalApp + backupPath = "/var/spool/cron/crontabs/" + externalApp + ".suspended" + + # Check if backup file exists + if not os.path.exists(backupPath): + print("1,No suspended cron jobs to restore") + return + + try: + CronUtil.CronPrem(1) # Enable permissions + + # Restore cron jobs from backup + command = f'cp {backupPath} {cronPath}' + ProcessUtilities.executioner(command, 'root') + + # Set proper ownership + command = f'chown {externalApp}:{externalApp} {cronPath}' + ProcessUtilities.executioner(command, 'root') + + # Remove backup file + os.remove(backupPath) + + CronUtil.CronPrem(0) # Restore permissions + + print("1,Cron jobs restored successfully") + + except Exception as e: + CronUtil.CronPrem(0) # Ensure permissions are restored + print(f"0,Failed to restore cron jobs: {str(e)}") + + except Exception as e: + print(f"0,Error restoring cron jobs: {str(e)}") + + @staticmethod + def getCronSuspensionStatus(externalApp): + """ + Check if cron jobs are currently suspended for a website. + Returns 1 if suspended, 0 if active, -1 if error. + """ + try: + if ProcessUtilities.decideDistro() == ProcessUtilities.centos or ProcessUtilities.decideDistro() == ProcessUtilities.cent8: + cronPath = "/var/spool/cron/" + externalApp + backupPath = "/var/spool/cron/" + externalApp + ".suspended" + else: + cronPath = "/var/spool/cron/crontabs/" + externalApp + backupPath = "/var/spool/cron/crontabs/" + externalApp + ".suspended" + + # Check if backup file exists (indicates suspension) + if os.path.exists(backupPath): + print("1,Cron jobs are suspended") + return + elif os.path.exists(cronPath): + # Check if cron file is empty (also indicates suspension) + try: + with open(cronPath, 'r') as f: + content = f.read().strip() + if not content: + print("1,Cron jobs are suspended (empty file)") + else: + print("0,Cron jobs are active") + except Exception as e: + print(f"-1,Error reading cron file: {str(e)}") + else: + print("0,No cron jobs configured") + + except Exception as e: + print(f"-1,Error checking cron status: {str(e)}") + def main(): @@ -162,6 +290,12 @@ def main(): CronUtil.remCronbyLine(args.externalApp, int(args.line)) elif args.function == "addNewCron": CronUtil.addNewCron(args.externalApp, args.finalCron) + elif args.function == "suspendWebsiteCrons": + CronUtil.suspendWebsiteCrons(args.externalApp) + elif args.function == "restoreWebsiteCrons": + CronUtil.restoreWebsiteCrons(args.externalApp) + elif args.function == "getCronSuspensionStatus": + CronUtil.getCronSuspensionStatus(args.externalApp) diff --git a/websiteFunctions/website.py b/websiteFunctions/website.py index 187b76807..8246f85b9 100644 --- a/websiteFunctions/website.py +++ b/websiteFunctions/website.py @@ -3151,9 +3151,27 @@ context /cyberpanel_suspension_page.html { except: pass - # Apply same suspension configuration to child domains + # Suspend cron jobs for child domains childDomains = website.childdomains_set.all() + for items in childDomains: + # Suspend cron jobs for child domain + try: + CronUtil.CronPrem(1) + execPath = "/usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/cronUtil.py" + execPath = execPath + " suspendWebsiteCrons --externalApp " + items.externalApp + cronOutput = ProcessUtilities.outputExecutioner(execPath, items.externalApp) + CronUtil.CronPrem(0) + + if cronOutput.find("1,") > -1: + logging.CyberCPLogFileWriter.writeToFile(f"Successfully suspended cron jobs for child domain {items.domain}") + else: + logging.CyberCPLogFileWriter.writeToFile(f"Warning: Failed to suspend cron jobs for child domain {items.domain}: {cronOutput}") + except Exception as e: + CronUtil.CronPrem(0) # Ensure permissions are restored + logging.CyberCPLogFileWriter.writeToFile(f"Error suspending cron jobs for child domain {items.domain}: {str(e)}") + + # Apply same suspension configuration to child domains for items in childDomains: childConfPath = virtualHostUtilities.Server_root + "/conf/vhosts/" + items.domain childVhostConfPath = childConfPath + "/vhost.conf" @@ -3198,6 +3216,22 @@ context /cyberpanel_suspension_page.html { except Exception as e: CyberCPLogFileWriter.writeToFile(f"Error suspending child domain {items.domain}: {str(e)}") + # Suspend cron jobs for this website + try: + CronUtil.CronPrem(1) + execPath = "/usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/cronUtil.py" + execPath = execPath + " suspendWebsiteCrons --externalApp " + website.externalApp + cronOutput = ProcessUtilities.outputExecutioner(execPath, website.externalApp) + CronUtil.CronPrem(0) + + if cronOutput.find("1,") > -1: + logging.CyberCPLogFileWriter.writeToFile(f"Successfully suspended cron jobs for {websiteName}") + else: + logging.CyberCPLogFileWriter.writeToFile(f"Warning: Failed to suspend cron jobs for {websiteName}: {cronOutput}") + except Exception as e: + CronUtil.CronPrem(0) # Ensure permissions are restored + logging.CyberCPLogFileWriter.writeToFile(f"Error suspending cron jobs for {websiteName}: {str(e)}") + # Restart LiteSpeed to apply changes try: installUtilities.reStartLiteSpeedSocket() @@ -3297,9 +3331,27 @@ context /cyberpanel_suspension_page.html { except: pass - # Remove suspension configuration from child domains + # Restore cron jobs for child domains childDomains = website.childdomains_set.all() + for items in childDomains: + # Restore cron jobs for child domain + try: + CronUtil.CronPrem(1) + execPath = "/usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/cronUtil.py" + execPath = execPath + " restoreWebsiteCrons --externalApp " + items.externalApp + cronOutput = ProcessUtilities.outputExecutioner(execPath, items.externalApp) + CronUtil.CronPrem(0) + + if cronOutput.find("1,") > -1: + logging.CyberCPLogFileWriter.writeToFile(f"Successfully restored cron jobs for child domain {items.domain}") + else: + logging.CyberCPLogFileWriter.writeToFile(f"Info: {cronOutput} for child domain {items.domain}") + except Exception as e: + CronUtil.CronPrem(0) # Ensure permissions are restored + logging.CyberCPLogFileWriter.writeToFile(f"Error restoring cron jobs for child domain {items.domain}: {str(e)}") + + # Remove suspension configuration from child domains for items in childDomains: childConfPath = virtualHostUtilities.Server_root + "/conf/vhosts/" + items.domain childVhostConfPath = childConfPath + "/vhost.conf" @@ -3346,6 +3398,22 @@ context /cyberpanel_suspension_page.html { except Exception as e: CyberCPLogFileWriter.writeToFile(f"Error unsuspending child domain {items.domain}: {str(e)}") + # Restore cron jobs for this website + try: + CronUtil.CronPrem(1) + execPath = "/usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/cronUtil.py" + execPath = execPath + " restoreWebsiteCrons --externalApp " + website.externalApp + cronOutput = ProcessUtilities.outputExecutioner(execPath, website.externalApp) + CronUtil.CronPrem(0) + + if cronOutput.find("1,") > -1: + logging.CyberCPLogFileWriter.writeToFile(f"Successfully restored cron jobs for {websiteName}") + else: + logging.CyberCPLogFileWriter.writeToFile(f"Info: {cronOutput} for {websiteName}") + except Exception as e: + CronUtil.CronPrem(0) # Ensure permissions are restored + logging.CyberCPLogFileWriter.writeToFile(f"Error restoring cron jobs for {websiteName}: {str(e)}") + # Restart LiteSpeed to apply changes try: installUtilities.reStartLiteSpeedSocket()