diff --git a/gns3server/handlers/file_upload_handler.py b/gns3server/handlers/file_upload_handler.py index 9ab65b97..eb0ceeeb 100644 --- a/gns3server/handlers/file_upload_handler.py +++ b/gns3server/handlers/file_upload_handler.py @@ -21,6 +21,7 @@ Simple file upload & listing handler. import os +import stat import tornado.web from ..config import Config @@ -74,4 +75,6 @@ class FileUploadHandler(tornado.web.RequestHandler): destination_path = os.path.join(self._upload_dir, fileinfo['filename']) with open(destination_path, 'wb') as f: f.write(fileinfo['body']) + st = os.stat(destination_path) + os.chmod(destination_path, st.st_mode | stat.S_IXUSR) self.redirect("/upload") diff --git a/gns3server/modules/dynamips/__init__.py b/gns3server/modules/dynamips/__init__.py index cca2ad02..a3ba093b 100644 --- a/gns3server/modules/dynamips/__init__.py +++ b/gns3server/modules/dynamips/__init__.py @@ -110,10 +110,11 @@ class Dynamips(IModule): self._frame_relay_switches = {} self._atm_switches = {} self._ethernet_hubs = {} - self._projects_dir = kwargs["projects_dir"] + self._projects_dir = os.path.join(kwargs["projects_dir"], "dynamips") self._tempdir = kwargs["temp_dir"] self._working_dir = self._projects_dir self._dynamips = "" + self._default_host = "0.0.0.0" self._callback = self.add_periodic_callback(self._check_hypervisors, 5000) self._callback.start() @@ -199,16 +200,18 @@ class Dynamips(IModule): if not os.access(self._dynamips, os.X_OK): raise DynamipsError("Dynamips {} is not executable".format(self._dynamips)) - # check if the working directory exists if not os.path.exists(self._working_dir): - raise DynamipsError("Working directory {} doesn't exist".format(self._working_dir)) + try: + os.makedirs(self._working_dir) + except EnvironmentError as e: + raise DynamipsError("Could not create working directory {}".format(e)) # check if the working directory is writable if not os.access(self._working_dir, os.W_OK): raise DynamipsError("Cannot write to working directory {}".format(self._working_dir)) log.info("starting the hypervisor manager with Dynamips working directory set to '{}'".format(self._working_dir)) - self._hypervisor_manager = HypervisorManager(self._dynamips, self._working_dir) + self._hypervisor_manager = HypervisorManager(self._dynamips, self._working_dir, self._default_host) for name, value in self._hypervisor_manager_settings.items(): if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value: @@ -245,7 +248,8 @@ class Dynamips(IModule): else: self._remote_server = True log.info("this server is remote") - self._working_dir = self._projects_dir + self._working_dir = os.path.join(self._projects_dir, request["project_name"]) + log.info("this server is remote with working directory path to {}".format(self._working_dir)) self._hypervisor_manager_settings = request @@ -329,8 +333,7 @@ class Dynamips(IModule): node.id, port, host)) - response = {"lport": port, - "lhost": host} + response = {"lport": port} return response @@ -421,5 +424,8 @@ class Dynamips(IModule): :param request: JSON request """ - import netifaces + try: + import netifaces + except ImportError: + raise DynamipsError("The netifaces module is not installed") self.send_response(netifaces.interfaces()) diff --git a/gns3server/modules/dynamips/backends/atmsw.py b/gns3server/modules/dynamips/backends/atmsw.py index b25e3d3d..98469748 100644 --- a/gns3server/modules/dynamips/backends/atmsw.py +++ b/gns3server/modules/dynamips/backends/atmsw.py @@ -141,7 +141,6 @@ class ATMSW(object): Response parameters: - port_id (port identifier) - - lhost (local host address) - lport (allocated local port) :param request: JSON request diff --git a/gns3server/modules/dynamips/backends/ethhub.py b/gns3server/modules/dynamips/backends/ethhub.py index 4d84d97b..60c5d959 100644 --- a/gns3server/modules/dynamips/backends/ethhub.py +++ b/gns3server/modules/dynamips/backends/ethhub.py @@ -140,7 +140,6 @@ class ETHHUB(object): Response parameters: - port_id (port identifier) - - lhost (local host address) - lport (allocated local port) :param request: JSON request diff --git a/gns3server/modules/dynamips/backends/ethsw.py b/gns3server/modules/dynamips/backends/ethsw.py index 5c288369..430b4010 100644 --- a/gns3server/modules/dynamips/backends/ethsw.py +++ b/gns3server/modules/dynamips/backends/ethsw.py @@ -159,7 +159,6 @@ class ETHSW(object): Response parameters: - port_id (port identifier) - - lhost (local host address) - lport (allocated local port) :param request: JSON request diff --git a/gns3server/modules/dynamips/backends/frsw.py b/gns3server/modules/dynamips/backends/frsw.py index 896bc11d..1460e095 100644 --- a/gns3server/modules/dynamips/backends/frsw.py +++ b/gns3server/modules/dynamips/backends/frsw.py @@ -139,7 +139,6 @@ class FRSW(object): Response parameters: - port_id (port identifier) - - lhost (local host address) - lport (allocated local port) :param request: JSON request diff --git a/gns3server/modules/dynamips/backends/vm.py b/gns3server/modules/dynamips/backends/vm.py index df9f57ab..85c47f9e 100644 --- a/gns3server/modules/dynamips/backends/vm.py +++ b/gns3server/modules/dynamips/backends/vm.py @@ -537,7 +537,6 @@ class VM(object): Response parameters: - port_id (unique port identifier) - - lhost (local host address) - lport (allocated local port) :param request: JSON request diff --git a/gns3server/modules/dynamips/hypervisor.py b/gns3server/modules/dynamips/hypervisor.py index fff8532b..eaa9acff 100644 --- a/gns3server/modules/dynamips/hypervisor.py +++ b/gns3server/modules/dynamips/hypervisor.py @@ -273,5 +273,5 @@ class Hypervisor(DynamipsHypervisor): if self._host != '0.0.0.0': command.extend(['-H', self._host + ':' + str(self._port)]) else: - command.extend(['-H', self._port]) + command.extend(['-H', str(self._port)]) return command diff --git a/gns3server/modules/iou/__init__.py b/gns3server/modules/iou/__init__.py index 385105cc..9ab032a1 100644 --- a/gns3server/modules/iou/__init__.py +++ b/gns3server/modules/iou/__init__.py @@ -54,13 +54,18 @@ class IOU(IModule): config = Config.instance() iou_config = config.get_section_config(name.upper()) self._iouyap = iou_config.get("iouyap") - if not self._iouyap: - for path in os.environ["PATH"].split(":"): - if "iouyap" in os.listdir(path) and os.access("iouyap", os.X_OK): - self._iouyap = os.path.join(path, "iouyap") - break - if not self._iouyap or not os.path.exists(self._iouyap): + iouyap_in_cwd = os.path.join(os.getcwd(), "iouyap") + if os.path.exists(iouyap_in_cwd): + self._iouyap = iouyap_in_cwd + else: + # look for iouyap if none is defined or accessible + for path in os.environ["PATH"].split(":"): + if "iouyap" in os.listdir(path) and os.access(os.path.join(path, "iouyap"), os.X_OK): + self._iouyap = os.path.join(path, "iouyap") + break + + if not self._iouyap: log.warning("iouyap binary couldn't be found!") elif not os.access(self._iouyap, os.X_OK): log.warning("iouyap is not executable") @@ -75,8 +80,8 @@ class IOU(IModule): self._udp_start_port_range = 30001 self._udp_end_port_range = 40001 self._current_udp_port = self._udp_start_port_range - self._host = "127.0.0.1" # FIXME: used by ZeroMQ... - self._projects_dir = kwargs["projects_dir"] + self._default_host = "0.0.0.0" + self._projects_dir = os.path.join(kwargs["projects_dir"], "iou") self._tempdir = kwargs["temp_dir"] self._working_dir = self._projects_dir self._iourc = "" @@ -146,6 +151,7 @@ class IOU(IModule): if self._iourc and os.path.exists(self._iourc): try: + log.info("deleting iourc file {}".format(self._iourc)) os.remove(self._iourc) except EnvironmentError as e: log.warn("could not delete iourc file {}: {}".format(self._iourc, e)) @@ -162,6 +168,7 @@ class IOU(IModule): Optional request parameters: - working_dir (path to a working directory) + - project_name - console_start_port_range - console_end_port_range - udp_start_port_range @@ -196,8 +203,8 @@ class IOU(IModule): iou_instance.working_dir = self._working_dir else: self._remote_server = True - log.info("this server is remote") - self._working_dir = self._projects_dir + self._working_dir = os.path.join(self._projects_dir, request["project_name"]) + log.info("this server is remote with working directory path to {}".format(self._working_dir)) if "console_start_port_range" in request and "console_end_port_range" in request: self._console_start_port_range = request["console_start_port_range"] @@ -233,11 +240,17 @@ class IOU(IModule): iou_path = request["path"] try: - iou_instance = IOUDevice(iou_path, self._working_dir, name=name) + if not os.path.exists(self._working_dir): + try: + os.makedirs(self._working_dir) + except EnvironmentError as e: + raise IOUError("Could not create working directory {}".format(e)) + + iou_instance = IOUDevice(iou_path, self._working_dir, host=self._default_host, name=name) # find a console port if self._current_console_port >= self._console_end_port_range: self._current_console_port = self._console_start_port_range - iou_instance.console = IOUDevice.find_unused_port(self._current_console_port, self._console_end_port_range, self._host) + iou_instance.console = IOUDevice.find_unused_port(self._current_console_port, self._console_end_port_range, self._default_host) self._current_console_port += 1 except IOUError as e: self.send_custom_error(str(e)) @@ -441,7 +454,6 @@ class IOU(IModule): Response parameters: - port_id (unique port identifier) - - lhost (local host address) - lport (allocated local port) :param request: JSON request @@ -461,15 +473,14 @@ class IOU(IModule): # find a UDP port if self._current_udp_port >= self._udp_end_port_range: self._current_udp_port = self._udp_start_port_range - port = IOUDevice.find_unused_port(self._current_udp_port, self._udp_end_port_range, host=self._host, socket_type="UDP") + port = IOUDevice.find_unused_port(self._current_udp_port, self._udp_end_port_range, host=self._default_host, socket_type="UDP") self._current_udp_port += 1 log.info("{} [id={}] has allocated UDP port {} with host {}".format(iou_instance .name, iou_instance .id, port, - self._host)) - response = {"lport": port, - "lhost": self._host} + self._default_host)) + response = {"lport": port} except IOUError as e: self.send_custom_error(str(e)) diff --git a/gns3server/server.py b/gns3server/server.py index 73434b02..990fe380 100644 --- a/gns3server/server.py +++ b/gns3server/server.py @@ -37,7 +37,6 @@ from .config import Config from .handlers.jsonrpc_websocket import JSONRPCWebSocket from .handlers.version_handler import VersionHandler from .handlers.file_upload_handler import FileUploadHandler -from .module_manager import ModuleManager from .modules import MODULES import logging @@ -129,9 +128,11 @@ class Server(object): router = self._create_zmq_router() # Add our JSON-RPC Websocket handler to Tornado self.handlers.extend([(r"/", JSONRPCWebSocket, dict(zmq_router=router))]) - tornado_app = tornado.web.Application(self.handlers, debug=True) # FIXME: debug mode! + tornado_app = tornado.web.Application(self.handlers, + template_path=os.path.join(os.path.dirname(__file__), "templates"), + debug=True) # FIXME: debug mode! try: - print("Starting server on port {}".format(self._port)) + print("Starting server on {}:{}".format(self._host, self._port)) tornado_app.listen(self._port, address=self._host) except socket.error as e: if e.errno == errno.EADDRINUSE: # socket already in use diff --git a/gns3server/handlers/upload.html b/gns3server/templates/upload.html similarity index 91% rename from gns3server/handlers/upload.html rename to gns3server/templates/upload.html index d8e534ee..f170e3dd 100644 --- a/gns3server/handlers/upload.html +++ b/gns3server/templates/upload.html @@ -15,7 +15,7 @@ File:

Files

diff --git a/setup.py b/setup.py index ebe534b3..7340df09 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ setup( cmdclass={"test": Tox}, author="Jeremy Grossmann", author_email="package-maintainer@gns3.net", - description="GNS3 server to asynchronously to manage emulators", + description="GNS3 server to asynchronously manage emulators", long_description=open("README.rst", "r").read(), install_requires=[ "tornado >= 2.0", @@ -54,6 +54,7 @@ setup( ] }, packages=find_packages(), + package_data={"gns3server": ["templates/upload.html"]}, include_package_data=True, platforms="any", classifiers=[