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_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

View File

@ -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()

View File

@ -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)}

View File

@ -16,13 +16,13 @@
# 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
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}

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
@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:

View File

@ -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)

View File

@ -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:

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.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))

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -15,15 +15,15 @@
# 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 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"
})

View File

@ -15,10 +15,13 @@
# 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 ....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__})

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",
"properties": {
"type": {
"enum": ["nio_generic_ethernet"]
"enum": ["nio_generic_ethernet", "nio_ethernet"]
},
"ethernet_device": {
"description": "Ethernet device name e.g. eth0",

View File

@ -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"]