refs #1090. PartitionAssistant changes
testing/ogGui-multibranch/pipeline/head This commit is unstable
Details
testing/ogGui-multibranch/pipeline/head This commit is unstable
Details
parent
4f905778f8
commit
016e5a821a
|
@ -198,7 +198,7 @@ export class ClientMainViewComponent implements OnInit {
|
|||
}
|
||||
|
||||
loadPartitions(): void {
|
||||
this.http.get<any>(`${this.baseUrl}/partitions?client.id=${this.clientData?.id}&order[partitionNumber]=ASC`).subscribe({
|
||||
this.http.get<any>(`${this.baseUrl}/partitions?client.id=${this.clientData?.id}&order[diskNumber, partitionNumber]=ASC`).subscribe({
|
||||
next: data => {
|
||||
this.dataSource = data['hydra:member'];
|
||||
this.partitions = data['hydra:member'];
|
||||
|
|
|
@ -54,9 +54,9 @@
|
|||
</table>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
<h3 *ngIf="isMethod('multicast')" class="input-group">Opciones multicast</h3>
|
||||
<h3 *ngIf="isMethod('torrent')" class="input-group">Opciones torrent</h3>
|
||||
<div *ngIf="isMethod('multicast')" class="input-group">
|
||||
<h3 *ngIf="isMethod('udpcast') || isMethod('uftp')" class="input-group">Opciones multicast</h3>
|
||||
<h3 *ngIf="isMethod('p2p')" class="input-group">Opciones torrent</h3>
|
||||
<div *ngIf="isMethod('udpcast') || isMethod('uftp')" class="input-group">
|
||||
<mat-form-field appearance="fill" class="input-field">
|
||||
<mat-label>Puerto</mat-label>
|
||||
<input matInput [(ngModel)]="mcastPort" name="mcastPort">
|
||||
|
|
|
@ -39,22 +39,25 @@ export class DeployImageComponent {
|
|||
{ name: 'Seeder', value: 'p2p-mode-seeder' },
|
||||
];
|
||||
protected multicastModeOptions = [
|
||||
{"name": 'Half duplex', "value": "half-duplex"},
|
||||
{"name": 'Full duplex', "value": "full-duplex"},
|
||||
{ name: 'Half duplex', value: "half"},
|
||||
{ name: 'Full duplex', value: "full"},
|
||||
];
|
||||
|
||||
allMethods = [
|
||||
'multicast',
|
||||
'uftp',
|
||||
'udpcast',
|
||||
'multicast-direct',
|
||||
'unicast',
|
||||
'unicast-direct',
|
||||
'torrent'
|
||||
'p2p'
|
||||
];
|
||||
|
||||
updateCacheMethods = [
|
||||
'uftp',
|
||||
'udpcast',
|
||||
'multicast',
|
||||
'unicast',
|
||||
'torrent'
|
||||
'p2p'
|
||||
];
|
||||
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
|
@ -177,8 +180,8 @@ export class DeployImageComponent {
|
|||
this.http.post(`${this.baseUrl}${this.selectedImage}/deploy-image`, payload)
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
this.toastService.success('Imagen creada exitosamente');
|
||||
this.router.navigate(['/commmands-logs'])
|
||||
this.toastService.success('Petición de despliegue enviada correctamente');
|
||||
this.router.navigate(['/commands-logs'])
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error:', error);
|
||||
|
|
|
@ -162,3 +162,8 @@ button.remove-btn:hover {
|
|||
align-content: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.disk-select {
|
||||
padding: 20px;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,27 @@
|
|||
<div class="header-container">
|
||||
<h2 class="title" i18n="@@subnetsTitle">Asistente de particionado</h2>
|
||||
<div class="subnets-button-row">
|
||||
<button mat-flat-button color="primary" (click)="save()">Ejecutar</button>
|
||||
<button mat-flat-button color="primary" [disabled]="data.status === 'busy'" (click)="save()">Ejecutar</button>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<mat-dialog-content>
|
||||
<div class="partition-assistant" *ngFor="let disk of disks; let i = index">
|
||||
<div class="header">
|
||||
<label for="disk-number-{{ i }}">Disco {{ disk.diskNumber }}:</label>
|
||||
<span class="disk-size">Tamaño: {{ (disk.totalDiskSize / 1024).toFixed(2) }} GB</span>
|
||||
</div>
|
||||
<div class="disk-select">
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Seleccionar disco</mat-label>
|
||||
<mat-select [(ngModel)]="selectedDiskNumber">
|
||||
<mat-option *ngFor="let disk of disks" [value]="disk.diskNumber">
|
||||
Disco {{ disk.diskNumber }} ({{ (disk.totalDiskSize / 1024).toFixed(2) }} GB)
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="partition-assistant" *ngIf="selectedDisk">
|
||||
<div class="partition-bar">
|
||||
<div
|
||||
*ngFor="let partition of activePartitions(disk.diskNumber)"
|
||||
*ngFor="let partition of activePartitions(selectedDisk.diskNumber)"
|
||||
[ngStyle]="{'width': partition.percentage + '%', 'background-color': partition.color}"
|
||||
class="partition-segment"
|
||||
>
|
||||
|
@ -23,7 +29,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button mat-flat-button color="primary" (click)="addPartition(disk.diskNumber)">Añadir partición</button>
|
||||
<button mat-flat-button color="primary" (click)="addPartition(selectedDisk.diskNumber)">Añadir partición</button>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
@ -41,7 +47,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<ng-container *ngFor="let partition of disk.partitions; let j = index">
|
||||
<ng-container *ngFor="let partition of selectedDisk.partitions; let j = index">
|
||||
<tr *ngIf="!partition.removed">
|
||||
<td>{{ partition.partitionNumber }}</td>
|
||||
<td>
|
||||
|
@ -62,21 +68,21 @@
|
|||
<input
|
||||
type="number"
|
||||
[(ngModel)]="partition.size" required
|
||||
(input)="updatePartitionSize(disk.diskNumber, j, partition.size)"
|
||||
(input)="updatePartitionSize(selectedDisk.diskNumber, j, partition.size)"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="number"
|
||||
[(ngModel)]="partition.percentage"
|
||||
(input)="updatePartitionSizeFromPercentage(disk.diskNumber, j, partition.percentage)"
|
||||
(input)="updatePartitionSizeFromPercentage(selectedDisk.diskNumber, j, partition.percentage)"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" [(ngModel)]="partition.format" />
|
||||
</td>
|
||||
<td>
|
||||
<button (click)="removePartition(disk.diskNumber, partition)" class="remove-btn">X</button>
|
||||
<button (click)="removePartition(selectedDisk.diskNumber, partition)" class="remove-btn">X</button>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
|
@ -87,7 +93,7 @@
|
|||
<div class="chart-container">
|
||||
<ngx-charts-pie-chart
|
||||
[view]="view"
|
||||
[results]="disk.chartData"
|
||||
[results]="selectedDisk.chartData"
|
||||
[doughnut]="true"
|
||||
>
|
||||
</ngx-charts-pie-chart>
|
||||
|
@ -96,5 +102,4 @@
|
|||
</div>
|
||||
</mat-dialog-content>
|
||||
|
||||
|
||||
<div *ngIf="errorMessage" class="error-message">{{ errorMessage }}</div>
|
||||
|
|
|
@ -35,6 +35,7 @@ export class PartitionAssistantComponent implements OnInit {
|
|||
originalPartitions: any[] = [];
|
||||
clientId: string | null = null;
|
||||
newPartitions: any[] = [];
|
||||
selectedDiskNumber: number | null = null;
|
||||
updateRequests: any[] = [];
|
||||
data: any = {};
|
||||
disks: { diskNumber: number; totalDiskSize: number; partitions: Partition[]; chartData: any[]; used: number; percentage: number }[] = [];
|
||||
|
@ -57,6 +58,10 @@ export class PartitionAssistantComponent implements OnInit {
|
|||
this.loadPartitions();
|
||||
}
|
||||
|
||||
get selectedDisk():any {
|
||||
return this.disks.find(disk => disk.diskNumber === this.selectedDiskNumber) || null;
|
||||
}
|
||||
|
||||
loadPartitions() {
|
||||
const url = `${this.baseUrl}/clients/${this.clientId}`;
|
||||
this.http.get(url).subscribe(
|
||||
|
@ -246,59 +251,57 @@ export class PartitionAssistantComponent implements OnInit {
|
|||
}
|
||||
|
||||
save() {
|
||||
const invalidDisks = this.disks.filter(disk => {
|
||||
const totalPartitionSize = disk.partitions.reduce((sum, partition) => sum + partition.size, 0);
|
||||
return totalPartitionSize > disk.totalDiskSize;
|
||||
});
|
||||
if (!this.selectedDisk) {
|
||||
this.errorMessage = 'Por favor selecciona un disco antes de guardar.';
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(invalidDisks);
|
||||
if (invalidDisks.length > 0) {
|
||||
this.errorMessage = 'El tamaño total de las particiones en uno o más discos excede el tamaño total del disco.';
|
||||
const totalPartitionSize = this.selectedDisk.partitions.reduce((sum: any, partition: { size: any; }) => sum + partition.size, 0);
|
||||
|
||||
if (totalPartitionSize > this.selectedDisk.totalDiskSize) {
|
||||
this.errorMessage = 'El tamaño total de las particiones en el disco seleccionado excede el tamaño total del disco.';
|
||||
return;
|
||||
} else {
|
||||
this.errorMessage = '';
|
||||
}
|
||||
|
||||
const modifiedPartitions = this.getModifiedOrNewPartitions();
|
||||
const modifiedPartitions = this.selectedDisk.partitions.filter((partition: { removed: any; format: any; }) => !partition.removed || partition.format);
|
||||
|
||||
if (modifiedPartitions.length === 0) {
|
||||
this.errorMessage = 'No hay cambios para guardar.';
|
||||
this.errorMessage = 'No hay cambios para guardar en el disco seleccionado.';
|
||||
return;
|
||||
}
|
||||
|
||||
modifiedPartitions.forEach(({ partition, diskNumber, partitionNumber }) => {
|
||||
const payload = {
|
||||
diskNumber: diskNumber,
|
||||
partitionNumber: partitionNumber,
|
||||
memoryUsage: partition.memoryUsage,
|
||||
size: partition.size,
|
||||
partitionCode: partition.partitionCode,
|
||||
filesystem: partition.filesystem,
|
||||
client: `/clients/${this.clientId}`,
|
||||
uuid: partition.uuid,
|
||||
removed: partition.removed || false,
|
||||
format: partition.format || false,
|
||||
};
|
||||
const newPartitions = modifiedPartitions.map((partition: { partitionNumber: any; memoryUsage: any; size: any; partitionCode: any; filesystem: any; uuid: any; removed: any; format: any; }) => ({
|
||||
diskNumber: this.selectedDisk.diskNumber,
|
||||
partitionNumber: partition.partitionNumber,
|
||||
memoryUsage: partition.memoryUsage,
|
||||
size: partition.size,
|
||||
partitionCode: partition.partitionCode,
|
||||
filesystem: partition.filesystem,
|
||||
client: `/clients/${this.clientId}`,
|
||||
uuid: partition.uuid,
|
||||
removed: partition.removed || false,
|
||||
format: partition.format || false,
|
||||
}));
|
||||
|
||||
this.newPartitions.push(payload);
|
||||
});
|
||||
|
||||
if (this.newPartitions.length > 0) {
|
||||
const bulkPayload = { partitions: this.newPartitions };
|
||||
if (newPartitions.length > 0) {
|
||||
const bulkPayload = { partitions: newPartitions };
|
||||
|
||||
this.http.post(this.apiUrl, bulkPayload).subscribe(
|
||||
(response) => {
|
||||
this.toastService.success('Particiones creadas exitosamente');
|
||||
this.toastService.success('Particiones creadas exitosamente para el disco seleccionado.');
|
||||
this.router.navigate(['/commands-logs']);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error al crear las particiones:', error);
|
||||
this.toastService.error('Error al crear las particiones');
|
||||
this.toastService.error('Error al crear las particiones.');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
removePartition(diskNumber: number, partition: Partition) {
|
||||
const disk = this.disks.find((d) => d.diskNumber === diskNumber);
|
||||
if (disk) {
|
||||
|
|
|
@ -220,7 +220,7 @@
|
|||
<button
|
||||
*ngIf="(!syncStatus || syncingClientId !== client.uuid)"
|
||||
mat-icon-button color="primary"
|
||||
(click)="getStatus(client)">
|
||||
(click)="getStatus(client, selectedNode)">
|
||||
<mat-icon>sync</mat-icon>
|
||||
</button>
|
||||
|
||||
|
@ -251,6 +251,23 @@
|
|||
</div>
|
||||
<div class="clients-table" *ngIf="currentView === 'list'">
|
||||
<table mat-table matSort [dataSource]="selectedClients" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="sync">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'sync' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let client">
|
||||
<button
|
||||
*ngIf="(!syncStatus || syncingClientId !== client.uuid)"
|
||||
mat-icon-button color="primary"
|
||||
(click)="getStatus(client, selectedNode)">
|
||||
<mat-icon>sync</mat-icon>
|
||||
</button>
|
||||
|
||||
<button
|
||||
*ngIf="syncStatus && syncingClientId === client.uuid"
|
||||
mat-icon-button color="primary">
|
||||
<mat-spinner diameter="24"></mat-spinner>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'name' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let client">
|
||||
|
@ -263,7 +280,7 @@
|
|||
</ng-container>
|
||||
<ng-container matColumnDef="oglive">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> OG Live </th>
|
||||
<td mat-cell *matCellDef="let client"> {{ client.ogLive?.name }} </td>
|
||||
<td mat-cell *matCellDef="let client"> {{ (client.ogLive?.name || '').slice(0, 15) }}{{ (client.ogLive?.name?.length > 15) ? '...' : '' }} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th>
|
||||
|
@ -279,23 +296,9 @@
|
|||
{{ client.status || 'off' }}
|
||||
|
||||
</mat-chip>
|
||||
<button
|
||||
*ngIf="(!syncStatus || syncingClientId !== client.uuid)"
|
||||
mat-icon-button color="primary"
|
||||
(click)="getStatus(client)">
|
||||
<mat-icon>sync</mat-icon>
|
||||
</button>
|
||||
|
||||
<button
|
||||
*ngIf="syncStatus && syncingClientId === client.uuid"
|
||||
mat-icon-button color="primary">
|
||||
<mat-spinner diameter="24"></mat-spinner>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
|
||||
<ng-container matColumnDef="maintenace">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'maintenance' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let client"> {{ client.maintenance }} </td>
|
||||
|
@ -320,8 +323,8 @@
|
|||
<button mat-icon-button [matMenuTriggerFor]="clientMenu">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<mat-menu #clientMenu="matMenu">
|
||||
|
||||
|
@ -330,7 +333,7 @@
|
|||
<span>{{ command.name }}</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
|
||||
<button mat-menu-item [matMenuTriggerFor]="commandMenu" (click)="fetchCommands()">
|
||||
<mat-icon>play_arrow</mat-icon>
|
||||
<span>{{ 'executeCommand' | translate }}</span>
|
||||
|
|
|
@ -63,7 +63,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
syncingClientId: string | null = null;
|
||||
private originalTreeData: TreeNode[] = [];
|
||||
|
||||
displayedColumns: string[] = ['name', 'oglive', 'status', 'maintenace', 'subnet', 'pxeTemplate', 'parentName', 'actions'];
|
||||
displayedColumns: string[] = ['sync', 'name', 'oglive', 'status', 'subnet', 'pxeTemplate', 'parentName', 'actions'];
|
||||
|
||||
private _sort!: MatSort;
|
||||
private _paginator!: MatPaginator;
|
||||
|
@ -563,7 +563,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
this.selectedNode = node;
|
||||
}
|
||||
|
||||
getStatus(client: Client): void {
|
||||
getStatus(client: Client, node: any): void {
|
||||
if (!client.uuid || !client['@id']) return;
|
||||
|
||||
this.syncingClientId = client.uuid;
|
||||
|
@ -573,14 +573,15 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
this.http.post(`${this.baseUrl}${client['@id']}/agent/status`, {}).subscribe(
|
||||
() => {
|
||||
this.toastr.success('Cliente actualizado correctamente');
|
||||
this.search();
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
this.onNodeClick(node);
|
||||
},
|
||||
() => {
|
||||
this.toastr.error('Error de conexión con el cliente');
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
this.onNodeClick(node);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue