mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-24 17:15:22 +00:00
Compare commits
1 Commits
v3.0.4
...
bugfix/150
Author | SHA1 | Date | |
---|---|---|---|
b510f3dc8f |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gns3-web-ui",
|
||||
"version": "3.0.4",
|
||||
"version": "3.1.0.dev1",
|
||||
"author": {
|
||||
"name": "GNS3 Technology Inc.",
|
||||
"email": "developers@gns3.com"
|
||||
|
@ -31,8 +31,7 @@ import { ProgressComponent } from './common/progress/progress.component';
|
||||
import { ProgressService } from './common/progress/progress.service';
|
||||
import { AdbutlerComponent } from './components/adbutler/adbutler.component';
|
||||
import { BundledControllerFinderComponent } from './components/bundled-controller-finder/bundled-controller-finder.component';
|
||||
import { InformationDialogComponent } from './components/dialogs/information-dialog/information-dialog.component';
|
||||
import { QuestionDialogComponent } from "./components/dialogs/question-dialog/question-dialog.component";
|
||||
import { InformationDialogComponent } from './components/dialogs/information-dialog.component';
|
||||
import { DirectLinkComponent } from './components/direct-link/direct-link.component';
|
||||
import { DrawingAddedComponent } from './components/drawings-listeners/drawing-added/drawing-added.component';
|
||||
import { DrawingDraggedComponent } from './components/drawings-listeners/drawing-dragged/drawing-dragged.component';
|
||||
@ -119,8 +118,6 @@ import { EditTextActionComponent } from './components/project-map/context-menu/a
|
||||
import { ExportConfigActionComponent } from './components/project-map/context-menu/actions/export-config/export-config-action.component';
|
||||
import { HttpConsoleNewTabActionComponent } from './components/project-map/context-menu/actions/http-console-new-tab/http-console-new-tab-action.component';
|
||||
import { HttpConsoleActionComponent } from './components/project-map/context-menu/actions/http-console/http-console-action.component';
|
||||
import { IdlePcActionComponent } from "./components/project-map/context-menu/actions/idle-pc-action/idle-pc-action.component";
|
||||
import { AutoIdlePcActionComponent } from "./components/project-map/context-menu/actions/auto-idle-pc-action/auto-idle-pc-action.component";
|
||||
import { ImportConfigActionComponent } from './components/project-map/context-menu/actions/import-config/import-config-action.component';
|
||||
import { LockActionComponent } from './components/project-map/context-menu/actions/lock-action/lock-action.component';
|
||||
import { MoveLayerDownActionComponent } from './components/project-map/context-menu/actions/move-layer-down-action/move-layer-down-action.component';
|
||||
@ -136,12 +133,11 @@ import { StartNodeActionComponent } from './components/project-map/context-menu/
|
||||
import { StopCaptureActionComponent } from './components/project-map/context-menu/actions/stop-capture/stop-capture-action.component';
|
||||
import { IsolateNodeActionComponent } from './components/project-map/context-menu/actions/isolate-node-action/isolate-node-action.component';
|
||||
import { UnisolateNodeActionComponent } from './components/project-map/context-menu/actions/unisolate-node-action/unisolate-node-action.component';
|
||||
import { StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
|
||||
import {StopNodeActionComponent } from './components/project-map/context-menu/actions/stop-node-action/stop-node-action.component';
|
||||
import { SuspendLinkActionComponent } from './components/project-map/context-menu/actions/suspend-link/suspend-link-action.component';
|
||||
import { SuspendNodeActionComponent } from './components/project-map/context-menu/actions/suspend-node-action/suspend-node-action.component';
|
||||
import { ContextMenuComponent } from './components/project-map/context-menu/context-menu.component';
|
||||
import { ConfigDialogComponent } from './components/project-map/context-menu/dialogs/config-dialog/config-dialog.component';
|
||||
import { IdlePCDialogComponent } from "./components/project-map/context-menu/dialogs/idle-pc-dialog/idle-pc-dialog.component";
|
||||
import { DrawLinkToolComponent } from './components/project-map/draw-link-tool/draw-link-tool.component';
|
||||
import { StyleEditorDialogComponent } from './components/project-map/drawings-editors/style-editor/style-editor.component';
|
||||
import { LinkStyleEditorDialogComponent } from './components/project-map/drawings-editors/link-style-editor/link-style-editor.component';
|
||||
@ -497,7 +493,6 @@ import { DeleteResourceConfirmationDialogComponent } from './components/resource
|
||||
AlignVerticallyActionComponent,
|
||||
ConfirmationBottomSheetComponent,
|
||||
ConfigDialogComponent,
|
||||
IdlePCDialogComponent,
|
||||
ImportApplianceComponent,
|
||||
DirectLinkComponent,
|
||||
SystemStatusComponent,
|
||||
@ -505,8 +500,6 @@ import { DeleteResourceConfirmationDialogComponent } from './components/resource
|
||||
StatusChartComponent,
|
||||
OpenFileExplorerActionComponent,
|
||||
HttpConsoleActionComponent,
|
||||
IdlePcActionComponent,
|
||||
AutoIdlePcActionComponent,
|
||||
WebConsoleComponent,
|
||||
ConsoleWrapperComponent,
|
||||
HttpConsoleNewTabActionComponent,
|
||||
@ -518,7 +511,6 @@ import { DeleteResourceConfirmationDialogComponent } from './components/resource
|
||||
ReadmeEditorComponent,
|
||||
MarkedDirective,
|
||||
InformationDialogComponent,
|
||||
QuestionDialogComponent,
|
||||
TemplateNameDialogComponent,
|
||||
ConfigureCustomAdaptersDialogComponent,
|
||||
EditNetworkConfigurationDialogComponent,
|
||||
|
@ -27,7 +27,6 @@ export class MapNodeToNodeConverter implements Converter<MapNode, Node> {
|
||||
node.port_name_format = mapNode.portNameFormat;
|
||||
node.port_segment_size = mapNode.portSegmentSize;
|
||||
node.ports = mapNode.ports ? mapNode.ports.map((mapPort) => this.mapPortToPort.convert(mapPort)) : [];
|
||||
node.properties = mapNode.properties;
|
||||
node.project_id = mapNode.projectId;
|
||||
node.status = mapNode.status;
|
||||
node.symbol = mapNode.symbol;
|
||||
|
@ -38,7 +38,6 @@ export class NodeToMapNodeConverter implements Converter<Node, MapNode> {
|
||||
mapNode.portNameFormat = node.port_name_format;
|
||||
mapNode.portSegmentSize = node.port_segment_size;
|
||||
mapNode.ports = node.ports ? node.ports.map((port) => this.portToMapPort.convert(port)) : [];
|
||||
mapNode.properties = node.properties;
|
||||
mapNode.projectId = node.project_id;
|
||||
mapNode.status = node.status;
|
||||
mapNode.symbol = node.symbol;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Indexed } from '../../datasources/map-datasource';
|
||||
import { MapLabel } from './map-label';
|
||||
import { MapPort } from './map-port';
|
||||
import { Properties } from '../node';
|
||||
|
||||
export class MapNode implements Indexed {
|
||||
id: string;
|
||||
@ -20,7 +19,6 @@ export class MapNode implements Indexed {
|
||||
portNameFormat: string;
|
||||
portSegmentSize: number;
|
||||
ports: MapPort[];
|
||||
properties: Properties;
|
||||
projectId: string;
|
||||
status: string;
|
||||
symbol: string;
|
||||
|
@ -14,15 +14,10 @@ export class Properties {
|
||||
headless: boolean;
|
||||
linked_clone: boolean;
|
||||
on_close: string;
|
||||
aux: number;
|
||||
aux_type: boolean;
|
||||
aux: number;
|
||||
ram: number;
|
||||
system_id: string;
|
||||
dynamips_id?: number;
|
||||
npe?: string;
|
||||
midplane?: string;
|
||||
nvram: number;
|
||||
image: string;
|
||||
usage: string;
|
||||
use_any_adapter: boolean;
|
||||
vmname: string;
|
||||
@ -53,40 +48,16 @@ export class Properties {
|
||||
kernel_image: string;
|
||||
kernel_image_md5sum?: any;
|
||||
mac_address: string;
|
||||
mac_addr: string;
|
||||
options: string;
|
||||
platform: string;
|
||||
chassis?: string;
|
||||
iomem?: number;
|
||||
disk0: number;
|
||||
disk1: number;
|
||||
idlepc: string;
|
||||
idlemax: number;
|
||||
idlesleep: number;
|
||||
exec_area: number;
|
||||
mmap: boolean;
|
||||
sparsemem: boolean;
|
||||
auto_delete_disks: boolean;
|
||||
process_priority: string;
|
||||
qemu_path: string;
|
||||
environment: string;
|
||||
extra_hosts: string;
|
||||
start_command: string;
|
||||
replicate_network_connection_state: boolean;
|
||||
memory: number;
|
||||
tpm: boolean;
|
||||
uefi: boolean;
|
||||
slot0?: string;
|
||||
slot1?: string;
|
||||
slot2?: string;
|
||||
slot3?: string;
|
||||
slot4?: string;
|
||||
slot5?: string;
|
||||
slot6?: string;
|
||||
slot7?: string;
|
||||
wic0?: string;
|
||||
wic1?: string;
|
||||
wic2?: string;
|
||||
}
|
||||
|
||||
export class Node {
|
||||
|
@ -1,8 +0,0 @@
|
||||
<h1 mat-dialog-title>{{ data.title }}</h1>
|
||||
<div mat-dialog-content>
|
||||
<p>{{ data.question }}</p>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button (click)="onNoClick()">No</button>
|
||||
<button mat-button (click)="onYesClick()">Yes</button>
|
||||
</div>
|
@ -1,21 +0,0 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'app-question-dialog',
|
||||
templateUrl: './question-dialog.component.html',
|
||||
})
|
||||
export class QuestionDialogComponent {
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<QuestionDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { title: string, question: string}
|
||||
) {}
|
||||
|
||||
onNoClick(): void {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
|
||||
onYesClick(): void {
|
||||
this.dialogRef.close(true);
|
||||
}
|
||||
}
|
@ -79,7 +79,6 @@ describe('LinkCreatedComponent', () => {
|
||||
portNameFormat: 'samplePortNameFormat',
|
||||
portSegmentSize: 0,
|
||||
ports: [],
|
||||
properties: undefined,
|
||||
projectId: 'sampleProjectId',
|
||||
status: 'sampleStatus',
|
||||
symbol: 'sampleSymbol',
|
||||
|
@ -59,7 +59,6 @@ describe('NodeDraggedComponent', () => {
|
||||
portNameFormat: 'samplePortNameFormat',
|
||||
portSegmentSize: 0,
|
||||
ports: [],
|
||||
properties: undefined,
|
||||
projectId: 'sampleProjectId',
|
||||
status: 'sampleStatus',
|
||||
symbol: 'sampleSymbol',
|
||||
|
@ -1,19 +1,19 @@
|
||||
<div class="content">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">Image Manager</h1>
|
||||
<button mat-raised-button color="primary" (click)="installAllImages()" class="install-all-button">
|
||||
<mat-icon>done_all</mat-icon> Install all images
|
||||
</button>
|
||||
<button mat-raised-button color="primary" (click)="pruneImages()" class="prune-button">
|
||||
<mat-icon>delete</mat-icon> Prune Images
|
||||
</button>
|
||||
<button mat-raised-button color="primary" (click)="addImageDialog()" class="add-button">
|
||||
<mat-icon>add</mat-icon> Add Image
|
||||
</button>
|
||||
<div class="col-md-9">
|
||||
<h1>Image Manager</h1>
|
||||
</div>
|
||||
<div class="col-md-3 btn-box">
|
||||
<button class="img-btn" mat-button
|
||||
(click)="addImageDialog()">
|
||||
<mat-icon>add</mat-icon> Add Image
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="default-content">
|
||||
<app-controller-discovery></app-controller-discovery>
|
||||
|
||||
@ -49,9 +49,9 @@
|
||||
<mat-header-cell *matHeaderCellDef> Image Size </mat-header-cell>
|
||||
<mat-cell *matCellDef="let row"> {{ (row.image_size/1000000).toFixed()}} MB </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<ng-container matColumnDef="delete" >
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
<button mat-button *ngIf="(selection.hasValue() && isAllSelected()) || selection.selected.length > 1" (click)="deleteAllFiles()" aria-label="Example icon button with a delete icon">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
@ -67,4 +67,4 @@
|
||||
</mat-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -2,22 +2,12 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.install-all-button {
|
||||
height: 40px;
|
||||
width: 160px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.prune-button {
|
||||
height: 40px;
|
||||
width: 160px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.add-button {
|
||||
height: 40px;
|
||||
width: 160px;
|
||||
margin: 20px;
|
||||
.img-btn{
|
||||
margin: auto;
|
||||
}
|
||||
.btn-box{
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
mat-header-cell, mat-cell {
|
||||
@ -31,3 +21,4 @@ mat-cell, mat-header-cell, mat-footer-cell {
|
||||
min-height: inherit;
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,12 @@ import { ProgressService } from 'app/common/progress/progress.service';
|
||||
import { Image } from '../../models/images';
|
||||
import { Controller } from '../../models/controller';
|
||||
import { ImageManagerService } from "../../services/image-manager.service";
|
||||
import { SelectionModel } from '@angular/cdk/collections';
|
||||
import { DataSource, SelectionModel } from '@angular/cdk/collections';
|
||||
import { AddImageDialogComponent } from './add-image-dialog/add-image-dialog.component';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ToasterService } from '../../services/toaster.service';
|
||||
import { DeleteAllImageFilesDialogComponent } from './deleteallfiles-dialog/deleteallfiles-dialog.component';
|
||||
import { imageDataSource, imageDatabase } from "./image-database-file";
|
||||
import { QuestionDialogComponent } from "@components/dialogs/question-dialog/question-dialog.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-image-manager',
|
||||
@ -37,6 +36,7 @@ export class ImageManagerComponent implements OnInit {
|
||||
private versionService: VersionService,
|
||||
private dialog: MatDialog,
|
||||
private toasterService: ToasterService,
|
||||
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
@ -60,6 +60,7 @@ export class ImageManagerComponent implements OnInit {
|
||||
},
|
||||
(error) => {
|
||||
this.toasterService.error(error.error.message)
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -99,49 +100,6 @@ export class ImageManagerComponent implements OnInit {
|
||||
this.isAllDelete = true;
|
||||
}
|
||||
|
||||
installAllImages() {
|
||||
const dialogRef = this.dialog.open(QuestionDialogComponent, {
|
||||
width: '450px',
|
||||
data: { title: 'Install all images', question: 'This will attempt to automatically create templates based on image checksums. Continue?'}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((result: boolean) => {
|
||||
if (result) {
|
||||
this.imageService.installImages(this.controller).subscribe(() => {
|
||||
this.toasterService.success('Images installed');
|
||||
},
|
||||
(error) => {
|
||||
this.toasterService.error(error.error.message)
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pruneImages() {
|
||||
const dialogRef = this.dialog.open(QuestionDialogComponent, {
|
||||
width: '450px',
|
||||
data: { title: 'Prune images', question: 'Delete all images not used by a template? This cannot be reverted.'}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((result: boolean) => {
|
||||
if (result) {
|
||||
this.imageService.pruneImages(this.controller).subscribe(
|
||||
() => {
|
||||
this.getImages()
|
||||
this.unChecked()
|
||||
this.toasterService.success('Images pruned');
|
||||
},
|
||||
(error) => {
|
||||
this.getImages()
|
||||
this.unChecked()
|
||||
this.toasterService.error(error.error.message)
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public addImageDialog() {
|
||||
const dialogRef = this.dialog.open(AddImageDialogComponent, {
|
||||
width: '600px',
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { PortsMappingEntity } from '../../../../models/ethernetHub/ports-mapping-enity';
|
||||
import { BuiltInTemplatesConfigurationService } from '../../../../services/built-in-templates-configuration.service';
|
||||
import { ToasterService } from "@services/toaster.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-ports',
|
||||
@ -13,23 +12,16 @@ export class PortsComponent implements OnInit {
|
||||
newPort: PortsMappingEntity = {
|
||||
name: '',
|
||||
port_number: 0,
|
||||
vlan: 1,
|
||||
type: 'access',
|
||||
ethertype: '0x8100',
|
||||
};
|
||||
|
||||
portTypes: string[] = [];
|
||||
etherTypes: string[] = [];
|
||||
displayedColumns: string[] = ['port_number', 'vlan', 'type', 'ethertype', 'action'];
|
||||
|
||||
constructor(
|
||||
private builtInTemplatesConfigurationService: BuiltInTemplatesConfigurationService,
|
||||
private toasterService: ToasterService,
|
||||
) {}
|
||||
constructor(private builtInTemplatesConfigurationService: BuiltInTemplatesConfigurationService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.getConfiguration();
|
||||
this.newPort.port_number = this.ethernetPorts.length;
|
||||
}
|
||||
|
||||
getConfiguration() {
|
||||
@ -38,18 +30,13 @@ export class PortsComponent implements OnInit {
|
||||
}
|
||||
|
||||
onAdd() {
|
||||
this.newPort.name = "Ethernet" + this.newPort.port_number;
|
||||
this.ethernetPorts.push(this.newPort);
|
||||
|
||||
const portExists = this.ethernetPorts.some(p => p.port_number === this.newPort.port_number);
|
||||
if (portExists) {
|
||||
this.toasterService.error(`Port number ${this.newPort.port_number} already exists.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const port: PortsMappingEntity = { ...this.newPort };
|
||||
port.name = "Ethernet" + port.port_number;
|
||||
this.ethernetPorts.push(port);
|
||||
this.ethernetPorts = [].concat(this.ethernetPorts); // this forces the refresh of the table
|
||||
this.newPort.port_number = this.ethernetPorts.length;
|
||||
this.newPort = {
|
||||
name: '',
|
||||
port_number: 0,
|
||||
};
|
||||
}
|
||||
|
||||
delete(port: PortsMappingEntity) {
|
||||
|
@ -109,24 +109,32 @@
|
||||
</mat-step>
|
||||
|
||||
<mat-step label="Network adapters">
|
||||
<div *ngIf="iosNameForm.get('platform').value">
|
||||
<div *ngFor="let index of [0, 1, 2, 3, 4, 5, 6]">
|
||||
<!-- <div *ngIf="chassis[iosNameForm.get('platform').value]">
|
||||
<div *ngFor="let index of [0,1,2,3,4,5,6,7]">
|
||||
<mat-select
|
||||
placeholder="Slot {{index}}"
|
||||
[(ngModel)]="networkAdaptersForTemplate[index]"
|
||||
[ngModelOptions]="{standalone: true}"
|
||||
*ngIf="networkAdapters[iosNameForm.get('chassis').value] && networkAdapters[iosNameForm.get('chassis').value][index]">
|
||||
<mat-option *ngFor="let option of networkAdapters[iosNameForm.get('chassis').value][index]" [value]="option">
|
||||
{{option}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div> -->
|
||||
<div *ngIf="selectedPlatform">
|
||||
<div *ngFor="let index of [0, 1, 2, 3, 4, 5, 6, 7]">
|
||||
<mat-select
|
||||
placeholder="Slot {{ index }}"
|
||||
[(ngModel)]="networkAdaptersForTemplate[index]"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
*ngIf="adapterMatrix[iosNameForm.get('platform').value][iosNameForm.get('chassis').value || '']
|
||||
&& adapterMatrix[iosNameForm.get('platform').value][iosNameForm.get('chassis').value || ''][index]"
|
||||
*ngIf="
|
||||
networkAdaptersForPlatform[iosNameForm.get('platform').value] &&
|
||||
networkAdaptersForPlatform[iosNameForm.get('platform').value][index]
|
||||
"
|
||||
>
|
||||
<mat-option
|
||||
*ngIf="adapterMatrix[iosNameForm.get('platform').value][iosNameForm.get('chassis').value|| ''][index].length > 1 &&
|
||||
!adapterMatrix[iosNameForm.get('platform').value][iosNameForm.get('chassis').value|| ''][index][0].startsWith('C7200')"
|
||||
[value]=""
|
||||
>
|
||||
{{ "" }}
|
||||
</mat-option>
|
||||
<mat-option
|
||||
*ngFor="let option of adapterMatrix[iosNameForm.get('platform').value][iosNameForm.get('chassis').value || ''][index]"
|
||||
*ngFor="let option of networkAdaptersForPlatform[iosNameForm.get('platform').value][index]"
|
||||
[value]="option"
|
||||
>
|
||||
{{ option }}
|
||||
@ -136,33 +144,33 @@
|
||||
</div>
|
||||
</mat-step>
|
||||
|
||||
<mat-step label="WIC modules" *ngIf="iosNameForm.get('platform').value && wicMatrix[iosNameForm.get('platform').value]">
|
||||
<div *ngFor="let index of [0, 1, 2]">
|
||||
<mat-select
|
||||
placeholder="WIC {{ index }}"
|
||||
[(ngModel)]="wicsForTemplate[index]"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
*ngIf="wicMatrix[iosNameForm.get('platform').value] && wicMatrix[iosNameForm.get('platform').value][index]"
|
||||
>
|
||||
<mat-option [value]="">
|
||||
{{ "" }}
|
||||
</mat-option>
|
||||
<mat-option
|
||||
*ngFor="let option of wicMatrix[iosNameForm.get('platform').value][index]"
|
||||
[value]="option"
|
||||
<mat-step label="WIC modules">
|
||||
<div *ngIf="iosNameForm.get('platform').value">
|
||||
<div *ngFor="let index of [0, 1, 2, 3]">
|
||||
<mat-select
|
||||
placeholder="WIC {{ index }}"
|
||||
[(ngModel)]="networkModulesForTemplate[index]"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
*ngIf="
|
||||
networkModules[iosNameForm.get('platform').value] &&
|
||||
networkModules[iosNameForm.get('platform').value][index]
|
||||
"
|
||||
>
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-option
|
||||
*ngFor="let option of networkModules[iosNameForm.get('platform').value][index]"
|
||||
[value]="option"
|
||||
>
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
</mat-step>
|
||||
|
||||
<mat-step label="Idle-PC">
|
||||
<form [formGroup]="iosIdlePCForm">
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="text" formControlName="idlepc" [(ngModel)]="iosTemplate.idlepc" placeholder="Idle-PC" />
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="text" [(ngModel)]="iosTemplate.idlepc" placeholder="Idle-PC" />
|
||||
</mat-form-field>
|
||||
</mat-step>
|
||||
</mat-vertical-stepper>
|
||||
</div>
|
||||
|
@ -32,8 +32,11 @@ export class AddIosTemplateComponent implements OnInit, OnDestroy {
|
||||
iosImageForm: UntypedFormGroup;
|
||||
iosNameForm: UntypedFormGroup;
|
||||
iosMemoryForm: UntypedFormGroup;
|
||||
iosIdlePCForm: UntypedFormGroup;
|
||||
selectedPlatform: string;
|
||||
|
||||
networkAdaptersForTemplate: string[] = [];
|
||||
networkModulesForTemplate: string[] = [];
|
||||
|
||||
iosImages: IosImage[] = [];
|
||||
platforms: string[] = [];
|
||||
platformsWithEtherSwitchRouterOption = {};
|
||||
@ -41,10 +44,9 @@ export class AddIosTemplateComponent implements OnInit, OnDestroy {
|
||||
chassis = {};
|
||||
defaultRam = {};
|
||||
defaultNvram = {};
|
||||
networkAdaptersForTemplate: string[] = [];
|
||||
wicsForTemplate: string[] = [];
|
||||
adapterMatrix = {};
|
||||
wicMatrix = {};
|
||||
networkAdapters = {};
|
||||
networkAdaptersForPlatform = {};
|
||||
networkModules = {};
|
||||
|
||||
ciscoUrl: string = 'https://cfn.cloudapps.cisco.com/ITDIT/CFN/jsp/SearchBySoftware.jsp';
|
||||
uploader: FileUploader;
|
||||
@ -80,10 +82,6 @@ export class AddIosTemplateComponent implements OnInit, OnDestroy {
|
||||
this.iosMemoryForm = this.formBuilder.group({
|
||||
memory: new UntypedFormControl(null, [Validators.required]),
|
||||
});
|
||||
|
||||
this.iosIdlePCForm = this.formBuilder.group({
|
||||
idlepc: new UntypedFormControl(null, [Validators.pattern(this.iosConfigurationService.getIdlepcRegex())]),
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@ -122,31 +120,19 @@ export class AddIosTemplateComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.templateMocksService.getIosTemplate().subscribe((iosTemplate: IosTemplate) => {
|
||||
this.iosTemplate = iosTemplate;
|
||||
|
||||
this.networkModules = this.iosConfigurationService.getNetworkModules();
|
||||
this.networkAdaptersForPlatform = this.iosConfigurationService.getNetworkAdaptersForPlatform();
|
||||
this.networkAdapters = this.iosConfigurationService.getNetworkAdapters();
|
||||
this.platforms = this.iosConfigurationService.getAvailablePlatforms();
|
||||
this.platformsWithEtherSwitchRouterOption = this.iosConfigurationService.getPlatformsWithEtherSwitchRouterOption();
|
||||
this.platformsWithChassis = this.iosConfigurationService.getPlatformsWithChassis();
|
||||
this.chassis = this.iosConfigurationService.getChassis();
|
||||
this.defaultRam = this.iosConfigurationService.getDefaultRamSettings();
|
||||
this.adapterMatrix = this.iosConfigurationService.getAdapterMatrix();
|
||||
this.wicMatrix = this.iosConfigurationService.getWicMatrix();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fillDefaultSlots() {
|
||||
|
||||
console.log("Fill default slots");
|
||||
if (this.iosNameForm.get('platform').value) {
|
||||
for (let i = 0; i <= 6; i++) {
|
||||
let adapters = this.adapterMatrix[this.iosNameForm.get('platform').value][this.iosNameForm.get('chassis').value || ''][i];
|
||||
if (adapters && (adapters.length === 1 || adapters[0].startsWith('C7200'))) {
|
||||
console.log("Set default adapter for slot" + i + " to " + adapters[0]);
|
||||
this.networkAdaptersForTemplate[i] = adapters[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setControllerType(controllerType: string) {
|
||||
if (controllerType === 'local') {
|
||||
this.isLocalComputerChosen = true;
|
||||
@ -180,7 +166,6 @@ export class AddIosTemplateComponent implements OnInit, OnDestroy {
|
||||
if (
|
||||
!this.iosImageForm.invalid &&
|
||||
!this.iosMemoryForm.invalid &&
|
||||
!this.iosIdlePCForm.invalid &&
|
||||
this.iosNameForm.get('templateName').value &&
|
||||
this.iosNameForm.get('platform').value
|
||||
) {
|
||||
@ -199,7 +184,7 @@ export class AddIosTemplateComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
if (this.networkAdaptersForTemplate.length > 0) this.completeAdaptersData();
|
||||
if (this.wicsForTemplate.length > 0) this.completeWicsData();
|
||||
if (this.networkModulesForTemplate.length > 0) this.completeModulesData();
|
||||
this.iosTemplate.compute_id = 'local';
|
||||
|
||||
this.iosService.addTemplate(this.controller, this.iosTemplate).subscribe((template: IosTemplate) => {
|
||||
@ -211,25 +196,44 @@ export class AddIosTemplateComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
completeAdaptersData() {
|
||||
for (let i = 0; i <= 6; i++) {
|
||||
if (this.adapterMatrix[this.iosTemplate.platform][this.iosTemplate.chassis || ''][i]) {
|
||||
if (this.networkAdaptersForTemplate[i] === undefined)
|
||||
this.iosTemplate[`slot${i}`] = ""
|
||||
else
|
||||
this.iosTemplate[`slot${i}`] = this.networkAdaptersForTemplate[i];
|
||||
if (this.chassis[this.iosTemplate.platform]) {
|
||||
if (Object.keys(this.networkAdapters[this.iosTemplate.chassis])) {
|
||||
for (let i = 0; i < Object.keys(this.networkAdapters[this.iosTemplate.chassis]).length; i++) {
|
||||
if (!this.networkAdaptersForTemplate[i]) this.networkAdaptersForTemplate[i] = '';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.networkAdaptersForPlatform[this.iosNameForm.get('platform').value]) {
|
||||
for (
|
||||
let i = 0;
|
||||
i < Object.keys(this.networkAdaptersForPlatform[this.iosNameForm.get('platform').value]).length;
|
||||
i++
|
||||
) {
|
||||
if (!this.networkAdaptersForTemplate[i]) this.networkAdaptersForTemplate[i] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.networkAdaptersForTemplate[0]) this.iosTemplate.slot0 = this.networkAdaptersForTemplate[0];
|
||||
if (this.networkAdaptersForTemplate[1]) this.iosTemplate.slot1 = this.networkAdaptersForTemplate[1];
|
||||
if (this.networkAdaptersForTemplate[2]) this.iosTemplate.slot2 = this.networkAdaptersForTemplate[2];
|
||||
if (this.networkAdaptersForTemplate[3]) this.iosTemplate.slot3 = this.networkAdaptersForTemplate[3];
|
||||
if (this.networkAdaptersForTemplate[4]) this.iosTemplate.slot4 = this.networkAdaptersForTemplate[4];
|
||||
if (this.networkAdaptersForTemplate[5]) this.iosTemplate.slot5 = this.networkAdaptersForTemplate[5];
|
||||
if (this.networkAdaptersForTemplate[6]) this.iosTemplate.slot6 = this.networkAdaptersForTemplate[6];
|
||||
if (this.networkAdaptersForTemplate[7]) this.iosTemplate.slot7 = this.networkAdaptersForTemplate[7];
|
||||
}
|
||||
|
||||
completeWicsData() {
|
||||
for (let i = 0; i <= 3; i++) {
|
||||
if (this.wicMatrix[this.iosTemplate.platform][i]) {
|
||||
if (this.wicsForTemplate[i] === undefined)
|
||||
this.iosTemplate[`wic${i}`] = ""
|
||||
else
|
||||
this.iosTemplate[`wic${i}`] = this.wicsForTemplate[i];
|
||||
completeModulesData() {
|
||||
if (Object.keys(this.networkModules[this.iosTemplate.platform])) {
|
||||
for (let i = 0; i < Object.keys(this.networkModules[this.iosTemplate.platform]).length; i++) {
|
||||
if (!this.networkModulesForTemplate[i]) this.networkModulesForTemplate[i] = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (this.networkModulesForTemplate[0]) this.iosTemplate.wic0 = this.networkModulesForTemplate[0];
|
||||
if (this.networkModulesForTemplate[1]) this.iosTemplate.wic1 = this.networkModulesForTemplate[1];
|
||||
if (this.networkModulesForTemplate[2]) this.iosTemplate.wic2 = this.networkModulesForTemplate[2];
|
||||
}
|
||||
|
||||
goBack() {
|
||||
@ -248,31 +252,25 @@ export class AddIosTemplateComponent implements OnInit, OnDestroy {
|
||||
this.selectedPlatform = name;
|
||||
}
|
||||
|
||||
if (name === 'c3620' || name === 'c3640' || name === 'c3660')
|
||||
this.iosNameForm.controls['chassis'].setValue(name.substring(1));
|
||||
else if (name === 'c1700') {
|
||||
this.iosNameForm.controls['chassis'].setValue('1760');
|
||||
if (name === 'c1700') {
|
||||
this.iosNameForm.controls['chassis'].setValue('1720');
|
||||
} else if (name === 'c2600') {
|
||||
this.iosNameForm.controls['chassis'].setValue('2651XM');
|
||||
this.iosNameForm.controls['chassis'].setValue('2610');
|
||||
} else {
|
||||
this.iosNameForm.controls['chassis'].setValue('');
|
||||
}
|
||||
this.iosMemoryForm.controls['memory'].setValue(this.defaultRam[this.selectedPlatform]);
|
||||
this.fillDefaultSlots();
|
||||
|
||||
this.iosMemoryForm.controls['memory'].setValue(this.defaultRam[name]);
|
||||
}
|
||||
|
||||
onPlatformChosen() {
|
||||
this.iosTemplate.chassis = '';
|
||||
this.networkAdaptersForTemplate = [];
|
||||
this.wicsForTemplate = [];
|
||||
if (!this.chassis[this.iosNameForm.get('platform').value])
|
||||
this.fillDefaultSlots();
|
||||
this.networkModulesForTemplate = [];
|
||||
}
|
||||
|
||||
onChassisChosen() {
|
||||
this.networkAdaptersForTemplate = [];
|
||||
if (this.chassis[this.iosNameForm.get('platform').value])
|
||||
this.fillDefaultSlots();
|
||||
}
|
||||
|
||||
cancelUploading() {
|
||||
|
@ -169,47 +169,60 @@
|
||||
<mat-panel-title> Slots </mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<h6>Adapters</h6>
|
||||
<div *ngFor="let index of [0, 1, 2, 3, 4, 5, 6]">
|
||||
<mat-select
|
||||
placeholder="Slot {{ index }}"
|
||||
[(ngModel)]="networkAdaptersForTemplate[index]"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
*ngIf="adapterMatrix[iosTemplate.platform][iosTemplate.chassis || ''][index]"
|
||||
>
|
||||
<mat-option
|
||||
*ngIf="adapterMatrix[iosTemplate.platform][iosTemplate.chassis || ''][index].length > 1 &&
|
||||
!adapterMatrix[iosTemplate.platform][iosTemplate.chassis || ''][index][0].startsWith('C7200')"
|
||||
[value]=""
|
||||
>
|
||||
{{ "" }}
|
||||
</mat-option>
|
||||
<mat-option
|
||||
*ngFor="let option of adapterMatrix[iosTemplate.platform][iosTemplate.chassis || ''][index]"
|
||||
[value]="option"
|
||||
>
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
<br />
|
||||
<div *ngIf="wicMatrix[iosTemplate.platform]">
|
||||
<h6>WICs</h6>
|
||||
<div *ngFor="let index of [0, 1, 2]">
|
||||
<div *ngIf="iosTemplate.chassis && chassis[iosTemplate.platform]">
|
||||
<div *ngFor="let index of [0, 1, 2, 3, 4, 5, 6, 7]">
|
||||
<mat-select
|
||||
placeholder="WIC {{ index }}"
|
||||
[(ngModel)]="wicsForTemplate[index]"
|
||||
placeholder="Slot {{ index }}"
|
||||
[(ngModel)]="networkAdaptersForTemplate[index]"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
*ngIf="wicMatrix[iosTemplate.platform][index]"
|
||||
*ngIf="networkAdapters[iosTemplate.chassis][index]"
|
||||
>
|
||||
<mat-option [value]="">
|
||||
{{ "" }}
|
||||
</mat-option>
|
||||
<mat-option *ngFor="let option of wicMatrix[iosTemplate.platform][index]" [value]="option">
|
||||
<mat-option *ngFor="let option of networkAdapters[iosTemplate.chassis][index]" [value]="option">
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="iosTemplate.platform && !chassis[iosTemplate.platform]">
|
||||
<div *ngFor="let index of [0, 1, 2, 3, 4, 5, 6, 7]">
|
||||
<mat-select
|
||||
placeholder="Slot {{ index }}"
|
||||
[(ngModel)]="networkAdaptersForTemplate[index]"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
*ngIf="networkAdaptersForPlatform[iosTemplate.platform][index]"
|
||||
>
|
||||
<mat-option
|
||||
*ngFor="let option of networkAdaptersForPlatform[iosTemplate.platform][index]"
|
||||
[value]="option"
|
||||
>
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<h6>WICs</h6>
|
||||
<div *ngIf="iosTemplate.wic0 || iosTemplate.wic0 === ''">
|
||||
<mat-select placeholder="WIC 0" [(ngModel)]="iosTemplate.wic0" [ngModelOptions]="{ standalone: true }">
|
||||
<mat-option *ngFor="let option of networkModules[iosTemplate.platform][0]" [value]="option">
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
<div *ngIf="iosTemplate.wic1 || iosTemplate.wic1 === ''">
|
||||
<mat-select placeholder="WIC 1" [(ngModel)]="iosTemplate.wic1" [ngModelOptions]="{ standalone: true }">
|
||||
<mat-option *ngFor="let option of networkModules[iosTemplate.platform][1]" [value]="option">
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
<div *ngIf="iosTemplate.wic2 || iosTemplate.wic2 === ''">
|
||||
<mat-select placeholder="WIC 2" [(ngModel)]="iosTemplate.wic2" [ngModelOptions]="{ standalone: true }">
|
||||
<mat-option *ngFor="let option of networkModules[iosTemplate.platform][2]" [value]="option">
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
@ -227,8 +240,8 @@
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
matInput
|
||||
formControlName="mac_addr"
|
||||
type="text"
|
||||
[(ngModel)]="iosTemplate.mac_addr"
|
||||
placeholder="Base MAC"
|
||||
@ -236,14 +249,13 @@
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
matInput
|
||||
formControlName="idlepc"
|
||||
type="text"
|
||||
[(ngModel)]="iosTemplate.idlepc"
|
||||
placeholder="Idle-PC"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<button mat-button class="idlePCFinderButton" (click)="findIdlePC()">Idle-PC finder</button><br /><br />
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput
|
||||
|
@ -1,3 +0,0 @@
|
||||
.idlePCFinderButton {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ import { ToasterService } from '../../../../services/toaster.service';
|
||||
import { MockedToasterService } from '../../../../services/toaster.service.spec';
|
||||
import { MockedActivatedRoute } from '../../preferences.component.spec';
|
||||
import { IosTemplateDetailsComponent } from './ios-template-details.component';
|
||||
import { MockedProgressService } from "@components/project-map/project-map.component.spec";
|
||||
import {ProgressService} from "../../../../common/progress/progress.service";
|
||||
|
||||
export class MockedIosService {
|
||||
public getTemplate(controller:Controller , template_id: string) {
|
||||
@ -40,7 +38,6 @@ describe('IosTemplateDetailsComponent', () => {
|
||||
let mockedControllerService = new MockedControllerService();
|
||||
let mockedIosService = new MockedIosService();
|
||||
let mockedToasterService = new MockedToasterService();
|
||||
let mockedProgressService = new MockedProgressService()
|
||||
let activatedRoute = new MockedActivatedRoute().get();
|
||||
|
||||
beforeEach(async() => {
|
||||
@ -64,7 +61,6 @@ describe('IosTemplateDetailsComponent', () => {
|
||||
{ provide: ControllerService, useValue: mockedControllerService },
|
||||
{ provide: IosService, useValue: mockedIosService },
|
||||
{ provide: ToasterService, useValue: mockedToasterService },
|
||||
{ provide: ProgressService, useValue: mockedProgressService },
|
||||
{ provide: IosConfigurationService, useClass: IosConfigurationService },
|
||||
],
|
||||
declarations: [IosTemplateDetailsComponent],
|
||||
@ -98,10 +94,9 @@ describe('IosTemplateDetailsComponent', () => {
|
||||
component.advancedForm.controls['idlemax'].setValue('0');
|
||||
component.advancedForm.controls['idlesleep'].setValue('0');
|
||||
component.advancedForm.controls['execarea'].setValue('0');
|
||||
component.advancedForm.controls['idlepc'].setValue('0x0');
|
||||
component.advancedForm.controls['mac_addr'].setValue('');
|
||||
spyOn(component, 'saveSlotsData').and.returnValue();
|
||||
|
||||
component.onSave();
|
||||
|
||||
expect(mockedIosService.saveTemplate).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -7,7 +7,6 @@ import { IosConfigurationService } from '../../../../services/ios-configuration.
|
||||
import { IosService } from '../../../../services/ios.service';
|
||||
import { ControllerService } from '../../../../services/controller.service';
|
||||
import { ToasterService } from '../../../../services/toaster.service';
|
||||
import { ProgressService } from "../../../../common/progress/progress.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-ios-template-details',
|
||||
@ -15,9 +14,12 @@ import { ProgressService } from "../../../../common/progress/progress.service";
|
||||
styleUrls: ['./ios-template-details.component.scss', '../../preferences.component.scss'],
|
||||
})
|
||||
export class IosTemplateDetailsComponent implements OnInit {
|
||||
controller: Controller;
|
||||
controller:Controller ;
|
||||
iosTemplate: IosTemplate;
|
||||
|
||||
isSymbolSelectionOpened: boolean = false;
|
||||
|
||||
networkAdaptersForTemplate: string[] = [];
|
||||
platforms: string[] = [];
|
||||
consoleTypes: string[] = [];
|
||||
categories = [];
|
||||
@ -26,10 +28,9 @@ export class IosTemplateDetailsComponent implements OnInit {
|
||||
chassis = {};
|
||||
defaultRam = {};
|
||||
defaultNvram = {};
|
||||
networkAdaptersForTemplate: string[] = [];
|
||||
wicsForTemplate: string[] = [];
|
||||
adapterMatrix = {};
|
||||
wicMatrix = {};
|
||||
networkAdapters = {};
|
||||
networkAdaptersForPlatform = {};
|
||||
networkModules = {};
|
||||
|
||||
generalSettingsForm: UntypedFormGroup;
|
||||
memoryForm: UntypedFormGroup;
|
||||
@ -42,7 +43,6 @@ export class IosTemplateDetailsComponent implements OnInit {
|
||||
private toasterService: ToasterService,
|
||||
private formBuilder: UntypedFormBuilder,
|
||||
private iosConfigurationService: IosConfigurationService,
|
||||
private progressService: ProgressService,
|
||||
private router: Router
|
||||
) {
|
||||
this.generalSettingsForm = this.formBuilder.group({
|
||||
@ -66,8 +66,6 @@ export class IosTemplateDetailsComponent implements OnInit {
|
||||
idlemax: new UntypedFormControl('', Validators.required),
|
||||
idlesleep: new UntypedFormControl('', Validators.required),
|
||||
execarea: new UntypedFormControl('', Validators.required),
|
||||
idlepc: new UntypedFormControl('', Validators.pattern(this.iosConfigurationService.getIdlepcRegex())),
|
||||
mac_addr: new UntypedFormControl('', Validators.pattern(this.iosConfigurationService.getMacAddrRegex())),
|
||||
});
|
||||
}
|
||||
|
||||
@ -80,12 +78,16 @@ export class IosTemplateDetailsComponent implements OnInit {
|
||||
this.getConfiguration();
|
||||
this.iosService.getTemplate(this.controller, template_id).subscribe((iosTemplate: IosTemplate) => {
|
||||
this.iosTemplate = iosTemplate;
|
||||
this.fillSlotsData();
|
||||
|
||||
this.fillAdaptersData();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getConfiguration() {
|
||||
this.networkModules = this.iosConfigurationService.getNetworkModules();
|
||||
this.networkAdaptersForPlatform = this.iosConfigurationService.getNetworkAdaptersForPlatform();
|
||||
this.networkAdapters = this.iosConfigurationService.getNetworkAdapters();
|
||||
this.platforms = this.iosConfigurationService.getAvailablePlatforms();
|
||||
this.platformsWithEtherSwitchRouterOption = this.iosConfigurationService.getPlatformsWithEtherSwitchRouterOption();
|
||||
this.platformsWithChassis = this.iosConfigurationService.getPlatformsWithChassis();
|
||||
@ -93,76 +95,35 @@ export class IosTemplateDetailsComponent implements OnInit {
|
||||
this.defaultRam = this.iosConfigurationService.getDefaultRamSettings();
|
||||
this.consoleTypes = this.iosConfigurationService.getConsoleTypes();
|
||||
this.categories = this.iosConfigurationService.getCategories();
|
||||
this.adapterMatrix = this.iosConfigurationService.getAdapterMatrix();
|
||||
this.wicMatrix = this.iosConfigurationService.getWicMatrix();
|
||||
}
|
||||
|
||||
findIdlePC() {
|
||||
let data = {
|
||||
"image": this.iosTemplate.image,
|
||||
"platform": this.iosTemplate.platform,
|
||||
"ram": this.iosTemplate.ram
|
||||
};
|
||||
this.progressService.activate();
|
||||
this.iosService.findIdlePC(this.controller, data).subscribe((result: any) => {
|
||||
this.progressService.deactivate();
|
||||
if (result.idlepc !== null) {
|
||||
this.iosTemplate.idlepc = result.idlepc;
|
||||
this.toasterService.success(`Idle-PC value found: ${result.idlepc}`);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
this.progressService.deactivate();
|
||||
this.toasterService.error(`Error while finding an idle-PC value`);
|
||||
}
|
||||
);
|
||||
fillAdaptersData() {
|
||||
if (this.iosTemplate.slot0) this.networkAdaptersForTemplate[0] = this.iosTemplate.slot0;
|
||||
if (this.iosTemplate.slot1) this.networkAdaptersForTemplate[1] = this.iosTemplate.slot1;
|
||||
if (this.iosTemplate.slot2) this.networkAdaptersForTemplate[2] = this.iosTemplate.slot2;
|
||||
if (this.iosTemplate.slot3) this.networkAdaptersForTemplate[3] = this.iosTemplate.slot3;
|
||||
if (this.iosTemplate.slot4) this.networkAdaptersForTemplate[4] = this.iosTemplate.slot4;
|
||||
if (this.iosTemplate.slot5) this.networkAdaptersForTemplate[5] = this.iosTemplate.slot5;
|
||||
if (this.iosTemplate.slot6) this.networkAdaptersForTemplate[6] = this.iosTemplate.slot6;
|
||||
if (this.iosTemplate.slot7) this.networkAdaptersForTemplate[7] = this.iosTemplate.slot7;
|
||||
}
|
||||
|
||||
fillSlotsData() {
|
||||
|
||||
// load network adapters
|
||||
for (let i = 0; i <= 6; i++) {
|
||||
if (this.iosTemplate[`slot${i}`]) {
|
||||
this.networkAdaptersForTemplate[i] = this.iosTemplate[`slot${i}`];
|
||||
}
|
||||
}
|
||||
|
||||
// load WICs
|
||||
for (let i = 0; i <= 3; i++) {
|
||||
if (this.iosTemplate[`wic${i}`]) {
|
||||
this.wicsForTemplate[i] = this.iosTemplate[`wic${i}`];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saveSlotsData() {
|
||||
|
||||
// save network adapters
|
||||
for (let i = 0; i <= 6; i++) {
|
||||
if (this.adapterMatrix[this.iosTemplate.platform][this.iosTemplate.chassis || ''][i]) {
|
||||
if (this.networkAdaptersForTemplate[i] === undefined)
|
||||
this.iosTemplate[`slot${i}`] = ""
|
||||
else
|
||||
this.iosTemplate[`slot${i}`] = this.networkAdaptersForTemplate[i];
|
||||
}
|
||||
}
|
||||
|
||||
// save WICs
|
||||
for (let i = 0; i <= 3; i++) {
|
||||
if (this.wicMatrix[this.iosTemplate.platform][i]) {
|
||||
if (this.wicsForTemplate[i] === undefined)
|
||||
this.iosTemplate[`wic${i}`] = ""
|
||||
else
|
||||
this.iosTemplate[`wic${i}`] = this.wicsForTemplate[i];
|
||||
}
|
||||
}
|
||||
completeAdaptersData() {
|
||||
if (this.networkAdaptersForTemplate[0]) this.iosTemplate.slot0 = this.networkAdaptersForTemplate[0];
|
||||
if (this.networkAdaptersForTemplate[1]) this.iosTemplate.slot1 = this.networkAdaptersForTemplate[1];
|
||||
if (this.networkAdaptersForTemplate[2]) this.iosTemplate.slot2 = this.networkAdaptersForTemplate[2];
|
||||
if (this.networkAdaptersForTemplate[3]) this.iosTemplate.slot3 = this.networkAdaptersForTemplate[3];
|
||||
if (this.networkAdaptersForTemplate[4]) this.iosTemplate.slot4 = this.networkAdaptersForTemplate[4];
|
||||
if (this.networkAdaptersForTemplate[5]) this.iosTemplate.slot5 = this.networkAdaptersForTemplate[5];
|
||||
if (this.networkAdaptersForTemplate[6]) this.iosTemplate.slot6 = this.networkAdaptersForTemplate[6];
|
||||
if (this.networkAdaptersForTemplate[7]) this.iosTemplate.slot7 = this.networkAdaptersForTemplate[7];
|
||||
}
|
||||
|
||||
onSave() {
|
||||
if (this.generalSettingsForm.invalid || this.memoryForm.invalid || this.advancedForm.invalid) {
|
||||
this.toasterService.error(`Fill all required fields`);
|
||||
} else {
|
||||
this.saveSlotsData();
|
||||
this.completeAdaptersData();
|
||||
|
||||
this.iosService.saveTemplate(this.controller, this.iosTemplate).subscribe((iosTemplate: IosTemplate) => {
|
||||
this.toasterService.success('Changes saved');
|
||||
|
@ -1,9 +0,0 @@
|
||||
<button
|
||||
mat-menu-item
|
||||
*ngIf="node.node_type === 'dynamips'"
|
||||
(click)="autoIdlePC()"
|
||||
>
|
||||
<mat-icon>query_builder</mat-icon>
|
||||
<span>Auto Idle-PC</span>
|
||||
</button>
|
||||
|
@ -1,36 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Node } from '../../../../../cartography/models/node';
|
||||
import { Controller } from '../../../../../models/controller';
|
||||
import { NodeService } from "@services/node.service";
|
||||
import { ToasterService } from "@services/toaster.service";
|
||||
import { ProgressService } from "../../../../../common/progress/progress.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-auto-idle-pc-action',
|
||||
templateUrl: './auto-idle-pc-action.component.html',
|
||||
})
|
||||
export class AutoIdlePcActionComponent {
|
||||
@Input() controller:Controller ;
|
||||
@Input() node: Node;
|
||||
|
||||
constructor(
|
||||
private nodeService: NodeService,
|
||||
private toasterService: ToasterService,
|
||||
private progressService: ProgressService,
|
||||
) {}
|
||||
|
||||
autoIdlePC() {
|
||||
this.progressService.activate();
|
||||
this.nodeService.getAutoIdlePC(this.controller, this.node).subscribe((result: any) => {
|
||||
this.progressService.deactivate();
|
||||
if (result.idlepc !== null) {
|
||||
this.toasterService.success(`Node ${this.node.name} updated with idle-PC value ${result.idlepc}`);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
this.progressService.deactivate();
|
||||
this.toasterService.error(`Error while updating idle-PC value for node ${this.node.name}`);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<button
|
||||
mat-menu-item
|
||||
*ngIf="node.node_type === 'dynamips'"
|
||||
(click)="idlePC()"
|
||||
>
|
||||
<mat-icon>query_builder</mat-icon>
|
||||
<span>Idle-PC</span>
|
||||
</button>
|
@ -1,28 +0,0 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Node } from '../../../../../cartography/models/node';
|
||||
import { Controller } from '../../../../../models/controller';
|
||||
import { IdlePCDialogComponent } from "@components/project-map/context-menu/dialogs/idle-pc-dialog/idle-pc-dialog.component";
|
||||
import { NodeService } from "@services/node.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-idle-pc-action',
|
||||
templateUrl: './idle-pc-action.component.html',
|
||||
})
|
||||
export class IdlePcActionComponent {
|
||||
@Input() controller:Controller ;
|
||||
@Input() node: Node;
|
||||
|
||||
constructor(private nodeService: NodeService, private dialog: MatDialog) {}
|
||||
|
||||
idlePC() {
|
||||
const dialogRef = this.dialog.open(IdlePCDialogComponent, {
|
||||
width: '500px',
|
||||
autoFocus: false,
|
||||
disableClose: true,
|
||||
});
|
||||
let instance = dialogRef.componentInstance;
|
||||
instance.controller = this.controller;
|
||||
instance.node = this.node;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<input type="file" accept=".txt, .vpc, .cfg" class="non-visible" #fileInput (change)="importConfig($event)" />
|
||||
<input type="file" accept=".txt, .vpc" class="non-visible" #fileInput (change)="importConfig($event)" />
|
||||
<button mat-menu-item (click)="triggerClick()">
|
||||
<mat-icon>call_received</mat-icon>
|
||||
<span>Import config</span>
|
||||
|
@ -94,16 +94,6 @@
|
||||
[controller]="controller"
|
||||
[node]="nodes[0]"
|
||||
></app-import-config-action>
|
||||
<app-idle-pc-action
|
||||
*ngIf="nodes.length === 1 && nodes[0].node_type === 'dynamips'"
|
||||
[controller]="controller"
|
||||
[node]="nodes[0]"
|
||||
></app-idle-pc-action>
|
||||
<app-auto-idle-pc-action
|
||||
*ngIf="nodes.length === 1 && nodes[0].node_type === 'dynamips'"
|
||||
[controller]="controller"
|
||||
[node]="nodes[0]"
|
||||
></app-auto-idle-pc-action>
|
||||
<app-move-layer-up-action
|
||||
*ngIf="!projectService.isReadOnly(project) && (drawings.length || nodes.length)"
|
||||
[controller]="controller"
|
||||
|
@ -1,25 +0,0 @@
|
||||
<div *ngIf="isComputing">
|
||||
<h6 align="center">Computing Idle-PC values, please wait...</h6>
|
||||
<div mat-dialog-content align="center">
|
||||
<mat-spinner color="accent"></mat-spinner>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!isComputing">
|
||||
<h1 mat-dialog-title>Choose an Idle-PC value</h1>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-select
|
||||
placeholder="Idle-PC"
|
||||
[ngModelOptions]="{standalone: true}"
|
||||
[(ngModel)]="idlePC"
|
||||
[matTooltip]="getTooltip()"
|
||||
matTooltipClass="multiline-tooltip"
|
||||
>
|
||||
<mat-option *ngFor="let idlepc of idlepcs" [value]="idlepc.key"> {{ idlepc.name }} </mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button *ngIf="!isComputing" (click)="onCompute()" color="accent">Compute</button>
|
||||
<button mat-button *ngIf="!isComputing" (click)="onApply()" color="accent">Apply</button>
|
||||
<button mat-button (click)="onClose()" color="accent">Close</button>
|
||||
</div>
|
@ -1,11 +0,0 @@
|
||||
.container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.multiline-tooltip {
|
||||
background-color: grey;
|
||||
color: #ffffff;
|
||||
white-space: pre-line;
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
import {Component, Input, OnInit, ViewEncapsulation} from '@angular/core';
|
||||
import {MatDialogRef} from '@angular/material/dialog';
|
||||
import {Controller} from "@models/controller";
|
||||
import {Node} from '../../../../../cartography/models/node';
|
||||
import {NodeService} from "@services/node.service";
|
||||
import {ToasterService} from "@services/toaster.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-idle-pc-dialog',
|
||||
templateUrl: './idle-pc-dialog.component.html',
|
||||
styleUrls: ['./idle-pc-dialog.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class IdlePCDialogComponent implements OnInit {
|
||||
@Input() controller: Controller;
|
||||
@Input() node: Node;
|
||||
|
||||
idlepcs = [];
|
||||
idlePC: string = '';
|
||||
isComputing: boolean = false;
|
||||
|
||||
constructor(
|
||||
private nodeService: NodeService,
|
||||
public dialogRef: MatDialogRef<IdlePCDialogComponent>,
|
||||
private toasterService: ToasterService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.onCompute();
|
||||
}
|
||||
|
||||
getTooltip(){
|
||||
return "Best Idle-PC values are obtained when IOS is in idle state, after the 'Press RETURN to get started' message has appeared on the console, messages have finished displaying on the console and you have have actually pressed the RETURN key.\n\nFinding the right idle-pc value is a trial and error process, consisting of applying different Idle-PC values and monitoring the CPU usage.\n\nSelect each value that appears in the list and click Apply, and note the CPU usage a few moments later. When you have found the value that minimises the CPU usage, apply that value.";
|
||||
}
|
||||
|
||||
onCompute() {
|
||||
this.isComputing = true;
|
||||
this.nodeService.getIdlePCProposals(this.controller, this.node).subscribe((idlepcs: any) => {
|
||||
let idlepcs_values = [];
|
||||
for (let value of idlepcs) {
|
||||
// validate idle-pc format, e.g. 0x60c09aa0
|
||||
const match = value.match(/^(0x[0-9a-f]{8})\s+\[(\d+)\]$/);
|
||||
if (match) {
|
||||
const idlepc = match[1];
|
||||
const count = parseInt(match[2], 10);
|
||||
if (50 <= count && count <= 60) {
|
||||
value += "*";
|
||||
}
|
||||
idlepcs_values.push({'key': idlepc, 'name': value})
|
||||
}
|
||||
}
|
||||
this.idlepcs = idlepcs_values;
|
||||
if (this.idlepcs.length > 0) {
|
||||
this.idlePC = this.idlepcs[0].key;
|
||||
}
|
||||
this.isComputing = false;
|
||||
});
|
||||
}
|
||||
|
||||
onClose() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
onApply() {
|
||||
if (this.idlePC && this.idlePC !== '0x0') {
|
||||
this.node.properties.idlepc = this.idlePC;
|
||||
this.nodeService.updateNode(this.controller, this.node).subscribe(() => {
|
||||
this.toasterService.success(`Node ${this.node.name} updated with idle-PC value ${this.idlePC}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -142,7 +142,7 @@ export class ImportApplianceComponent implements OnInit {
|
||||
}
|
||||
this.template = template;
|
||||
|
||||
const url = this.getUploadPath(this.controller, name);
|
||||
const url = this.getUploadPath(this.controller, template.template_type, name);
|
||||
this.uploader.queue.forEach((elem) => (elem.url = url));
|
||||
const itemToUpload = this.uploader.queue[0];
|
||||
this.uploader.uploadItem(itemToUpload);
|
||||
@ -150,7 +150,7 @@ export class ImportApplianceComponent implements OnInit {
|
||||
fileReader.readAsText(file);
|
||||
}
|
||||
|
||||
private getUploadPath(controller:Controller , filename: string) {
|
||||
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${filename}`;
|
||||
private getUploadPath(controller:Controller , emulator: string, filename: string) {
|
||||
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/${emulator}/images/${filename}`;
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@
|
||||
<mat-card [hidden]="!(!isLinuxPlatform || applianceToInstall.dynamips)">
|
||||
<div *ngIf="applianceToInstall.qemu">
|
||||
<div>
|
||||
Install the required files
|
||||
Install required files
|
||||
<button
|
||||
mat-icon-button
|
||||
matTooltip="Refresh list of images"
|
||||
@ -380,11 +380,11 @@
|
||||
{{ image.filename }}
|
||||
</span>
|
||||
<div>
|
||||
<span *ngIf="checkImageFromVersion(image.filename)">
|
||||
<mat-icon matTooltip="Ready to install" matTooltipClass="custom-tooltip">check</mat-icon>
|
||||
<span *ngIf="checkImageFromVersion(image.filename)"
|
||||
><mat-icon matTooltip="Ready to install" matTooltipClass="custom-tooltip">check</mat-icon>
|
||||
</span>
|
||||
<span *ngIf="!checkImageFromVersion(image.filename)">
|
||||
<mat-icon matTooltip="Missing" matTooltipClass="custom-tooltip">close</mat-icon>
|
||||
<span *ngIf="!checkImageFromVersion(image.filename)"
|
||||
><mat-icon matTooltip="Missing" matTooltipClass="custom-tooltip">close</mat-icon>
|
||||
</span>
|
||||
<input
|
||||
type="file"
|
||||
@ -407,7 +407,7 @@
|
||||
|
||||
<div *ngIf="applianceToInstall.iou">
|
||||
<div>
|
||||
Install the required images
|
||||
Install required images
|
||||
<button
|
||||
mat-icon-button
|
||||
matTooltip="Refresh list of images"
|
||||
@ -419,16 +419,16 @@
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let image of applianceToInstall.images">
|
||||
<div class="list-item">
|
||||
<span>
|
||||
{{ image.filename }}
|
||||
</span>
|
||||
<span *ngIf="checkImageFromVersion(image.filename)">
|
||||
<mat-icon matTooltip="Ready to install" matTooltipClass="custom-tooltip">check</mat-icon>
|
||||
</span>
|
||||
<span *ngIf="!checkImageFromVersion(image.filename)">
|
||||
<mat-icon matTooltip="Missing" matTooltipClass="custom-tooltip">close</mat-icon>
|
||||
</span>
|
||||
<div>
|
||||
{{ image.filename }}
|
||||
</div>
|
||||
<div>
|
||||
<span *ngIf="checkImageFromVersion(image.filename)"
|
||||
><mat-icon matTooltip="Ready to install" matTooltipClass="custom-tooltip">check</mat-icon>
|
||||
</span>
|
||||
<span *ngIf="!checkImageFromVersion(image.filename)"
|
||||
><mat-icon matTooltip="Missing" matTooltipClass="custom-tooltip">close</mat-icon>
|
||||
</span>
|
||||
<input
|
||||
type="file"
|
||||
class="non-visible"
|
||||
|
@ -11,7 +11,7 @@ import { FileItem, FileUploader, ParsedResponseHeaders } from 'ng2-file-upload';
|
||||
import * as SparkMD5 from 'spark-md5';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { ProgressService } from '../../../common/progress/progress.service';
|
||||
import { InformationDialogComponent } from '../../../components/dialogs/information-dialog/information-dialog.component';
|
||||
import { InformationDialogComponent } from '../../../components/dialogs/information-dialog.component';
|
||||
import { Appliance, Image, Version } from '../../../models/appliance';
|
||||
import { Project } from '../../../models/project';
|
||||
import { QemuBinary } from '../../../models/qemu/qemu-binary';
|
||||
@ -266,7 +266,7 @@ export class NewTemplateDialogComponent implements OnInit {
|
||||
if (appliance.iou) emulator = 'iou';
|
||||
if (appliance.qemu) emulator = 'qemu';
|
||||
|
||||
const url = this.applianceService.getUploadPath(this.controller, fileName);
|
||||
const url = this.applianceService.getUploadPath(this.controller, emulator, fileName);
|
||||
this.uploader.queue.forEach((elem) => (elem.url = url));
|
||||
|
||||
const itemToUpload = this.uploader.queue[0];
|
||||
@ -341,6 +341,8 @@ export class NewTemplateDialogComponent implements OnInit {
|
||||
dialogRef.componentInstance.appliance = object;
|
||||
}
|
||||
|
||||
|
||||
|
||||
importImage(event, imageName) {
|
||||
this.computeChecksumMd5(event.target.files[0], false).then((output) => {
|
||||
let imageToInstall = this.applianceToInstall.images.filter((n) => n.filename === imageName)[0];
|
||||
@ -357,21 +359,22 @@ export class NewTemplateDialogComponent implements OnInit {
|
||||
The MD5 sum is ${output} and should be ${imageToInstall.md5sum}. Do you want to accept it at your own risks?`;
|
||||
dialogRef.afterClosed().subscribe((answer: boolean) => {
|
||||
if (answer) {
|
||||
this.importImageFile(event, imageName);
|
||||
this.importImageFile(event);
|
||||
this.openSnackBar()
|
||||
} else {
|
||||
this.uploaderImage.clearQueue();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.importImageFile(event, imageName);
|
||||
this.importImageFile(event);
|
||||
this.openSnackBar()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
importImageFile(event, imageName) {
|
||||
importImageFile(event) {
|
||||
let name = event.target.files[0].name.split('-')[0];
|
||||
let fileName = event.target.files[0].name;
|
||||
let file = event.target.files[0];
|
||||
let fileReader: FileReader = new FileReader();
|
||||
let emulator;
|
||||
@ -381,7 +384,7 @@ export class NewTemplateDialogComponent implements OnInit {
|
||||
if (this.applianceToInstall.dynamips) emulator = 'dynamips';
|
||||
if (this.applianceToInstall.iou) emulator = 'iou';
|
||||
|
||||
const url = this.applianceService.getUploadPath(this.controller, imageName);
|
||||
const url = this.applianceService.getUploadPath(this.controller, emulator, fileName);
|
||||
this.uploaderImage.queue.forEach((elem) => (elem.url = url));
|
||||
|
||||
const itemToUpload = this.uploaderImage.queue[0];
|
||||
|
@ -33,27 +33,17 @@
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput
|
||||
formControlName="mac_address"
|
||||
type="text"
|
||||
[(ngModel)]="node.properties.mac_address"
|
||||
placeholder="Base MAC"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<input formControlName="memory" matInput type="number" min="0" [(ngModel)]="node.properties.memory" placeholder="Maximum memory">
|
||||
<input formControlName="memory" matInput type="number" min="1" [(ngModel)]="node.properties.memory" placeholder="Maximum memory">
|
||||
<span matSuffix>MB</span>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<input formControlName="cpus" matInput type="number" min="0" [(ngModel)]="node.properties.cpus" placeholder="Maximum CPUs">
|
||||
<input formControlName="cpus" matInput type="number" min="1" [(ngModel)]="node.properties.cpus" placeholder="Maximum CPUs">
|
||||
</mat-form-field>
|
||||
|
||||
<!-- <button mat-button class="form-field" (click)="configureCustomAdapters()">-->
|
||||
<!-- Configure custom adapters-->
|
||||
<!-- </button>-->
|
||||
<button mat-button class="form-field" (click)="configureCustomAdapters()">
|
||||
Configure custom adapters
|
||||
</button>
|
||||
|
||||
<mat-form-field class="select">
|
||||
<mat-select
|
||||
|
@ -42,7 +42,6 @@ export class ConfiguratorDialogDockerComponent implements OnInit {
|
||||
this.generalSettingsForm = this.formBuilder.group({
|
||||
name: new UntypedFormControl('', Validators.required),
|
||||
adapter: new UntypedFormControl('', Validators.required),
|
||||
mac_address: new UntypedFormControl('', Validators.pattern(this.dockerConfigurationService.getMacAddrRegex())),
|
||||
memory: new UntypedFormControl('', nonNegativeValidator.get),
|
||||
cpus: new UntypedFormControl('', nonNegativeValidator.get),
|
||||
startCommand: new UntypedFormControl(''),
|
||||
|
@ -7,31 +7,11 @@
|
||||
<mat-tab-group *ngIf="name">
|
||||
<mat-tab label="General settings">
|
||||
<br />
|
||||
<mat-label>Platform: {{ node.properties.platform }}</mat-label>
|
||||
<mat-label *ngIf="node.properties.chassis"> (chassis: {{ node.properties.chassis }})</mat-label>
|
||||
<br /><br />
|
||||
<form [formGroup]="generalSettingsForm">
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="text" formControlName="name" [(ngModel)]="node.name" placeholder="Name" />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="text" formControlName="path" [(ngModel)]="node.properties.image" placeholder="IOS image path"/>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<mat-form-field class="select" *ngIf="node.properties.midplane">
|
||||
<mat-select placeholder="Midplane" [(ngModel)]="node.properties.midplane">
|
||||
<mat-option *ngFor="let type of MidplaneTypes" [value]="type">
|
||||
{{ type }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="select" *ngIf="node.properties.npe">
|
||||
<mat-select placeholder="NPE" [(ngModel)]="node.properties.npe">
|
||||
<mat-option *ngFor="let type of NPETypes" [value]="type">
|
||||
{{ type }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="select">
|
||||
<mat-select placeholder="Console type" [(ngModel)]="node.console_type">
|
||||
<mat-option *ngFor="let type of consoleTypes" [value]="type">
|
||||
@ -40,7 +20,7 @@
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="select">
|
||||
<mat-select placeholder="Auxiliary console type" [(ngModel)]="node.properties.aux_type">
|
||||
<mat-select placeholder="Auxiliary console type" [(ngModel)]="node.aux_type">
|
||||
<mat-option *ngFor="let type of consoleTypes" [value]="type">
|
||||
{{ type }}
|
||||
</mat-option>
|
||||
@ -56,144 +36,23 @@
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
min="0"
|
||||
formControlName="ram"
|
||||
[(ngModel)]="node.properties.ram"
|
||||
placeholder="RAM size"
|
||||
/>
|
||||
<span matSuffix>MiB</span>
|
||||
<span matSuffix>MB</span>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
min="0"
|
||||
formControlName="nvram"
|
||||
[(ngModel)]="node.properties.nvram"
|
||||
placeholder="NVRAM size"
|
||||
/>
|
||||
<span matSuffix>MiB</span>
|
||||
<span matSuffix>MB</span>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<mat-form-field class="form-field" *ngIf="node.properties.iomem">
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
[(ngModel)]="node.properties.iomem"
|
||||
placeholder="I/O memory"
|
||||
/>
|
||||
<span matSuffix>%</span>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
min="0"
|
||||
[(ngModel)]="node.properties.disk0"
|
||||
placeholder="PCMCIA disk0"
|
||||
/>
|
||||
<span matSuffix>MiB</span>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
min="0"
|
||||
[(ngModel)]="node.properties.disk1"
|
||||
placeholder="PCMCIA disk1"
|
||||
/>
|
||||
<span matSuffix>MiB</span>
|
||||
</mat-form-field>
|
||||
<mat-checkbox [(ngModel)]="node.properties.auto_delete_disks"> Automatically delete NVRAM and disk files </mat-checkbox><br />
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab label="Slots">
|
||||
<br />
|
||||
<h6>Adapters</h6>
|
||||
<div *ngFor="let index of [0, 1, 2, 3, 4, 5, 6]">
|
||||
<mat-select
|
||||
placeholder="Slot {{ index }}"
|
||||
[(ngModel)]="networkAdaptersForNode[index]"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
*ngIf="adapterMatrix[node.properties.platform][node.properties.chassis || ''][index]"
|
||||
>
|
||||
<mat-option
|
||||
*ngIf="adapterMatrix[node.properties.platform][node.properties.chassis || ''][index].length > 1 &&
|
||||
!adapterMatrix[node.properties.platform][node.properties.chassis || ''][index][0].startsWith('C7200')"
|
||||
[value]=""
|
||||
>
|
||||
{{ "" }}
|
||||
</mat-option>
|
||||
<mat-option
|
||||
*ngFor="let option of adapterMatrix[node.properties.platform][node.properties.chassis || ''][index]"
|
||||
[value]="option"
|
||||
>
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
<br />
|
||||
<div *ngIf="wicMatrix[node.properties.platform]">
|
||||
<h6>WICs</h6>
|
||||
<div *ngFor="let index of [0, 1, 2]">
|
||||
<mat-select
|
||||
placeholder="WIC {{ index }}"
|
||||
[(ngModel)]="wicsForNode[index]"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
*ngIf="wicMatrix[node.properties.platform][index]"
|
||||
>
|
||||
<mat-option [value]="">
|
||||
{{ "" }}
|
||||
</mat-option>
|
||||
<mat-option *ngFor="let option of wicMatrix[node.properties.platform][index]" [value]="option">
|
||||
{{ option }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab label="Advanced">
|
||||
<mat-card>
|
||||
<mat-card-title></mat-card-title>
|
||||
<mat-card-subtitle> System </mat-card-subtitle>
|
||||
<mat-card-content>
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="text" [(ngModel)]="node.properties.system_id" placeholder="System ID" />
|
||||
</mat-form-field>
|
||||
<form [formGroup]="advancedSettingsForm">
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput formControlName="mac_addr" type="text" [(ngModel)]="node.properties.mac_addr" placeholder="Base MAC" />
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<mat-card>
|
||||
<mat-card-title></mat-card-title>
|
||||
<mat-card-subtitle> Optimizations </mat-card-subtitle>
|
||||
<mat-card-content>
|
||||
<form [formGroup]="advancedSettingsForm">
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="text" formControlName="idlepc" [(ngModel)]="node.properties.idlepc" placeholder="Idle-PC" />
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="number" min="0" [(ngModel)]="node.properties.idlemax" placeholder="Idlemax" />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="number" min="0" [(ngModel)]="node.properties.idlesleep" placeholder="Idlesleep" />
|
||||
<span matSuffix>ms</span>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="number" min="0" [(ngModel)]="node.properties.exec_area" placeholder="Exec area" />
|
||||
<span matSuffix>MiB</span>
|
||||
</mat-form-field>
|
||||
<mat-checkbox [(ngModel)]="node.properties.mmap"> Enable mmap support </mat-checkbox><br />
|
||||
<mat-checkbox [(ngModel)]="node.properties.sparsemem"> Enable sparse memory support </mat-checkbox><br />
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab label="Usage">
|
||||
|
@ -18,14 +18,7 @@ export class ConfiguratorDialogIosComponent implements OnInit {
|
||||
name: string;
|
||||
generalSettingsForm: UntypedFormGroup;
|
||||
memoryForm: UntypedFormGroup;
|
||||
advancedSettingsForm: UntypedFormGroup;
|
||||
consoleTypes: string[] = [];
|
||||
NPETypes: string[] = [];
|
||||
MidplaneTypes: string[] = [];
|
||||
networkAdaptersForNode: string[] = [];
|
||||
wicsForNode: string[] = [];
|
||||
adapterMatrix = {};
|
||||
wicMatrix = {};
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<ConfiguratorDialogIosComponent>,
|
||||
@ -36,18 +29,12 @@ export class ConfiguratorDialogIosComponent implements OnInit {
|
||||
) {
|
||||
this.generalSettingsForm = this.formBuilder.group({
|
||||
name: new UntypedFormControl('', Validators.required),
|
||||
path: new UntypedFormControl('', Validators.required),
|
||||
});
|
||||
|
||||
this.memoryForm = this.formBuilder.group({
|
||||
ram: new UntypedFormControl('', Validators.required),
|
||||
nvram: new UntypedFormControl('', Validators.required),
|
||||
});
|
||||
|
||||
this.advancedSettingsForm = this.formBuilder.group({
|
||||
mac_addr: new UntypedFormControl('', Validators.pattern(this.configurationService.getMacAddrRegex())),
|
||||
idlepc: new UntypedFormControl('', Validators.pattern(this.configurationService.getIdlepcRegex())),
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@ -55,61 +42,15 @@ export class ConfiguratorDialogIosComponent implements OnInit {
|
||||
this.node = node;
|
||||
this.name = node.name;
|
||||
this.getConfiguration();
|
||||
this.fillSlotsData();
|
||||
});
|
||||
}
|
||||
|
||||
getConfiguration() {
|
||||
this.consoleTypes = this.configurationService.getConsoleTypes();
|
||||
this.NPETypes = this.configurationService.getNPETypes();
|
||||
this.MidplaneTypes = this.configurationService.getMidplaneTypes();
|
||||
this.adapterMatrix = this.configurationService.getAdapterMatrix();
|
||||
this.wicMatrix = this.configurationService.getWicMatrix();
|
||||
}
|
||||
|
||||
fillSlotsData() {
|
||||
|
||||
// load network adapters
|
||||
for (let i = 0; i <= 6; i++) {
|
||||
if (this.node.properties[`slot${i}`]) {
|
||||
this.networkAdaptersForNode[i] = this.node.properties[`slot${i}`];
|
||||
}
|
||||
}
|
||||
|
||||
// load WICs
|
||||
for (let i = 0; i <= 3; i++) {
|
||||
if (this.node.properties[`wic${i}`]) {
|
||||
this.wicsForNode[i] = this.node.properties[`wic${i}`];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saveSlotsData() {
|
||||
|
||||
// save network adapters
|
||||
for (let i = 0; i <= 6; i++) {
|
||||
if (this.adapterMatrix[this.node.properties.platform][this.node.properties.chassis || ''][i]) {
|
||||
if (this.networkAdaptersForNode[i] === undefined)
|
||||
this.node.properties[`slot${i}`] = ""
|
||||
else
|
||||
this.node.properties[`slot${i}`] = this.networkAdaptersForNode[i];
|
||||
}
|
||||
}
|
||||
|
||||
// save WICs
|
||||
for (let i = 0; i <= 3; i++) {
|
||||
if (this.wicMatrix[this.node.properties.platform][i]) {
|
||||
if (this.wicsForNode[i] === undefined)
|
||||
this.node.properties[`wic${i}`] = ""
|
||||
else
|
||||
this.node.properties[`wic${i}`] = this.wicsForNode[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSaveClick() {
|
||||
if (this.generalSettingsForm.valid && this.memoryForm.valid && this.advancedSettingsForm.valid) {
|
||||
this.saveSlotsData();
|
||||
if (this.generalSettingsForm.valid && this.memoryForm.valid) {
|
||||
this.nodeService.updateNode(this.controller, this.node).subscribe(() => {
|
||||
this.toasterService.success(`Node ${this.node.name} updated.`);
|
||||
this.onCancelClick();
|
||||
|
@ -152,43 +152,15 @@
|
||||
</mat-tab>
|
||||
<mat-tab label="Network">
|
||||
<br />
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput
|
||||
min=0
|
||||
type="number"
|
||||
[(ngModel)]="node.properties.adapters"
|
||||
placeholder="Adapters"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<form [formGroup]="networkSettingsForm">
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput
|
||||
formControlName="mac_address"
|
||||
type="text"
|
||||
[(ngModel)]="node.properties.mac_address"
|
||||
placeholder="Base MAC"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<mat-select placeholder="Type" [(ngModel)]="node.properties.adapter_type">
|
||||
<mat-option *ngFor="let type of networkTypes" [value]="type.value">
|
||||
{{ type.name }} ({{ type.value }})
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<!-- <button mat-button class="form-field" (click)="setCustomAdaptersConfiguratorState(true)">-->
|
||||
<!-- Configure custom adapters-->
|
||||
<!-- </button>-->
|
||||
<br /><br /><mat-checkbox [(ngModel)]="node.properties.replicate_network_connection_state">
|
||||
<br /><mat-checkbox [(ngModel)]="node.properties.replicate_network_connection_state">
|
||||
Replicate network connection state
|
||||
</mat-checkbox>
|
||||
<!-- <app-custom-adapters-table-->
|
||||
<!-- #customAdapters-->
|
||||
<!-- [networkTypes]="networkTypes"-->
|
||||
<!-- [displayedColumns]="displayedColumns"-->
|
||||
<!-- [adapters]="node.ports"-->
|
||||
<!-- ></app-custom-adapters-table>-->
|
||||
<app-custom-adapters-table
|
||||
#customAdapters
|
||||
[networkTypes]="networkTypes"
|
||||
[displayedColumns]="displayedColumns"
|
||||
[adapters]="node.ports"
|
||||
></app-custom-adapters-table>
|
||||
</mat-tab>
|
||||
<mat-tab label="Advanced">
|
||||
<mat-card>
|
||||
|
@ -22,7 +22,6 @@ export class ConfiguratorDialogQemuComponent implements OnInit {
|
||||
node: Node;
|
||||
name: string;
|
||||
generalSettingsForm: UntypedFormGroup;
|
||||
networkSettingsForm: UntypedFormGroup;
|
||||
consoleTypes: string[] = [];
|
||||
onCloseOptions = [];
|
||||
bootPriorities = [];
|
||||
@ -55,10 +54,6 @@ export class ConfiguratorDialogQemuComponent implements OnInit {
|
||||
name: new UntypedFormControl('', Validators.required),
|
||||
ram: new UntypedFormControl('', Validators.required),
|
||||
});
|
||||
|
||||
this.networkSettingsForm = this.formBuilder.group({
|
||||
mac_address: new UntypedFormControl('', Validators.pattern(this.qemuConfigurationService.getMacAddrRegex())),
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@ -108,16 +103,16 @@ export class ConfiguratorDialogQemuComponent implements OnInit {
|
||||
}
|
||||
|
||||
onSaveClick() {
|
||||
if (this.generalSettingsForm.valid && this.networkSettingsForm.valid) {
|
||||
// this.node.custom_adapters = [];
|
||||
// this.customAdapters.adapters.forEach((n) => {
|
||||
// this.node.custom_adapters.push({
|
||||
// adapter_number: n.adapter_number,
|
||||
// adapter_type: n.adapter_type,
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// this.node.properties.adapters = this.node.custom_adapters.length;
|
||||
if (this.generalSettingsForm.valid) {
|
||||
this.node.custom_adapters = [];
|
||||
this.customAdapters.adapters.forEach((n) => {
|
||||
this.node.custom_adapters.push({
|
||||
adapter_number: n.adapter_number,
|
||||
adapter_type: n.adapter_type,
|
||||
});
|
||||
});
|
||||
|
||||
this.node.properties.adapters = this.node.custom_adapters.length;
|
||||
|
||||
this.nodeService.updateNodeWithCustomAdapters(this.controller, this.node).subscribe(() => {
|
||||
this.toasterService.success(`Node ${this.node.name} updated.`);
|
||||
|
@ -98,25 +98,42 @@ export class ProjectMapMenuComponent implements OnInit, OnDestroy {
|
||||
|
||||
private async saveImage(screenshotProperties: Screenshot) {
|
||||
if (screenshotProperties.filetype === 'png') {
|
||||
let splittedSvg = document.getElementsByTagName('svg')[0].outerHTML.split('image');
|
||||
let i = 1;
|
||||
try {
|
||||
// Get the SVG element and clone it to avoid modifying the original
|
||||
const originalSvg = document.getElementsByTagName('svg')[0];
|
||||
const svgClone = originalSvg.cloneNode(true) as SVGElement;
|
||||
|
||||
while (i < splittedSvg.length) {
|
||||
let splittedImage = splittedSvg[i].split('"');
|
||||
let splittedUrl = splittedImage[1].split('/');
|
||||
// Process any embedded images
|
||||
const images = svgClone.getElementsByTagName('image');
|
||||
for (let i = 0; i < images.length; i++) {
|
||||
const image = images[i];
|
||||
const href = image.getAttribute('href') || image.getAttribute('xlink:href');
|
||||
if (href) {
|
||||
const urlParts = href.split('/');
|
||||
const symbolId = urlParts[urlParts.length - 1];
|
||||
try {
|
||||
const rawSvg = await this.symbolService.raw(this.controller, symbolId).toPromise();
|
||||
if (rawSvg) {
|
||||
// Extract SVG content, fallback to raw content if parsing fails
|
||||
const svgContent = rawSvg.includes('-->') ?
|
||||
rawSvg.split('-->')[1].trim() :
|
||||
rawSvg.trim();
|
||||
image.outerHTML = svgContent;
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`Failed to process embedded image: ${symbolId}`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let elem = await this.symbolService.raw(this.controller, splittedUrl[7]).toPromise();
|
||||
let splittedElement = elem.split('-->');
|
||||
splittedSvg[i] = splittedElement[1].substring(2);
|
||||
i += 2;
|
||||
// Create a temporary container and save as PNG
|
||||
const container = document.createElement('div');
|
||||
container.appendChild(svgClone);
|
||||
svg.saveSvgAsPng(svgClone, `${screenshotProperties.name}.png`);
|
||||
} catch (err) {
|
||||
console.error('Failed to save PNG:', err);
|
||||
throw err;
|
||||
}
|
||||
let svgString = splittedSvg.join();
|
||||
|
||||
let placeholder = document.createElement('div');
|
||||
placeholder.innerHTML = svgString;
|
||||
let element = placeholder.firstChild;
|
||||
|
||||
svg.saveSvgAsPng(element, `${screenshotProperties.name}.png`);
|
||||
} else {
|
||||
var svg_el = select('svg').attr('version', 1.1).attr('xmlns', 'http://www.w3.org/2000/svg').node();
|
||||
downloadSvg(select('svg').node(), `${screenshotProperties.name}`);
|
||||
|
@ -25,7 +25,7 @@ export class ScreenshotDialogComponent implements OnInit {
|
||||
this.nameForm = this.formBuilder.group({
|
||||
screenshotName: new UntypedFormControl(`screenshot-${Date.now()}`, [Validators.required]),
|
||||
});
|
||||
this.isPngAvailable = this.electronService.isWindows || this.deviceService.getDeviceInfo().os === 'Windows';
|
||||
this.isPngAvailable = true;
|
||||
}
|
||||
|
||||
ngOnInit() {}
|
||||
|
@ -10,7 +10,7 @@ import { ProjectService } from '../../../services/project.service';
|
||||
styleUrls: ['./choose-name-dialog.component.scss'],
|
||||
})
|
||||
export class ChooseNameDialogComponent implements OnInit {
|
||||
@Input() controller: Controller;
|
||||
@Input() controller:Controller ;
|
||||
@Input() project: Project;
|
||||
name: string;
|
||||
|
||||
|
@ -21,18 +21,8 @@ export class ReadmeEditorComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.projectService.getReadmeFile(this.controller, this.project.project_id).subscribe({
|
||||
next: (file) => {
|
||||
if (file) {
|
||||
this.markdown = file;
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
if (err.status === 404) {
|
||||
// File doesn't exist yet, which is fine
|
||||
this.markdown = '';
|
||||
}
|
||||
}
|
||||
this.projectService.getReadmeFile(this.controller, this.project.project_id).subscribe(file => {
|
||||
if (file) this.markdown = file;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
|
||||
@Injectable()
|
||||
export class ProjectNameValidator {
|
||||
get(projectName) {
|
||||
var pattern = new RegExp(/[~`!#$%\^&*+=\[\]\\';,/{}|\\"<>\?]/);
|
||||
var pattern = new RegExp(/[~`!#$%\^&*+=\[\]\\';,/{}|\\":<>\?]/);
|
||||
|
||||
if (!pattern.test(projectName.value)) {
|
||||
return null;
|
||||
|
@ -67,7 +67,7 @@ export class EditUserDialogComponent implements OnInit {
|
||||
|
||||
updatedUser.user_id = this.data.user.user_id;
|
||||
console.log(updatedUser)
|
||||
this.userService.update(this.data.controller, updatedUser, false)
|
||||
this.userService.update(this.data.controller, updatedUser)
|
||||
.subscribe((user: User) => {
|
||||
console.log("Done ", user)
|
||||
this.toasterService.success(`User ${user.username} updated`);
|
||||
|
@ -1,10 +1,10 @@
|
||||
<h1 mat-dialog-title>Change password for {{ user.username }}</h1>
|
||||
<h1 mat-dialog-title>Change password for user : </h1>
|
||||
<div>
|
||||
<form [formGroup]="editPasswordForm" class="input-field">
|
||||
<mat-form-field class="input-field">
|
||||
<input matInput type="password" formControlName="password" placeholder="Password"/>
|
||||
<mat-error *ngIf="passwordForm.password?.touched && passwordForm.password?.errors"
|
||||
>Password must be at least 8 characters long and contain at least one digit, one lowercase letter and one uppercase letter.
|
||||
>Password must be between 6 and 100 characters.
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="input-field">
|
||||
|
@ -18,18 +18,17 @@ export class ChangeUserPasswordComponent implements OnInit {
|
||||
user: User;
|
||||
|
||||
constructor(private dialogRef: MatDialogRef<ChangeUserPasswordComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { user: User, controller: Controller, self_update: boolean },
|
||||
@Inject(MAT_DIALOG_DATA) public data: { user: User, controller: Controller },
|
||||
private userService: UserService,
|
||||
private toasterService: ToasterService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
const password_regex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8}$/;
|
||||
this.user = this.data.user;
|
||||
this.editPasswordForm = new UntypedFormGroup({
|
||||
password: new UntypedFormControl(null,
|
||||
[Validators.minLength(6), Validators.maxLength(100), Validators.pattern(password_regex), Validators.required] ),
|
||||
[Validators.minLength(6), Validators.maxLength(100), Validators.required] ),
|
||||
confirmPassword: new UntypedFormControl(null,
|
||||
[Validators.minLength(6), Validators.maxLength(100), Validators.pattern(password_regex), Validators.required] ),
|
||||
[Validators.minLength(6), Validators.maxLength(100), Validators.required] ),
|
||||
},{
|
||||
validators: [matchingPassword]
|
||||
})
|
||||
@ -53,14 +52,16 @@ export class ChangeUserPasswordComponent implements OnInit {
|
||||
updatedUser['password'] = this.editPasswordForm.get('password').value;
|
||||
updatedUser['user_id'] = this.user.user_id;
|
||||
|
||||
this.userService.update(this.data.controller, updatedUser, this.data.self_update)
|
||||
console.log(updatedUser);
|
||||
|
||||
this.userService.update(this.data.controller, updatedUser)
|
||||
.subscribe((user: User) => {
|
||||
this.toasterService.success(`User ${user.username} password updated`);
|
||||
this.editPasswordForm.reset();
|
||||
this.dialogRef.close(true);
|
||||
},
|
||||
(error) => {
|
||||
this.toasterService.error('Cannot update password for user: ' + error);
|
||||
this.toasterService.error('Cannot update password for user : ' + error);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ export class UserDetailComponent implements OnInit {
|
||||
const updatedUser = this.getUpdatedValues();
|
||||
updatedUser['user_id'] = this.user.user_id;
|
||||
|
||||
this.userService.update(this.controller, updatedUser, false)
|
||||
this.userService.update(this.controller, updatedUser)
|
||||
.subscribe((user: User) => {
|
||||
this.toasterService.success(`User ${user.username} updated`);
|
||||
},
|
||||
|
@ -11,7 +11,6 @@
|
||||
* Author: Sylvain MATHIEU, Elise LEBEAU
|
||||
*/
|
||||
import {Component, OnInit, QueryList, ViewChild, ViewChildren} from '@angular/core';
|
||||
import {Location} from '@angular/common';
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {Controller} from "@models/controller";
|
||||
import {MatSort} from "@angular/material/sort";
|
||||
@ -50,8 +49,7 @@ export class UserManagementComponent implements OnInit {
|
||||
private progressService: ProgressService,
|
||||
private controllerService: ControllerService,
|
||||
public dialog: MatDialog,
|
||||
private toasterService: ToasterService,
|
||||
private location: Location) { }
|
||||
private toasterService: ToasterService) { }
|
||||
|
||||
ngOnInit() {
|
||||
const controllerId = this.route.parent.snapshot.paramMap.get('controller_id');
|
||||
@ -90,8 +88,6 @@ export class UserManagementComponent implements OnInit {
|
||||
},
|
||||
(error) => {
|
||||
this.progressService.setError(error);
|
||||
this.toasterService.error(`Cannot open the user management page`);
|
||||
this.location.back();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -7,13 +7,11 @@
|
||||
<div class="default-content">
|
||||
<mat-card *ngIf="user">
|
||||
<mat-list>
|
||||
<mat-list-item> Username: {{ user.username }} </mat-list-item>
|
||||
<mat-list-item> Full name: {{ user.full_name }} </mat-list-item>
|
||||
<mat-list-item> Email: {{ user.email }} </mat-list-item>
|
||||
<mat-list-item> Username: {{user.username}} </mat-list-item>
|
||||
<mat-list-item> Full name: {{user.full_name}} </mat-list-item>
|
||||
<mat-list-item> Email: {{user.email}} </mat-list-item>
|
||||
</mat-list>
|
||||
<div class="buttons-bar">
|
||||
<button mat-raised-button color="primary" class="full_width" (click)="changePassword()">Change password</button><br />
|
||||
</div>
|
||||
|
||||
<div class="buttons-bar">
|
||||
<button mat-raised-button color="primary" class="full_width" (click)="copyToken()">Click to copy access token</button><br />
|
||||
</div>
|
||||
|
@ -5,8 +5,6 @@ import { UserService } from '../../../services/user.service';
|
||||
import { ToasterService } from '../../../services/toaster.service';
|
||||
import { User } from '../../../models/users/user';
|
||||
import { Controller } from '../../../models/controller';
|
||||
import { ChangeUserPasswordComponent } from "@components/user-management/user-detail/change-user-password/change-user-password.component";
|
||||
import { MatDialog } from "@angular/material/dialog";
|
||||
|
||||
@Component({
|
||||
selector: 'app-logged-user',
|
||||
@ -21,8 +19,7 @@ export class LoggedUserComponent implements OnInit {
|
||||
private route: ActivatedRoute,
|
||||
private controllerService: ControllerService,
|
||||
private userService: UserService,
|
||||
private toasterService: ToasterService,
|
||||
public dialog: MatDialog
|
||||
private toasterService: ToasterService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@ -35,11 +32,6 @@ export class LoggedUserComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
changePassword() {
|
||||
this.dialog.open<ChangeUserPasswordComponent>(ChangeUserPasswordComponent,
|
||||
{width: '500px', height: '300px', data: {user: this.user, controller: this.controller, self_update: true}});
|
||||
}
|
||||
|
||||
copyToken() {
|
||||
const selBox = document.createElement('textarea');
|
||||
selBox.style.position = 'fixed';
|
||||
|
@ -17,8 +17,8 @@ export class ApplianceService {
|
||||
return this.httpController.get<Appliance>(controller, url) as Observable<Appliance>;
|
||||
}
|
||||
|
||||
getUploadPath(controller:Controller, filename: string) {
|
||||
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${filename}`;
|
||||
getUploadPath(controller:Controller , emulator: string, filename: string) {
|
||||
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${filename}?allow_raw_image=true`;
|
||||
}
|
||||
|
||||
updateAppliances(controller:Controller ): Observable<Appliance[]> {
|
||||
|
@ -14,6 +14,10 @@ export class ComputeService {
|
||||
return this.httpController.get<Compute[]>(controller, '/computes') as Observable<Compute[]>;
|
||||
}
|
||||
|
||||
getUploadPath(controller:Controller , emulator: string, filename: string) {
|
||||
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/${emulator}/images/${filename}`;
|
||||
}
|
||||
|
||||
getStatistics(controller:Controller ): Observable<ComputeStatistics[]> {
|
||||
return this.httpController.get(controller, `/statistics`);
|
||||
}
|
||||
|
@ -27,8 +27,4 @@ export class DockerConfigurationService {
|
||||
|
||||
return consoleResolutions;
|
||||
}
|
||||
|
||||
getMacAddrRegex() {
|
||||
return /^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$/;
|
||||
}
|
||||
}
|
||||
|
@ -12,27 +12,22 @@ export class ImageManagerService {
|
||||
|
||||
constructor(private httpController: HttpController) { }
|
||||
|
||||
getImages(controller: Controller) {
|
||||
getImages(controller:Controller ) {
|
||||
return this.httpController.get<Image[]>(controller, '/images') as Observable<Image[]>;
|
||||
}
|
||||
|
||||
getImagePath(controller: Controller, install_appliance, image_path){
|
||||
getImagePath(controller :Controller, install_appliance, image_path){
|
||||
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${image_path}?install_appliances=${install_appliance}`;
|
||||
}
|
||||
|
||||
uploadedImage(controller: Controller, install_appliance, image_path, file){
|
||||
return this.httpController.post<Image[]>(controller, `/images/upload/${image_path}?install_appliances=${install_appliance}`, file) as Observable<Image[]>;
|
||||
getUploadPath(controller:Controller , emulator: string, filename: string) {
|
||||
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${filename}`;
|
||||
}
|
||||
|
||||
deleteFile(controller: Controller, image_path){
|
||||
uploadedImage(controller :Controller, install_appliance, image_path, flie){
|
||||
return this.httpController.post<Image[]>(controller, `/images/upload/${image_path}?install_appliances=${install_appliance}`,flie) as Observable<Image[]>;
|
||||
}
|
||||
deleteFile(controller :Controller, image_path){
|
||||
return this.httpController.delete<Image[]>(controller, `/images/${image_path}`) as Observable<Image[]>;
|
||||
}
|
||||
|
||||
pruneImages(controller: Controller){
|
||||
return this.httpController.delete(controller, '/images/prune');
|
||||
}
|
||||
|
||||
installImages(controller: Controller) {
|
||||
return this.httpController.post(controller, '/images/install', {});
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,9 @@ import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class IosConfigurationService {
|
||||
c1700_wics = ['WIC-1T', 'WIC-2T', 'WIC-1ENET'];
|
||||
c2600_wics = ['WIC-1T', 'WIC-2T'];
|
||||
c3700_wics = ['WIC-1T', 'WIC-2T'];
|
||||
|
||||
c2600_nms = ['NM-1FE-TX', 'NM-1E', 'NM-4E', 'NM-16ESW'];
|
||||
c3600_nms = ['NM-1FE-TX', 'NM-1E', 'NM-4E', 'NM-16ESW', 'NM-4T'];
|
||||
@ -9,10 +12,6 @@ export class IosConfigurationService {
|
||||
c7200_pas = ['PA-A1', 'PA-FE-TX', 'PA-2FE-TX', 'PA-GE', 'PA-4T+', 'PA-8T', 'PA-4E', 'PA-8E', 'PA-POS-OC3'];
|
||||
c7200_io = ['C7200-IO-FE', 'C7200-IO-2FE', 'C7200-IO-GE-E'];
|
||||
|
||||
c1700_wics = ['WIC-1T', 'WIC-2T', 'WIC-1ENET'];
|
||||
c2600_wics = ['WIC-1T', 'WIC-2T'];
|
||||
c3700_wics = ['WIC-1T', 'WIC-2T'];
|
||||
|
||||
getConsoleTypes() {
|
||||
return ['telnet', 'none'];
|
||||
}
|
||||
@ -46,7 +45,10 @@ export class IosConfigurationService {
|
||||
c1700: 128,
|
||||
c2600: 128,
|
||||
c2691: 256,
|
||||
c3600: 256,
|
||||
c3600: 192,
|
||||
c3620: 192,
|
||||
c3640: 192,
|
||||
c3660: 192,
|
||||
c3725: 256,
|
||||
c3745: 256,
|
||||
c7200: 512,
|
||||
@ -89,101 +91,170 @@ export class IosConfigurationService {
|
||||
};
|
||||
}
|
||||
|
||||
getNPETypes() {
|
||||
return ['npe-100', 'npe-150', 'npe-175', 'npe-200', 'npe-225', 'npe-300', 'npe-400', 'npe-g2'];
|
||||
getNetworkModules() {
|
||||
return {
|
||||
c1700: {
|
||||
0: this.c1700_wics,
|
||||
1: this.c1700_wics,
|
||||
},
|
||||
c2600: {
|
||||
0: this.c2600_wics,
|
||||
1: this.c2600_wics,
|
||||
2: this.c2600_wics,
|
||||
},
|
||||
c2691: {
|
||||
0: this.c3700_wics,
|
||||
1: this.c3700_wics,
|
||||
2: this.c3700_wics,
|
||||
},
|
||||
c3725: {
|
||||
0: this.c3700_wics,
|
||||
1: this.c3700_wics,
|
||||
2: this.c3700_wics,
|
||||
},
|
||||
c3745: {
|
||||
0: this.c3700_wics,
|
||||
1: this.c3700_wics,
|
||||
2: this.c3700_wics,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
getMidplaneTypes() {
|
||||
return ['std', 'vxr'];
|
||||
getNetworkAdapters() {
|
||||
return {
|
||||
'1720': {
|
||||
0: ['C1700-MB-1FE'],
|
||||
},
|
||||
'1721': {
|
||||
0: ['C1700-MB-1FE'],
|
||||
},
|
||||
'1750': {
|
||||
0: ['C1700-MB-1FE'],
|
||||
},
|
||||
'1751': {
|
||||
0: ['C1700-MB-1FE'],
|
||||
1: ['C1700-MB-WIC1'],
|
||||
},
|
||||
'1760': {
|
||||
0: ['C1700-MB-1FE'],
|
||||
1: ['C1700-MB-WIC1'],
|
||||
},
|
||||
'2610': {
|
||||
0: ['C2600-MB-1E'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2611': {
|
||||
0: ['C2600-MB-2E'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2620': {
|
||||
0: ['C2600-MB-1FE'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2621': {
|
||||
0: ['C2600-MB-2FE'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2610XM': {
|
||||
0: ['C2600-MB-1FE'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2611XM': {
|
||||
0: ['C2600-MB-2FE'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2620XM': {
|
||||
0: ['C2600-MB-1FE'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2621XM': {
|
||||
0: ['C2600-MB-2FE'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2650XM': {
|
||||
0: ['C2600-MB-1FE'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'2651XM': {
|
||||
0: ['C2600-MB-2FE'],
|
||||
1: this.c2600_nms,
|
||||
},
|
||||
'3620': {
|
||||
0: this.c3600_nms,
|
||||
1: this.c3600_nms,
|
||||
},
|
||||
'3640': {
|
||||
0: this.c3600_nms,
|
||||
1: this.c3600_nms,
|
||||
2: this.c3600_nms,
|
||||
3: this.c3600_nms,
|
||||
},
|
||||
'3660': {
|
||||
0: ['Leopard-2FE'],
|
||||
1: this.c3600_nms,
|
||||
2: this.c3600_nms,
|
||||
3: this.c3600_nms,
|
||||
4: this.c3600_nms,
|
||||
5: this.c3600_nms,
|
||||
6: this.c3600_nms,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
getAdapterMatrix() {
|
||||
getNetworkAdaptersForPlatform() {
|
||||
let networkAdaptersForPlatform = {};
|
||||
networkAdaptersForPlatform['c2691'] = {
|
||||
0: ['GT96100-FE'],
|
||||
1: this.c3700_nms,
|
||||
};
|
||||
networkAdaptersForPlatform['c3725'] = {
|
||||
0: ['GT96100-FE'],
|
||||
1: this.c3700_nms,
|
||||
2: this.c3700_nms,
|
||||
};
|
||||
networkAdaptersForPlatform['c3745'] = {
|
||||
0: ['GT96100-FE'],
|
||||
1: this.c3700_nms,
|
||||
2: this.c3700_nms,
|
||||
3: this.c3700_nms,
|
||||
4: this.c3700_nms,
|
||||
};
|
||||
networkAdaptersForPlatform['c7200'] = {
|
||||
0: this.c7200_io,
|
||||
1: this.c7200_pas,
|
||||
2: this.c7200_pas,
|
||||
3: this.c7200_pas,
|
||||
4: this.c7200_pas,
|
||||
5: this.c7200_pas,
|
||||
6: this.c7200_pas,
|
||||
};
|
||||
|
||||
let adapter_matrix: any = {};
|
||||
for (let platform of ["c1700", "c2600", "c2691", "c3725", "c3745", "c3600", "c7200"]) {
|
||||
adapter_matrix[platform] = {};
|
||||
}
|
||||
|
||||
// 1700s have one interface on the MB, 2 sub-slots for WICs, and no NM slots
|
||||
for (let chassis of ["1720", "1721", "1750", "1751", "1760"]) {
|
||||
adapter_matrix["c1700"][chassis] = { 0: ["C1700-MB-1FE"] };
|
||||
}
|
||||
|
||||
// Add a fake NM in slot 1 on 1751s and 1760s to provide two WIC slots
|
||||
for (let chassis of ["1751", "1760"]) {
|
||||
adapter_matrix["c1700"][chassis][1] = ["C1700-MB-WIC1"];
|
||||
}
|
||||
|
||||
// 2600s have one or more interfaces on the MB, 2 subslots for WICs, and an available NM slot 1
|
||||
for (let chassis of ["2620", "2610XM", "2620XM", "2650XM"]) {
|
||||
adapter_matrix["c2600"][chassis] = { 0: ["C2600-MB-1FE"], 1: this.c2600_nms };
|
||||
}
|
||||
|
||||
for (let chassis of ["2621", "2611XM", "2621XM", "2651XM"]) {
|
||||
adapter_matrix["c2600"][chassis] = { 0: ["C2600-MB-2FE"], 1: this.c2600_nms };
|
||||
}
|
||||
|
||||
adapter_matrix["c2600"]["2610"] = { 0: ["C2600-MB-1E"], 1: this.c2600_nms };
|
||||
adapter_matrix["c2600"]["2611"] = { 0: ["C2600-MB-2E"], 1: this.c2600_nms };
|
||||
|
||||
// 2691s have two FEs on the motherboard and one NM slot
|
||||
adapter_matrix["c2691"][""] = { 0: ["GT96100-FE"], 1: this.c3700_nms };
|
||||
|
||||
// 3620s have two generic NM slots
|
||||
adapter_matrix["c3600"]["3620"] = {};
|
||||
for (let slot = 0; slot < 2; slot++) {
|
||||
adapter_matrix["c3600"]["3620"][slot] = this.c3600_nms;
|
||||
}
|
||||
|
||||
// 3640s have four generic NM slots
|
||||
adapter_matrix["c3600"]["3640"] = {};
|
||||
for (let slot = 0; slot < 4; slot++) {
|
||||
adapter_matrix["c3600"]["3640"][slot] = this.c3600_nms;
|
||||
}
|
||||
|
||||
// 3660s have 2 FEs on the motherboard and 6 generic NM slots
|
||||
adapter_matrix["c3600"]["3660"] = { 0: ["Leopard-2FE"] };
|
||||
for (let slot = 1; slot < 7; slot++) {
|
||||
adapter_matrix["c3600"]["3660"][slot] = this.c3600_nms;
|
||||
}
|
||||
|
||||
// 3725s have 2 FEs on the motherboard and 2 generic NM slots
|
||||
adapter_matrix["c3725"][""] = { 0: ["GT96100-FE"] };
|
||||
for (let slot = 1; slot < 3; slot++) {
|
||||
adapter_matrix["c3725"][""][slot] = this.c3700_nms;
|
||||
}
|
||||
|
||||
// 3745s have 2 FEs on the motherboard and 4 generic NM slots
|
||||
adapter_matrix["c3745"][""] = { 0: ["GT96100-FE"] };
|
||||
for (let slot = 1; slot < 5; slot++) {
|
||||
adapter_matrix["c3745"][""][slot] = this.c3700_nms;
|
||||
}
|
||||
|
||||
// 7206s allow an IO controller in slot 0, and a generic PA in slots 1-6
|
||||
adapter_matrix["c7200"][""] = { 0: this.c7200_io };
|
||||
for (let slot = 1; slot < 7; slot++) {
|
||||
adapter_matrix["c7200"][""][slot] = this.c7200_pas;
|
||||
}
|
||||
|
||||
return adapter_matrix;
|
||||
}
|
||||
|
||||
getWicMatrix() {
|
||||
let wic_matrix: any = {};
|
||||
|
||||
wic_matrix["c1700"] = { 0: this.c1700_wics, 1: this.c1700_wics };
|
||||
wic_matrix["c2600"] = { 0: this.c2600_wics, 1: this.c2600_wics, 2: this.c2600_wics };
|
||||
wic_matrix["c2691"] = { 0: this.c3700_wics, 1: this.c3700_wics, 2: this.c3700_wics };
|
||||
wic_matrix["c3725"] = { 0: this.c3700_wics, 1: this.c3700_wics, 2: this.c3700_wics };
|
||||
wic_matrix["c3745"] = { 0: this.c3700_wics, 1: this.c3700_wics, 2: this.c3700_wics };
|
||||
return wic_matrix;
|
||||
}
|
||||
|
||||
getIdlepcRegex() {
|
||||
return /^(0x[0-9a-fA-F]+)?$|^$/;
|
||||
}
|
||||
|
||||
getMacAddrRegex() {
|
||||
return /^([0-9a-fA-F]{4}\.){2}[0-9a-fA-F]{4}$|^$/;
|
||||
return {
|
||||
c2691: {
|
||||
0: ['GT96100-FE'],
|
||||
1: this.c3700_nms,
|
||||
},
|
||||
c3725: {
|
||||
0: ['GT96100-FE'],
|
||||
1: this.c3700_nms,
|
||||
2: this.c3700_nms,
|
||||
},
|
||||
c3745: {
|
||||
0: ['GT96100-FE'],
|
||||
1: this.c3700_nms,
|
||||
2: this.c3700_nms,
|
||||
3: this.c3700_nms,
|
||||
4: this.c3700_nms,
|
||||
},
|
||||
c7200: {
|
||||
0: this.c7200_io,
|
||||
1: this.c7200_pas,
|
||||
2: this.c7200_pas,
|
||||
3: this.c7200_pas,
|
||||
4: this.c7200_pas,
|
||||
5: this.c7200_pas,
|
||||
6: this.c7200_pas,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -37,9 +37,4 @@ export class IosService {
|
||||
iosTemplate
|
||||
) as Observable<IosTemplate>;
|
||||
}
|
||||
|
||||
findIdlePC(controller:Controller, body: any) {
|
||||
return this.httpController.post(controller, `/computes/${environment.compute_id}/dynamips/auto_idlepc`, body);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ export class NodeService {
|
||||
} else if (node.node_type === 'iou') {
|
||||
urlPath += '/files/startup-config.cfg';
|
||||
} else if (node.node_type === 'dynamips') {
|
||||
urlPath += `/files/configs/i${node.properties.dynamips_id}_startup-config.cfg`;
|
||||
urlPath += `/files/configs/i${node.node_id}_startup-config.cfg`;
|
||||
}
|
||||
|
||||
return this.httpController.get(controller, urlPath, { responseType: 'text' as 'json' });
|
||||
@ -201,7 +201,7 @@ export class NodeService {
|
||||
if (node.node_type === 'iou') {
|
||||
urlPath += '/files/private-config.cfg';
|
||||
} else if (node.node_type === 'dynamips') {
|
||||
urlPath += `/files/configs/i${node.properties.dynamips_id}_private-config.cfg`;
|
||||
urlPath += `/files/configs/i${node.node_id}_private-config.cfg`;
|
||||
}
|
||||
|
||||
return this.httpController.get(controller, urlPath, { responseType: 'text' as 'json' });
|
||||
@ -215,7 +215,7 @@ export class NodeService {
|
||||
} else if (node.node_type === 'iou') {
|
||||
urlPath += '/files/startup-config.cfg';
|
||||
} else if (node.node_type === 'dynamips') {
|
||||
urlPath += `/files/configs/i${node.properties.dynamips_id}_startup-config.cfg`;
|
||||
urlPath += `/files/configs/i${node.node_id}_startup-config.cfg`;
|
||||
}
|
||||
|
||||
return this.httpController.post(controller, urlPath, configuration);
|
||||
@ -227,17 +227,9 @@ export class NodeService {
|
||||
if (node.node_type === 'iou') {
|
||||
urlPath += '/files/private-config.cfg';
|
||||
} else if (node.node_type === 'dynamips') {
|
||||
urlPath += `/files/configs/i${node.properties.dynamips_id}_private-config.cfg`;
|
||||
urlPath += `/files/configs/i${node.node_id}_private-config.cfg`;
|
||||
}
|
||||
|
||||
return this.httpController.post(controller, urlPath, configuration);
|
||||
}
|
||||
|
||||
getIdlePCProposals(controller:Controller, node: Node) {
|
||||
return this.httpController.get(controller, `/projects/${node.project_id}/nodes/${node.node_id}/dynamips/idlepc_proposals`);
|
||||
}
|
||||
|
||||
getAutoIdlePC(controller:Controller, node: Node) {
|
||||
return this.httpController.get(controller, `/projects/${node.project_id}/nodes/${node.node_id}/dynamips/auto_idlepc`);
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +76,34 @@ export class QemuConfigurationService {
|
||||
{ value: 'vmxnet3', name: 'VMWare Paravirtualized Ethernet v3' },
|
||||
];
|
||||
|
||||
// let networkTypes = [
|
||||
// 'e1000',
|
||||
// 'e1000-82544gc',
|
||||
// 'e1000-82545em',
|
||||
// 'e1000e',
|
||||
// 'rocker',
|
||||
// 'Intel Gigabit Ethernet',
|
||||
// 'i82550',
|
||||
// 'i82551',
|
||||
// 'i82557a',
|
||||
// 'i82557b',
|
||||
// 'i82557c',
|
||||
// 'i82558a',
|
||||
// 'i82558b',
|
||||
// 'i82559a',
|
||||
// 'i82559b',
|
||||
// 'i82559c',
|
||||
// 'i82559er',
|
||||
// 'i82562',
|
||||
// 'i82801',
|
||||
// 'ne2k_pci',
|
||||
// 'pcnet',
|
||||
// 'rtl8139',
|
||||
// 'virtio',
|
||||
// 'virtio-net-pci',
|
||||
// 'vmxnet3',
|
||||
// ];
|
||||
|
||||
return networkTypes;
|
||||
}
|
||||
|
||||
@ -118,8 +146,4 @@ export class QemuConfigurationService {
|
||||
|
||||
return priorities;
|
||||
}
|
||||
|
||||
getMacAddrRegex() {
|
||||
return /^([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})$/;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import { Controller } from '../models/controller';
|
||||
import { HttpController } from './http-controller.service';
|
||||
import { User } from '../models/users/user';
|
||||
import { Group } from "@models/groups/group";
|
||||
import {Image} from "@models/images";
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
@ -33,10 +32,7 @@ export class UserService {
|
||||
return this.httpController.delete(controller, `/access/users/${user_id}`);
|
||||
}
|
||||
|
||||
update(controller: Controller, user: any, self_update: boolean): Observable<User> {
|
||||
if (self_update) {
|
||||
return this.httpController.put<User>(controller, `/access/users/me`, user);
|
||||
}
|
||||
update(controller: Controller, user: any): Observable<User> {
|
||||
return this.httpController.put<User>(controller, `/access/users/${user.user_id}`, user);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user