mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-02-01 00:45:53 +00:00
Support for creating virtual box templates added
This commit is contained in:
parent
41eb0d882d
commit
23c7e3bc8e
@ -17,6 +17,10 @@ import { VpcsPreferencesComponent } from './components/preferences/vpcs/vpcs-pre
|
||||
import { VpcsTemplatesComponent } from './components/preferences/vpcs/vpcs-templates/vpcs-templates.component';
|
||||
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 { VirtualBoxPreferencesComponent } from './components/preferences/virtual-box/virtual-box-preferences/virtual-box-preferences.component';
|
||||
import { VirtualBoxTemplatesComponent } from './components/preferences/virtual-box/virtual-box-templates/virtual-box-templates.component';
|
||||
import { VirtualBoxTemplateDetailsComponent } from './components/preferences/virtual-box/virtual-box-template-details/virtual-box-template-details.component';
|
||||
import { AddVirtualBoxTemplateComponent } from './components/preferences/virtual-box/add-virtual-box-template/add-virtual-box-template.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -40,7 +44,12 @@ const routes: Routes = [
|
||||
// { path: 'server/:server_id/preferences/vpcs', component: VpcsPreferencesComponent },
|
||||
{ path: 'server/:server_id/preferences/vpcs/templates', component: VpcsTemplatesComponent },
|
||||
{ path: 'server/:server_id/preferences/vpcs/templates/:template_id', component: VpcsTemplateDetailsComponent},
|
||||
{ path: 'server/:server_id/preferences/vpcs/addtemplate', component: AddVpcsTemplateComponent }
|
||||
{ path: 'server/:server_id/preferences/vpcs/addtemplate', component: AddVpcsTemplateComponent },
|
||||
// temporary disabled
|
||||
// { path: 'server/:server_id/preferences/virtualbox', component: VirtualBoxPreferencesComponent }
|
||||
{ path: 'server/:server_id/preferences/virtualbox/templates', component: VirtualBoxTemplatesComponent },
|
||||
{ path: 'server/:server_id/preferences/virtualbox/templates/:template_id', component: VirtualBoxTemplateDetailsComponent },
|
||||
{ path: 'server/:server_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent }
|
||||
]
|
||||
},
|
||||
{ path: 'server/:server_id/project/:project_id', component: ProjectMapComponent }
|
||||
|
@ -103,6 +103,11 @@ 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';
|
||||
import { VirtualBoxPreferencesComponent } from './components/preferences/virtual-box/virtual-box-preferences/virtual-box-preferences.component';
|
||||
import { VirtualBoxTemplatesComponent } from './components/preferences/virtual-box/virtual-box-templates/virtual-box-templates.component';
|
||||
import { VirtualBoxService } from './services/virtual-box.service';
|
||||
import { VirtualBoxTemplateDetailsComponent } from './components/preferences/virtual-box/virtual-box-template-details/virtual-box-template-details.component';
|
||||
import { AddVirtualBoxTemplateComponent } from './components/preferences/virtual-box/add-virtual-box-template/add-virtual-box-template.component';
|
||||
|
||||
if (environment.production) {
|
||||
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
|
||||
@ -164,7 +169,11 @@ if (environment.production) {
|
||||
VpcsPreferencesComponent,
|
||||
VpcsTemplatesComponent,
|
||||
AddVpcsTemplateComponent,
|
||||
VpcsTemplateDetailsComponent
|
||||
VpcsTemplateDetailsComponent,
|
||||
VirtualBoxPreferencesComponent,
|
||||
VirtualBoxTemplatesComponent,
|
||||
VirtualBoxTemplateDetailsComponent,
|
||||
AddVirtualBoxTemplateComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@ -214,7 +223,8 @@ if (environment.production) {
|
||||
ServerSettingsService,
|
||||
QemuService,
|
||||
VpcsService,
|
||||
TemplateMocksService
|
||||
TemplateMocksService,
|
||||
VirtualBoxService
|
||||
],
|
||||
entryComponents: [
|
||||
AddServerDialogComponent,
|
||||
|
@ -17,6 +17,11 @@
|
||||
QEMU
|
||||
</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item>
|
||||
<button mat-button routerLink="/server/{{serverId}}/preferences/virtualbox/templates">
|
||||
VirtualBox
|
||||
</button>
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="content">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">New QEMU template</h1>
|
||||
<h1 class="col">New QEMU VM template</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="default-content">
|
||||
|
@ -312,6 +312,9 @@
|
||||
Usage
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<mat-form-field class="row">
|
||||
<textarea matInput type="text" [(ngModel)]="qemuTemplate.usage"></textarea>
|
||||
</mat-form-field>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
<div class="buttons-bar"><button mat-raised-button color="primary" (click)="onSave()">Save</button></div>
|
||||
|
@ -0,0 +1,23 @@
|
||||
<div class="content">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">New VirtualBox VM template</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="default-content" *ngIf="virtualBoxTemplate">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-select
|
||||
placeholder="VM list"
|
||||
[(ngModel)]="selectedVM"
|
||||
[ngModelOptions]="{standalone: true}" >
|
||||
<mat-option *ngFor="let vm of virtualMachines" [value]="vm">
|
||||
{{vm.vmname}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field><br/>
|
||||
<mat-checkbox [(ngModel)]="virtualBoxTemplate.linked_clone">
|
||||
Use as a linked base VM (experimental)
|
||||
</mat-checkbox>
|
||||
<div class="buttons-bar"><button mat-raised-button color="primary" (click)="addTemplate()">Add template</button></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,3 @@
|
||||
.form-field {
|
||||
width: 100%;
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Server } from '../../../../models/server';
|
||||
import { ActivatedRoute, ParamMap, Router, Router, Router, Router, Router, Router } from '@angular/router';
|
||||
import { ServerService } from '../../../../services/server.service';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { VirtualBoxService } from '../../../../services/virtual-box.service';
|
||||
import { VirtualBoxVm } from '../../../../models/virtualbox/virtualboxVm';
|
||||
import { ToasterService } from '../../../../services/toaster.service';
|
||||
import { TemplateMocksService } from '../../../../services/template-mocks.service';
|
||||
import { VirtualBoxTemplate } from '../../../../models/templates/virtualbox-template';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-virtual-box-template',
|
||||
templateUrl: './add-virtual-box-template.component.html',
|
||||
styleUrls: ['./add-virtual-box-template.component.scss']
|
||||
})
|
||||
export class AddVirtualBoxTemplateComponent implements OnInit {
|
||||
server: Server;
|
||||
virtualMachines: VirtualBoxVm[];
|
||||
selectedVM: VirtualBoxVm;
|
||||
virtualBoxTemplate: VirtualBoxTemplate;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private serverService: ServerService,
|
||||
private virtualBoxService: VirtualBoxService,
|
||||
private toasterService: ToasterService,
|
||||
private templateMocksService: TemplateMocksService,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.paramMap
|
||||
.pipe(
|
||||
switchMap((params: ParamMap) => {
|
||||
const server_id = params.get('server_id');
|
||||
return this.serverService.get(parseInt(server_id, 10));
|
||||
})
|
||||
)
|
||||
.subscribe((server: Server) => {
|
||||
this.server = server;
|
||||
|
||||
this.virtualBoxService.getVirtualMachines(this.server).subscribe((virtualMachines: VirtualBoxVm[]) => {
|
||||
this.virtualMachines = virtualMachines;
|
||||
|
||||
this.templateMocksService.getVirtualBoxTemplate().subscribe((template: VirtualBoxTemplate) => {
|
||||
this.virtualBoxTemplate = template;
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
addTemplate() {
|
||||
if (this.selectedVM) {
|
||||
this.virtualBoxTemplate.name = this.selectedVM.vmname;
|
||||
this.virtualBoxTemplate.vmname = this.selectedVM.vmname;
|
||||
this.virtualBoxTemplate.ram = this.selectedVM.ram;
|
||||
this.virtualBoxTemplate.template_id = uuid();
|
||||
|
||||
this.virtualBoxService.addTemplate(this.server, this.virtualBoxTemplate).subscribe((template: VirtualBoxTemplate) => {
|
||||
this.router.navigate(['/server', this.server.id, 'preferences', 'virtualbox', 'templates']);
|
||||
});
|
||||
} else {
|
||||
this.toasterService.error(`Fill all required fields`);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<div class="content">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">VirtualBox preferences</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="default-content">
|
||||
<mat-form-field class="form-field">
|
||||
<input matInput type="text" [(ngModel)]="vpcsExecutable" placeholder="Path to VPCS executable"/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,42 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ServerSettingsService } from '../../../../services/server-settings.service';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { Server } from '../../../../models/server';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { ServerService } from '../../../../services/server.service';
|
||||
import { ToasterService } from '../../../../services/toaster.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-virtual-box-preferences',
|
||||
templateUrl: './virtual-box-preferences.component.html',
|
||||
styleUrls: ['./virtual-box-preferences.component.scss']
|
||||
})
|
||||
export class VirtualBoxPreferencesComponent implements OnInit {
|
||||
server: Server;
|
||||
vboxManagePath: string;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private serverService: ServerService,
|
||||
private serverSettingsService: ServerSettingsService,
|
||||
private toasterService: ToasterService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.paramMap
|
||||
.pipe(
|
||||
switchMap((params: ParamMap) => {
|
||||
const server_id = params.get('server_id');
|
||||
return this.serverService.get(parseInt(server_id, 10));
|
||||
})
|
||||
)
|
||||
.subscribe((server: Server) => {
|
||||
this.server = server;
|
||||
});
|
||||
}
|
||||
|
||||
restoreDefaults(){
|
||||
this.vboxManagePath = '';
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
<div class="content" [ngClass]="{ shadowed: isConfiguratorOpened }" [ngClass]="{ nonshadowed: !isConfiguratorOpened }">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">VirtualBox VM configuration</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="default-content" *ngIf="virtualBoxTemplate">
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
General settings
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<mat-form-field class="row">
|
||||
<input matInput type="text" [(ngModel)]="virtualBoxTemplate.name" placeholder="Template name">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<input matInput type="text" [(ngModel)]="virtualBoxTemplate.default_name_format" placeholder="Default name format">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<input matInput type="text" [(ngModel)]="virtualBoxTemplate.symbol" placeholder="Symbol">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<mat-select placeholder="Category" [(ngModel)]="virtualBoxTemplate.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" [(ngModel)]="virtualBoxTemplate.console_type">
|
||||
<mat-option *ngFor="let type of consoleTypes" [value]="type">
|
||||
{{type}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-checkbox [(ngModel)]="virtualBoxTemplate.console_auto_start">
|
||||
Auto start console
|
||||
</mat-checkbox>
|
||||
<mat-form-field class="row">
|
||||
<input matInput type="number" [(ngModel)]="virtualBoxTemplate.ram" placeholder="RAM">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<mat-select placeholder="On close" [(ngModel)]="virtualBoxTemplate.on_close">
|
||||
<mat-option *ngFor="let option of onCloseOptions" [value]="option[1]">
|
||||
{{option[0]}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-checkbox [(ngModel)]="virtualBoxTemplate.headless">
|
||||
Start VM in headless mode
|
||||
</mat-checkbox><br/>
|
||||
<mat-checkbox [(ngModel)]="virtualBoxTemplate.linked_clone">
|
||||
Use as a linked base VM (experimental)
|
||||
</mat-checkbox>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Network
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<mat-form-field class="row">
|
||||
<input matInput type="number" [(ngModel)]="virtualBoxTemplate.adapters" placeholder="Adapters">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<input matInput type="text" [(ngModel)]="virtualBoxTemplate.first_port_name" placeholder="First port name">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<input matInput type="text" [(ngModel)]="virtualBoxTemplate.port_name_format" placeholder="Name format">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<input matInput type="number" [(ngModel)]="virtualBoxTemplate.port_segment_size" placeholder="Segment size">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="row">
|
||||
<mat-select placeholder="Type" [(ngModel)]="virtualBoxTemplate.adapter_type">
|
||||
<mat-option *ngFor="let type of networkTypes" [value]="type">
|
||||
{{type}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<button mat-raised-button class="configButton" (click)="configureCustomAdapters()">Configure custom adapters</button><br/>
|
||||
<mat-checkbox [(ngModel)]="virtualBoxTemplate.use_any_adapter">
|
||||
Allow GNS3 to use any configured VirtualBox adapter
|
||||
</mat-checkbox>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Usage
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<mat-form-field class="row">
|
||||
<textarea matInput type="text" [(ngModel)]="virtualBoxTemplate.usage"></textarea>
|
||||
</mat-form-field>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
<div class="buttons-bar"><button mat-raised-button color="primary" (click)="onSave()">Save</button></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content" class="configurator" *ngIf="isConfiguratorOpened">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">Custom adapters configuration</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="default-content" *ngIf="virtualBoxTemplate">
|
||||
<div class="container mat-elevation-z8">
|
||||
<table class="table" mat-table [dataSource]="adapters">
|
||||
<ng-container matColumnDef="adapter_number">
|
||||
<th mat-header-cell *matHeaderCellDef> Adapter number </th>
|
||||
<td mat-cell *matCellDef="let element"> Adapter {{element.adapter_number}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="port_name">
|
||||
<th mat-header-cell *matHeaderCellDef> Port name </th>
|
||||
<td mat-cell *matCellDef="let element"> Ethernet {{element.adapter_number}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="adapter_type">
|
||||
<th mat-header-cell *matHeaderCellDef> Adapter type </th>
|
||||
<td mat-cell *matCellDef="let element; let i = index;">
|
||||
<mat-select placeholder="Type" [(ngModel)]="adapters[i].adapter_type">
|
||||
<mat-option *ngFor="let type of networkTypes" [value]="type">
|
||||
{{type}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button mat-raised-button color="primary" class="configHideButton" (click)="configureCustomAdapters()">Apply</button><br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,41 @@
|
||||
.row {
|
||||
width: 100%;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.configButton {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.configHideButton {
|
||||
margin-left: 80%;
|
||||
width: 20%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.shadowed {
|
||||
display: none;
|
||||
transition: 0.25s;
|
||||
}
|
||||
|
||||
.nonshadowed {
|
||||
opacity: 0;
|
||||
transition: 0.25s;
|
||||
}
|
||||
|
||||
th {
|
||||
border: 0px!important;
|
||||
}
|
||||
|
||||
th.mat-header-cell {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
td.mat-cell {
|
||||
padding-top: 15px;
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ServerService } from '../../../../services/server.service';
|
||||
import { Server } from '../../../../models/server';
|
||||
import { ToasterService } from '../../../../services/toaster.service';
|
||||
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
|
||||
import { VirtualBoxService } from '../../../../services/virtual-box.service';
|
||||
import { VirtualBoxTemplate } from '../../../../models/templates/virtualbox-template';
|
||||
import { CustomAdapter } from '../../../../models/qemu/qemu-custom-adapter';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-virtual-box-template-details',
|
||||
templateUrl: './virtual-box-template-details.component.html',
|
||||
styleUrls: ['./virtual-box-template-details.component.scss']
|
||||
})
|
||||
export class VirtualBoxTemplateDetailsComponent implements OnInit {
|
||||
server: Server;
|
||||
virtualBoxTemplate: VirtualBoxTemplate;
|
||||
|
||||
consoleTypes: string[] = ['telnet', 'none'];
|
||||
onCloseOptions = [["Power off the VM", "power_off"],
|
||||
["Send the shutdown signal (ACPI)", "shutdown_signal"],
|
||||
["Save the VM state", "save_vm_state"]];
|
||||
categories = [["Default", "guest"],
|
||||
["Routers", "routers"],
|
||||
["Switches", "switches"],
|
||||
["End devices", "end_devices"],
|
||||
["Security devices", "security_devices"]];
|
||||
networkTypes = ["PCnet-PCI II (Am79C970A)",
|
||||
"PCNet-FAST III (Am79C973)",
|
||||
"Intel PRO/1000 MT Desktop (82540EM)",
|
||||
"Intel PRO/1000 T Server (82543GC)",
|
||||
"Intel PRO/1000 MT Server (82545EM)",
|
||||
"Paravirtualized Network (virtio-net)"];
|
||||
adapters: CustomAdapter[] = [];
|
||||
displayedColumns: string[] = ['adapter_number', 'port_name', 'adapter_type'];
|
||||
isConfiguratorOpened: boolean = false;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private serverService: ServerService,
|
||||
private virtualBoxService: VirtualBoxService,
|
||||
private toasterService: ToasterService,
|
||||
private formBuilder: FormBuilder
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
const server_id = this.route.snapshot.paramMap.get("server_id");
|
||||
const template_id = this.route.snapshot.paramMap.get("template_id");
|
||||
this.serverService.get(parseInt(server_id, 10)).then((server: Server) => {
|
||||
this.server = server;
|
||||
|
||||
this.virtualBoxService.getTemplate(this.server, template_id).subscribe((virtualBoxTemplate: VirtualBoxTemplate) => {
|
||||
this.virtualBoxTemplate = virtualBoxTemplate;
|
||||
|
||||
for(let i=0; i<this.virtualBoxTemplate.adapters; i++){
|
||||
let adapter = this.virtualBoxTemplate.custom_adapters.find(elem => elem.adapter_number === i);
|
||||
if (adapter) {
|
||||
this.adapters.push(adapter);
|
||||
} else {
|
||||
this.adapters.push({
|
||||
adapter_number: i,
|
||||
adapter_type: this.virtualBoxTemplate.adapter_type
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
configureCustomAdapters(){
|
||||
this.isConfiguratorOpened = !this.isConfiguratorOpened;
|
||||
this.virtualBoxTemplate.custom_adapters = this.adapters;
|
||||
}
|
||||
|
||||
onSave() {
|
||||
this.virtualBoxService.saveTemplate(this.server, this.virtualBoxTemplate).subscribe((virtualBoxTemplate: VirtualBoxTemplate) => {
|
||||
this.toasterService.success("Changes saved");
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<div class="content">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">VirtualBox VM templates</h1>
|
||||
<button *ngIf="server" class="top-button" routerLink="/server/{{server.id}}/preferences/virtualbox/addtemplate" mat-raised-button color="primary">Add Virtual Box VM template</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="default-content">
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-nav-list *ngIf="server">
|
||||
<mat-list-item *ngFor='let template of virtualBoxTemplates' routerLink="{{template.template_id}}">
|
||||
{{template.name}}
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,4 @@
|
||||
.top-button {
|
||||
height: 36px;
|
||||
margin-top: 22px
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Server } from '../../../../models/server';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { ServerService } from '../../../../services/server.service';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { VirtualBoxTemplate } from '../../../../models/templates/virtualbox-template';
|
||||
import { VirtualBoxService } from '../../../../services/virtual-box.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-virtual-box-templates',
|
||||
templateUrl: './virtual-box-templates.component.html',
|
||||
styleUrls: ['./virtual-box-templates.component.scss']
|
||||
})
|
||||
export class VirtualBoxTemplatesComponent implements OnInit {
|
||||
server: Server;
|
||||
virtualBoxTemplates: VirtualBoxTemplate[] = [];
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private serverService: ServerService,
|
||||
private virtualBoxService: VirtualBoxService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.paramMap
|
||||
.pipe(
|
||||
switchMap((params: ParamMap) => {
|
||||
const server_id = params.get('server_id');
|
||||
return this.serverService.get(parseInt(server_id, 10));
|
||||
})
|
||||
)
|
||||
.subscribe((server: Server) => {
|
||||
this.server = server;
|
||||
|
||||
this.virtualBoxService.getTemplates(this.server).subscribe((virtualBoxTemplates: VirtualBoxTemplate[]) => {
|
||||
virtualBoxTemplates.forEach((template) => {
|
||||
if ((template.template_type === 'virtualbox') && !template.builtin) {
|
||||
this.virtualBoxTemplates.push(template);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
<div class="content" [ngClass]="{ shadowed: isConfiguratorOpened }" [ngClass]="{ nonshadowed: !isConfiguratorOpened }">
|
||||
<div class="content">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">VPCS device configuration</h1>
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { CustomAdapter } from '../qemu/qemu-custom-adapter';
|
||||
|
||||
export interface VirtualBoxTemplate {
|
||||
adapter_type: string;
|
||||
adapters: number;
|
||||
@ -6,7 +8,7 @@ export interface VirtualBoxTemplate {
|
||||
compute_id: string;
|
||||
console_auto_start: boolean;
|
||||
console_type: string;
|
||||
custom_adapters?: (null)[] | null;
|
||||
custom_adapters?: CustomAdapter[];
|
||||
default_name_format: string;
|
||||
first_port_name: string;
|
||||
headless: boolean;
|
||||
|
4
src/app/models/virtualBox/virtualBoxVm.ts
Normal file
4
src/app/models/virtualBox/virtualBoxVm.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class VirtualBoxVm {
|
||||
ram: number;
|
||||
vmname: string;
|
||||
}
|
@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { QemuTemplate } from '../models/templates/qemu-template';
|
||||
import { VpcsTemplate } from '../models/templates/vpcs-template';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { VirtualBoxTemplate } from '../models/templates/virtualbox-template';
|
||||
|
||||
@Injectable()
|
||||
export class TemplateMocksService {
|
||||
@ -71,4 +72,34 @@ export class TemplateMocksService {
|
||||
|
||||
return of(template);
|
||||
}
|
||||
|
||||
getVirtualBoxTemplate() : Observable<VirtualBoxTemplate> {
|
||||
let template: VirtualBoxTemplate = {
|
||||
adapter_type: 'Intel PRO/1000 MT Desktop (82540EM)',
|
||||
adapters: 1,
|
||||
builtin: false,
|
||||
category: 'guest',
|
||||
compute_id: 'local',
|
||||
console_auto_start: false,
|
||||
console_type: 'none',
|
||||
custom_adapters: [],
|
||||
default_name_format: '{name}-{0}',
|
||||
first_port_name: '',
|
||||
headless: false,
|
||||
linked_clone: false,
|
||||
name: '',
|
||||
on_close: 'power_off',
|
||||
port_name_format: 'Ethernet{0}',
|
||||
port_segment_size: 0,
|
||||
ram: 0,
|
||||
symbol: ':/symbols/vbox_guest.svg',
|
||||
template_id: '',
|
||||
template_type: 'virtualbox',
|
||||
usage: '',
|
||||
use_any_adapter: false,
|
||||
vmname: ''
|
||||
}
|
||||
|
||||
return of(template);
|
||||
}
|
||||
}
|
||||
|
0
src/app/services/virtual-box.service.spec.ts
Normal file
0
src/app/services/virtual-box.service.spec.ts
Normal file
31
src/app/services/virtual-box.service.ts
Normal file
31
src/app/services/virtual-box.service.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { HttpServer } from './http-server.service';
|
||||
import { Server } from '../models/server';
|
||||
import { Observable } from 'rxjs';
|
||||
import { VirtualBoxTemplate } from '../models/templates/virtualbox-template';
|
||||
import { VirtualBoxVm } from '../models/virtualbox/virtualboxVm';
|
||||
|
||||
@Injectable()
|
||||
export class VirtualBoxService {
|
||||
constructor(private httpServer: HttpServer) {}
|
||||
|
||||
getTemplates(server: Server): Observable<VirtualBoxTemplate[]> {
|
||||
return this.httpServer.get<VirtualBoxTemplate[]>(server, '/templates') as Observable<VirtualBoxTemplate[]>;
|
||||
}
|
||||
|
||||
getTemplate(server: Server, template_id: string): Observable<VirtualBoxTemplate> {
|
||||
return this.httpServer.get<VirtualBoxTemplate>(server, `/templates/${template_id}`) as Observable<VirtualBoxTemplate>;
|
||||
}
|
||||
|
||||
addTemplate(server: Server, virtualBoxTemplate: VirtualBoxTemplate): Observable<VirtualBoxTemplate> {
|
||||
return this.httpServer.post<VirtualBoxTemplate>(server, `/templates`, virtualBoxTemplate) as Observable<VirtualBoxTemplate>;
|
||||
}
|
||||
|
||||
saveTemplate(server: Server, virtualBoxTemplate: VirtualBoxTemplate): Observable<VirtualBoxTemplate> {
|
||||
return this.httpServer.put<VirtualBoxTemplate>(server, `/templates/${virtualBoxTemplate.template_id}`, virtualBoxTemplate) as Observable<VirtualBoxTemplate>;
|
||||
}
|
||||
|
||||
getVirtualMachines(server: Server) : Observable<VirtualBoxVm[]> {
|
||||
return this.httpServer.get<VirtualBoxVm[]>(server, '/compute/virtualbox/vms') as Observable<VirtualBoxVm[]>;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user