| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- <?php
- /* * ********************************************************************
- * ProxmoxVPS product developed. (Apr 19, 2019)
- * *
- *
- * CREATED BY MODULESGARDEN -> http://modulesgarden.com
- * CONTACT -> contact@modulesgarden.com
- *
- *
- * This software is furnished under a license and may be used and copied
- * only in accordance with the terms of such license and with the
- * inclusion of the above copyright notice. This software or any other
- * copies thereof may not be provided or otherwise made available to any
- * other person. No title to and ownership of the software is hereby
- * transferred.
- *
- *
- * ******************************************************************** */
- namespace ModulesGarden\ProxmoxAddon\App\Cron;
- use MGProvision\Proxmox\v2\VmFactory;
- use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\NetworkRate\MaximumVmRateJob;
- use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\NetworkRate\MinimumVmRateJob;
- use ModulesGarden\ProxmoxAddon\App\Models\ModuleSetting;
- use ModulesGarden\ProxmoxAddon\App\Models\ProductConfiguration;
- use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
- use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Hosting;
- use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
- use ModulesGarden\ProxmoxAddon\App\Services\Utility;
- use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
- use ModulesGarden\ProxmoxAddon\Core\Api\Whmcs;
- use ModulesGarden\ProxmoxAddon\Core\CommandLine\Command;
- use ModulesGarden\ProxmoxAddon\Core\CommandLine\Hypervisor;
- use ModulesGarden\ProxmoxAddon\Core\Models\Whmcs\Admins;
- use ModulesGarden\ProxmoxAddon\Core\Models\Whmcs\Server;
- use ModulesGarden\ProxmoxAddon\Core\UI\Traits\WhmcsParams;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Console\Style\SymfonyStyle;
- use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
- use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
- use ModulesGarden\ProxmoxAddon\App\Enum\Vps;
- use ModulesGarden\ProxmoxAddon\App\Enum\Cloud;
- /**
- * Description of Users
- *
- * @author Pawel Kopec <pawelk@modulesgardne.com>
- */
- class UsageUpdate extends Command
- {
- use WhmcsParams;
- use ProductService;
- use ApiService;
- /**
- * Command name
- * @var string
- */
- protected $name = 'update-server-usage';
- /**
- * Command description
- * @var string
- */
- protected $description = 'Updating Disk & Bandwidth Usage Stat';
- /**
- * Command help text
- * @var string
- */
- protected $help = '';
- protected function process(InputInterface $input, OutputInterface $output, SymfonyStyle $io)
- {
- $io->title('Update Server Usage: Starting');
- if (!function_exists('ModuleBuildParams'))
- {
- require_once ROOTDIR . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . "modulefunctions.php";
- }
- //Update hosting date 0000-00-00 00:00:00 to now
- $this->updateEmptyLastUpdate();
- //init bandwidth reset date to run daily cron job
- $this->updateEmptyBandwidthResetDate();
- //Run daily
- if($this->isDailyJob()){
- //Reset BW
- $this->resetBandwidth();
- $this->unsuspendOverageUsage();
- $this->endDailyJob();
- }
- //Update hosting bandwidth
- $h = (new Hosting())->getTable();
- $s = (new Server())->getTable();
- $hostings = Hosting::select("{$h}.id", "{$h}.packageid", "{$h}.lastupdate", "{$h}.bwusage", "{$h}.bwlimit", "{$h}.regdate")
- ->rightJoin($s, "{$h}.server", '=', "{$s}.id")
- ->where("{$h}.domainstatus", "Active")
- ->whereIn("{$s}.type", ["proxmoxVPS", "ProxmoxCloudVps"])
- ->orderBy("{$h}.server");
- $i = 0;
- /**
- * @var Hosting $hosting
- */
- foreach ($hostings->get() as $hosting)
- {
- $i++;
- $output->writeln(sprintf("Synchronize hosting: %s", $hosting->id));
- try
- {
- $params = \ModuleBuildParams($hosting->id);
- sl("whmcsParams")->setParams($params);
- unset($this->vm, $this->api, $this->configuration, $this->productId, $this->hostingId);
- $this->api();
- if ($params['moduletype'] == "proxmoxVPS"){
- if (!$params['customfields'][Vps\CustomField::VMID])
- {
- throw new \Exception("Custom Field \"vmid\" is empty");
- }
- if (!$params['customfields'][Vps\CustomField::NODE])
- {
- throw new \Exception("Custom Field \"node\" is empty");
- }
- $status = $this->vm()->status();
- $rrData = $this->vm()->rrdData(["timeframe" => "hour", "cf" => "AVERAGE"]);
- $bandwidth = 0;
- foreach ($rrData as $k => $rrd)
- {
- if ($rrd['time'] < $hosting->getLastUpdate()->getTimestamp())
- {
- continue;
- }
- $total = ((float)$rrd['netin'] + (float)$rrd['netout']);
- if ($total > 1000000000)
- {
- $total = 0;
- }
- $bandwidth += ($total * 57.3);
- $bandwithTime = date("Y-m-d H:i:s", $rrd['time']);
- }
- if (!$bandwithTime)
- {
- continue;
- }
- $diskUsage = (int)$status['disk'];
- Utility::unitFormat($bandwidth, "bytes", "mb");
- Utility::unitFormat($diskUsage, "bytes", "mb");
- $hosting->bwusage += $bandwidth;
- $hosting->update(
- [
- "diskusage" => $diskUsage,
- "bwusage" => $hosting->bwusage,
- "lastupdate" => $bandwithTime
- ]
- );
- $rate = null;
- if ($this->getWhmcsConfigOption(Vps\ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()) && $this->getWhmcsConfigOption(Vps\ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()) !="-1")
- {
- $rate = $this->getWhmcsConfigOption(Vps\ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate());
- }
- //Minimum VM Network Rate
- if ($hosting->isBandwidthOverageUsage() && $this->configuration()->getMinimumRate() &&
- $this->vm()->getNetworkDevices($this->configuration()->getBridge())[0] &&
- $this->vm()->getNetworkDevices($this->configuration()->getBridge())[0]->getRate() != $this->configuration()->getMinimumRate())
- {
- queue(MinimumVmRateJob::class, [], null, "hosting", $hosting->id);
- //Maximum VM Network Rate
- } else if (!$hosting->isBandwidthOverageUsage() &&
- $this->configuration()->getMinimumRate() &&
- $this->vm()->getNetworkDevices($this->configuration()->getBridge())[0] &&
- $this->vm()->getNetworkDevices($this->configuration()->getBridge())[0]->getRate() != $rate) {
- queue(MaximumVmRateJob::class, [], null, "hosting", $hosting->id);
- }
- //Suspend On Bandwidth Overage
- if ($this->configuration()->isSuspendOnBandwidthOverage() && $hosting->domainstatus != "Suspended" && $hosting->isBandwidthOverageUsage())
- {
- $localApi = new Whmcs(new Admins());
- $localApi->call("modulesuspend", ["accountid" => $hosting->id, "suspendreason" => "Overage Usage"]);
- $output->writeln(sprintf("Hosting: %s has been suspended, reanson: Overage Usage", $hosting->id));
- }
- $output->writeln(sprintf("Hosting: %s has been synchronized, bandwith usage: %s MB", $hosting->id, $bandwidth));
- }
- if ($params['moduletype'] == "ProxmoxCloudVps"){
- $bandwidth = 0;
- $diskUsage = 0;
- $rate = null;
- if ($this->getWhmcsConfigOption(Cloud\ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()) && $this->getWhmcsConfigOption(Cloud\ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()) !="-1")
- {
- $rate = $this->getWhmcsConfigOption(Cloud\ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate());
- }
- $vservers = VmModel::ofHostingId($hosting->id);
- foreach ($vservers->get() as $vserver)
- {
- $vm = (new VmFactory())->fromVmModel($vserver);
- $status = $vm->status();
- $diskUsage += (int)$status['disk'];
- $rrData = $vm->rrdData(["timeframe" => "hour", "cf" => "AVERAGE"]);
- foreach ($rrData as $k => $rrd)
- {
- if ($rrd['time'] < $hosting->getLastUpdate()->getTimestamp())
- {
- continue;
- }
- $total = ((float)$rrd['netin'] + (float)$rrd['netout']);
- if ($total > 1000000000)
- {
- $total = 0;
- }
- $bandwidth += ($total * 57.3);
- $bandwithTime = date("Y-m-d H:i:s", $rrd['time']);
- }
- if (!$bandwithTime)
- {
- continue;
- }
- //Minimum VM Network Rate
- if ($hosting->isBandwidthOverageUsage() && $this->configuration()->getMinimumRate() &&
- $vm->getNetworkDevices($this->configuration()->getBridge())[0] &&
- $vm->getNetworkDevices($this->configuration()->getBridge())[0]->getRate() != $this->configuration()->getMinimumRate())
- {
- queue(\ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\NetworkRate\MinimumVmRateJob::class, [], null, "hosting", $hosting->id, $vserver->id);
- //Maximum VM Network Rate
- } else if (!$hosting->isBandwidthOverageUsage() &&
- $this->configuration()->getMinimumRate() &&
- $vm->getNetworkDevices($this->configuration()->getBridge())[0] &&
- $vm->getNetworkDevices($this->configuration()->getBridge())[0]->getRate() != $rate) {
- queue(\ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\NetworkRate\MaximumVmRateJob::class, [], null, "hosting", $hosting->id, $vserver->id);
- }
- }
- Utility::unitFormat($bandwidth, "bytes", "mb");
- Utility::unitFormat($diskUsage, "bytes", "mb");
- $hosting->bwusage += $bandwidth;
- $hosting->update(
- [
- "diskusage" => $diskUsage,
- "bwusage" => $hosting->bwusage,
- "lastupdate" => $bandwithTime
- ]
- );
- //Suspend On Bandwidth Overage
- if ($this->configuration()->isSuspendOnBandwidthOverage() && $hosting->domainstatus != "Suspended" && $hosting->isBandwidthOverageUsage())
- {
- $localApi = new Whmcs(new Admins());
- $localApi->call("modulesuspend", ["accountid" => $hosting->id, "suspendreason" => "Overage Usage"]);
- $output->writeln(sprintf("Hosting: %s has been suspended, reanson: Overage Usage", $hosting->id));
- }
- $output->writeln(sprintf("Hosting: %s has been synchronized, bandwith usage: %s MB", $hosting->id, $bandwidth));
- }
- }
- catch (\Exception $ex)
- {
- $msg = $ex->getMessage();
- if ($hosting)
- {
- $msg = sprintf("Hosting Id #%s, %s", $hosting->id, $ex->getMessage());
- }
- $io->error($msg);
- }
- (new Hypervisor($this->getName(), $input->getOptions()))
- ->ping();
- }
- $output->writeln("");
- $io->success([
- sprintf("Synchronize hostings: %s Entries Processed.", $i),
- "Update Server Usage: Done"
- ]);
- }
- private function updateEmptyLastUpdate()
- {
- $h = 'tblhosting';
- Hosting::ofProxmoxVpsAndProxmoxCloud()
- ->where("{$h}.domainstatus", 'Active')
- ->where("{$h}.lastupdate", "0000-00-00 00:00:00")
- ->update(["{$h}.lastupdate" => Hosting::raw('NOW()')]);
- return $this;
- }
- private function updateEmptyBandwidthResetDate()
- {
- if (ModuleSetting::bandwidthResetDate()->count())
- {
- return $this;
- }
- $setting = new ModuleSetting();
- $setting->setting = "bandwidthResetDate";
- $setting->value = date("Y-m-d H:i:s");
- $setting->save();
- return $this;
- }
- private function isDailyJob(){
- return ModuleSetting::bandwidthResetDate()->whereRaw("DATE(`value`) <= DATE_SUB(NOW(),INTERVAL 24 HOUR) ")->count() > 0;
- }
- private function endDailyJob(){
- $setting = ModuleSetting::bandwidthResetDate()->firstOrFail();
- // save last rest bandwidth date
- $setting->value = date("Y-m-d H:i:s");
- $setting->save();
- }
- private function resetBandwidth()
- {
- $productIds = ProductConfiguration::ofSetting('resetUsageFirstDayOfMonth')
- ->where("value", "like", '\"on\"')
- ->pluck("product_id")
- ->all();
- $h = 'tblhosting';
- Hosting::ofProxmoxVpsAndProxmoxCloud()
- ->whereIn("{$h}.domainstatus", ["Active", "Suspended"])
- ->whereNotIn("{$h}.packageid", $productIds)
- ->whereRaw(" DAY({$h}.regdate) = DAY(NOW()) ")
- ->update(["{$h}.bwusage" => 0]);
- //Reset Usage First Day Of Month
- if(date("d")=="01"){
- Hosting::ofProxmoxVpsAndProxmoxCloud()
- ->whereIn("{$h}.domainstatus", ["Active", "Suspended"])
- ->whereIn("{$h}.packageid", $productIds)
- ->update(["{$h}.bwusage" => 0]);
- }
- }
- private function unsuspendOverageUsage(){
- //get products where option suspendOnBandwidthOverage is on
- $productIds = ProductConfiguration::ofSetting('suspendOnBandwidthOverage')
- ->where("value", "like", '\"on\"')
- ->pluck("product_id")
- ->all();
- if(empty( $productIds)){
- return;
- }
- //get hosting where domainstatus is Suspended and registration day is now and suspendreason is Overage Usage
- $h = (new Hosting())->getTable();
- $s = (new Server())->getTable();
- $hostings = Hosting::select("{$h}.id", "{$h}.packageid", "{$h}.lastupdate", "{$h}.bwusage", "{$h}.bwlimit", "{$h}.regdate")
- ->rightJoin($s, "{$h}.server", '=', "{$s}.id")
- ->where("{$h}.domainstatus", "Suspended")
- ->where("{$h}.suspendreason", "Overage Usage")
- ->whereIn("{$h}.packageid", $productIds)
- ->where("{$s}.type", "proxmoxVPS")
- ->whereRaw(" DAY({$h}.regdate) = DAY(NOW()) ");
- $i = 0;
- /**
- * @var Hosting $hosting
- */
- foreach ($hostings->get() as $hosting)
- {
- try{
- $localApi = new Whmcs(new Admins());
- $localApi->call("ModuleUnsuspend", ["accountid" => $hosting->id]);
- } catch (\Exception $ex)
- {
- echo sprintf("Error: %s, Hosting ID: #%s",$ex->getMessage(), $hosting->id);
- }
- }
- }
- }
|