mirror of https://github.com/GNS3/gns3-server
parent
c6152c9503
commit
58f93edaf7
@ -1,51 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: UTF-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2013 GNS3 Technologies Inc.
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Python 2.6 and 2.7 compatibility
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import division
|
|
||||||
from __future__ import print_function
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import tornado.ioloop
|
|
||||||
import tornado.web
|
|
||||||
import gns3server
|
|
||||||
from datetime import date
|
|
||||||
|
|
||||||
class MainHandler(tornado.web.RequestHandler):
|
|
||||||
def get(self):
|
|
||||||
self.write("Ready to serve")
|
|
||||||
|
|
||||||
application = tornado.web.Application([
|
|
||||||
(r"/", MainHandler),
|
|
||||||
])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
|
|
||||||
print("GNS3 server version {0}".format(gns3server.__version__))
|
|
||||||
print("Copyright (c) 2007-{0} GNS3 Technologies Inc.".format(date.today().year))
|
|
||||||
|
|
||||||
if sys.version_info < (2, 6):
|
|
||||||
raise RuntimeError("Python 2.6 or higher is required")
|
|
||||||
elif sys.version_info[0] == 3 and sys.version_info < (3, 3):
|
|
||||||
raise RuntimeError("Python 3.3 or higher is required")
|
|
||||||
|
|
||||||
application.listen(8888)
|
|
||||||
tornado.ioloop.IOLoop.instance().start()
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import gns3server
|
||||||
|
import tornado.options
|
||||||
|
|
||||||
|
# command line options
|
||||||
|
from tornado.options import define
|
||||||
|
define("port", default=8000, help="run on the given port", type=int)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
current_year = datetime.date.today().year
|
||||||
|
print("GNS3 server version {}".format(gns3server.__version__))
|
||||||
|
print("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year))
|
||||||
|
|
||||||
|
# we only support Python 2 version >= 2.7 and Python 3 version >= 3.3
|
||||||
|
if sys.version_info < (2, 7):
|
||||||
|
raise RuntimeError("Python 2.7 or higher is required")
|
||||||
|
elif sys.version_info[0] == 3 and sys.version_info < (3, 3):
|
||||||
|
raise RuntimeError("Python 3.3 or higher is required")
|
||||||
|
|
||||||
|
try:
|
||||||
|
tornado.options.parse_command_line()
|
||||||
|
except (tornado.options.Error, ValueError):
|
||||||
|
tornado.options.print_help()
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
#FIXME: log everything for now (excepting DEBUG)
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
server = gns3server.Server()
|
||||||
|
server.load_plugins()
|
||||||
|
server.run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -0,0 +1,87 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import imp
|
||||||
|
import inspect
|
||||||
|
import pkgutil
|
||||||
|
import logging
|
||||||
|
from gns3server.plugins import IPlugin
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(object):
|
||||||
|
"""Plugin representation for the PluginManager
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name, cls):
|
||||||
|
|
||||||
|
self._name = name
|
||||||
|
self._cls = cls
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@name.setter
|
||||||
|
def name(self, new_name):
|
||||||
|
self._name = new_name
|
||||||
|
|
||||||
|
#@property
|
||||||
|
def cls(self):
|
||||||
|
return self._cls
|
||||||
|
|
||||||
|
|
||||||
|
class PluginManager(object):
|
||||||
|
"""Manages plugins
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, plugin_paths=['plugins']):
|
||||||
|
|
||||||
|
self._plugins = []
|
||||||
|
self._plugin_paths = plugin_paths
|
||||||
|
|
||||||
|
def load_plugins(self):
|
||||||
|
|
||||||
|
for _, name, ispkg in pkgutil.iter_modules(self._plugin_paths):
|
||||||
|
if (ispkg):
|
||||||
|
logger.info("analyzing '{}' package".format(name))
|
||||||
|
try:
|
||||||
|
file, pathname, description = imp.find_module(name, self._plugin_paths)
|
||||||
|
plugin_module = imp.load_module(name, file, pathname, description)
|
||||||
|
plugin_classes = inspect.getmembers(plugin_module, inspect.isclass)
|
||||||
|
for plugin_class in plugin_classes:
|
||||||
|
if issubclass(plugin_class[1], IPlugin):
|
||||||
|
# don't instantiate any parent plugins
|
||||||
|
if plugin_class[1].__module__ == name:
|
||||||
|
logger.info("loading '{}' plugin".format(plugin_class[0]))
|
||||||
|
info = Plugin(name=plugin_class[0], cls=plugin_class[1])
|
||||||
|
self._plugins.append(info)
|
||||||
|
finally:
|
||||||
|
if file:
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
def get_all_plugins(self):
|
||||||
|
return self._plugins
|
||||||
|
|
||||||
|
def activate_plugin(self, plugin):
|
||||||
|
|
||||||
|
plugin_class = plugin.cls()
|
||||||
|
plugin_instance = plugin_class()
|
||||||
|
logger.info("'{}' plugin activated".format(plugin.name))
|
||||||
|
return plugin_instance
|
@ -0,0 +1,18 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from gns3server.plugins.base import IPlugin
|
@ -0,0 +1,30 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
class IPlugin(object):
|
||||||
|
"""Plugin interface
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
"""Called before the plugin is asked to do anything
|
||||||
|
"""
|
||||||
|
|
||||||
|
raise NotImplementedError()
|
@ -0,0 +1,42 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import tornado.web
|
||||||
|
from gns3server.plugins import IPlugin
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class TestHandler(tornado.web.RequestHandler):
|
||||||
|
def get(self):
|
||||||
|
self.write("This is my test handler")
|
||||||
|
|
||||||
|
|
||||||
|
class Dynamips(IPlugin):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
IPlugin.__init__(self)
|
||||||
|
logger.info("Dynamips plugin is initializing")
|
||||||
|
|
||||||
|
def handlers(self):
|
||||||
|
"""Returns tornado web request handlers that the plugin manages
|
||||||
|
|
||||||
|
:returns: List of tornado.web.RequestHandler
|
||||||
|
"""
|
||||||
|
|
||||||
|
return [(r"/test", TestHandler)]
|
@ -0,0 +1,80 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 GNS3 Technologies Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import socket
|
||||||
|
import tornado.ioloop
|
||||||
|
import tornado.web
|
||||||
|
import gns3server
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class MainHandler(tornado.web.RequestHandler):
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
self.write("Welcome to the GNS3 server!")
|
||||||
|
|
||||||
|
|
||||||
|
class VersionHandler(tornado.web.RequestHandler):
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
response = {'version': gns3server.__version__}
|
||||||
|
self.write(response)
|
||||||
|
|
||||||
|
|
||||||
|
class Server(object):
|
||||||
|
|
||||||
|
# built-in handlers
|
||||||
|
handlers = [(r"/", MainHandler),
|
||||||
|
(r"/version", VersionHandler)]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self._plugins = []
|
||||||
|
|
||||||
|
def load_plugins(self):
|
||||||
|
"""Loads the plugins
|
||||||
|
"""
|
||||||
|
|
||||||
|
plugin_manager = gns3server.PluginManager()
|
||||||
|
plugin_manager.load_plugins()
|
||||||
|
for plugin in plugin_manager.get_all_plugins():
|
||||||
|
instance = plugin_manager.activate_plugin(plugin)
|
||||||
|
self._plugins.append(instance)
|
||||||
|
plugin_handlers = instance.handlers()
|
||||||
|
self.handlers.extend(plugin_handlers)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Starts the tornado web server
|
||||||
|
"""
|
||||||
|
|
||||||
|
from tornado.options import options
|
||||||
|
tornado_app = tornado.web.Application(self.handlers)
|
||||||
|
try:
|
||||||
|
port = options.port
|
||||||
|
print("Starting server on port {}".format(port))
|
||||||
|
tornado_app.listen(port)
|
||||||
|
except socket.error as e:
|
||||||
|
if e.errno is 48: # socket already in use
|
||||||
|
logging.critical("socket in use for port {}".format(port))
|
||||||
|
raise SystemExit
|
||||||
|
try:
|
||||||
|
tornado.ioloop.IOLoop.instance().start()
|
||||||
|
except (KeyboardInterrupt, SystemExit):
|
||||||
|
print("\nExiting...")
|
||||||
|
tornado.ioloop.IOLoop.instance().stop()
|
@ -1,5 +1,3 @@
|
|||||||
Yapsy==1.10.2-pythons2n3
|
tornado
|
||||||
astroid==1.0.0
|
jsonschema
|
||||||
logilab-common==0.60.0
|
networkx
|
||||||
networkx==1.8.1
|
|
||||||
tornado==3.1.1
|
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
from tornado.testing import AsyncHTTPTestCase
|
||||||
|
from gns3server.server import VersionHandler
|
||||||
|
from gns3server._compat import urlencode
|
||||||
|
import tornado.web
|
||||||
|
import json
|
||||||
|
|
||||||
|
# URL to test
|
||||||
|
URL = "/version"
|
||||||
|
|
||||||
|
|
||||||
|
class TestVersionHandler(AsyncHTTPTestCase):
|
||||||
|
|
||||||
|
def get_app(self):
|
||||||
|
return tornado.web.Application([(URL, VersionHandler)])
|
||||||
|
|
||||||
|
def test_endpoint(self):
|
||||||
|
self.http_client.fetch(self.get_url(URL), self.stop)
|
||||||
|
response = self.wait()
|
||||||
|
assert response.code == 200
|
||||||
|
|
||||||
|
# def test_post(self):
|
||||||
|
# data = urlencode({'test': 'works'})
|
||||||
|
# req = tornado.httpclient.HTTPRequest(self.get_url(URL),
|
||||||
|
# method='POST',
|
||||||
|
# body=data)
|
||||||
|
# self.http_client.fetch(req, self.stop)
|
||||||
|
# response = self.wait()
|
||||||
|
# assert response.code == 200
|
||||||
|
#
|
||||||
|
# def test_endpoint_differently(self):
|
||||||
|
# self.http_client.fetch(self.get_url(URL), self.stop)
|
||||||
|
# response = self.wait()
|
||||||
|
# assert(response.headers['Content-Type'].startswith('application/json'))
|
||||||
|
# assert(response.body != "")
|
||||||
|
# body = json.loads(response.body.decode('utf-8'))
|
||||||
|
# assert body['version'] == "0.1.dev"
|
||||||
|
|
Loading…
Reference in new issue