mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-06-02 07:20:42 +00:00
Merge branch '2.2' into master-3.0
# Conflicts: # package.json # src/app/app.module.ts # src/app/components/project-map/context-menu/actions/console-device-action-browser/console-device-action-browser.component.ts # src/app/components/project-map/packet-capturing/start-capture/start-capture.component.spec.ts # src/app/components/project-map/project-map.component.ts # src/app/services/packet-capture.service.ts # yarn.lock
This commit is contained in:
commit
3880d28ec1
@ -217,6 +217,7 @@ import { DefaultLayoutComponent } from './layouts/default-layout/default-layout.
|
|||||||
import { MATERIAL_IMPORTS } from './material.imports';
|
import { MATERIAL_IMPORTS } from './material.imports';
|
||||||
import { ControllerResolve } from './resolvers/controller-resolve';
|
import { ControllerResolve } from './resolvers/controller-resolve';
|
||||||
import { ApplianceService } from './services/appliances.service';
|
import { ApplianceService } from './services/appliances.service';
|
||||||
|
import { ProtocolHandlerService } from './services/protocol-handler.service';
|
||||||
import { BuiltInTemplatesConfigurationService } from './services/built-in-templates-configuration.service';
|
import { BuiltInTemplatesConfigurationService } from './services/built-in-templates-configuration.service';
|
||||||
import { BuiltInTemplatesService } from './services/built-in-templates.service';
|
import { BuiltInTemplatesService } from './services/built-in-templates.service';
|
||||||
import { ComputeService } from './services/compute.service';
|
import { ComputeService } from './services/compute.service';
|
||||||
@ -651,6 +652,7 @@ import { DeleteResourceConfirmationDialogComponent } from './components/resource
|
|||||||
InfoService,
|
InfoService,
|
||||||
ComputeService,
|
ComputeService,
|
||||||
PacketCaptureService,
|
PacketCaptureService,
|
||||||
|
ProtocolHandlerService,
|
||||||
NotificationService,
|
NotificationService,
|
||||||
ThemeService,
|
ThemeService,
|
||||||
GoogleAnalyticsService,
|
GoogleAnalyticsService,
|
||||||
|
@ -14,6 +14,7 @@ export class Properties {
|
|||||||
headless: boolean;
|
headless: boolean;
|
||||||
linked_clone: boolean;
|
linked_clone: boolean;
|
||||||
on_close: string;
|
on_close: string;
|
||||||
|
aux: number;
|
||||||
ram: number;
|
ram: number;
|
||||||
nvram: number;
|
nvram: number;
|
||||||
usage: string;
|
usage: string;
|
||||||
|
@ -2,3 +2,11 @@
|
|||||||
<mat-icon>web_asset</mat-icon>
|
<mat-icon>web_asset</mat-icon>
|
||||||
<span>Console</span>
|
<span>Console</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
*ngIf="node.node_type === 'docker' || node.node_type === 'dynamips'"
|
||||||
|
(click)="openConsole(auxiliary=true)"
|
||||||
|
>
|
||||||
|
<mat-icon>web_asset</mat-icon>
|
||||||
|
<span>Auxiliary console</span>
|
||||||
|
</button>
|
||||||
|
@ -4,6 +4,8 @@ import { Node } from '../../../../../cartography/models/node';
|
|||||||
import { Controller } from '../../../../../models/controller';
|
import { Controller } from '../../../../../models/controller';
|
||||||
import { NodeService } from '../../../../../services/node.service';
|
import { NodeService } from '../../../../../services/node.service';
|
||||||
import { ToasterService } from '../../../../../services/toaster.service';
|
import { ToasterService } from '../../../../../services/toaster.service';
|
||||||
|
import { ProtocolHandlerService } from '../../../../../services/protocol-handler.service';
|
||||||
|
|
||||||
import * as ipaddr from 'ipaddr.js';
|
import * as ipaddr from 'ipaddr.js';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -17,43 +19,18 @@ export class ConsoleDeviceActionBrowserComponent {
|
|||||||
constructor(
|
constructor(
|
||||||
private toasterService: ToasterService,
|
private toasterService: ToasterService,
|
||||||
private nodeService: NodeService,
|
private nodeService: NodeService,
|
||||||
private deviceService: DeviceDetectorService
|
private deviceService: DeviceDetectorService,
|
||||||
|
private protocolHandlerService: ProtocolHandlerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
openConsole() {
|
openConsole(auxiliary: boolean = false) {
|
||||||
this.nodeService.getNode(this.controller, this.node).subscribe((node: Node) => {
|
this.nodeService.getNode(this.controller, this.node).subscribe((node: Node) => {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.startConsole();
|
this.startConsole(auxiliary);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createHiddenIframe(target: Element, uri: string) {
|
startConsole(auxiliary: boolean) {
|
||||||
const iframe = document.createElement("iframe");
|
|
||||||
iframe.src = uri;
|
|
||||||
iframe.id = "hiddenIframe";
|
|
||||||
iframe.style.display = "none";
|
|
||||||
target.appendChild(iframe);
|
|
||||||
return iframe;
|
|
||||||
}
|
|
||||||
|
|
||||||
openUriUsingFirefox(uri: string) {
|
|
||||||
var iframe = (document.querySelector("#hiddenIframe") as HTMLIFrameElement);
|
|
||||||
|
|
||||||
if (!iframe) {
|
|
||||||
iframe = this.createHiddenIframe(document.body, "about:blank");
|
|
||||||
//setTimeout(() => { iframe.parentNode.removeChild(iframe); }, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
iframe.contentWindow.location.href = uri;
|
|
||||||
} catch (e) {
|
|
||||||
if (e.name === "NS_ERROR_UNKNOWN_PROTOCOL") {
|
|
||||||
this.toasterService.error('Protocol handler does not exist');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
startConsole() {
|
|
||||||
if (this.node.status !== 'started') {
|
if (this.node.status !== 'started') {
|
||||||
this.toasterService.error('This node must be started before a console can be opened');
|
this.toasterService.error('This node must be started before a console can be opened');
|
||||||
} else {
|
} else {
|
||||||
@ -65,8 +42,6 @@ export class ConsoleDeviceActionBrowserComponent {
|
|||||||
this.node.console_host = this.controller.host;
|
this.node.console_host = this.controller.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device = this.deviceService.getDeviceInfo();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var uri;
|
var uri;
|
||||||
var host = this.node.console_host;
|
var host = this.node.console_host;
|
||||||
@ -74,7 +49,18 @@ export class ConsoleDeviceActionBrowserComponent {
|
|||||||
host = `[${host}]`;
|
host = `[${host}]`;
|
||||||
}
|
}
|
||||||
if (this.node.console_type === 'telnet') {
|
if (this.node.console_type === 'telnet') {
|
||||||
uri = `gns3+telnet://${host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`;
|
|
||||||
|
var console_port;
|
||||||
|
if (auxiliary === true) {
|
||||||
|
console_port = this.node.properties.aux;
|
||||||
|
if (console_port === undefined) {
|
||||||
|
this.toasterService.error('Auxiliary console port is not set.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console_port = this.node.console;
|
||||||
|
}
|
||||||
|
uri = `gns3+telnet://${host}:${console_port}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`;
|
||||||
} else if (this.node.console_type === 'vnc') {
|
} else if (this.node.console_type === 'vnc') {
|
||||||
uri = `gns3+vnc://${host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`;
|
uri = `gns3+vnc://${host}:${this.node.console}?name=${this.node.name}&project_id=${this.node.project_id}&node_id=${this.node.node_id}`;
|
||||||
} else if (this.node.console_type.startsWith('spice')) {
|
} else if (this.node.console_type.startsWith('spice')) {
|
||||||
@ -84,16 +70,10 @@ export class ConsoleDeviceActionBrowserComponent {
|
|||||||
return window.open(uri); // open an http console directly in a new window/tab
|
return window.open(uri); // open an http console directly in a new window/tab
|
||||||
} else {
|
} else {
|
||||||
this.toasterService.error('Supported console types are: telnet, vnc, spice and spice+agent.');
|
this.toasterService.error('Supported console types are: telnet, vnc, spice and spice+agent.');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Opening external console using " + device.browser + " browser");
|
this.protocolHandlerService.open(uri);
|
||||||
if (device.browser === "Firefox") {
|
|
||||||
// Use a hidden iframe otherwise Firefox will disconnect
|
|
||||||
// from the GNS3 controller websocket if we use location.assign()
|
|
||||||
this.openUriUsingFirefox(uri);
|
|
||||||
} else {
|
|
||||||
location.assign(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.toasterService.error(e);
|
this.toasterService.error(e);
|
||||||
|
@ -6,6 +6,7 @@ import { MatMenuModule } from '@angular/material/menu';
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { ToasterService } from '../../../services/toaster.service';
|
import { ToasterService } from '../../../services/toaster.service';
|
||||||
|
import { ProtocolHandlerService } from '../../../services/protocol-handler.service';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { NodesDataSource } from '../../../cartography/datasources/nodes-datasource';
|
import { NodesDataSource } from '../../../cartography/datasources/nodes-datasource';
|
||||||
import { ProjectWebServiceHandler, WebServiceMessage } from '../../../handlers/project-web-service-handler';
|
import { ProjectWebServiceHandler, WebServiceMessage } from '../../../handlers/project-web-service-handler';
|
||||||
@ -38,6 +39,7 @@ describe('LogConsoleComponent', () => {
|
|||||||
let nodeConsoleService: NodeConsoleService;
|
let nodeConsoleService: NodeConsoleService;
|
||||||
let mapSettingsService: MapSettingsService;
|
let mapSettingsService: MapSettingsService;
|
||||||
let toasterService: ToasterService;
|
let toasterService: ToasterService;
|
||||||
|
let protocolHandlerService: ProtocolHandlerService;
|
||||||
|
|
||||||
let httpController = new HttpController({} as HttpClient, {} as ControllerErrorHandler);
|
let httpController = new HttpController({} as HttpClient, {} as ControllerErrorHandler);
|
||||||
|
|
||||||
@ -52,6 +54,7 @@ describe('LogConsoleComponent', () => {
|
|||||||
{ provide: HttpController, useValue: httpController },
|
{ provide: HttpController, useValue: httpController },
|
||||||
NodeConsoleService,
|
NodeConsoleService,
|
||||||
ToasterService,
|
ToasterService,
|
||||||
|
ProtocolHandlerService,
|
||||||
MapSettingsService
|
MapSettingsService
|
||||||
],
|
],
|
||||||
declarations: [LogConsoleComponent],
|
declarations: [LogConsoleComponent],
|
||||||
@ -59,6 +62,7 @@ describe('LogConsoleComponent', () => {
|
|||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
toasterService = TestBed.inject(ToasterService);
|
toasterService = TestBed.inject(ToasterService);
|
||||||
|
protocolHandlerService = TestBed.inject(ProtocolHandlerService);
|
||||||
mapSettingsService = TestBed.inject(MapSettingsService);
|
mapSettingsService = TestBed.inject(MapSettingsService);
|
||||||
nodeConsoleService = TestBed.inject(NodeConsoleService);
|
nodeConsoleService = TestBed.inject(NodeConsoleService);
|
||||||
});
|
});
|
||||||
|
@ -23,6 +23,7 @@ import{ Controller } from '../../../models/controller';
|
|||||||
import { HttpController } from '../../../services/http-controller.service';
|
import { HttpController } from '../../../services/http-controller.service';
|
||||||
import { NodeService } from '../../../services/node.service';
|
import { NodeService } from '../../../services/node.service';
|
||||||
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
import { NodeConsoleService } from '../../../services/nodeConsole.service';
|
||||||
|
import { ProtocolHandlerService } from '../../../services/protocol-handler.service';
|
||||||
import { ThemeService } from '../../../services/theme.service';
|
import { ThemeService } from '../../../services/theme.service';
|
||||||
import { version } from '../../../version';
|
import { version } from '../../../version';
|
||||||
import { LogEventsDataSource } from './log-events-datasource';
|
import { LogEventsDataSource } from './log-events-datasource';
|
||||||
@ -70,6 +71,7 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
private projectWebServiceHandler: ProjectWebServiceHandler,
|
private projectWebServiceHandler: ProjectWebServiceHandler,
|
||||||
private nodeService: NodeService,
|
private nodeService: NodeService,
|
||||||
private nodesDataSource: NodesDataSource,
|
private nodesDataSource: NodesDataSource,
|
||||||
|
private protocolHandlerService: ProtocolHandlerService,
|
||||||
private logEventsDataSource: LogEventsDataSource,
|
private logEventsDataSource: LogEventsDataSource,
|
||||||
private httpService: HttpController,
|
private httpService: HttpController,
|
||||||
private themeService: ThemeService,
|
private themeService: ThemeService,
|
||||||
@ -230,15 +232,15 @@ export class LogConsoleComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
host = `[${host}]`;
|
host = `[${host}]`;
|
||||||
}
|
}
|
||||||
if (node.console_type === 'telnet') {
|
if (node.console_type === 'telnet') {
|
||||||
location.assign(
|
this.protocolHandlerService.open(
|
||||||
`gns3+telnet://${host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
`gns3+telnet://${host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
||||||
);
|
);
|
||||||
} else if (node.console_type === 'vnc') {
|
} else if (node.console_type === 'vnc') {
|
||||||
location.assign(
|
this.protocolHandlerService.open(
|
||||||
`gns3+vnc://${host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
`gns3+vnc://${host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
||||||
);
|
);
|
||||||
} else if (node.console_type.startsWith('spice')) {
|
} else if (node.console_type.startsWith('spice')) {
|
||||||
location.assign(
|
this.protocolHandlerService.open(
|
||||||
`gns3+spice://${host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
`gns3+spice://${host}:${node.console}?name=${node.name}&project_id=${node.project_id}&node_id=${node.node_id}`
|
||||||
);
|
);
|
||||||
} else if (node.console_type.startsWith('http')) {
|
} else if (node.console_type.startsWith('http')) {
|
||||||
|
@ -17,6 +17,7 @@ import { ToasterService } from '../../../../services/toaster.service';
|
|||||||
import { MockedToasterService } from '../../../../services/toaster.service.spec';
|
import { MockedToasterService } from '../../../../services/toaster.service.spec';
|
||||||
import { MockedLinkService, MockedNodesDataSource } from '../../project-map.component.spec';
|
import { MockedLinkService, MockedNodesDataSource } from '../../project-map.component.spec';
|
||||||
import { StartCaptureDialogComponent } from './start-capture.component';
|
import { StartCaptureDialogComponent } from './start-capture.component';
|
||||||
|
import { ProtocolHandlerService } from '../../../../services/protocol-handler.service';
|
||||||
|
|
||||||
describe('StartCaptureDialogComponent', () => {
|
describe('StartCaptureDialogComponent', () => {
|
||||||
let component: StartCaptureDialogComponent;
|
let component: StartCaptureDialogComponent;
|
||||||
@ -25,6 +26,8 @@ describe('StartCaptureDialogComponent', () => {
|
|||||||
let mockedToasterService = new MockedToasterService();
|
let mockedToasterService = new MockedToasterService();
|
||||||
let mockedLinkService = new MockedLinkService();
|
let mockedLinkService = new MockedLinkService();
|
||||||
let mockedNodesDataSource = new MockedNodesDataSource();
|
let mockedNodesDataSource = new MockedNodesDataSource();
|
||||||
|
let protocolHandlerService: ProtocolHandlerService;
|
||||||
|
|
||||||
let dialogRef = {
|
let dialogRef = {
|
||||||
close: jasmine.createSpy('close'),
|
close: jasmine.createSpy('close'),
|
||||||
};
|
};
|
||||||
@ -49,11 +52,14 @@ describe('StartCaptureDialogComponent', () => {
|
|||||||
{ provide: LinkService, useValue: mockedLinkService },
|
{ provide: LinkService, useValue: mockedLinkService },
|
||||||
{ provide: NodesDataSource, useValue: mockedNodesDataSource },
|
{ provide: NodesDataSource, useValue: mockedNodesDataSource },
|
||||||
{ provide: PacketCaptureService },
|
{ provide: PacketCaptureService },
|
||||||
|
ProtocolHandlerService,
|
||||||
],
|
],
|
||||||
declarations: [StartCaptureDialogComponent],
|
declarations: [StartCaptureDialogComponent],
|
||||||
schemas: [NO_ERRORS_SCHEMA],
|
schemas: [NO_ERRORS_SCHEMA],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
});
|
|
||||||
|
protocolHandlerService = TestBed.inject(ProtocolHandlerService);
|
||||||
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(StartCaptureDialogComponent);
|
fixture = TestBed.createComponent(StartCaptureDialogComponent);
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Link } from '../models/link';
|
import { Link } from '../models/link';
|
||||||
import { Project } from '../models/project';
|
import { Project } from '../models/project';
|
||||||
import{ Controller } from '../models/controller';
|
import { Controller } from '../models/controller';
|
||||||
|
import { ProtocolHandlerService } from './protocol-handler.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PacketCaptureService {
|
export class PacketCaptureService {
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
startCapture(controller:Controller , project: Project, link: Link, name: string) {
|
constructor(private protocolHandlerService: ProtocolHandlerService) {}
|
||||||
location.assign(
|
|
||||||
`gns3+pcap://${controller.host}:${controller.port}?protocol=${controller.protocol.slice(0, -1)}&project_id=${project.project_id}&link_id=${link.link_id}&project=${project.name}&name=${name}`
|
startCapture(controller: Controller, project: Project, link: Link, name: string) {
|
||||||
);
|
|
||||||
|
const uri = `gns3+pcap://${controller.host}:${controller.port}?protocol=${controller.protocol.slice(0, -1)}&project_id=${project.project_id}&link_id=${link.link_id}&project=${project.name}&name=${name}`;
|
||||||
|
this.protocolHandlerService.open(uri);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
48
src/app/services/protocol-handler.service.ts
Normal file
48
src/app/services/protocol-handler.service.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||||
|
import { ToasterService } from './toaster.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ProtocolHandlerService {
|
||||||
|
|
||||||
|
constructor(private toasterService: ToasterService, private deviceService: DeviceDetectorService) {}
|
||||||
|
|
||||||
|
createHiddenIframe(target: Element, uri: string) {
|
||||||
|
const iframe = document.createElement("iframe");
|
||||||
|
iframe.src = uri;
|
||||||
|
iframe.id = "hiddenIframe";
|
||||||
|
iframe.style.display = "none";
|
||||||
|
target.appendChild(iframe);
|
||||||
|
return iframe;
|
||||||
|
}
|
||||||
|
|
||||||
|
openUriUsingFirefox(uri: string) {
|
||||||
|
var iframe = (document.querySelector("#hiddenIframe") as HTMLIFrameElement);
|
||||||
|
|
||||||
|
if (!iframe) {
|
||||||
|
iframe = this.createHiddenIframe(document.body, "about:blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
iframe.contentWindow.location.href = uri;
|
||||||
|
} catch (e) {
|
||||||
|
if (e.name === "NS_ERROR_UNKNOWN_PROTOCOL") {
|
||||||
|
this.toasterService.error('Protocol handler does not exist');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open(uri: string) {
|
||||||
|
|
||||||
|
const device = this.deviceService.getDeviceInfo();
|
||||||
|
|
||||||
|
console.log("Launching external protocol handler with " + device.browser + ": " + uri)
|
||||||
|
if (device.browser === "Firefox") {
|
||||||
|
// Use a hidden iframe otherwise Firefox will disconnect
|
||||||
|
// from the GNS3 controller websocket if we use location.assign()
|
||||||
|
this.openUriUsingFirefox(uri);
|
||||||
|
} else {
|
||||||
|
location.assign(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user