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

Some cleaning + move "/version" endpoint to "/server/version".

This commit is contained in:
grossmj 2016-06-01 17:50:31 -06:00
parent 87f15eafe0
commit cd07a99118
18 changed files with 70 additions and 187 deletions

View File

@ -37,7 +37,7 @@ from .project_manager import ProjectManager
from .nios.nio_udp import NIOUDP from .nios.nio_udp import NIOUDP
from .nios.nio_tap import NIOTAP from .nios.nio_tap import NIOTAP
from .nios.nio_generic_ethernet import NIOGenericEthernet from .nios.nio_ethernet import NIOEthernet
from ..utils.images import md5sum, remove_checksum from ..utils.images import md5sum, remove_checksum
from .node_error import NodeError from .node_error import NodeError
@ -317,8 +317,7 @@ class BaseManager:
@staticmethod @staticmethod
def has_privileged_access(executable): def has_privileged_access(executable):
""" """
Check if an executable can access Ethernet and TAP devices in Check if an executable have the right to attach to Ethernet and TAP adapters.
RAW mode.
:param executable: executable path :param executable: executable path
@ -382,11 +381,11 @@ class BaseManager:
# if not self.has_privileged_access(executable): # if not self.has_privileged_access(executable):
# raise aiohttp.web.HTTPForbidden(text="{} has no privileged access to {}.".format(executable, tap_device)) # raise aiohttp.web.HTTPForbidden(text="{} has no privileged access to {}.".format(executable, tap_device))
nio = NIOTAP(tap_device) nio = NIOTAP(tap_device)
elif nio_settings["type"] == "nio_generic_ethernet": elif nio_settings["type"] in ("nio_generic_ethernet", "nio_ethernet"):
ethernet_device = nio_settings["ethernet_device"] ethernet_device = nio_settings["ethernet_device"]
if not is_interface_up(ethernet_device): if not is_interface_up(ethernet_device):
raise aiohttp.web.HTTPConflict(text="Ethernet interface {} does not exist or is down".format(ethernet_device)) raise aiohttp.web.HTTPConflict(text="Ethernet interface {} does not exist or is down".format(ethernet_device))
nio = NIOGenericEthernet(ethernet_device) nio = NIOEthernet(ethernet_device)
assert nio is not None assert nio is not None
return nio return nio

View File

@ -142,7 +142,7 @@ class Cloud(BaseNode):
if port_info["type"] in ("ethernet", "tap"): if port_info["type"] in ("ethernet", "tap"):
network_interfaces = [interface["name"] for interface in interfaces()] network_interfaces = [interface["name"] for interface in interfaces()]
if not port_info["interface"] in network_interfaces: if not port_info["interface"] in network_interfaces:
raise NodeError("Interface {} could not be found on this system".format(port_info["interface"])) raise NodeError("Interface '{}' could not be found on this system".format(port_info["interface"]))
if sys.platform.startswith("win"): if sys.platform.startswith("win"):
windows_interfaces = interfaces() windows_interfaces = interfaces()

View File

@ -41,7 +41,7 @@ from ..adapters.ethernet_adapter import EthernetAdapter
from ..adapters.serial_adapter import SerialAdapter from ..adapters.serial_adapter import SerialAdapter
from ..nios.nio_udp import NIOUDP from ..nios.nio_udp import NIOUDP
from ..nios.nio_tap import NIOTAP from ..nios.nio_tap import NIOTAP
from ..nios.nio_generic_ethernet import NIOGenericEthernet from ..nios.nio_ethernet import NIOEthernet
from ..base_node import BaseNode from ..base_node import BaseNode
from .utils.iou_import import nvram_import from .utils.iou_import import nvram_import
from .utils.iou_export import nvram_export from .utils.iou_export import nvram_export
@ -610,7 +610,7 @@ class IOUVM(BaseNode):
# TAP interface # TAP interface
connection = {"tap_dev": "{tap_device}".format(tap_device=nio.tap_device)} connection = {"tap_dev": "{tap_device}".format(tap_device=nio.tap_device)}
elif isinstance(nio, NIOGenericEthernet): elif isinstance(nio, NIOEthernet):
# Ethernet interface # Ethernet interface
connection = {"eth_dev": "{ethernet_device}".format(ethernet_device=nio.ethernet_device)} connection = {"eth_dev": "{ethernet_device}".format(ethernet_device=nio.ethernet_device)}

View File

@ -16,13 +16,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
Interface for generic Ethernet NIOs (PCAP library). Interface for Ethernet NIOs.
""" """
from .nio import NIO from .nio import NIO
class NIOGenericEthernet(NIO): class NIOEthernet(NIO):
""" """
Generic Ethernet NIO. Generic Ethernet NIO.
@ -51,5 +51,5 @@ class NIOGenericEthernet(NIO):
def __json__(self): def __json__(self):
return {"type": "nio_generic_ethernet", return {"type": "nio_ethernet",
"ethernet_device": self._ethernet_device} "ethernet_device": self._ethernet_device}

View File

@ -1,41 +0,0 @@
# -*- 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/>.
"""
Interface for NAT NIOs.
"""
from .nio import NIO
class NIONAT(NIO):
"""
NAT NIO.
"""
def __init__(self):
super().__init__()
def __str__(self):
return "NIO TAP"
def __json__(self):
return {"type": "nio_nat"}

View File

@ -135,7 +135,7 @@ class PortManager:
return self._used_udp_ports return self._used_udp_ports
@staticmethod @staticmethod
def find_unused_port(start_port, end_port, host="127.0.0.1", socket_type="TCP", ignore_ports=[]): def find_unused_port(start_port, end_port, host="127.0.0.1", socket_type="TCP", ignore_ports=None):
""" """
Finds an unused port in a range. Finds an unused port in a range.
@ -151,7 +151,7 @@ class PortManager:
last_exception = None last_exception = None
for port in range(start_port, end_port + 1): for port in range(start_port, end_port + 1):
if port in ignore_ports or port in BANNED_PORTS: if ignore_ports and (port in ignore_ports or port in BANNED_PORTS):
continue continue
try: try:

View File

@ -369,7 +369,7 @@ class Project:
""" """
files = [] files = []
for (dirpath, dirnames, filenames) in os.walk(self.path): for dirpath, dirnames, filenames in os.walk(self.path):
for filename in filenames: for filename in filenames:
if not filename.endswith(".ghost"): if not filename.endswith(".ghost"):
path = os.path.relpath(dirpath, self.path) path = os.path.relpath(dirpath, self.path)

View File

@ -31,7 +31,7 @@ class Qcow2:
def __init__(self, path): def __init__(self, path):
self.path = path self._path = path
self._reload() self._reload()
def _reload(self): def _reload(self):
@ -57,15 +57,14 @@ class Qcow2:
# uint32_t nb_snapshots; # uint32_t nb_snapshots;
# uint64_t snapshots_offset; # uint64_t snapshots_offset;
# } QCowHeader; # } QCowHeader;
struct_format = ">IIQi" struct_format = ">IIQi"
with open(self._path, 'rb') as f:
with open(self.path, 'rb') as f:
content = f.read(struct.calcsize(struct_format)) content = f.read(struct.calcsize(struct_format))
self.magic, self.version, self.backing_file_offset, self.backing_file_size = struct.unpack_from(struct_format, content) self.magic, self.version, self.backing_file_offset, self.backing_file_size = struct.unpack_from(struct_format, content)
if self.magic != 1363560955: # The first 4 bytes contain the characters 'Q', 'F', 'I' followed by 0xfb. if self.magic != 1363560955: # The first 4 bytes contain the characters 'Q', 'F', 'I' followed by 0xfb.
raise Qcow2Error("Invalid magic for {}".format(self.path)) raise Qcow2Error("Invalid magic for {}".format(self._path))
@property @property
def backing_file(self): def backing_file(self):
@ -74,9 +73,11 @@ class Qcow2:
:returns: None if it's not a linked clone, the path otherwise :returns: None if it's not a linked clone, the path otherwise
""" """
with open(self.path, 'rb') as f:
with open(self._path, 'rb') as f:
f.seek(self.backing_file_offset) f.seek(self.backing_file_offset)
content = f.read(self.backing_file_size) content = f.read(self.backing_file_size)
path = content.decode() path = content.decode()
if len(path) == 0: if len(path) == 0:
return None return None
@ -90,9 +91,10 @@ class Qcow2:
:param qemu_img: Path to the qemu-img binary :param qemu_img: Path to the qemu-img binary
:param base_image: Path to the base image :param base_image: Path to the base image
""" """
if not os.path.exists(base_image): if not os.path.exists(base_image):
raise FileNotFoundError(base_image) raise FileNotFoundError(base_image)
command = [qemu_img, "rebase", "-u", "-b", base_image, self.path] command = [qemu_img, "rebase", "-u", "-b", base_image, self._path]
process = yield from asyncio.create_subprocess_exec(*command) process = yield from asyncio.create_subprocess_exec(*command)
retcode = yield from process.wait() retcode = yield from process.wait()
if retcode != 0: if retcode != 0:

View File

@ -1,53 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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/>.
"""
Interface for VMnet NIOs.
"""
from ..nios.nio import NIO
class NIOVMNET(NIO):
"""
VMnet NIO.
"""
def __init__(self, vmnet):
super().__init__()
self._vmnet = vmnet
@property
def vmnet(self):
"""
Returns vmnet interface used by this NIO.
:returns: vmnet interface name
"""
return self._vmnet
def __str__(self):
return "NIO VMNET"
def __json__(self):
return {"type": "nio_vmnet",
"vmnet": self._vmnet}

View File

@ -60,8 +60,7 @@ class Compute:
self._version = None self._version = None
self.name = name self.name = name
# If the compute is local but the compute id is local # It's a configuration issue if the compute is not configured to be local but the compute id is local
# it's a configuration issue
if compute_id == "local" and Config.instance().get_section_config("Server")["local"] is False: if compute_id == "local" and Config.instance().get_section_config("Server")["local"] is False:
raise ComputeError("The local compute is started without --local") raise ComputeError("The local compute is started without --local")
@ -183,7 +182,7 @@ class Compute:
def password(self): def password(self):
return self._password return self._password
@user.setter @password.setter
def password(self, value): def password(self, value):
self._set_auth(self._user, value) self._set_auth(self._user, value)
@ -229,7 +228,7 @@ class Compute:
Check if remote server is accessible Check if remote server is accessible
""" """
if not self._connected: if not self._connected:
response = yield from self._run_http_query("GET", "/version") response = yield from self._run_http_query("GET", "/server/version")
if "version" not in response.json: if "version" not in response.json:
raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server".format(self._id)) raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server".format(self._id))

View File

@ -228,7 +228,7 @@ class IOUHandler:
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
nio_type = request.json["type"] nio_type = request.json["type"]
if nio_type not in ("nio_udp", "nio_tap", "nio_generic_ethernet"): if nio_type not in ("nio_udp", "nio_tap", "nio_ethernet", "nio_generic_ethernet"):
raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
nio = iou_manager.create_nio(vm.iouyap_path, request.json) nio = iou_manager.create_nio(vm.iouyap_path, request.json)
yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"]), nio) yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"]), nio)

View File

@ -25,7 +25,7 @@ from aiohttp.web import HTTPConflict
class VersionHandler: class VersionHandler:
@Route.get( @Route.get(
r"/version", r"/server/version",
description="Retrieve the server version number", description="Retrieve the server version number",
output=VERSION_SCHEMA) output=VERSION_SCHEMA)
def version(request, response): def version(request, response):
@ -35,7 +35,7 @@ class VersionHandler:
response.json({"version": __version__, "local": local_server}) response.json({"version": __version__, "local": local_server})
@Route.post( @Route.post(
r"/version", r"/server/version",
description="Check if version is the same as the server", description="Check if version is the same as the server",
output=VERSION_SCHEMA, output=VERSION_SCHEMA,
input=VERSION_SCHEMA, input=VERSION_SCHEMA,

View File

@ -17,7 +17,6 @@
from .compute_handler import ComputeHandler from .compute_handler import ComputeHandler
from .project_handler import ProjectHandler from .project_handler import ProjectHandler
from .version_handler import VersionHandler
from .node_handler import NodeHandler from .node_handler import NodeHandler
from .link_handler import LinkHandler from .link_handler import LinkHandler
from .server_handler import ServerHandler from .server_handler import ServerHandler

View File

@ -15,15 +15,15 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import asyncio
from aiohttp.web import HTTPForbidden
from gns3server.web.route import Route from gns3server.web.route import Route
from gns3server.config import Config
from gns3server.compute.project_manager import ProjectManager
from gns3server.schemas.compute import COMPUTE_CREATE_SCHEMA, COMPUTE_OBJECT_SCHEMA, COMPUTE_UPDATE_SCHEMA
from gns3server.controller import Controller from gns3server.controller import Controller
from gns3server.schemas.compute import (
COMPUTE_CREATE_SCHEMA,
COMPUTE_OBJECT_SCHEMA,
COMPUTE_UPDATE_SCHEMA
)
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -47,7 +47,7 @@ class ComputeHandler:
@Route.get( @Route.get(
r"/computes", r"/computes",
description="List of compute server", description="List of compute servers",
status_codes={ status_codes={
200: "Compute servers list returned" 200: "Compute servers list returned"
}) })

View File

@ -15,10 +15,13 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from ....web.route import Route from gns3server.web.route import Route
from ....config import Config from gns3server.config import Config
from ....controller import Controller from gns3server.controller import Controller
from aiohttp.web import HTTPForbidden from gns3server.schemas.version import VERSION_SCHEMA
from gns3server.version import __version__
from aiohttp.web import HTTPConflict, HTTPForbidden
import asyncio import asyncio
import logging import logging
@ -42,9 +45,9 @@ class ServerHandler:
if config.get_section_config("Server").getboolean("local", False) is False: if config.get_section_config("Server").getboolean("local", False) is False:
raise HTTPForbidden(text="You can only stop a local server") raise HTTPForbidden(text="You can only stop a local server")
log.info("Start shuting down the server") log.info("Start shutting down the server")
# close all the projets first # close all the projects first
controller = Controller.instance() controller = Controller.instance()
projects = controller.projects projects = controller.projects
@ -66,3 +69,27 @@ class ServerHandler:
server = WebServer.instance() server = WebServer.instance()
asyncio.async(server.shutdown_server()) asyncio.async(server.shutdown_server())
response.set_status(201) response.set_status(201)
@Route.get(
r"/server/version",
description="Retrieve the server version number",
output=VERSION_SCHEMA)
def version(request, response):
config = Config.instance()
local_server = config.get_section_config("Server").getboolean("local", False)
response.json({"version": __version__, "local": local_server})
@Route.post(
r"/server/version",
description="Check if version is the same as the server",
output=VERSION_SCHEMA,
input=VERSION_SCHEMA,
status_codes={
200: "Same version",
409: "Invalid version"
})
def check_version(request, response):
if request.json["version"] != __version__:
raise HTTPConflict(text="Client version {} differs with server version {}".format(request.json["version"], __version__))
response.json({"version": __version__})

View File

@ -1,49 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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.web.route import Route
from gns3server.config import Config
from gns3server.schemas.version import VERSION_SCHEMA
from gns3server.version import __version__
from aiohttp.web import HTTPConflict
class VersionHandler:
@Route.get(
r"/version",
description="Retrieve the server version number",
output=VERSION_SCHEMA)
def version(request, response):
config = Config.instance()
local_server = config.get_section_config("Server").getboolean("local", False)
response.json({"version": __version__, "local": local_server})
@Route.post(
r"/version",
description="Check if version is the same as the server",
output=VERSION_SCHEMA,
input=VERSION_SCHEMA,
status_codes={
200: "Same version",
409: "Invalid version"
})
def check_version(request, response):
if request.json["version"] != __version__:
raise HTTPConflict(text="Client version {} differs with server version {}".format(request.json["version"], __version__))
response.json({"version": __version__})

View File

@ -52,7 +52,7 @@ NIO_SCHEMA = {
"description": "Generic Ethernet Network Input/Output", "description": "Generic Ethernet Network Input/Output",
"properties": { "properties": {
"type": { "type": {
"enum": ["nio_generic_ethernet"] "enum": ["nio_generic_ethernet", "nio_ethernet"]
}, },
"ethernet_device": { "ethernet_device": {
"description": "Ethernet device name e.g. eth0", "description": "Ethernet device name e.g. eth0",

View File

@ -143,7 +143,7 @@ class Hypervisor(UBridgeHypervisor):
yield from self._check_ubridge_version() yield from self._check_ubridge_version()
env = os.environ.copy() env = os.environ.copy()
if sys.platform.startswith("win"): if sys.platform.startswith("win"):
# add the Npcap directory to $PATH to force Dynamips to use npcap DLL instead of Winpcap (if installed) # add the Npcap directory to $PATH to force uBridge to use npcap DLL instead of Winpcap (if installed)
system_root = os.path.join(os.path.expandvars("%SystemRoot%"), "System32", "Npcap") system_root = os.path.join(os.path.expandvars("%SystemRoot%"), "System32", "Npcap")
if os.path.isdir(system_root): if os.path.isdir(system_root):
env["PATH"] = system_root + ';' + env["PATH"] env["PATH"] = system_root + ';' + env["PATH"]