Skip to content

Commit

Permalink
NAS-132299: PR Update
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKarpov98 committed Nov 19, 2024
2 parents a564c1c + cdc9269 commit 9d90505
Show file tree
Hide file tree
Showing 117 changed files with 1,141 additions and 615 deletions.
11 changes: 6 additions & 5 deletions src/app/interfaces/api/api-call-directory.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,9 @@ import {
VmDisplayWebUriParams, VmPortWizardResult,
} from 'app/interfaces/virtual-machine.interface';
import {
VirtualizationDevice, VirtualizationGlobalConfig, AvailableGpu,
VirtualizationDevice, VirtualizationGlobalConfig,
VirtualizationImage, VirtualizationImageParams,
VirtualizationInstance, VirtualizationNetwork, AvailableUsb,
VirtualizationInstance, VirtualizationNetwork, AvailableUsb, AvailableGpus,
} from 'app/interfaces/virtualization.interface';
import {
VmDevice, VmDeviceDelete, VmDeviceUpdate, VmDisplayDevice, VmPassthroughDeviceChoice, VmUsbPassthroughDeviceChoice,
Expand Down Expand Up @@ -832,15 +832,16 @@ export interface ApiCallDirectory {

// Virt
'virt.instance.query': { params: QueryParams<VirtualizationInstance>; response: VirtualizationInstance[] };
'virt.instance.device_add': { params: [instanceId: string, device: VirtualizationDevice]; response: void }; // TODO
'virt.instance.device_delete': { params: [instanceId: string, name: string]; response: unknown }; // TODO:
'virt.instance.device_add': { params: [instanceId: string, device: VirtualizationDevice]; response: true };
'virt.instance.device_update': { params: [instanceId: string, device: VirtualizationDevice]; response: true };
'virt.instance.device_delete': { params: [instanceId: string, name: string]; response: true };
'virt.instance.device_list': { params: [instanceId: string]; response: VirtualizationDevice[] };
'virt.instance.image_choices': { params: [VirtualizationImageParams]; response: Record<string, VirtualizationImage> };

'virt.device.disk_choices': { params: []; response: Choices };
'virt.device.gpu_choices': {
params: [instanceType: VirtualizationType, gpuType: VirtualizationGpuType];
response: Record<string, AvailableGpu>;
response: AvailableGpus;
};
'virt.device.usb_choices': { params: []; response: Record<string, AvailableUsb> };

Expand Down
5 changes: 5 additions & 0 deletions src/app/interfaces/virtualization.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ export interface AvailableGpu {
vendor: string | null;
}

// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
export interface AvailableGpus {
[pci: string]: AvailableGpu;
}

export interface AvailableUsb {
vendor_id: string;
product_id: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ <h4 class="menu-header">{{ 'USB Devices' | translate }}</h4>
}
}

@if (availableGpuDevices().length) {
@let gpus = availableGpuDevices() | keyvalue;
@if (gpus.length) {
<h4 class="menu-header">{{ 'GPUs' | translate }}</h4>
@for (gpu of availableGpuDevices(); track gpu) {
@for (gpu of gpus; track gpu.key) {
<button
mat-menu-item
[ixTest]="['add-gpu-device', gpu.description]"
(click)="addGpu(gpu)"
[ixTest]="['add-gpu-device', gpu.value.description]"
(click)="addGpu(gpu.key)"
>
{{ gpu.description }}
{{ gpu.value.description }}
</button>
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ describe('AddDeviceMenuComponent', () => {
} as AvailableUsb,
}),
mockCall('virt.device.gpu_choices', {
gpu1: {
pci_0000_01_00_0: {
description: 'NDIVIA XTR 2000',
} as AvailableGpu,
gpu2: {
pci_0000_01_00_1: {
description: 'MAD Galeon 5000',
} as AvailableGpu,
}),
Expand All @@ -48,6 +48,7 @@ describe('AddDeviceMenuComponent', () => {
},
{
dev_type: VirtualizationDeviceType.Gpu,
pci: 'pci_0000_01_00_0',
description: 'NDIVIA XTR 2000',
},
] as VirtualizationDevice[],
Expand Down Expand Up @@ -95,7 +96,7 @@ describe('AddDeviceMenuComponent', () => {

expect(spectator.inject(ApiService).call).toHaveBeenCalledWith('virt.instance.device_add', ['my-instance', {
dev_type: VirtualizationDeviceType.Gpu,
description: 'MAD Galeon 5000',
pci: 'pci_0000_01_00_1',
} as VirtualizationDevice]);
expect(spectator.inject(VirtualizationInstancesStore).loadDevices).toHaveBeenCalled();
expect(spectator.inject(SnackbarService).success).toHaveBeenCalledWith('Device was added');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { KeyValuePipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, computed } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { MatButton } from '@angular/material/button';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { pickBy } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { VirtualizationDeviceType, VirtualizationGpuType, VirtualizationType } from 'app/enums/virtualization.enum';
import {
AvailableGpu,
AvailableUsb,
VirtualizationDevice,
VirtualizationGpu,
Expand Down Expand Up @@ -35,6 +36,7 @@ import { ApiService } from 'app/services/websocket/api.service';
TranslateModule,
MatMenuTrigger,
NgxSkeletonLoaderModule,
KeyValuePipe,
],
})
export class AddDeviceMenuComponent {
Expand All @@ -55,18 +57,17 @@ export class AddDeviceMenuComponent {
});

protected readonly availableGpuDevices = computed(() => {
const gpuChoices = Object.values(this.gpuChoices());
const existingGpuDevices = this.instanceStore.selectedInstanceDevices()
const gpuChoices = this.gpuChoices();
const usedGpus = this.instanceStore.selectedInstanceDevices()
.filter((device) => device.dev_type === VirtualizationDeviceType.Gpu);

return gpuChoices.filter((gpu) => {
// TODO: Condition is incorrect.
return !existingGpuDevices.find((device) => device.description === gpu.description);
return pickBy(gpuChoices, (_, pci) => {
return !usedGpus.find((usedGpu) => usedGpu.pci === pci);
});
});

protected readonly hasDevicesToAdd = computed(() => {
return this.availableUsbDevices().length > 0 || this.availableGpuDevices().length > 0;
return this.availableUsbDevices().length > 0 || Object.keys(this.availableGpuDevices()).length > 0;
});

constructor(
Expand All @@ -85,11 +86,10 @@ export class AddDeviceMenuComponent {
} as VirtualizationUsb);
}

protected addGpu(gpu: AvailableGpu): void {
protected addGpu(gpuPci: string): void {
this.addDevice({
dev_type: VirtualizationDeviceType.Gpu,
// TODO: Incorrect value.
description: gpu.description,
pci: gpuPci,
} as VirtualizationGpu);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ <h3 mat-card-title>
<div class="device">
<span>{{ getDeviceDescription(device) }}</span>

<ix-delete-device-button [device]="device"></ix-delete-device-button>
<ix-device-actions-menu
[device]="device"
[showEdit]="false"
></ix-device-actions-menu>
</div>
} @empty {
{{ 'No devices added.' | translate }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
InstanceDevicesComponent,
} from 'app/pages/virtualization/components/all-instances/instance-details/instance-devices/instance-devices.component';
import {
DeleteDeviceButtonComponent,
} from 'app/pages/virtualization/components/common/delete-device-button/delete-device-button.component';
DeviceActionsMenuComponent,
} from 'app/pages/virtualization/components/common/device-actions-menu/device-actions-menu.component';
import { VirtualizationInstancesStore } from 'app/pages/virtualization/stores/virtualization-instances.store';

describe('InstanceDevicesComponent', () => {
Expand All @@ -33,7 +33,7 @@ describe('InstanceDevicesComponent', () => {
component: InstanceDevicesComponent,
imports: [
MockComponents(
DeleteDeviceButtonComponent,
DeviceActionsMenuComponent,
AddDeviceMenuComponent,
),
],
Expand All @@ -59,10 +59,10 @@ describe('InstanceDevicesComponent', () => {
expect(deviceRows[1]).toHaveText('Matrox G200eW');
});

it('renders a button to delete the device', () => {
const deleteButtons = spectator.queryAll(DeleteDeviceButtonComponent);
expect(deleteButtons).toHaveLength(2);
expect(deleteButtons[0].device).toBe(devices[0]);
it('renders a menu to delete the device', () => {
const actionsMenu = spectator.queryAll(DeviceActionsMenuComponent);
expect(actionsMenu).toHaveLength(2);
expect(actionsMenu[0].device).toBe(devices[0]);
});

it('renders a menu to add a new device', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import {
} from '@angular/core';
import { MatCard, MatCardContent, MatCardHeader } from '@angular/material/card';
import { UntilDestroy } from '@ngneat/until-destroy';
import { TranslateModule } from '@ngx-translate/core';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { VirtualizationDeviceType, virtualizationDeviceTypeLabels } from 'app/enums/virtualization.enum';
import { VirtualizationDeviceType } from 'app/enums/virtualization.enum';
import {
VirtualizationDevice,
} from 'app/interfaces/virtualization.interface';
import {
AddDeviceMenuComponent,
} from 'app/pages/virtualization/components/all-instances/instance-details/instance-devices/add-device-menu/add-device-menu.component';
import {
DeleteDeviceButtonComponent,
} from 'app/pages/virtualization/components/common/delete-device-button/delete-device-button.component';
DeviceActionsMenuComponent,
} from 'app/pages/virtualization/components/common/device-actions-menu/device-actions-menu.component';
import { getDeviceDescription } from 'app/pages/virtualization/components/common/utils/get-device-description.utils';
import { VirtualizationInstancesStore } from 'app/pages/virtualization/stores/virtualization-instances.store';

@UntilDestroy()
Expand All @@ -30,7 +31,7 @@ import { VirtualizationInstancesStore } from 'app/pages/virtualization/stores/vi
TranslateModule,
MatCardContent,
NgxSkeletonLoaderModule,
DeleteDeviceButtonComponent,
DeviceActionsMenuComponent,
AddDeviceMenuComponent,
],
})
Expand All @@ -44,17 +45,11 @@ export class InstanceDevicesComponent {
});

constructor(
private translate: TranslateService,
private instanceStore: VirtualizationInstancesStore,
) {}

protected getDeviceDescription(device: VirtualizationDevice): string {
const type = virtualizationDeviceTypeLabels.has(device.dev_type)
? virtualizationDeviceTypeLabels.get(device.dev_type)
: device.dev_type;

// TODO: Remove `.replace(`${type}:`, '')` after https://ixsystems.atlassian.net/browse/NAS-132543
const description = `${device.description} (${device.product_id})`.replace(`${type}:`, '').trim();

return `${type}: ${description}`;
return getDeviceDescription(this.translate, device);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<ix-modal-header2
[title]="'Add Disk' | translate"
[title]="title()"
[loading]="isLoading()"
></ix-modal-header2>

Expand All @@ -26,10 +26,10 @@
mat-button
type="submit"
color="primary"
ixTest="add"
ixTest="save"
[disabled]="form.invalid || isLoading()"
>
{{ 'Add' | translate }}
{{ 'Save' | translate }}
</button>
</ix-form-actions>
</form>
Expand Down
Loading

0 comments on commit 9d90505

Please sign in to comment.