From cd07a99118ca1b9c266382497ba450d42e95a8d0 Mon Sep 17 00:00:00 2001 From: grossmj Date: Wed, 1 Jun 2016 17:50:31 -0600 Subject: [PATCH] Some cleaning + move "/version" endpoint to "/server/version". --- gns3server/compute/base_manager.py | 9 ++-- gns3server/compute/builtin/nodes/cloud.py | 2 +- gns3server/compute/iou/iou_vm.py | 4 +- ...io_generic_ethernet.py => nio_ethernet.py} | 6 +-- gns3server/compute/nios/nio_nat.py | 41 -------------- gns3server/compute/port_manager.py | 4 +- gns3server/compute/project.py | 2 +- gns3server/compute/qemu/qcow2.py | 16 +++--- gns3server/compute/vmware/nio_vmnet.py | 53 ------------------- gns3server/controller/compute.py | 7 ++- .../handlers/api/compute/iou_handler.py | 2 +- .../handlers/api/compute/version_handler.py | 4 +- .../handlers/api/controller/__init__.py | 1 - .../api/controller/compute_handler.py | 14 ++--- .../handlers/api/controller/server_handler.py | 39 +++++++++++--- .../api/controller/version_handler.py | 49 ----------------- gns3server/schemas/nio.py | 2 +- gns3server/ubridge/hypervisor.py | 2 +- 18 files changed, 70 insertions(+), 187 deletions(-) rename gns3server/compute/nios/{nio_generic_ethernet.py => nio_ethernet.py} (90%) delete mode 100644 gns3server/compute/nios/nio_nat.py delete mode 100644 gns3server/compute/vmware/nio_vmnet.py delete mode 100644 gns3server/handlers/api/controller/version_handler.py diff --git a/gns3server/compute/base_manager.py b/gns3server/compute/base_manager.py index 2f5e4356..63685bd3 100644 --- a/gns3server/compute/base_manager.py +++ b/gns3server/compute/base_manager.py @@ -37,7 +37,7 @@ from .project_manager import ProjectManager from .nios.nio_udp import NIOUDP 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 .node_error import NodeError @@ -317,8 +317,7 @@ class BaseManager: @staticmethod def has_privileged_access(executable): """ - Check if an executable can access Ethernet and TAP devices in - RAW mode. + Check if an executable have the right to attach to Ethernet and TAP adapters. :param executable: executable path @@ -382,11 +381,11 @@ class BaseManager: # if not self.has_privileged_access(executable): # raise aiohttp.web.HTTPForbidden(text="{} has no privileged access to {}.".format(executable, 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"] if not is_interface_up(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 return nio diff --git a/gns3server/compute/builtin/nodes/cloud.py b/gns3server/compute/builtin/nodes/cloud.py index 31df3e01..20f8a9ac 100644 --- a/gns3server/compute/builtin/nodes/cloud.py +++ b/gns3server/compute/builtin/nodes/cloud.py @@ -142,7 +142,7 @@ class Cloud(BaseNode): if port_info["type"] in ("ethernet", "tap"): network_interfaces = [interface["name"] for interface in 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"): windows_interfaces = interfaces() diff --git a/gns3server/compute/iou/iou_vm.py b/gns3server/compute/iou/iou_vm.py index 8d07ac33..a5192052 100644 --- a/gns3server/compute/iou/iou_vm.py +++ b/gns3server/compute/iou/iou_vm.py @@ -41,7 +41,7 @@ from ..adapters.ethernet_adapter import EthernetAdapter from ..adapters.serial_adapter import SerialAdapter from ..nios.nio_udp import NIOUDP 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 .utils.iou_import import nvram_import from .utils.iou_export import nvram_export @@ -610,7 +610,7 @@ class IOUVM(BaseNode): # TAP interface connection = {"tap_dev": "{tap_device}".format(tap_device=nio.tap_device)} - elif isinstance(nio, NIOGenericEthernet): + elif isinstance(nio, NIOEthernet): # Ethernet interface connection = {"eth_dev": "{ethernet_device}".format(ethernet_device=nio.ethernet_device)} diff --git a/gns3server/compute/nios/nio_generic_ethernet.py b/gns3server/compute/nios/nio_ethernet.py similarity index 90% rename from gns3server/compute/nios/nio_generic_ethernet.py rename to gns3server/compute/nios/nio_ethernet.py index fee02d1a..a9604424 100644 --- a/gns3server/compute/nios/nio_generic_ethernet.py +++ b/gns3server/compute/nios/nio_ethernet.py @@ -16,13 +16,13 @@ # along with this program. If not, see . """ -Interface for generic Ethernet NIOs (PCAP library). +Interface for Ethernet NIOs. """ from .nio import NIO -class NIOGenericEthernet(NIO): +class NIOEthernet(NIO): """ Generic Ethernet NIO. @@ -51,5 +51,5 @@ class NIOGenericEthernet(NIO): def __json__(self): - return {"type": "nio_generic_ethernet", + return {"type": "nio_ethernet", "ethernet_device": self._ethernet_device} diff --git a/gns3server/compute/nios/nio_nat.py b/gns3server/compute/nios/nio_nat.py deleted file mode 100644 index 3293b8b8..00000000 --- a/gns3server/compute/nios/nio_nat.py +++ /dev/null @@ -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 . - -""" -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"} diff --git a/gns3server/compute/port_manager.py b/gns3server/compute/port_manager.py index 5283c0f4..375a90c3 100644 --- a/gns3server/compute/port_manager.py +++ b/gns3server/compute/port_manager.py @@ -135,7 +135,7 @@ class PortManager: return self._used_udp_ports @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. @@ -151,7 +151,7 @@ class PortManager: last_exception = None 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 try: diff --git a/gns3server/compute/project.py b/gns3server/compute/project.py index ef1f48c7..6483edfb 100644 --- a/gns3server/compute/project.py +++ b/gns3server/compute/project.py @@ -369,7 +369,7 @@ class Project: """ files = [] - for (dirpath, dirnames, filenames) in os.walk(self.path): + for dirpath, dirnames, filenames in os.walk(self.path): for filename in filenames: if not filename.endswith(".ghost"): path = os.path.relpath(dirpath, self.path) diff --git a/gns3server/compute/qemu/qcow2.py b/gns3server/compute/qemu/qcow2.py index 563d5120..cb7ab899 100644 --- a/gns3server/compute/qemu/qcow2.py +++ b/gns3server/compute/qemu/qcow2.py @@ -31,7 +31,7 @@ class Qcow2: def __init__(self, path): - self.path = path + self._path = path self._reload() def _reload(self): @@ -57,15 +57,14 @@ class Qcow2: # uint32_t nb_snapshots; # uint64_t snapshots_offset; # } QCowHeader; + struct_format = ">IIQi" - - with open(self.path, 'rb') as f: + with open(self._path, 'rb') as f: 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) 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 def backing_file(self): @@ -74,9 +73,11 @@ class Qcow2: :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) content = f.read(self.backing_file_size) + path = content.decode() if len(path) == 0: return None @@ -90,9 +91,10 @@ class Qcow2: :param qemu_img: Path to the qemu-img binary :param base_image: Path to the base image """ + if not os.path.exists(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) retcode = yield from process.wait() if retcode != 0: diff --git a/gns3server/compute/vmware/nio_vmnet.py b/gns3server/compute/vmware/nio_vmnet.py deleted file mode 100644 index 13e2c211..00000000 --- a/gns3server/compute/vmware/nio_vmnet.py +++ /dev/null @@ -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 . - -""" -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} diff --git a/gns3server/controller/compute.py b/gns3server/controller/compute.py index 894f03ab..5e78780b 100644 --- a/gns3server/controller/compute.py +++ b/gns3server/controller/compute.py @@ -60,8 +60,7 @@ class Compute: self._version = None self.name = name - # If the compute is local but the compute id is local - # it's a configuration issue + # It's a configuration issue if the compute is not configured to be local but the compute id is local if compute_id == "local" and Config.instance().get_section_config("Server")["local"] is False: raise ComputeError("The local compute is started without --local") @@ -183,7 +182,7 @@ class Compute: def password(self): return self._password - @user.setter + @password.setter def password(self, value): self._set_auth(self._user, value) @@ -229,7 +228,7 @@ class Compute: Check if remote server is accessible """ 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: raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server".format(self._id)) diff --git a/gns3server/handlers/api/compute/iou_handler.py b/gns3server/handlers/api/compute/iou_handler.py index b7b14caf..281d6f29 100644 --- a/gns3server/handlers/api/compute/iou_handler.py +++ b/gns3server/handlers/api/compute/iou_handler.py @@ -228,7 +228,7 @@ class IOUHandler: iou_manager = IOU.instance() vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) 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)) 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) diff --git a/gns3server/handlers/api/compute/version_handler.py b/gns3server/handlers/api/compute/version_handler.py index b45f4aa9..a84e507a 100644 --- a/gns3server/handlers/api/compute/version_handler.py +++ b/gns3server/handlers/api/compute/version_handler.py @@ -25,7 +25,7 @@ from aiohttp.web import HTTPConflict class VersionHandler: @Route.get( - r"/version", + r"/server/version", description="Retrieve the server version number", output=VERSION_SCHEMA) def version(request, response): @@ -35,7 +35,7 @@ class VersionHandler: response.json({"version": __version__, "local": local_server}) @Route.post( - r"/version", + r"/server/version", description="Check if version is the same as the server", output=VERSION_SCHEMA, input=VERSION_SCHEMA, diff --git a/gns3server/handlers/api/controller/__init__.py b/gns3server/handlers/api/controller/__init__.py index 5920a677..9fd0827f 100644 --- a/gns3server/handlers/api/controller/__init__.py +++ b/gns3server/handlers/api/controller/__init__.py @@ -17,7 +17,6 @@ from .compute_handler import ComputeHandler from .project_handler import ProjectHandler -from .version_handler import VersionHandler from .node_handler import NodeHandler from .link_handler import LinkHandler from .server_handler import ServerHandler diff --git a/gns3server/handlers/api/controller/compute_handler.py b/gns3server/handlers/api/controller/compute_handler.py index 9c238b36..60bde7e2 100644 --- a/gns3server/handlers/api/controller/compute_handler.py +++ b/gns3server/handlers/api/controller/compute_handler.py @@ -15,15 +15,15 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import asyncio -from aiohttp.web import HTTPForbidden - 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.schemas.compute import ( + COMPUTE_CREATE_SCHEMA, + COMPUTE_OBJECT_SCHEMA, + COMPUTE_UPDATE_SCHEMA +) + import logging log = logging.getLogger(__name__) @@ -47,7 +47,7 @@ class ComputeHandler: @Route.get( r"/computes", - description="List of compute server", + description="List of compute servers", status_codes={ 200: "Compute servers list returned" }) diff --git a/gns3server/handlers/api/controller/server_handler.py b/gns3server/handlers/api/controller/server_handler.py index 737ac4f7..f81af854 100644 --- a/gns3server/handlers/api/controller/server_handler.py +++ b/gns3server/handlers/api/controller/server_handler.py @@ -15,10 +15,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from ....web.route import Route -from ....config import Config -from ....controller import Controller -from aiohttp.web import HTTPForbidden +from gns3server.web.route import Route +from gns3server.config import Config +from gns3server.controller import Controller +from gns3server.schemas.version import VERSION_SCHEMA +from gns3server.version import __version__ + +from aiohttp.web import HTTPConflict, HTTPForbidden import asyncio import logging @@ -42,9 +45,9 @@ class ServerHandler: if config.get_section_config("Server").getboolean("local", False) is False: 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() projects = controller.projects @@ -66,3 +69,27 @@ class ServerHandler: server = WebServer.instance() asyncio.async(server.shutdown_server()) 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__}) diff --git a/gns3server/handlers/api/controller/version_handler.py b/gns3server/handlers/api/controller/version_handler.py deleted file mode 100644 index b45f4aa9..00000000 --- a/gns3server/handlers/api/controller/version_handler.py +++ /dev/null @@ -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 . - -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__}) diff --git a/gns3server/schemas/nio.py b/gns3server/schemas/nio.py index ead1287f..5efe4840 100644 --- a/gns3server/schemas/nio.py +++ b/gns3server/schemas/nio.py @@ -52,7 +52,7 @@ NIO_SCHEMA = { "description": "Generic Ethernet Network Input/Output", "properties": { "type": { - "enum": ["nio_generic_ethernet"] + "enum": ["nio_generic_ethernet", "nio_ethernet"] }, "ethernet_device": { "description": "Ethernet device name e.g. eth0", diff --git a/gns3server/ubridge/hypervisor.py b/gns3server/ubridge/hypervisor.py index 7c43e838..dee11e83 100644 --- a/gns3server/ubridge/hypervisor.py +++ b/gns3server/ubridge/hypervisor.py @@ -143,7 +143,7 @@ class Hypervisor(UBridgeHypervisor): yield from self._check_ubridge_version() env = os.environ.copy() 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") if os.path.isdir(system_root): env["PATH"] = system_root + ';' + env["PATH"]