mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-05-11 13:03:05 +00:00
Merge remote-tracking branch 'origin/os-console' into putty-bundled
This commit is contained in:
commit
39e98e31ba
33
console-executor.js
Normal file
33
console-executor.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
const { spawn } = require('child_process');
|
||||||
|
|
||||||
|
exports.openConsole = async (consoleRequest) => {
|
||||||
|
const genericConsoleCommand = 'xfce4-terminal --tab -T "%d" -e "telnet %h %p"';
|
||||||
|
const command = prepareCommand(genericConsoleCommand, consoleRequest);
|
||||||
|
console.log(`Starting console with command: '${command}'`);
|
||||||
|
|
||||||
|
let consoleProcess = spawn(command, [], {
|
||||||
|
shell :true
|
||||||
|
});
|
||||||
|
|
||||||
|
consoleProcess.stdout.on('data', (data) => {
|
||||||
|
console.log(`Console is producing: ${data.toString()}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function prepareCommand(consoleCommand, consoleRequest) {
|
||||||
|
const mapping = {
|
||||||
|
h: consoleRequest.host,
|
||||||
|
p: consoleRequest.port,
|
||||||
|
d: consoleRequest.name,
|
||||||
|
i: consoleRequest.project_id,
|
||||||
|
n: consoleRequest.node_id,
|
||||||
|
c: consoleRequest.server_url
|
||||||
|
};
|
||||||
|
|
||||||
|
for(var key in mapping) {
|
||||||
|
const regExp = new RegExp(`%${key}`, 'g');
|
||||||
|
consoleCommand = consoleCommand.replace(regExp, mapping[key]);
|
||||||
|
}
|
||||||
|
return consoleCommand;
|
||||||
|
}
|
@ -16,6 +16,7 @@ files:
|
|||||||
- sentry.js
|
- sentry.js
|
||||||
- installed-software.js
|
- installed-software.js
|
||||||
- local-server.js
|
- local-server.js
|
||||||
|
- console-executor.js
|
||||||
- package.json
|
- package.json
|
||||||
|
|
||||||
extraFiles:
|
extraFiles:
|
||||||
|
@ -51,6 +51,7 @@ import { CopyIosTemplateComponent } from './components/preferences/dynamips/copy
|
|||||||
import { CopyDockerTemplateComponent } from './components/preferences/docker/copy-docker-template/copy-docker-template.component';
|
import { CopyDockerTemplateComponent } from './components/preferences/docker/copy-docker-template/copy-docker-template.component';
|
||||||
import { CopyIouTemplateComponent } from './components/preferences/ios-on-unix/copy-iou-template/copy-iou-template.component';
|
import { CopyIouTemplateComponent } from './components/preferences/ios-on-unix/copy-iou-template/copy-iou-template.component';
|
||||||
import { ListOfSnapshotsComponent } from './components/snapshots/list-of-snapshots/list-of-snapshots.component';
|
import { ListOfSnapshotsComponent } from './components/snapshots/list-of-snapshots/list-of-snapshots.component';
|
||||||
|
import { ConsoleComponent } from './components/settings/console/console.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -62,6 +63,7 @@ const routes: Routes = [
|
|||||||
{ path: 'bundled', component: BundledServerFinderComponent },
|
{ path: 'bundled', component: BundledServerFinderComponent },
|
||||||
{ path: 'server/:server_id/projects', component: ProjectsComponent },
|
{ path: 'server/:server_id/projects', component: ProjectsComponent },
|
||||||
{ path: 'settings', component: SettingsComponent },
|
{ path: 'settings', component: SettingsComponent },
|
||||||
|
{ path: 'settings/console', component: ConsoleComponent },
|
||||||
{ path: 'installed-software', component: InstalledSoftwareComponent },
|
{ path: 'installed-software', component: InstalledSoftwareComponent },
|
||||||
{ path: 'server/:server_id/project/:project_id/snapshots', component: ListOfSnapshotsComponent },
|
{ path: 'server/:server_id/project/:project_id/snapshots', component: ListOfSnapshotsComponent },
|
||||||
{ path: 'server/:server_id/preferences', component: PreferencesComponent },
|
{ path: 'server/:server_id/preferences', component: PreferencesComponent },
|
||||||
|
@ -168,6 +168,9 @@ import { ListOfSnapshotsComponent } from './components/snapshots/list-of-snapsho
|
|||||||
import { DateFilter } from './filters/dateFilter.pipe';
|
import { DateFilter } from './filters/dateFilter.pipe';
|
||||||
import { NameFilter } from './filters/nameFilter.pipe';
|
import { NameFilter } from './filters/nameFilter.pipe';
|
||||||
import { CustomAdaptersComponent } from './components/preferences/common/custom-adapters/custom-adapters.component';
|
import { CustomAdaptersComponent } from './components/preferences/common/custom-adapters/custom-adapters.component';
|
||||||
|
|
||||||
|
import { ConsoleDeviceActionComponent } from './components/project-map/context-menu/actions/console-device-action/console-device-action.component';
|
||||||
|
import { ConsoleComponent } from './components/settings/console/console.component';
|
||||||
import { NodesMenuComponent } from './components/project-map/nodes-menu/nodes-menu.component';
|
import { NodesMenuComponent } from './components/project-map/nodes-menu/nodes-menu.component';
|
||||||
import { PacketFiltersActionComponent } from './components/project-map/context-menu/actions/packet-filters-action/packet-filters-action.component';
|
import { PacketFiltersActionComponent } from './components/project-map/context-menu/actions/packet-filters-action/packet-filters-action.component';
|
||||||
import { PacketFiltersDialogComponent } from './components/project-map/packet-capturing/packet-filters/packet-filters.component';
|
import { PacketFiltersDialogComponent } from './components/project-map/packet-capturing/packet-filters/packet-filters.component';
|
||||||
@ -291,6 +294,8 @@ if (environment.production) {
|
|||||||
NameFilter,
|
NameFilter,
|
||||||
ListOfSnapshotsComponent,
|
ListOfSnapshotsComponent,
|
||||||
CustomAdaptersComponent,
|
CustomAdaptersComponent,
|
||||||
|
ConsoleDeviceActionComponent,
|
||||||
|
ConsoleComponent,
|
||||||
NodesMenuComponent
|
NodesMenuComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
<button mat-menu-item (click)="console()">
|
||||||
|
<mat-icon>web_asset</mat-icon>
|
||||||
|
<span>Console</span>
|
||||||
|
</button>
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ConsoleDeviceActionComponent } from './console-device-action.component';
|
||||||
|
|
||||||
|
describe('ConsoleDeviceActionComponent', () => {
|
||||||
|
let component: ConsoleDeviceActionComponent;
|
||||||
|
let fixture: ComponentFixture<ConsoleDeviceActionComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ ConsoleDeviceActionComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ConsoleDeviceActionComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,43 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { Node } from '../../../../../cartography/models/node';
|
||||||
|
import { Server } from '../../../../../models/server';
|
||||||
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
import { Project } from '../../../../../models/project';
|
||||||
|
import { ServerService } from '../../../../../services/server.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-console-device-action',
|
||||||
|
templateUrl: './console-device-action.component.html'
|
||||||
|
})
|
||||||
|
export class ConsoleDeviceActionComponent implements OnInit {
|
||||||
|
@Input() server: Server;
|
||||||
|
@Input() project: Project;
|
||||||
|
@Input() nodes: Node[];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private electronService: ElectronService,
|
||||||
|
private serverService: ServerService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
async console() {
|
||||||
|
for(var node of this.nodes) {
|
||||||
|
const consoleRequest = {
|
||||||
|
type: node.console_type,
|
||||||
|
host: node.console_host,
|
||||||
|
port: node.console,
|
||||||
|
name: node.name,
|
||||||
|
project_id: this.project.project_id,
|
||||||
|
node_id: node.node_id,
|
||||||
|
server_url: this.serverService.getServerUrl(this.server)
|
||||||
|
};
|
||||||
|
await this.openConsole(consoleRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async openConsole(request) {
|
||||||
|
return await this.electronService.remote.require('./console-executor.js').openConsole(request);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,12 @@
|
|||||||
<mat-menu #contextMenu="matMenu" class="context-menu-items">
|
<mat-menu #contextMenu="matMenu" class="context-menu-items">
|
||||||
<app-start-node-action *ngIf="nodes.length" [server]="server" [nodes]="nodes"></app-start-node-action>
|
<app-start-node-action *ngIf="nodes.length" [server]="server" [nodes]="nodes"></app-start-node-action>
|
||||||
<app-stop-node-action *ngIf="nodes.length" [server]="server" [nodes]="nodes"></app-stop-node-action>
|
<app-stop-node-action *ngIf="nodes.length" [server]="server" [nodes]="nodes"></app-stop-node-action>
|
||||||
|
<app-console-device-action
|
||||||
|
*ngIf="!projectService.isReadOnly(project) && nodes.length && isElectronApp"
|
||||||
|
[project]="project"
|
||||||
|
[server]="server"
|
||||||
|
[nodes]="nodes"
|
||||||
|
></app-console-device-action>
|
||||||
<app-edit-style-action *ngIf="drawings.length===1 && !hasTextCapabilities"
|
<app-edit-style-action *ngIf="drawings.length===1 && !hasTextCapabilities"
|
||||||
[server]="server"
|
[server]="server"
|
||||||
[project]="project"
|
[project]="project"
|
||||||
|
@ -9,6 +9,7 @@ import { Drawing } from '../../../cartography/models/drawing';
|
|||||||
import { TextElement } from '../../../cartography/models/drawings/text-element';
|
import { TextElement } from '../../../cartography/models/drawings/text-element';
|
||||||
import { Label } from '../../../cartography/models/label';
|
import { Label } from '../../../cartography/models/label';
|
||||||
import { Link } from '../../../models/link';
|
import { Link } from '../../../models/link';
|
||||||
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -30,17 +31,21 @@ export class ContextMenuComponent implements OnInit {
|
|||||||
labels: Label[] = [];
|
labels: Label[] = [];
|
||||||
links: Link[] = [];
|
links: Link[] = [];
|
||||||
|
|
||||||
hasTextCapabilities: boolean = false;
|
hasTextCapabilities = false;
|
||||||
|
isElectronApp = false;
|
||||||
isBundledServer: boolean = false;
|
isBundledServer: boolean = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private sanitizer: DomSanitizer,
|
private sanitizer: DomSanitizer,
|
||||||
private changeDetector: ChangeDetectorRef,
|
private changeDetector: ChangeDetectorRef,
|
||||||
|
private electronService: ElectronService,
|
||||||
public projectService: ProjectService
|
public projectService: ProjectService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.setPosition(0, 0);
|
this.setPosition(0, 0);
|
||||||
|
|
||||||
|
this.isElectronApp = this.electronService.isElectronApp;
|
||||||
this.isBundledServer = this.server.location === 'bundled';
|
this.isBundledServer = this.server.location === 'bundled';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
src/app/components/settings/console/console.component.html
Normal file
26
src/app/components/settings/console/console.component.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<div class="content">
|
||||||
|
<div class="default-header">
|
||||||
|
<div class="row">
|
||||||
|
<h1 class="col">Console settings</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="default-content">
|
||||||
|
<mat-card>
|
||||||
|
<form [formGroup]="consoleForm">
|
||||||
|
<mat-form-field class="form-field">
|
||||||
|
<input
|
||||||
|
matInput type="text"
|
||||||
|
formControlName="runner"
|
||||||
|
placeholder="Predefined command">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="form-field">
|
||||||
|
<textarea matInput formControlName="command" placeholder="Command"></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
</form>
|
||||||
|
</mat-card>
|
||||||
|
<div class="buttons-bar">
|
||||||
|
<button class="cancel-button" (click)="goBack()" mat-button>Cancel</button>
|
||||||
|
<button mat-raised-button color="primary" (click)="onSave()">Save</button><br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ConsoleComponent } from './console.component';
|
||||||
|
|
||||||
|
describe('ConsoleComponent', () => {
|
||||||
|
let component: ConsoleComponent;
|
||||||
|
let fixture: ComponentFixture<ConsoleComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ ConsoleComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ConsoleComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
21
src/app/components/settings/console/console.component.ts
Normal file
21
src/app/components/settings/console/console.component.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-console',
|
||||||
|
templateUrl: './console.component.html',
|
||||||
|
styleUrls: ['./console.component.scss']
|
||||||
|
})
|
||||||
|
export class ConsoleComponent implements OnInit {
|
||||||
|
|
||||||
|
consoleForm = new FormGroup({
|
||||||
|
'runner': new FormControl('', [ Validators.required ]),
|
||||||
|
'command': new FormControl(''),
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -27,6 +27,21 @@
|
|||||||
>
|
>
|
||||||
</div> -->
|
</div> -->
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
|
|
||||||
|
<mat-expansion-panel [expanded]="true">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title> Console settings </mat-panel-title>
|
||||||
|
<mat-panel-description> Customize console settings </mat-panel-description>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="example-full-width">
|
||||||
|
<input matInput placeholder="console">
|
||||||
|
<a mat-icon-button matSuffix routerLink="/settings/console"><mat-icon>mode_edit</mat-icon></a>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-expansion-panel>
|
||||||
</mat-accordion>
|
</mat-accordion>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
.example-full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
@ -55,6 +55,10 @@ export class ServerService {
|
|||||||
return this.onReady(() => this.indexedDbService.get().delete(this.tablename, server.id));
|
return this.onReady(() => this.indexedDbService.get().delete(this.tablename, server.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getServerUrl(server: Server) {
|
||||||
|
return `http://${server.host}:${server.port}/`;
|
||||||
|
}
|
||||||
|
|
||||||
public getLocalServer(host: string, port: number) {
|
public getLocalServer(host: string, port: number) {
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
this.findAll().then((servers: Server[]) => {
|
this.findAll().then((servers: Server[]) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user