diff --git a/docs/file_format.rst b/docs/file_format.rst index d0a01ef4..d25b51ef 100644 --- a/docs/file_format.rst +++ b/docs/file_format.rst @@ -23,6 +23,7 @@ A minimal version: The revision is the version of file format: +* 8: GNS3 2.1 * 7: GNS3 2.0 * 6: GNS3 2.0 < beta 3 * 5: GNS3 2.0 < alpha 4 diff --git a/gns3server/compute/dynamips/__init__.py b/gns3server/compute/dynamips/__init__.py index 4ad0472f..6d6bafda 100644 --- a/gns3server/compute/dynamips/__init__.py +++ b/gns3server/compute/dynamips/__init__.py @@ -515,25 +515,12 @@ class Dynamips(BaseManager): default_startup_config_path = os.path.join(module_workdir, vm.id, "configs", "i{}_startup-config.cfg".format(vm.dynamips_id)) default_private_config_path = os.path.join(module_workdir, vm.id, "configs", "i{}_private-config.cfg".format(vm.dynamips_id)) - startup_config_path = settings.get("startup_config") startup_config_content = settings.get("startup_config_content") - if startup_config_path: - yield from vm.set_configs(startup_config_path) - elif startup_config_content: - startup_config_path = self._create_config(vm, default_startup_config_path, startup_config_content) - yield from vm.set_configs(startup_config_path) - elif os.path.isfile(default_startup_config_path) and os.path.getsize(default_startup_config_path) == 0: - # An empty startup-config may crash Dynamips - startup_config_path = self._create_config(vm, default_startup_config_path, "!\n") - yield from vm.set_configs(startup_config_path) - - private_config_path = settings.get("private_config") + if startup_config_content: + self._create_config(vm, default_startup_config_path, startup_config_content) private_config_content = settings.get("private_config_content") - if private_config_path: - yield from vm.set_configs(vm.startup_config, private_config_path) - elif private_config_content: - private_config_path = self._create_config(vm, default_private_config_path, private_config_content) - yield from vm.set_configs(vm.startup_config, private_config_path) + if private_config_content: + self._create_config(vm, default_private_config_path, private_config_content) def _create_config(self, vm, path, content=None): """ @@ -553,6 +540,11 @@ class Dynamips(BaseManager): except OSError as e: raise DynamipsError("Could not create Dynamips configs directory: {}".format(e)) + if content is None or len(content) == 0: + content = "!\n" + if os.path.exists(path): + return + try: with open(path, "wb") as f: if content: diff --git a/gns3server/compute/dynamips/nodes/router.py b/gns3server/compute/dynamips/nodes/router.py index e43b827f..33c01655 100644 --- a/gns3server/compute/dynamips/nodes/router.py +++ b/gns3server/compute/dynamips/nodes/router.py @@ -78,8 +78,6 @@ class Router(BaseNode): self._dynamips_id = dynamips_id self._platform = platform self._image = "" - self._startup_config = "" - self._private_config = "" self._ram = 128 # Megabytes self._nvram = 128 # Kilobytes self._mmap = True @@ -102,8 +100,6 @@ class Router(BaseNode): self._slots = [] self._ghost_flag = ghost_flag self._memory_watcher = None - self._startup_config_content = "" - self._private_config_content = "" if not ghost_flag: if not dynamips_id: @@ -152,8 +148,6 @@ class Router(BaseNode): "platform": self._platform, "image": self._image, "image_md5sum": md5sum(self._image), - "startup_config": self._startup_config, - "private_config": self._private_config, "ram": self._ram, "nvram": self._nvram, "mmap": self._mmap, @@ -171,9 +165,7 @@ class Router(BaseNode): "console_type": "telnet", "aux": self.aux, "mac_addr": self._mac_addr, - "system_id": self._system_id, - "startup_config_content": self._startup_config_content, - "private_config_content": self._private_config_content} + "system_id": self._system_id} # return the relative path if the IOS image is in the images_path directory router_info["image"] = self.manager.get_relative_image_path(self._image) @@ -289,6 +281,16 @@ class Router(BaseNode): if not self._ghost_flag: self.check_available_ram(self.ram) + startup_config_path = os.path.join("configs", "i{}_startup-config.cfg".format(self._dynamips_id)) + private_config_path = os.path.join("configs", "i{}_private-config.cfg".format(self._dynamips_id)) + + if not os.path.exists(private_config_path) or not os.path.getsize(private_config_path): + # an empty private-config can prevent a router to boot. + private_config_path = '' + yield from self._hypervisor.send('vm set_config "{name}" "{startup}" "{private}"'.format( + name=self._name, + startup=startup_config_path, + private=private_config_path)) yield from self._hypervisor.send('vm start "{name}"'.format(name=self._name)) self.status = "started" log.info('router "{name}" [{id}] has been started'.format(name=self._name, id=self._id)) @@ -1458,26 +1460,6 @@ class Router(BaseNode): return self._slots - @property - def startup_config(self): - """ - Returns the startup-config for this router. - - :returns: path to startup-config file - """ - - return self._startup_config - - @property - def private_config(self): - """ - Returns the private-config for this router. - - :returns: path to private-config file - """ - - return self._private_config - @asyncio.coroutine def set_name(self, new_name): """ @@ -1486,89 +1468,34 @@ class Router(BaseNode): :param new_name: new name string """ - if self._startup_config: - # change the hostname in the startup-config - startup_config_path = os.path.join(self._working_directory, "configs", "i{}_startup-config.cfg".format(self._dynamips_id)) - if os.path.isfile(startup_config_path): - try: - with open(startup_config_path, "r+", encoding="utf-8", errors="replace") as f: - old_config = f.read() - new_config = old_config.replace(self.name, new_name) - f.seek(0) - self._startup_config_content = new_config - f.write(new_config) - except OSError as e: - raise DynamipsError("Could not amend the configuration {}: {}".format(startup_config_path, e)) + # change the hostname in the startup-config + startup_config_path = os.path.join(self._working_directory, "configs", "i{}_startup-config.cfg".format(self._dynamips_id)) + if os.path.isfile(startup_config_path): + try: + with open(startup_config_path, "r+", encoding="utf-8", errors="replace") as f: + old_config = f.read() + new_config = old_config.replace(self.name, new_name) + f.seek(0) + f.write(new_config) + except OSError as e: + raise DynamipsError("Could not amend the configuration {}: {}".format(startup_config_path, e)) - if self._private_config: - # change the hostname in the private-config - private_config_path = os.path.join(self._working_directory, "configs", "i{}_private-config.cfg".format(self._dynamips_id)) - if os.path.isfile(private_config_path): - try: - with open(private_config_path, "r+", encoding="utf-8", errors="replace") as f: - old_config = f.read() - new_config = old_config.replace(self.name, new_name) - f.seek(0) - self._private_config_content = new_config - f.write(new_config) - except OSError as e: - raise DynamipsError("Could not amend the configuration {}: {}".format(private_config_path, e)) + # change the hostname in the private-config + private_config_path = os.path.join(self._working_directory, "configs", "i{}_private-config.cfg".format(self._dynamips_id)) + if os.path.isfile(private_config_path): + try: + with open(private_config_path, "r+", encoding="utf-8", errors="replace") as f: + old_config = f.read() + new_config = old_config.replace(self.name, new_name) + f.seek(0) + f.write(new_config) + except OSError as e: + raise DynamipsError("Could not amend the configuration {}: {}".format(private_config_path, e)) yield from self._hypervisor.send('vm rename "{name}" "{new_name}"'.format(name=self._name, new_name=new_name)) log.info('Router "{name}" [{id}]: renamed to "{new_name}"'.format(name=self._name, id=self._id, new_name=new_name)) self._name = new_name - @asyncio.coroutine - def set_configs(self, startup_config, private_config=''): - """ - Sets the config files that are pushed to startup-config and - private-config in NVRAM when the instance is started. - - :param startup_config: path to statup-config file - :param private_config: path to private-config file - (keep existing data when if an empty string) - """ - - startup_config = startup_config.replace("\\", '/') - private_config = private_config.replace("\\", '/') - - if self._startup_config != startup_config or self._private_config != private_config: - self._startup_config = startup_config - self._private_config = private_config - - if private_config: - private_config_path = os.path.join(self._working_directory, private_config) - try: - if not os.path.getsize(private_config_path): - # an empty private-config can prevent a router to boot. - private_config = '' - self._private_config_content = "" - else: - with open(private_config_path) as f: - self._private_config_content = f.read() - except OSError as e: - raise DynamipsError("Cannot access the private-config {}: {}".format(private_config_path, e)) - - try: - startup_config_path = os.path.join(self._working_directory, startup_config) - with open(startup_config_path) as f: - self._startup_config_content = f.read() - except OSError as e: - raise DynamipsError("Cannot access the startup-config {}: {}".format(startup_config_path, e)) - - yield from self._hypervisor.send('vm set_config "{name}" "{startup}" "{private}"'.format(name=self._name, - startup=startup_config, - private=private_config)) - - log.info('Router "{name}" [{id}]: has a new startup-config set: "{startup}"'.format(name=self._name, - id=self._id, - startup=startup_config)) - - if private_config: - log.info('Router "{name}" [{id}]: has a new private-config set: "{private}"'.format(name=self._name, - id=self._id, - private=private_config)) - @asyncio.coroutine def extract_config(self): """ @@ -1594,41 +1521,35 @@ class Router(BaseNode): Saves the startup-config and private-config to files. """ - if self.startup_config or self.private_config: + try: + config_path = os.path.join(self._working_directory, "configs") + os.makedirs(config_path, exist_ok=True) + except OSError as e: + raise DynamipsError("Could could not create configuration directory {}: {}".format(config_path, e)) + startup_config_base64, private_config_base64 = yield from self.extract_config() + if startup_config_base64: + startup_config = os.path.join("configs", "i{}_startup-config.cfg".format(self._dynamips_id)) try: - config_path = os.path.join(self._working_directory, "configs") - os.makedirs(config_path, exist_ok=True) - except OSError as e: - raise DynamipsError("Could could not create configuration directory {}: {}".format(config_path, e)) - - startup_config_base64, private_config_base64 = yield from self.extract_config() - if startup_config_base64: - if not self.startup_config: - self._startup_config = os.path.join("configs", "i{}_startup-config.cfg".format(self._dynamips_id)) - try: - config = base64.b64decode(startup_config_base64).decode("utf-8", errors="replace") - config = "!\n" + config.replace("\r", "") - config_path = os.path.join(self._working_directory, self.startup_config) - with open(config_path, "wb") as f: - log.info("saving startup-config to {}".format(self.startup_config)) - self._startup_config_content = config - f.write(config.encode("utf-8")) - except (binascii.Error, OSError) as e: - raise DynamipsError("Could not save the startup configuration {}: {}".format(config_path, e)) - - if private_config_base64 and base64.b64decode(private_config_base64) != b'\nkerberos password \nend\n': - if not self.private_config: - self._private_config = os.path.join("configs", "i{}_private-config.cfg".format(self._dynamips_id)) - try: - config = base64.b64decode(private_config_base64).decode("utf-8", errors="replace") - config_path = os.path.join(self._working_directory, self.private_config) - with open(config_path, "wb") as f: - log.info("saving private-config to {}".format(self.private_config)) - self._private_config_content = config - f.write(config.encode("utf-8")) - except (binascii.Error, OSError) as e: - raise DynamipsError("Could not save the private configuration {}: {}".format(config_path, e)) + config = base64.b64decode(startup_config_base64).decode("utf-8", errors="replace") + config = "!\n" + config.replace("\r", "") + config_path = os.path.join(self._working_directory, startup_config) + with open(config_path, "wb") as f: + log.info("saving startup-config to {}".format(startup_config)) + f.write(config.encode("utf-8")) + except (binascii.Error, OSError) as e: + raise DynamipsError("Could not save the startup configuration {}: {}".format(config_path, e)) + + if private_config_base64 and base64.b64decode(private_config_base64) != b'\nkerberos password \nend\n': + private_config = os.path.join("configs", "i{}_private-config.cfg".format(self._dynamips_id)) + try: + config = base64.b64decode(private_config_base64).decode("utf-8", errors="replace") + config_path = os.path.join(self._working_directory, private_config) + with open(config_path, "wb") as f: + log.info("saving private-config to {}".format(private_config)) + f.write(config.encode("utf-8")) + except (binascii.Error, OSError) as e: + raise DynamipsError("Could not save the private configuration {}: {}".format(config_path, e)) def delete(self): """ diff --git a/gns3server/compute/iou/iou_vm.py b/gns3server/compute/iou/iou_vm.py index fc5ce499..bed1b715 100644 --- a/gns3server/compute/iou/iou_vm.py +++ b/gns3server/compute/iou/iou_vm.py @@ -26,8 +26,6 @@ import re import asyncio import subprocess import shutil -import argparse -import threading import configparser import struct import hashlib @@ -207,10 +205,6 @@ class IOUVM(BaseNode): "ram": self._ram, "nvram": self._nvram, "l1_keepalives": self._l1_keepalives, - "startup_config": self.relative_startup_config_file, - "startup_config_content": self.startup_config_content, - "private_config_content": self.private_config_content, - "private_config": self.relative_private_config_file, "use_default_iou_values": self._use_default_iou_values, "command_line": self.command_line} diff --git a/gns3server/compute/vpcs/vpcs_vm.py b/gns3server/compute/vpcs/vpcs_vm.py index 85952be3..97439c7b 100644 --- a/gns3server/compute/vpcs/vpcs_vm.py +++ b/gns3server/compute/vpcs/vpcs_vm.py @@ -109,7 +109,7 @@ class VPCSVM(BaseNode): raise VPCSError("No path to a VPCS executable has been set") # This raise an error if ubridge is not available - ubridge_path = self.ubridge_path + self.ubridge_path if not os.path.isfile(path): raise VPCSError("VPCS program '{}' is not accessible".format(path)) @@ -128,8 +128,6 @@ class VPCSVM(BaseNode): "console": self._console, "console_type": "telnet", "project_id": self.project.id, - "startup_script": self.startup_script, - "startup_script_path": self.relative_startup_script, "command_line": self.command_line} @property diff --git a/gns3server/configs/ios_base_startup-config.txt b/gns3server/configs/ios_base_startup-config.txt new file mode 100644 index 00000000..8ba5c6a2 --- /dev/null +++ b/gns3server/configs/ios_base_startup-config.txt @@ -0,0 +1,26 @@ +! +service timestamps debug datetime msec +service timestamps log datetime msec +no service password-encryption +! +hostname %h +! +ip cef +no ip domain-lookup +no ip icmp rate-limit unreachable +ip tcp synwait 5 +no cdp log mismatch duplex +! +line con 0 + exec-timeout 0 0 + logging synchronous + privilege level 15 + no login +line aux 0 + exec-timeout 0 0 + logging synchronous + privilege level 15 + no login +! +! +end diff --git a/gns3server/configs/ios_etherswitch_startup-config.txt b/gns3server/configs/ios_etherswitch_startup-config.txt new file mode 100644 index 00000000..2367b347 --- /dev/null +++ b/gns3server/configs/ios_etherswitch_startup-config.txt @@ -0,0 +1,181 @@ +! +service timestamps debug datetime msec +service timestamps log datetime msec +no service password-encryption +no service dhcp +! +hostname %h +! +ip cef +no ip routing +no ip domain-lookup +no ip icmp rate-limit unreachable +ip tcp synwait 5 +no cdp log mismatch duplex +vtp file nvram:vlan.dat +! +! +interface FastEthernet0/0 + description *** Unused for Layer2 EtherSwitch *** + no ip address + shutdown +! +interface FastEthernet0/1 + description *** Unused for Layer2 EtherSwitch *** + no ip address + shutdown +! +interface FastEthernet1/0 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/1 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/2 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/3 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/4 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/5 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/6 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/7 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/8 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/9 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/10 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/11 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/12 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/13 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/14 + no shutdown + duplex full + speed 100 +! +interface FastEthernet1/15 + no shutdown + duplex full + speed 100 +! +interface Vlan1 + no ip address + shutdown +! +! +line con 0 + exec-timeout 0 0 + logging synchronous + privilege level 15 + no login +line aux 0 + exec-timeout 0 0 + logging synchronous + privilege level 15 + no login +! +! +banner exec $ + +*************************************************************** +This is a normal Router with a SW module inside (NM-16ESW) +It has been preconfigured with hard coded speed and duplex + +To create vlans use the command "vlan database" from exec mode +After creating all desired vlans use "exit" to apply the config + +To view existing vlans use the command "show vlan-switch brief" + +Warning: You are using an old IOS image for this router. +Please update the IOS to enable the "macro" command! +*************************************************************** + +$ +! +!Warning: If the IOS is old and doesn't support macro, it will stop the configuration loading from this point! +! +macro name add_vlan +end +vlan database +vlan $v +exit +@ +macro name del_vlan +end +vlan database +no vlan $v +exit +@ +! +! +banner exec $ + +*************************************************************** +This is a normal Router with a Switch module inside (NM-16ESW) +It has been pre-configured with hard-coded speed and duplex + +To create vlans use the command "vlan database" in exec mode +After creating all desired vlans use "exit" to apply the config + +To view existing vlans use the command "show vlan-switch brief" + +Alias(exec) : vl - "show vlan-switch brief" command +Alias(configure): va X - macro to add vlan X +Alias(configure): vd X - macro to delete vlan X +*************************************************************** + +$ +! +alias configure va macro global trace add_vlan $v +alias configure vd macro global trace del_vlan $v +alias exec vl show vlan-switch brief +! +! +end diff --git a/gns3server/configs/iou_l2_base_startup-config.txt b/gns3server/configs/iou_l2_base_startup-config.txt new file mode 100644 index 00000000..501355f6 --- /dev/null +++ b/gns3server/configs/iou_l2_base_startup-config.txt @@ -0,0 +1,132 @@ +! +service timestamps debug datetime msec +service timestamps log datetime msec +no service password-encryption +! +hostname %h +! +! +! +logging discriminator EXCESS severity drops 6 msg-body drops EXCESSCOLL +logging buffered 50000 +logging console discriminator EXCESS +! +no ip icmp rate-limit unreachable +! +ip cef +no ip domain-lookup +! +! +! +! +! +! +ip tcp synwait-time 5 +! +! +! +! +! +! +interface Ethernet0/0 + no ip address + no shutdown + duplex auto +! +interface Ethernet0/1 + no ip address + no shutdown + duplex auto +! +interface Ethernet0/2 + no ip address + no shutdown + duplex auto +! +interface Ethernet0/3 + no ip address + no shutdown + duplex auto +! +interface Ethernet1/0 + no ip address + no shutdown + duplex auto +! +interface Ethernet1/1 + no ip address + no shutdown + duplex auto +! +interface Ethernet1/2 + no ip address + no shutdown + duplex auto +! +interface Ethernet1/3 + no ip address + no shutdown + duplex auto +! +interface Ethernet2/0 + no ip address + no shutdown + duplex auto +! +interface Ethernet2/1 + no ip address + no shutdown + duplex auto +! +interface Ethernet2/2 + no ip address + no shutdown + duplex auto +! +interface Ethernet2/3 + no ip address + no shutdown + duplex auto +! +interface Ethernet3/0 + no ip address + no shutdown + duplex auto +! +interface Ethernet3/1 + no ip address + no shutdown + duplex auto +! +interface Ethernet3/2 + no ip address + no shutdown + duplex auto +! +interface Ethernet3/3 + no ip address + no shutdown + duplex auto +! +interface Vlan1 + no ip address + shutdown +! +! +! +! +! +! +! +! +! +line con 0 + exec-timeout 0 0 + privilege level 15 + logging synchronous +line aux 0 + exec-timeout 0 0 + privilege level 15 + logging synchronous +! +end diff --git a/gns3server/configs/iou_l3_base_startup-config.txt b/gns3server/configs/iou_l3_base_startup-config.txt new file mode 100644 index 00000000..81d574ff --- /dev/null +++ b/gns3server/configs/iou_l3_base_startup-config.txt @@ -0,0 +1,108 @@ +! +service timestamps debug datetime msec +service timestamps log datetime msec +no service password-encryption +! +hostname %h +! +! +! +no ip icmp rate-limit unreachable +! +! +! +! +ip cef +no ip domain-lookup +! +! +ip tcp synwait-time 5 +! +! +! +! +interface Ethernet0/0 + no ip address + shutdown +! +interface Ethernet0/1 + no ip address + shutdown +! +interface Ethernet0/2 + no ip address + shutdown +! +interface Ethernet0/3 + no ip address + shutdown +! +interface Ethernet1/0 + no ip address + shutdown +! +interface Ethernet1/1 + no ip address + shutdown +! +interface Ethernet1/2 + no ip address + shutdown +! +interface Ethernet1/3 + no ip address + shutdown +! +interface Serial2/0 + no ip address + shutdown + serial restart-delay 0 +! +interface Serial2/1 + no ip address + shutdown + serial restart-delay 0 +! +interface Serial2/2 + no ip address + shutdown + serial restart-delay 0 +! +interface Serial2/3 + no ip address + shutdown + serial restart-delay 0 +! +interface Serial3/0 + no ip address + shutdown + serial restart-delay 0 +! +interface Serial3/1 + no ip address + shutdown + serial restart-delay 0 +! +interface Serial3/2 + no ip address + shutdown + serial restart-delay 0 +! +interface Serial3/3 + no ip address + shutdown + serial restart-delay 0 +! +! +no cdp log mismatch duplex +! +line con 0 + exec-timeout 0 0 + privilege level 15 + logging synchronous +line aux 0 + exec-timeout 0 0 + privilege level 15 + logging synchronous +! +end diff --git a/gns3server/configs/vpcs_base_config.txt b/gns3server/configs/vpcs_base_config.txt new file mode 100644 index 00000000..9e5efd8f --- /dev/null +++ b/gns3server/configs/vpcs_base_config.txt @@ -0,0 +1 @@ +set pcname %h diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index 295e6762..3e597d2c 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -16,9 +16,9 @@ # along with this program. If not, see . import os -import sys import json import socket +import shutil import asyncio import aiohttp @@ -30,7 +30,7 @@ from .symbols import Symbols from ..version import __version__ from .topology import load_topology from .gns3vm import GNS3VM - +from ..utils.get_resource import get_resource import logging log = logging.getLogger(__name__) @@ -54,6 +54,7 @@ class Controller: @asyncio.coroutine def start(self): log.info("Start controller") + self.load_base_files() yield from self.load() server_config = Config.instance().get_section_config("Server") host = server_config.get("host", "localhost") @@ -163,6 +164,20 @@ class Controller: except OSError as e: log.error(str(e)) + def load_base_files(self): + """ + At startup we copy base file to the user location to allow + them to customize it + """ + dst_path = self.configs_path() + src_path = get_resource('configs') + try: + for file in os.listdir(src_path): + if not os.path.exists(os.path.join(dst_path, file)): + shutil.copy(os.path.join(src_path, file), os.path.join(dst_path, file)) + except OSError: + pass + def images_path(self): """ Get the image storage directory @@ -172,6 +187,15 @@ class Controller: os.makedirs(images_path, exist_ok=True) return images_path + def configs_path(self): + """ + Get the configs storage directory + """ + server_config = Config.instance().get_section_config("Server") + images_path = os.path.expanduser(server_config.get("configs_path", "~/GNS3/projects")) + os.makedirs(images_path, exist_ok=True) + return images_path + @asyncio.coroutine def _import_gns3_gui_conf(self): """ diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index 9b330cf2..49337325 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -146,6 +146,15 @@ class Node: def properties(self, val): self._properties = val + def _base_config_file_content(self, path): + if not os.path.isabs(path): + path = os.path.join(self.project.controller.configs_path(), path) + try: + with open(path) as f: + return f.read() + except (PermissionError, OSError): + return None + @property def project(self): return self._project @@ -366,8 +375,12 @@ class Node: self._console_type = value elif key == "name": self.name = value - elif key in ["node_id", "project_id", "console_host"]: - pass + elif key in ["node_id", "project_id", "console_host", + "startup_config_content", + "private_config_content", + "startup_script"]: + if key in self._properties: + del self._properties[key] else: self._properties[key] = value self._list_ports() @@ -384,6 +397,17 @@ class Node: data = copy.copy(properties) else: data = copy.copy(self._properties) + # We replace the startup script name by the content of the file + mapping = { + "base_script_file": "startup_script", + "startup_config": "startup_config_content", + "private_config": "private_config_content", + } + for k, v in mapping.items(): + if k in list(self._properties.keys()): + data[v] = self._base_config_file_content(self._properties[k]) + del data[k] + del self._properties[k] # We send the file only one time data["name"] = self._name if self._console: # console is optional for builtin nodes @@ -585,17 +609,6 @@ class Node: return False return self.id == other.id and other.project.id == self.project.id - def _filter_properties(self): - """ - Some properties are private and should not be exposed - """ - PRIVATE_PROPERTIES = ("iourc_content", ) - prop = copy.copy(self._properties) - for k in list(prop.keys()): - if k in PRIVATE_PROPERTIES: - del prop[k] - return prop - def __json__(self, topology_dump=False): """ :param topology_dump: Filter to keep only properties require for saving on disk @@ -608,7 +621,7 @@ class Node: "name": self._name, "console": self._console, "console_type": self._console_type, - "properties": self._filter_properties(), + "properties": self._properties, "label": self._label, "x": self._x, "y": self._y, @@ -631,7 +644,7 @@ class Node: "console_host": str(self._compute.console_host), "console_type": self._console_type, "command_line": self._command_line, - "properties": self._filter_properties(), + "properties": self._properties, "status": self._status, "label": self._label, "x": self._x, diff --git a/gns3server/controller/topology.py b/gns3server/controller/topology.py index b9400364..a126593d 100644 --- a/gns3server/controller/topology.py +++ b/gns3server/controller/topology.py @@ -36,7 +36,7 @@ import logging log = logging.getLogger(__name__) -GNS3_FILE_FORMAT_REVISION = 7 +GNS3_FILE_FORMAT_REVISION = 8 def _check_topology_schema(topo): @@ -138,6 +138,10 @@ def load_topology(path): if topo["revision"] < 7: topo = _convert_2_0_0_beta_2(topo, path) + # Version before GNS3 2.1 + if topo["revision"] < 8: + topo = _convert_2_0_0(topo, path) + _check_topology_schema(topo) if changed: @@ -146,6 +150,34 @@ def load_topology(path): return topo +def _convert_2_0_0(topo, topo_path): + """ + Convert topologies from GNS3 2.0.0 to 2.1 + + Changes: + * Remove startup_script_path from VPCS and base config file for IOU and Dynamips + """ + topo["revision"] = 8 + + for node in topo.get("topology", {}).get("nodes", []): + if "properties" in node: + if node["node_type"] == "vpcs": + if "startup_script_path" in node["properties"]: + del node["properties"]["startup_script_path"] + if "startup_script" in node["properties"]: + del node["properties"]["startup_script"] + elif node["node_type"] == "dynamips" or node["node_type"] == "iou": + if "startup_config" in node["properties"]: + del node["properties"]["startup_config"] + if "private_config" in node["properties"]: + del node["properties"]["private_config"] + if "startup_config_content" in node["properties"]: + del node["properties"]["startup_config_content"] + if "private_config_content" in node["properties"]: + del node["properties"]["private_config_content"] + return topo + + def _convert_2_0_0_beta_2(topo, topo_path): """ Convert topologies from GNS3 2.0.0 beta 2 to beta 3. diff --git a/gns3server/handlers/api/compute/dynamips_vm_handler.py b/gns3server/handlers/api/compute/dynamips_vm_handler.py index c8b1f318..dd0352de 100644 --- a/gns3server/handlers/api/compute/dynamips_vm_handler.py +++ b/gns3server/handlers/api/compute/dynamips_vm_handler.py @@ -17,7 +17,6 @@ import os import sys -import base64 from gns3server.web.route import Route from gns3server.schemas.nio import NIO_SCHEMA @@ -78,7 +77,6 @@ class DynamipsVMHandler: aux=request.json.get("aux"), chassis=request.json.pop("chassis", default_chassis), node_type="dynamips") - yield from dynamips_manager.update_vm_settings(vm, request.json) response.set_status(201) response.json(vm) diff --git a/gns3server/handlers/api/controller/node_handler.py b/gns3server/handlers/api/controller/node_handler.py index 67857df7..d9a715f0 100644 --- a/gns3server/handlers/api/controller/node_handler.py +++ b/gns3server/handlers/api/controller/node_handler.py @@ -344,10 +344,7 @@ class NodeHandler: raise aiohttp.web.HTTPForbidden node_type = node.node_type - if node_type == "dynamips": - path = "/project-files/{}/{}".format(node_type, path) - else: - path = "/project-files/{}/{}/{}".format(node_type, node.id, path) + path = "/project-files/{}/{}/{}".format(node_type, node.id, path) res = yield from node.compute.http_query("GET", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), timeout=None, raw=True) response.set_status(200) @@ -384,12 +381,9 @@ class NodeHandler: raise aiohttp.web.HTTPForbidden node_type = node.node_type - if node_type == "dynamips": - path = "/project-files/{}/{}".format(node_type, path) - else: - path = "/project-files/{}/{}/{}".format(node_type, node.id, path) + path = "/project-files/{}/{}/{}".format(node_type, node.id, path) data = yield from request.content.read() - res = yield from node.compute.http_query("POST", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), data=data, timeout=None, raw=True) + yield from node.compute.http_query("POST", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), data=data, timeout=None, raw=True) response.set_status(201) diff --git a/gns3server/schemas/dynamips_vm.py b/gns3server/schemas/dynamips_vm.py index c5225c21..0a2bcc71 100644 --- a/gns3server/schemas/dynamips_vm.py +++ b/gns3server/schemas/dynamips_vm.py @@ -62,18 +62,10 @@ VM_CREATE_SCHEMA = { "type": ["string", "null"], "minLength": 1, }, - "startup_config": { - "description": "Path to the IOS startup configuration file", - "type": "string", - }, "startup_config_content": { "description": "Content of IOS startup configuration file", "type": "string", }, - "private_config": { - "description": "Path to the IOS private configuration file", - "type": "string", - }, "private_config_content": { "description": "Content of IOS private configuration file", "type": "string", @@ -296,22 +288,6 @@ VM_UPDATE_SCHEMA = { "description": "Dynamips ID", "type": "integer" }, - "startup_config": { - "description": "Path to the IOS startup configuration file.", - "type": "string", - }, - "private_config": { - "description": "Path to the IOS private configuration file.", - "type": "string", - }, - "startup_config_content": { - "description": "Content of IOS startup configuration file", - "type": "string", - }, - "private_config_content": { - "description": "Content of IOS private configuration file", - "type": "string", - }, "ram": { "description": "Amount of RAM in MB", "type": "integer" @@ -552,14 +528,6 @@ VM_OBJECT_SCHEMA = { "type": ["string", "null"], "minLength": 1, }, - "startup_config": { - "description": "Path to the IOS startup configuration file", - "type": "string", - }, - "private_config": { - "description": "Path to the IOS private configuration file", - "type": "string", - }, "ram": { "description": "Amount of RAM in MB", "type": "integer" @@ -706,14 +674,6 @@ VM_OBJECT_SCHEMA = { {"type": "null"} ] }, - "startup_config_content": { - "description": "Content of IOS startup configuration file", - "type": "string", - }, - "private_config_content": { - "description": "Content of IOS private configuration file", - "type": "string", - }, # C7200 properties "npe": { "description": "NPE model", diff --git a/gns3server/schemas/iou.py b/gns3server/schemas/iou.py index 8e54be64..389dea6e 100644 --- a/gns3server/schemas/iou.py +++ b/gns3server/schemas/iou.py @@ -78,14 +78,6 @@ IOU_CREATE_SCHEMA = { "description": "Use default IOU values", "type": ["boolean", "null"] }, - "startup_config": { - "description": "Path to the startup-config of IOU", - "type": ["string", "null"] - }, - "private_config": { - "description": "Path to the private-config of IOU", - "type": ["string", "null"] - }, "startup_config_content": { "description": "Startup-config of IOU", "type": ["string", "null"] @@ -94,10 +86,6 @@ IOU_CREATE_SCHEMA = { "description": "Private-config of IOU", "type": ["string", "null"] }, - "iourc_content": { - "description": "Content of the iourc file. Ignored if Null", - "type": ["string", "null"] - } }, "additionalProperties": False, "required": ["name", "path"] @@ -187,30 +175,10 @@ IOU_OBJECT_SCHEMA = { "description": "Always up ethernet interface", "type": "boolean" }, - "startup_config": { - "description": "Path of the startup-config content relative to project directory", - "type": ["string", "null"] - }, - "private_config": { - "description": "Path of the private-config content relative to project directory", - "type": ["string", "null"] - }, "use_default_iou_values": { "description": "Use default IOU values", "type": ["boolean", "null"] }, - "startup_config_content": { - "description": "Startup-config of IOU", - "type": ["string", "null"] - }, - "private_config_content": { - "description": "Private-config of IOU", - "type": ["string", "null"] - }, - "iourc_content": { - "description": "Content of the iourc file. Ignored if Null", - "type": ["string", "null"] - }, "command_line": { "description": "Last command line used by GNS3 to start QEMU", "type": "string" diff --git a/gns3server/schemas/vpcs.py b/gns3server/schemas/vpcs.py index 283f1091..f36351a8 100644 --- a/gns3server/schemas/vpcs.py +++ b/gns3server/schemas/vpcs.py @@ -50,10 +50,6 @@ VPCS_CREATE_SCHEMA = { "description": "Content of the VPCS startup script", "type": ["string", "null"] }, - "startup_script_path": { - "description": "Path of the VPCS startup script relative to project directory (IGNORED)", - "type": ["string", "null"] - } }, "additionalProperties": False, "required": ["name"] @@ -79,14 +75,6 @@ VPCS_UPDATE_SCHEMA = { "description": "Console type", "enum": ["telnet"] }, - "startup_script": { - "description": "Content of the VPCS startup script", - "type": ["string", "null"] - }, - "startup_script_path": { - "description": "Path of the VPCS startup script relative to project directory (IGNORED)", - "type": ["string", "null"] - } }, "additionalProperties": False, } @@ -133,19 +121,11 @@ VPCS_OBJECT_SCHEMA = { "maxLength": 36, "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" }, - "startup_script": { - "description": "Content of the VPCS startup script", - "type": ["string", "null"] - }, - "startup_script_path": { - "description": "Path of the VPCS startup script relative to project directory", - "type": ["string", "null"] - }, "command_line": { "description": "Last command line used by GNS3 to start QEMU", "type": "string" } }, "additionalProperties": False, - "required": ["name", "node_id", "status", "console", "console_type", "project_id", "startup_script_path", "command_line"] + "required": ["name", "node_id", "status", "console", "console_type", "project_id", "command_line"] } diff --git a/tests/controller/test_controller.py b/tests/controller/test_controller.py index 3227c54f..34a98741 100644 --- a/tests/controller/test_controller.py +++ b/tests/controller/test_controller.py @@ -465,3 +465,17 @@ def test_get_free_project_name(controller, async_run): async_run(controller.add_project(project_id=str(uuid.uuid4()), name="Test-1")) assert controller.get_free_project_name("Test") == "Test-2" assert controller.get_free_project_name("Hello") == "Hello" + + +def test_load_base_files(controller, config, tmpdir): + config.set_section_config("Server", {"configs_path": str(tmpdir)}) + + with open(str(tmpdir / 'iou_l2_base_startup-config.txt'), 'w+') as f: + f.write('test') + + controller.load_base_files() + assert os.path.exists(str(tmpdir / 'iou_l3_base_startup-config.txt')) + + # Check is the file has not been overwrite + with open(str(tmpdir / 'iou_l2_base_startup-config.txt')) as f: + assert f.read() == 'test' diff --git a/tests/controller/test_node.py b/tests/controller/test_node.py index f3b6e55a..0d7e7456 100644 --- a/tests/controller/test_node.py +++ b/tests/controller/test_node.py @@ -88,19 +88,6 @@ def test_eq(compute, project, node, controller): assert node != Node(Project(str(uuid.uuid4()), controller=controller), compute, "demo3", node_id=node.id, node_type="qemu") -def test_properties_filter(project, compute): - """ - Some properties are private and should not be exposed - """ - node = Node(project, compute, "demo", - node_id=str(uuid.uuid4()), - node_type="vpcs", - console_type="vnc", - properties={"startup_script": "echo test", "iourc_content": "test"}) - assert node._properties == {"startup_script": "echo test", "iourc_content": "test"} - assert node._filter_properties() == {"startup_script": "echo test"} - - def test_json(node, compute): assert node.__json__() == { "compute_id": str(compute.id), @@ -207,6 +194,30 @@ def test_create_image_missing(node, compute, project, async_run): node._upload_missing_image.called is True +def test_create_base_script(node, config, compute, tmpdir, async_run): + config.set_section_config("Server", {"configs_path": str(tmpdir)}) + + with open(str(tmpdir / 'test.txt'), 'w+') as f: + f.write('hostname test') + + node._properties = {"base_script_file": "test.txt"} + node._console = 2048 + + response = MagicMock() + response.json = {"console": 2048} + compute.post = AsyncioMagicMock(return_value=response) + + assert async_run(node.create()) is True + data = { + "console": 2048, + "console_type": "vnc", + "node_id": node.id, + "startup_script": "hostname test", + "name": "demo" + } + compute.post.assert_called_with("/projects/{}/vpcs/nodes".format(node.project.id), data=data, timeout=120) + + def test_symbol(node, symbols_dir): """ Change symbol should change the node size diff --git a/tests/controller/test_project.py b/tests/controller/test_project.py index 1fec7320..bb3c1228 100644 --- a/tests/controller/test_project.py +++ b/tests/controller/test_project.py @@ -137,7 +137,7 @@ def test_add_node_local(async_run, controller): response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) - node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) + node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"})) assert node.id in project._nodes compute.post.assert_any_call('/projects', data={ @@ -147,7 +147,7 @@ def test_add_node_local(async_run, controller): }) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id, - 'startup_config': 'test.cfg', + 'startup_script': 'test.cfg', 'name': 'test'}, timeout=120) assert compute in project._project_created_on_compute @@ -167,7 +167,7 @@ def test_add_node_non_local(async_run, controller): response.json = {"console": 2048} compute.post = AsyncioMagicMock(return_value=response) - node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) + node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_script": "test.cfg"})) compute.post.assert_any_call('/projects', data={ "name": project._name, @@ -175,7 +175,7 @@ def test_add_node_non_local(async_run, controller): }) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id, - 'startup_config': 'test.cfg', + 'startup_script': 'test.cfg', 'name': 'test'}, timeout=120) assert compute in project._project_created_on_compute diff --git a/tests/controller/test_project_open.py b/tests/controller/test_project_open.py index 252692dd..ac0473d5 100644 --- a/tests/controller/test_project_open.py +++ b/tests/controller/test_project_open.py @@ -106,7 +106,6 @@ def demo_topology(): "node_type": "vpcs", "properties": { "startup_script": "", - "startup_script_path": "startup.vpc" }, "symbol": ":/symbols/computer.svg", "width": 65, @@ -131,7 +130,6 @@ def demo_topology(): "node_type": "vpcs", "properties": { "startup_script": "", - "startup_script_path": "startup.vpc" }, "symbol": ":/symbols/computer.svg", "width": 65, diff --git a/tests/handlers/api/compute/test_iou.py b/tests/handlers/api/compute/test_iou.py index 8d63cbdf..f31f367a 100644 --- a/tests/handlers/api/compute/test_iou.py +++ b/tests/handlers/api/compute/test_iou.py @@ -80,7 +80,6 @@ def test_iou_create_with_params(http_compute, project, base_params): params["l1_keepalives"] = True params["startup_config_content"] = "hostname test" params["use_default_iou_values"] = True - params["iourc_content"] = "test" response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), params, example=True) assert response.status == 201 @@ -94,7 +93,6 @@ def test_iou_create_with_params(http_compute, project, base_params): assert response.json["l1_keepalives"] is True assert response.json["use_default_iou_values"] is True - assert "startup-config.cfg" in response.json["startup_config"] with open(startup_config_file(project, response.json)) as f: assert f.read() == "hostname test" @@ -115,7 +113,6 @@ def test_iou_create_startup_config_already_exist(http_compute, project, base_par assert response.status == 201 assert response.route == "/projects/{project_id}/iou/nodes" - assert "startup-config.cfg" in response.json["startup_config"] with open(startup_config_file(project, response.json)) as f: assert f.read() == "echo hello" @@ -183,9 +180,7 @@ def test_iou_update(http_compute, vm, tmpdir, free_console_port, project): "ethernet_adapters": 4, "serial_adapters": 0, "l1_keepalives": True, - "startup_config_content": "hostname test", "use_default_iou_values": True, - "iourc_content": "test" } response = http_compute.put("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params, example=True) assert response.status == 200 @@ -197,9 +192,6 @@ def test_iou_update(http_compute, vm, tmpdir, free_console_port, project): assert response.json["nvram"] == 2048 assert response.json["l1_keepalives"] is True assert response.json["use_default_iou_values"] is True - assert "startup-config.cfg" in response.json["startup_config"] - with open(startup_config_file(project, response.json)) as f: - assert f.read() == "hostname test" def test_iou_nio_create_udp(http_compute, vm): diff --git a/tests/handlers/api/compute/test_vpcs.py b/tests/handlers/api/compute/test_vpcs.py index 6a0ea0b7..85456e5e 100644 --- a/tests/handlers/api/compute/test_vpcs.py +++ b/tests/handlers/api/compute/test_vpcs.py @@ -43,7 +43,6 @@ def test_vpcs_get(http_compute, project, vm): assert response.route == "/projects/{project_id}/vpcs/nodes/{node_id}" assert response.json["name"] == "PC TEST 1" assert response.json["project_id"] == project.id - assert response.json["startup_script_path"] is None assert response.json["status"] == "stopped" @@ -53,8 +52,6 @@ def test_vpcs_create_startup_script(http_compute, project): assert response.route == "/projects/{project_id}/vpcs/nodes" assert response.json["name"] == "PC TEST 1" assert response.json["project_id"] == project.id - assert response.json["startup_script"] == os.linesep.join(["ip 192.168.1.2", "echo TEST"]) - assert response.json["startup_script_path"] == "startup.vpc" def test_vpcs_create_port(http_compute, project, free_console_port): diff --git a/tests/topologies/1_3_dynamips/after/1_3_dynamips.gns3 b/tests/topologies/1_3_dynamips/after/1_3_dynamips.gns3 index eb264324..30326e4e 100644 --- a/tests/topologies/1_3_dynamips/after/1_3_dynamips.gns3 +++ b/tests/topologies/1_3_dynamips/after/1_3_dynamips.gns3 @@ -63,7 +63,6 @@ ], "slot0": "C7200-IO-FE", "sparsemem": true, - "startup_config": "configs/i1_startup-config.cfg", "system_id": "FTX0945W0MY" }, "x": -112, diff --git a/tests/topologies/1_3_dynamips_missing_platform/after/1_3_dynamips_missing_platform.gns3 b/tests/topologies/1_3_dynamips_missing_platform/after/1_3_dynamips_missing_platform.gns3 index 40db2eb6..948e0745 100644 --- a/tests/topologies/1_3_dynamips_missing_platform/after/1_3_dynamips_missing_platform.gns3 +++ b/tests/topologies/1_3_dynamips_missing_platform/after/1_3_dynamips_missing_platform.gns3 @@ -27,7 +27,6 @@ "slot0": "Leopard-2FE", "idlepc": "0x6057efc8", "chassis": "3660", - "startup_config": "configs/i1_startup-config.cfg", "image": "c3660-a3jk9s-mz.124-25c.bin", "mac_addr": "cc01.20b8.0000", "aux": 2103, diff --git a/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 b/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 index 81532226..ea1e08f0 100644 --- a/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 +++ b/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 @@ -53,7 +53,6 @@ "ram": 256, "slot0": "GT96100-FE", "sparsemem": true, - "startup_config": "configs/i1_startup-config.cfg", "system_id": "FTX0945W0MY" }, "symbol": ":/symbols/router.svg", @@ -100,7 +99,6 @@ "slot0": "Leopard-2FE", "slot1": "NM-16ESW", "sparsemem": true, - "startup_config": "configs/i2_startup-config.cfg", "system_id": "FTX0945W0MY" }, "symbol": ":/symbols/multilayer_switch.svg", diff --git a/tests/topologies/1_5_internet/after/1_5_internet.gns3 b/tests/topologies/1_5_internet/after/1_5_internet.gns3 index 7214d7c7..76109038 100644 --- a/tests/topologies/1_5_internet/after/1_5_internet.gns3 +++ b/tests/topologies/1_5_internet/after/1_5_internet.gns3 @@ -76,7 +76,6 @@ "port_segment_size": 0, "first_port_name": null, "properties": { - "startup_script_path": "startup.vpc" }, "symbol": ":/symbols/vpcs_guest.svg", "x": -29, diff --git a/tests/topologies/1_5_iou/after/1_5_iou.gns3 b/tests/topologies/1_5_iou/after/1_5_iou.gns3 index f45baa1c..ba57da26 100644 --- a/tests/topologies/1_5_iou/after/1_5_iou.gns3 +++ b/tests/topologies/1_5_iou/after/1_5_iou.gns3 @@ -41,7 +41,6 @@ "path": "i86bi-linux-l3-adventerprisek9-15.4.1T.bin", "ram": 256, "serial_adapters": 2, - "startup_config": "startup-config.cfg", "use_default_iou_values": true }, "symbol": ":/symbols/router.svg", diff --git a/tests/topologies/1_5_snapshot/after/1_5_snapshot.gns3 b/tests/topologies/1_5_snapshot/after/1_5_snapshot.gns3 index 08f8c367..e1d2afaf 100644 --- a/tests/topologies/1_5_snapshot/after/1_5_snapshot.gns3 +++ b/tests/topologies/1_5_snapshot/after/1_5_snapshot.gns3 @@ -18,7 +18,6 @@ "port_segment_size": 0, "first_port_name": null, "properties" : { - "startup_script_path" : "startup.vpc" }, "label" : { "y" : -25, diff --git a/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 b/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 index 59e98ebb..64c5083d 100644 --- a/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 +++ b/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 @@ -50,7 +50,6 @@ "port_segment_size": 0, "first_port_name": null, "properties": { - "startup_script_path": "startup.vpc" }, "symbol": ":/symbols/vpcs_guest.svg", "x": -87, @@ -75,7 +74,6 @@ "port_segment_size": 0, "first_port_name": null, "properties": { - "startup_script_path": "startup.vpc" }, "symbol": ":/symbols/vpcs_guest.svg", "x": 123, diff --git a/tests/topologies/dynamips_2_0_0_b2/after/dynamips_2_0_0_b2.gns3 b/tests/topologies/dynamips_2_0_0_b2/after/dynamips_2_0_0_b2.gns3 index 13febe9f..336bb988 100644 --- a/tests/topologies/dynamips_2_0_0_b2/after/dynamips_2_0_0_b2.gns3 +++ b/tests/topologies/dynamips_2_0_0_b2/after/dynamips_2_0_0_b2.gns3 @@ -61,8 +61,6 @@ 1, 1 ], - "private_config": "", - "private_config_content": "", "ram": 512, "sensors": [ 22, @@ -78,8 +76,6 @@ "slot5": null, "slot6": null, "sparsemem": true, - "startup_config": "configs/i1_startup-config.cfg", - "startup_config_content": "!\n!\nservice timestamps debug datetime msec\nservice timestamps log datetime msec\nno service password-encryption\n!\nhostname R1\n!\nip cef\nno ip domain-lookup\nno ip icmp rate-limit unreachable\nip tcp synwait 5\nno cdp log mismatch duplex\n!\nline con 0\n exec-timeout 0 0\n logging synchronous\n privilege level 15\n no login\nline aux 0\n exec-timeout 0 0\n logging synchronous\n privilege level 15\n no login\n!\n!\nend\n", "system_id": "FTX0945W0MY" }, "symbol": ":/symbols/router.svg", @@ -129,8 +125,6 @@ 1, 1 ], - "private_config": "", - "private_config_content": "", "ram": 512, "sensors": [ 22, @@ -146,8 +140,6 @@ "slot5": null, "slot6": null, "sparsemem": true, - "startup_config": "configs/i2_startup-config.cfg", - "startup_config_content": "!\n!\nservice timestamps debug datetime msec\nservice timestamps log datetime msec\nno service password-encryption\n!\nhostname R2\n!\nip cef\nno ip domain-lookup\nno ip icmp rate-limit unreachable\nip tcp synwait 5\nno cdp log mismatch duplex\n!\nline con 0\n exec-timeout 0 0\n logging synchronous\n privilege level 15\n no login\nline aux 0\n exec-timeout 0 0\n logging synchronous\n privilege level 15\n no login\n!\n!\nend\n", "system_id": "FTX0945W0MY" }, "symbol": ":/symbols/router.svg", @@ -160,4 +152,4 @@ }, "type": "topology", "version": "2.0.0dev7" -} \ No newline at end of file +}