diff --git a/renderer.js b/renderer.js index 901d75ec..74dcf68e 100644 --- a/renderer.js +++ b/renderer.js @@ -1,3 +1,11 @@ // This file is required by the index.html file and will // be executed in the renderer process for that window. // All of the Node.js APIs are available in this process. + +let shell = require('electron').shell +document.addEventListener('click', function (event) { + if (event.target.tagName === 'A' && event.target.href.startsWith('http')) { + event.preventDefault() + shell.openExternal(event.target.href) + } +}) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 7310c969..f49a073d 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -34,6 +34,8 @@ import { EthernetSwitchesTemplateDetailsComponent } from './components/preferenc import { DynamipsPreferencesComponent } from './components/preferences/dynamips/dynamips-preferences/dynamips-preferences.component'; import { IosTemplatesComponent } from './components/preferences/dynamips/ios-templates/ios-templates.component'; import { InstalledSoftwareComponent } from './components/installed-software/installed-software.component'; +import { IosTemplateDetailsComponent } from './components/preferences/dynamips/ios-template-details/ios-template-details.component'; +import { AddIosTemplateComponent } from './components/preferences/dynamips/add-ios-template/add-ios-template.component'; const routes: Routes = [ { @@ -64,8 +66,8 @@ const routes: Routes = [ //{ path: 'server/:server_id/preferences/dynamips', component: DynamipsPreferencesComponent }, { path: 'server/:server_id/preferences/dynamips/templates', component: IosTemplatesComponent }, - { path: 'server/:server_id/preferences/dynamips/templates/addtemplate', component: IosTemplatesComponent }, - { path: 'server/:server_id/preferences/dynamips/templates/:template_id', component: IosTemplatesComponent }, + { path: 'server/:server_id/preferences/dynamips/templates/addtemplate', component: AddIosTemplateComponent }, + { path: 'server/:server_id/preferences/dynamips/templates/:template_id', component: IosTemplateDetailsComponent }, // { path: 'server/:server_id/preferences/qemu', component: QemuPreferencesComponent }, { path: 'server/:server_id/preferences/qemu/templates', component: QemuVmTemplatesComponent }, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3a51eea7..1bb18e30 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -130,6 +130,8 @@ import { SymbolsComponent } from './components/preferences/common/symbols/symbol import { InstalledSoftwareService } from './services/installed-software.service'; import { ExternalSoftwareDefinitionService } from './services/external-software-definition.service'; import { PlatformService } from './services/platform.service'; +import { IosTemplateDetailsComponent } from './components/preferences/dynamips/ios-template-details/ios-template-details.component'; +import { AddIosTemplateComponent } from './components/preferences/dynamips/add-ios-template/add-ios-template.component'; if (environment.production) { Raven.config('https://b2b1cfd9b043491eb6b566fd8acee358@sentry.io/842726', { @@ -210,6 +212,8 @@ if (environment.production) { EthernetSwitchesTemplateDetailsComponent, DynamipsPreferencesComponent, IosTemplatesComponent, + IosTemplateDetailsComponent, + AddIosTemplateComponent, SymbolsComponent ], imports: [ diff --git a/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.html b/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.html new file mode 100644 index 00000000..68cdcbc0 --- /dev/null +++ b/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.html @@ -0,0 +1,127 @@ +
+
+
+

New IOS router

+
+
+
+
+ + +
+ + + +
+
+ +
+ + + +
+ + + + {{platform}} + + + + + + + {{chassis}} + + + + + This is an EtherSwitch router + +
+ +
+ + + + + Check for minimum and maximum RAM requirement + +
+
+ +
+
+ + + {{option}} + + +
+
+
+
+ + + {{option}} + + +
+
+
+ +
+
+ + + {{option}} + + +
+
+
+ + + + +
+
+
+
+
+
diff --git a/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.scss b/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.scss new file mode 100644 index 00000000..9c2173c2 --- /dev/null +++ b/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.scss @@ -0,0 +1,3 @@ +.form-field { + width: 100%; +} diff --git a/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.spec.ts b/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.ts b/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.ts new file mode 100644 index 00000000..9a59ff97 --- /dev/null +++ b/src/app/components/preferences/dynamips/add-ios-template/add-ios-template.component.ts @@ -0,0 +1,330 @@ +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } 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 { IosTemplate } from '../../../../models/templates/ios-template'; +import { IosService } from '../../../../services/ios.service'; +import { v4 as uuid } from 'uuid'; +import { TemplateMocksService } from '../../../../services/template-mocks.service'; + + +@Component({ + selector: 'app-add-ios-template', + templateUrl: './add-ios-template.component.html', + styleUrls: ['./add-ios-template.component.scss'] +}) +export class AddIosTemplateComponent implements OnInit { + server: Server; + iosTemplate: IosTemplate; + isEtherSwitchRouter: boolean = false; + + iosImageForm: FormGroup; + iosNameForm: FormGroup; + iosMemoryForm: FormGroup; + + networkAdaptersForTemplate: string[] = []; + networkModulesForTemplate: string[] = []; + + platforms: string[] = ["c1700", "c2600", "c2691", "c3725", "c3745", "c3600", "c7200"]; + platformsWithEtherSwitchRouterOption = { + "c1700": false, + "c2600": true, + "c2691": true, + "c3725": true, + "c3745": true, + "c3600": true, + "c7200": false + }; + platformsWithChassis = { + "c1700": true, + "c2600": true, + "c2691": false, + "c3725": false, + "c3745": false, + "c3600": true, + "c7200": false + }; + chassis = { + "c1700": ["1720", "1721", "1750", "1751", "1760"], + "c2600": ["2610", "2611", "2620", "2621", "2610XM", "2611XM", "2620XM", "2621XM", "2650XM", "2651XM"], + "c3600": ["3620", "3640", "3660"] + }; + defaultRam = { + "c1700": 160, + "c2600": 160, + "c2691": 192, + "c3600": 192, + "c3725": 128, + "c3745": 256, + "c7200": 512 + }; + defaultNvram = { + "c1700": 128, + "c2600": 128, + "c2691": 256, + "c3600": 256, + "c3725": 256, + "c3745": 256, + "c7200": 512 + }; + ciscoUrl: string = "https://cfn.cloudapps.cisco.com/ITDIT/CFN/jsp/SearchBySoftware.jsp"; + + c1700_wics = ["WIC-1T", "WIC-2T", "WIC-1ENET"]; + c2600_wics = ["WIC-1T", "WIC-2T"]; + c3700_wics = ["WIC-1T", "WIC-2T"]; + + c2600_nms = [ + "NM-1FE-TX", + "NM-1E", + "NM-4E", + "NM-16ESW" + ]; + c3600_nms = [ + "NM-1FE-TX", + "NM-1E", + "NM-4E", + "NM-16ESW", + "NM-4T" + ]; + c3700_nms = [ + "NM-1FE-TX", + "NM-4T", + "NM-16ESW", + ]; + c7200_pas = [ + "PA-A1", + "PA-FE-TX", + "PA-2FE-TX", + "PA-GE", + "PA-4T+", + "PA-8T", + "PA-4E", + "PA-8E", + "PA-POS-OC3", + ]; + c7200_io = [ + "C7200-IO-FE", + "C7200-IO-2FE", + "C7200-IO-GE-E" + ]; + + networkAdapters = { + "1720": { + 0: ["C1700-MB-1FE"] + }, + "1721": { + 0: ["C1700-MB-1FE"] + }, + "1750": { + 0: ["C1700-MB-1FE"] + }, + "1751": { + 0: ["C1700-MB-1FE"], + 1: ["C1700-MB-WIC1"] + }, + "1760": { + 0: ["C1700-MB-1FE"], + 1: ["C1700-MB-WIC1"] + }, + "2610": { + 0: ["C2600-MB-1E"], + 1: this.c2600_nms + }, + "2611": { + 0: ["C2600-MB-2E"], + 1: this.c2600_nms + }, + "2620": { + 0: ["C2600-MB-1FE"], + 1: this.c2600_nms + }, + "2621": { + 0: ["C2600-MB-2FE"], + 1: this.c2600_nms + }, + "2610XM": { + 0: ["C2600-MB-1FE"], + 1: this.c2600_nms + }, + "2611XM": { + 0: ["C2600-MB-2FE"], + 1: this.c2600_nms + }, + "2620XM": { + 0: ["C2600-MB-1FE"], + 1: this.c2600_nms + }, + "2621XM": { + 0: ["C2600-MB-2FE"], + 1: this.c2600_nms + }, + "2650XM": { + 0: ["C2600-MB-1FE"], + 1: this.c2600_nms + }, + "2651XM": { + 0: ["C2600-MB-2FE"], + 1: this.c2600_nms + }, + "3620": { + 0: this.c3600_nms, + 1: this.c3600_nms + }, + "3640": { + 0: this.c3600_nms, + 1: this.c3600_nms, + 2: this.c3600_nms, + 3: this.c3600_nms + }, + "3660": { + 0: ["Leopard-2FE"], + 1: this.c3600_nms, + 2: this.c3600_nms, + 3: this.c3600_nms, + 4: this.c3600_nms, + 5: this.c3600_nms, + 6: this.c3600_nms, + 7: this.c3600_nms + } + }; + networkAdaptersForPlatform = { + "c2691": { + 0: ["GT96100-FE"], + 1: this.c3700_nms + }, + "c3725": { + 0: ["GT96100-FE"], + 1: this.c3700_nms, + 2: this.c3700_nms, + 3: this.c3700_nms + }, + "c3745": { + 0: ["GT96100-FE"], + 1: this.c3700_nms, + 2: this.c3700_nms, + 3: this.c3700_nms, + 4: this.c3700_nms, + 5: this.c3700_nms + }, + "c7200": { + 0: this.c7200_io, + 1: this.c7200_pas, + 2: this.c7200_pas, + 3: this.c7200_pas, + 4: this.c7200_pas, + 5: this.c7200_pas, + 6: this.c7200_pas, + 7: this.c7200_pas + } + }; + networkModules = { + "c1700": { + 0: this.c1700_wics, + 1: this.c1700_wics + }, + "c2600": { + 0: this.c2600_wics, + 1: this.c2600_wics, + 2: this.c2600_wics + }, + "c2691": { + 0: this.c3700_wics, + 1: this.c3700_wics, + 2: this.c3700_wics + }, + "c3725": { + 0: this.c3700_wics, + 1: this.c3700_wics, + 2: this.c3700_wics + }, + "c3745": { + 0: this.c3700_wics, + 1: this.c3700_wics, + 2: this.c3700_wics + } + }; + + constructor( + private route: ActivatedRoute, + private serverService: ServerService, + private iosService: IosService, + private toasterService: ToasterService, + private formBuilder: FormBuilder, + private router: Router, + private templateMocksService: TemplateMocksService + ) { + this.iosTemplate = new IosTemplate(); + + this.iosImageForm = this.formBuilder.group({ + imageName: new FormControl(null, [Validators.required]) + }); + + this.iosNameForm = this.formBuilder.group({ + templateName: new FormControl(null, [Validators.required]) + }); + + this.iosMemoryForm = this.formBuilder.group({ + memory: new FormControl(null, [Validators.required]) + }); + } + + ngOnInit(){ + const server_id = this.route.snapshot.paramMap.get("server_id"); + this.serverService.get(parseInt(server_id, 10)).then((server: Server) => { + this.server = server; + + this.templateMocksService.getIosTemplate().subscribe((iosTemplate: IosTemplate) => { + this.iosTemplate = iosTemplate; + }); + }); + } + + addTemplate() { + if (!this.iosImageForm.invalid) { + this.iosTemplate.template_id = uuid(); + + if (this.isEtherSwitchRouter) { + this.iosTemplate.symbol = ":/symbols/multilayer_switch.svg"; + this.iosTemplate.category = "switch"; + } + + if (this.networkAdaptersForTemplate.length>0) this.completeAdaptersData(); + if (this.networkModulesForTemplate.length>0) this.completeModulesData(); + + this.iosService.addTemplate(this.server, this.iosTemplate).subscribe((template: IosTemplate) => { + this.router.navigate(['/server', this.server.id, 'preferences', 'dynamips', 'templates']); + }); + } else { + this.toasterService.error(`Fill all required fields`); + } + } + + completeAdaptersData() { + if (this.networkAdaptersForTemplate[0]) this.iosTemplate.slot0 = this.networkAdaptersForTemplate[0]; + if (this.networkAdaptersForTemplate[1]) this.iosTemplate.slot1 = this.networkAdaptersForTemplate[1]; + if (this.networkAdaptersForTemplate[2]) this.iosTemplate.slot2 = this.networkAdaptersForTemplate[2]; + if (this.networkAdaptersForTemplate[3]) this.iosTemplate.slot3 = this.networkAdaptersForTemplate[3]; + if (this.networkAdaptersForTemplate[4]) this.iosTemplate.slot4 = this.networkAdaptersForTemplate[4]; + if (this.networkAdaptersForTemplate[5]) this.iosTemplate.slot5 = this.networkAdaptersForTemplate[5]; + if (this.networkAdaptersForTemplate[6]) this.iosTemplate.slot6 = this.networkAdaptersForTemplate[6]; + if (this.networkAdaptersForTemplate[7]) this.iosTemplate.slot7 = this.networkAdaptersForTemplate[7]; + } + + completeModulesData() { + if (this.networkModulesForTemplate[0]) this.iosTemplate.wic0 = this.networkModulesForTemplate[0]; + if (this.networkModulesForTemplate[1]) this.iosTemplate.wic1 = this.networkModulesForTemplate[1]; + if (this.networkModulesForTemplate[2]) this.iosTemplate.wic2 = this.networkModulesForTemplate[2]; + } + + onPlatformChosen() { + this.iosTemplate.chassis = ''; + this.networkAdaptersForTemplate = []; + this.networkModulesForTemplate = []; + } + + onChassisChosen() { + this.networkAdaptersForTemplate = []; + } +} diff --git a/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.html b/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.html new file mode 100644 index 00000000..89c3e728 --- /dev/null +++ b/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.html @@ -0,0 +1,141 @@ +
+
+
+

Dynamips IOS Router configuration

+
+
+
+ + + + + General settings + + + + + + + + + Platform - {{iosTemplate.platform}}

+ Chassis - {{iosTemplate.chassis}}

+ + + +

+ + + + {{category[0]}} + + + + + + + + + + + + + + + + {{type}} + + + + + Auto start console + +
+ + + + Memories and disks + + + + + + + + + + + + + + + + + + + Automatically delete NVRAM and disk files + + + + + + Slots + + + + + + + Advanced + + + + + + + + + + + + + + + + + + + + + + Enable mmap support +

+ + Enable sparse memory supoport + +
+ + + + Usage + + + + + + +
+
+
+
+
+
+
+

Symbol selection

+ +
+
+
+ +
+
diff --git a/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.scss b/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.scss new file mode 100644 index 00000000..c20e763d --- /dev/null +++ b/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.scss @@ -0,0 +1,22 @@ +.row { + width: 100%; + margin-left: 0px; +} + +.select { + width: 100%; +} + +.top-button { + height: 36px; + margin-top: 22px +} + +.shadowed { + display: none; + transition: 0.25s; +} + +.symbolSelectionButton { + width: 100%; +} diff --git a/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.spec.ts b/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.ts b/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.ts new file mode 100644 index 00000000..6fade9c7 --- /dev/null +++ b/src/app/components/preferences/dynamips/ios-template-details/ios-template-details.component.ts @@ -0,0 +1,63 @@ +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 { IosTemplate } from '../../../../models/templates/ios-template'; +import { IosService } from '../../../../services/ios.service'; + + +@Component({ + selector: 'app-ios-template-details', + templateUrl: './ios-template-details.component.html', + styleUrls: ['./ios-template-details.component.scss'] +}) +export class IosTemplateDetailsComponent implements OnInit { + server: Server; + iosTemplate: IosTemplate; + + isSymbolSelectionOpened: boolean = false; + + consoleTypes: string[] = ['telnet', 'none']; + categories = [["Default", "guest"], + ["Routers", "router"], + ["Switches", "switch"], + ["End devices", "end_device"], + ["Security devices", "security_device"]]; + isConfiguratorOpened: boolean = false; + + constructor( + private route: ActivatedRoute, + private serverService: ServerService, + private iosService: IosService, + 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.iosService.getTemplate(this.server, template_id).subscribe((iosTemplate: IosTemplate) => { + this.iosTemplate = iosTemplate; + }); + }); + } + + onSave() { + this.iosService.saveTemplate(this.server, this.iosTemplate).subscribe((iosTemplate: IosTemplate) => { + this.toasterService.success("Changes saved"); + }); + } + + chooseSymbol() { + this.isSymbolSelectionOpened = !this.isSymbolSelectionOpened; + } + + symbolChanged(chosenSymbol: string) { + this.iosTemplate.symbol = chosenSymbol; + } +} diff --git a/src/app/components/preferences/dynamips/ios-templates/ios-templates.component.html b/src/app/components/preferences/dynamips/ios-templates/ios-templates.component.html index 5c65a2b3..eaf08f17 100644 --- a/src/app/components/preferences/dynamips/ios-templates/ios-templates.component.html +++ b/src/app/components/preferences/dynamips/ios-templates/ios-templates.component.html @@ -2,7 +2,7 @@

IOS routers templates

- +
diff --git a/src/app/models/templates/ios-template.ts b/src/app/models/templates/ios-template.ts index 2c5d1e57..f73630ba 100644 --- a/src/app/models/templates/ios-template.ts +++ b/src/app/models/templates/ios-template.ts @@ -1,4 +1,4 @@ -export interface IosTemplate { +export class IosTemplate { auto_delete_disks: boolean; builtin: boolean; category: string; @@ -22,7 +22,14 @@ export interface IosTemplate { platform: string; private_config: string; ram: number; - slot0: string; + slot0?: string; + slot1?: string; + slot2?: string; + slot3?: string; + slot4?: string; + slot5?: string; + slot6?: string; + slot7?: string; sparsemem: boolean; startup_config: string; symbol: string; @@ -30,6 +37,7 @@ export interface IosTemplate { template_id: string; template_type: string; usage: string; - wic0: string; - wic1: string; + wic0?: string; + wic1?: string; + wic2?: string; } diff --git a/src/app/services/template-mocks.service.ts b/src/app/services/template-mocks.service.ts index dae0ee7d..fcad09a7 100644 --- a/src/app/services/template-mocks.service.ts +++ b/src/app/services/template-mocks.service.ts @@ -162,7 +162,7 @@ export class TemplateMocksService { auto_delete_disks: true, builtin: false, category: 'router', - chassis: '1720', + chassis: '', compute_id: 'local', console_auto_start: false, console_type: 'telnet', @@ -182,16 +182,13 @@ export class TemplateMocksService { platform: '', private_config: '', ram: 128, - slot0: '', sparsemem: true, startup_config: '', symbol: ':/symbols/router.svg', system_id: 'FTX0945W0MY', template_id: '', template_type: 'dynamips', - usage: '', - wic0: '', - wic1: '' + usage: '' } return of(template);