Default host binding is 0.0.0.0.

Move the file uploader template.
UDP port allocation (removed the host).
Minor changes with iouyap lookup and remote server project directory.
This commit is contained in:
grossmj 2014-03-29 21:29:10 -06:00
parent f534a02324
commit c91f876656
12 changed files with 53 additions and 36 deletions

View File

@ -21,6 +21,7 @@ Simple file upload & listing handler.
import os import os
import stat
import tornado.web import tornado.web
from ..config import Config from ..config import Config
@ -74,4 +75,6 @@ class FileUploadHandler(tornado.web.RequestHandler):
destination_path = os.path.join(self._upload_dir, fileinfo['filename']) destination_path = os.path.join(self._upload_dir, fileinfo['filename'])
with open(destination_path, 'wb') as f: with open(destination_path, 'wb') as f:
f.write(fileinfo['body']) f.write(fileinfo['body'])
st = os.stat(destination_path)
os.chmod(destination_path, st.st_mode | stat.S_IXUSR)
self.redirect("/upload") self.redirect("/upload")

View File

@ -110,10 +110,11 @@ class Dynamips(IModule):
self._frame_relay_switches = {} self._frame_relay_switches = {}
self._atm_switches = {} self._atm_switches = {}
self._ethernet_hubs = {} 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._tempdir = kwargs["temp_dir"]
self._working_dir = self._projects_dir self._working_dir = self._projects_dir
self._dynamips = "" self._dynamips = ""
self._default_host = "0.0.0.0"
self._callback = self.add_periodic_callback(self._check_hypervisors, 5000) self._callback = self.add_periodic_callback(self._check_hypervisors, 5000)
self._callback.start() self._callback.start()
@ -199,16 +200,18 @@ class Dynamips(IModule):
if not os.access(self._dynamips, os.X_OK): if not os.access(self._dynamips, os.X_OK):
raise DynamipsError("Dynamips {} is not executable".format(self._dynamips)) raise DynamipsError("Dynamips {} is not executable".format(self._dynamips))
# check if the working directory exists
if not os.path.exists(self._working_dir): 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 # check if the working directory is writable
if not os.access(self._working_dir, os.W_OK): if not os.access(self._working_dir, os.W_OK):
raise DynamipsError("Cannot write to working directory {}".format(self._working_dir)) 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)) 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(): for name, value in self._hypervisor_manager_settings.items():
if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value: if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value:
@ -245,7 +248,8 @@ class Dynamips(IModule):
else: else:
self._remote_server = True self._remote_server = True
log.info("this server is remote") 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 self._hypervisor_manager_settings = request
@ -329,8 +333,7 @@ class Dynamips(IModule):
node.id, node.id,
port, port,
host)) host))
response = {"lport": port, response = {"lport": port}
"lhost": host}
return response return response
@ -421,5 +424,8 @@ class Dynamips(IModule):
:param request: JSON request :param request: JSON request
""" """
import netifaces try:
import netifaces
except ImportError:
raise DynamipsError("The netifaces module is not installed")
self.send_response(netifaces.interfaces()) self.send_response(netifaces.interfaces())

View File

@ -141,7 +141,6 @@ class ATMSW(object):
Response parameters: Response parameters:
- port_id (port identifier) - port_id (port identifier)
- lhost (local host address)
- lport (allocated local port) - lport (allocated local port)
:param request: JSON request :param request: JSON request

View File

@ -140,7 +140,6 @@ class ETHHUB(object):
Response parameters: Response parameters:
- port_id (port identifier) - port_id (port identifier)
- lhost (local host address)
- lport (allocated local port) - lport (allocated local port)
:param request: JSON request :param request: JSON request

View File

@ -159,7 +159,6 @@ class ETHSW(object):
Response parameters: Response parameters:
- port_id (port identifier) - port_id (port identifier)
- lhost (local host address)
- lport (allocated local port) - lport (allocated local port)
:param request: JSON request :param request: JSON request

View File

@ -139,7 +139,6 @@ class FRSW(object):
Response parameters: Response parameters:
- port_id (port identifier) - port_id (port identifier)
- lhost (local host address)
- lport (allocated local port) - lport (allocated local port)
:param request: JSON request :param request: JSON request

View File

@ -537,7 +537,6 @@ class VM(object):
Response parameters: Response parameters:
- port_id (unique port identifier) - port_id (unique port identifier)
- lhost (local host address)
- lport (allocated local port) - lport (allocated local port)
:param request: JSON request :param request: JSON request

View File

@ -273,5 +273,5 @@ class Hypervisor(DynamipsHypervisor):
if self._host != '0.0.0.0': if self._host != '0.0.0.0':
command.extend(['-H', self._host + ':' + str(self._port)]) command.extend(['-H', self._host + ':' + str(self._port)])
else: else:
command.extend(['-H', self._port]) command.extend(['-H', str(self._port)])
return command return command

View File

@ -54,13 +54,18 @@ class IOU(IModule):
config = Config.instance() config = Config.instance()
iou_config = config.get_section_config(name.upper()) iou_config = config.get_section_config(name.upper())
self._iouyap = iou_config.get("iouyap") 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): 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!") log.warning("iouyap binary couldn't be found!")
elif not os.access(self._iouyap, os.X_OK): elif not os.access(self._iouyap, os.X_OK):
log.warning("iouyap is not executable") log.warning("iouyap is not executable")
@ -75,8 +80,8 @@ class IOU(IModule):
self._udp_start_port_range = 30001 self._udp_start_port_range = 30001
self._udp_end_port_range = 40001 self._udp_end_port_range = 40001
self._current_udp_port = self._udp_start_port_range self._current_udp_port = self._udp_start_port_range
self._host = "127.0.0.1" # FIXME: used by ZeroMQ... self._default_host = "0.0.0.0"
self._projects_dir = kwargs["projects_dir"] self._projects_dir = os.path.join(kwargs["projects_dir"], "iou")
self._tempdir = kwargs["temp_dir"] self._tempdir = kwargs["temp_dir"]
self._working_dir = self._projects_dir self._working_dir = self._projects_dir
self._iourc = "" self._iourc = ""
@ -146,6 +151,7 @@ class IOU(IModule):
if self._iourc and os.path.exists(self._iourc): if self._iourc and os.path.exists(self._iourc):
try: try:
log.info("deleting iourc file {}".format(self._iourc))
os.remove(self._iourc) os.remove(self._iourc)
except EnvironmentError as e: except EnvironmentError as e:
log.warn("could not delete iourc file {}: {}".format(self._iourc, e)) log.warn("could not delete iourc file {}: {}".format(self._iourc, e))
@ -162,6 +168,7 @@ class IOU(IModule):
Optional request parameters: Optional request parameters:
- working_dir (path to a working directory) - working_dir (path to a working directory)
- project_name
- console_start_port_range - console_start_port_range
- console_end_port_range - console_end_port_range
- udp_start_port_range - udp_start_port_range
@ -196,8 +203,8 @@ class IOU(IModule):
iou_instance.working_dir = self._working_dir iou_instance.working_dir = self._working_dir
else: else:
self._remote_server = True self._remote_server = True
log.info("this server is remote") self._working_dir = os.path.join(self._projects_dir, request["project_name"])
self._working_dir = self._projects_dir 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: if "console_start_port_range" in request and "console_end_port_range" in request:
self._console_start_port_range = request["console_start_port_range"] self._console_start_port_range = request["console_start_port_range"]
@ -233,11 +240,17 @@ class IOU(IModule):
iou_path = request["path"] iou_path = request["path"]
try: 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 # find a console port
if self._current_console_port >= self._console_end_port_range: if self._current_console_port >= self._console_end_port_range:
self._current_console_port = self._console_start_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 self._current_console_port += 1
except IOUError as e: except IOUError as e:
self.send_custom_error(str(e)) self.send_custom_error(str(e))
@ -441,7 +454,6 @@ class IOU(IModule):
Response parameters: Response parameters:
- port_id (unique port identifier) - port_id (unique port identifier)
- lhost (local host address)
- lport (allocated local port) - lport (allocated local port)
:param request: JSON request :param request: JSON request
@ -461,15 +473,14 @@ class IOU(IModule):
# find a UDP port # find a UDP port
if self._current_udp_port >= self._udp_end_port_range: if self._current_udp_port >= self._udp_end_port_range:
self._current_udp_port = self._udp_start_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 self._current_udp_port += 1
log.info("{} [id={}] has allocated UDP port {} with host {}".format(iou_instance .name, log.info("{} [id={}] has allocated UDP port {} with host {}".format(iou_instance .name,
iou_instance .id, iou_instance .id,
port, port,
self._host)) self._default_host))
response = {"lport": port, response = {"lport": port}
"lhost": self._host}
except IOUError as e: except IOUError as e:
self.send_custom_error(str(e)) self.send_custom_error(str(e))

View File

@ -37,7 +37,6 @@ from .config import Config
from .handlers.jsonrpc_websocket import JSONRPCWebSocket from .handlers.jsonrpc_websocket import JSONRPCWebSocket
from .handlers.version_handler import VersionHandler from .handlers.version_handler import VersionHandler
from .handlers.file_upload_handler import FileUploadHandler from .handlers.file_upload_handler import FileUploadHandler
from .module_manager import ModuleManager
from .modules import MODULES from .modules import MODULES
import logging import logging
@ -129,9 +128,11 @@ class Server(object):
router = self._create_zmq_router() router = self._create_zmq_router()
# Add our JSON-RPC Websocket handler to Tornado # Add our JSON-RPC Websocket handler to Tornado
self.handlers.extend([(r"/", JSONRPCWebSocket, dict(zmq_router=router))]) 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: 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) tornado_app.listen(self._port, address=self._host)
except socket.error as e: except socket.error as e:
if e.errno == errno.EADDRINUSE: # socket already in use if e.errno == errno.EADDRINUSE: # socket already in use

View File

@ -15,7 +15,7 @@ File: <input type="file" name="file" />
<h3>Files</h3> <h3>Files</h3>
<ul> <ul>
{%for item in items%} {%for item in items%}
<li>{{path}}{{item}}</a></li> <li>{{path}}/{{item}}</a></li>
{%end%} {%end%}
{%end%} {%end%}
</ul> </ul>

View File

@ -42,7 +42,7 @@ setup(
cmdclass={"test": Tox}, cmdclass={"test": Tox},
author="Jeremy Grossmann", author="Jeremy Grossmann",
author_email="package-maintainer@gns3.net", 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(), long_description=open("README.rst", "r").read(),
install_requires=[ install_requires=[
"tornado >= 2.0", "tornado >= 2.0",
@ -54,6 +54,7 @@ setup(
] ]
}, },
packages=find_packages(), packages=find_packages(),
package_data={"gns3server": ["templates/upload.html"]},
include_package_data=True, include_package_data=True,
platforms="any", platforms="any",
classifiers=[ classifiers=[