1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-30 20:28:08 +00:00

Use Dynamips, IOU and VPCS identifiers to correctly load a topology.

This commit is contained in:
grossmj 2014-06-15 05:18:33 -06:00
parent f9ee38dd55
commit cb763e0926
18 changed files with 115 additions and 55 deletions

View File

@ -176,7 +176,11 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler):
Invoked when the WebSocket is closed. Invoked when the WebSocket is closed.
""" """
log.info("Websocket client {} disconnected".format(self.session_id)) try:
log.info("Websocket client {} disconnected".format(self.session_id))
except RuntimeError:
# to ignore logging exception: RuntimeError: reentrant call inside <_io.BufferedWriter name='<stderr>'>
pass
self.clients.remove(self) self.clients.remove(self)
# Reset the modules if there are no clients anymore # Reset the modules if there are no clients anymore

View File

@ -132,9 +132,8 @@ class VM(object):
image = request["image"] image = request["image"]
ram = request["ram"] ram = request["ram"]
hypervisor = None hypervisor = None
chassis = None chassis = request.get("chassis")
if "chassis" in request: router_id = request.get("router_id")
chassis = request["chassis"]
try: try:
@ -147,9 +146,9 @@ class VM(object):
hypervisor = self._hypervisor_manager.allocate_hypervisor_for_router(image, ram) hypervisor = self._hypervisor_manager.allocate_hypervisor_for_router(image, ram)
if chassis: if chassis:
router = PLATFORMS[platform](hypervisor, name, chassis=chassis) router = PLATFORMS[platform](hypervisor, name, router_id, chassis=chassis)
else: else:
router = PLATFORMS[platform](hypervisor, name) router = PLATFORMS[platform](hypervisor, name, router_id)
router.ram = ram router.ram = ram
router.image = image router.image = image
router.sparsemem = self._hypervisor_manager.sparse_memory_support router.sparsemem = self._hypervisor_manager.sparse_memory_support

View File

@ -34,13 +34,14 @@ class C1700(Router):
:param hypervisor: Dynamips hypervisor instance :param hypervisor: Dynamips hypervisor instance
:param name: name for this router :param name: name for this router
:param router_id: router instance ID
:param chassis: chassis for this router: :param chassis: chassis for this router:
1720, 1721, 1750, 1751 or 1760 (default = 1720). 1720, 1721, 1750, 1751 or 1760 (default = 1720).
1710 is not supported. 1710 is not supported.
""" """
def __init__(self, hypervisor, name, chassis="1720"): def __init__(self, hypervisor, name, router_id=None, chassis="1720"):
Router.__init__(self, hypervisor, name, platform="c1700") Router.__init__(self, hypervisor, name, router_id, platform="c1700")
# Set default values for this platform # Set default values for this platform
self._ram = 64 self._ram = 64

View File

@ -36,6 +36,7 @@ class C2600(Router):
:param hypervisor: Dynamips hypervisor instance :param hypervisor: Dynamips hypervisor instance
:param name: name for this router :param name: name for this router
:param router_id: router instance ID
:param chassis: chassis for this router: :param chassis: chassis for this router:
2610, 2611, 2620, 2621, 2610XM, 2611XM 2610, 2611, 2620, 2621, 2610XM, 2611XM
2620XM, 2621XM, 2650XM or 2651XM (default = 2610). 2620XM, 2621XM, 2650XM or 2651XM (default = 2610).
@ -54,8 +55,8 @@ class C2600(Router):
"2650XM": C2600_MB_1FE, "2650XM": C2600_MB_1FE,
"2651XM": C2600_MB_2FE} "2651XM": C2600_MB_2FE}
def __init__(self, hypervisor, name, chassis="2610"): def __init__(self, hypervisor, name, router_id=None, chassis="2610"):
Router.__init__(self, hypervisor, name, platform="c2600") Router.__init__(self, hypervisor, name, router_id, platform="c2600")
# Set default values for this platform # Set default values for this platform
self._ram = 64 self._ram = 64

View File

@ -33,10 +33,11 @@ class C2691(Router):
:param hypervisor: Dynamips hypervisor instance :param hypervisor: Dynamips hypervisor instance
:param name: name for this router :param name: name for this router
:param router_id: router instance ID
""" """
def __init__(self, hypervisor, name): def __init__(self, hypervisor, name, router_id=None):
Router.__init__(self, hypervisor, name, platform="c2691") Router.__init__(self, hypervisor, name, router_id, platform="c2691")
# Set default values for this platform # Set default values for this platform
self._ram = 128 self._ram = 128

View File

@ -33,12 +33,13 @@ class C3600(Router):
:param hypervisor: Dynamips hypervisor instance :param hypervisor: Dynamips hypervisor instance
:param name: name for this router :param name: name for this router
:param router_id: router instance ID
:param chassis: chassis for this router: :param chassis: chassis for this router:
3620, 3640 or 3660 (default = 3640). 3620, 3640 or 3660 (default = 3640).
""" """
def __init__(self, hypervisor, name, chassis="3640"): def __init__(self, hypervisor, name, router_id=None, chassis="3640"):
Router.__init__(self, hypervisor, name, platform="c3600") Router.__init__(self, hypervisor, name, router_id, platform="c3600")
# Set default values for this platform # Set default values for this platform
self._ram = 128 self._ram = 128

View File

@ -33,10 +33,11 @@ class C3725(Router):
:param hypervisor: Dynamips hypervisor instance :param hypervisor: Dynamips hypervisor instance
:param name: name for this router :param name: name for this router
:param router_id: router instance ID
""" """
def __init__(self, hypervisor, name): def __init__(self, hypervisor, name, router_id=None):
Router.__init__(self, hypervisor, name, platform="c3725") Router.__init__(self, hypervisor, name, router_id, platform="c3725")
# Set default values for this platform # Set default values for this platform
self._ram = 128 self._ram = 128

View File

@ -33,10 +33,11 @@ class C3745(Router):
:param hypervisor: Dynamips hypervisor instance :param hypervisor: Dynamips hypervisor instance
:param name: name for this router :param name: name for this router
:param router_id: router instance ID
""" """
def __init__(self, hypervisor, name): def __init__(self, hypervisor, name, router_id=None):
Router.__init__(self, hypervisor, name, platform="c3745") Router.__init__(self, hypervisor, name, router_id, platform="c3745")
# Set default values for this platform # Set default values for this platform
self._ram = 128 self._ram = 128

View File

@ -35,11 +35,12 @@ class C7200(Router):
:param hypervisor: Dynamips hypervisor instance :param hypervisor: Dynamips hypervisor instance
:param name: name for this router :param name: name for this router
:param router_id: router instance ID
:param npe: default NPE :param npe: default NPE
""" """
def __init__(self, hypervisor, name, npe="npe-400"): def __init__(self, hypervisor, name, router_id=None, npe="npe-400"):
Router.__init__(self, hypervisor, name, platform="c7200") Router.__init__(self, hypervisor, name, router_id, platform="c7200")
# Set default values for this platform # Set default values for this platform
self._ram = 256 self._ram = 256

View File

@ -37,6 +37,7 @@ class Router(object):
:param hypervisor: Dynamips hypervisor instance :param hypervisor: Dynamips hypervisor instance
:param name: name for this router :param name: name for this router
:param router_id: router instance ID
:param platform: c7200, c3745, c3725, c3600, c2691, c2600 or c1700 :param platform: c7200, c3745, c3725, c3600, c2691, c2600 or c1700
:param ghost_flag: used when creating a ghost IOS. :param ghost_flag: used when creating a ghost IOS.
""" """
@ -49,20 +50,26 @@ class Router(object):
2: "running", 2: "running",
3: "suspended"} 3: "suspended"}
def __init__(self, hypervisor, name, platform="c7200", ghost_flag=False): def __init__(self, hypervisor, name, router_id=None, platform="c7200", ghost_flag=False):
if not ghost_flag: if not ghost_flag:
# find an instance identifier (0 < id <= 4096) if not router_id:
self._id = 0 # find an instance identifier if none is provided (0 < id <= 4096)
for identifier in range(1, 4097): self._id = 0
if identifier not in self._instances: for identifier in range(1, 4097):
self._id = identifier if identifier not in self._instances:
self._instances.append(self._id) self._id = identifier
break self._instances.append(self._id)
break
if self._id == 0: if self._id == 0:
raise DynamipsError("Maximum number of instances reached") raise DynamipsError("Maximum number of instances reached")
else:
if router_id in self._instances:
raise DynamipsError("Router identifier {} is already used by another router".format(router_id))
self._id = router_id
self._instances.append(self._id)
else: else:
log.info("creating a new ghost IOS file") log.info("creating a new ghost IOS file")

View File

@ -25,6 +25,10 @@ VM_CREATE_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"router_id": {
"description": "VM/router instance ID",
"type": "integer"
},
"platform": { "platform": {
"description": "router platform", "description": "router platform",
"type": "string", "type": "string",

View File

@ -290,12 +290,14 @@ class IOU(IModule):
name = request["name"] name = request["name"]
iou_path = request["path"] iou_path = request["path"]
console = request.get("console") console = request.get("console")
iou_id = request.get("iou_id")
try: try:
iou_instance = IOUDevice(name, iou_instance = IOUDevice(name,
iou_path, iou_path,
self._working_dir, self._working_dir,
self._host, self._host,
iou_id,
console, console,
self._console_start_port_range, self._console_start_port_range,
self._console_end_port_range) self._console_end_port_range)

View File

@ -46,10 +46,11 @@ class IOUDevice(object):
""" """
IOU device implementation. IOU device implementation.
:param name: name of this IOU device
:param path: path to IOU executable :param path: path to IOU executable
:param working_dir: path to a working directory :param working_dir: path to a working directory
:param host: host/address to bind for console and UDP connections :param host: host/address to bind for console and UDP connections
:param name: name of this IOU device :param iou_id: IOU instance ID
:param console: TCP console port :param console: TCP console port
:param console_start_port_range: TCP console port range start :param console_start_port_range: TCP console port range start
:param console_end_port_range: TCP console port range end :param console_end_port_range: TCP console port range end
@ -63,20 +64,27 @@ class IOUDevice(object):
path, path,
working_dir, working_dir,
host="127.0.0.1", host="127.0.0.1",
iou_id = None,
console=None, console=None,
console_start_port_range=4001, console_start_port_range=4001,
console_end_port_range=4512): console_end_port_range=4512):
# find an instance identifier (0 < id <= 512) if not iou_id:
self._id = 0 # find an instance identifier if none is provided (0 < id <= 512)
for identifier in range(1, 513): self._id = 0
if identifier not in self._instances: for identifier in range(1, 513):
self._id = identifier if identifier not in self._instances:
self._instances.append(self._id) self._id = identifier
break self._instances.append(self._id)
break
if self._id == 0: if self._id == 0:
raise IOUError("Maximum number of IOU instances reached") raise IOUError("Maximum number of IOU instances reached")
else:
if iou_id in self._instances:
raise IOUError("IOU identifier {} is already used by another IOU device".format(iou_id))
self._id = iou_id
self._instances.append(self._id)
self._name = name self._name = name
self._path = path self._path = path
@ -106,8 +114,13 @@ class IOUDevice(object):
self._ram = 256 # Megabytes self._ram = 256 # Megabytes
self._l1_keepalives = False # used to overcome the always-up Ethernet interfaces (not supported by all IOSes). self._l1_keepalives = False # used to overcome the always-up Ethernet interfaces (not supported by all IOSes).
working_dir_path = os.path.join(working_dir, "iou", "device-{}".format(self._id))
if iou_id and not os.path.isdir(working_dir_path):
raise IOUError("Working directory {} doesn't exist".format(working_dir_path))
# create the device own working directory # create the device own working directory
self.working_dir = os.path.join(working_dir, "iou", "{}".format(self._name)) self.working_dir = working_dir_path
if not self._console: if not self._console:
# allocate a console port # allocate a console port

View File

@ -26,6 +26,10 @@ IOU_CREATE_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"iou_id": {
"description": "IOU device instance ID",
"type": "integer"
},
"console": { "console": {
"description": "console TCP port", "description": "console TCP port",
"minimum": 1, "minimum": 1,

View File

@ -226,6 +226,7 @@ class VPCS(IModule):
name = request["name"] name = request["name"]
console = request.get("console") console = request.get("console")
vpcs_id = request.get("vpcs_id")
try: try:
@ -236,6 +237,7 @@ class VPCS(IModule):
self._vpcs, self._vpcs,
self._working_dir, self._working_dir,
self._host, self._host,
vpcs_id,
console, console,
self._console_start_port_range, self._console_start_port_range,
self._console_end_port_range) self._console_end_port_range)

View File

@ -26,6 +26,10 @@ VPCS_CREATE_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"vpcs_id": {
"description": "VPCS device instance ID",
"type": "integer"
},
"console": { "console": {
"description": "console TCP port", "description": "console TCP port",
"minimum": 1, "minimum": 1,

View File

@ -40,10 +40,11 @@ class VPCSDevice(object):
""" """
VPCS device implementation. VPCS device implementation.
:param name: name of this VPCS device
:param path: path to VPCS executable :param path: path to VPCS executable
:param working_dir: path to a working directory :param working_dir: path to a working directory
:param host: host/address to bind for console and UDP connections :param host: host/address to bind for console and UDP connections
:param name: name of this VPCS device :param vpcs_id: VPCS instance ID
:param console: TCP console port :param console: TCP console port
:param console_start_port_range: TCP console port range start :param console_start_port_range: TCP console port range start
:param console_end_port_range: TCP console port range end :param console_end_port_range: TCP console port range end
@ -57,22 +58,30 @@ class VPCSDevice(object):
path, path,
working_dir, working_dir,
host="127.0.0.1", host="127.0.0.1",
vpcs_id=None,
console=None, console=None,
console_start_port_range=4512, console_start_port_range=4512,
console_end_port_range=5000): console_end_port_range=5000):
# find an instance identifier (1 <= id <= 255)
# This 255 limit is due to a restriction on the number of possible
# MAC addresses given in VPCS using the -m option
self._id = 0
for identifier in range(1, 256):
if identifier not in self._instances:
self._id = identifier
self._instances.append(self._id)
break
if self._id == 0: if not vpcs_id:
raise VPCSError("Maximum number of VPCS instances reached") # find an instance identifier is none is provided (1 <= id <= 255)
# This 255 limit is due to a restriction on the number of possible
# MAC addresses given in VPCS using the -m option
self._id = 0
for identifier in range(1, 256):
if identifier not in self._instances:
self._id = identifier
self._instances.append(self._id)
break
if self._id == 0:
raise VPCSError("Maximum number of VPCS instances reached")
else:
if vpcs_id in self._instances:
raise VPCSError("VPCS identifier {} is already used by another VPCS device".format(vpcs_id))
self._id = vpcs_id
self._instances.append(self._id)
self._name = name self._name = name
self._path = path self._path = path
@ -91,8 +100,13 @@ class VPCSDevice(object):
self._script_file = "" self._script_file = ""
self._ethernet_adapter = EthernetAdapter() # one adapter with 1 Ethernet interface self._ethernet_adapter = EthernetAdapter() # one adapter with 1 Ethernet interface
working_dir_path = os.path.join(working_dir, "vpcs", "pc-{}".format(self._id))
if vpcs_id and not os.path.isdir(working_dir_path):
raise VPCSError("Working directory {} doesn't exist".format(working_dir_path))
# create the device own working directory # create the device own working directory
self.working_dir = os.path.join(working_dir, "vpcs", "{}".format(name)) self.working_dir = working_dir_path
if not self._console: if not self._console:
# allocate a console port # allocate a console port

View File

@ -23,5 +23,5 @@
# or negative for a release candidate or beta (after the base version # or negative for a release candidate or beta (after the base version
# number has been incremented) # number has been incremented)
__version__ = "1.0a7.dev1" __version__ = "1.0a7.dev2"
__version_info__ = (1, 0, 0, -99) __version_info__ = (1, 0, 0, -99)