Untitled
unknown
plain_text
2 years ago
6.8 kB
3
Indexable
<?php namespace App\Jobs; use App\Events\InstanceEvent; use App\Models\Instance; use App\Models\Project; use App\Models\PublicIpv4; use App\Models\User; use Confirm\ZabbixApi\ZabbixApi; use Illuminate\Bus\Batchable; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Log; use Popson\CloudStack\Clients\UserClient; use Popson\CloudStack\Model\AsyncJob; use Popson\CloudStack\Model\VirtualMachine; use Popson\CloudStack\Services\User\AddressApiService; use Popson\CloudStack\Services\User\AsyncJobApiService; use Popson\CloudStack\Services\User\FirewallApiService; use Popson\CloudStack\Services\User\NatApiService; use Popson\CloudStack\Services\User\VirtualMachineApiService; class AssignIpAddressJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Batchable; protected User $user; protected PublicIpv4 $ipv4; protected AsyncJob $virtualMachineJob; protected string $networkType; protected string $isSourceIpUsed; public int|float $timeout = 60 * 15; // 15 minutes public bool $failOnTimeout = true; public function __construct(User $user, PublicIpv4 $ipv4, AsyncJob $virtualMachineJob, string $networkType, $isSourceIpUsed) { $this->user = $user; $this->ipv4 = $ipv4; $this->virtualMachineJob = $virtualMachineJob; $this->networkType = $networkType; $this->isSourceIpUsed = $isSourceIpUsed; } public function handle() { // PublicIpv4 Migrated from PublicIpv4::query() to Polymorphic Relation // So instance_id replaced with public_ipv4able_id $instance = Instance::query()->findOrFail($this->ipv4->public_ipv4able_id); $project = Project::find($this->ipv4->project_id); $os_family = $instance?->os_version_offering?->osVersion?->os?->family??'Linux'; app()->singleton(UserClient::class, function () { return new UserClient(config('services.cloudstack'), $this->user); }); $asyncJobApiService = app(AsyncJobApiService::class); $firewallApiService = app(FirewallApiService::class); $addressApiService = app(AddressApiService::class); $natApiService = app(NatApiService::class); $virtualMachineApiService = app(VirtualMachineApiService::class); $vm = $this->waitForTheVmToBeCreated($asyncJobApiService); if ($vm->password_enabled) { $instance->update([ 'password_enabled' => true, 'encrypted_password' => Crypt::encryptString($vm->password ?? '<password not set>'), ]); } if(empty($this->ipv4->ipv4_id)){ event(new InstanceEvent($this->user->id, 'vm-ready', "Instance is ready...")); return; } $this->waitForIpv4GetAllocated($this->ipv4, $addressApiService); if($this->networkType == 'Isolated' && $this->isSourceIpUsed){ $this->batch()->add(new CreateFirewallRuleJob($this->user, $this->ipv4->ipv4_id, $os_family, $instance)); } Log::debug('Strategy:: '. $this->ipv4->strategy); $ipv4 = $this->ipv4; $user = $this->user; $this->batch()->add((function() use($project, $natApiService, $vm, $firewallApiService, $ipv4, $user, $asyncJobApiService){ sleep(30); if ($ipv4->strategy === 'static') { $natApiService->enableStaticNat([ 'ipaddressid' => $ipv4->ipv4_id, 'virtualmachineid' => $ipv4->public_ipv4able_id, 'networkid' => $ipv4->network_id, 'projectid' => $project->id, 'domainid' => $project->account->domain_id, 'account' => $project->account->username, 'vmguestip' => $vm->nic?->first()->ipaddress, ]); event(new InstanceEvent($user->id, 'vm-ready', "Static nat enabled successfully!")); } else { foreach ([80, 443, 22] as $port) { $rule = [ 'ipaddressid' => $ipv4->ipv4_id, 'privateport' => $port, 'publicport' => $port, 'virtualmachineid' => $ipv4->public_ipv4able_id, 'networkid' => $ipv4->network_id, 'openfirewall' => false, 'privateendport' => $port, 'publicendport' => $port, ]; $job = $firewallApiService->createPortForwardingRule($rule + ['protocol' => 'tcp']); $this->followJob($asyncJobApiService, $job); $job = $firewallApiService->createPortForwardingRule($rule + ['protocol' => 'udp']); $this->followJob($asyncJobApiService, $job); } event(new InstanceEvent($user->id, 'vm-ready', "Port forwarding rules created successfully!")); } })); } protected function followJob(AsyncJobApiService $asyncJobApiService, AsyncJob $job) { $retries = 10; while ($retries-- > 0) { $result = $asyncJobApiService->queryAsyncJobResult(['jobid' => $job->jobId]); if (!$result->finished()) sleep(3); else return; } $this->release(30); } protected function waitForTheVmToBeCreated(mixed $asyncJobApiService): VirtualMachine { // wait for the vm to start while (true) { /** @var \Popson\CloudStack\Model\AsyncJobResult $result */ $result = $asyncJobApiService->queryAsyncJobResult(['jobid' => $this->virtualMachineJob->jobId]); if ($result->finished()) { return new VirtualMachine($result->job_result['virtualmachine'] ?? []); } sleep(5); } } private function waitForIpv4GetAllocated(PublicIpv4 $ipv4, AddressApiService $addressApiService) { while (true) { $publicIpAddresses = $addressApiService->listPublicIpAddresses([ 'id' => $ipv4->ipv4_id, 'allocatedonly' => false ]); /** @var \Popson\CloudStack\Model\PublicIpAddress $publicIpAddress */ $publicIpAddress = $publicIpAddresses->first(); if ($publicIpAddress->state === 'Allocated') { return; } sleep(2); } } }
Editor is loading...