mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-04-24 21:09:40 +00:00
Merge pull request #508 from GNS3/winpcap-support
User should have possibility to start capture in WebUI (branch from node configurator to avoid conflicts) & console connect to all nodes
This commit is contained in:
commit
bb11e88f13
@ -236,6 +236,8 @@ import { TracengService } from './services/traceng.service';
|
|||||||
import { TracengTemplateDetailsComponent } from './components/preferences/traceng/traceng-template-details/traceng-template-details.component';
|
import { TracengTemplateDetailsComponent } from './components/preferences/traceng/traceng-template-details/traceng-template-details.component';
|
||||||
import { QemuImageCreatorComponent } from './components/project-map/node-editors/configurator/qemu/qemu-image-creator/qemu-image-creator.component';
|
import { QemuImageCreatorComponent } from './components/project-map/node-editors/configurator/qemu/qemu-image-creator/qemu-image-creator.component';
|
||||||
import { ChooseNameDialogComponent } from './components/projects/choose-name-dialog/choose-name-dialog.component';
|
import { ChooseNameDialogComponent } from './components/projects/choose-name-dialog/choose-name-dialog.component';
|
||||||
|
import { PacketCaptureService } from './services/packet-capture.service';
|
||||||
|
import { StartCaptureOnStartedLinkActionComponent } from './components/project-map/context-menu/actions/start-capture-on-started-link/start-capture-on-started-link.component';
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
|
Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', {
|
||||||
@ -398,7 +400,8 @@ if (environment.production) {
|
|||||||
TracengTemplatesComponent,
|
TracengTemplatesComponent,
|
||||||
TracengTemplateDetailsComponent,
|
TracengTemplateDetailsComponent,
|
||||||
QemuImageCreatorComponent,
|
QemuImageCreatorComponent,
|
||||||
ChooseNameDialogComponent
|
ChooseNameDialogComponent,
|
||||||
|
StartCaptureOnStartedLinkActionComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@ -478,7 +481,8 @@ if (environment.production) {
|
|||||||
MapSettingsService,
|
MapSettingsService,
|
||||||
InfoService,
|
InfoService,
|
||||||
ComputeService,
|
ComputeService,
|
||||||
TracengService
|
TracengService,
|
||||||
|
PacketCaptureService
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
AddServerDialogComponent,
|
AddServerDialogComponent,
|
||||||
|
@ -11,6 +11,8 @@ import { SettingsService } from '../../../../../services/settings.service';
|
|||||||
import { MockedSettingsService } from '../../../../../services/settings.service.spec';
|
import { MockedSettingsService } from '../../../../../services/settings.service.spec';
|
||||||
import { Node } from '../../../../../cartography/models/node';
|
import { Node } from '../../../../../cartography/models/node';
|
||||||
import { Server } from '../../../../../models/server';
|
import { Server } from '../../../../../models/server';
|
||||||
|
import { MockedNodeService } from '../../../project-map.component.spec';
|
||||||
|
import { NodeService } from '../../../../../services/node.service';
|
||||||
|
|
||||||
|
|
||||||
describe('ConsoleDeviceActionComponent', () => {
|
describe('ConsoleDeviceActionComponent', () => {
|
||||||
@ -20,7 +22,8 @@ describe('ConsoleDeviceActionComponent', () => {
|
|||||||
let server: Server;
|
let server: Server;
|
||||||
let mockedSettingsService: MockedSettingsService;
|
let mockedSettingsService: MockedSettingsService;
|
||||||
let mockedServerService: MockedServerService;
|
let mockedServerService: MockedServerService;
|
||||||
let mockedToaster: MockedToasterService
|
let mockedToaster: MockedToasterService;
|
||||||
|
let mockedNodeService: MockedNodeService = new MockedNodeService();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
electronService = {
|
electronService = {
|
||||||
@ -47,7 +50,8 @@ describe('ConsoleDeviceActionComponent', () => {
|
|||||||
{ provide: ElectronService, useValue: electronService },
|
{ provide: ElectronService, useValue: electronService },
|
||||||
{ provide: ServerService, useValue: mockedServerService },
|
{ provide: ServerService, useValue: mockedServerService },
|
||||||
{ provide: SettingsService, useValue: mockedSettingsService },
|
{ provide: SettingsService, useValue: mockedSettingsService },
|
||||||
{ provide: ToasterService, useValue: mockedToaster }
|
{ provide: ToasterService, useValue: mockedToaster },
|
||||||
|
{ provide: NodeService, useValue: mockedNodeService }
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
MatIconModule
|
MatIconModule
|
||||||
|
@ -5,6 +5,7 @@ import { ElectronService } from 'ngx-electron';
|
|||||||
import { ServerService } from '../../../../../services/server.service';
|
import { ServerService } from '../../../../../services/server.service';
|
||||||
import { SettingsService } from '../../../../../services/settings.service';
|
import { SettingsService } from '../../../../../services/settings.service';
|
||||||
import { ToasterService } from '../../../../../services/toaster.service';
|
import { ToasterService } from '../../../../../services/toaster.service';
|
||||||
|
import { NodeService } from '../../../../../services/node.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-console-device-action',
|
selector: 'app-console-device-action',
|
||||||
@ -18,19 +19,14 @@ export class ConsoleDeviceActionComponent implements OnInit {
|
|||||||
private electronService: ElectronService,
|
private electronService: ElectronService,
|
||||||
private serverService: ServerService,
|
private serverService: ServerService,
|
||||||
private settingsService: SettingsService,
|
private settingsService: SettingsService,
|
||||||
private toasterService: ToasterService
|
private toasterService: ToasterService,
|
||||||
|
private nodeService: NodeService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {}
|
||||||
}
|
|
||||||
|
|
||||||
async console() {
|
async console() {
|
||||||
let consoleCommand = this.settingsService.get<string>('console_command');
|
let consoleCommand = this.settingsService.get<string>('console_command') ? this.settingsService.get<string>('console_command') : this.nodeService.getDefaultCommand();
|
||||||
|
|
||||||
if(consoleCommand === undefined) {
|
|
||||||
consoleCommand = `putty.exe -telnet \%h \%p -wt \"\%d\" -gns3 5 -skin 4`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const startedNodes = this.nodes.filter(node => node.status === 'started');
|
const startedNodes = this.nodes.filter(node => node.status === 'started');
|
||||||
|
|
||||||
if(startedNodes.length === 0) {
|
if(startedNodes.length === 0) {
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
<button mat-menu-item *ngIf="link.capturing" (click)="startCapture()">
|
||||||
|
<mat-icon>search</mat-icon>
|
||||||
|
<span>Start Wireshark</span>
|
||||||
|
</button>
|
@ -0,0 +1,24 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { Server } from '../../../../../models/server';
|
||||||
|
import { Link } from '../../../../../models/link';
|
||||||
|
import { Project } from '../../../../../models/project';
|
||||||
|
import { PacketCaptureService } from '../../../../../services/packet-capture.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-start-capture-on-started-link-action',
|
||||||
|
templateUrl: './start-capture-on-started-link.component.html'
|
||||||
|
})
|
||||||
|
export class StartCaptureOnStartedLinkActionComponent {
|
||||||
|
@Input() server: Server;
|
||||||
|
@Input() project: Project;
|
||||||
|
@Input() link: Link;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private packetCaptureService: PacketCaptureService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
startCapture() {
|
||||||
|
var splittedFileName = this.link.capture_file_name.split('.');
|
||||||
|
this.packetCaptureService.startCapture(this.server, this.project, this.link, splittedFileName[0]);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ import { Server } from '../../../../../models/server';
|
|||||||
import { Link } from '../../../../../models/link';
|
import { Link } from '../../../../../models/link';
|
||||||
import { MatDialog } from '@angular/material';
|
import { MatDialog } from '@angular/material';
|
||||||
import { StartCaptureDialogComponent } from '../../../packet-capturing/start-capture/start-capture.component';
|
import { StartCaptureDialogComponent } from '../../../packet-capturing/start-capture/start-capture.component';
|
||||||
|
import { Project } from '../../../../../models/project';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-start-capture-action',
|
selector: 'app-start-capture-action',
|
||||||
@ -10,6 +11,7 @@ import { StartCaptureDialogComponent } from '../../../packet-capturing/start-cap
|
|||||||
})
|
})
|
||||||
export class StartCaptureActionComponent {
|
export class StartCaptureActionComponent {
|
||||||
@Input() server: Server;
|
@Input() server: Server;
|
||||||
|
@Input() project: Project;
|
||||||
@Input() link: Link;
|
@Input() link: Link;
|
||||||
|
|
||||||
constructor(private dialog: MatDialog) {}
|
constructor(private dialog: MatDialog) {}
|
||||||
@ -21,6 +23,7 @@ export class StartCaptureActionComponent {
|
|||||||
});
|
});
|
||||||
let instance = dialogRef.componentInstance;
|
let instance = dialogRef.componentInstance;
|
||||||
instance.server = this.server;
|
instance.server = this.server;
|
||||||
|
instance.project = this.project;
|
||||||
instance.link = this.link;
|
instance.link = this.link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,17 +86,25 @@
|
|||||||
[drawings]="drawings"
|
[drawings]="drawings"
|
||||||
></app-bring-to-front-action>
|
></app-bring-to-front-action>
|
||||||
<app-start-capture-action
|
<app-start-capture-action
|
||||||
*ngIf="!projectService.isReadOnly(project) && isBundledServer
|
*ngIf="!projectService.isReadOnly(project)
|
||||||
&& drawings.length===0 && nodes.length===0 && links.length===1"
|
&& drawings.length===0 && nodes.length===0 && links.length===1"
|
||||||
[server]="server"
|
[server]="server"
|
||||||
|
[project]="project"
|
||||||
[link]="links[0]"
|
[link]="links[0]"
|
||||||
></app-start-capture-action>
|
></app-start-capture-action>
|
||||||
<app-stop-capture-action
|
<app-stop-capture-action
|
||||||
*ngIf="!projectService.isReadOnly(project) && isBundledServer
|
*ngIf="!projectService.isReadOnly(project)
|
||||||
&& drawings.length===0 && nodes.length===0 && links.length===1 && linkNodes.length === 0"
|
&& drawings.length===0 && nodes.length===0 && links.length===1 && linkNodes.length === 0"
|
||||||
[server]="server"
|
[server]="server"
|
||||||
[link]="links[0]"
|
[link]="links[0]"
|
||||||
></app-stop-capture-action>
|
></app-stop-capture-action>
|
||||||
|
<app-start-capture-on-started-link-action
|
||||||
|
*ngIf="!projectService.isReadOnly(project)
|
||||||
|
&& drawings.length===0 && nodes.length===0 && links.length===1 && linkNodes.length === 0"
|
||||||
|
[server]="server"
|
||||||
|
[project]="project"
|
||||||
|
[link]="links[0]"
|
||||||
|
></app-start-capture-on-started-link-action>
|
||||||
<app-packet-filters-action
|
<app-packet-filters-action
|
||||||
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1 && linkNodes.length === 0"
|
*ngIf="!projectService.isReadOnly(project) && drawings.length===0 && nodes.length===0 && links.length===1 && linkNodes.length === 0"
|
||||||
[server]="server"
|
[server]="server"
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
<button
|
||||||
|
matTooltip="Console connect to all nodes"
|
||||||
|
mat-icon-button
|
||||||
|
(click)="startConsoleForAllNodes()"
|
||||||
|
class="menu-button"
|
||||||
|
>
|
||||||
|
<mat-icon>web_asset</mat-icon>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
matTooltip="Start/Resume all nodes"
|
matTooltip="Start/Resume all nodes"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { NodesMenuComponent } from './nodes-menu.component';
|
import { NodesMenuComponent } from './nodes-menu.component';
|
||||||
import { MockedToasterService } from '../../../services/toaster.service.spec';
|
import { MockedToasterService } from '../../../services/toaster.service.spec';
|
||||||
import { MockedNodeService } from '../project-map.component.spec';
|
import { MockedNodeService, MockedNodesDataSource } from '../project-map.component.spec';
|
||||||
import { MatButtonModule, MatIconModule } from '@angular/material';
|
import { MatButtonModule, MatIconModule } from '@angular/material';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
@ -9,19 +9,28 @@ import { NO_ERRORS_SCHEMA } from '@angular/core';
|
|||||||
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 { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
|
import { NodesDataSource } from '../../../cartography/datasources/nodes-datasource';
|
||||||
|
import { ServerService } from '../../../services/server.service';
|
||||||
|
import { SettingsService } from '../../../services/settings.service';
|
||||||
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
|
||||||
describe('NodesMenuComponent', () => {
|
describe('NodesMenuComponent', () => {
|
||||||
let component: NodesMenuComponent;
|
let component: NodesMenuComponent;
|
||||||
let fixture: ComponentFixture<NodesMenuComponent>;
|
let fixture: ComponentFixture<NodesMenuComponent>;
|
||||||
let mockedToasterService: MockedToasterService = new MockedToasterService();
|
let mockedToasterService: MockedToasterService = new MockedToasterService();
|
||||||
let mockedNodeService: MockedNodeService = new MockedNodeService();
|
let mockedNodeService: MockedNodeService = new MockedNodeService();
|
||||||
|
let mockedNodesDataSource: MockedNodesDataSource = new MockedNodesDataSource();
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [MatButtonModule, MatIconModule, CommonModule, NoopAnimationsModule],
|
imports: [MatButtonModule, MatIconModule, CommonModule, NoopAnimationsModule],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: NodeService, useValue: mockedNodeService },
|
{ provide: NodeService, useValue: mockedNodeService },
|
||||||
{ provide: ToasterService, useValue: mockedToasterService }
|
{ provide: ToasterService, useValue: mockedToasterService },
|
||||||
|
{ provide: NodesDataSource, useValue: mockedNodesDataSource },
|
||||||
|
{ provide: ServerService },
|
||||||
|
{ provide: SettingsService },
|
||||||
|
{ provide: ElectronService }
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
NodesMenuComponent,
|
NodesMenuComponent,
|
||||||
|
@ -3,6 +3,10 @@ import { Project } from '../../../models/project';
|
|||||||
import { Server } from '../../../models/server';
|
import { Server } from '../../../models/server';
|
||||||
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 { NodesDataSource } from '../../../cartography/datasources/nodes-datasource';
|
||||||
|
import { ElectronService } from 'ngx-electron';
|
||||||
|
import { SettingsService } from '../../../services/settings.service';
|
||||||
|
import { ServerService } from '../../../services/server.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-nodes-menu',
|
selector: 'app-nodes-menu',
|
||||||
@ -15,9 +19,36 @@ export class NodesMenuComponent {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private nodeService: NodeService,
|
private nodeService: NodeService,
|
||||||
private toasterService: ToasterService
|
private nodesDataSource: NodesDataSource,
|
||||||
|
private toasterService: ToasterService,
|
||||||
|
private serverService: ServerService,
|
||||||
|
private settingsService: SettingsService,
|
||||||
|
private electronService: ElectronService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async startConsoleForAllNodes() {
|
||||||
|
if (this.electronService.isElectronApp) {
|
||||||
|
let consoleCommand = this.settingsService.get<string>('console_command') ? this.settingsService.get<string>('console_command') : this.nodeService.getDefaultCommand();
|
||||||
|
|
||||||
|
let nodes = this.nodesDataSource.getItems();
|
||||||
|
for(var node of nodes) {
|
||||||
|
const request = {
|
||||||
|
command: consoleCommand,
|
||||||
|
type: node.console_type,
|
||||||
|
host: node.console_host,
|
||||||
|
port: node.console,
|
||||||
|
name: node.name,
|
||||||
|
project_id: node.project_id,
|
||||||
|
node_id: node.node_id,
|
||||||
|
server_url: this.serverService.getServerUrl(this.server)
|
||||||
|
};
|
||||||
|
await this.electronService.remote.require('./console-executor.js').openConsole(request);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.toasterService.error("Starting all nodes available only in Electron app.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
startNodes() {
|
startNodes() {
|
||||||
this.nodeService.startAll(this.server, this.project).subscribe(() => {
|
this.nodeService.startAll(this.server, this.project).subscribe(() => {
|
||||||
this.toasterService.success('All nodes successfully started');
|
this.toasterService.success('All nodes successfully started');
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
formControlName="fileName"
|
formControlName="fileName"
|
||||||
matInput type="text">
|
matInput type="text">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- <mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="startProgram">
|
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="startProgram">
|
||||||
Start the capture visualization program
|
Start the capture visualization program
|
||||||
</mat-checkbox> -->
|
</mat-checkbox>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import { MockedLinkService, MockedNodesDataSource } from '../../project-map.comp
|
|||||||
import { Link } from '../../../../models/link';
|
import { Link } from '../../../../models/link';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { NodesDataSource } from '../../../../cartography/datasources/nodes-datasource';
|
import { NodesDataSource } from '../../../../cartography/datasources/nodes-datasource';
|
||||||
|
import { PacketCaptureService } from '../../../../services/packet-capture.service';
|
||||||
|
|
||||||
describe('StartCaptureDialogComponent', () => {
|
describe('StartCaptureDialogComponent', () => {
|
||||||
let component: StartCaptureDialogComponent;
|
let component: StartCaptureDialogComponent;
|
||||||
@ -32,7 +33,8 @@ describe('StartCaptureDialogComponent', () => {
|
|||||||
{ provide: MAT_DIALOG_DATA, useValue: [] },
|
{ provide: MAT_DIALOG_DATA, useValue: [] },
|
||||||
{ provide: ToasterService, useValue: mockedToasterService },
|
{ provide: ToasterService, useValue: mockedToasterService },
|
||||||
{ provide: LinkService, useValue: mockedLinkService },
|
{ provide: LinkService, useValue: mockedLinkService },
|
||||||
{ provide: NodesDataSource, useValue: mockedNodesDataSource }
|
{ provide: NodesDataSource, useValue: mockedNodesDataSource },
|
||||||
|
{ provide: PacketCaptureService }
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
StartCaptureDialogComponent
|
StartCaptureDialogComponent
|
||||||
|
@ -9,6 +9,8 @@ import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms'
|
|||||||
import { ToasterService } from '../../../../services/toaster.service';
|
import { ToasterService } from '../../../../services/toaster.service';
|
||||||
import { LinkNode } from '../../../../models/link-node';
|
import { LinkNode } from '../../../../models/link-node';
|
||||||
import { NodesDataSource } from '../../../../cartography/datasources/nodes-datasource';
|
import { NodesDataSource } from '../../../../cartography/datasources/nodes-datasource';
|
||||||
|
import { PacketCaptureService } from '../../../../services/packet-capture.service';
|
||||||
|
import { Project } from '../../../../models/project';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-start-capture',
|
selector: 'app-start-capture',
|
||||||
@ -17,6 +19,7 @@ import { NodesDataSource } from '../../../../cartography/datasources/nodes-datas
|
|||||||
})
|
})
|
||||||
export class StartCaptureDialogComponent implements OnInit {
|
export class StartCaptureDialogComponent implements OnInit {
|
||||||
server: Server;
|
server: Server;
|
||||||
|
project: Project;
|
||||||
link: Link;
|
link: Link;
|
||||||
linkTypes = [];
|
linkTypes = [];
|
||||||
inputForm: FormGroup;
|
inputForm: FormGroup;
|
||||||
@ -27,7 +30,8 @@ export class StartCaptureDialogComponent implements OnInit {
|
|||||||
private linkService: LinkService,
|
private linkService: LinkService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private toasterService: ToasterService,
|
private toasterService: ToasterService,
|
||||||
private nodesDataSource: NodesDataSource
|
private nodesDataSource: NodesDataSource,
|
||||||
|
private packetCaptureService: PacketCaptureService
|
||||||
) {
|
) {
|
||||||
this.inputForm = this.formBuilder.group({
|
this.inputForm = this.formBuilder.group({
|
||||||
linkType: new FormControl('', Validators.required),
|
linkType: new FormControl('', Validators.required),
|
||||||
@ -73,6 +77,10 @@ export class StartCaptureDialogComponent implements OnInit {
|
|||||||
data_link_type: this.inputForm.get('linkType').value
|
data_link_type: this.inputForm.get('linkType').value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.startProgram) {
|
||||||
|
this.packetCaptureService.startCapture(this.server, this.project, this.link, captureSettings.capture_file_name);
|
||||||
|
}
|
||||||
|
|
||||||
this.linkService.startCaptureOnLink(this.server, this.link, captureSettings).subscribe(() => {
|
this.linkService.startCaptureOnLink(this.server, this.link, captureSettings).subscribe(() => {
|
||||||
this.dialogRef.close();
|
this.dialogRef.close();
|
||||||
});
|
});
|
||||||
|
@ -80,7 +80,7 @@ g.node:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.extended {
|
.extended {
|
||||||
width: 770px !important;
|
width: 830px !important;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,10 @@ export class MockedNodeService {
|
|||||||
public node = { label: {} } as Node;
|
public node = { label: {} } as Node;
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
getDefaultCommand(): string {
|
||||||
|
return `putty.exe -telnet \%h \%p -wt \"\%d\" -gns3 5 -skin 4`;
|
||||||
|
}
|
||||||
|
|
||||||
updateLabel(): Observable<Node> {
|
updateLabel(): Observable<Node> {
|
||||||
return of(this.node);
|
return of(this.node);
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,14 @@
|
|||||||
<div class="summaryFilters">
|
<div class="summaryFilters">
|
||||||
Filter by status <br/>
|
Filter by status <br/>
|
||||||
<div class="filterBox">
|
<div class="filterBox">
|
||||||
<mat-checkbox (change)="applyStatusFilter($event.checked, 'started')">Started</mat-checkbox>
|
<mat-checkbox (change)="applyStatusFilter($event.checked, 'started')">started</mat-checkbox>
|
||||||
<mat-checkbox (change)="applyStatusFilter($event.checked, 'suspended')">Suspended</mat-checkbox>
|
<mat-checkbox (change)="applyStatusFilter($event.checked, 'suspended')">suspended</mat-checkbox>
|
||||||
<mat-checkbox (change)="applyStatusFilter($event.checked, 'stopped')">Stopped</mat-checkbox>
|
<mat-checkbox (change)="applyStatusFilter($event.checked, 'stopped')">stopped</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
Show devices with <br/>
|
||||||
|
<div class="filterBox">
|
||||||
|
<mat-checkbox (change)="applyCaptureFilter($event.checked, 'capture')">active capture(s)</mat-checkbox>
|
||||||
|
<mat-checkbox (change)="applyCaptureFilter($event.checked, 'packet')">active packet filters</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="summarySorting">
|
<div class="summarySorting">
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
.summaryContent {
|
.summaryContent {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
max-height: 230px;
|
max-height: 180px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
scrollbar-color: darkgrey #263238;
|
scrollbar-color: darkgrey #263238;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
|
@ -6,13 +6,14 @@ import { MatTableModule, MatTooltipModule, MatIconModule, MatSortModule, MatDial
|
|||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { of } from 'rxjs';
|
import { of } from 'rxjs';
|
||||||
import { MockedNodesDataSource } from '../project-map/project-map.component.spec';
|
import { MockedNodesDataSource, MockedLinksDataSource } from '../project-map/project-map.component.spec';
|
||||||
import { NodesDataSource } from '../../cartography/datasources/nodes-datasource';
|
import { NodesDataSource } from '../../cartography/datasources/nodes-datasource';
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { Project } from '../../models/project';
|
import { Project } from '../../models/project';
|
||||||
import { Node } from '../../cartography/models/node';
|
import { Node } from '../../cartography/models/node';
|
||||||
import { Server } from '../../models/server';
|
import { Server } from '../../models/server';
|
||||||
import { ComputeService } from '../../services/compute.service';
|
import { ComputeService } from '../../services/compute.service';
|
||||||
|
import { LinksDataSource } from '../../cartography/datasources/links-datasource';
|
||||||
|
|
||||||
export class MockedComputeService {
|
export class MockedComputeService {
|
||||||
getComputes(server: Server) {
|
getComputes(server: Server) {
|
||||||
@ -26,6 +27,7 @@ describe('TopologySummaryComponent', () => {
|
|||||||
let mockedProjectService: MockedProjectService = new MockedProjectService();
|
let mockedProjectService: MockedProjectService = new MockedProjectService();
|
||||||
let mockedNodesDataSource: MockedNodesDataSource = new MockedNodesDataSource();
|
let mockedNodesDataSource: MockedNodesDataSource = new MockedNodesDataSource();
|
||||||
let mockedComputeService: MockedComputeService = new MockedComputeService();
|
let mockedComputeService: MockedComputeService = new MockedComputeService();
|
||||||
|
let mockedLinksDataSource: MockedLinksDataSource = new MockedLinksDataSource();
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@ -41,7 +43,8 @@ describe('TopologySummaryComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: ProjectService, useValue: mockedProjectService },
|
{ provide: ProjectService, useValue: mockedProjectService },
|
||||||
{ provide: NodesDataSource, useValue: mockedNodesDataSource },
|
{ provide: NodesDataSource, useValue: mockedNodesDataSource },
|
||||||
{ provide: ComputeService, useValue: mockedComputeService}
|
{ provide: ComputeService, useValue: mockedComputeService},
|
||||||
|
{ provide: LinksDataSource, useValue: mockedLinksDataSource }
|
||||||
],
|
],
|
||||||
declarations: [TopologySummaryComponent],
|
declarations: [TopologySummaryComponent],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@ -8,6 +8,7 @@ import { ProjectService } from '../../services/project.service';
|
|||||||
import { ProjectStatistics } from '../../models/project-statistics';
|
import { ProjectStatistics } from '../../models/project-statistics';
|
||||||
import { Compute } from '../../models/compute';
|
import { Compute } from '../../models/compute';
|
||||||
import { ComputeService } from '../../services/compute.service';
|
import { ComputeService } from '../../services/compute.service';
|
||||||
|
import { LinksDataSource } from '../../cartography/datasources/links-datasource';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -29,13 +30,16 @@ export class TopologySummaryComponent implements OnInit, OnDestroy {
|
|||||||
startedStatusFilterEnabled: boolean = false;
|
startedStatusFilterEnabled: boolean = false;
|
||||||
suspendedStatusFilterEnabled: boolean = false;
|
suspendedStatusFilterEnabled: boolean = false;
|
||||||
stoppedStatusFilterEnabled: boolean = false;
|
stoppedStatusFilterEnabled: boolean = false;
|
||||||
|
captureFilterEnabled: boolean = false;
|
||||||
|
packetFilterEnabled: boolean = false;
|
||||||
computes: Compute[] = [];
|
computes: Compute[] = [];
|
||||||
isTopologyVisible: boolean = true;
|
isTopologyVisible: boolean = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private nodesDataSource: NodesDataSource,
|
private nodesDataSource: NodesDataSource,
|
||||||
private projectService: ProjectService,
|
private projectService: ProjectService,
|
||||||
private computeService: ComputeService
|
private computeService: ComputeService,
|
||||||
|
private linksDataSource: LinksDataSource
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -97,6 +101,15 @@ export class TopologySummaryComponent implements OnInit, OnDestroy {
|
|||||||
this.applyFilters();
|
this.applyFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyCaptureFilter(value: boolean, filter: string) {
|
||||||
|
if (filter === 'capture') {
|
||||||
|
this.captureFilterEnabled = value;
|
||||||
|
} else if (filter === 'packet') {
|
||||||
|
this.packetFilterEnabled = value;
|
||||||
|
}
|
||||||
|
this.applyFilters();
|
||||||
|
}
|
||||||
|
|
||||||
applyFilters() {
|
applyFilters() {
|
||||||
let nodes: Node[] = [];
|
let nodes: Node[] = [];
|
||||||
|
|
||||||
@ -116,6 +129,14 @@ export class TopologySummaryComponent implements OnInit, OnDestroy {
|
|||||||
nodes = nodes.concat(this.nodes);
|
nodes = nodes.concat(this.nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.captureFilterEnabled) {
|
||||||
|
nodes = this.checkCapturing(nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.packetFilterEnabled) {
|
||||||
|
nodes = this.checkPacketFilters(nodes);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.sortingOrder === 'asc') {
|
if (this.sortingOrder === 'asc') {
|
||||||
this.filteredNodes = nodes.sort(this.compareAsc);
|
this.filteredNodes = nodes.sort(this.compareAsc);
|
||||||
} else {
|
} else {
|
||||||
@ -123,6 +144,48 @@ export class TopologySummaryComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkCapturing(nodes: Node[]): Node[] {
|
||||||
|
let links = this.linksDataSource.getItems();
|
||||||
|
let nodesWithCapturing: string[] = [];
|
||||||
|
|
||||||
|
links.forEach(link => {
|
||||||
|
if (link.capturing) {
|
||||||
|
link.nodes.forEach(node => {
|
||||||
|
nodesWithCapturing.push(node.node_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let filteredNodes: Node[] = [];
|
||||||
|
nodes.forEach(node => {
|
||||||
|
if (nodesWithCapturing.includes(node.node_id)) {
|
||||||
|
filteredNodes.push(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filteredNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPacketFilters(nodes: Node[]): Node[] {
|
||||||
|
let links = this.linksDataSource.getItems();
|
||||||
|
let nodesWithPacketFilters: string[] = [];
|
||||||
|
|
||||||
|
links.forEach(link => {
|
||||||
|
if (link.filters.bpf || link.filters.corrupt || link.filters.corrupt || link.filters.packet_loss || link.filters.frequency_drop) {
|
||||||
|
link.nodes.forEach(node => {
|
||||||
|
nodesWithPacketFilters.push(node.node_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let filteredNodes: Node[] = [];
|
||||||
|
nodes.forEach(node => {
|
||||||
|
if (nodesWithPacketFilters.includes(node.node_id)) {
|
||||||
|
filteredNodes.push(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filteredNodes;
|
||||||
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.closeTopologySummary.emit(false);
|
this.closeTopologySummary.emit(false);
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,10 @@ export class NodeService {
|
|||||||
return this.httpServer.get(server, `/projects/${node.project_id}/nodes/${node.node_id}`)
|
return this.httpServer.get(server, `/projects/${node.project_id}/nodes/${node.node_id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDefaultCommand(): string {
|
||||||
|
return `putty.exe -telnet \%h \%p -wt \"\%d\" -gns3 5 -skin 4`;
|
||||||
|
}
|
||||||
|
|
||||||
getConfiguration(server: Server, node: Node) {
|
getConfiguration(server: Server, node: Node) {
|
||||||
let urlPath: string = `/projects/${node.project_id}/nodes/${node.node_id}`
|
let urlPath: string = `/projects/${node.project_id}/nodes/${node.node_id}`
|
||||||
|
|
||||||
|
13
src/app/services/packet-capture.service.ts
Normal file
13
src/app/services/packet-capture.service.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Server } from '../models/server';
|
||||||
|
import { Project } from '../models/project';
|
||||||
|
import { Link } from '../models/link';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PacketCaptureService {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
startCapture(server: Server, project: Project, link: Link, name: string) {
|
||||||
|
location.assign(`gns3+pcap://${server.host}:${server.port}?project_id=${project.project_id}&link_id=${link.link_id}&name=${name}`);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user