mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2024-12-23 23:02:22 +00:00
Form validation for Qemu
This commit is contained in:
parent
5a21d117ca
commit
a6b4c4a9c8
@ -102,6 +102,7 @@ import { VpcsTemplatesComponent } from './components/preferences/vpcs/vpcs-templ
|
||||
import { VpcsService } from './services/vpcs.service';
|
||||
import { AddVpcsTemplateComponent } from './components/preferences/vpcs/add-vpcs-template/add-vpcs-template.component';
|
||||
import { VpcsTemplateDetailsComponent } from './components/preferences/vpcs/vpcs-template-details/vpcs-template-details.component';
|
||||
import { TemplateMocksService } from './services/template-mocks.service';
|
||||
|
||||
if (environment.production) {
|
||||
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
|
||||
@ -212,7 +213,8 @@ if (environment.production) {
|
||||
ToolsService,
|
||||
ServerSettingsService,
|
||||
QemuService,
|
||||
VpcsService
|
||||
VpcsService,
|
||||
TemplateMocksService
|
||||
],
|
||||
entryComponents: [
|
||||
AddServerDialogComponent,
|
||||
|
@ -8,60 +8,87 @@
|
||||
<div class="example-container mat-elevation-z8">
|
||||
<mat-vertical-stepper [linear]="true">
|
||||
<mat-step label="QEMU VM Name">
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="text" [(ngModel)]="templateName" placeholder="Please choose a descriptive name for your new QEMU virtual machine"/>
|
||||
</mat-form-field><br/>
|
||||
<mat-checkbox>
|
||||
This is a legacy ASA VM
|
||||
</mat-checkbox>
|
||||
<form [formGroup]="firstStepForm">
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput type="text"
|
||||
[(ngModel)]="qemuTemplate.name"
|
||||
formControlName="templateName"
|
||||
placeholder="Please choose a descriptive name for your new QEMU virtual machine"/>
|
||||
</mat-form-field><br/>
|
||||
<mat-checkbox>
|
||||
This is a legacy ASA VM
|
||||
</mat-checkbox>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step label="QEMU binary and memory">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-select placeholder="Qemu binary" [(ngModel)]="selectedBinary">
|
||||
<mat-option *ngFor="let binary of qemuBinaries" [value]="binary">
|
||||
{{binary.path}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field><br/>
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="number" placeholder="RAM" [(ngModel)]="ramMemory"/>
|
||||
</mat-form-field>
|
||||
<form [formGroup]="secondStepForm">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-select
|
||||
placeholder="Qemu binary"
|
||||
[(ngModel)]="selectedBinary"
|
||||
[ngModelOptions]="{standalone: true}" >
|
||||
<mat-option *ngFor="let binary of qemuBinaries" [value]="binary">
|
||||
{{binary.path}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field><br/>
|
||||
<mat-form-field class="form-field">
|
||||
<input
|
||||
matInput type="number"
|
||||
placeholder="RAM"
|
||||
[(ngModel)]="ramMemory"
|
||||
formControlName="ramMemory"/>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step label="Console type">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-select placeholder="Console type" [(ngModel)]="selectedConsoleType">
|
||||
<mat-option *ngFor="let type of consoleTypes" [value]="type">
|
||||
{{type}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<form [formGroup]="thirdStepForm">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-select
|
||||
placeholder="Console type"
|
||||
[(ngModel)]="qemuTemplate.console_type"
|
||||
[ngModelOptions]="{standalone: true}" >
|
||||
<mat-option *ngFor="let type of consoleTypes" [value]="type">
|
||||
{{type}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</mat-step>
|
||||
<mat-step label="Disk image">
|
||||
<mat-radio-group class="radio-group">
|
||||
<mat-radio-button class="radio-button" value="1" (click)="setDiskImage('existingImage')" checked>Existing image</mat-radio-button>
|
||||
<mat-radio-button class="radio-button" value="2" (click)="setDiskImage('newImage')">New image</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
<mat-select *ngIf="!newImageSelected" placeholder="Disk image (hda)" [(ngModel)]="selectedImage">
|
||||
<mat-option *ngFor="let image of qemuImages" [value]="image">
|
||||
{{image.filename}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<div *ngIf="newImageSelected">
|
||||
<input
|
||||
type="file"
|
||||
accept=".qcow2"
|
||||
#file
|
||||
class="nonvisible"
|
||||
(change)="uploadImageFile($event)"/>
|
||||
<button mat-raised-button color="primary" (click)="file.click()" class="file-button">Browse</button>
|
||||
<mat-form-field class="file-name-form-field">
|
||||
<form [formGroup]="fourthStepForm">
|
||||
<mat-radio-group class="radio-group">
|
||||
<mat-radio-button class="radio-button" value="1" (click)="setDiskImage('existingImage')" checked>Existing image</mat-radio-button>
|
||||
<mat-radio-button class="radio-button" value="2" (click)="setDiskImage('newImage')">New image</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
<mat-select
|
||||
*ngIf="!newImageSelected"
|
||||
placeholder="Disk image (hda)"
|
||||
[ngModelOptions]="{standalone: true}"
|
||||
[(ngModel)]="selectedImage">
|
||||
<mat-option *ngFor="let image of qemuImages" [value]="image">
|
||||
{{image.filename}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<div *ngIf="newImageSelected">
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
[(ngModel)]="chosenImage"
|
||||
placeholder="Please enter name"/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
type="file"
|
||||
accept=".qcow2"
|
||||
#file
|
||||
class="nonvisible"
|
||||
(change)="uploadImageFile($event)"/>
|
||||
<button mat-raised-button color="primary" (click)="file.click()" class="file-button">Browse</button>
|
||||
<mat-form-field class="file-name-form-field">
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
[(ngModel)]="chosenImage"
|
||||
formControlName="fileName"
|
||||
placeholder="Please enter name"/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
<div class="buttons-bar"><button mat-raised-button color="primary" (click)="addTemplate()">Add template</button></div>
|
||||
</mat-step>
|
||||
</mat-vertical-stepper>
|
||||
|
@ -8,6 +8,9 @@ import { QemuBinary } from '../../../../models/qemu/qemu-binary';
|
||||
import { QemuImage } from '../../../../models/qemu/qemu-image';
|
||||
import { ToasterService } from '../../../../services/toaster.service';
|
||||
import { QemuTemplate } from '../../../../models/templates/qemu-template';
|
||||
import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { TemplateMocksService } from '../../../../services/template-mocks.service';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -17,24 +20,46 @@ import { QemuTemplate } from '../../../../models/templates/qemu-template';
|
||||
})
|
||||
export class AddQemuVmTemplateComponent implements OnInit {
|
||||
server: Server;
|
||||
templateName: string;
|
||||
qemuBinaries: QemuBinary[] = [];
|
||||
selectedBinary: QemuBinary;
|
||||
ramMemory: number;
|
||||
consoleTypes: string[] = ['telnet', 'vnc', 'spice', 'spice+agent', 'none'];
|
||||
selectedConsoleType: string;
|
||||
newImageSelected: boolean;
|
||||
newImageSelected: boolean = false;;
|
||||
qemuImages: QemuImage[] = [];
|
||||
selectedImage: QemuImage;
|
||||
chosenImage: string;
|
||||
chosenImage: string = '';
|
||||
qemuTemplate: QemuTemplate;
|
||||
|
||||
firstStepForm: FormGroup;
|
||||
secondStepForm: FormGroup;
|
||||
thirdStepForm: FormGroup;
|
||||
fourthStepForm: FormGroup;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private serverService: ServerService,
|
||||
private qemuService: QemuService,
|
||||
private toasterService: ToasterService,
|
||||
private router: Router
|
||||
) {}
|
||||
private router: Router,
|
||||
private formBuilder: FormBuilder,
|
||||
private templateMocksService: TemplateMocksService
|
||||
) {
|
||||
this.qemuTemplate = new QemuTemplate();
|
||||
|
||||
this.firstStepForm = this.formBuilder.group({
|
||||
templateName: new FormControl('', Validators.required)
|
||||
});
|
||||
|
||||
this.secondStepForm = this.formBuilder.group({
|
||||
ramMemory: new FormControl('', Validators.required)
|
||||
});
|
||||
|
||||
this.thirdStepForm = this.formBuilder.group({});
|
||||
|
||||
this.fourthStepForm = this.formBuilder.group({
|
||||
fileName: new FormControl('', Validators.required)
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.paramMap
|
||||
@ -46,9 +71,15 @@ export class AddQemuVmTemplateComponent implements OnInit {
|
||||
)
|
||||
.subscribe((server: Server) => {
|
||||
this.server = server;
|
||||
|
||||
this.templateMocksService.getQemuTemplate().subscribe((qemuTemplate: QemuTemplate) => {
|
||||
this.qemuTemplate = qemuTemplate;
|
||||
})
|
||||
|
||||
this.qemuService.getBinaries(server).subscribe((qemuBinaries: QemuBinary[]) => {
|
||||
this.qemuBinaries = qemuBinaries;
|
||||
});
|
||||
|
||||
this.qemuService.getImages(server).subscribe((qemuImages: QemuImage[]) => {
|
||||
this.qemuImages = qemuImages;
|
||||
});
|
||||
@ -64,15 +95,18 @@ export class AddQemuVmTemplateComponent implements OnInit {
|
||||
}
|
||||
|
||||
addTemplate() {
|
||||
if (!(this.templateName && this.selectedBinary && this.ramMemory && this.selectedConsoleType &&
|
||||
(this.selectedImage || this.chosenImage))) {
|
||||
let qemuTemplate = new QemuTemplate();
|
||||
qemuTemplate.adapter_type = "e1000";
|
||||
qemuTemplate.adapters = 1;
|
||||
qemuTemplate.boot_priority = "c";
|
||||
qemuTemplate.category = "guest";
|
||||
qemuTemplate.name = this.templateName;
|
||||
this.qemuService.addTemplate(this.server, qemuTemplate).subscribe((template: QemuTemplate) => {
|
||||
if (!this.firstStepForm.invalid && !this.secondStepForm.invalid && !this.thirdStepForm.invalid
|
||||
&& (this.selectedImage || this.chosenImage)) {
|
||||
this.qemuTemplate.ram = this.ramMemory;
|
||||
this.qemuTemplate.qemu_path = this.selectedBinary.path;
|
||||
if (this.newImageSelected) {
|
||||
this.qemuTemplate.hda_disk_image = this.chosenImage;
|
||||
} else {
|
||||
this.qemuTemplate.hda_disk_image = this.selectedImage.path;
|
||||
}
|
||||
this.qemuTemplate.template_id = uuid();
|
||||
|
||||
this.qemuService.addTemplate(this.server, this.qemuTemplate).subscribe((template: QemuTemplate) => {
|
||||
this.router.navigate(['/server', this.server.id, 'preferences', 'qemu', 'templates']);
|
||||
});
|
||||
} else {
|
||||
|
@ -7,6 +7,7 @@ import { VpcsService } from '../../../../services/vpcs.service';
|
||||
import { VpcsTemplate } from '../../../../models/templates/vpcs-template';
|
||||
import { ToasterService } from '../../../../services/toaster.service';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { TemplateMocksService } from '../../../../services/template-mocks.service';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -23,7 +24,8 @@ export class AddVpcsTemplateComponent implements OnInit {
|
||||
private serverService: ServerService,
|
||||
private vpcsService: VpcsService,
|
||||
private router: Router,
|
||||
private toasterService: ToasterService
|
||||
private toasterService: ToasterService,
|
||||
private templateMocksService: TemplateMocksService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@ -41,19 +43,15 @@ export class AddVpcsTemplateComponent implements OnInit {
|
||||
|
||||
addTemplate() {
|
||||
if (this.templateName) {
|
||||
let vpcsTemplate: VpcsTemplate = {
|
||||
base_script_file: 'vpcs_base_config.txt',
|
||||
builtin: false,
|
||||
category: 'guest',
|
||||
compute_id: 'local',
|
||||
console_auto_start: false,
|
||||
console_type: 'telnet',
|
||||
default_name_format: 'PC{0}',
|
||||
name: this.templateName,
|
||||
symbol: ':/symbols/vpcs_guest.svg',
|
||||
template_id: uuid(),
|
||||
template_type: 'vpcs'
|
||||
};
|
||||
let vpcsTemplate: VpcsTemplate;
|
||||
|
||||
this.templateMocksService.getVpcsTemplate().subscribe((template: VpcsTemplate) => {
|
||||
vpcsTemplate = template;
|
||||
});
|
||||
|
||||
vpcsTemplate.template_id = uuid(),
|
||||
vpcsTemplate.name = this.templateName,
|
||||
|
||||
this.vpcsService.addTemplate(this.server, vpcsTemplate).subscribe((vpcsTemplate) => {
|
||||
this.router.navigate(['/server', this.server.id, 'preferences', 'vpcs', 'templates']);
|
||||
});
|
||||
|
@ -35,20 +35,28 @@
|
||||
placeholder="Symbol">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<mat-select placeholder="Category" [ngModelOptions]="{standalone: true}" [(ngModel)]="vpcsTemplate.category">
|
||||
<mat-select
|
||||
placeholder="Category"
|
||||
[ngModelOptions]="{standalone: true}"
|
||||
[(ngModel)]="vpcsTemplate.category">
|
||||
<mat-option *ngFor="let category of categories" [value]="category[1]">
|
||||
{{category[0]}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="select">
|
||||
<mat-select placeholder="Console type" [ngModelOptions]="{standalone: true}" [(ngModel)]="vpcsTemplate.console_type">
|
||||
<mat-select
|
||||
placeholder="Console type"
|
||||
[ngModelOptions]="{standalone: true}"
|
||||
[(ngModel)]="vpcsTemplate.console_type">
|
||||
<mat-option *ngFor="let type of consoleTypes" [value]="type">
|
||||
{{type}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="vpcsTemplate.console_auto_start">
|
||||
<mat-checkbox
|
||||
[ngModelOptions]="{standalone: true}"
|
||||
[(ngModel)]="vpcsTemplate.console_auto_start">
|
||||
Auto start console
|
||||
</mat-checkbox>
|
||||
</form>
|
||||
|
@ -53,7 +53,7 @@ export class VpcsTemplateDetailsComponent implements OnInit {
|
||||
}
|
||||
|
||||
onSave() {
|
||||
if( this.inputForm.invalid) {
|
||||
if (this.inputForm.invalid) {
|
||||
this.toasterService.error(`Fill all required fields`);
|
||||
} else {
|
||||
this.vpcsService.saveTemplate(this.server, this.vpcsTemplate).subscribe((vpcsTemaple: VpcsTemplate) => {
|
||||
|
0
src/app/services/template-mocks.service.spec.ts
Normal file
0
src/app/services/template-mocks.service.spec.ts
Normal file
74
src/app/services/template-mocks.service.ts
Normal file
74
src/app/services/template-mocks.service.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { QemuTemplate } from '../models/templates/qemu-template';
|
||||
import { VpcsTemplate } from '../models/templates/vpcs-template';
|
||||
import { Observable, of } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class TemplateMocksService {
|
||||
getQemuTemplate() : Observable<QemuTemplate> {
|
||||
let template : QemuTemplate = {
|
||||
adapter_type: 'e1000',
|
||||
adapters: 4,
|
||||
bios_image: '',
|
||||
boot_priority: 'c',
|
||||
builtin: false,
|
||||
category: 'guest',
|
||||
cdrom_image: '',
|
||||
compute_id: 'local',
|
||||
console_auto_start: false,
|
||||
console_type: 'telnet',
|
||||
cpu_throttling: 0,
|
||||
cpus: 1,
|
||||
custom_adapters: [],
|
||||
default_name_format: '{name}-{0}',
|
||||
first_port_name: '',
|
||||
hda_disk_image: '',
|
||||
hda_disk_interface: 'ide',
|
||||
hdb_disk_image: '',
|
||||
hdb_disk_interface: 'ide',
|
||||
hdc_disk_image: '',
|
||||
hdc_disk_interface: 'ide',
|
||||
hdd_disk_image: '',
|
||||
hdd_disk_interface: 'ide',
|
||||
initrd: '',
|
||||
kernel_command_line: '',
|
||||
kernel_image: '',
|
||||
legacy_networking: false,
|
||||
linked_clone: true,
|
||||
mac_address: '',
|
||||
name: '',
|
||||
on_close: 'power_off',
|
||||
options: '-nographic',
|
||||
platform: '',
|
||||
port_name_format: 'Ethernet{0}',
|
||||
port_segment_size: 0,
|
||||
process_priority: 'normal',
|
||||
qemu_path: '',
|
||||
ram: 256,
|
||||
symbol: ':/symbols/qemu_guest.svg',
|
||||
template_id: '',
|
||||
template_type: 'qemu',
|
||||
usage: ''
|
||||
}
|
||||
|
||||
return of(template);
|
||||
}
|
||||
|
||||
getVpcsTemplate() : Observable<VpcsTemplate> {
|
||||
let template: VpcsTemplate = {
|
||||
base_script_file: 'vpcs_base_config.txt',
|
||||
builtin: false,
|
||||
category: 'guest',
|
||||
compute_id: 'local',
|
||||
console_auto_start: false,
|
||||
console_type: 'telnet',
|
||||
default_name_format: 'PC{0}',
|
||||
name: '',
|
||||
symbol: ':/symbols/vpcs_guest.svg',
|
||||
template_id: '',
|
||||
template_type: 'vpcs'
|
||||
}
|
||||
|
||||
return of(template);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user