root il y a 4 ans
Parent
commit
0239354018

+ 10 - 15
app/Cron/Snapshots.php

@@ -18,8 +18,7 @@ use Symfony\Component\Console\Output\OutputInterface;
 use Symfony\Component\Console\Style\SymfonyStyle;
 use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
 
-class Snapshots extends Command
-{
+class Snapshots extends Command {
     use WhmcsParams;
     use ProductService;
     use ApiService;
@@ -50,19 +49,17 @@ class Snapshots extends Command
      * @query daily SELECT *, DATE(`updated_at`) as t FROM `ProxmoxAddon_SnapshotJob` where `period` = 'daily' and TIMESTAMP(`start_time`) < TIMESTAMP(NOW()) and TIMESTAMP(updated_at) < TIMESTAMP(`start_time`) or ( `period` = 'daily' AND `start_time` is NULL AND DATE(`updated_at`) != DATE(NOW()) )
      * @query hourly SELECT *, DATE(`updated_at`) as t FROM `ProxmoxAddon_SnapshotJob` where `period` = 'hourly' and TIMESTAMP(NOW()) >= TIMESTAMP( DATE_ADD(updated_at, INTERVAL `run_every` HOUR ))
      */
-    protected function process(InputInterface $input, OutputInterface $output, SymfonyStyle $io)
-    {
+    protected function process(InputInterface $input, OutputInterface $output, SymfonyStyle $io) {
         $io->title('Snapshots schedule: Starting');
         $productIds = ProductConfiguration::ofSetting('permissionSnapshotJob')
             ->where("value", "not like", '\"\"')
             ->pluck("product_id")
             ->all();
-        if (empty($productIds))
-        {
+        if (empty($productIds)) {
             $io->error("Scheduled Snapshot Jobs is not configured");
             return;
         }
-        $h        = (new Hosting())->getTable();
+        $h  = (new Hosting())->getTable();
         $sj =  (new SnapshotJob())->getTable();
         $entities = SnapshotJob::select("{$sj}.*")
             ->leftJoin($h, "{$h}.id", '=', "{$sj}.hosting_id")
@@ -80,16 +77,15 @@ class Snapshots extends Command
                         ")
             ->where("{$h}.domainstatus", "Active")
             ->whereIn("{$h}.packageid", $productIds);
-        $i        = 0;
+        $i = 0;
+        
+        
         /**
          * DAYName(NOW())        Friday
          * @var  SnapshotJob $entity
          */
-        foreach ($entities->get() as $entity)
-        {
-
-            try
-            {
+        foreach ($entities->get() as $entity) {
+            try {
                 $now = new \DateTime();
                 $today = $now->format("l");
                 if($entity->period == "daily" && ( $entity->days && !in_array($today, $entity->days) ) ){
@@ -103,8 +99,7 @@ class Snapshots extends Command
                     $entity->update(['updated_at' => date("Y-m-d H:i:s")]);
                     $output->writeln(sprintf("Snapshot job #%s has been synchronized", $entity->id));
                 }
-            }catch (\Exception $ex)
-            {
+            } catch (\Exception $ex) {
                 $io->error( $ex->getMessage());
             }
         }

+ 27 - 21
app/Jobs/Cloud/SnapshotVmJob.php

@@ -1,6 +1,4 @@
 <?php
-
-
 namespace ModulesGarden\ProxmoxAddon\App\Jobs\Cloud;
 
 
@@ -13,8 +11,8 @@ use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
 use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
 
-class SnapshotVmJob extends BaseJob
-{
+
+class SnapshotVmJob extends BaseJob {
 
     use ProductService;
 
@@ -23,31 +21,31 @@ class SnapshotVmJob extends BaseJob
      */
     private  $snapshotJob;
 
-    public function handle($text = null)
-    {
+    public function handle($text = null)  {
+        openlog("ProxmoxSnapshot", LOG_PID, LOG_SYSLOG);
+
         $this->initParams();
         $this->setHostingId($this->getWhmcsParamByKey("serviceid"));
         $this->initVm();
-        if ($this->isDone())
-        {
+        if ($this->isDone()) {
             return true;
-        }
-        elseif ($this->isTaskRunning())
-        {
+        } elseif ($this->isTaskRunning()) {
             //sleep
             $this->sleep(5);
             return false;
         }
-        $this->clean();
         $snapshot = new Snapshot();
         $snapshot->setApi($this->api());
         $snapshot->setPath(sl('Vm')->getVm()->getPath() . "/snapshot");
         $snapshot->setAttributes([
-            "name"        => $this->getSnapshotJob()->name."_".$this->model->id,
+            // Changed by Roland at 2021-08-28 because duplicate snappshot names which causes the error: TASK ERROR: snapshot name 'Secure_280' already used
+            // Added ' "_" . date("m") . "_" . date("d") . "_" . date("H"),' to make the snapshot-name more unique
+            "name"        => $this->getSnapshotJob()->name . "_" . $this->model->id . "_" . date("m") . "_" . date("d") . "_" . date("H"),
             "description" => $this->snapshotJob->description,
         ]);
-        if (!is_null($this->snapshotJob->vmstate ) && sl('Vm')->getVm() instanceof  Kvm)
-        {
+        
+        syslog(LOG_NOTICE,"Creating Snapshot for " . $this->getSnapshotJob()->name . "_" . $this->model->id . date("d") . "_" . date("H"));
+        if (!is_null($this->snapshotJob->vmstate ) && sl('Vm')->getVm() instanceof  Kvm) {
             $snapshot->setVmstate($this->snapshotJob->vmstate );
         }
         $taskId =  $snapshot->create();
@@ -55,6 +53,9 @@ class SnapshotVmJob extends BaseJob
         $this->putModelDataAndSave(["taskId" => $taskId, "node" => sl('Vm')->getVm()->getNode()]);
         //sleep
         $this->sleep(5);
+
+        $this->clean();
+        $this->sleep(25);
         return false;
     }
 
@@ -66,26 +67,31 @@ class SnapshotVmJob extends BaseJob
     }
 
     private function clean(){
+        syslog(LOG_NOTICE,"Snapshot Clean for " . $this->model->id );
         $limit = $this->getWhmcsConfigOption(ConfigurableOption::SNAPSHOTS, $this->configuration()->getSnapshotMaxFiles());
-        if($limit=="-1"){
+        if($limit=="-1") {
             return;
         }
-        if(!$limit || !is_numeric($limit)){
+        syslog(LOG_NOTICE,"   Checking Snapshot Limit (" . $limit . ") for " . $this->model->id );
+        if(!$limit || !is_numeric($limit)) {
             throw new \InvalidArgumentException("Snapshot limit cannot be empty");
         }
         $snapshotRepository = new SnapshotRepository();
         $snapshotRepository->setApi($this->api());
         $snapshotRepository->findByVm(sl('Vm')->getVm());
         $snapshotRepository->ignoreCurrent(true);
-        if($snapshotRepository->count() < $limit){
+        if($snapshotRepository->count() < $limit) {
             return;
         }
         $toDelete = (int) $snapshotRepository->count() - $limit;
-        foreach ($snapshotRepository->sortBySnaptime()->fetch() as $entity)
-        {
-            if($toDelete <=0){
+        syslog(LOG_NOTICE,"   Snapshots: Existing: " . $snapshotRepository->count() . "   Limit: " . $limit );
+        syslog(LOG_NOTICE,"   Number of Snapshots to delete: " . $toDelete );
+        foreach ($snapshotRepository->sortBySnaptime()->fetch() as $entity) {
+            syslog(LOG_NOTICE,"   Checking Snapshot: " . $entity->getName() . " (" . $entity->getPath() . ")" );
+            if($toDelete <=0) {
                 break;
             }
+            syslog(LOG_NOTICE,"   ->Delete Snapshot: " . $entity->getName() . " (" . $entity->getPath() . ")" );
             $entity->delete();
             $toDelete --;
         }

+ 26 - 54
app/Jobs/Vps/BaseJob.php

@@ -58,8 +58,7 @@ class BaseJob extends Job
      */
     protected $additionalMountPointService;
 
-    protected function initServices()
-    {
+    protected function initServices()  {
         $this->emailService     = new EmailService();
         $this->containerService = new ContainerService();
         $this->agentService = new AgentService();
@@ -68,8 +67,7 @@ class BaseJob extends Job
 
     }
 
-    public function initParams()
-    {
+    public function initParams()  {
         if (!$this->model->rel_id)
         {
             new \InvalidArgumentException(sprintf("Job model: #%s rel_id cannot be empty", $this->model->id));
@@ -85,15 +83,13 @@ class BaseJob extends Job
         return $this;
     }
 
-    protected function sleep($seconds = 60)
-    {
+    protected function sleep($seconds = 60)  {
         $this->model->setWaiting();
         $this->model->setRetryAfter(date("Y-m-d H:i:s", strtotime("+{$seconds} seconds")));
         $this->model->increaseRetryCount();
     }
 
-    protected function vmidExistInWhmcs($vmid)
-    {
+    protected function vmidExistInWhmcs($vmid)  {
         //vps
         $cfv   = 'tblcustomfieldsvalues';
         $cfn   = 'tblcustomfields';
@@ -104,8 +100,7 @@ class BaseJob extends Job
             ->where("{$cfn}.fieldname", "like", "vmid%")
             ->where("{$cfv}.value", $vmid)
             ->whereIn("{$h}.domainstatus", ['Active', "Suspended"]);
-        if ($query->count())
-        {
+        if ($query->count())  {
             return true;
         }
         //cloud
@@ -120,53 +115,39 @@ class BaseJob extends Job
         return false;
     }
 
-    protected function findFreeVmid($vmid)
-    {
-        for ($i = $vmid; $i <= 1000000; $i++)
-        {
-            if ($this->vmidExistInWhmcs($i))
-            {
+    protected function findFreeVmid($vmid)  {
+        for ($i = $vmid; $i <= 1000000; $i++) {
+            if ($this->vmidExistInWhmcs($i)) {
                 continue;
             }
-            try
-            {
+            try  {
                 $res = $this->api()->get("/cluster/nextid", ['vmid' => $i]);
-            }
-            catch (\Exception $ex)
-            {
+            } catch (\Exception $ex) {
                 continue;
             }
-            if ($res == $i)
-            {
+            if ($res == $i) {
                 return $i;
             }
         }
         throw new \Exception("Unable to obtain vmid");
     }
 
-    protected function isVmRange()
-    {
-        if (RangeVm::ofServerId($this->getWhmcsParamByKey("serverid"))->count())
-        {
+    protected function isVmRange(){
+        if (RangeVm::ofServerId($this->getWhmcsParamByKey("serverid"))->count()) {
             return true;
         }
         return Configuration::where("setting", "proxmoxVPSMinimumVMID")->count() > 0;
     }
 
-    protected function nextVmid()
-    {
+    protected function nextVmid() {
         $data = $this->api()->get("/cluster/nextid", []);
         $vmid = (int)$data ? (int)$data : 100;
         $vmid = $this->findFreeVmid($vmid);
-        if ($this->isVmRange())
-        {
+        if ($this->isVmRange()) {
             $rageVm = new RangeVmRepository($this->getWhmcsParamByKey('serverid'));
-            if (!$rageVm->has() && !$rageVm->getMin())
-            {
+            if (!$rageVm->has() && !$rageVm->getMin()) {
                 return $vmid;
-            }
-            else
-            {
+            } else  {
                 if (!$rageVm->getMax() && $rageVm->getMin())
                 {
                     $from = (int)$rageVm->getMin();
@@ -300,23 +281,18 @@ class BaseJob extends Job
         return $task->getExitstatus() && $task->getExitstatus() != "OK";
     }
 
-    protected function failed($error)
-    {
+    protected function failed($error) {
 
-        if ((int)$this->model->retry_count != 21)
-        {
+        if ((int)$this->model->retry_count != 21) {
             return;
         }
-        if (!preg_match("/Create/", $this->model->job) || preg_match("/Clone/", $this->model->job))
-        {
+        if (!preg_match("/Create/", $this->model->job) || preg_match("/Clone/", $this->model->job)) {
             return;
         }
         //create new entery on to do list
-        if ($this->configuration()->isToDoList())
-        {
+        if ($this->configuration()->isToDoList())  {
             $title = sprintf('Creation Failed - Service ID: %s', $this->getWhmcsParamByKey('serviceid'));
-            if (ToDoList::ofTitle($title)->pending()->count())
-            {
+            if (ToDoList::ofTitle($title)->pending()->count())  {
                 return;
             }
             $entity = new ToDoList();
@@ -364,21 +340,17 @@ class BaseJob extends Job
     /**
      * @return \ModulesGarden\ProxmoxAddon\App\Models\Job:
      */
-    protected function getParentModel()
-    {
-        if (is_null($this->model->parent_id))
-        {
+    protected function getParentModel() {
+        if (is_null($this->model->parent_id)) {
             throw new \InvalidArgumentException("The Parent Id is not valid");
         }
-        if ($this->parent)
-        {
+        if ($this->parent) {
             return $this->parent;
         }
         return $this->parent = \ModulesGarden\ProxmoxAddon\App\Models\Job::ofId($this->model->parent_id)->firstOrFail();
     }
 
-    protected function getParentModelData()
-    {
+    protected function getParentModelData() {
         return unserialize($this->getParentModel()->data);
     }
 

+ 36 - 21
app/Jobs/Vps/SnapshotVmJob.php

@@ -1,9 +1,6 @@
 <?php
-
-
 namespace ModulesGarden\ProxmoxAddon\App\Jobs\Vps;
 
-
 use MGProvision\Proxmox\v2\models\Kvm;
 use MGProvision\Proxmox\v2\models\Snapshot;
 use MGProvision\Proxmox\v2\repository\SnapshotRepository;
@@ -11,8 +8,7 @@ use ModulesGarden\ProxmoxAddon\App\Models\SnapshotJob;
 use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Enum\Vps\ConfigurableOption;
 
-class SnapshotVmJob extends BaseJob
-{
+class SnapshotVmJob extends BaseJob {
 
     use ProductService;
 
@@ -21,37 +17,50 @@ class SnapshotVmJob extends BaseJob
      */
     private  $snapshotJob;
 
-    public function handle($text = null)
-    {
+    public function handle($text = null)  {
+        openlog("ProxmoxSnapshot", LOG_PID,LOG_SYSLOG);
+        syslog(LOG_NOTICE,"Snapshot Create for " . $this->model->id );
         $this->initParams();
         $this->setHostingId($this->getWhmcsParamByKey("serviceid"));
-        if ($this->isDone())
-        {
+        if ($this->isDone()) {
             return true;
-        }
-        elseif ($this->isTaskRunning())
-        {
+        } elseif ($this->isTaskRunning())  {
             //sleep
             $this->sleep(5);
             return false;
         }
-        $this->clean();
         $snapshot = new Snapshot();
         $snapshot->setApi($this->api());
         $snapshot->setPath($this->vm()->getPath() . "/snapshot");
         $snapshot->setAttributes([
-            "name"        => $this->getSnapshotJob()->name."_".$this->model->id,
+    	    // Changed by Roland at 2021-08-28 because duplicate snappshot names which causes the error: TASK ERROR: snapshot name 'Secure_280' already used
+    	    // Added ' "_" . date("m") . "_" . date("d") . "_" . date("H"),' to make the snapshot-name more unique
+            "name"        => $this->getSnapshotJob()->name . "_" . $this->model->id . "_" . date("m") . "_" . date("d") . "_" . date("H"),
             "description" => $this->snapshotJob->description,
         ]);
-        if (!is_null($this->snapshotJob->vmstate ) && $this->vm() instanceof  Kvm)
-        {
+        syslog(LOG_NOTICE,"   Creating Snapshot for " . $this->getSnapshotJob()->name . "_" . $this->model->id . "_" . date("m") . "_" . date("d") . "_" . date("H"));
+        if (!is_null($this->snapshotJob->vmstate ) && $this->vm() instanceof  Kvm) {
             $snapshot->setVmstate($this->snapshotJob->vmstate );
         }
-        $taskId =  $snapshot->create();
+        try {
+    	    $taskId =  $snapshot->create();
+        } catch(\Exception $ex) {
+    	    $message = $ex->getMessage();
+	    if (strpos($message,"snapshot") === false && strpos($message,"already") === false && strpos($message,"used") === false ) {
+    	        throw $ex;
+    	    }
+        }
+
         //save task id
         $this->putModelDataAndSave(["taskId" => $taskId, "node" => $this->vm()->getNode()]);
+        
         //sleep
-        $this->sleep(5);
+        $this->sleep(25);
+        $this->clean();
+	$this->sleep(5);
+
+	$stackTrace = implode("\n", debug_backtrace());
+	syslog(LOG_NOTICE,"Stack Trace " . $stackTrace );
         return false;
     }
 
@@ -62,8 +71,10 @@ class SnapshotVmJob extends BaseJob
         return $this->snapshotJob = SnapshotJob::findOrFail($this->getModelData()['snapshotJobId']);
     }
 
-    private function clean(){
+    private function clean() {
+        syslog(LOG_NOTICE,"Snapshot Clean for " . $this->model->id );
         $limit = $this->getWhmcsConfigOption(ConfigurableOption::SNAPSHOTS, $this->configuration()->getSnapshotMaxFiles());
+        syslog(LOG_NOTICE,"   Checking Snapshot Limit (" . $limit . ") for " . $this->model->id );
         if($limit=="-1"){
             return;
         }
@@ -78,11 +89,15 @@ class SnapshotVmJob extends BaseJob
             return;
         }
         $toDelete = (int) $snapshotRepository->count() - $limit;
-        foreach ($snapshotRepository->sortBySnaptime()->fetch() as $entity)
-        {
+        syslog(LOG_NOTICE,"   Snapshots: Existing: " . $snapshotRepository->count() . "   Limit: " . $limit );
+        syslog(LOG_NOTICE,"   Number of Snapshots to delete: " . $toDelete );
+        
+        foreach ($snapshotRepository->sortBySnaptime()->fetch() as $entity) {
+    	    syslog(LOG_NOTICE,"   Checking Snapshot: " . $entity->getName() . " (" . $entity->getPath() . ")" );
             if($toDelete <=0){
                 break;
             }
+            syslog(LOG_NOTICE,"   ->Delete Snapshot: " . $entity->getName() . " (" . $entity->getPath() . ")" );
             $entity->delete();
             $toDelete --;
         }

+ 2 - 4
app/Models/Job.php

@@ -23,10 +23,8 @@ class Job extends \ModulesGarden\ProxmoxAddon\Core\Queue\Models\Job
         return $query->where("job", $job . '@handle');
     }
 
-    public function scopeOfJobs($query, $jobs)
-    {
-        foreach ($jobs as &$job)
-        {
+    public function scopeOfJobs($query, $jobs)  {
+        foreach ($jobs as &$job) {
             $job .= '@handle';
         }
         return $query->whereIn("job", $jobs);

+ 2 - 4
app/Models/SnapshotJob.php

@@ -21,8 +21,7 @@ use ModulesGarden\ProxmoxAddon\Core\Models\ExtendedEloquentModel;
  * @property string $created_at
  * @method static $this ofHostingId($hostingId)
  */
-class SnapshotJob extends ExtendedEloquentModel
-{
+class SnapshotJob extends ExtendedEloquentModel {
 
     /** @var string */
     protected $table = 'SnapshotJob';
@@ -37,8 +36,7 @@ class SnapshotJob extends ExtendedEloquentModel
         'days' => 'array',
     ];
 
-    public function scopeOfHostingId($query, $hostingId)
-    {
+    public function scopeOfHostingId($query, $hostingId) {
         return $query->where("hosting_id", $hostingId);
     }
 

+ 1 - 2
app/Services/Vm.php

@@ -8,8 +8,7 @@ use MGProvision\Proxmox\v2\models\Kvm;
 use MGProvision\Proxmox\v2\models\Lxc;
 use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
 
-class Vm
-{
+class Vm {
     /**
      * @var Kvm|Lxc
      */

+ 1 - 2
core/CommandLine/CronManager.php

@@ -2,7 +2,6 @@
 
 namespace ModulesGarden\ProxmoxAddon\Core\CommandLine;
 
-class CronManager extends Application
-{
+class CronManager extends Application {
     protected $dir = 'Cron';
 }

+ 25 - 26
core/Queue/Manager.php

@@ -5,8 +5,7 @@ namespace ModulesGarden\ProxmoxAddon\Core\Queue;
 use ModulesGarden\ProxmoxAddon\Core\DependencyInjection\DependencyInjection;
 use ModulesGarden\ProxmoxAddon\Core\Queue\Services\Log;
 
-class Manager
-{
+class Manager {
     /**
      * @var Models\Job
      */
@@ -21,36 +20,39 @@ class Manager
      * Manager constructor.
      * @param Models\Job $job
      */
-    public function __construct(\ModulesGarden\ProxmoxAddon\Core\Queue\Models\Job $job)
-    {
+    public function __construct(\ModulesGarden\ProxmoxAddon\Core\Queue\Models\Job $job) {
         $this->job  = $job;
         $this->log  = new Log($this->job);
     }
 
     /**
-     *
+     *  snapshot name 'Snapshot_320_08_30_02' already used
      */
-    public function fire()
-    {
-        try
-        {
+    public function fire(){
+        try  {
             $this->job->setRunning();
 
             $ret    = $this->resolveAndFire($this->job->job, $this->job->data);
-            if($ret !== false)
-            {
+            if($ret !== false) {
                 $this->job->setFinished();
             }
-        }
-        catch(\Exception $ex)
-        {
-            //Set error in job
-            $this->job->setError();
-            $this->job->setRetryAfter(date('Y-m-d H:i:s', strtotime('+ 60 seconds')));
-            $this->job->increaseRetryCount();
+        } catch(\Exception $ex) {
+    	    $message = $ex->getMessage();
+    	    if (strpos($message,"snapshot") !== false && strpos($message,"already") !== false && strpos($message,"used") !== false) {
+    		$this->job->setFinished();
+    	    
+    		//add log message
+        	$this->log->error($ex->getMessage(), debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
+    	    } else {
+        	//Set error in job
+                $this->job->setError();
+	        $this->job->setRetryAfter(date('Y-m-d H:i:s', strtotime('+ 60 seconds')));
+    	        $this->job->increaseRetryCount();
 
-            //add log message
-            $this->log->error($ex->getMessage(), debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
+        	//add log message
+        	$this->log->error($ex->getMessage(), debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
+    	    }
+        
         }
     }
 
@@ -59,8 +61,7 @@ class Manager
      * @param $data
      * @return mixed
      */
-    protected function resolveAndFire($job, $data)
-    {
+    protected function resolveAndFire($job, $data)  {
         list($class, $method)   = $this->parseJob($job);
         $instance               = $this->resolve($class);
 
@@ -71,8 +72,7 @@ class Manager
      * @param $class
      * @return mixed
      */
-    protected function resolve($class)
-    {
+    protected function resolve($class) {
         return new $class($this->job, $this->log);
     }
 
@@ -82,8 +82,7 @@ class Manager
      * @param  string  $job
      * @return array
      */
-    protected function parseJob($job)
-    {
+    protected function parseJob($job)  {
         $segments = explode('@', $job);
         return count($segments) > 1 ? $segments : array($segments[0], 'fire');
     }

+ 1 - 2
cron/cron.php

@@ -11,8 +11,7 @@ require_once $modulePath . DS . 'core' . DS . 'Bootstrap.php';
 ini_set('max_execution_time', 0);
 
 $argList = $argv ? $argv : $_SERVER['argv'];
-if (count($argList) === 0)
-{
+if (count($argList) === 0) {
     $argList = [__FILE__];
 }