Skip to content

Commit

Permalink
[3.0-SAFE] add ISO imports
Browse files Browse the repository at this point in the history
  • Loading branch information
ericwang401 committed Jun 20, 2023
1 parent 28cef99 commit b329f4b
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 84 deletions.
18 changes: 18 additions & 0 deletions app/Data/Node/Storage/IsoData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Convoy\Data\Node\Storage;

use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Spatie\LaravelData\Data;

class IsoData extends Data
{
public function __construct(
public string $file_name,
public int $size,
public CarbonInterface $created_at,
)
{
}
}
25 changes: 20 additions & 5 deletions app/Http/Controllers/Admin/Nodes/IsoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,27 @@ public function index(Node $node, Request $request)

public function store(StoreIsoRequest $request, Node $node)
{
$checksumData = (bool) $request->checksum_algorithum ? ChecksumData::from([
'algorithm' => ChecksumAlgorithm::from($request->checksum_algorithum),
'checksum' => $request->checksum,
]) : null;
$shouldDownload = $request->boolean('should_download');

$iso = $this->isoService->create($node, $request->name, $request->file_name, $request->link, $checksumData, $request->hidden);
if($shouldDownload) {
$checksumData = (bool) $request->checksum_algorithum ? ChecksumData::from([
'algorithm' => ChecksumAlgorithm::from($request->checksum_algorithum),
'checksum' => $request->checksum,
]) : null;

$iso = $this->isoService->download($node, $request->name, $request->file_name, $request->link, $checksumData, $request->hidden);
} else {
$isoFromProxmox = $this->isoService->getIso($node, $request->file_name);

$iso = $node->isos()->create([
'is_successful' => true,
'name' => $request->name,
'file_name' => $request->file_name,
'size' => $isoFromProxmox->size,
'hidden' => $request->boolean('hidden'),
'completed_at' => now(),
]);
}

return fractal($iso, new IsoTransformer)->respond();
}
Expand Down
2 changes: 2 additions & 0 deletions app/Http/Controllers/Admin/Nodes/NodeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public function updateCoterm(UpdateCotermRequest $request, Node $node)
$payload['coterm_token'] = $creds['token'];
}



$node->update($payload);

return new JsonResponse([
Expand Down
28 changes: 24 additions & 4 deletions app/Http/Requests/Admin/Nodes/Isos/StoreIsoRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace Convoy\Http\Requests\Admin\Nodes\Isos;

use Convoy\Models\Node;
use Illuminate\Validation\Validator;
use Convoy\Http\Requests\FormRequest;
use Convoy\Services\Nodes\Isos\IsoService;
use Convoy\Enums\Helpers\ChecksumAlgorithm;
use Convoy\Models\ISO;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;

class StoreIsoRequest extends FormRequest
Expand All @@ -14,14 +17,31 @@ public function rules(): array
$isoRules = ISO::getRules();

$rules = [
'should_download' => 'required|boolean',
'name' => $isoRules['name'],
'file_name' => $isoRules['file_name'],
'hidden' => $isoRules['hidden'],
'link' => 'required|url|max:191',
'checksum_algorithm' => ['sometimes', new Enum(ChecksumAlgorithm::class)],
'checksum' => 'required_with:checksum_algorithm|string|max:191',
'link' => 'required_if:should_download,1|url|max:191|exclude_if:should_download,0',
'checksum_algorithm' => ['sometimes', new Enum(ChecksumAlgorithm::class), 'exclude_if:should_download,0'],
'checksum' => 'required_with:checksum_algorithm|string|max:191|exclude_if:should_download,0',
];

return $rules;
}

public function withValidator(Validator $validator)
{

if (!$this->boolean('should_download')) {
$validator->after(function (Validator $validator) {
$node = $this->parameter('node', Node::class);

$iso = app(IsoService::class)->getIso($node, $this->input('file_name'));

if (is_null($iso)) {
$validator->errors()->add('file_name', 'This ISO doesn\'t exist.');
}
});
}
}
}
13 changes: 0 additions & 13 deletions app/Http/Requests/Admin/Nodes/UpdateNodeRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,6 @@

class UpdateNodeRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules(): array
{
$rules = Node::getRulesForUpdate($this->parameter('node', Node::class));
Expand Down
13 changes: 12 additions & 1 deletion app/Models/ISO.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Convoy\Models;

use Illuminate\Support\Str;
use Convoy\Casts\MebibytesToAndFromBytes;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class ISO extends Model
Expand All @@ -14,11 +16,11 @@ class ISO extends Model

protected $casts = [
'is_successful' => 'boolean',
'size' => MebibytesToAndFromBytes::class,
'hidden' => 'boolean',
];

public static $validationRules = [
'uuid' => 'required|uuid',
'node_id' => 'required|integer|exists:nodes,id',
'is_successful' => 'sometimes|boolean',
'name' => 'required|string|min:1|max:40',
Expand All @@ -32,4 +34,13 @@ public function node()
{
return $this->belongsTo(Node::class);
}

protected static function boot()
{
parent::boot();

static::creating(function (ISO $user) {
$user->uuid = Str::uuid()->toString();
});
}
}
42 changes: 36 additions & 6 deletions app/Repositories/Proxmox/Node/ProxmoxStorageRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

namespace Convoy\Repositories\Proxmox\Node;

use Convoy\Models\Node;
use Carbon\CarbonImmutable;
use Illuminate\Support\Arr;
use Webmozart\Assert\Assert;
use Convoy\Data\Helpers\ChecksumData;
use Convoy\Data\Node\Storage\IsoData;
use Spatie\LaravelData\DataCollection;
use Convoy\Data\Node\Storage\FileMetaData;
use Convoy\Enums\Node\Storage\ContentType;
use Convoy\Exceptions\Service\Node\IsoLibrary\InvalidIsoLinkException;
use Convoy\Models\Node;
use Convoy\Repositories\Proxmox\ProxmoxRepository;
use Illuminate\Support\Arr;
use Webmozart\Assert\Assert;
use Convoy\Exceptions\Service\Node\IsoLibrary\InvalidIsoLinkException;

class ProxmoxStorageRepository extends ProxmoxRepository
{
Expand Down Expand Up @@ -51,13 +54,40 @@ public function deleteFile(ContentType $contentType, string $fileName)
'storage' => $this->node->iso_storage,
'file' => "{$this->node->iso_storage}:$contentType->value/$fileName",
])
->delete('/api2/json/nodes/{node}/storage/{storage}/content//{file}')
->delete('/api2/json/nodes/{node}/storage/{storage}/content/{file}')
->json();

return $this->getData($response);
}

public function getFileMetadata(string $link, ?bool $verifyCertificates = true)
public function getIsos()
{
Assert::isInstanceOf($this->node, Node::class);

$response = $this->getHttpClient()
->withUrlParameters([
'node' => $this->node->cluster,
'storage' => $this->node->iso_storage,
])
->get('/api2/json/nodes/{node}/storage/{storage}/content?content=iso')
->json();

$response = $this->getData($response);

$isos = [];

foreach ($response as $iso) {
$isos[] = IsoData::from([
'file_name' => explode('/', $iso['volid'])[1],
'size' => $iso['size'],
'created_at' => CarbonImmutable::createFromTimestamp($iso['ctime']),
]);
}

return IsoData::collection($isos);
}

public function getFileMetadata(string $link, ?bool $verifyCertificates = true): FileMetaData
{
Assert::isInstanceOf($this->node, Node::class);
Assert::regex($link, '/^(http|https):\/\//');
Expand Down
18 changes: 12 additions & 6 deletions app/Services/Nodes/Isos/IsoService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

namespace Convoy\Services\Nodes\Isos;

use Convoy\Models\ISO;
use Convoy\Models\Node;
use Convoy\Data\Helpers\ChecksumData;
use Convoy\Data\Node\Storage\IsoData;
use Convoy\Enums\Node\Storage\ContentType;
use Convoy\Jobs\Node\MonitorIsoDownloadJob;
use Convoy\Models\ISO;
use Convoy\Models\Node;
use Convoy\Repositories\Proxmox\Node\ProxmoxStorageRepository;
use Illuminate\Database\ConnectionInterface;
use Ramsey\Uuid\Uuid;
use Convoy\Repositories\Proxmox\Node\ProxmoxStorageRepository;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class IsoService
Expand All @@ -18,13 +18,12 @@ public function __construct(private ConnectionInterface $connection, private Pro
{
}

public function create(Node $node, string $name, ?string $fileName, string $link, ?ChecksumData $checksumData = null, ?bool $hidden = false)
public function download(Node $node, string $name, ?string $fileName, string $link, ?ChecksumData $checksumData = null, ?bool $hidden = false)
{
$queriedFileMetadata = $this->repository->setNode($node)->getFileMetadata($link);

return $this->connection->transaction(function () use ($queriedFileMetadata, $node, $hidden, $fileName, $link, $name, $checksumData) {
$iso = ISO::create([
'uuid' => Uuid::uuid4()->toString(),
'node_id' => $node->id,
'name' => $name,
'file_name' => $fileName ?? $queriedFileMetadata->file_name,
Expand All @@ -40,6 +39,13 @@ public function create(Node $node, string $name, ?string $fileName, string $link
});
}

public function getIso(Node $node, string $fileName): ?IsoData
{
$isos = $this->repository->setNode($node)->getIsos();

return $isos->where('file_name', '=', $fileName)->first();
}

public function delete(Node $node, ISO $iso)
{
if (is_null($iso->completed_at)) {
Expand Down
1 change: 1 addition & 0 deletions lang/en_US/strings.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,5 @@
'link' => 'Link',
'file_name' => 'File Name',
'query' => 'Query',
'import' => 'Import',
];
15 changes: 10 additions & 5 deletions resources/scripts/api/admin/nodes/isos/createIso.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,30 @@ import http from '@/api/http'
export type ChecksumAlgorithm = 'md5' | 'sha1' | 'sha224' | 'sha256' | 'sha384' | 'sha512'

interface CreateIsoParameters {
shouldDownload: boolean
name: string
fileName?: string
fileName: string
hidden: boolean
link: string
link?: string
checksumAlgorithm?: ChecksumAlgorithm
checksum?: string
}

const createIso = async (nodeId: number, {fileName, checksumAlgorithm, checksum, ...data}: CreateIsoParameters): Promise<ISO> => {
const createIso = async (
nodeId: number,
{ shouldDownload, fileName, checksumAlgorithm, checksum, ...data }: CreateIsoParameters
): Promise<ISO> => {
const {
data: { data: responseData },
} = await http.post(`/api/admin/nodes/${nodeId}/isos`, {
should_download: shouldDownload,
file_name: fileName,
checksum_algorithm: checksumAlgorithm,
checksum: checksumAlgorithm ? checksum : undefined,
...data
...data,
})

return rawDataToISO(responseData)
}

export default createIso
export default createIso
Loading

0 comments on commit b329f4b

Please sign in to comment.