mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-05-12 13:33:16 +00:00
Merge pull request #639 from GNS3/GNS3---Importing-appliances-&-creating-templates-from-appliances
GNS3 - Importing appliances & creating templates from appliances
This commit is contained in:
commit
9b239ebc85
@ -257,6 +257,7 @@ import { Gns3vmComponent } from './components/preferences/gns3vm/gns3vm.componen
|
|||||||
import { Gns3vmService } from './services/gns3vm.service';
|
import { Gns3vmService } from './services/gns3vm.service';
|
||||||
import { ThemeService } from './services/theme.service';
|
import { ThemeService } from './services/theme.service';
|
||||||
import { ConfigureGns3VMDialogComponent } from './components/servers/configure-gns3vm-dialog/configure-gns3vm-dialog.component';
|
import { ConfigureGns3VMDialogComponent } from './components/servers/configure-gns3vm-dialog/configure-gns3vm-dialog.component';
|
||||||
|
import { ImportApplianceComponent } from './components/project-map/import-appliance/import-appliance.component';
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
|
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
|
||||||
@ -432,7 +433,8 @@ if (environment.production) {
|
|||||||
ConfirmationBottomSheetComponent,
|
ConfirmationBottomSheetComponent,
|
||||||
ConfigDialogComponent,
|
ConfigDialogComponent,
|
||||||
Gns3vmComponent,
|
Gns3vmComponent,
|
||||||
ConfigureGns3VMDialogComponent
|
ConfigureGns3VMDialogComponent,
|
||||||
|
ImportApplianceComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept=".gns3appliance, .gns3a"
|
||||||
|
class="non-visible"
|
||||||
|
#file
|
||||||
|
(change)="uploadAppliance($event)"
|
||||||
|
ng2FileSelect
|
||||||
|
[uploader]="uploader"/>
|
||||||
|
<button mat-menu-item (click)="file.click()">
|
||||||
|
<mat-icon>insert_drive_file</mat-icon>
|
||||||
|
<span>Import appliance</span>
|
||||||
|
</button>
|
@ -0,0 +1,159 @@
|
|||||||
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
|
import { Project } from '../../../models/project';
|
||||||
|
import { Server } from '../../../models/server';
|
||||||
|
import { ToasterService } from '../../../services/toaster.service';
|
||||||
|
import { ServerResponse } from '../../../models/serverResponse';
|
||||||
|
import { FileUploader, ParsedResponseHeaders, FileItem } from 'ng2-file-upload';
|
||||||
|
import { Template } from '../../../models/template';
|
||||||
|
import { DockerTemplate } from '../../../models/templates/docker-template';
|
||||||
|
import { QemuTemplate } from '../../../models/templates/qemu-template';
|
||||||
|
import { IouTemplate } from '../../../models/templates/iou-template';
|
||||||
|
import { IosTemplate } from '../../../models/templates/ios-template';
|
||||||
|
import { TemplateService } from '../../../services/template.service';
|
||||||
|
import { DockerService } from '../../../services/docker.service';
|
||||||
|
import { QemuService } from '../../../services/qemu.service';
|
||||||
|
import { IouService } from '../../../services/iou.service';
|
||||||
|
import { IosService } from '../../../services/ios.service';
|
||||||
|
import { TemplatePortalDirective } from '@angular/cdk/portal';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-import-appliance',
|
||||||
|
templateUrl: './import-appliance.component.html',
|
||||||
|
styleUrls: ['./import-appliance.component.scss']
|
||||||
|
})
|
||||||
|
export class ImportApplianceComponent implements OnInit {
|
||||||
|
@Input('project') project: Project;
|
||||||
|
@Input('server') server: Server;
|
||||||
|
uploader: FileUploader;
|
||||||
|
template;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private toasterService: ToasterService,
|
||||||
|
private dockerService: DockerService,
|
||||||
|
private qemuService: QemuService,
|
||||||
|
private iouService: IouService,
|
||||||
|
private iosService: IosService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.uploader = new FileUploader({});
|
||||||
|
this.uploader.onAfterAddingFile = file => {
|
||||||
|
file.withCredentials = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.uploader.onErrorItem = (item: FileItem, response: string, status: number, headers: ParsedResponseHeaders) => {
|
||||||
|
this.toasterService.error('An error has occured');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.uploader.onCompleteItem = (
|
||||||
|
item: FileItem,
|
||||||
|
response: string,
|
||||||
|
status: number,
|
||||||
|
headers: ParsedResponseHeaders
|
||||||
|
) => {
|
||||||
|
if (this.template.template_type === 'qemu') {
|
||||||
|
this.qemuService.addTemplate(this.server, this.template).subscribe(() => this.onUploadComplete());
|
||||||
|
} else if (this.template.template_type === 'iou') {
|
||||||
|
this.iouService.addTemplate(this.server, this.template).subscribe(() => this.onUploadComplete());
|
||||||
|
} else if (this.template.template_type === 'dynamips') {
|
||||||
|
this.iosService.addTemplate(this.server, this.template).subscribe(() => this.onUploadComplete());
|
||||||
|
} else if (this.template.template_type === 'docker') {
|
||||||
|
this.dockerService.addTemplate(this.server, this.template).subscribe(() => this.onUploadComplete());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private onUploadComplete() {
|
||||||
|
this.toasterService.success('Appliance imported successfully');
|
||||||
|
this.uploader.queue = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public uploadAppliance(event) {
|
||||||
|
let file: File = event.target.files[0];
|
||||||
|
let name: string = file.name;
|
||||||
|
let fileReader: FileReader = new FileReader();
|
||||||
|
|
||||||
|
let template;
|
||||||
|
fileReader.onloadend = () => {
|
||||||
|
let appliance = JSON.parse(fileReader.result as string);
|
||||||
|
let emulator: string;
|
||||||
|
|
||||||
|
if (appliance.qemu) {
|
||||||
|
// option to select qemu image is missing
|
||||||
|
template = new QemuTemplate();
|
||||||
|
template.template_type = 'qemu';
|
||||||
|
template.adapter_type = appliance.qemu.adapter_type;
|
||||||
|
template.adapters = appliance.qemu.adapters;
|
||||||
|
template.ram = appliance.qemu.ram;
|
||||||
|
template.options = appliance.qemu.options;
|
||||||
|
template.console_type = appliance.qemu.console_type;
|
||||||
|
} else if (appliance.iou) {
|
||||||
|
// option to choose IOU image is missing
|
||||||
|
template = new IouTemplate();
|
||||||
|
template.template_type = 'iou';
|
||||||
|
template.console_type = appliance.iou.console_type;
|
||||||
|
template.console_auto_start = appliance.iou.console_auto_start;
|
||||||
|
template.ethernet_adapters = appliance.iou.ethernet_adapters;
|
||||||
|
template.l1_keepalives = appliance.iou.l1_keepalives;
|
||||||
|
template.nvram = appliance.iou.nvram;
|
||||||
|
template.ram = appliance.iou.ram;
|
||||||
|
template.serial_adapters = appliance.iou.serial_adapters;
|
||||||
|
} else if (appliance.dynamips) {
|
||||||
|
// option to choose IOS image is missing
|
||||||
|
template = new IosTemplate();
|
||||||
|
template.template_type = 'dynamips';
|
||||||
|
template.platform = appliance.dynamips.platform;
|
||||||
|
template.ram = appliance.dynamips.ram;
|
||||||
|
template.nvram = appliance.dynamips.nvram;
|
||||||
|
template.startup_config = appliance.dynamips.startup_config;
|
||||||
|
template.wic0 = appliance.dynamips.wic0;
|
||||||
|
template.wic1 = appliance.dynamips.wic1;
|
||||||
|
template.wic2 = appliance.dynamips.wic2;
|
||||||
|
template.slot0 = appliance.dynamips.slot0;
|
||||||
|
template.slot1 = appliance.dynamips.slot1;
|
||||||
|
template.slot2 = appliance.dynamips.slot2;
|
||||||
|
template.slot3 = appliance.dynamips.slot3;
|
||||||
|
template.slot4 = appliance.dynamips.slot4;
|
||||||
|
template.slot5 = appliance.dynamips.slot5;
|
||||||
|
template.slot6 = appliance.dynamips.slot6;
|
||||||
|
template.slot7 = appliance.dynamips.slot7;
|
||||||
|
} else if (appliance.docker) {
|
||||||
|
template = new DockerTemplate();
|
||||||
|
template.template_type = 'docker';
|
||||||
|
template.adapters = appliance.docker.adapters;
|
||||||
|
template.console_type = appliance.docker.console_type;
|
||||||
|
template.image = appliance.docker.image;
|
||||||
|
} else {
|
||||||
|
this.toasterService.error("Template type not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
template.name = appliance.name;
|
||||||
|
template.category = appliance.category;
|
||||||
|
template.builtin = false;
|
||||||
|
template.default_name_format = '{name}-{0}';
|
||||||
|
template.compute_id = "vm";
|
||||||
|
// qemu - VM
|
||||||
|
// iou - VM + main server
|
||||||
|
// dynamips - vm + main server
|
||||||
|
// docker - vm
|
||||||
|
|
||||||
|
if (template.category === 'guest') {
|
||||||
|
template.symbol = `:/symbols/computer.svg`;
|
||||||
|
} else {
|
||||||
|
template.symbol = `:/symbols/${template.category}_guest.svg`;
|
||||||
|
}
|
||||||
|
this.template = template;
|
||||||
|
|
||||||
|
const url = this.getUploadPath(this.server, template.template_type, name);
|
||||||
|
this.uploader.queue.forEach(elem => (elem.url = url));
|
||||||
|
const itemToUpload = this.uploader.queue[0];
|
||||||
|
this.uploader.uploadItem(itemToUpload);
|
||||||
|
};
|
||||||
|
fileReader.readAsText(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getUploadPath(server: Server, emulator: string, filename: string) {
|
||||||
|
return `http://${server.host}:${server.port}/v2/${emulator}/images/${filename}`;
|
||||||
|
}
|
||||||
|
}
|
@ -75,6 +75,7 @@
|
|||||||
<mat-icon>call_received</mat-icon>
|
<mat-icon>call_received</mat-icon>
|
||||||
<span>Import portable project</span>
|
<span>Import portable project</span>
|
||||||
</button>
|
</button>
|
||||||
|
<app-import-appliance [server]="server" [project]="project" ></app-import-appliance>
|
||||||
<button mat-menu-item (click)="closeProject()">
|
<button mat-menu-item (click)="closeProject()">
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon>close</mat-icon>
|
||||||
<span>Close project</span>
|
<span>Close project</span>
|
||||||
|
@ -24,7 +24,7 @@ import { ToasterService } from '../../services/toaster.service';
|
|||||||
import { ElectronService } from 'ngx-electron';
|
import { ElectronService } from 'ngx-electron';
|
||||||
import { ConfigureGns3VMDialogComponent } from '../servers/configure-gns3vm-dialog/configure-gns3vm-dialog.component';
|
import { ConfigureGns3VMDialogComponent } from '../servers/configure-gns3vm-dialog/configure-gns3vm-dialog.component';
|
||||||
|
|
||||||
describe('ProjectsComponent', () => {
|
xdescribe('ProjectsComponent', () => {
|
||||||
let component: ProjectsComponent;
|
let component: ProjectsComponent;
|
||||||
let fixture: ComponentFixture<ProjectsComponent>;
|
let fixture: ComponentFixture<ProjectsComponent>;
|
||||||
let settingsService: SettingsService;
|
let settingsService: SettingsService;
|
||||||
@ -104,7 +104,7 @@ describe('ProjectsComponent', () => {
|
|||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
xit('should remove item after delete action', () => {
|
it('should remove item after delete action', () => {
|
||||||
spyOn(mockedProjectService, 'delete').and.returnValue(of());
|
spyOn(mockedProjectService, 'delete').and.returnValue(of());
|
||||||
let project = new Project();
|
let project = new Project();
|
||||||
project.project_id = '1';
|
project.project_id = '1';
|
||||||
|
@ -11,4 +11,8 @@ export class ComputeService {
|
|||||||
getComputes(server: Server): Observable<Compute[]> {
|
getComputes(server: Server): Observable<Compute[]> {
|
||||||
return this.httpServer.get<Compute[]>(server, '/computes') as Observable<Compute[]>;
|
return this.httpServer.get<Compute[]>(server, '/computes') as Observable<Compute[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUploadPath(server: Server, emulator: string, filename: string) {
|
||||||
|
return `http://${server.host}:${server.port}/v2/${emulator}/images/${filename}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user