From f9ee38dd5593da70c2dbc58a70b12a3588491cba Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 10 Jun 2014 09:33:27 -0600 Subject: [PATCH] Fixes issues to restore the correct working directories for IOU and VPCS devices when loading a project. Prevent multiple clients to use the same server (this is not supported yet). --- gns3server/handlers/jsonrpc_websocket.py | 8 +++++ gns3server/modules/dynamips/nodes/router.py | 2 +- gns3server/modules/iou/__init__.py | 33 +-------------------- gns3server/modules/iou/iou_device.py | 26 +++++++++++----- gns3server/modules/vpcs/__init__.py | 6 ---- gns3server/modules/vpcs/vpcs_device.py | 32 ++++++++++++-------- 6 files changed, 49 insertions(+), 58 deletions(-) diff --git a/gns3server/handlers/jsonrpc_websocket.py b/gns3server/handlers/jsonrpc_websocket.py index fdab3cad..d1db0e14 100644 --- a/gns3server/handlers/jsonrpc_websocket.py +++ b/gns3server/handlers/jsonrpc_websocket.py @@ -27,6 +27,7 @@ from ..jsonrpc import JSONRPCParseError from ..jsonrpc import JSONRPCInvalidRequest from ..jsonrpc import JSONRPCMethodNotFound from ..jsonrpc import JSONRPCNotification +from ..jsonrpc import JSONRPCCustomError import logging log = logging.getLogger(__name__) @@ -142,6 +143,13 @@ class JSONRPCWebSocket(tornado.websocket.WebSocketHandler): if jsonrpc_version != self.version: return self.write_message(JSONRPCInvalidRequest()()) + if len(self.clients) > 1: + #TODO: multiple client support + log.warn("GNS3 server doesn't support multiple clients yet") + return self.write_message(JSONRPCCustomError(-3200, + "There are {} clients connected, the GNS3 server cannot handle multiple clients yet".format(len(self.clients)), + request_id)()) + if method not in self.destinations: if request_id: return self.write_message(JSONRPCMethodNotFound(request_id)()) diff --git a/gns3server/modules/dynamips/nodes/router.py b/gns3server/modules/dynamips/nodes/router.py index bfdc9c28..525c4e36 100644 --- a/gns3server/modules/dynamips/nodes/router.py +++ b/gns3server/modules/dynamips/nodes/router.py @@ -364,7 +364,7 @@ class Router(object): # IOS images must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1 if elf_header_start != b'\x7fELF\x01\x02\x01': - raise DynamipsError("'{}' is not a valid IOU image".format(self._image)) + raise DynamipsError("'{}' is not a valid IOS image".format(self._image)) self._hypervisor.send("vm start {}".format(self._name)) log.info("router {name} [id={id}] has been started".format(name=self._name, id=self._id)) diff --git a/gns3server/modules/iou/__init__.py b/gns3server/modules/iou/__init__.py index 74a3a444..13a3e252 100644 --- a/gns3server/modules/iou/__init__.py +++ b/gns3server/modules/iou/__init__.py @@ -263,30 +263,6 @@ class IOU(IModule): log.debug("received request {}".format(request)) - def test_result(self, message, result="error"): - """ - """ - - return {"result": result, "message": message} - - @IModule.route("iou.test_settings") - def test_settings(self, request): - """ - """ - - response = [] - - # test iourc - if self._iourc == "": - response.append(self.test_result("No iourc file has been added")) - elif not os.path.isfile(self._iourc): - response.append(self.test_result("iourc file {} is not accessible".format(self._iourc))) - else: - #TODO: check hostname + license inside the file - pass - - self.send_response(response) - @IModule.route("iou.create") def iou_create(self, request): """ @@ -312,17 +288,10 @@ class IOU(IModule): return name = request["name"] - console = request.get("console") iou_path = request["path"] + console = request.get("console") try: - try: - os.makedirs(self._working_dir) - except FileExistsError: - pass - except OSError as e: - raise IOUError("Could not create working directory {}".format(e)) - iou_instance = IOUDevice(name, iou_path, self._working_dir, diff --git a/gns3server/modules/iou/iou_device.py b/gns3server/modules/iou/iou_device.py index 42a5cd6c..f465fdfa 100644 --- a/gns3server/modules/iou/iou_device.py +++ b/gns3server/modules/iou/iou_device.py @@ -83,7 +83,7 @@ class IOUDevice(object): self._iourc = "" self._iouyap = "" self._console = console - self._working_dir = working_dir + self._working_dir = None self._command = [] self._process = None self._iouyap_process = None @@ -106,8 +106,8 @@ class IOUDevice(object): self._ram = 256 # Megabytes self._l1_keepalives = False # used to overcome the always-up Ethernet interfaces (not supported by all IOSes). - # update the working directory - self.working_dir = working_dir + # create the device own working directory + self.working_dir = os.path.join(working_dir, "iou", "{}".format(self._name)) if not self._console: # allocate a console port @@ -183,6 +183,18 @@ class IOUDevice(object): :param new_name: name """ + if self._started: + raise IOUError("Cannot change the name to {} while the device is running".format(new_name)) + + new_working_dir = os.path.join(os.path.dirname(self._working_dir), new_name) + try: + shutil.move(self._working_dir, new_working_dir) + self._working_dir = new_working_dir + except OSError as e: + raise IOUError("Could not move working directory from {} to {}: {}".format(self._working_dir, + new_working_dir, + e)) + if self._startup_config: # update the startup-config config_path = os.path.join(self._working_dir, "startup-config") @@ -288,8 +300,6 @@ class IOUDevice(object): :param working_dir: path to the working directory """ - # create our own working directory - working_dir = os.path.join(working_dir, "iou", "device-{}".format(self._id)) try: os.makedirs(working_dir) except FileExistsError: @@ -345,7 +355,8 @@ class IOUDevice(object): """ self.stop() - self._instances.remove(self._id) + if self._id in self._instances: + self._instances.remove(self._id) if self.console: self._allocated_console_ports.remove(self.console) @@ -359,7 +370,8 @@ class IOUDevice(object): """ self.stop() - self._instances.remove(self._id) + if self._id in self._instances: + self._instances.remove(self._id) if self.console: self._allocated_console_ports.remove(self.console) diff --git a/gns3server/modules/vpcs/__init__.py b/gns3server/modules/vpcs/__init__.py index 7140d592..4a0f1a4b 100644 --- a/gns3server/modules/vpcs/__init__.py +++ b/gns3server/modules/vpcs/__init__.py @@ -228,12 +228,6 @@ class VPCS(IModule): console = request.get("console") try: - try: - os.makedirs(self._working_dir) - except FileExistsError: - pass - except OSError as e: - raise VPCSError("Could not create working directory {}".format(e)) if not self._vpcs: raise VPCSError("No path to a VPCS executable has been set") diff --git a/gns3server/modules/vpcs/vpcs_device.py b/gns3server/modules/vpcs/vpcs_device.py index 5cd09489..09152328 100644 --- a/gns3server/modules/vpcs/vpcs_device.py +++ b/gns3server/modules/vpcs/vpcs_device.py @@ -74,14 +74,10 @@ class VPCSDevice(object): if self._id == 0: raise VPCSError("Maximum number of VPCS instances reached") - if name: - self._name = name - else: - self._name = "VPCS{}".format(self._id) - + self._name = name self._path = path self._console = console - self._working_dir = working_dir + self._working_dir = None self._host = host self._command = [] self._process = None @@ -95,8 +91,8 @@ class VPCSDevice(object): self._script_file = "" self._ethernet_adapter = EthernetAdapter() # one adapter with 1 Ethernet interface - # update the working directory - self.working_dir = working_dir + # create the device own working directory + self.working_dir = os.path.join(working_dir, "vpcs", "{}".format(name)) if not self._console: # allocate a console port @@ -165,6 +161,18 @@ class VPCSDevice(object): :param new_name: name """ + if self._started: + raise VPCSError("Cannot change the name to {} while the device is running".format(new_name)) + + new_working_dir = os.path.join(os.path.dirname(self._working_dir), new_name) + try: + shutil.move(self._working_dir, new_working_dir) + self._working_dir = new_working_dir + except OSError as e: + raise VPCSError("Could not move working directory from {} to {}: {}".format(self._working_dir, + new_working_dir, + e)) + if self._script_file: # update the startup.vpc config_path = os.path.join(self._working_dir, "startup.vpc") @@ -224,8 +232,6 @@ class VPCSDevice(object): :param working_dir: path to the working directory """ - # create our own working directory - working_dir = os.path.join(working_dir, "vpcs", "pc-{}".format(self._id)) try: os.makedirs(working_dir) except FileExistsError: @@ -281,7 +287,8 @@ class VPCSDevice(object): """ self.stop() - self._instances.remove(self._id) + if self._id in self._instances: + self._instances.remove(self._id) if self.console: self._allocated_console_ports.remove(self.console) @@ -295,7 +302,8 @@ class VPCSDevice(object): """ self.stop() - self._instances.remove(self._id) + if self._id in self._instances: + self._instances.remove(self._id) if self.console: self._allocated_console_ports.remove(self.console)