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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{platform}}
+
+
+
+
+
+
+ {{chassis}}
+
+
+
+
+ This is an EtherSwitch router
+
+
+
+
+
+
+
+
+
+
+ {{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 @@
+
+
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 @@
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);