mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-25 16:28:11 +00:00
Merge pull request #890 from GNS3/base_config_server_side
Manage base configuration on server
This commit is contained in:
commit
5672b4b748
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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))
|
||||
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))
|
||||
|
||||
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))
|
||||
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):
|
||||
"""
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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
|
||||
|
26
gns3server/configs/ios_base_startup-config.txt
Normal file
26
gns3server/configs/ios_base_startup-config.txt
Normal file
@ -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
|
181
gns3server/configs/ios_etherswitch_startup-config.txt
Normal file
181
gns3server/configs/ios_etherswitch_startup-config.txt
Normal file
@ -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
|
132
gns3server/configs/iou_l2_base_startup-config.txt
Normal file
132
gns3server/configs/iou_l2_base_startup-config.txt
Normal file
@ -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
|
108
gns3server/configs/iou_l3_base_startup-config.txt
Normal file
108
gns3server/configs/iou_l3_base_startup-config.txt
Normal file
@ -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
|
1
gns3server/configs/vpcs_base_config.txt
Normal file
1
gns3server/configs/vpcs_base_config.txt
Normal file
@ -0,0 +1 @@
|
||||
set pcname %h
|
@ -18,6 +18,7 @@
|
||||
import os
|
||||
import json
|
||||
import socket
|
||||
import shutil
|
||||
import asyncio
|
||||
import aiohttp
|
||||
|
||||
@ -29,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__)
|
||||
@ -53,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")
|
||||
@ -162,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
|
||||
@ -171,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):
|
||||
"""
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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"]
|
||||
}
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -63,7 +63,6 @@
|
||||
],
|
||||
"slot0": "C7200-IO-FE",
|
||||
"sparsemem": true,
|
||||
"startup_config": "configs/i1_startup-config.cfg",
|
||||
"system_id": "FTX0945W0MY"
|
||||
},
|
||||
"x": -112,
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
|
@ -18,7 +18,6 @@
|
||||
"port_segment_size": 0,
|
||||
"first_port_name": null,
|
||||
"properties" : {
|
||||
"startup_script_path" : "startup.vpc"
|
||||
},
|
||||
"label" : {
|
||||
"y" : -25,
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user