Skip to content

Commit

Permalink
Merge branch 'origin/master' into 129003/NAS-129003
Browse files Browse the repository at this point in the history
  • Loading branch information
bvasilenko committed Jul 15, 2024
2 parents b86d19c + 963c184 commit db6b519
Show file tree
Hide file tree
Showing 860 changed files with 31,331 additions and 17,846 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"@angular/platform-browser": "^18.0.0",
"@angular/platform-browser-dynamic": "^18.0.0",
"@angular/router": "^18.0.0",
"@bartholomej/ngx-translate-extract": "~8.0.1",
"@vendure/ngx-translate-extract": "~9.2.0",
"@biesbjerg/ngx-translate-extract-marker": "~1.0.0",
"@bugsplat/angular-tree-component": "~13.0.1",
"@codemirror/autocomplete": "~6.13.0",
Expand All @@ -78,7 +78,7 @@
"@mdi/font": "~7.4.47",
"@ngbracket/ngx-layout": "~17.0.1",
"@ngneat/reactive-forms": "~5.0.2",
"@ngneat/spectator": "~18.0.1",
"@ngneat/spectator": "~19.0.0",
"@ngneat/until-destroy": "~9.2.3",
"@ngrx/component-store": "~17.2.0",
"@ngrx/effects": "~17.2.0",
Expand Down Expand Up @@ -167,7 +167,7 @@
"mime-types": "~2.1.35",
"ng-gallery": "~8.0.4",
"ng-lazyload-image": "~9.1.3",
"ng-mocks": "~14.12.1",
"ng-mocks": "~14.13.0",
"ng-qrcode": "~8.0.1",
"ng2-charts": "~6.0.0",
"ng2-fittext": "~1.4.3",
Expand Down
7 changes: 0 additions & 7 deletions src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,6 @@ export const rootRouterConfig: Routes = [
path: 'system/audit',
loadChildren: () => import('./pages/audit/audit.module').then((module) => module.AuditModule),
},
{
path: 'errors',
children: [{
path: 'unauthorized',
loadChildren: () => import('./pages/unauthorized/unauthorized.module').then((module) => module.UnauthorizedModule),
}],
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import { EnclosureStatus } from 'app/enums/enclosure-slot-status.enum';
import { DashboardEnclosure, DashboardEnclosureSlot } from 'app/interfaces/enclosure.interface';

export function addDisksToSlots(enclosures: DashboardEnclosure[], percentageToAdd: number): DashboardEnclosure[] {
const totalSlots = countSlots(enclosures);
let totalAddedDisks = -1;

return mapSlots(enclosures, ({ slot, index }) => {
if (index > totalSlots * percentageToAdd) {
return mapSlots(enclosures, ({ slot, enclosure, index }) => {
const slotsInEnclosure = countSlots(enclosure);
if (index > slotsInEnclosure * percentageToAdd) {
return slot;
}

return addDisk(slot, index);
totalAddedDisks = totalAddedDisks + 1;

return addDisk(slot, totalAddedDisks);
});
}

Expand Down Expand Up @@ -43,6 +46,5 @@ function generateDiskName(index: number): string {
index = Math.floor(index / base) - 1;
}

result = 'sd' + String.fromCharCode(offset + index) + result;
return result;
return 'sd' + String.fromCharCode(offset + index) + result;
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,85 @@
import { countSlotsBy, mapSlots } from 'app/core/testing/mock-enclosure/enclosure-templates/utils/slots.utils';
import { EnclosureDiskStatus } from 'app/enums/enclosure-slot-status.enum';
import { mapSlots } from 'app/core/testing/mock-enclosure/enclosure-templates/utils/slots.utils';
import { EnclosureDiskStatus, EnclosureElementType } from 'app/enums/enclosure-slot-status.enum';
import { VdevType } from 'app/enums/v-dev-type.enum';
import { DashboardEnclosure } from 'app/interfaces/enclosure.interface';
import { DashboardEnclosure, DashboardEnclosureSlot } from 'app/interfaces/enclosure.interface';

// TODO: Only creates single disk vdevs in the same pool. Improve.
// TODO: Messy.
export function addPoolsToDisks(enclosures: DashboardEnclosure[], percentageToAdd: number): DashboardEnclosure[] {
return mapSlots(enclosures, ({ slot, enclosure, index }) => {
const totalDisks = countSlotsBy([enclosure], ({ dev }) => Boolean(dev));
const disksPerVdev = 3;
const poolsToAdd = 40;

if (index >= totalDisks * percentageToAdd) {
return slot;
const slotsToUpdate: DashboardEnclosureSlot[] = [];
enclosures.forEach((enclosure) => {
const enclosureSlotsWithDisks = Object.values(enclosure.elements[EnclosureElementType.ArrayDeviceSlot])
.filter((slot) => Boolean(slot.dev));

const enclosureSlotsToUse = enclosureSlotsWithDisks.slice(
0,
Math.floor(enclosureSlotsWithDisks.length * percentageToAdd),
);

slotsToUpdate.push(...enclosureSlotsToUse);
});

const vdevs = groupDisksIntoVdevs(slotsToUpdate, disksPerVdev);

let i = 0;
return mapSlots(enclosures, ({ slot: originalSlot, enclosure }) => {
const updatedSlot = slotsToUpdate.find((slot) => slot.dev === originalSlot.dev);

if (!updatedSlot) {
return originalSlot;
}

const vdevIndex = Math.floor(i / disksPerVdev);
const vdev = vdevs[vdevIndex];
i = i + 1;

return {
...slot,
...originalSlot,
pool_info: {
pool_name: 'Test Pool',
pool_name: `pool-${vdevIndex % poolsToAdd + 1}`,
disk_status: EnclosureDiskStatus.Online,
disk_read_errors: 0,
disk_write_errors: 0,
disk_checksum_errors: 0,
vdev_name: 'stripe',
vdev_type: VdevType.Data,
vdev_disks: [{
enclosure_id: '5b0bd6d1a30714bf',
slot: slot.drive_bay_number,
dev: slot.dev,
}],
vdev_disks: vdev.map((disk) => ({
// TODO: Bug. Enclosure id should come from the disk.
enclosure_id: enclosure.id,
slot: disk.drive_bay_number,
dev: disk.dev,
})),
},
};
});
}

function groupDisksIntoVdevs(slots: DashboardEnclosureSlot[], disksPerVdev: number): DashboardEnclosureSlot[][] {
return slots.reduce((acc, slot, index) => {
const vdevIndex = Math.floor(index / disksPerVdev);
if (!acc[vdevIndex]) {
acc[vdevIndex] = [];
}

acc[vdevIndex].push(slot);
return acc;
}, [] as DashboardEnclosureSlot[][]);
}

export function randomizeDiskStatuses(enclosures: DashboardEnclosure[]): DashboardEnclosure[] {
const allStatuses = Object.values(EnclosureDiskStatus);
return mapSlots(enclosures, ({ slot, index }) => {
if (!slot.pool_info) {
return slot;
}

return {
...slot,
pool_info: {
...slot.pool_info,
disk_status: allStatuses[index % allStatuses.length],
},
};
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { EnclosureElementType } from 'app/enums/enclosure-slot-status.enum';
import {
DashboardEnclosure,
DashboardEnclosureSlot,
DashboardEnclosureElements,
} from 'app/interfaces/enclosure.interface';
import { mapSlots, countSlots } from './slots.utils';

describe('mapSlots', () => {
it('should correctly map slots for each enclosure', () => {
const enclosures = [
{
elements: {
[EnclosureElementType.ArrayDeviceSlot]: {
1: { model: 'test1' } as DashboardEnclosureSlot,
2: { model: 'test2' } as DashboardEnclosureSlot,
},
} as DashboardEnclosureElements,
},
] as DashboardEnclosure[];

const result = mapSlots(enclosures, ({ slot }) => ({
...slot,
model: `mapped-${slot.model}`,
}));

expect(result).toEqual([
{
elements: {
[EnclosureElementType.ArrayDeviceSlot]: {
1: { model: 'mapped-test1' } as DashboardEnclosureSlot,
2: { model: 'mapped-test2' } as DashboardEnclosureSlot,
},
} as DashboardEnclosureElements,
},
]);
});
});

describe('countSlots', () => {
it('should return the correct number of slots', () => {
const enclosure = {
elements: {
[EnclosureElementType.ArrayDeviceSlot]: {
1: {} as DashboardEnclosureSlot,
2: {} as DashboardEnclosureSlot,
},
} as DashboardEnclosureElements,
} as DashboardEnclosure;
const result = countSlots(enclosure);
expect(result).toBe(2);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface SlotMappingFunction {

export function mapSlots(
enclosures: DashboardEnclosure[],
mappingFunction: ({ slot, enclosure, index }: SlotMappingFunction) => DashboardEnclosureSlot,
mappingFunction: ({ slot, index }: SlotMappingFunction) => DashboardEnclosureSlot,
): DashboardEnclosure[] {
return enclosures.map((enclosure) => {
let i = -1;
Expand All @@ -29,17 +29,6 @@ export function mapSlots(
});
}

export function countSlots(enclosures: DashboardEnclosure[]): number {
return enclosures.reduce((acc, enclosure) => {
return acc + Object.keys(enclosure.elements[EnclosureElementType.ArrayDeviceSlot]).length;
}, 0);
}

export function countSlotsBy(
enclosures: DashboardEnclosure[],
predicate: (slot: DashboardEnclosureSlot) => boolean,
): number {
return enclosures.reduce((acc, enclosure) => {
return acc + Object.values(enclosure.elements[EnclosureElementType.ArrayDeviceSlot]).filter(predicate).length;
}, 0);
export function countSlots(enclosure: DashboardEnclosure): number {
return Object.keys(enclosure.elements[EnclosureElementType.ArrayDeviceSlot]).length;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,19 @@ export enum MockStorageScenario {
*/
FillSomeSlots = 'fill-some',
FillAllSlots = 'all-slots',
DiskStatuses = 'disk-statuses',
}

export const mockStorageScenarioLabels = new Map<MockStorageScenario, string>([
[MockStorageScenario.AllSlotsEmpty, 'All slots empty'],
[MockStorageScenario.FillSomeSlots, 'Add disks to some slots and add a pool to some disks'],
[MockStorageScenario.FillAllSlots, 'Add disks to all slots and add a pool to all disks'],
[MockStorageScenario.FillSomeSlots, 'Add disks to some slots and add pools to some disks.'],
[MockStorageScenario.FillAllSlots, 'Add disks to all slots and add pools to all disks'],
[MockStorageScenario.DiskStatuses, 'Fill some slots and use all disk statuses'],
]);

/**
* @deprecated
*/
export enum MockDiskType {
'Hdd' = 'Hdd',
'Nvme' = 'Nvme',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { unsupportedEnclosureMock } from 'app/constants/server-series.constant';
import { enclosureMocks } from 'app/core/testing/mock-enclosure/enclosure-templates/enclosure-mocks';
import { addDisksToSlots } from 'app/core/testing/mock-enclosure/enclosure-templates/utils/disk.utils';
import { addPoolsToDisks } from 'app/core/testing/mock-enclosure/enclosure-templates/utils/pool.utils';
import {
addPoolsToDisks,
randomizeDiskStatuses,
} from 'app/core/testing/mock-enclosure/enclosure-templates/utils/pool.utils';
import { MockStorageScenario } from 'app/core/testing/mock-enclosure/enums/mock-storage.enum';
import { MockEnclosureConfig } from 'app/core/testing/mock-enclosure/interfaces/mock-enclosure.interface';
import { EnclosureModel } from 'app/enums/enclosure-model.enum';
Expand Down Expand Up @@ -60,6 +63,11 @@ export class MockStorageGenerator {
this.enclosures = addDisksToSlots(this.enclosures, 1);
this.enclosures = addPoolsToDisks(this.enclosures, 1);
return;
case MockStorageScenario.DiskStatuses:
this.enclosures = addDisksToSlots(this.enclosures, 0.8);
this.enclosures = addPoolsToDisks(this.enclosures, 0.8);
this.enclosures = randomizeDiskStatuses(this.enclosures);
return;
default:
assertUnreachable(scenario);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ <h5 class="tooltip-title">
mat-icon-button
ixTest="tooltip-close"
class="close-button"
[attr.aria-label]="'Close Tooltip' | translate"
(click)="popperTooltip.hide()"
>
<ix-icon
Expand Down
15 changes: 15 additions & 0 deletions src/app/directives/common/ui-search.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ export class UiSearchDirective implements OnInit, OnDestroy {
return getSearchableElementId(this.config);
}

get ariaLabel(): string {
const hierarchyItem = this.config.hierarchy?.[this.config.hierarchy.length - 1] || '';
const isSingleWord = hierarchyItem.trim().split(/\s+/).length === 1;

if (isSingleWord && this.config.synonyms?.length > 0) {
return this.config.synonyms.reduce((best, synonym) => {
const synonymWordCount = synonym.trim().split(/\s+/).length;
const bestWordCount = best.trim().split(/\s+/).length;
return synonymWordCount > bestWordCount ? synonym : best;
}, hierarchyItem);
}
return hierarchyItem;
}

constructor(
private renderer: Renderer2,
private elementRef: ElementRef<HTMLElement>,
Expand All @@ -26,6 +40,7 @@ export class UiSearchDirective implements OnInit, OnDestroy {
ngOnInit(): void {
if (this.id) {
this.renderer.setAttribute(this.elementRef.nativeElement, 'id', this.id);
this.renderer.setAttribute(this.elementRef.nativeElement, 'aria-label', this.ariaLabel);
}
this.searchDirectives.register(this);
}
Expand Down
6 changes: 6 additions & 0 deletions src/app/enums/chart-release-status.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ export enum ChartReleaseStatus {
Deploying = 'DEPLOYING',
Stopped = 'STOPPED',
}

export const chartStatusIcons = new Map<ChartReleaseStatus, string>([
[ChartReleaseStatus.Active, 'mdi-check-circle'],
[ChartReleaseStatus.Deploying, 'mdi-progress-wrench'],
[ChartReleaseStatus.Stopped, 'mdi-stop-circle'],
]);
10 changes: 10 additions & 0 deletions src/app/enums/directory-service-state.enum.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { marker as T } from '@biesbjerg/ngx-translate-extract-marker';

export enum DirectoryServiceState {
Disabled = 'DISABLED',
Healthy = 'HEALTHY',
Faulted = 'FAULTED',
Leaving = 'LEAVING',
Joining = 'JOINING',
}

export const directoryServiceStateLabels = new Map<DirectoryServiceState, string>([
[DirectoryServiceState.Disabled, T('Disabled')],
[DirectoryServiceState.Healthy, T('Healthy')],
[DirectoryServiceState.Faulted, T('Faulted')],
[DirectoryServiceState.Leaving, T('Leaving')],
[DirectoryServiceState.Joining, T('Joining')],
]);
11 changes: 11 additions & 0 deletions src/app/enums/enclosure-slot-status.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ export enum EnclosureDiskStatus {
Unknown = 'UNKNOWN',
}

export const enclosureDiskStatusLabels = new Map<EnclosureDiskStatus, string>([
[EnclosureDiskStatus.Offline, T('Offline')],
[EnclosureDiskStatus.Removed, T('Removed')],
[EnclosureDiskStatus.Faulted, T('Faulted')],
[EnclosureDiskStatus.Split, T('Split')],
[EnclosureDiskStatus.Unavail, T('Unavailable')],
[EnclosureDiskStatus.Degraded, T('Degraded')],
[EnclosureDiskStatus.Online, T('Online')],
[EnclosureDiskStatus.Unknown, T('Unknown')],
]);

// TODO: Find out what all element name possibilities are to complete the enum
export enum EnclosureElementType {
ArrayDeviceSlot = 'Array Device Slot',
Expand Down
2 changes: 2 additions & 0 deletions src/app/enums/nfs-acl.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export enum NfsAclTag {
Everyone = 'everyone@',
User = 'USER',
UserGroup = 'GROUP',
Both = 'BOTH', // middleware returns `ID_TYPE_BOTH` when it is not possible to determine whether an AD entity is a user or a group
}

export const nfsAclTagLabels = new Map<NfsAclTag, string>([
Expand All @@ -19,6 +20,7 @@ export const nfsAclTagLabels = new Map<NfsAclTag, string>([
export const smbAclTagLabels = new Map<NfsAclTag, string>([
[NfsAclTag.User, T('User')],
[NfsAclTag.UserGroup, T('Group')],
[NfsAclTag.Both, T('Unknown')],
[NfsAclTag.Everyone, T('everyone@')],
]);

Expand Down
Loading

0 comments on commit db6b519

Please sign in to comment.