diff --git a/docs/api/examples/post_project.txt b/docs/api/examples/post_project.txt
index 6d61c41f..3a99e4e6 100644
--- a/docs/api/examples/post_project.txt
+++ b/docs/api/examples/post_project.txt
@@ -1,8 +1,8 @@
-curl -i -X POST 'http://localhost:8000/project' -d '{"location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-301/test_create_project_with_dir0"}'
+curl -i -X POST 'http://localhost:8000/project' -d '{"location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-308/test_create_project_with_dir0"}'
POST /project HTTP/1.1
{
- "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-301/test_create_project_with_dir0"
+ "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-308/test_create_project_with_dir0"
}
@@ -15,6 +15,6 @@ SERVER: Python/3.4 aiohttp/0.13.1
X-ROUTE: /project
{
- "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-301/test_create_project_with_dir0",
- "uuid": "d4d66c3f-439b-4ae9-972b-59040189c995"
+ "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-308/test_create_project_with_dir0",
+ "uuid": "7b9efb50-4909-4dc2-bb61-0bf443874c4c"
}
diff --git a/gns3server/modules/old_vpcs/__init__.py b/gns3server/modules/old_vpcs/__init__.py
deleted file mode 100644
index aa0f216e..00000000
--- a/gns3server/modules/old_vpcs/__init__.py
+++ /dev/null
@@ -1,652 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 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 .
-
-"""
-VPCS server module.
-"""
-
-import os
-import base64
-import socket
-import shutil
-
-from gns3server.modules import IModule
-from gns3server.config import Config
-from .vpcs_device import VPCSDevice
-from .vpcs_error import VPCSError
-from .nios.nio_udp import NIO_UDP
-from .nios.nio_tap import NIO_TAP
-from ..attic import find_unused_port
-
-from .schemas import VPCS_CREATE_SCHEMA
-from .schemas import VPCS_DELETE_SCHEMA
-from .schemas import VPCS_UPDATE_SCHEMA
-from .schemas import VPCS_START_SCHEMA
-from .schemas import VPCS_STOP_SCHEMA
-from .schemas import VPCS_RELOAD_SCHEMA
-from .schemas import VPCS_ALLOCATE_UDP_PORT_SCHEMA
-from .schemas import VPCS_ADD_NIO_SCHEMA
-from .schemas import VPCS_DELETE_NIO_SCHEMA
-from .schemas import VPCS_EXPORT_CONFIG_SCHEMA
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class VPCS(IModule):
- """
- VPCS module.
-
- :param name: module name
- :param args: arguments for the module
- :param kwargs: named arguments for the module
- """
-
- def __init__(self, name, *args, **kwargs):
-
- # get the VPCS location
- config = Config.instance()
- vpcs_config = config.get_section_config(name.upper())
- self._vpcs = vpcs_config.get("vpcs_path")
- if not self._vpcs or not os.path.isfile(self._vpcs):
- paths = [os.getcwd()] + os.environ["PATH"].split(os.pathsep)
- # look for VPCS in the current working directory and $PATH
- for path in paths:
- try:
- if "vpcs" in os.listdir(path) and os.access(os.path.join(path, "vpcs"), os.X_OK):
- self._vpcs = os.path.join(path, "vpcs")
- break
- except OSError:
- continue
-
- if not self._vpcs:
- log.warning("VPCS binary couldn't be found!")
- elif not os.access(self._vpcs, os.X_OK):
- log.warning("VPCS is not executable")
-
- # a new process start when calling IModule
- IModule.__init__(self, name, *args, **kwargs)
- self._vpcs_instances = {}
- self._console_start_port_range = vpcs_config.get("console_start_port_range", 4501)
- self._console_end_port_range = vpcs_config.get("console_end_port_range", 5000)
- self._allocated_udp_ports = []
- self._udp_start_port_range = vpcs_config.get("udp_start_port_range", 20501)
- self._udp_end_port_range = vpcs_config.get("udp_end_port_range", 21000)
- self._host = vpcs_config.get("host", kwargs["host"])
- self._console_host = vpcs_config.get("console_host", kwargs["console_host"])
- self._projects_dir = kwargs["projects_dir"]
- self._tempdir = kwargs["temp_dir"]
- self._working_dir = self._projects_dir
-
- def stop(self, signum=None):
- """
- Properly stops the module.
-
- :param signum: signal number (if called by the signal handler)
- """
-
- # delete all VPCS instances
- for vpcs_id in self._vpcs_instances:
- vpcs_instance = self._vpcs_instances[vpcs_id]
- vpcs_instance.delete()
-
- IModule.stop(self, signum) # this will stop the I/O loop
-
- def get_vpcs_instance(self, vpcs_id):
- """
- Returns a VPCS device instance.
-
- :param vpcs_id: VPCS device identifier
-
- :returns: VPCSDevice instance
- """
-
- if vpcs_id not in self._vpcs_instances:
- log.debug("VPCS device ID {} doesn't exist".format(vpcs_id), exc_info=1)
- self.send_custom_error("VPCS device ID {} doesn't exist".format(vpcs_id))
- return None
- return self._vpcs_instances[vpcs_id]
-
- @IModule.route("vpcs.reset")
- def reset(self, request):
- """
- Resets the module.
-
- :param request: JSON request
- """
-
- # delete all vpcs instances
- for vpcs_id in self._vpcs_instances:
- vpcs_instance = self._vpcs_instances[vpcs_id]
- vpcs_instance.delete()
-
- # resets the instance IDs
- VPCSDevice.reset()
-
- self._vpcs_instances.clear()
- self._allocated_udp_ports.clear()
-
- self._working_dir = self._projects_dir
- log.info("VPCS module has been reset")
-
- @IModule.route("vpcs.settings")
- def settings(self, request):
- """
- Set or update settings.
-
- Optional request parameters:
- - path (path to vpcs)
- - working_dir (path to a working directory)
- - project_name
- - console_start_port_range
- - console_end_port_range
- - udp_start_port_range
- - udp_end_port_range
-
- :param request: JSON request
- """
-
- if request is None:
- self.send_param_error()
- return
-
- if "path" in request and request["path"]:
- self._vpcs = request["path"]
- log.info("VPCS path set to {}".format(self._vpcs))
- for vpcs_id in self._vpcs_instances:
- vpcs_instance = self._vpcs_instances[vpcs_id]
- vpcs_instance.path = self._vpcs
-
- if "working_dir" in request:
- new_working_dir = request["working_dir"]
- log.info("this server is local with working directory path to {}".format(new_working_dir))
- else:
- new_working_dir = os.path.join(self._projects_dir, request["project_name"])
- log.info("this server is remote with working directory path to {}".format(new_working_dir))
- if self._projects_dir != self._working_dir != new_working_dir:
- if not os.path.isdir(new_working_dir):
- try:
- shutil.move(self._working_dir, new_working_dir)
- except OSError as e:
- log.error("could not move working directory from {} to {}: {}".format(self._working_dir,
- new_working_dir,
- e))
- return
-
- # update the working directory if it has changed
- if self._working_dir != new_working_dir:
- self._working_dir = new_working_dir
- for vpcs_id in self._vpcs_instances:
- vpcs_instance = self._vpcs_instances[vpcs_id]
- vpcs_instance.working_dir = os.path.join(self._working_dir, "vpcs", "pc-{}".format(vpcs_instance.id))
-
- 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_end_port_range = request["console_end_port_range"]
-
- if "udp_start_port_range" in request and "udp_end_port_range" in request:
- self._udp_start_port_range = request["udp_start_port_range"]
- self._udp_end_port_range = request["udp_end_port_range"]
-
- log.debug("received request {}".format(request))
-
- @IModule.route("vpcs.create")
- def vpcs_create(self, request):
- """
- Creates a new VPCS instance.
-
- Mandatory request parameters:
- - name (VPCS name)
-
- Optional request parameters:
- - console (VPCS console port)
-
- Response parameters:
- - id (VPCS instance identifier)
- - name (VPCS name)
- - default settings
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_CREATE_SCHEMA):
- return
-
- name = request["name"]
- console = request.get("console")
- vpcs_id = request.get("vpcs_id")
-
- try:
-
- if not self._vpcs:
- raise VPCSError("No path to a VPCS executable has been set")
-
- vpcs_instance = VPCSDevice(name,
- self._vpcs,
- self._working_dir,
- vpcs_id,
- console,
- self._console_host,
- self._console_start_port_range,
- self._console_end_port_range)
-
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
-
- response = {"name": vpcs_instance.name,
- "id": vpcs_instance.id}
-
- defaults = vpcs_instance.defaults()
- response.update(defaults)
- self._vpcs_instances[vpcs_instance.id] = vpcs_instance
- self.send_response(response)
-
- @IModule.route("vpcs.delete")
- def vpcs_delete(self, request):
- """
- Deletes a VPCS instance.
-
- Mandatory request parameters:
- - id (VPCS instance identifier)
-
- Response parameter:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_DELETE_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- try:
- vpcs_instance.clean_delete()
- del self._vpcs_instances[request["id"]]
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("vpcs.update")
- def vpcs_update(self, request):
- """
- Updates a VPCS instance
-
- Mandatory request parameters:
- - id (VPCS instance identifier)
-
- Optional request parameters:
- - any setting to update
- - script_file_base64 (base64 encoded)
-
- Response parameters:
- - updated settings
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_UPDATE_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- config_path = os.path.join(vpcs_instance.working_dir, "startup.vpc")
- try:
- if "script_file_base64" in request:
- # a new startup-config has been pushed
- config = base64.decodebytes(request["script_file_base64"].encode("utf-8")).decode("utf-8")
- config = config.replace("\r", "")
- config = config.replace('%h', vpcs_instance.name)
- try:
- with open(config_path, "w") as f:
- log.info("saving script file to {}".format(config_path))
- f.write(config)
- except OSError as e:
- raise VPCSError("Could not save the configuration {}: {}".format(config_path, e))
- # update the request with the new local startup-config path
- request["script_file"] = os.path.basename(config_path)
- elif "script_file" in request:
- if os.path.isfile(request["script_file"]) and request["script_file"] != config_path:
- # this is a local file set in the GUI
- try:
- with open(request["script_file"], "r", errors="replace") as f:
- config = f.read()
- with open(config_path, "w") as f:
- config = config.replace("\r", "")
- config = config.replace('%h', vpcs_instance.name)
- f.write(config)
- request["script_file"] = os.path.basename(config_path)
- except OSError as e:
- raise VPCSError("Could not save the configuration from {} to {}: {}".format(request["script_file"], config_path, e))
- elif not os.path.isfile(config_path):
- raise VPCSError("Startup-config {} could not be found on this server".format(request["script_file"]))
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
-
- # update the VPCS settings
- response = {}
- for name, value in request.items():
- if hasattr(vpcs_instance, name) and getattr(vpcs_instance, name) != value:
- try:
- setattr(vpcs_instance, name, value)
- response[name] = value
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(response)
-
- @IModule.route("vpcs.start")
- def vpcs_start(self, request):
- """
- Starts a VPCS instance.
-
- Mandatory request parameters:
- - id (VPCS instance identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_START_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- try:
- vpcs_instance.start()
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
- self.send_response(True)
-
- @IModule.route("vpcs.stop")
- def vpcs_stop(self, request):
- """
- Stops a VPCS instance.
-
- Mandatory request parameters:
- - id (VPCS instance identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_STOP_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- try:
- vpcs_instance.stop()
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
- self.send_response(True)
-
- @IModule.route("vpcs.reload")
- def vpcs_reload(self, request):
- """
- Reloads a VPCS instance.
-
- Mandatory request parameters:
- - id (VPCS identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_RELOAD_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- try:
- if vpcs_instance.is_running():
- vpcs_instance.stop()
- vpcs_instance.start()
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
- self.send_response(True)
-
- @IModule.route("vpcs.allocate_udp_port")
- def allocate_udp_port(self, request):
- """
- Allocates a UDP port in order to create an UDP NIO.
-
- Mandatory request parameters:
- - id (VPCS identifier)
- - port_id (unique port identifier)
-
- Response parameters:
- - port_id (unique port identifier)
- - lport (allocated local port)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_ALLOCATE_UDP_PORT_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- try:
- port = find_unused_port(self._udp_start_port_range,
- self._udp_end_port_range,
- host=self._host,
- socket_type="UDP",
- ignore_ports=self._allocated_udp_ports)
- except Exception as e:
- self.send_custom_error(str(e))
- return
-
- self._allocated_udp_ports.append(port)
- log.info("{} [id={}] has allocated UDP port {} with host {}".format(vpcs_instance.name,
- vpcs_instance.id,
- port,
- self._host))
-
- response = {"lport": port,
- "port_id": request["port_id"]}
- self.send_response(response)
-
- @IModule.route("vpcs.add_nio")
- def add_nio(self, request):
- """
- Adds an NIO (Network Input/Output) for a VPCS instance.
-
- Mandatory request parameters:
- - id (VPCS instance identifier)
- - port (port number)
- - port_id (unique port identifier)
- - nio (one of the following)
- - type "nio_udp"
- - lport (local port)
- - rhost (remote host)
- - rport (remote port)
- - type "nio_tap"
- - tap_device (TAP device name e.g. tap0)
-
- Response parameters:
- - port_id (unique port identifier)
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_ADD_NIO_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- port = request["port"]
- try:
- nio = None
- if request["nio"]["type"] == "nio_udp":
- lport = request["nio"]["lport"]
- rhost = request["nio"]["rhost"]
- rport = request["nio"]["rport"]
- try:
- #TODO: handle IPv6
- with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
- sock.connect((rhost, rport))
- except OSError as e:
- raise VPCSError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
- nio = NIO_UDP(lport, rhost, rport)
- elif request["nio"]["type"] == "nio_tap":
- tap_device = request["nio"]["tap_device"]
- if not self.has_privileged_access(self._vpcs):
- raise VPCSError("{} has no privileged access to {}.".format(self._vpcs, tap_device))
- nio = NIO_TAP(tap_device)
- if not nio:
- raise VPCSError("Requested NIO does not exist or is not supported: {}".format(request["nio"]["type"]))
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
-
- try:
- vpcs_instance.port_add_nio_binding(port, nio)
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response({"port_id": request["port_id"]})
-
- @IModule.route("vpcs.delete_nio")
- def delete_nio(self, request):
- """
- Deletes an NIO (Network Input/Output).
-
- Mandatory request parameters:
- - id (VPCS instance identifier)
- - port (port identifier)
-
- Response parameters:
- - True on success
-
- :param request: JSON request
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_DELETE_NIO_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- port = request["port"]
- try:
- nio = vpcs_instance.port_remove_nio_binding(port)
- if isinstance(nio, NIO_UDP) and nio.lport in self._allocated_udp_ports:
- self._allocated_udp_ports.remove(nio.lport)
- except VPCSError as e:
- self.send_custom_error(str(e))
- return
-
- self.send_response(True)
-
- @IModule.route("vpcs.export_config")
- def export_config(self, request):
- """
- Exports the script file from a VPCS instance.
-
- Mandatory request parameters:
- - id (vm identifier)
-
- Response parameters:
- - script_file_base64 (script file base64 encoded)
- - False if no configuration can be exported
- """
-
- # validate the request
- if not self.validate_request(request, VPCS_EXPORT_CONFIG_SCHEMA):
- return
-
- # get the instance
- vpcs_instance = self.get_vpcs_instance(request["id"])
- if not vpcs_instance:
- return
-
- response = {}
- script_file_path = os.path.join(vpcs_instance.working_dir, vpcs_instance.script_file)
- try:
- with open(script_file_path, "rb") as f:
- config = f.read()
- response["script_file_base64"] = base64.encodebytes(config).decode("utf-8")
- except OSError as e:
- self.send_custom_error("unable to export the script file: {}".format(e))
- return
-
- if not response:
- self.send_response(False)
- else:
- self.send_response(response)
-
- @IModule.route("vpcs.echo")
- def echo(self, request):
- """
- Echo end point for testing purposes.
-
- :param request: JSON request
- """
-
- if request is None:
- self.send_param_error()
- else:
- log.debug("received request {}".format(request))
- self.send_response(request)
diff --git a/gns3server/modules/old_vpcs/adapters/__init__.py b/gns3server/modules/old_vpcs/adapters/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/gns3server/modules/old_vpcs/adapters/adapter.py b/gns3server/modules/old_vpcs/adapters/adapter.py
deleted file mode 100644
index cf439427..00000000
--- a/gns3server/modules/old_vpcs/adapters/adapter.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 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 .
-
-
-class Adapter(object):
- """
- Base class for adapters.
-
- :param interfaces: number of interfaces supported by this adapter.
- """
-
- def __init__(self, interfaces=1):
-
- self._interfaces = interfaces
-
- self._ports = {}
- for port_id in range(0, interfaces):
- self._ports[port_id] = None
-
- def removable(self):
- """
- Returns True if the adapter can be removed from a slot
- and False if not.
-
- :returns: boolean
- """
-
- return True
-
- def port_exists(self, port_id):
- """
- Checks if a port exists on this adapter.
-
- :returns: True is the port exists,
- False otherwise.
- """
-
- if port_id in self._ports:
- return True
- return False
-
- def add_nio(self, port_id, nio):
- """
- Adds a NIO to a port on this adapter.
-
- :param port_id: port ID (integer)
- :param nio: NIO instance
- """
-
- self._ports[port_id] = nio
-
- def remove_nio(self, port_id):
- """
- Removes a NIO from a port on this adapter.
-
- :param port_id: port ID (integer)
- """
-
- self._ports[port_id] = None
-
- def get_nio(self, port_id):
- """
- Returns the NIO assigned to a port.
-
- :params port_id: port ID (integer)
-
- :returns: NIO instance
- """
-
- return self._ports[port_id]
-
- @property
- def ports(self):
- """
- Returns port to NIO mapping
-
- :returns: dictionary port -> NIO
- """
-
- return self._ports
-
- @property
- def interfaces(self):
- """
- Returns the number of interfaces supported by this adapter.
-
- :returns: number of interfaces
- """
-
- return self._interfaces
diff --git a/gns3server/modules/old_vpcs/adapters/ethernet_adapter.py b/gns3server/modules/old_vpcs/adapters/ethernet_adapter.py
deleted file mode 100644
index bbca7f40..00000000
--- a/gns3server/modules/old_vpcs/adapters/ethernet_adapter.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 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 .adapter import Adapter
-
-
-class EthernetAdapter(Adapter):
- """
- VPCS Ethernet adapter.
- """
-
- def __init__(self):
- Adapter.__init__(self, interfaces=1)
-
- def __str__(self):
-
- return "VPCS Ethernet adapter"
diff --git a/gns3server/modules/old_vpcs/nios/__init__.py b/gns3server/modules/old_vpcs/nios/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/gns3server/modules/old_vpcs/nios/nio_tap.py b/gns3server/modules/old_vpcs/nios/nio_tap.py
deleted file mode 100644
index 4c3ed6b2..00000000
--- a/gns3server/modules/old_vpcs/nios/nio_tap.py
+++ /dev/null
@@ -1,46 +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 TAP NIOs (UNIX based OSes only).
-"""
-
-
-class NIO_TAP(object):
- """
- TAP NIO.
-
- :param tap_device: TAP device name (e.g. tap0)
- """
-
- def __init__(self, tap_device):
-
- self._tap_device = tap_device
-
- @property
- def tap_device(self):
- """
- Returns the TAP device used by this NIO.
-
- :returns: the TAP device name
- """
-
- return self._tap_device
-
- def __str__(self):
-
- return "NIO TAP"
diff --git a/gns3server/modules/old_vpcs/nios/nio_udp.py b/gns3server/modules/old_vpcs/nios/nio_udp.py
deleted file mode 100644
index 0527f675..00000000
--- a/gns3server/modules/old_vpcs/nios/nio_udp.py
+++ /dev/null
@@ -1,72 +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 UDP NIOs.
-"""
-
-
-class NIO_UDP(object):
- """
- UDP NIO.
-
- :param lport: local port number
- :param rhost: remote address/host
- :param rport: remote port number
- """
-
- _instance_count = 0
-
- def __init__(self, lport, rhost, rport):
-
- self._lport = lport
- self._rhost = rhost
- self._rport = rport
-
- @property
- def lport(self):
- """
- Returns the local port
-
- :returns: local port number
- """
-
- return self._lport
-
- @property
- def rhost(self):
- """
- Returns the remote host
-
- :returns: remote address/host
- """
-
- return self._rhost
-
- @property
- def rport(self):
- """
- Returns the remote port
-
- :returns: remote port number
- """
-
- return self._rport
-
- def __str__(self):
-
- return "NIO UDP"
diff --git a/gns3server/modules/old_vpcs/schemas.py b/gns3server/modules/old_vpcs/schemas.py
deleted file mode 100644
index 6556895b..00000000
--- a/gns3server/modules/old_vpcs/schemas.py
+++ /dev/null
@@ -1,347 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 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 .
-
-
-VPCS_CREATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to create a new VPCS instance",
- "type": "object",
- "properties": {
- "name": {
- "description": "VPCS device name",
- "type": "string",
- "minLength": 1,
- },
- "vpcs_id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- "console": {
- "description": "console TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["name"]
-}
-
-VPCS_DELETE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a VPCS instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VPCS_UPDATE_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to update a VPCS instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- "name": {
- "description": "VPCS device name",
- "type": "string",
- "minLength": 1,
- },
- "console": {
- "description": "console TCP port",
- "minimum": 1,
- "maximum": 65535,
- "type": "integer"
- },
- "script_file": {
- "description": "Path to the VPCS script file file",
- "type": "string",
- "minLength": 1,
- },
- "script_file_base64": {
- "description": "Script file base64 encoded",
- "type": "string"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VPCS_START_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to start a VPCS instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VPCS_STOP_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to stop a VPCS instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VPCS_RELOAD_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to reload a VPCS instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
-
-VPCS_ALLOCATE_UDP_PORT_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to allocate an UDP port for a VPCS instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the VPCS instance",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id"]
-}
-
-VPCS_ADD_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to add a NIO for a VPCS instance",
- "type": "object",
-
- "definitions": {
- "UDP": {
- "description": "UDP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_udp"]
- },
- "lport": {
- "description": "Local port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- },
- "rhost": {
- "description": "Remote host",
- "type": "string",
- "minLength": 1
- },
- "rport": {
- "description": "Remote port",
- "type": "integer",
- "minimum": 1,
- "maximum": 65535
- }
- },
- "required": ["type", "lport", "rhost", "rport"],
- "additionalProperties": False
- },
- "Ethernet": {
- "description": "Generic Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_generic_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "LinuxEthernet": {
- "description": "Linux Ethernet Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_linux_ethernet"]
- },
- "ethernet_device": {
- "description": "Ethernet device name e.g. eth0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "ethernet_device"],
- "additionalProperties": False
- },
- "TAP": {
- "description": "TAP Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_tap"]
- },
- "tap_device": {
- "description": "TAP device name e.g. tap0",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "tap_device"],
- "additionalProperties": False
- },
- "UNIX": {
- "description": "UNIX Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_unix"]
- },
- "local_file": {
- "description": "path to the UNIX socket file (local)",
- "type": "string",
- "minLength": 1
- },
- "remote_file": {
- "description": "path to the UNIX socket file (remote)",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "local_file", "remote_file"],
- "additionalProperties": False
- },
- "VDE": {
- "description": "VDE Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_vde"]
- },
- "control_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- "local_file": {
- "description": "path to the VDE control file",
- "type": "string",
- "minLength": 1
- },
- },
- "required": ["type", "control_file", "local_file"],
- "additionalProperties": False
- },
- "NULL": {
- "description": "NULL Network Input/Output",
- "properties": {
- "type": {
- "enum": ["nio_null"]
- },
- },
- "required": ["type"],
- "additionalProperties": False
- },
- },
-
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- "port_id": {
- "description": "Unique port identifier for the VPCS instance",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0,
- "maximum": 0
- },
- "nio": {
- "type": "object",
- "description": "Network Input/Output",
- "oneOf": [
- {"$ref": "#/definitions/UDP"},
- {"$ref": "#/definitions/Ethernet"},
- {"$ref": "#/definitions/LinuxEthernet"},
- {"$ref": "#/definitions/TAP"},
- {"$ref": "#/definitions/UNIX"},
- {"$ref": "#/definitions/VDE"},
- {"$ref": "#/definitions/NULL"},
- ]
- },
- },
- "additionalProperties": False,
- "required": ["id", "port_id", "port", "nio"]
-}
-
-VPCS_DELETE_NIO_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to delete a NIO for a VPCS instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- "port": {
- "description": "Port number",
- "type": "integer",
- "minimum": 0,
- "maximum": 0
- },
- },
- "additionalProperties": False,
- "required": ["id", "port"]
-}
-
-VPCS_EXPORT_CONFIG_SCHEMA = {
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "Request validation to export the script file of a VPCS instance",
- "type": "object",
- "properties": {
- "id": {
- "description": "VPCS device instance ID",
- "type": "integer"
- },
- },
- "additionalProperties": False,
- "required": ["id"]
-}
diff --git a/gns3server/modules/old_vpcs/vpcs_device.py b/gns3server/modules/old_vpcs/vpcs_device.py
deleted file mode 100644
index 65664f39..00000000
--- a/gns3server/modules/old_vpcs/vpcs_device.py
+++ /dev/null
@@ -1,557 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2014 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 .
-
-"""
-VPCS device management (creates command line, processes, files etc.) in
-order to run an VPCS instance.
-"""
-
-import os
-import sys
-import subprocess
-import signal
-import shutil
-import re
-
-from pkg_resources import parse_version
-from .vpcs_error import VPCSError
-from .adapters.ethernet_adapter import EthernetAdapter
-from .nios.nio_udp import NIO_UDP
-from .nios.nio_tap import NIO_TAP
-from ..attic import find_unused_port
-
-import logging
-log = logging.getLogger(__name__)
-
-
-class VPCSDevice(object):
- """
- VPCS device implementation.
-
- :param name: name of this VPCS device
- :param path: path to VPCS executable
- :param working_dir: path to a working directory
- :param vpcs_id: VPCS instance ID
- :param console: TCP console port
- :param console_host: IP address to bind for console connections
- :param console_start_port_range: TCP console port range start
- :param console_end_port_range: TCP console port range end
- """
-
- _instances = []
- _allocated_console_ports = []
-
- def __init__(self,
- name,
- path,
- working_dir,
- vpcs_id=None,
- console=None,
- console_host="0.0.0.0",
- console_start_port_range=4512,
- console_end_port_range=5000):
-
-
- if not vpcs_id:
- # find an instance identifier is none is provided (1 <= id <= 255)
- # This 255 limit is due to a restriction on the number of possible
- # MAC addresses given in VPCS using the -m option
- self._id = 0
- for identifier in range(1, 256):
- if identifier not in self._instances:
- self._id = identifier
- self._instances.append(self._id)
- break
-
- if self._id == 0:
- raise VPCSError("Maximum number of VPCS instances reached")
- else:
- if vpcs_id in self._instances:
- raise VPCSError("VPCS identifier {} is already used by another VPCS device".format(vpcs_id))
- self._id = vpcs_id
- self._instances.append(self._id)
-
- self._name = name
- self._path = path
- self._console = console
- self._working_dir = None
- self._console_host = console_host
- self._command = []
- self._process = None
- self._vpcs_stdout_file = ""
- self._started = False
- self._console_start_port_range = console_start_port_range
- self._console_end_port_range = console_end_port_range
-
- # VPCS settings
- self._script_file = ""
- self._ethernet_adapter = EthernetAdapter() # one adapter with 1 Ethernet interface
-
- working_dir_path = os.path.join(working_dir, "vpcs", "pc-{}".format(self._id))
-
- if vpcs_id and not os.path.isdir(working_dir_path):
- raise VPCSError("Working directory {} doesn't exist".format(working_dir_path))
-
- # create the device own working directory
- self.working_dir = working_dir_path
-
- if not self._console:
- # allocate a console port
- try:
- self._console = find_unused_port(self._console_start_port_range,
- self._console_end_port_range,
- self._console_host,
- ignore_ports=self._allocated_console_ports)
- except Exception as e:
- raise VPCSError(e)
-
- if self._console in self._allocated_console_ports:
- raise VPCSError("Console port {} is already used by another VPCS device".format(console))
- self._allocated_console_ports.append(self._console)
-
- log.info("VPCS device {name} [id={id}] has been created".format(name=self._name,
- id=self._id))
-
- def defaults(self):
- """
- Returns all the default attribute values for VPCS.
-
- :returns: default values (dictionary)
- """
-
- vpcs_defaults = {"name": self._name,
- "script_file": self._script_file,
- "console": self._console}
-
- return vpcs_defaults
-
- @property
- def id(self):
- """
- Returns the unique ID for this VPCS device.
-
- :returns: id (integer)
- """
-
- return self._id
-
- @classmethod
- def reset(cls):
- """
- Resets allocated instance list.
- """
-
- cls._instances.clear()
- cls._allocated_console_ports.clear()
-
- @property
- def name(self):
- """
- Returns the name of this VPCS device.
-
- :returns: name
- """
-
- return self._name
-
- @name.setter
- def name(self, new_name):
- """
- Sets the name of this VPCS device.
-
- :param new_name: name
- """
-
- if self._script_file:
- # update the startup.vpc
- config_path = os.path.join(self._working_dir, "startup.vpc")
- if os.path.isfile(config_path):
- try:
- with open(config_path, "r+", errors="replace") as f:
- old_config = f.read()
- new_config = old_config.replace(self._name, new_name)
- f.seek(0)
- f.write(new_config)
- except OSError as e:
- raise VPCSError("Could not amend the configuration {}: {}".format(config_path, e))
-
- log.info("VPCS {name} [id={id}]: renamed to {new_name}".format(name=self._name,
- id=self._id,
- new_name=new_name))
- self._name = new_name
-
- @property
- def path(self):
- """
- Returns the path to the VPCS executable.
-
- :returns: path to VPCS
- """
-
- return self._path
-
- @path.setter
- def path(self, path):
- """
- Sets the path to the VPCS executable.
-
- :param path: path to VPCS
- """
-
- self._path = path
- log.info("VPCS {name} [id={id}]: path changed to {path}".format(name=self._name,
- id=self._id,
- path=path))
-
- @property
- def working_dir(self):
- """
- Returns current working directory
-
- :returns: path to the working directory
- """
-
- return self._working_dir
-
- @working_dir.setter
- def working_dir(self, working_dir):
- """
- Sets the working directory for VPCS.
-
- :param working_dir: path to the working directory
- """
-
- try:
- os.makedirs(working_dir)
- except FileExistsError:
- pass
- except OSError as e:
- raise VPCSError("Could not create working directory {}: {}".format(working_dir, e))
-
- self._working_dir = working_dir
- log.info("VPCS {name} [id={id}]: working directory changed to {wd}".format(name=self._name,
- id=self._id,
- wd=self._working_dir))
-
- @property
- def console(self):
- """
- Returns the TCP console port.
-
- :returns: console port (integer)
- """
-
- return self._console
-
- @console.setter
- def console(self, console):
- """
- Sets the TCP console port.
-
- :param console: console port (integer)
- """
-
- if console in self._allocated_console_ports:
- raise VPCSError("Console port {} is already used by another VPCS device".format(console))
-
- self._allocated_console_ports.remove(self._console)
- self._console = console
- self._allocated_console_ports.append(self._console)
- log.info("VPCS {name} [id={id}]: console port set to {port}".format(name=self._name,
- id=self._id,
- port=console))
-
- def command(self):
- """
- Returns the VPCS command line.
-
- :returns: VPCS command line (string)
- """
-
- return " ".join(self._build_command())
-
- def delete(self):
- """
- Deletes this VPCS device.
- """
-
- self.stop()
- if self._id in self._instances:
- self._instances.remove(self._id)
-
- if self.console and self.console in self._allocated_console_ports:
- self._allocated_console_ports.remove(self.console)
-
- log.info("VPCS device {name} [id={id}] has been deleted".format(name=self._name,
- id=self._id))
-
- def clean_delete(self):
- """
- Deletes this VPCS device & all files (configs, logs etc.)
- """
-
- self.stop()
- if self._id in self._instances:
- self._instances.remove(self._id)
-
- if self.console:
- self._allocated_console_ports.remove(self.console)
-
- try:
- shutil.rmtree(self._working_dir)
- except OSError as e:
- log.error("could not delete VPCS device {name} [id={id}]: {error}".format(name=self._name,
- id=self._id,
- error=e))
- return
-
- log.info("VPCS device {name} [id={id}] has been deleted (including associated files)".format(name=self._name,
- id=self._id))
-
- @property
- def started(self):
- """
- Returns either this VPCS device has been started or not.
-
- :returns: boolean
- """
-
- return self._started
-
- def _check_vpcs_version(self):
- """
- Checks if the VPCS executable version is >= 0.5b1.
- """
-
- try:
- output = subprocess.check_output([self._path, "-v"], cwd=self._working_dir)
- match = re.search("Welcome to Virtual PC Simulator, version ([0-9a-z\.]+)", output.decode("utf-8"))
- if match:
- version = match.group(1)
- if parse_version(version) < parse_version("0.5b1"):
- raise VPCSError("VPCS executable version must be >= 0.5b1")
- else:
- raise VPCSError("Could not determine the VPCS version for {}".format(self._path))
- except (OSError, subprocess.SubprocessError) as e:
- raise VPCSError("Error while looking for the VPCS version: {}".format(e))
-
- def start(self):
- """
- Starts the VPCS process.
- """
-
- if not self.is_running():
-
- if not self._path:
- raise VPCSError("No path to a VPCS executable has been set")
-
- if not os.path.isfile(self._path):
- raise VPCSError("VPCS program '{}' is not accessible".format(self._path))
-
- if not os.access(self._path, os.X_OK):
- raise VPCSError("VPCS program '{}' is not executable".format(self._path))
-
- self._check_vpcs_version()
-
- if not self._ethernet_adapter.get_nio(0):
- raise VPCSError("This VPCS instance must be connected in order to start")
-
- self._command = self._build_command()
- try:
- log.info("starting VPCS: {}".format(self._command))
- self._vpcs_stdout_file = os.path.join(self._working_dir, "vpcs.log")
- log.info("logging to {}".format(self._vpcs_stdout_file))
- flags = 0
- if sys.platform.startswith("win32"):
- flags = subprocess.CREATE_NEW_PROCESS_GROUP
- with open(self._vpcs_stdout_file, "w") as fd:
- self._process = subprocess.Popen(self._command,
- stdout=fd,
- stderr=subprocess.STDOUT,
- cwd=self._working_dir,
- creationflags=flags)
- log.info("VPCS instance {} started PID={}".format(self._id, self._process.pid))
- self._started = True
- except (OSError, subprocess.SubprocessError) as e:
- vpcs_stdout = self.read_vpcs_stdout()
- log.error("could not start VPCS {}: {}\n{}".format(self._path, e, vpcs_stdout))
- raise VPCSError("could not start VPCS {}: {}\n{}".format(self._path, e, vpcs_stdout))
-
- def stop(self):
- """
- Stops the VPCS process.
- """
-
- # stop the VPCS process
- if self.is_running():
- log.info("stopping VPCS instance {} PID={}".format(self._id, self._process.pid))
- if sys.platform.startswith("win32"):
- self._process.send_signal(signal.CTRL_BREAK_EVENT)
- else:
- self._process.terminate()
-
- self._process.wait()
-
- self._process = None
- self._started = False
-
- def read_vpcs_stdout(self):
- """
- Reads the standard output of the VPCS process.
- Only use when the process has been stopped or has crashed.
- """
-
- output = ""
- if self._vpcs_stdout_file:
- try:
- with open(self._vpcs_stdout_file, errors="replace") as file:
- output = file.read()
- except OSError as e:
- log.warn("could not read {}: {}".format(self._vpcs_stdout_file, e))
- return output
-
- def is_running(self):
- """
- Checks if the VPCS process is running
-
- :returns: True or False
- """
-
- if self._process and self._process.poll() is None:
- return True
- return False
-
- def port_add_nio_binding(self, port_id, nio):
- """
- Adds a port NIO binding.
-
- :param port_id: port ID
- :param nio: NIO instance to add to the slot/port
- """
-
- if not self._ethernet_adapter.port_exists(port_id):
- raise VPCSError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter,
- port_id=port_id))
-
- self._ethernet_adapter.add_nio(port_id, nio)
- log.info("VPCS {name} [id={id}]: {nio} added to port {port_id}".format(name=self._name,
- id=self._id,
- nio=nio,
- port_id=port_id))
-
- def port_remove_nio_binding(self, port_id):
- """
- Removes a port NIO binding.
-
- :param port_id: port ID
-
- :returns: NIO instance
- """
-
- if not self._ethernet_adapter.port_exists(port_id):
- raise VPCSError("Port {port_id} doesn't exist in adapter {adapter}".format(adapter=self._ethernet_adapter,
- port_id=port_id))
-
- nio = self._ethernet_adapter.get_nio(port_id)
- self._ethernet_adapter.remove_nio(port_id)
- log.info("VPCS {name} [id={id}]: {nio} removed from port {port_id}".format(name=self._name,
- id=self._id,
- nio=nio,
- port_id=port_id))
- return nio
-
- def _build_command(self):
- """
- Command to start the VPCS process.
- (to be passed to subprocess.Popen())
-
- VPCS command line:
- usage: vpcs [options] [scriptfile]
- Option:
- -h print this help then exit
- -v print version information then exit
-
- -i num number of vpc instances to start (default is 9)
- -p port run as a daemon listening on the tcp 'port'
- -m num start byte of ether address, default from 0
- -r file load and execute script file
- compatible with older versions, DEPRECATED.
-
- -e tap mode, using /dev/tapx by default (linux only)
- -u udp mode, default
-
- udp mode options:
- -s port local udp base port, default from 20000
- -c port remote udp base port (dynamips udp port), default from 30000
- -t ip remote host IP, default 127.0.0.1
-
- tap mode options:
- -d device device name, works only when -i is set to 1
-
- hypervisor mode option:
- -H port run as the hypervisor listening on the tcp 'port'
-
- If no 'scriptfile' specified, vpcs will read and execute the file named
- 'startup.vpc' if it exsits in the current directory.
-
- """
-
- command = [self._path]
- command.extend(["-p", str(self._console)]) # listen to console port
-
- nio = self._ethernet_adapter.get_nio(0)
- if nio:
- if isinstance(nio, NIO_UDP):
- # UDP tunnel
- command.extend(["-s", str(nio.lport)]) # source UDP port
- command.extend(["-c", str(nio.rport)]) # destination UDP port
- command.extend(["-t", nio.rhost]) # destination host
-
- elif isinstance(nio, NIO_TAP):
- # TAP interface
- command.extend(["-e"])
- command.extend(["-d", nio.tap_device])
-
- command.extend(["-m", str(self._id)]) # the unique ID is used to set the MAC address offset
- command.extend(["-i", "1"]) # option to start only one VPC instance
- command.extend(["-F"]) # option to avoid the daemonization of VPCS
- if self._script_file:
- command.extend([self._script_file])
- return command
-
- @property
- def script_file(self):
- """
- Returns the script-file for this VPCS instance.
-
- :returns: path to script-file
- """
-
- return self._script_file
-
- @script_file.setter
- def script_file(self, script_file):
- """
- Sets the script-file for this VPCS instance.
-
- :param script_file: path to base-script-file
- """
-
- self._script_file = script_file
- log.info("VPCS {name} [id={id}]: script_file set to {config}".format(name=self._name,
- id=self._id,
- config=self._script_file))
diff --git a/gns3server/modules/old_vpcs/vpcs_error.py b/gns3server/modules/old_vpcs/vpcs_error.py
deleted file mode 100644
index 167129ba..00000000
--- a/gns3server/modules/old_vpcs/vpcs_error.py
+++ /dev/null
@@ -1,39 +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 .
-
-"""
-Custom exceptions for VPCS module.
-"""
-
-
-class VPCSError(Exception):
-
- def __init__(self, message, original_exception=None):
-
- Exception.__init__(self, message)
- if isinstance(message, Exception):
- message = str(message)
- self._message = message
- self._original_exception = original_exception
-
- def __repr__(self):
-
- return self._message
-
- def __str__(self):
-
- return self._message
diff --git a/gns3server/modules/vpcs/__init__.py b/gns3server/modules/vpcs/__init__.py
index 52191f2f..6ad5d8cc 100644
--- a/gns3server/modules/vpcs/__init__.py
+++ b/gns3server/modules/vpcs/__init__.py
@@ -20,8 +20,8 @@ VPCS server module.
"""
from ..base_manager import BaseManager
-from .vpcs_device import VPCSDevice
+from .vpcs_vm import VPCSVM
class VPCS(BaseManager):
- _VM_CLASS = VPCSDevice
+ _VM_CLASS = VPCSVM
diff --git a/gns3server/modules/vpcs/vpcs_device.py b/gns3server/modules/vpcs/vpcs_vm.py
similarity index 96%
rename from gns3server/modules/vpcs/vpcs_device.py
rename to gns3server/modules/vpcs/vpcs_vm.py
index 44b09682..a1ffdd57 100644
--- a/gns3server/modules/vpcs/vpcs_device.py
+++ b/gns3server/modules/vpcs/vpcs_vm.py
@@ -16,7 +16,7 @@
# along with this program. If not, see .
"""
-VPCS device management (creates command line, processes, files etc.) in
+VPCS vm management (creates command line, processes, files etc.) in
order to run an VPCS instance.
"""
@@ -42,11 +42,11 @@ import logging
log = logging.getLogger(__name__)
-class VPCSDevice(BaseVM):
+class VPCSVM(BaseVM):
"""
- VPCS device implementation.
+ VPCS vm implementation.
- :param name: name of this VPCS device
+ :param name: name of this VPCS vm
:param uuid: VPCS instance UUID
:param project: Project instance
:param manager: parent VM Manager
@@ -78,7 +78,7 @@ class VPCSDevice(BaseVM):
# if vpcs_id and not os.path.isdir(working_dir_path):
# raise VPCSError("Working directory {} doesn't exist".format(working_dir_path))
#
- # # create the device own working directory
+ # # create the vm own working directory
# self.working_dir = working_dir_path
#
try:
@@ -113,7 +113,7 @@ class VPCSDevice(BaseVM):
@property
def console(self):
"""
- Returns the console port of this VPCS device.
+ Returns the console port of this VPCS vm.
:returns: console port
"""
@@ -124,7 +124,7 @@ class VPCSDevice(BaseVM):
@BaseVM.name.setter
def name(self, new_name):
"""
- Sets the name of this VPCS device.
+ Sets the name of this VPCS vm.
:param new_name: name
"""
@@ -265,10 +265,10 @@ class VPCSDevice(BaseVM):
raise VPCSError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e))
nio = NIO_UDP(lport, rhost, rport)
elif nio_settings["type"] == "nio_tap":
- tap_device = nio_settings["tap_device"]
+ tap_vm = nio_settings["tap_device"]
if not has_privileged_access(self._path):
- raise VPCSError("{} has no privileged access to {}.".format(self._path, tap_device))
- nio = NIO_TAP(tap_device)
+ raise VPCSError("{} has no privileged access to {}.".format(self._path, tap_vm))
+ nio = NIO_TAP(tap_vm)
if not nio:
raise VPCSError("Requested NIO does not exist or is not supported: {}".format(nio_settings["type"]))
@@ -326,7 +326,7 @@ class VPCSDevice(BaseVM):
-t ip remote host IP, default 127.0.0.1
tap mode options:
- -d device device name, works only when -i is set to 1
+ -d vm device name, works only when -i is set to 1
hypervisor mode option:
-H port run as the hypervisor listening on the tcp 'port'
@@ -352,7 +352,7 @@ class VPCSDevice(BaseVM):
elif isinstance(nio, NIO_TAP):
# TAP interface
command.extend(["-e"])
- command.extend(["-d", nio.tap_device])
+ command.extend(["-d", nio.tap_vm])
# FIXME: find workaround
# command.extend(["-m", str(self._id)]) # the unique ID is used to set the MAC address offset
diff --git a/tests/api/test_vpcs.py b/tests/api/test_vpcs.py
index 04d01c63..205e74a0 100644
--- a/tests/api/test_vpcs.py
+++ b/tests/api/test_vpcs.py
@@ -49,7 +49,7 @@ def test_vpcs_nio_create_udp(server, vm):
assert response.json["type"] == "nio_udp"
-@patch("gns3server.modules.vpcs.vpcs_device.has_privileged_access", return_value=True)
+@patch("gns3server.modules.vpcs.vpcs_vm.has_privileged_access", return_value=True)
def test_vpcs_nio_create_tap(mock, server, vm):
response = server.post("/vpcs/{}/ports/0/nio".format(vm["uuid"]), {"type": "nio_tap",
"tap_device": "test"})
diff --git a/tests/modules/vpcs/test_vpcs_device.py b/tests/modules/vpcs/test_vpcs_vm.py
similarity index 80%
rename from tests/modules/vpcs/test_vpcs_device.py
rename to tests/modules/vpcs/test_vpcs_vm.py
index 2fe1aa26..57cf71d8 100644
--- a/tests/modules/vpcs/test_vpcs_device.py
+++ b/tests/modules/vpcs/test_vpcs_vm.py
@@ -23,7 +23,7 @@ from tests.utils import asyncio_patch
from tests.api.base import loop, project
from asyncio.subprocess import Process
from unittest.mock import patch, MagicMock
-from gns3server.modules.vpcs.vpcs_device import VPCSDevice
+from gns3server.modules.vpcs.vpcs_vm import VPCSVM
from gns3server.modules.vpcs.vpcs_error import VPCSError
from gns3server.modules.vpcs import VPCS
from gns3server.modules.port_manager import PortManager
@@ -38,7 +38,7 @@ def manager():
@patch("subprocess.check_output", return_value="Welcome to Virtual PC Simulator, version 0.6".encode("utf-8"))
def test_vm(manager):
- vm = VPCSDevice("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
+ vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
assert vm.name == "test"
assert vm.uuid == "00010203-0405-0607-0809-0a0b0c0d0e0f"
@@ -46,7 +46,7 @@ def test_vm(manager):
@patch("subprocess.check_output", return_value="Welcome to Virtual PC Simulator, version 0.1".encode("utf-8"))
def test_vm_invalid_vpcs_version(project, manager):
with pytest.raises(VPCSError):
- vm = VPCSDevice("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
+ vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
assert vm.name == "test"
assert vm.uuid == "00010203-0405-0607-0809-0a0b0c0d0e0f"
@@ -54,14 +54,14 @@ def test_vm_invalid_vpcs_version(project, manager):
@patch("gns3server.config.Config.get_section_config", return_value={"path": "/bin/test_fake"})
def test_vm_invalid_vpcs_path(project, manager):
with pytest.raises(VPCSError):
- vm = VPCSDevice("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
+ vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
assert vm.name == "test"
assert vm.uuid == "00010203-0405-0607-0809-0a0b0c0d0e0f"
def test_start(project, loop, manager):
with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()):
- vm = VPCSDevice("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
+ vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
nio = vm.port_add_nio_binding(0, {"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
loop.run_until_complete(asyncio.async(vm.start()))
@@ -71,7 +71,7 @@ def test_start(project, loop, manager):
def test_stop(project, loop, manager):
process = MagicMock()
with asyncio_patch("asyncio.create_subprocess_exec", return_value=process):
- vm = VPCSDevice("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
+ vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
nio = vm.port_add_nio_binding(0, {"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
loop.run_until_complete(asyncio.async(vm.start()))
@@ -82,28 +82,28 @@ def test_stop(project, loop, manager):
def test_add_nio_binding_udp(manager):
- vm = VPCSDevice("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
+ vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
nio = vm.port_add_nio_binding(0, {"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
assert nio.lport == 4242
def test_add_nio_binding_tap(project, manager):
- vm = VPCSDevice("test", 42, project, manager)
- with patch("gns3server.modules.vpcs.vpcs_device.has_privileged_access", return_value=True):
+ vm = VPCSVM("test", 42, project, manager)
+ with patch("gns3server.modules.vpcs.vpcs_vm.has_privileged_access", return_value=True):
nio = vm.port_add_nio_binding(0, {"type": "nio_tap", "tap_device": "test"})
assert nio.tap_device == "test"
def test_add_nio_binding_tap_no_privileged_access(manager):
- vm = VPCSDevice("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
- with patch("gns3server.modules.vpcs.vpcs_device.has_privileged_access", return_value=False):
+ vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
+ with patch("gns3server.modules.vpcs.vpcs_vm.has_privileged_access", return_value=False):
with pytest.raises(VPCSError):
vm.port_add_nio_binding(0, {"type": "nio_tap", "tap_device": "test"})
assert vm._ethernet_adapter.ports[0] is None
def test_port_remove_nio_binding(manager):
- vm = VPCSDevice("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
+ vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
nio = vm.port_add_nio_binding(0, {"type": "nio_udp", "lport": 4242, "rport": 4243, "rhost": "127.0.0.1"})
vm.port_remove_nio_binding(0)
assert vm._ethernet_adapter.ports[0] is None