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

Refactoring to use a common node class for all VMs and other (future) objects.

This commit is contained in:
grossmj 2016-05-11 11:35:36 -06:00
parent 9dca7dfe4a
commit 5a76f81271
102 changed files with 1654 additions and 1672 deletions

View File

@ -9,8 +9,8 @@ Get a Dynamips device instance
Parameters Parameters
********** **********
- **device_id**: UUID for the instance
- **project_id**: UUID for the project - **project_id**: UUID for the project
- **device_id**: UUID for the instance
Response status codes Response status codes
********************** **********************
@ -38,8 +38,8 @@ Update a Dynamips device instance
Parameters Parameters
********** **********
- **device_id**: UUID for the instance
- **project_id**: UUID for the project - **project_id**: UUID for the project
- **device_id**: UUID for the instance
Response status codes Response status codes
********************** **********************
@ -96,8 +96,8 @@ Delete a Dynamips device instance
Parameters Parameters
********** **********
- **device_id**: UUID for the instance
- **project_id**: UUID for the project - **project_id**: UUID for the project
- **device_id**: UUID for the instance
Response status codes Response status codes
********************** **********************

View File

@ -9,9 +9,9 @@ Add a NIO to a Dynamips device instance
Parameters Parameters
********** **********
- **project_id**: UUID for the project
- **port_number**: Port on the device - **port_number**: Port on the device
- **device_id**: UUID for the instance - **device_id**: UUID for the instance
- **project_id**: UUID for the project
Response status codes Response status codes
********************** **********************
@ -139,9 +139,9 @@ Remove a NIO from a Dynamips device instance
Parameters Parameters
********** **********
- **project_id**: UUID for the project
- **port_number**: Port on the device - **port_number**: Port on the device
- **device_id**: UUID for the instance - **device_id**: UUID for the instance
- **project_id**: UUID for the project
Response status codes Response status codes
********************** **********************

View File

@ -9,9 +9,9 @@ Start a packet capture on a Dynamips device instance
Parameters Parameters
********** **********
- **project_id**: UUID for the project
- **port_number**: Port on the device - **port_number**: Port on the device
- **device_id**: UUID for the instance - **device_id**: UUID for the instance
- **project_id**: UUID for the project
Response status codes Response status codes
********************** **********************
@ -26,6 +26,6 @@ Input
<table> <table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr> <tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>capture_file_name</td> <td>&#10004;</td> <td>string</td> <td>Capture file name</td> </tr> <tr><td>capture_file_name</td> <td>&#10004;</td> <td>string</td> <td>Capture file name</td> </tr>
<tr><td>data_link_type</td> <td> </td> <td>string</td> <td>PCAP data link type</td> </tr> <tr><td>data_link_type</td> <td> </td> <td>enum</td> <td>Possible values: DLT_ATM_RFC1483, DLT_EN10MB, DLT_FRELAY, DLT_C_HDLC</td> </tr>
</table> </table>

View File

@ -9,9 +9,9 @@ Stop a packet capture on a Dynamips device instance
Parameters Parameters
********** **********
- **project_id**: UUID for the project
- **port_number**: Port on the device - **port_number**: Port on the device
- **device_id**: UUID for the instance - **device_id**: UUID for the instance
- **project_id**: UUID for the project
Response status codes Response status codes
********************** **********************

View File

@ -5,7 +5,7 @@
GET /v2/compute/virtualbox/vms GET /v2/compute/virtualbox/vms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get all VirtualBox VMs available Get all available VirtualBox VMs
Response status codes Response status codes
********************** **********************

View File

@ -40,3 +40,12 @@ Output
<tr><td>version</td> <td> </td> <td>['string', 'null']</td> <td>Version of the GNS3 remote compute</td> </tr> <tr><td>version</td> <td> </td> <td>['string', 'null']</td> <td>Version of the GNS3 remote compute</td> </tr>
</table> </table>
GET /v2/computes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
List compute nodes
Response status codes
**********************
- **200**: Compute list

View File

@ -22,6 +22,9 @@ Input
<table> <table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr> <tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>capture_file_name</td> <td> </td> <td>['string', 'null']</td> <td>Read only propertie. The name of the capture file if capture is running</td> </tr>
<tr><td>capture_file_path</td> <td> </td> <td>['string', 'null']</td> <td>Read only propertie. The full path of the capture file if capture is running</td> </tr>
<tr><td>capturing</td> <td> </td> <td>boolean</td> <td>Read only propertie. True if a capture running on the link</td> </tr>
<tr><td>link_id</td> <td> </td> <td>string</td> <td>Link identifier</td> </tr> <tr><td>link_id</td> <td> </td> <td>string</td> <td>Link identifier</td> </tr>
<tr><td>vms</td> <td>&#10004;</td> <td>array</td> <td>List of the VMS</td> </tr> <tr><td>vms</td> <td>&#10004;</td> <td>array</td> <td>List of the VMS</td> </tr>
</table> </table>
@ -32,6 +35,9 @@ Output
<table> <table>
<tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr> <tr> <th>Name</th> <th>Mandatory</th> <th>Type</th> <th>Description</th> </tr>
<tr><td>capture_file_name</td> <td> </td> <td>['string', 'null']</td> <td>Read only propertie. The name of the capture file if capture is running</td> </tr>
<tr><td>capture_file_path</td> <td> </td> <td>['string', 'null']</td> <td>Read only propertie. The full path of the capture file if capture is running</td> </tr>
<tr><td>capturing</td> <td> </td> <td>boolean</td> <td>Read only propertie. True if a capture running on the link</td> </tr>
<tr><td>link_id</td> <td> </td> <td>string</td> <td>Link identifier</td> </tr> <tr><td>link_id</td> <td> </td> <td>string</td> <td>Link identifier</td> </tr>
<tr><td>vms</td> <td>&#10004;</td> <td>array</td> <td>List of the VMS</td> </tr> <tr><td>vms</td> <td>&#10004;</td> <td>array</td> <td>List of the VMS</td> </tr>
</table> </table>

View File

@ -9,8 +9,8 @@ Delete a link instance
Parameters Parameters
********** **********
- **link_id**: UUID of the link
- **project_id**: UUID for the project - **project_id**: UUID for the project
- **link_id**: UUID of the link
Response status codes Response status codes
********************** **********************

View File

@ -42,3 +42,12 @@ Sample session
.. literalinclude:: ../../../examples/controller_post_projects.txt .. literalinclude:: ../../../examples/controller_post_projects.txt
GET /v2/projects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
List projects
Response status codes
**********************
- **200**: List of projects

View File

@ -40,14 +40,14 @@ from .nios.nio_tap import NIOTAP
from .nios.nio_nat import NIONAT from .nios.nio_nat import NIONAT
from .nios.nio_generic_ethernet import NIOGenericEthernet from .nios.nio_generic_ethernet import NIOGenericEthernet
from ..utils.images import md5sum, remove_checksum from ..utils.images import md5sum, remove_checksum
from .vm_error import VMError from .node_error import NodeError
class BaseManager: class BaseManager:
""" """
Base class for all Manager classes. Base class for all Manager classes.
Responsible of management of a VM pool of the same type. Responsible of management of a node pool of the same type.
""" """
_convert_lock = None _convert_lock = None
@ -55,7 +55,7 @@ class BaseManager:
def __init__(self): def __init__(self):
BaseManager._convert_lock = asyncio.Lock() BaseManager._convert_lock = asyncio.Lock()
self._vms = {} self._nodes = {}
self._port_manager = None self._port_manager = None
self._config = Config.instance() self._config = Config.instance()
@ -110,8 +110,8 @@ class BaseManager:
def unload(self): def unload(self):
tasks = [] tasks = []
for vm_id in self._vms.keys(): for node_id in self._nodes.keys():
tasks.append(asyncio.async(self.close_vm(vm_id))) tasks.append(asyncio.async(self.close_node(node_id)))
if tasks: if tasks:
done, _ = yield from asyncio.wait(tasks) done, _ = yield from asyncio.wait(tasks)
@ -119,21 +119,21 @@ class BaseManager:
try: try:
future.result() future.result()
except (Exception, GeneratorExit) as e: except (Exception, GeneratorExit) as e:
log.error("Could not close VM {}".format(e), exc_info=1) log.error("Could not close node {}".format(e), exc_info=1)
continue continue
if hasattr(BaseManager, "_instance"): if hasattr(BaseManager, "_instance"):
BaseManager._instance = None BaseManager._instance = None
log.debug("Module {} unloaded".format(self.module_name)) log.debug("Module {} unloaded".format(self.module_name))
def get_vm(self, vm_id, project_id=None): def get_node(self, node_id, project_id=None):
""" """
Returns a VM instance. Returns a Node instance.
:param vm_id: VM identifier :param node_id: Node identifier
:param project_id: Project identifier :param project_id: Project identifier
:returns: VM instance :returns: Node instance
""" """
if project_id: if project_id:
@ -141,19 +141,19 @@ class BaseManager:
project = ProjectManager.instance().get_project(project_id) project = ProjectManager.instance().get_project(project_id)
try: try:
UUID(vm_id, version=4) UUID(node_id, version=4)
except ValueError: except ValueError:
raise aiohttp.web.HTTPBadRequest(text="VM ID {} is not a valid UUID".format(vm_id)) raise aiohttp.web.HTTPBadRequest(text="Node ID {} is not a valid UUID".format(node_id))
if vm_id not in self._vms: if node_id not in self._nodes:
raise aiohttp.web.HTTPNotFound(text="VM ID {} doesn't exist".format(vm_id)) raise aiohttp.web.HTTPNotFound(text="Node ID {} doesn't exist".format(node_id))
vm = self._vms[vm_id] node = self._nodes[node_id]
if project_id: if project_id:
if vm.project.id != project.id: if node.project.id != project.id:
raise aiohttp.web.HTTPNotFound(text="Project ID {} doesn't belong to VM {}".format(project_id, vm.name)) raise aiohttp.web.HTTPNotFound(text="Project ID {} doesn't belong to node {}".format(project_id, node.name))
return vm return node
@asyncio.coroutine @asyncio.coroutine
def convert_old_project(self, project, legacy_id, name): def convert_old_project(self, project, legacy_id, name):
@ -194,8 +194,8 @@ class BaseManager:
new_remote_project_path, e)) new_remote_project_path, e))
if hasattr(self, "get_legacy_vm_workdir"): if hasattr(self, "get_legacy_vm_workdir"):
# rename old project VM working dir # rename old project node working dir
log.info("Converting old VM working directory...") log.info("Converting old node working directory...")
legacy_vm_dir = self.get_legacy_vm_workdir(legacy_id, name) legacy_vm_dir = self.get_legacy_vm_workdir(legacy_id, name)
legacy_vm_working_path = os.path.join(new_project_files_path, legacy_vm_dir) legacy_vm_working_path = os.path.join(new_project_files_path, legacy_vm_dir)
new_vm_working_path = os.path.join(new_project_files_path, self.module_name.lower(), new_id) new_vm_working_path = os.path.join(new_project_files_path, self.module_name.lower(), new_id)
@ -204,57 +204,58 @@ class BaseManager:
log.info('Moving "{}" to "{}"'.format(legacy_vm_working_path, new_vm_working_path)) log.info('Moving "{}" to "{}"'.format(legacy_vm_working_path, new_vm_working_path))
yield from wait_run_in_executor(shutil.move, legacy_vm_working_path, new_vm_working_path) yield from wait_run_in_executor(shutil.move, legacy_vm_working_path, new_vm_working_path)
except OSError as e: except OSError as e:
raise aiohttp.web.HTTPInternalServerError(text="Could not move VM working directory: {} to {} {}".format(legacy_vm_working_path, raise aiohttp.web.HTTPInternalServerError(text="Could not move vm working directory: {} to {} {}".format(legacy_vm_working_path,
new_vm_working_path, e)) new_vm_working_path,e))
return new_id return new_id
@asyncio.coroutine @asyncio.coroutine
def create_vm(self, name, project_id, vm_id, *args, **kwargs): def create_node(self, name, project_id, node_id, *args, **kwargs):
""" """
Create a new VM Create a new node
:param name: VM name :param name: Node name
:param project_id: Project identifier :param project_id: Project identifier
:param vm_id: restore a VM identifier :param node_id: restore a node identifier
""" """
if vm_id in self._vms: if node_id in self._nodes:
return self._vms[vm_id] return self._nodes[node_id]
project = ProjectManager.instance().get_project(project_id) project = ProjectManager.instance().get_project(project_id)
if vm_id and isinstance(vm_id, int): if node_id and isinstance(node_id, int):
# old project
with (yield from BaseManager._convert_lock): with (yield from BaseManager._convert_lock):
vm_id = yield from self.convert_old_project(project, vm_id, name) node_id = yield from self.convert_old_project(project, node_id, name)
if not vm_id: if not node_id:
vm_id = str(uuid4()) node_id = str(uuid4())
vm = self._VM_CLASS(name, vm_id, project, self, *args, **kwargs) node = self._NODE_CLASS(name, node_id, project, self, *args, **kwargs)
if asyncio.iscoroutinefunction(vm.create): if asyncio.iscoroutinefunction(node.create):
yield from vm.create() yield from node.create()
else: else:
vm.create() node.create()
self._vms[vm.id] = vm self._nodes[node.id] = node
project.add_vm(vm) project.add_node(node)
return vm return node
@asyncio.coroutine @asyncio.coroutine
def close_vm(self, vm_id): def close_node(self, node_id):
""" """
Close a VM Close a node
:param vm_id: VM identifier :param node_id: Node identifier
:returns: VM instance :returns: Node instance
""" """
vm = self.get_vm(vm_id) node = self.get_node(node_id)
if asyncio.iscoroutinefunction(vm.close): if asyncio.iscoroutinefunction(node.close):
yield from vm.close() yield from node.close()
else: else:
vm.close() node.close()
return vm return node
@asyncio.coroutine @asyncio.coroutine
def project_closing(self, project): def project_closing(self, project):
@ -274,9 +275,9 @@ class BaseManager:
:param project: Project instance :param project: Project instance
""" """
for vm in project.vms: for node in project.nodes:
if vm.id in self._vms: if node.id in self._nodes:
del self._vms[vm.id] del self._nodes[node.id]
@asyncio.coroutine @asyncio.coroutine
def project_moved(self, project): def project_moved(self, project):
@ -299,20 +300,19 @@ class BaseManager:
pass pass
@asyncio.coroutine @asyncio.coroutine
def delete_vm(self, vm_id): def delete_node(self, node_id):
""" """
Delete a VM. VM working directory will be destroy when Delete a node. The node working directory will be destroyed when a commit is received.
we receive a commit.
:param vm_id: VM identifier :param node_id: Node identifier
:returns: VM instance :returns: Node instance
""" """
vm = yield from self.close_vm(vm_id) node = yield from self.close_node(node_id)
vm.project.mark_vm_for_destruction(vm) node.project.mark_node_for_destruction(node)
if vm.id in self._vms: if node.id in self._nodes:
del self._vms[vm.id] del self._nodes[node.id]
return vm return node
@staticmethod @staticmethod
def has_privileged_access(executable): def has_privileged_access(executable):
@ -408,7 +408,7 @@ class BaseManager:
# Windows path should not be send to a unix server # Windows path should not be send to a unix server
if not sys.platform.startswith("win"): if not sys.platform.startswith("win"):
if re.match(r"^[A-Z]:", path) is not None: if re.match(r"^[A-Z]:", path) is not None:
raise VMError("{} is not allowed on this remote server. Please use only a filename in {}.".format(path, img_directory)) raise NodeError("{} is not allowed on this remote server. Please use only a filename in {}.".format(path, img_directory))
if not os.path.isabs(path): if not os.path.isabs(path):
s = os.path.split(path) s = os.path.split(path)
@ -429,7 +429,7 @@ class BaseManager:
img_directory = force_unix_path(img_directory) img_directory = force_unix_path(img_directory)
path = force_unix_path(path) path = force_unix_path(path)
if len(os.path.commonprefix([img_directory, path])) < len(img_directory): if len(os.path.commonprefix([img_directory, path])) < len(img_directory):
raise VMError("{} is not allowed on this remote server. Please use only a filename in {}.".format(path, img_directory)) raise NodeError("{} is not allowed on this remote server. Please use only a filename in {}.".format(path, img_directory))
return force_unix_path(path) return force_unix_path(path)
@ -454,7 +454,7 @@ class BaseManager:
@asyncio.coroutine @asyncio.coroutine
def list_images(self): def list_images(self):
""" """
Return the list of available images for this VM type Return the list of available images for this node type
:returns: Array of hash :returns: Array of hash
""" """

View File

@ -24,34 +24,33 @@ import tempfile
import psutil import psutil
import platform import platform
from gns3server.utils import parse_version
from ..utils.asyncio import wait_run_in_executor from ..utils.asyncio import wait_run_in_executor
from ..ubridge.hypervisor import Hypervisor from ..ubridge.hypervisor import Hypervisor
from .vm_error import VMError from .node_error import NodeError
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class BaseVM: class BaseNode:
""" """
Base vm implementation. Base node implementation.
:param name: name of this IOU vm :param name: name of this node
:param vm_id: IOU instance identifier :param node_id: Node instance identifier
:param project: Project instance :param project: Project instance
:param manager: parent VM Manager :param manager: parent node manager
:param console: TCP console port :param console: TCP console port
:param aux: TCP aux console port :param aux: TCP aux console port
:param allocate_aux: Boolean if true will allocate an aux console port :param allocate_aux: Boolean if true will allocate an aux console port
""" """
def __init__(self, name, vm_id, project, manager, console=None, console_type="telnet", aux=None, allocate_aux=False): def __init__(self, name, node_id, project, manager, console=None, console_type="telnet", aux=None, allocate_aux=False):
self._name = name self._name = name
self._usage = "" self._usage = ""
self._id = vm_id self._id = node_id
self._project = project self._project = project
self._manager = manager self._manager = manager
self._console = console self._console = console
@ -61,7 +60,7 @@ class BaseVM:
self._hw_virtualization = False self._hw_virtualization = False
self._ubridge_hypervisor = None self._ubridge_hypervisor = None
self._closed = False self._closed = False
self._vm_status = "stopped" self._node_status = "stopped"
self._command_line = "" self._command_line = ""
self._allocate_aux = allocate_aux self._allocate_aux = allocate_aux
@ -98,19 +97,19 @@ class BaseVM:
@property @property
def status(self): def status(self):
"""Return current VM status""" """Return current node status"""
return self._vm_status return self._node_status
@status.setter @status.setter
def status(self, status): def status(self, status):
self._vm_status = status self._node_status = status
self._project.emit("vm.{}".format(status), self) self._project.emit("node.{}".format(status), self)
@property @property
def command_line(self): def command_line(self):
"""Return command used to start the VM""" """Return command used to start the node"""
return self._command_line return self._command_line
@ -122,7 +121,7 @@ class BaseVM:
@property @property
def project(self): def project(self):
""" """
Returns the VM current project. Returns the node current project.
:returns: Project instance. :returns: Project instance.
""" """
@ -132,7 +131,7 @@ class BaseVM:
@property @property
def name(self): def name(self):
""" """
Returns the name for this VM. Returns the name for this node.
:returns: name :returns: name
""" """
@ -142,7 +141,7 @@ class BaseVM:
@name.setter @name.setter
def name(self, new_name): def name(self, new_name):
""" """
Sets the name of this VM. Sets the name of this node.
:param new_name: name :param new_name: name
""" """
@ -156,7 +155,7 @@ class BaseVM:
@property @property
def usage(self): def usage(self):
""" """
Returns the usage for this VM. Returns the usage for this node.
:returns: usage :returns: usage
""" """
@ -166,7 +165,7 @@ class BaseVM:
@usage.setter @usage.setter
def usage(self, new_usage): def usage(self, new_usage):
""" """
Sets the usage of this VM. Sets the usage of this node.
:param new_usage: usage :param new_usage: usage
""" """
@ -176,9 +175,9 @@ class BaseVM:
@property @property
def id(self): def id(self):
""" """
Returns the ID for this VM. Returns the ID for this node.
:returns: VM identifier (string) :returns: Node identifier (string)
""" """
return self._id return self._id
@ -186,7 +185,7 @@ class BaseVM:
@property @property
def manager(self): def manager(self):
""" """
Returns the manager for this VM. Returns the manager for this node.
:returns: instance of manager :returns: instance of manager
""" """
@ -196,10 +195,10 @@ class BaseVM:
@property @property
def working_dir(self): def working_dir(self):
""" """
Return VM working directory Return the node working directory
""" """
return self._project.vm_working_directory(self) return self._project.node_working_directory(self)
@property @property
def temporary_directory(self): def temporary_directory(self):
@ -207,43 +206,43 @@ class BaseVM:
try: try:
self._temporary_directory = tempfile.mkdtemp() self._temporary_directory = tempfile.mkdtemp()
except OSError as e: except OSError as e:
raise VMError("Can't create temporary directory: {}".format(e)) raise NodeError("Can't create temporary directory: {}".format(e))
return self._temporary_directory return self._temporary_directory
def create(self): def create(self):
""" """
Creates the VM. Creates the node.
""" """
log.info("{module}: {name} [{id}] created".format(module=self.manager.module_name, log.info("{module}: {name} [{id}] created".format(module=self.manager.module_name,
name=self.name, name=self.name,
id=self.id)) id=self.id))
self._project.emit("vm.created", self) self._project.emit("node.created", self)
@asyncio.coroutine @asyncio.coroutine
def delete(self): def delete(self):
""" """
Delete the VM (including all its files). Delete the node (including all its files).
""" """
self._project.emit("vm.deleted", self) self._project.emit("node.deleted", self)
directory = self.project.vm_working_directory(self) directory = self.project.node_working_directory(self)
if os.path.exists(directory): if os.path.exists(directory):
try: try:
yield from wait_run_in_executor(shutil.rmtree, directory) yield from wait_run_in_executor(shutil.rmtree, directory)
except OSError as e: except OSError as e:
raise aiohttp.web.HTTPInternalServerError(text="Could not delete the VM working directory: {}".format(e)) raise aiohttp.web.HTTPInternalServerError(text="Could not delete the node working directory: {}".format(e))
def start(self): def start(self):
""" """
Starts the VM process. Starts the node process.
""" """
raise NotImplementedError raise NotImplementedError
def stop(self): def stop(self):
""" """
Starts the VM process. Starts the node process.
""" """
raise NotImplementedError raise NotImplementedError
@ -251,7 +250,7 @@ class BaseVM:
@asyncio.coroutine @asyncio.coroutine
def close(self): def close(self):
""" """
Close the VM process. Close the node process.
""" """
if self._closed: if self._closed:
@ -290,7 +289,7 @@ class BaseVM:
@property @property
def aux(self): def aux(self):
""" """
Returns the aux console port of this VM. Returns the aux console port of this node.
:returns: aux console port :returns: aux console port
""" """
@ -321,7 +320,7 @@ class BaseVM:
@property @property
def console(self): def console(self):
""" """
Returns the console port of this VM. Returns the console port of this node.
:returns: console port :returns: console port
""" """
@ -340,7 +339,7 @@ class BaseVM:
return return
if self._console_type == "vnc" and console is not None and console < 5900: if self._console_type == "vnc" and console is not None and console < 5900:
raise VMError("VNC console require a port superior or equal to 5900 currently it's {}".format(console)) raise NodeError("VNC console require a port superior or equal to 5900 currently it's {}".format(console))
if self._console: if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project) self._manager.port_manager.release_tcp_port(self._console, self._project)
@ -359,7 +358,7 @@ class BaseVM:
@property @property
def console_type(self): def console_type(self):
""" """
Returns the console type for this VM. Returns the console type for this node.
:returns: console type (string) :returns: console type (string)
""" """
@ -369,15 +368,11 @@ class BaseVM:
@console_type.setter @console_type.setter
def console_type(self, console_type): def console_type(self, console_type):
""" """
Sets the console type for this VM. Sets the console type for this node.
:param console_type: console type (string) :param console_type: console type (string)
""" """
log.info('QEMU VM "{name}" [{id}] has set the console type to {console_type}'.format(name=self._name,
id=self._id,
console_type=console_type))
if console_type != self._console_type: if console_type != self._console_type:
# get a new port if the console type change # get a new port if the console type change
self._manager.port_manager.release_tcp_port(self._console, self._project) self._manager.port_manager.release_tcp_port(self._console, self._project)
@ -406,17 +401,17 @@ class BaseVM:
path = shutil.which("ubridge") path = shutil.which("ubridge")
if path is None or len(path) == 0: if path is None or len(path) == 0:
raise VMError("uBridge is not installed") raise NodeError("uBridge is not installed")
return path return path
@asyncio.coroutine @asyncio.coroutine
def _start_ubridge(self): def _start_ubridge(self):
""" """
Starts uBridge (handles connections to and from this VMware VM). Starts uBridge (handles connections to and from this node).
""" """
if not self._manager.has_privileged_access(self.ubridge_path): if not self._manager.has_privileged_access(self.ubridge_path):
raise VMError("uBridge requires root access or capability to interact with network adapters") raise NodeError("uBridge requires root access or capability to interact with network adapters")
server_config = self._manager.config.get_section_config("Server") server_config = self._manager.config.get_section_config("Server")
server_host = server_config.get("host") server_host = server_config.get("host")
@ -430,7 +425,7 @@ class BaseVM:
@property @property
def hw_virtualization(self): def hw_virtualization(self):
""" """
Returns either the VM is using hardware virtualization or not. Returns either the node is using hardware virtualization or not.
:return: boolean :return: boolean
""" """

View File

@ -37,7 +37,7 @@ DOCKER_MINIMUM_API_VERSION = "1.21"
class Docker(BaseManager): class Docker(BaseManager):
_VM_CLASS = DockerVM _NODE_CLASS = DockerVM
def __init__(self): def __init__(self):
super().__init__() super().__init__()

View File

@ -19,10 +19,10 @@
Custom exceptions for the Docker module. Custom exceptions for the Docker module.
""" """
from ..vm_error import VMError from ..node_error import NodeError
class DockerError(VMError): class DockerError(NodeError):
pass pass

View File

@ -27,9 +27,8 @@ import aiohttp
import json import json
import os import os
from ...ubridge.hypervisor import Hypervisor
from .docker_error import * from .docker_error import *
from ..base_vm import BaseVM from ..base_node import BaseNode
from ..adapters.ethernet_adapter import EthernetAdapter from ..adapters.ethernet_adapter import EthernetAdapter
from ..nios.nio_udp import NIOUDP from ..nios.nio_udp import NIOUDP
from ...utils.asyncio.telnet_server import AsyncioTelnetServer from ...utils.asyncio.telnet_server import AsyncioTelnetServer
@ -43,11 +42,11 @@ import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class DockerVM(BaseVM): class DockerVM(BaseNode):
"""Docker container implementation. """Docker container implementation.
:param name: Docker container name :param name: Docker container name
:param vm_id: Docker VM identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Manager instance :param manager: Manager instance
:param image: Docker image :param image: Docker image
@ -59,11 +58,11 @@ class DockerVM(BaseVM):
:param console_http_path: Url part with the path of the web interface :param console_http_path: Url part with the path of the web interface
""" """
def __init__(self, name, vm_id, project, manager, image, def __init__(self, name, node_id, project, manager, image,
console=None, aux=None, start_command=None, console=None, aux=None, start_command=None,
adapters=None, environment=None, console_type="telnet", adapters=None, environment=None, console_type="telnet",
console_resolution="1024x768", console_http_port=80, console_http_path="/"): console_resolution="1024x768", console_http_port=80, console_http_path="/"):
super().__init__(name, vm_id, project, manager, console=console, aux=aux, allocate_aux=True, console_type=console_type) super().__init__(name, node_id, project, manager, console=console, aux=aux, allocate_aux=True, console_type=console_type)
self._image = image self._image = image
self._start_command = start_command self._start_command = start_command
@ -93,7 +92,7 @@ class DockerVM(BaseVM):
def __json__(self): def __json__(self):
return { return {
"name": self._name, "name": self._name,
"vm_id": self._id, "node_id": self._id,
"container_id": self._cid, "container_id": self._cid,
"project_id": self._project.id, "project_id": self._project.id,
"image": self._image, "image": self._image,
@ -757,7 +756,7 @@ class DockerVM(BaseVM):
adapter = "bridge{}".format(adapter_number) adapter = "bridge{}".format(adapter_number)
if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running():
raise VMwareError("Cannot start the packet capture: uBridge is not running") raise DockerError("Cannot start the packet capture: uBridge is not running")
yield from self._ubridge_hypervisor.send('bridge start_capture {name} "{output_file}"'.format(name=adapter, output_file=output_file)) yield from self._ubridge_hypervisor.send('bridge start_capture {name} "{output_file}"'.format(name=adapter, output_file=output_file))
@asyncio.coroutine @asyncio.coroutine
@ -770,7 +769,7 @@ class DockerVM(BaseVM):
adapter = "bridge{}".format(adapter_number) adapter = "bridge{}".format(adapter_number)
if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running():
raise VMwareError("Cannot stop the packet capture: uBridge is not running") raise DockerError("Cannot stop the packet capture: uBridge is not running")
yield from self._ubridge_hypervisor.send("bridge stop_capture {name}".format(name=adapter)) yield from self._ubridge_hypervisor.send("bridge stop_capture {name}".format(name=adapter))
@asyncio.coroutine @asyncio.coroutine

View File

@ -102,7 +102,7 @@ WIC_MATRIX = {"WIC-1ENET": WIC_1ENET,
class Dynamips(BaseManager): class Dynamips(BaseManager):
_VM_CLASS = DynamipsVM _NODE_CLASS = DynamipsVM
_DEVICE_CLASS = DynamipsDevice _DEVICE_CLASS = DynamipsDevice
_ghost_ios_lock = None _ghost_ios_lock = None
@ -142,7 +142,7 @@ class Dynamips(BaseManager):
def release_dynamips_id(self, project_id, dynamips_id): def release_dynamips_id(self, project_id, dynamips_id):
""" """
A dynamips id can be reused by another vm A Dynamips id can be reused by another VM
:param project_id: UUID of the project :param project_id: UUID of the project
:param dynamips_id: Asked id :param dynamips_id: Asked id
@ -231,9 +231,9 @@ class Dynamips(BaseManager):
:param project: Project instance :param project: Project instance
""" """
for vm in self._vms.values(): for node in self._nodes.values():
if vm.project.id == project.id: if node.project.id == project.id:
yield from vm.hypervisor.set_working_dir(project.module_working_directory(self.module_name.lower())) yield from node.hypervisor.set_working_dir(project.module_working_directory(self.module_name.lower()))
for device in self._devices.values(): for device in self._devices.values():
if device.project.id == project.id: if device.project.id == project.id:
@ -248,10 +248,10 @@ class Dynamips(BaseManager):
""" """
# save the configs when the project is committed # save the configs when the project is committed
for vm in self._vms.copy().values(): for node in self._nodes.copy().values():
if vm.project.id == project.id: if node.project.id == project.id:
try: try:
yield from vm.save_configs() yield from node.save_configs()
except DynamipsError as e: except DynamipsError as e:
log.warning(e) log.warning(e)
continue continue
@ -273,7 +273,6 @@ class Dynamips(BaseManager):
:param name: Device name :param name: Device name
:param project_id: Project identifier :param project_id: Project identifier
:param vm_id: restore a VM identifier
""" """
project = ProjectManager.instance().get_project(project_id) project = ProjectManager.instance().get_project(project_id)

View File

@ -19,9 +19,9 @@
Custom exceptions for the Dynamips module. Custom exceptions for the Dynamips module.
""" """
from ..vm_error import VMError from ..node_error import NodeError
class DynamipsError(VMError): class DynamipsError(NodeError):
pass pass

View File

@ -43,9 +43,9 @@ class DynamipsVM:
Factory to create an Router object based on the correct platform. Factory to create an Router object based on the correct platform.
""" """
def __new__(cls, name, vm_id, project, manager, dynamips_id, platform, **kwargs): def __new__(cls, name, node_id, project, manager, dynamips_id, platform, **kwargs):
if platform not in PLATFORMS: if platform not in PLATFORMS:
raise DynamipsError("Unknown router platform: {}".format(platform)) raise DynamipsError("Unknown router platform: {}".format(platform))
return PLATFORMS[platform](name, vm_id, project, manager, dynamips_id, **kwargs) return PLATFORMS[platform](name, node_id, project, manager, dynamips_id, **kwargs)

View File

@ -35,7 +35,7 @@ class C1700(Router):
Dynamips c1700 router. Dynamips c1700 router.
:param name: The name of this router :param name: The name of this router
:param vm_id: Router instance identifier :param node_id: Node instance identifier
:param project: Project instance :param project: Project instance
:param manager: Parent VM Manager :param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips :param dynamips_id: ID to use with Dynamips
@ -46,9 +46,9 @@ class C1700(Router):
1710 is not supported. 1710 is not supported.
""" """
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="1720"): def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis="1720"):
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c1700") super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c1700")
# Set default values for this platform (must be the same as Dynamips) # Set default values for this platform (must be the same as Dynamips)
self._ram = 64 self._ram = 64

View File

@ -37,7 +37,7 @@ class C2600(Router):
Dynamips c2600 router. Dynamips c2600 router.
:param name: The name of this router :param name: The name of this router
:param vm_id: Router instance identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Parent VM Manager :param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips :param dynamips_id: ID to use with Dynamips
@ -61,9 +61,9 @@ class C2600(Router):
"2650XM": C2600_MB_1FE, "2650XM": C2600_MB_1FE,
"2651XM": C2600_MB_2FE} "2651XM": C2600_MB_2FE}
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="2610"): def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis="2610"):
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c2600") super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c2600")
# Set default values for this platform (must be the same as Dynamips) # Set default values for this platform (must be the same as Dynamips)
self._ram = 64 self._ram = 64

View File

@ -35,7 +35,7 @@ class C2691(Router):
Dynamips c2691 router. Dynamips c2691 router.
:param name: The name of this router :param name: The name of this router
:param vm_id: Router instance identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Parent VM Manager :param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips :param dynamips_id: ID to use with Dynamips
@ -43,9 +43,9 @@ class C2691(Router):
:param aux: auxiliary console port :param aux: auxiliary console port
""" """
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c2691") super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c2691")
# Set default values for this platform (must be the same as Dynamips) # Set default values for this platform (must be the same as Dynamips)
self._ram = 128 self._ram = 128

View File

@ -34,7 +34,7 @@ class C3600(Router):
Dynamips c3600 router. Dynamips c3600 router.
:param name: The name of this router :param name: The name of this router
:param vm_id: Router instance identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Parent VM Manager :param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips :param dynamips_id: ID to use with Dynamips
@ -44,9 +44,9 @@ class C3600(Router):
3620, 3640 or 3660 (default = 3640). 3620, 3640 or 3660 (default = 3640).
""" """
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="3640"): def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis="3640"):
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3600") super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c3600")
# Set default values for this platform (must be the same as Dynamips) # Set default values for this platform (must be the same as Dynamips)
self._ram = 128 self._ram = 128

View File

@ -35,7 +35,7 @@ class C3725(Router):
Dynamips c3725 router. Dynamips c3725 router.
:param name: The name of this router :param name: The name of this router
:param vm_id: Router instance identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Parent VM Manager :param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips :param dynamips_id: ID to use with Dynamips
@ -43,9 +43,9 @@ class C3725(Router):
:param aux: auxiliary console port :param aux: auxiliary console port
""" """
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3725") super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c3725")
# Set default values for this platform (must be the same as Dynamips) # Set default values for this platform (must be the same as Dynamips)
self._ram = 128 self._ram = 128

View File

@ -35,7 +35,7 @@ class C3745(Router):
Dynamips c3745 router. Dynamips c3745 router.
:param name: The name of this router :param name: The name of this router
:param vm_id: Router instance identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Parent VM Manager :param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips :param dynamips_id: ID to use with Dynamips
@ -43,9 +43,9 @@ class C3745(Router):
:param aux: auxiliary console port :param aux: auxiliary console port
""" """
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3745") super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c3745")
# Set default values for this platform (must be the same as Dynamips) # Set default values for this platform (must be the same as Dynamips)
self._ram = 128 self._ram = 128

View File

@ -37,7 +37,7 @@ class C7200(Router):
Dynamips c7200 router (model is 7206). Dynamips c7200 router (model is 7206).
:param name: The name of this router :param name: The name of this router
:param vm_id: Router instance identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Parent VM Manager :param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips :param dynamips_id: ID to use with Dynamips
@ -46,9 +46,9 @@ class C7200(Router):
:param npe: Default NPE :param npe: Default NPE
""" """
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, npe="npe-400", chassis=None): def __init__(self, name, node_id, project, manager, dynamips_id, console=None, aux=None, npe="npe-400", chassis=None):
super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c7200") super().__init__(name, node_id, project, manager, dynamips_id, console, aux, platform="c7200")
# Set default values for this platform (must be the same as Dynamips) # Set default values for this platform (must be the same as Dynamips)
self._ram = 256 self._ram = 256

View File

@ -69,7 +69,7 @@ class Device:
@name.setter @name.setter
def name(self, new_name): def name(self, new_name):
""" """
Sets the name of this VM. Sets the name of this device.
:param new_name: name :param new_name: name
""" """

View File

@ -31,7 +31,7 @@ import binascii
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
from ...base_vm import BaseVM from ...base_node import BaseNode
from ..dynamips_error import DynamipsError from ..dynamips_error import DynamipsError
from ..nios.nio_udp import NIOUDP from ..nios.nio_udp import NIOUDP
@ -39,13 +39,13 @@ from gns3server.utils.asyncio import wait_run_in_executor, monitor_process
from gns3server.utils.images import md5sum from gns3server.utils.images import md5sum
class Router(BaseVM): class Router(BaseNode):
""" """
Dynamips router implementation. Dynamips router implementation.
:param name: The name of this router :param name: The name of this router
:param vm_id: Router instance identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Parent VM Manager :param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips :param dynamips_id: ID to use with Dynamips
@ -59,11 +59,11 @@ class Router(BaseVM):
2: "running", 2: "running",
3: "suspended"} 3: "suspended"}
def __init__(self, name, vm_id, project, manager, dynamips_id=None, console=None, aux=None, platform="c7200", hypervisor=None, ghost_flag=False): def __init__(self, name, node_id, project, manager, dynamips_id=None, console=None, aux=None, platform="c7200", hypervisor=None, ghost_flag=False):
allocate_aux = manager.config.get_section_config("Dynamips").getboolean("allocate_aux_console_ports", False) allocate_aux = manager.config.get_section_config("Dynamips").getboolean("allocate_aux_console_ports", False)
super().__init__(name, vm_id, project, manager, console=console, aux=aux, allocate_aux=aux) super().__init__(name, node_id, project, manager, console=console, aux=aux, allocate_aux=aux)
self._hypervisor = hypervisor self._hypervisor = hypervisor
self._dynamips_id = dynamips_id self._dynamips_id = dynamips_id
@ -111,7 +111,7 @@ class Router(BaseVM):
def __json__(self): def __json__(self):
router_info = {"name": self.name, router_info = {"name": self.name,
"vm_id": self.id, "node_id": self.id,
"vm_directory": os.path.join(self.project.module_working_directory(self.manager.module_name.lower())), "vm_directory": os.path.join(self.project.module_working_directory(self.manager.module_name.lower())),
"project_id": self.project.id, "project_id": self.project.id,
"dynamips_id": self._dynamips_id, "dynamips_id": self._dynamips_id,
@ -1549,7 +1549,7 @@ class Router(BaseVM):
def delete(self): def delete(self):
""" """
Delete the VM (including all its files). Delete this VM (including all its files).
""" """
# delete the VM files # delete the VM files

View File

@ -32,7 +32,7 @@ log = logging.getLogger(__name__)
class IOU(BaseManager): class IOU(BaseManager):
_VM_CLASS = IOUVM _NODE_CLASS = IOUVM
def __init__(self): def __init__(self):
@ -41,35 +41,35 @@ class IOU(BaseManager):
self._used_application_ids = {} self._used_application_ids = {}
@asyncio.coroutine @asyncio.coroutine
def create_vm(self, *args, **kwargs): def create_node(self, *args, **kwargs):
""" """
Creates a new IOU VM. Creates a new IOU VM.
:returns: IOUVM instance :returns: IOUVM instance
""" """
vm = yield from super().create_vm(*args, **kwargs) node = yield from super().create_node(*args, **kwargs)
try: try:
self._used_application_ids[vm.id] = self._free_application_ids.pop(0) self._used_application_ids[node.id] = self._free_application_ids.pop(0)
except IndexError: except IndexError:
raise IOUError("Cannot create a new IOU VM (limit of 512 VMs reached on this host)") raise IOUError("Cannot create a new IOU VM (limit of 512 VMs reached on this host)")
return vm return node
@asyncio.coroutine @asyncio.coroutine
def close_vm(self, vm_id, *args, **kwargs): def close_node(self, node_id, *args, **kwargs):
""" """
Closes an IOU VM. Closes an IOU VM.
:returns: IOUVM instance :returns: IOUVM instance
""" """
vm = self.get_vm(vm_id) node = self.get_node(node_id)
if vm_id in self._used_application_ids: if node_id in self._used_application_ids:
i = self._used_application_ids[vm_id] i = self._used_application_ids[node_id]
self._free_application_ids.insert(0, i) self._free_application_ids.insert(0, i)
del self._used_application_ids[vm_id] del self._used_application_ids[node_id]
yield from super().close_vm(vm_id, *args, **kwargs) yield from super().close_node(node_id, *args, **kwargs)
return vm return node
@asyncio.coroutine @asyncio.coroutine
def project_committed(self, project): def project_committed(self, project):
@ -80,32 +80,32 @@ class IOU(BaseManager):
""" """
# save the configs when the project is committed # save the configs when the project is committed
for vm in self._vms.copy().values(): for node in self._nodes.copy().values():
if vm.project.id == project.id: if node.project.id == project.id:
try: try:
vm.save_configs() node.save_configs()
except IOUError as e: except IOUError as e:
log.warning(e) log.warning(e)
continue continue
def get_application_id(self, vm_id): def get_application_id(self, node_id):
""" """
Get an unique application identifier for IOU. Get an unique application identifier for IOU.
:param vm_id: IOU VM identifier :param node_id: Node identifier
:returns: IOU application identifier :returns: IOU application identifier
""" """
return self._used_application_ids.get(vm_id, 1) return self._used_application_ids.get(node_id, 1)
@staticmethod @staticmethod
def get_legacy_vm_workdir(legacy_vm_id, name): def get_legacy_vm_workdir(legacy_vm_id, name):
""" """
Returns the name of the legacy working directory (pre 1.3) name for a VM. Returns the name of the legacy working directory (pre 1.3) name for a node.
:param legacy_vm_id: legacy VM identifier (integer) :param legacy_vm_id: legacy node identifier (integer)
:param name: VM name (not used) :param name: Node name (not used)
:returns: working directory name :returns: working directory name
""" """

View File

@ -19,8 +19,8 @@
Custom exceptions for the IOU module. Custom exceptions for the IOU module.
""" """
from ..vm_error import VMError from ..node_error import NodeError
class IOUError(VMError): class IOUError(NodeError):
pass pass

View File

@ -42,7 +42,7 @@ from ..adapters.serial_adapter import SerialAdapter
from ..nios.nio_udp import NIOUDP from ..nios.nio_udp import NIOUDP
from ..nios.nio_tap import NIOTAP from ..nios.nio_tap import NIOTAP
from ..nios.nio_generic_ethernet import NIOGenericEthernet from ..nios.nio_generic_ethernet import NIOGenericEthernet
from ..base_vm import BaseVM from ..base_node import BaseNode
from .utils.iou_import import nvram_import from .utils.iou_import import nvram_import
from .utils.iou_export import nvram_export from .utils.iou_export import nvram_export
from .ioucon import start_ioucon from .ioucon import start_ioucon
@ -55,22 +55,22 @@ import sys
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class IOUVM(BaseVM): class IOUVM(BaseNode):
module_name = 'iou' module_name = 'iou'
""" """
IOU VM implementation. IOU VM implementation.
:param name: IOU VM name :param name: IOU VM name
:param vm_id: IOU VM identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Manager instance :param manager: Manager instance
:param console: TCP console port :param console: TCP console port
""" """
def __init__(self, name, vm_id, project, manager, console=None): def __init__(self, name, node_id, project, manager, console=None):
super().__init__(name, vm_id, project, manager, console=console) super().__init__(name, node_id, project, manager, console=console)
self._iouyap_process = None self._iouyap_process = None
self._iou_process = None self._iou_process = None
@ -202,7 +202,7 @@ class IOUVM(BaseVM):
def __json__(self): def __json__(self):
iou_vm_info = {"name": self.name, iou_vm_info = {"name": self.name,
"vm_id": self.id, "node_id": self.id,
"vm_directory": self.working_dir, "vm_directory": self.working_dir,
"console": self._console, "console": self._console,
"project_id": self.project.id, "project_id": self.project.id,
@ -315,7 +315,7 @@ class IOUVM(BaseVM):
new_nvram=nvram)) new_nvram=nvram))
self._nvram = nvram self._nvram = nvram
@BaseVM.name.setter @BaseNode.name.setter
def name(self, new_name): def name(self, new_name):
""" """
Sets the name of this IOU VM. Sets the name of this IOU VM.

View File

@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
class VMError(Exception): class NodeError(Exception):
def __init__(self, message, original_exception=None): def __init__(self, message, original_exception=None):

View File

@ -24,7 +24,7 @@ import zipstream
import zipfile import zipfile
import json import json
from uuid import UUID, uuid4 from uuid import UUID
from .port_manager import PortManager from .port_manager import PortManager
from .notification_manager import NotificationManager from .notification_manager import NotificationManager
from ..config import Config from ..config import Config
@ -38,8 +38,8 @@ log = logging.getLogger(__name__)
class Project: class Project:
""" """
A project contains a list of VM. A project contains a list of nodes.
In theory VM are isolated project/project. In theory nodes are isolated project/project.
:param project_id: force project identifier (None by default auto generate an UUID) :param project_id: force project identifier (None by default auto generate an UUID)
:param path: path of the project. (None use the standard directory) :param path: path of the project. (None use the standard directory)
@ -55,8 +55,8 @@ class Project:
raise aiohttp.web.HTTPBadRequest(text="{} is not a valid UUID".format(project_id)) raise aiohttp.web.HTTPBadRequest(text="{} is not a valid UUID".format(project_id))
self._id = project_id self._id = project_id
self._vms = set() self._nodes = set()
self._vms_to_destroy = set() self._nodes_to_destroy = set()
self.temporary = temporary self.temporary = temporary
self._used_tcp_ports = set() self._used_tcp_ports = set()
self._used_udp_ports = set() self._used_udp_ports = set()
@ -155,9 +155,9 @@ class Project:
self._name = name self._name = name
@property @property
def vms(self): def nodes(self):
return self._vms return self._nodes
@property @property
def temporary(self): def temporary(self):
@ -260,21 +260,21 @@ class Project:
return os.path.join(self._path, "project-files", module_name) return os.path.join(self._path, "project-files", module_name)
def vm_working_directory(self, vm): def node_working_directory(self, node):
""" """
Returns a working directory for a specific VM. Returns a working directory for a specific node.
If the directory doesn't exist, the directory is created. If the directory doesn't exist, the directory is created.
:param vm: VM instance :param node: Node instance
:returns: VM working directory :returns: Node working directory
""" """
workdir = os.path.join(self._path, "project-files", vm.manager.module_name.lower(), vm.id) workdir = os.path.join(self._path, "project-files", node.manager.module_name.lower(), node.id)
try: try:
os.makedirs(workdir, exist_ok=True) os.makedirs(workdir, exist_ok=True)
except OSError as e: except OSError as e:
raise aiohttp.web.HTTPInternalServerError(text="Could not create the VM working directory: {}".format(e)) raise aiohttp.web.HTTPInternalServerError(text="Could not create the node working directory: {}".format(e))
return workdir return workdir
def tmp_working_directory(self): def tmp_working_directory(self):
@ -297,34 +297,34 @@ class Project:
raise aiohttp.web.HTTPInternalServerError(text="Could not create the capture working directory: {}".format(e)) raise aiohttp.web.HTTPInternalServerError(text="Could not create the capture working directory: {}".format(e))
return workdir return workdir
def mark_vm_for_destruction(self, vm): def mark_node_for_destruction(self, node):
""" """
:param vm: An instance of VM :param node: An instance of Node
""" """
self.remove_vm(vm) self.remove_node(node)
self._vms_to_destroy.add(vm) self._nodes_to_destroy.add(node)
def add_vm(self, vm): def add_node(self, node):
""" """
Adds a VM to the project. Adds a node to the project.
In theory this should be called by the VM manager. In theory this should be called by the node manager.
:param vm: VM instance :param node: Node instance
""" """
self._vms.add(vm) self._nodes.add(node)
def remove_vm(self, vm): def remove_node(self, node):
""" """
Removes a VM from the project. Removes a node from the project.
In theory this should be called by the VM manager. In theory this should be called by the node manager.
:param vm: VM instance :param node: Node instance
""" """
if vm in self._vms: if node in self._nodes:
self._vms.remove(vm) self._nodes.remove(node)
@asyncio.coroutine @asyncio.coroutine
def close(self): def close(self):
@ -353,8 +353,8 @@ class Project:
""" """
tasks = [] tasks = []
for vm in self._vms: for node in self._nodes:
tasks.append(asyncio.async(vm.manager.close_vm(vm.id))) tasks.append(asyncio.async(node.manager.close_node(node.id)))
if tasks: if tasks:
done, _ = yield from asyncio.wait(tasks) done, _ = yield from asyncio.wait(tasks)
@ -362,7 +362,7 @@ class Project:
try: try:
future.result() future.result()
except (Exception, GeneratorExit) as e: except (Exception, GeneratorExit) as e:
log.error("Could not close VM or device {}".format(e), exc_info=1) log.error("Could not close node {}".format(e), exc_info=1)
if cleanup and os.path.exists(self.path): if cleanup and os.path.exists(self.path):
try: try:
@ -378,7 +378,7 @@ class Project:
if self._used_udp_ports: if self._used_udp_ports:
log.warning("Project {} has UDP ports still in use: {}".format(self.id, self._used_udp_ports)) log.warning("Project {} has UDP ports still in use: {}".format(self.id, self._used_udp_ports))
# clean the remaining ports that have not been cleaned by their respective VM or device. # clean the remaining ports that have not been cleaned by their respective node.
port_manager = PortManager.instance() port_manager = PortManager.instance()
for port in self._used_tcp_ports.copy(): for port in self._used_tcp_ports.copy():
port_manager.release_tcp_port(port, self) port_manager.release_tcp_port(port, self)
@ -391,10 +391,10 @@ class Project:
Writes project changes on disk Writes project changes on disk
""" """
while self._vms_to_destroy: while self._nodes_to_destroy:
vm = self._vms_to_destroy.pop() node = self._nodes_to_destroy.pop()
yield from vm.delete() yield from node.delete()
self.remove_vm(vm) self.remove_node(node)
for module in self.compute(): for module in self.compute():
yield from module.instance().project_committed(self) yield from module.instance().project_committed(self)
@ -427,7 +427,7 @@ class Project:
def compute(self): def compute(self):
""" """
Returns all loaded VM compute. Returns all loaded modules from compute.
""" """
# We import it at the last time to avoid circular dependencies # We import it at the last time to avoid circular dependencies
@ -571,7 +571,7 @@ class Project:
Import a project contain in a zip file Import a project contain in a zip file
:param stream: A io.BytesIO of the zipfile :param stream: A io.BytesIO of the zipfile
:param gns3vm: True move docker, iou and qemu to the GNS3 VM :param gns3vm: True move Docker, IOU and Qemu to the GNS3 VM
""" """
with zipfile.ZipFile(stream) as myzip: with zipfile.ZipFile(stream) as myzip:
@ -608,7 +608,7 @@ class Project:
vm_directory = os.path.join(self.path, "servers", "vm", "project-files") vm_directory = os.path.join(self.path, "servers", "vm", "project-files")
vm_server_use = False vm_server_use = False
for module, device_type in modules_to_vm.items(): for module, vm_type in modules_to_vm.items():
module_directory = os.path.join(self.path, "project-files", module) module_directory = os.path.join(self.path, "project-files", module)
if os.path.exists(module_directory): if os.path.exists(module_directory):
os.makedirs(vm_directory, exist_ok=True) os.makedirs(vm_directory, exist_ok=True)
@ -616,7 +616,7 @@ class Project:
# Patch node to use the GNS3 VM # Patch node to use the GNS3 VM
for node in topology["topology"]["nodes"]: for node in topology["topology"]["nodes"]:
if node["type"] == device_type: if node["type"] == vm_type:
node["server_id"] = 2 node["server_id"] = 2
vm_server_use = True vm_server_use = True

View File

@ -94,7 +94,7 @@ class ProjectManager:
raise aiohttp.web.HTTPNotFound(text="Project ID {} doesn't exist".format(project_id)) raise aiohttp.web.HTTPNotFound(text="Project ID {} doesn't exist".format(project_id))
del self._projects[project_id] del self._projects[project_id]
def check_hardware_virtualization(self, source_vm): def check_hardware_virtualization(self, source_node):
""" """
Checks if hardware virtualization can be used. Checks if hardware virtualization can be used.
@ -102,9 +102,9 @@ class ProjectManager:
""" """
for project in self._projects.values(): for project in self._projects.values():
for vm in project.vms: for node in project.nodes:
if vm == source_vm: if node == source_node:
continue continue
if vm.hw_virtualization and vm.__class__.__name__ != source_vm.__class__.__name__: if node.hw_virtualization and node.__class__.__name__ != source_node.__class__.__name__:
return False return False
return True return True

View File

@ -37,7 +37,7 @@ log = logging.getLogger(__name__)
class Qemu(BaseManager): class Qemu(BaseManager):
_VM_CLASS = QemuVM _NODE_CLASS = QemuVM
@staticmethod @staticmethod
@asyncio.coroutine @asyncio.coroutine
@ -218,10 +218,10 @@ class Qemu(BaseManager):
@staticmethod @staticmethod
def get_legacy_vm_workdir(legacy_vm_id, name): def get_legacy_vm_workdir(legacy_vm_id, name):
""" """
Returns the name of the legacy working directory name for a VM. Returns the name of the legacy working directory name for a node.
:param legacy_vm_id: legacy VM identifier (integer) :param legacy_vm_id: legacy VM identifier (integer)
:param: VM name (not used) :param: node name (not used)
:returns: working directory name :returns: working directory name
""" """

View File

@ -19,9 +19,9 @@
Custom exceptions for the Qemu module. Custom exceptions for the Qemu module.
""" """
from ..vm_error import VMError from ..node_error import NodeError
class QemuError(VMError): class QemuError(NodeError):
pass pass

View File

@ -36,7 +36,7 @@ from ..adapters.ethernet_adapter import EthernetAdapter
from ..nios.nio_udp import NIOUDP from ..nios.nio_udp import NIOUDP
from ..nios.nio_tap import NIOTAP from ..nios.nio_tap import NIOTAP
from ..nios.nio_nat import NIONAT from ..nios.nio_nat import NIONAT
from ..base_vm import BaseVM from ..base_node import BaseNode
from ...schemas.qemu import QEMU_OBJECT_SCHEMA, QEMU_PLATFORMS from ...schemas.qemu import QEMU_OBJECT_SCHEMA, QEMU_PLATFORMS
from ...utils.asyncio import monitor_process from ...utils.asyncio import monitor_process
from ...utils.images import md5sum from ...utils.images import md5sum
@ -48,14 +48,14 @@ import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class QemuVM(BaseVM): class QemuVM(BaseNode):
module_name = 'qemu' module_name = 'qemu'
""" """
QEMU VM implementation. QEMU VM implementation.
:param name: Qemu VM name :param name: Qemu VM name
:param vm_id: Qemu VM identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Manager instance :param manager: Manager instance
:param console: TCP console port :param console: TCP console port
@ -64,9 +64,9 @@ class QemuVM(BaseVM):
:param console: TCP console port :param console: TCP console port
""" """
def __init__(self, name, vm_id, project, manager, linked_clone=True, qemu_path=None, console=None, console_type="telnet", platform=None): def __init__(self, name, node_id, project, manager, linked_clone=True, qemu_path=None, console=None, console_type="telnet", platform=None):
super().__init__(name, vm_id, project, manager, console=console, console_type=console_type) super().__init__(name, node_id, project, manager, console=console, console_type=console_type)
server_config = manager.config.get_section_config("Server") server_config = manager.config.get_section_config("Server")
self._host = server_config.get("host", "127.0.0.1") self._host = server_config.get("host", "127.0.0.1")
self._monitor_host = server_config.get("monitor_host", "127.0.0.1") self._monitor_host = server_config.get("monitor_host", "127.0.0.1")
@ -1448,7 +1448,7 @@ class QemuVM(BaseVM):
def __json__(self): def __json__(self):
answer = { answer = {
"project_id": self.project.id, "project_id": self.project.id,
"vm_id": self.id, "node_id": self.id,
"vm_directory": self.working_dir "vm_directory": self.working_dir
} }
# Qemu has a long list of options. The JSON schema is the single source of information # Qemu has a long list of options. The JSON schema is the single source of information

View File

@ -35,7 +35,7 @@ from .virtualbox_error import VirtualBoxError
class VirtualBox(BaseManager): class VirtualBox(BaseManager):
_VM_CLASS = VirtualBoxVM _NODE_CLASS = VirtualBoxVM
def __init__(self): def __init__(self):
@ -160,7 +160,7 @@ class VirtualBox(BaseManager):
Gets VirtualBox VM list. Gets VirtualBox VM list.
""" """
vms = [] vbox_vms = []
result = yield from self.execute("list", ["vms"]) result = yield from self.execute("list", ["vms"])
for line in result: for line in result:
if len(line) == 0 or line[0] != '"' or line[-1:] != "}": if len(line) == 0 or line[0] != '"' or line[-1:] != "}":
@ -182,16 +182,16 @@ class VirtualBox(BaseManager):
break break
except ValueError: except ValueError:
continue continue
vms.append({"vmname": vmname, "ram": ram}) vbox_vms.append({"vmname": vmname, "ram": ram})
return vms return vbox_vms
@staticmethod @staticmethod
def get_legacy_vm_workdir(legacy_vm_id, name): def get_legacy_vm_workdir(legacy_vm_id, name):
""" """
Returns the name of the legacy working directory name for a VM. Returns the name of the legacy working directory name for a node.
:param legacy_vm_id: legacy VM identifier (not used) :param legacy_vm_id: legacy node identifier (not used)
:param name: VM name :param name: node name
:returns: working directory name :returns: working directory name
""" """

View File

@ -19,9 +19,9 @@
Custom exceptions for the VirtualBox module. Custom exceptions for the VirtualBox module.
""" """
from ..vm_error import VMError from ..node_error import NodeError
class VirtualBoxError(VMError): class VirtualBoxError(NodeError):
pass pass

View File

@ -35,7 +35,7 @@ from .virtualbox_error import VirtualBoxError
from ..nios.nio_udp import NIOUDP from ..nios.nio_udp import NIOUDP
from ..nios.nio_nat import NIONAT from ..nios.nio_nat import NIONAT
from ..adapters.ethernet_adapter import EthernetAdapter from ..adapters.ethernet_adapter import EthernetAdapter
from ..base_vm import BaseVM from ..base_node import BaseNode
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
import msvcrt import msvcrt
@ -45,15 +45,15 @@ import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class VirtualBoxVM(BaseVM): class VirtualBoxVM(BaseNode):
""" """
VirtualBox VM implementation. VirtualBox VM implementation.
""" """
def __init__(self, name, vm_id, project, manager, vmname, linked_clone, console=None, adapters=0): def __init__(self, name, node_id, project, manager, vmname, linked_clone, console=None, adapters=0):
super().__init__(name, vm_id, project, manager, console=console) super().__init__(name, node_id, project, manager, console=console)
self._maximum_adapters = 8 self._maximum_adapters = 8
self._linked_clone = linked_clone self._linked_clone = linked_clone
@ -75,7 +75,7 @@ class VirtualBoxVM(BaseVM):
def __json__(self): def __json__(self):
json = {"name": self.name, json = {"name": self.name,
"vm_id": self.id, "node_id": self.id,
"console": self.console, "console": self.console,
"project_id": self.project.id, "project_id": self.project.id,
"vmname": self.vmname, "vmname": self.vmname,

View File

@ -43,7 +43,7 @@ from gns3server.compute.vmware.nio_vmnet import NIOVMNET
class VMware(BaseManager): class VMware(BaseManager):
_VM_CLASS = VMwareVM _NODE_CLASS = VMwareVM
def __init__(self): def __init__(self):
@ -324,8 +324,8 @@ class VMware(BaseManager):
vmnet_interfaces = self._get_vmnet_interfaces() vmnet_interfaces = self._get_vmnet_interfaces()
# remove vmnets already in use # remove vmnets already in use
for vm in self._vms.values(): for vmware_vm in self._nodes.values():
for used_vmnet in vm.vmnets: for used_vmnet in vmware_vm.vmnets:
if used_vmnet in vmnet_interfaces: if used_vmnet in vmnet_interfaces:
log.debug("{} is already in use".format(used_vmnet)) log.debug("{} is already in use".format(used_vmnet))
vmnet_interfaces.remove(used_vmnet) vmnet_interfaces.remove(used_vmnet)
@ -558,7 +558,7 @@ class VMware(BaseManager):
""" """
vm_entries = {} vm_entries = {}
vms = [] vmware_vms = []
try: try:
log.debug('Reading VMware inventory file "{}"'.format(inventory_path)) log.debug('Reading VMware inventory file "{}"'.format(inventory_path))
pairs = self.parse_vmware_file(inventory_path) pairs = self.parse_vmware_file(inventory_path)
@ -577,8 +577,8 @@ class VMware(BaseManager):
for vm_settings in vm_entries.values(): for vm_settings in vm_entries.values():
if "displayname" in vm_settings and "config" in vm_settings: if "displayname" in vm_settings and "config" in vm_settings:
log.debug('Found VM named "{}" with VMX file "{}"'.format(vm_settings["displayname"], vm_settings["config"])) log.debug('Found VM named "{}" with VMX file "{}"'.format(vm_settings["displayname"], vm_settings["config"]))
vms.append({"vmname": vm_settings["displayname"], "vmx_path": vm_settings["config"]}) vmware_vms.append({"vmname": vm_settings["displayname"], "vmx_path": vm_settings["config"]})
return vms return vmware_vms
def _get_vms_from_directory(self, directory): def _get_vms_from_directory(self, directory):
""" """
@ -589,7 +589,7 @@ class VMware(BaseManager):
:returns: list of VMs :returns: list of VMs
""" """
vms = [] vmware_vms = []
for path, _, filenames in os.walk(directory): for path, _, filenames in os.walk(directory):
for filename in filenames: for filename in filenames:
if os.path.splitext(filename)[1] == ".vmx": if os.path.splitext(filename)[1] == ".vmx":
@ -599,11 +599,11 @@ class VMware(BaseManager):
pairs = self.parse_vmware_file(vmx_path) pairs = self.parse_vmware_file(vmx_path)
if "displayname" in pairs: if "displayname" in pairs:
log.debug('Found VM named "{}"'.format(pairs["displayname"])) log.debug('Found VM named "{}"'.format(pairs["displayname"]))
vms.append({"vmname": pairs["displayname"], "vmx_path": vmx_path}) vmware_vms.append({"vmname": pairs["displayname"], "vmx_path": vmx_path})
except OSError as e: except OSError as e:
log.warning('Could not read VMware VMX file "{}": {}'.format(vmx_path, e)) log.warning('Could not read VMware VMX file "{}": {}'.format(vmx_path, e))
continue continue
return vms return vmware_vms
@staticmethod @staticmethod
def get_vmware_inventory_path(): def get_vmware_inventory_path():
@ -687,7 +687,7 @@ class VMware(BaseManager):
default_vm_path = pairs["prefvmx.defaultvmpath"] default_vm_path = pairs["prefvmx.defaultvmpath"]
if not os.path.isdir(default_vm_path): if not os.path.isdir(default_vm_path):
raise VMwareError('Could not find the default VM directory: "{}"'.format(default_vm_path)) raise VMwareError('Could not find the default VM directory: "{}"'.format(default_vm_path))
vms = self._get_vms_from_directory(default_vm_path) vmware_vms = self._get_vms_from_directory(default_vm_path)
# looks for VMX paths in the preferences file in case not all VMs are in the default directory # looks for VMX paths in the preferences file in case not all VMs are in the default directory
for key, value in pairs.items(): for key, value in pairs.items():
@ -696,12 +696,12 @@ class VMware(BaseManager):
display_name = "pref.mruVM{}.displayName".format(m.group(1)) display_name = "pref.mruVM{}.displayName".format(m.group(1))
if display_name in pairs: if display_name in pairs:
found = False found = False
for vm in vms: for vmware_vm in vmware_vms:
if vm["vmname"] == display_name: if vmware_vm["vmname"] == display_name:
found = True found = True
if found is False: if found is False:
vms.append({"vmname": pairs[display_name], "vmx_path": value}) vmware_vms.append({"vmname": pairs[display_name], "vmx_path": value})
return vms return vmware_vms
@staticmethod @staticmethod
def _get_linux_vmware_binary(): def _get_linux_vmware_binary():

View File

@ -19,9 +19,9 @@
Custom exceptions for the VMware module. Custom exceptions for the VMware module.
""" """
from ..vm_error import VMError from ..node_error import NodeError
class VMwareError(VMError): class VMwareError(NodeError):
pass pass

View File

@ -34,7 +34,7 @@ from ..nios.nio_udp import NIOUDP
from ..nios.nio_nat import NIONAT from ..nios.nio_nat import NIONAT
from .nio_vmnet import NIOVMNET from .nio_vmnet import NIOVMNET
from ..adapters.ethernet_adapter import EthernetAdapter from ..adapters.ethernet_adapter import EthernetAdapter
from ..base_vm import BaseVM from ..base_node import BaseNode
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
import msvcrt import msvcrt
@ -44,15 +44,15 @@ import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class VMwareVM(BaseVM): class VMwareVM(BaseNode):
""" """
VMware VM implementation. VMware VM implementation.
""" """
def __init__(self, name, vm_id, project, manager, vmx_path, linked_clone, console=None): def __init__(self, name, node_id, project, manager, vmx_path, linked_clone, console=None):
super().__init__(name, vm_id, project, manager, console=console) super().__init__(name, node_id, project, manager, console=console)
self._linked_clone = linked_clone self._linked_clone = linked_clone
self._vmx_pairs = OrderedDict() self._vmx_pairs = OrderedDict()
@ -75,12 +75,12 @@ class VMwareVM(BaseVM):
self._use_any_adapter = False self._use_any_adapter = False
if not os.path.exists(vmx_path): if not os.path.exists(vmx_path):
raise VMwareError('VMware VM "{name}" [{id}]: could not find VMX file "{vmx_path}"'.format(name=name, id=vm_id, vmx_path=vmx_path)) raise VMwareError('VMware VM "{name}" [{id}]: could not find VMX file "{vmx_path}"'.format(name=name, id=node_id, vmx_path=vmx_path))
def __json__(self): def __json__(self):
json = {"name": self.name, json = {"name": self.name,
"vm_id": self.id, "node_id": self.id,
"console": self.console, "console": self.console,
"project_id": self.project.id, "project_id": self.project.id,
"vmx_path": self.vmx_path, "vmx_path": self.vmx_path,

View File

@ -29,7 +29,7 @@ from .vpcs_vm import VPCSVM
class VPCS(BaseManager): class VPCS(BaseManager):
_VM_CLASS = VPCSVM _NODE_CLASS = VPCSVM
def __init__(self): def __init__(self):
@ -38,55 +38,55 @@ class VPCS(BaseManager):
self._used_mac_ids = {} self._used_mac_ids = {}
@asyncio.coroutine @asyncio.coroutine
def create_vm(self, *args, **kwargs): def create_node(self, *args, **kwargs):
""" """
Creates a new VPCS VM. Creates a new VPCS VM.
:returns: VPCSVM instance :returns: VPCSVM instance
""" """
vm = yield from super().create_vm(*args, **kwargs) node = yield from super().create_node(*args, **kwargs)
self._free_mac_ids.setdefault(vm.project.id, list(range(0, 255))) self._free_mac_ids.setdefault(node.project.id, list(range(0, 255)))
try: try:
self._used_mac_ids[vm.id] = self._free_mac_ids[vm.project.id].pop(0) self._used_mac_ids[node.id] = self._free_mac_ids[node.project.id].pop(0)
except IndexError: except IndexError:
raise VPCSError("Cannot create a new VPCS VM (limit of 255 VMs reached on this host)") raise VPCSError("Cannot create a new VPCS VM (limit of 255 VMs reached on this host)")
return vm return node
@asyncio.coroutine @asyncio.coroutine
def close_vm(self, vm_id, *args, **kwargs): def close_node(self, node_id, *args, **kwargs):
""" """
Closes a VPCS VM. Closes a VPCS VM.
:returns: VPCSVM instance :returns: VPCSVM instance
""" """
vm = self.get_vm(vm_id) node = self.get_node(node_id)
if vm_id in self._used_mac_ids: if node_id in self._used_mac_ids:
i = self._used_mac_ids[vm_id] i = self._used_mac_ids[node_id]
self._free_mac_ids[vm.project.id].insert(0, i) self._free_mac_ids[node.project.id].insert(0, i)
del self._used_mac_ids[vm_id] del self._used_mac_ids[node_id]
yield from super().close_vm(vm_id, *args, **kwargs) yield from super().close_node(node_id, *args, **kwargs)
return vm return node
def get_mac_id(self, vm_id): def get_mac_id(self, node_id):
""" """
Get an unique VPCS MAC id (offset) Get an unique VPCS MAC id (offset)
:param vm_id: VPCS VM identifier :param node_id: VPCS node identifier
:returns: VPCS MAC identifier :returns: VPCS MAC identifier
""" """
return self._used_mac_ids.get(vm_id, 1) return self._used_mac_ids.get(node_id, 1)
@staticmethod @staticmethod
def get_legacy_vm_workdir(legacy_vm_id, name): def get_legacy_vm_workdir(legacy_vm_id, name):
""" """
Returns the name of the legacy working directory name for a VM. Returns the name of the legacy working directory name for a node.
:param legacy_vm_id: legacy VM identifier (integer) :param legacy_vm_id: legacy node identifier (integer)
:param name: VM name (not used) :param name: node name (not used)
:returns: working directory name :returns: working directory name
""" """

View File

@ -19,9 +19,9 @@
Custom exceptions for the VPCS module. Custom exceptions for the VPCS module.
""" """
from ..vm_error import VMError from ..node_error import NodeError
class VPCSError(VMError): class VPCSError(NodeError):
pass pass

View File

@ -36,29 +36,29 @@ from .vpcs_error import VPCSError
from ..adapters.ethernet_adapter import EthernetAdapter from ..adapters.ethernet_adapter import EthernetAdapter
from ..nios.nio_udp import NIOUDP from ..nios.nio_udp import NIOUDP
from ..nios.nio_tap import NIOTAP from ..nios.nio_tap import NIOTAP
from ..base_vm import BaseVM from ..base_node import BaseNode
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class VPCSVM(BaseVM): class VPCSVM(BaseNode):
module_name = 'vpcs' module_name = 'vpcs'
""" """
VPCS VM implementation. VPCS VM implementation.
:param name: VPCS VM name :param name: VPCS VM name
:param vm_id: VPCS VM identifier :param node_id: Node identifier
:param project: Project instance :param project: Project instance
:param manager: Manager instance :param manager: Manager instance
:param console: TCP console port :param console: TCP console port
:param startup_script: content of the startup script file :param startup_script: content of the startup script file
""" """
def __init__(self, name, vm_id, project, manager, console=None, startup_script=None): def __init__(self, name, node_id, project, manager, console=None, startup_script=None):
super().__init__(name, vm_id, project, manager, console=console) super().__init__(name, node_id, project, manager, console=console)
self._process = None self._process = None
self._vpcs_stdout_file = "" self._vpcs_stdout_file = ""
self._vpcs_version = None self._vpcs_version = None
@ -108,7 +108,7 @@ class VPCSVM(BaseVM):
def __json__(self): def __json__(self):
return {"name": self.name, return {"name": self.name,
"vm_id": self.id, "node_id": self.id,
"vm_directory": self.working_dir, "vm_directory": self.working_dir,
"status": self.status, "status": self.status,
"console": self._console, "console": self._console,
@ -145,7 +145,7 @@ class VPCSVM(BaseVM):
path = shutil.which("vpcs") path = shutil.which("vpcs")
return path return path
@BaseVM.name.setter @BaseNode.name.setter
def name(self, new_name): def name(self, new_name):
""" """
Sets the name of this VPCS VM. Sets the name of this VPCS VM.

View File

@ -77,7 +77,7 @@ class Controller:
return return
for c in data["computes"]: for c in data["computes"]:
compute_id = c.pop("compute_id") compute_id = c.pop("compute_id")
yield from self.addCompute(compute_id, **c) yield from self.add_compute(compute_id, **c)
def isEnabled(self): def isEnabled(self):
""" """
@ -87,7 +87,7 @@ class Controller:
return Config.instance().get_section_config("Server").getboolean("controller") return Config.instance().get_section_config("Server").getboolean("controller")
@asyncio.coroutine @asyncio.coroutine
def addCompute(self, compute_id, **kwargs): def add_compute(self, compute_id, **kwargs):
""" """
Add a server to the dictionnary of computes controlled by GNS3 Add a server to the dictionnary of computes controlled by GNS3
@ -126,11 +126,11 @@ class Controller:
project = Project(project_id=project_id, **kwargs) project = Project(project_id=project_id, **kwargs)
self._projects[project.id] = project self._projects[project.id] = project
for compute in self._computes.values(): for compute in self._computes.values():
yield from project.addCompute(compute) yield from project.add_compute(compute)
return self._projects[project.id] return self._projects[project.id]
return self._projects[project_id] return self._projects[project_id]
def getProject(self, project_id): def get_project(self, project_id):
""" """
Return a project or raise a 404 Return a project or raise a 404
""" """

View File

@ -29,18 +29,18 @@ class Link:
def __init__(self, project): def __init__(self, project):
self._id = str(uuid.uuid4()) self._id = str(uuid.uuid4())
self._vms = [] self._nodes = []
self._project = project self._project = project
self._capturing = False self._capturing = False
self._capture_file_name = None self._capture_file_name = None
@asyncio.coroutine @asyncio.coroutine
def addVM(self, vm, adapter_number, port_number): def add_node(self, node, adapter_number, port_number):
""" """
Add a VM to the link Add a node to the link
""" """
self._vms.append({ self._nodes.append({
"vm": vm, "node": node,
"adapter_number": adapter_number, "adapter_number": adapter_number,
"port_number": port_number "port_number": port_number
}) })
@ -107,12 +107,12 @@ class Link:
:returns: File name for a capture on this link :returns: File name for a capture on this link
""" """
capture_file_name = "{}_{}-{}_to_{}_{}-{}".format( capture_file_name = "{}_{}-{}_to_{}_{}-{}".format(
self._vms[0]["vm"].name, self._nodes[0]["node"].name,
self._vms[0]["adapter_number"], self._nodes[0]["adapter_number"],
self._vms[0]["port_number"], self._nodes[0]["port_number"],
self._vms[1]["vm"].name, self._nodes[1]["node"].name,
self._vms[1]["adapter_number"], self._nodes[1]["adapter_number"],
self._vms[1]["port_number"]) self._nodes[1]["port_number"])
return re.sub("[^0-9A-Za-z_-]", "", capture_file_name) + ".pcap" return re.sub("[^0-9A-Za-z_-]", "", capture_file_name) + ".pcap"
@property @property
@ -135,14 +135,14 @@ class Link:
def __json__(self): def __json__(self):
res = [] res = []
for side in self._vms: for side in self._nodes:
res.append({ res.append({
"vm_id": side["vm"].id, "node_id": side["node"].id,
"adapter_number": side["adapter_number"], "adapter_number": side["adapter_number"],
"port_number": side["port_number"] "port_number": side["port_number"]
}) })
return { return {
"vms": res, "link_id": self._id, "nodes": res, "link_id": self._id,
"capturing": self._capturing, "capturing": self._capturing,
"capture_file_name": self._capture_file_name, "capture_file_name": self._capture_file_name,
"capture_file_path": self.capture_file_path "capture_file_path": self.capture_file_path

View File

@ -21,29 +21,29 @@ import copy
import uuid import uuid
class VM: class Node:
def __init__(self, project, compute, vm_id=None, vm_type=None, name=None, console=None, console_type="telnet", properties={}): def __init__(self, project, compute, node_id=None, node_type=None, name=None, console=None, console_type="telnet", properties={}):
""" """
:param project: Project of the VM :param project: Project of the node
:param compute: Hypervisor server where the server will run :param compute: Compute server where the server will run
:param vm_id: UUID of the vm. Integer id :param node_id: UUID of the node (integer)
:param vm_type: Type of emulator :param node_type: Type of emulator
:param name: Name of the vm :param name: Name of the node
:param console: TCP port of the console :param console: TCP port of the console
:param console_type: Type of the console (telnet, vnc, serial..) :param console_type: Type of the console (telnet, vnc, serial..)
:param properties: Emulator specific properties of the VM :param properties: Emulator specific properties of the node
""" """
if vm_id is None: if node_id is None:
self._id = str(uuid.uuid4()) self._id = str(uuid.uuid4())
else: else:
self._id = vm_id self._id = node_id
self._name = name self._name = name
self._project = project self._project = project
self._compute = compute self._compute = compute
self._vm_type = vm_type self._node_type = node_type
self._console = console self._console = console
self._console_type = console_type self._console_type = console_type
self._properties = properties self._properties = properties
@ -57,8 +57,8 @@ class VM:
return self._name return self._name
@property @property
def vm_type(self): def node_type(self):
return self._vm_type return self._node_type
@property @property
def console(self): def console(self):
@ -90,24 +90,24 @@ class VM:
@asyncio.coroutine @asyncio.coroutine
def create(self): def create(self):
""" """
Create the VM on the compute Node Create the node on the compute server
""" """
data = self._vm_data() data = self._node_data()
data["vm_id"] = self._id data["node_id"] = self._id
response = yield from self._compute.post("/projects/{}/{}/vms".format(self._project.id, self._vm_type), data=data) response = yield from self._compute.post("/projects/{}/{}/nodes".format(self._project.id, self._node_type), data=data)
self._parse_vm_response(response) self._parse_node_response(response)
@asyncio.coroutine @asyncio.coroutine
def update(self, name=None, console=None, console_type="telnet", properties={}): def update(self, name=None, console=None, console_type="telnet", properties={}):
""" """
Update the VM on the compute Node Update the node on the compute server
:param vm_id: UUID of the vm. Integer id :param node_id: UUID of the node
:param vm_type: Type of emulator :param node_type: Type of emulator
:param name: Name of the vm :param name: Name of the node
:param console: TCP port of the console :param console: TCP port of the console
:param console_type: Type of the console (telnet, vnc, serial..) :param console_type: Type of the console (telnet, vnc, serial..)
:param properties: Emulator specific properties of the VM :param properties: Emulator specific properties of the node
""" """
if name: if name:
@ -119,25 +119,25 @@ class VM:
if properties != {}: if properties != {}:
self._properties = properties self._properties = properties
data = self._vm_data() data = self._node_data()
response = yield from self.put(None, data=data) response = yield from self.put(None, data=data)
self._parse_vm_response(response) self._parse_node_response(response)
def _parse_vm_response(self, response): def _parse_node_response(self, response):
""" """
Update the object with the remote VM object Update the object with the remote node object
""" """
for key, value in response.json.items(): for key, value in response.json.items():
if key == "console": if key == "console":
self._console = value self._console = value
elif key in ["console_type", "name", "vm_id", "project_id", "vm_directory", "command_line", "status"]: elif key in ["console_type", "name", "node_id", "project_id", "node_directory", "command_line", "status"]:
pass pass
else: else:
self._properties[key] = value self._properties[key] = value
def _vm_data(self): def _node_data(self):
""" """
Prepare VM data to send to the remote controller Prepare node data to send to the remote controller
""" """
data = copy.copy(self._properties) data = copy.copy(self._properties)
data["name"] = self._name data["name"] = self._name
@ -157,50 +157,50 @@ class VM:
@asyncio.coroutine @asyncio.coroutine
def start(self): def start(self):
""" """
Start a VM Start a node
""" """
yield from self.post("/start") yield from self.post("/start")
@asyncio.coroutine @asyncio.coroutine
def stop(self): def stop(self):
""" """
Stop a VM Stop a node
""" """
yield from self.post("/stop") yield from self.post("/stop")
@asyncio.coroutine @asyncio.coroutine
def suspend(self): def suspend(self):
""" """
Suspend a VM Suspend a node
""" """
yield from self.post("/suspend") yield from self.post("/suspend")
@asyncio.coroutine @asyncio.coroutine
def reload(self): def reload(self):
""" """
Suspend a VM Suspend a node
""" """
yield from self.post("/reload") yield from self.post("/reload")
@asyncio.coroutine @asyncio.coroutine
def post(self, path, data=None): def post(self, path, data=None):
""" """
HTTP post on the VM HTTP post on the node
""" """
if data: if data:
return (yield from self._compute.post("/projects/{}/{}/vms/{}{}".format(self._project.id, self._vm_type, self._id, path), data=data)) return (yield from self._compute.post("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path), data=data))
else: else:
return (yield from self._compute.post("/projects/{}/{}/vms/{}{}".format(self._project.id, self._vm_type, self._id, path))) return (yield from self._compute.post("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path)))
@asyncio.coroutine @asyncio.coroutine
def put(self, path, data=None): def put(self, path, data=None):
""" """
HTTP post on the VM HTTP post on the node
""" """
if path is None: if path is None:
path = "/projects/{}/{}/vms/{}".format(self._project.id, self._vm_type, self._id) path = "/projects/{}/{}/nodes/{}".format(self._project.id, self._node_type, self._id)
else: else:
path = "/projects/{}/{}/vms/{}{}".format(self._project.id, self._vm_type, self._id, path) path = "/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path)
if data: if data:
return (yield from self._compute.put(path, data=data)) return (yield from self._compute.put(path, data=data))
else: else:
@ -209,22 +209,22 @@ class VM:
@asyncio.coroutine @asyncio.coroutine
def delete(self, path=None): def delete(self, path=None):
""" """
HTTP post on the VM HTTP post on the node
""" """
if path is None: if path is None:
return (yield from self._compute.delete("/projects/{}/{}/vms/{}".format(self._project.id, self._vm_type, self._id))) return (yield from self._compute.delete("/projects/{}/{}/nodes/{}".format(self._project.id, self._node_type, self._id)))
else: else:
return (yield from self._compute.delete("/projects/{}/{}/vms/{}{}".format(self._project.id, self._vm_type, self._id, path))) return (yield from self._compute.delete("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path)))
def __repr__(self): def __repr__(self):
return "<gns3server.controller.VM {} {}>".format(self._vm_type, self._name) return "<gns3server.controller.Node {} {}>".format(self._node_type, self._name)
def __json__(self): def __json__(self):
return { return {
"compute_id": self._compute.id, "compute_id": self._compute.id,
"project_id": self._project.id, "project_id": self._project.id,
"vm_id": self._id, "node_id": self._id,
"vm_type": self._vm_type, "node_type": self._node_type,
"name": self._name, "name": self._name,
"console": self._console, "console": self._console,
"console_type": self._console_type, "console_type": self._console_type,

View File

@ -18,10 +18,12 @@
import os import os
import asyncio import asyncio
import aiohttp import aiohttp
import shutil
from uuid import UUID, uuid4 from uuid import UUID, uuid4
from contextlib import contextmanager from contextlib import contextmanager
from .vm import VM from .node import Node
from .udp_link import UDPLink from .udp_link import UDPLink
from ..notification_queue import NotificationQueue from ..notification_queue import NotificationQueue
from ..config import Config from ..config import Config
@ -56,7 +58,7 @@ class Project:
self._temporary = temporary self._temporary = temporary
self._computes = set() self._computes = set()
self._vms = {} self._nodes = {}
self._links = {} self._links = {}
self._listeners = set() self._listeners = set()
@ -101,42 +103,42 @@ class Project:
return path return path
@asyncio.coroutine @asyncio.coroutine
def addCompute(self, compute): def add_compute(self, compute):
self._computes.add(compute) self._computes.add(compute)
yield from compute.post("/projects", self) yield from compute.post("/projects", self)
@asyncio.coroutine @asyncio.coroutine
def addVM(self, compute, vm_id, **kwargs): def add_node(self, compute, node_id, **kwargs):
""" """
Create a vm or return an existing vm Create a node or return an existing node
:param kwargs: See the documentation of VM :param kwargs: See the documentation of node
""" """
if vm_id not in self._vms: if node_id not in self._nodes:
vm = VM(self, compute, vm_id=vm_id, **kwargs) node = Node(self, compute, node_id=node_id, **kwargs)
yield from vm.create() yield from node.create()
self._vms[vm.id] = vm self._nodes[node.id] = node
return vm return node
return self._vms[vm_id] return self._nodes[node_id]
def getVM(self, vm_id): def get_node(self, node_id):
""" """
Return the VM or raise a 404 if the VM is unknown Return the node or raise a 404 if the node is unknown
""" """
try: try:
return self._vms[vm_id] return self._nodes[node_id]
except KeyError: except KeyError:
raise aiohttp.web.HTTPNotFound(text="VM ID {} doesn't exist".format(vm_id)) raise aiohttp.web.HTTPNotFound(text="Node ID {} doesn't exist".format(node_id))
@property @property
def vms(self): def nodes(self):
""" """
:returns: Dictionnary of the VMS :returns: Dictionary of the nodes
""" """
return self._vms return self._nodes
@asyncio.coroutine @asyncio.coroutine
def addLink(self): def add_link(self):
""" """
Create a link. By default the link is empty Create a link. By default the link is empty
""" """
@ -144,9 +146,9 @@ class Project:
self._links[link.id] = link self._links[link.id] = link
return link return link
def getLink(self, link_id): def get_link(self, link_id):
""" """
Return the Link or raise a 404 if the VM is unknown Return the Link or raise a 404 if the link is unknown
""" """
try: try:
return self._links[link_id] return self._links[link_id]
@ -156,7 +158,7 @@ class Project:
@property @property
def links(self): def links(self):
""" """
:returns: Dictionnary of the Links :returns: Dictionary of the Links
""" """
return self._links return self._links
@ -174,7 +176,7 @@ class Project:
def delete(self): def delete(self):
for compute in self._computes: for compute in self._computes:
yield from compute.delete("/projects/{}".format(self._id)) yield from compute.delete("/projects/{}".format(self._id))
shutil.rmtree(self.path) shutil.rmtree(self.path, ignore_errors=True)
@contextmanager @contextmanager
def queue(self): def queue(self):

View File

@ -26,58 +26,58 @@ class UDPLink(Link):
def __init__(self, project): def __init__(self, project):
super().__init__(project) super().__init__(project)
self._capture_vm = None self._capture_node = None
@asyncio.coroutine @asyncio.coroutine
def create(self): def create(self):
""" """
Create the link on the VMs Create the link on the nodes
""" """
vm1 = self._vms[0]["vm"] node1 = self._nodes[0]["node"]
adapter_number1 = self._vms[0]["adapter_number"] adapter_number1 = self._nodes[0]["adapter_number"]
port_number1 = self._vms[0]["port_number"] port_number1 = self._nodes[0]["port_number"]
vm2 = self._vms[1]["vm"] node2 = self._nodes[1]["node"]
adapter_number2 = self._vms[1]["adapter_number"] adapter_number2 = self._nodes[1]["adapter_number"]
port_number2 = self._vms[1]["port_number"] port_number2 = self._nodes[1]["port_number"]
# Reserve a UDP port on both side # Reserve a UDP port on both side
response = yield from vm1.compute.post("/projects/{}/ports/udp".format(self._project.id)) response = yield from node1.compute.post("/projects/{}/ports/udp".format(self._project.id))
self._vm1_port = response.json["udp_port"] self._node1_port = response.json["udp_port"]
response = yield from vm2.compute.post("/projects/{}/ports/udp".format(self._project.id)) response = yield from node2.compute.post("/projects/{}/ports/udp".format(self._project.id))
self._vm2_port = response.json["udp_port"] self._node2_port = response.json["udp_port"]
# Create the tunnel on both side # Create the tunnel on both side
data = { data = {
"lport": self._vm1_port, "lport": self._node1_port,
"rhost": vm2.compute.host, "rhost": node2.compute.host,
"rport": self._vm2_port, "rport": self._node2_port,
"type": "nio_udp" "type": "nio_udp"
} }
yield from vm1.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=data) yield from node1.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=data)
data = { data = {
"lport": self._vm2_port, "lport": self._node2_port,
"rhost": vm1.compute.host, "rhost": node1.compute.host,
"rport": self._vm1_port, "rport": self._node1_port,
"type": "nio_udp" "type": "nio_udp"
} }
yield from vm2.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=data) yield from node2.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=data)
@asyncio.coroutine @asyncio.coroutine
def delete(self): def delete(self):
""" """
Delete the link and free the ressources Delete the link and free the resources
""" """
vm1 = self._vms[0]["vm"] node1 = self._nodes[0]["node"]
adapter_number1 = self._vms[0]["adapter_number"] adapter_number1 = self._nodes[0]["adapter_number"]
port_number1 = self._vms[0]["port_number"] port_number1 = self._nodes[0]["port_number"]
vm2 = self._vms[1]["vm"] node2 = self._nodes[1]["node"]
adapter_number2 = self._vms[1]["adapter_number"] adapter_number2 = self._nodes[1]["adapter_number"]
port_number2 = self._vms[1]["port_number"] port_number2 = self._nodes[1]["port_number"]
yield from vm1.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1)) yield from node1.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1))
yield from vm2.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2)) yield from node2.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2))
@asyncio.coroutine @asyncio.coroutine
def start_capture(self, data_link_type="DLT_EN10MB", capture_file_name=None): def start_capture(self, data_link_type="DLT_EN10MB", capture_file_name=None):
@ -86,12 +86,12 @@ class UDPLink(Link):
""" """
if not capture_file_name: if not capture_file_name:
capture_file_name = self.default_capture_file_name() capture_file_name = self.default_capture_file_name()
self._capture_vm = self._choose_capture_side() self._capture_node = self._choose_capture_side()
data = { data = {
"capture_file_name": capture_file_name, "capture_file_name": capture_file_name,
"data_link_type": data_link_type "data_link_type": data_link_type
} }
yield from self._capture_vm["vm"].post("/adapters/{adapter_number}/ports/{port_number}/start_capture".format(adapter_number=self._capture_vm["adapter_number"], port_number=self._capture_vm["port_number"]), data=data) yield from self._capture_node["node"].post("/adapters/{adapter_number}/ports/{port_number}/start_capture".format(adapter_number=self._capture_node["adapter_number"], port_number=self._capture_node["port_number"]), data=data)
yield from super().start_capture(data_link_type=data_link_type, capture_file_name=capture_file_name) yield from super().start_capture(data_link_type=data_link_type, capture_file_name=capture_file_name)
@asyncio.coroutine @asyncio.coroutine
@ -99,9 +99,9 @@ class UDPLink(Link):
""" """
Stop capture on a link Stop capture on a link
""" """
if self._capture_vm: if self._capture_node:
yield from self._capture_vm["vm"].post("/adapters/{adapter_number}/ports/{port_number}/stop_capture".format(adapter_number=self._capture_vm["adapter_number"], port_number=self._capture_vm["port_number"])) yield from self._capture_node["node"].post("/adapters/{adapter_number}/ports/{port_number}/stop_capture".format(adapter_number=self._capture_node["adapter_number"], port_number=self._capture_node["port_number"]))
self._capture_vm = None self._capture_node = None
yield from super().stop_capture() yield from super().stop_capture()
def _choose_capture_side(self): def _choose_capture_side(self):
@ -111,17 +111,17 @@ class UDPLink(Link):
The ideal candidate is a node who support capture on controller The ideal candidate is a node who support capture on controller
server server
:returns: VM where the capture should run :returns: Node where the capture should run
""" """
# For saving bandwith we use the local node first # use the local node first to save bandwidth
for vm in self._vms: for node in self._nodes:
if vm["vm"].compute.id == "local" and vm["vm"].vm_type not in ["qemu", "vpcs"]: if node["node"].compute.id == "local" and node["node"].node_type not in ["qemu", "vpcs"]:
return vm return node
for vm in self._vms: for node in self._nodes:
if vm["vm"].vm_type not in ["qemu", "vpcs"]: if node["node"].node_type not in ["qemu", "vpcs"]:
return vm return node
raise aiohttp.web.HTTPConflict(text="Capture is not supported for this link") raise aiohttp.web.HTTPConflict(text="Capture is not supported for this link")
@ -130,6 +130,6 @@ class UDPLink(Link):
""" """
Return a FileStream of the Pcap from the compute node Return a FileStream of the Pcap from the compute node
""" """
if self._capture_vm: if self._capture_node:
compute = self._capture_vm["vm"].compute compute = self._capture_node["node"].compute
return compute.streamFile(self._project, "tmp/captures/" + self._capture_file_name) return compute.streamFile(self._project, "tmp/captures/" + self._capture_file_name)

View File

@ -27,7 +27,7 @@ from ....schemas.docker import (
DOCKER_UPDATE_SCHEMA, DOCKER_UPDATE_SCHEMA,
DOCKER_LIST_IMAGES_SCHEMA DOCKER_LIST_IMAGES_SCHEMA
) )
from ....schemas.vm import VM_CAPTURE_SCHEMA from ....schemas.node import NODE_CAPTURE_SCHEMA
from ....schemas.nio import NIO_SCHEMA from ....schemas.nio import NIO_SCHEMA
@ -49,7 +49,7 @@ class DockerHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/docker/vms", r"/projects/{project_id}/docker/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
@ -63,35 +63,33 @@ class DockerHandler:
output=DOCKER_OBJECT_SCHEMA) output=DOCKER_OBJECT_SCHEMA)
def create(request, response): def create(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
container = yield from docker_manager.create_vm( vm = yield from docker_manager.create_node(request.json.pop("name"),
request.json.pop("name"), request.match_info["project_id"],
request.match_info["project_id"], request.json.get("node_id"),
request.json.get("vm_id"), image=request.json.pop("image"),
image=request.json.pop("image"), start_command=request.json.get("start_command"),
start_command=request.json.get("start_command"), environment=request.json.get("environment"),
environment=request.json.get("environment"), adapters=request.json.get("adapters"),
adapters=request.json.get("adapters"), console=request.json.get("console"),
console=request.json.get("console"), console_type=request.json.get("console_type"),
console_type=request.json.get("console_type"), console_resolution=request.json.get("console_resolution", "1024x768"),
console_resolution=request.json.get("console_resolution", "1024x768"), console_http_port=request.json.get("console_http_port", 80),
console_http_port=request.json.get("console_http_port", 80), console_http_path=request.json.get("console_http_path", "/"),
console_http_path=request.json.get("console_http_path", "/"), aux=request.json.get("aux"))
aux=request.json.get("aux")
)
for name, value in request.json.items(): for name, value in request.json.items():
if name != "_vm_id": if name != "_node_id":
if hasattr(container, name) and getattr(container, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
setattr(container, name, value) setattr(vm, name, value)
response.set_status(201) response.set_status(201)
response.json(container) response.json(vm)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/docker/vms/{id}/start", r"/projects/{project_id}/docker/nodes/{node_id}/start",
parameters={ parameters={
"project_id": "UUID of the project", "project_id": "UUID of the project",
"id": "ID of the container" "node_id": "ID of the container"
}, },
status_codes={ status_codes={
204: "Instance started", 204: "Instance started",
@ -103,18 +101,16 @@ class DockerHandler:
output=DOCKER_OBJECT_SCHEMA) output=DOCKER_OBJECT_SCHEMA)
def start(request, response): def start(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
container = docker_manager.get_vm( vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
request.match_info["id"], yield from vm.start()
project_id=request.match_info["project_id"])
yield from container.start()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/docker/vms/{id}/stop", r"/projects/{project_id}/docker/nodes/{node_id}/stop",
parameters={ parameters={
"project_id": "UUID of the project", "project_id": "UUID of the project",
"id": "ID of the container" "node_id": "ID of the container"
}, },
status_codes={ status_codes={
204: "Instance stopped", 204: "Instance stopped",
@ -126,18 +122,16 @@ class DockerHandler:
output=DOCKER_OBJECT_SCHEMA) output=DOCKER_OBJECT_SCHEMA)
def stop(request, response): def stop(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
container = docker_manager.get_vm( vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
request.match_info["id"], yield from vm.stop()
project_id=request.match_info["project_id"])
yield from container.stop()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/docker/vms/{id}/reload", r"/projects/{project_id}/docker/nodes/{node_id}/reload",
parameters={ parameters={
"project_id": "UUID of the project", "project_id": "UUID of the project",
"id": "ID of the container" "node_id": "ID of the container"
}, },
status_codes={ status_codes={
204: "Instance restarted", 204: "Instance restarted",
@ -149,18 +143,16 @@ class DockerHandler:
output=DOCKER_OBJECT_SCHEMA) output=DOCKER_OBJECT_SCHEMA)
def reload(request, response): def reload(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
container = docker_manager.get_vm( vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
request.match_info["id"], yield from vm.restart()
project_id=request.match_info["project_id"])
yield from container.restart()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/docker/vms/{id}", r"/projects/{project_id}/docker/nodes/{node_id}",
parameters={ parameters={
"id": "ID for the container", "project_id": "UUID for the project",
"project_id": "UUID for the project" "node_id": "ID for the container",
}, },
status_codes={ status_codes={
204: "Instance deleted", 204: "Instance deleted",
@ -170,18 +162,16 @@ class DockerHandler:
description="Delete a Docker container") description="Delete a Docker container")
def delete(request, response): def delete(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
container = docker_manager.get_vm( vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
request.match_info["id"], yield from vm.delete()
project_id=request.match_info["project_id"])
yield from container.delete()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/docker/vms/{id}/suspend", r"/projects/{project_id}/docker/nodes/{node_id}/suspend",
parameters={ parameters={
"project_id": "UUID of the project", "project_id": "UUID of the project",
"id": "ID of the container" "node_id": "ID of the container"
}, },
status_codes={ status_codes={
204: "Instance paused", 204: "Instance paused",
@ -193,17 +183,15 @@ class DockerHandler:
output=DOCKER_OBJECT_SCHEMA) output=DOCKER_OBJECT_SCHEMA)
def suspend(request, response): def suspend(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
container = docker_manager.get_vm( vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
request.match_info["id"], yield from vm.pause()
project_id=request.match_info["project_id"])
yield from container.pause()
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/docker/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"id": "ID of the container", "node_id": "ID of the container",
"adapter_number": "Adapter where the nio should be added", "adapter_number": "Adapter where the nio should be added",
"port_number": "Port on the adapter" "port_number": "Port on the adapter"
}, },
@ -217,29 +205,21 @@ class DockerHandler:
output=NIO_SCHEMA) output=NIO_SCHEMA)
def create_nio(request, response): def create_nio(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
container = docker_manager.get_vm( vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
request.match_info["vm_id"],
project_id=request.match_info["project_id"])
nio_type = request.json["type"] nio_type = request.json["type"]
if nio_type not in ("nio_udp"): if nio_type not in ("nio_udp"):
raise HTTPConflict( raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
text="NIO of type {} is not supported".format(nio_type)) nio = docker_manager.create_nio(int(request.match_info["adapter_number"]), request.json)
nio = docker_manager.create_nio( yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
int(request.match_info["adapter_number"]), request.json)
adapter = container._ethernet_adapters[
int(request.match_info["adapter_number"])
]
yield from container.adapter_add_nio_binding(
int(request.match_info["adapter_number"]), nio)
response.set_status(201) response.set_status(201)
response.json(nio) response.json(nio)
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/docker/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"id": "ID of the container", "node_id": "ID of the container",
"adapter_number": "Adapter where the nio should be added", "adapter_number": "Adapter where the nio should be added",
"port_number": "Port on the adapter" "port_number": "Port on the adapter"
}, },
@ -251,19 +231,16 @@ class DockerHandler:
description="Remove a NIO from a Docker container") description="Remove a NIO from a Docker container")
def delete_nio(request, response): def delete_nio(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
container = docker_manager.get_vm( vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
request.match_info["vm_id"], yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]))
project_id=request.match_info["project_id"])
yield from container.adapter_remove_nio_binding(
int(request.match_info["adapter_number"]))
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.put( @Route.put(
r"/projects/{project_id}/docker/vms/{vm_id}", r"/projects/{project_id}/docker/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance updated", 200: "Instance updated",
@ -277,7 +254,7 @@ class DockerHandler:
def update(request, response): def update(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
vm = docker_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
vm.name = request.json.get("name", vm.name) vm.name = request.json.get("name", vm.name)
vm.console = request.json.get("console", vm.console) vm.console = request.json.get("console", vm.console)
vm.aux = request.json.get("aux", vm.aux) vm.aux = request.json.get("aux", vm.aux)
@ -292,10 +269,10 @@ class DockerHandler:
response.json(vm) response.json(vm)
@Route.post( @Route.post(
r"/projects/{project_id}/docker/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture", r"/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to start a packet capture", "adapter_number": "Adapter to start a packet capture",
"port_number": "Port on the adapter" "port_number": "Port on the adapter"
}, },
@ -303,14 +280,14 @@ class DockerHandler:
200: "Capture started", 200: "Capture started",
400: "Invalid request", 400: "Invalid request",
404: "Instance doesn't exist", 404: "Instance doesn't exist",
409: "VM not started" 409: "Node not started"
}, },
description="Start a packet capture on a IOU VM instance", description="Start a packet capture on a Docker VM instance",
input=VM_CAPTURE_SCHEMA) input=NODE_CAPTURE_SCHEMA)
def start_capture(request, response): def start_capture(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
vm = docker_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
adapter_number = int(request.match_info["adapter_number"]) adapter_number = int(request.match_info["adapter_number"])
pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"])
@ -320,10 +297,10 @@ class DockerHandler:
response.json({"pcap_file_path": str(pcap_file_path)}) response.json({"pcap_file_path": str(pcap_file_path)})
@Route.post( @Route.post(
r"/projects/{project_id}/docker/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture", r"/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to stop a packet capture", "adapter_number": "Adapter to stop a packet capture",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -337,7 +314,7 @@ class DockerHandler:
def stop_capture(request, response): def stop_capture(request, response):
docker_manager = Docker.instance() docker_manager = Docker.instance()
vm = docker_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
if not vm.is_running(): if not vm.is_running():
raise HTTPConflict(text="Cannot capture traffic on a non started VM") raise HTTPConflict(text="Cannot capture traffic on a non started VM")

View File

@ -22,7 +22,7 @@ from ....schemas.dynamips_device import DEVICE_CREATE_SCHEMA
from ....schemas.dynamips_device import DEVICE_UPDATE_SCHEMA from ....schemas.dynamips_device import DEVICE_UPDATE_SCHEMA
from ....schemas.dynamips_device import DEVICE_OBJECT_SCHEMA from ....schemas.dynamips_device import DEVICE_OBJECT_SCHEMA
from ....schemas.dynamips_device import DEVICE_NIO_SCHEMA from ....schemas.dynamips_device import DEVICE_NIO_SCHEMA
from ....schemas.vm import VM_CAPTURE_SCHEMA from ....schemas.node import NODE_CAPTURE_SCHEMA
from ....compute.dynamips import Dynamips from ....compute.dynamips import Dynamips
@ -198,7 +198,7 @@ class DynamipsDeviceHandler:
404: "Instance doesn't exist" 404: "Instance doesn't exist"
}, },
description="Start a packet capture on a Dynamips device instance", description="Start a packet capture on a Dynamips device instance",
input=VM_CAPTURE_SCHEMA) input=NODE_CAPTURE_SCHEMA)
def start_capture(request, response): def start_capture(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()

View File

@ -21,12 +21,12 @@ import base64
from ....web.route import Route from ....web.route import Route
from ....schemas.nio import NIO_SCHEMA from ....schemas.nio import NIO_SCHEMA
from ....schemas.vm import VM_LIST_IMAGES_SCHEMA
from ....schemas.dynamips_vm import VM_CREATE_SCHEMA from ....schemas.dynamips_vm import VM_CREATE_SCHEMA
from ....schemas.dynamips_vm import VM_UPDATE_SCHEMA from ....schemas.dynamips_vm import VM_UPDATE_SCHEMA
from ....schemas.dynamips_vm import VM_OBJECT_SCHEMA from ....schemas.dynamips_vm import VM_OBJECT_SCHEMA
from ....schemas.dynamips_vm import VM_CONFIGS_SCHEMA from ....schemas.dynamips_vm import VM_CONFIGS_SCHEMA
from ....schemas.vm import VM_CAPTURE_SCHEMA from ....schemas.node import NODE_CAPTURE_SCHEMA
from ....schemas.node import NODE_LIST_IMAGES_SCHEMA
from ....compute.dynamips import Dynamips from ....compute.dynamips import Dynamips
from ....compute.dynamips.dynamips_error import DynamipsError from ....compute.dynamips.dynamips_error import DynamipsError
from ....compute.project_manager import ProjectManager from ....compute.project_manager import ProjectManager
@ -46,7 +46,7 @@ class DynamipsVMHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms", r"/projects/{project_id}/dynamips/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
@ -65,9 +65,9 @@ class DynamipsVMHandler:
default_chassis = None default_chassis = None
if platform in DEFAULT_CHASSIS: if platform in DEFAULT_CHASSIS:
default_chassis = DEFAULT_CHASSIS[platform] default_chassis = DEFAULT_CHASSIS[platform]
vm = yield from dynamips_manager.create_vm(request.json.pop("name"), vm = yield from dynamips_manager.create_node(request.json.pop("name"),
request.match_info["project_id"], request.match_info["project_id"],
request.json.get("vm_id"), request.json.get("node_id"),
request.json.get("dynamips_id"), request.json.get("dynamips_id"),
platform, platform,
console=request.json.get("console"), console=request.json.get("console"),
@ -80,10 +80,10 @@ class DynamipsVMHandler:
@classmethod @classmethod
@Route.get( @Route.get(
r"/projects/{project_id}/dynamips/vms/{vm_id}", r"/projects/{project_id}/dynamips/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Success", 200: "Success",
@ -95,15 +95,15 @@ class DynamipsVMHandler:
def show(request, response): def show(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
response.json(vm) response.json(vm)
@classmethod @classmethod
@Route.put( @Route.put(
r"/projects/{project_id}/dynamips/vms/{vm_id}", r"/projects/{project_id}/dynamips/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance updated", 200: "Instance updated",
@ -117,17 +117,16 @@ class DynamipsVMHandler:
def update(request, response): def update(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from dynamips_manager.update_vm_settings(vm, request.json) yield from dynamips_manager.update_vm_settings(vm, request.json)
response.json(vm) response.json(vm)
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/dynamips/vms/{vm_id}", r"/projects/{project_id}/dynamips/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance deleted", 204: "Instance deleted",
@ -140,15 +139,15 @@ class DynamipsVMHandler:
# check the project_id exists # check the project_id exists
ProjectManager.instance().get_project(request.match_info["project_id"]) ProjectManager.instance().get_project(request.match_info["project_id"])
yield from Dynamips.instance().delete_vm(request.match_info["vm_id"]) yield from Dynamips.instance().delete_node(request.match_info["node_id"])
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/start", r"/projects/{project_id}/dynamips/nodes/{node_id}/start",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance started", 204: "Instance started",
@ -159,7 +158,7 @@ class DynamipsVMHandler:
def start(request, response): def start(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
try: try:
yield from dynamips_manager.ghost_ios_support(vm) yield from dynamips_manager.ghost_ios_support(vm)
except GeneratorExit: except GeneratorExit:
@ -169,10 +168,10 @@ class DynamipsVMHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/stop", r"/projects/{project_id}/dynamips/nodes/{node_id}/stop",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance stopped", 204: "Instance stopped",
@ -183,16 +182,16 @@ class DynamipsVMHandler:
def stop(request, response): def stop(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.stop() yield from vm.stop()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/suspend", r"/projects/{project_id}/dynamips/nodes/{node_id}/suspend",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance suspended", 204: "Instance suspended",
@ -203,16 +202,16 @@ class DynamipsVMHandler:
def suspend(request, response): def suspend(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.suspend() yield from vm.suspend()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/resume", r"/projects/{project_id}/dynamips/nodes/{node_id}/resume",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance resumed", 204: "Instance resumed",
@ -223,16 +222,16 @@ class DynamipsVMHandler:
def resume(request, response): def resume(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.resume() yield from vm.resume()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/reload", r"/projects/{project_id}/dynamips/nodes/{node_id}/reload",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance reloaded", 204: "Instance reloaded",
@ -243,15 +242,15 @@ class DynamipsVMHandler:
def reload(request, response): def reload(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.reload() yield from vm.reload()
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/dynamips/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter where the nio should be added", "adapter_number": "Adapter where the nio should be added",
"port_number": "Port on the adapter" "port_number": "Port on the adapter"
}, },
@ -266,7 +265,7 @@ class DynamipsVMHandler:
def create_nio(request, response): def create_nio(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
nio = yield from dynamips_manager.create_nio(vm, request.json) nio = yield from dynamips_manager.create_nio(vm, request.json)
slot_number = int(request.match_info["adapter_number"]) slot_number = int(request.match_info["adapter_number"])
port_number = int(request.match_info["port_number"]) port_number = int(request.match_info["port_number"])
@ -276,10 +275,10 @@ class DynamipsVMHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/dynamips/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/dynamips/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter from where the nio should be removed", "adapter_number": "Adapter from where the nio should be removed",
"port_number": "Port on the adapter" "port_number": "Port on the adapter"
}, },
@ -292,7 +291,7 @@ class DynamipsVMHandler:
def delete_nio(request, response): def delete_nio(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
slot_number = int(request.match_info["adapter_number"]) slot_number = int(request.match_info["adapter_number"])
port_number = int(request.match_info["port_number"]) port_number = int(request.match_info["port_number"])
nio = yield from vm.slot_remove_nio_binding(slot_number, port_number) nio = yield from vm.slot_remove_nio_binding(slot_number, port_number)
@ -300,10 +299,10 @@ class DynamipsVMHandler:
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture", r"/projects/{project_id}/dynamips/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to start a packet capture", "adapter_number": "Adapter to start a packet capture",
"port_number": "Port on the adapter" "port_number": "Port on the adapter"
}, },
@ -313,11 +312,11 @@ class DynamipsVMHandler:
404: "Instance doesn't exist" 404: "Instance doesn't exist"
}, },
description="Start a packet capture on a Dynamips VM instance", description="Start a packet capture on a Dynamips VM instance",
input=VM_CAPTURE_SCHEMA) input=NODE_CAPTURE_SCHEMA)
def start_capture(request, response): def start_capture(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
slot_number = int(request.match_info["adapter_number"]) slot_number = int(request.match_info["adapter_number"])
port_number = int(request.match_info["port_number"]) port_number = int(request.match_info["port_number"])
pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"])
@ -333,10 +332,10 @@ class DynamipsVMHandler:
response.json({"pcap_file_path": pcap_file_path}) response.json({"pcap_file_path": pcap_file_path})
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture", r"/projects/{project_id}/dynamips/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to stop a packet capture", "adapter_number": "Adapter to stop a packet capture",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -349,14 +348,14 @@ class DynamipsVMHandler:
def stop_capture(request, response): def stop_capture(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
slot_number = int(request.match_info["adapter_number"]) slot_number = int(request.match_info["adapter_number"])
port_number = int(request.match_info["port_number"]) port_number = int(request.match_info["port_number"])
yield from vm.stop_capture(slot_number, port_number) yield from vm.stop_capture(slot_number, port_number)
response.set_status(204) response.set_status(204)
@Route.get( @Route.get(
r"/projects/{project_id}/dynamips/vms/{vm_id}/configs", r"/projects/{project_id}/dynamips/nodes/{node_id}/configs",
status_codes={ status_codes={
200: "Configs retrieved", 200: "Configs retrieved",
400: "Invalid request", 400: "Invalid request",
@ -367,8 +366,7 @@ class DynamipsVMHandler:
def get_configs(request, response): def get_configs(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
project_id=request.match_info["project_id"])
startup_config_base64, private_config_base64 = yield from vm.extract_config() startup_config_base64, private_config_base64 = yield from vm.extract_config()
module_workdir = vm.project.module_working_directory(dynamips_manager.module_name.lower()) module_workdir = vm.project.module_working_directory(dynamips_manager.module_name.lower())
@ -411,7 +409,7 @@ class DynamipsVMHandler:
response.json(result) response.json(result)
@Route.post( @Route.post(
r"/projects/{project_id}/dynamips/vms/{vm_id}/configs/save", r"/projects/{project_id}/dynamips/nodes/{node_id}/configs/save",
status_codes={ status_codes={
200: "Configs saved", 200: "Configs saved",
400: "Invalid request", 400: "Invalid request",
@ -421,14 +419,12 @@ class DynamipsVMHandler:
def save_configs(request, response): def save_configs(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
project_id=request.match_info["project_id"])
yield from vm.save_configs() yield from vm.save_configs()
response.set_status(200) response.set_status(200)
@Route.get( @Route.get(
r"/projects/{project_id}/dynamips/vms/{vm_id}/idlepc_proposals", r"/projects/{project_id}/dynamips/nodes/{node_id}/idlepc_proposals",
status_codes={ status_codes={
200: "Idle-PCs retrieved", 200: "Idle-PCs retrieved",
400: "Invalid request", 400: "Invalid request",
@ -438,16 +434,14 @@ class DynamipsVMHandler:
def get_idlepcs(request, response): def get_idlepcs(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
project_id=request.match_info["project_id"])
yield from vm.set_idlepc("0x0") yield from vm.set_idlepc("0x0")
idlepcs = yield from vm.get_idle_pc_prop() idlepcs = yield from vm.get_idle_pc_prop()
response.set_status(200) response.set_status(200)
response.json(idlepcs) response.json(idlepcs)
@Route.get( @Route.get(
r"/projects/{project_id}/dynamips/vms/{vm_id}/auto_idlepc", r"/projects/{project_id}/dynamips/nodes/{node_id}/auto_idlepc",
status_codes={ status_codes={
200: "Best Idle-pc value found", 200: "Best Idle-pc value found",
400: "Invalid request", 400: "Invalid request",
@ -457,19 +451,18 @@ class DynamipsVMHandler:
def get_auto_idlepc(request, response): def get_auto_idlepc(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
vm = dynamips_manager.get_vm(request.match_info["vm_id"], vm = dynamips_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
project_id=request.match_info["project_id"])
idlepc = yield from dynamips_manager.auto_idlepc(vm) idlepc = yield from dynamips_manager.auto_idlepc(vm)
response.set_status(200) response.set_status(200)
response.json({"idlepc": idlepc}) response.json({"idlepc": idlepc})
@Route.get( @Route.get(
r"/dynamips/vms", r"/dynamips/nodes",
status_codes={ status_codes={
200: "List of Dynamips VM retrieved", 200: "List of Dynamips VM retrieved",
}, },
description="Retrieve the list of Dynamips VMS", description="Retrieve the list of Dynamips VMS",
output=VM_LIST_IMAGES_SCHEMA) output=NODE_LIST_IMAGES_SCHEMA)
def list_vms(request, response): def list_vms(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
@ -478,13 +471,13 @@ class DynamipsVMHandler:
response.json(vms) response.json(vms)
@Route.post( @Route.post(
r"/dynamips/vms/{path}", r"/dynamips/nodes/{path}",
status_codes={ status_codes={
204: "Image uploaded", 204: "Image uploaded",
}, },
raw=True, raw=True,
description="Upload Dynamips image.") description="Upload Dynamips image")
def upload_vm(request, response): def upload_image(request, response):
dynamips_manager = Dynamips.instance() dynamips_manager = Dynamips.instance()
yield from dynamips_manager.write_image(request.match_info["path"], request.content) yield from dynamips_manager.write_image(request.match_info["path"], request.content)

View File

@ -25,8 +25,8 @@ from ....schemas.iou import IOU_START_SCHEMA
from ....schemas.iou import IOU_UPDATE_SCHEMA from ....schemas.iou import IOU_UPDATE_SCHEMA
from ....schemas.iou import IOU_OBJECT_SCHEMA from ....schemas.iou import IOU_OBJECT_SCHEMA
from ....schemas.iou import IOU_CONFIGS_SCHEMA from ....schemas.iou import IOU_CONFIGS_SCHEMA
from ....schemas.vm import VM_LIST_IMAGES_SCHEMA from ....schemas.node import NODE_LIST_IMAGES_SCHEMA
from ....schemas.vm import VM_CAPTURE_SCHEMA from ....schemas.node import NODE_CAPTURE_SCHEMA
from ....compute.iou import IOU from ....compute.iou import IOU
@ -38,7 +38,7 @@ class IOUHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/iou/vms", r"/projects/{project_id}/iou/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
@ -53,10 +53,10 @@ class IOUHandler:
def create(request, response): def create(request, response):
iou = IOU.instance() iou = IOU.instance()
vm = yield from iou.create_vm(request.json.pop("name"), vm = yield from iou.create_node(request.json.pop("name"),
request.match_info["project_id"], request.match_info["project_id"],
request.json.get("vm_id"), request.json.get("node_id"),
console=request.json.get("console")) console=request.json.get("console"))
for name, value in request.json.items(): for name, value in request.json.items():
if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
@ -74,10 +74,10 @@ class IOUHandler:
@classmethod @classmethod
@Route.get( @Route.get(
r"/projects/{project_id}/iou/vms/{vm_id}", r"/projects/{project_id}/iou/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Success", 200: "Success",
@ -89,15 +89,15 @@ class IOUHandler:
def show(request, response): def show(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
response.json(vm) response.json(vm)
@classmethod @classmethod
@Route.put( @Route.put(
r"/projects/{project_id}/iou/vms/{vm_id}", r"/projects/{project_id}/iou/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance updated", 200: "Instance updated",
@ -111,7 +111,7 @@ class IOUHandler:
def update(request, response): def update(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
for name, value in request.json.items(): for name, value in request.json.items():
if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
@ -124,10 +124,10 @@ class IOUHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/iou/vms/{vm_id}", r"/projects/{project_id}/iou/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance deleted", 204: "Instance deleted",
@ -137,15 +137,15 @@ class IOUHandler:
description="Delete a IOU instance") description="Delete a IOU instance")
def delete(request, response): def delete(request, response):
yield from IOU.instance().delete_vm(request.match_info["vm_id"]) yield from IOU.instance().delete_node(request.match_info["node_id"])
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/iou/vms/{vm_id}/start", r"/projects/{project_id}/iou/nodes/{node_id}/start",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance started", 200: "Instance started",
@ -158,7 +158,7 @@ class IOUHandler:
def start(request, response): def start(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
for name, value in request.json.items(): for name, value in request.json.items():
if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
@ -169,10 +169,10 @@ class IOUHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/iou/vms/{vm_id}/stop", r"/projects/{project_id}/iou/nodes/{node_id}/stop",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance stopped", 204: "Instance stopped",
@ -183,16 +183,16 @@ class IOUHandler:
def stop(request, response): def stop(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.stop() yield from vm.stop()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/iou/vms/{vm_id}/reload", r"/projects/{project_id}/iou/nodes/{node_id}/reload",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
}, },
status_codes={ status_codes={
204: "Instance reloaded", 204: "Instance reloaded",
@ -203,15 +203,15 @@ class IOUHandler:
def reload(request, response): def reload(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.reload() yield from vm.reload()
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Network adapter where the nio is located", "adapter_number": "Network adapter where the nio is located",
"port_number": "Port where the nio should be added" "port_number": "Port where the nio should be added"
}, },
@ -226,7 +226,7 @@ class IOUHandler:
def create_nio(request, response): def create_nio(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
nio_type = request.json["type"] nio_type = request.json["type"]
if nio_type not in ("nio_udp", "nio_tap", "nio_generic_ethernet"): if nio_type not in ("nio_udp", "nio_tap", "nio_generic_ethernet"):
raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
@ -237,10 +237,10 @@ class IOUHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Network adapter where the nio is located", "adapter_number": "Network adapter where the nio is located",
"port_number": "Port from where the nio should be removed" "port_number": "Port from where the nio should be removed"
}, },
@ -253,15 +253,15 @@ class IOUHandler:
def delete_nio(request, response): def delete_nio(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"])) yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"]))
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture", r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to start a packet capture", "adapter_number": "Adapter to start a packet capture",
"port_number": "Port on the adapter" "port_number": "Port on the adapter"
}, },
@ -272,25 +272,24 @@ class IOUHandler:
409: "VM not started" 409: "VM not started"
}, },
description="Start a packet capture on a IOU VM instance", description="Start a packet capture on a IOU VM instance",
input=VM_CAPTURE_SCHEMA) input=NODE_CAPTURE_SCHEMA)
def start_capture(request, response): def start_capture(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
adapter_number = int(request.match_info["adapter_number"]) adapter_number = int(request.match_info["adapter_number"])
port_number = int(request.match_info["port_number"]) port_number = int(request.match_info["port_number"])
pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"])
if not vm.is_running(): if not vm.is_running():
raise HTTPConflict(text="Cannot capture traffic on a non started VM") raise HTTPConflict(text="Cannot capture traffic on a non started VM")
yield from vm.start_capture(adapter_number, port_number, pcap_file_path, request.json["data_link_type"]) yield from vm.start_capture(adapter_number, port_number, pcap_file_path, request.json["data_link_type"])
response.json({"pcap_file_path": str(pcap_file_path)}) response.json({"pcap_file_path": str(pcap_file_path)})
@Route.post( @Route.post(
r"/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture", r"/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to stop a packet capture", "adapter_number": "Adapter to stop a packet capture",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -304,7 +303,7 @@ class IOUHandler:
def stop_capture(request, response): def stop_capture(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
if not vm.is_running(): if not vm.is_running():
raise HTTPConflict(text="Cannot capture traffic on a non started VM") raise HTTPConflict(text="Cannot capture traffic on a non started VM")
@ -315,7 +314,7 @@ class IOUHandler:
response.set_status(204) response.set_status(204)
@Route.get( @Route.get(
r"/projects/{project_id}/iou/vms/{vm_id}/configs", r"/projects/{project_id}/iou/nodes/{node_id}/configs",
status_codes={ status_codes={
200: "Configs retrieved", 200: "Configs retrieved",
400: "Invalid request", 400: "Invalid request",
@ -326,7 +325,7 @@ class IOUHandler:
def get_configs(request, response): def get_configs(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
startup_config_content, private_config_content = vm.extract_configs() startup_config_content, private_config_content = vm.extract_configs()
result = {} result = {}
@ -352,7 +351,7 @@ class IOUHandler:
response.json(result) response.json(result)
@Route.post( @Route.post(
r"/projects/{project_id}/iou/vms/{vm_id}/configs/save", r"/projects/{project_id}/iou/nodes/{node_id}/configs/save",
status_codes={ status_codes={
200: "Configs saved", 200: "Configs saved",
400: "Invalid request", 400: "Invalid request",
@ -362,32 +361,32 @@ class IOUHandler:
def save_configs(request, response): def save_configs(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = iou_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
vm.save_configs() vm.save_configs()
response.set_status(200) response.set_status(200)
@Route.get( @Route.get(
r"/iou/vms", r"/iou/nodes",
status_codes={ status_codes={
200: "List of IOU VM retrieved", 200: "List of IOU VM retrieved",
}, },
description="Retrieve the list of IOU VMS", description="Retrieve the list of IOU VMS",
output=VM_LIST_IMAGES_SCHEMA) output=NODE_LIST_IMAGES_SCHEMA)
def list_vms(request, response): def list_iou_nodes(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
vms = yield from iou_manager.list_images() iou_nodes = yield from iou_manager.list_images()
response.set_status(200) response.set_status(200)
response.json(vms) response.json(iou_nodes)
@Route.post( @Route.post(
r"/iou/vms/{path}", r"/iou/nodes/{path}",
status_codes={ status_codes={
204: "Image uploaded", 204: "Image uploaded",
}, },
raw=True, raw=True,
description="Upload IOU image.") description="Upload IOU image.")
def upload_vm(request, response): def upload_image(request, response):
iou_manager = IOU.instance() iou_manager = IOU.instance()
yield from iou_manager.write_image(request.match_info["path"], request.content) yield from iou_manager.write_image(request.match_info["path"], request.content)

View File

@ -29,7 +29,7 @@ from ....schemas.qemu import QEMU_BINARY_FILTER_SCHEMA
from ....schemas.qemu import QEMU_BINARY_LIST_SCHEMA from ....schemas.qemu import QEMU_BINARY_LIST_SCHEMA
from ....schemas.qemu import QEMU_CAPABILITY_LIST_SCHEMA from ....schemas.qemu import QEMU_CAPABILITY_LIST_SCHEMA
from ....schemas.qemu import QEMU_IMAGE_CREATE_SCHEMA from ....schemas.qemu import QEMU_IMAGE_CREATE_SCHEMA
from ....schemas.vm import VM_LIST_IMAGES_SCHEMA from ....schemas.node import NODE_LIST_IMAGES_SCHEMA
from ....compute.qemu import Qemu from ....compute.qemu import Qemu
from ....config import Config from ....config import Config
@ -42,7 +42,7 @@ class QEMUHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/qemu/vms", r"/projects/{project_id}/qemu/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
@ -57,14 +57,14 @@ class QEMUHandler:
def create(request, response): def create(request, response):
qemu = Qemu.instance() qemu = Qemu.instance()
vm = yield from qemu.create_vm(request.json.pop("name"), vm = yield from qemu.create_node(request.json.pop("name"),
request.match_info["project_id"], request.match_info["project_id"],
request.json.pop("vm_id", None), request.json.pop("node_id", None),
linked_clone=request.json.get("linked_clone", True), linked_clone=request.json.get("linked_clone", True),
qemu_path=request.json.pop("qemu_path", None), qemu_path=request.json.pop("qemu_path", None),
console=request.json.pop("console", None), console=request.json.pop("console", None),
console_type=request.json.pop("console_type", "telnet"), console_type=request.json.pop("console_type", "telnet"),
platform=request.json.pop("platform", None)) platform=request.json.pop("platform", None))
for name, value in request.json.items(): for name, value in request.json.items():
if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
@ -75,10 +75,10 @@ class QEMUHandler:
@classmethod @classmethod
@Route.get( @Route.get(
r"/projects/{project_id}/qemu/vms/{vm_id}", r"/projects/{project_id}/qemu/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Success", 200: "Success",
@ -90,15 +90,15 @@ class QEMUHandler:
def show(request, response): def show(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
response.json(vm) response.json(vm)
@classmethod @classmethod
@Route.put( @Route.put(
r"/projects/{project_id}/qemu/vms/{vm_id}", r"/projects/{project_id}/qemu/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance updated", 200: "Instance updated",
@ -112,7 +112,7 @@ class QEMUHandler:
def update(request, response): def update(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
for name, value in request.json.items(): for name, value in request.json.items():
if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
@ -122,10 +122,10 @@ class QEMUHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/qemu/vms/{vm_id}", r"/projects/{project_id}/qemu/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance deleted", 204: "Instance deleted",
@ -135,15 +135,15 @@ class QEMUHandler:
description="Delete a Qemu VM instance") description="Delete a Qemu VM instance")
def delete(request, response): def delete(request, response):
yield from Qemu.instance().delete_vm(request.match_info["vm_id"]) yield from Qemu.instance().delete_node(request.match_info["node_id"])
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/qemu/vms/{vm_id}/start", r"/projects/{project_id}/qemu/nodes/{node_id}/start",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance started", 200: "Instance started",
@ -155,7 +155,7 @@ class QEMUHandler:
def start(request, response): def start(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
if sys.platform.startswith("linux") and qemu_manager.config.get_section_config("Qemu").getboolean("enable_kvm", True) \ if sys.platform.startswith("linux") and qemu_manager.config.get_section_config("Qemu").getboolean("enable_kvm", True) \
and "-no-kvm" not in vm.options: and "-no-kvm" not in vm.options:
pm = ProjectManager.instance() pm = ProjectManager.instance()
@ -166,10 +166,10 @@ class QEMUHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/qemu/vms/{vm_id}/stop", r"/projects/{project_id}/qemu/nodes/{node_id}/stop",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "vm_node": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance stopped", 204: "Instance stopped",
@ -180,16 +180,16 @@ class QEMUHandler:
def stop(request, response): def stop(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.stop() yield from vm.stop()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/qemu/vms/{vm_id}/reload", r"/projects/{project_id}/qemu/nodes/{node_id}/reload",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
}, },
status_codes={ status_codes={
204: "Instance reloaded", 204: "Instance reloaded",
@ -200,16 +200,16 @@ class QEMUHandler:
def reload(request, response): def reload(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.reload() yield from vm.reload()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/qemu/vms/{vm_id}/suspend", r"/projects/{project_id}/qemu/nodes/{node_id}/suspend",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
}, },
status_codes={ status_codes={
204: "Instance suspended", 204: "Instance suspended",
@ -220,16 +220,16 @@ class QEMUHandler:
def suspend(request, response): def suspend(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.suspend() yield from vm.suspend()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/qemu/vms/{vm_id}/resume", r"/projects/{project_id}/qemu/nodes/{node_id}/resume",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
}, },
status_codes={ status_codes={
204: "Instance resumed", 204: "Instance resumed",
@ -240,15 +240,15 @@ class QEMUHandler:
def resume(request, response): def resume(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.resume() yield from vm.resume()
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/qemu/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Network adapter where the nio is located", "adapter_number": "Network adapter where the nio is located",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -263,7 +263,7 @@ class QEMUHandler:
def create_nio(request, response): def create_nio(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
nio_type = request.json["type"] nio_type = request.json["type"]
if nio_type not in ("nio_udp", "nio_tap", "nio_nat"): if nio_type not in ("nio_udp", "nio_tap", "nio_nat"):
raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
@ -274,10 +274,10 @@ class QEMUHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/qemu/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Network adapter where the nio is located", "adapter_number": "Network adapter where the nio is located",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -290,7 +290,7 @@ class QEMUHandler:
def delete_nio(request, response): def delete_nio(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = qemu_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"])) yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]))
response.set_status(204) response.set_status(204)
@ -363,27 +363,27 @@ class QEMUHandler:
response.set_status(201) response.set_status(201)
@Route.get( @Route.get(
r"/qemu/vms", r"/qemu/nodes",
status_codes={ status_codes={
200: "List of Qemu images retrieved", 200: "List of Qemu images retrieved",
}, },
description="Retrieve the list of Qemu images", description="Retrieve the list of Qemu images",
output=VM_LIST_IMAGES_SCHEMA) output=NODE_LIST_IMAGES_SCHEMA)
def list_vms(request, response): def list_vm_nodes(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
vms = yield from qemu_manager.list_images() vm_nodes = yield from qemu_manager.list_images()
response.set_status(200) response.set_status(200)
response.json(vms) response.json(vm_nodes)
@Route.post( @Route.post(
r"/qemu/vms/{path:.+}", r"/qemu/nodes/{path:.+}",
status_codes={ status_codes={
204: "Image uploaded", 204: "Image uploaded",
}, },
raw=True, raw=True,
description="Upload Qemu image.") description="Upload Qemu image.")
def upload_vm(request, response): def upload_image(request, response):
qemu_manager = Qemu.instance() qemu_manager = Qemu.instance()
yield from qemu_manager.write_image(request.match_info["path"], request.content) yield from qemu_manager.write_image(request.match_info["path"], request.content)

View File

@ -23,7 +23,7 @@ from ....schemas.nio import NIO_SCHEMA
from ....schemas.virtualbox import VBOX_CREATE_SCHEMA from ....schemas.virtualbox import VBOX_CREATE_SCHEMA
from ....schemas.virtualbox import VBOX_UPDATE_SCHEMA from ....schemas.virtualbox import VBOX_UPDATE_SCHEMA
from ....schemas.virtualbox import VBOX_OBJECT_SCHEMA from ....schemas.virtualbox import VBOX_OBJECT_SCHEMA
from ....schemas.vm import VM_CAPTURE_SCHEMA from ....schemas.node import NODE_CAPTURE_SCHEMA
from ....compute.virtualbox import VirtualBox from ....compute.virtualbox import VirtualBox
from ....compute.project_manager import ProjectManager from ....compute.project_manager import ProjectManager
@ -40,16 +40,16 @@ class VirtualBoxHandler:
status_codes={ status_codes={
200: "Success", 200: "Success",
}, },
description="Get all VirtualBox VMs available") description="Get all available VirtualBox VMs")
def index(request, response): def index(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vms = yield from vbox_manager.list_images() vms = yield from vbox_manager.list_vms()
response.json(vms) response.json(vms)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms", r"/projects/{project_id}/virtualbox/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
@ -64,13 +64,13 @@ class VirtualBoxHandler:
def create(request, response): def create(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = yield from vbox_manager.create_vm(request.json.pop("name"), vm = yield from vbox_manager.create_node(request.json.pop("name"),
request.match_info["project_id"], request.match_info["project_id"],
request.json.get("vm_id"), request.json.get("node_id"),
request.json.pop("vmname"), request.json.pop("vmname"),
request.json.pop("linked_clone"), request.json.pop("linked_clone"),
console=request.json.get("console", None), console=request.json.get("console", None),
adapters=request.json.get("adapters", 0)) adapters=request.json.get("adapters", 0))
if "enable_remote_console" in request.json: if "enable_remote_console" in request.json:
yield from vm.set_enable_remote_console(request.json.pop("enable_remote_console")) yield from vm.set_enable_remote_console(request.json.pop("enable_remote_console"))
@ -81,7 +81,7 @@ class VirtualBoxHandler:
yield from vm.set_ram(ram) yield from vm.set_ram(ram)
for name, value in request.json.items(): for name, value in request.json.items():
if name != "vm_id": if name != "node_id":
if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
setattr(vm, name, value) setattr(vm, name, value)
@ -90,10 +90,10 @@ class VirtualBoxHandler:
@classmethod @classmethod
@Route.get( @Route.get(
r"/projects/{project_id}/virtualbox/vms/{vm_id}", r"/projects/{project_id}/virtualbox/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Success", 200: "Success",
@ -105,15 +105,15 @@ class VirtualBoxHandler:
def show(request, response): def show(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
response.json(vm) response.json(vm)
@classmethod @classmethod
@Route.put( @Route.put(
r"/projects/{project_id}/virtualbox/vms/{vm_id}", r"/projects/{project_id}/virtualbox/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance updated", 200: "Instance updated",
@ -127,7 +127,7 @@ class VirtualBoxHandler:
def update(request, response): def update(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
if "vmname" in request.json: if "vmname" in request.json:
vmname = request.json.pop("vmname") vmname = request.json.pop("vmname")
@ -155,10 +155,10 @@ class VirtualBoxHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/virtualbox/vms/{vm_id}", r"/projects/{project_id}/virtualbox/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance deleted", 204: "Instance deleted",
@ -171,15 +171,15 @@ class VirtualBoxHandler:
# check the project_id exists # check the project_id exists
ProjectManager.instance().get_project(request.match_info["project_id"]) ProjectManager.instance().get_project(request.match_info["project_id"])
yield from VirtualBox.instance().delete_vm(request.match_info["vm_id"]) yield from VirtualBox.instance().delete_node(request.match_info["node_id"])
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/start", r"/projects/{project_id}/virtualbox/nodes/{node_id}/start",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance started", 204: "Instance started",
@ -190,7 +190,7 @@ class VirtualBoxHandler:
def start(request, response): def start(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
if (yield from vm.check_hw_virtualization()): if (yield from vm.check_hw_virtualization()):
pm = ProjectManager.instance() pm = ProjectManager.instance()
if pm.check_hardware_virtualization(vm) is False: if pm.check_hardware_virtualization(vm) is False:
@ -200,10 +200,10 @@ class VirtualBoxHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/stop", r"/projects/{project_id}/virtualbox/nodes/{node_id}/stop",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance stopped", 204: "Instance stopped",
@ -214,16 +214,16 @@ class VirtualBoxHandler:
def stop(request, response): def stop(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.stop() yield from vm.stop()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/suspend", r"/projects/{project_id}/virtualbox/nodes/{node_id}/suspend",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance suspended", 204: "Instance suspended",
@ -234,16 +234,16 @@ class VirtualBoxHandler:
def suspend(request, response): def suspend(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.suspend() yield from vm.suspend()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/resume", r"/projects/{project_id}/virtualbox/nodes/{node_id}/resume",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance resumed", 204: "Instance resumed",
@ -254,16 +254,16 @@ class VirtualBoxHandler:
def resume(request, response): def resume(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.resume() yield from vm.resume()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/reload", r"/projects/{project_id}/virtualbox/nodes/{node_id}/reload",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance reloaded", 204: "Instance reloaded",
@ -274,15 +274,15 @@ class VirtualBoxHandler:
def reload(request, response): def reload(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.reload() yield from vm.reload()
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter where the nio should be added", "adapter_number": "Adapter where the nio should be added",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -297,7 +297,7 @@ class VirtualBoxHandler:
def create_nio(request, response): def create_nio(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
nio_type = request.json["type"] nio_type = request.json["type"]
if nio_type not in ("nio_udp", "nio_nat"): if nio_type not in ("nio_udp", "nio_nat"):
raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
@ -308,10 +308,10 @@ class VirtualBoxHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter from where the nio should be removed", "adapter_number": "Adapter from where the nio should be removed",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -324,15 +324,15 @@ class VirtualBoxHandler:
def delete_nio(request, response): def delete_nio(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"])) yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]))
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture", r"/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to start a packet capture", "adapter_number": "Adapter to start a packet capture",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -342,21 +342,21 @@ class VirtualBoxHandler:
404: "Instance doesn't exist" 404: "Instance doesn't exist"
}, },
description="Start a packet capture on a VirtualBox VM instance", description="Start a packet capture on a VirtualBox VM instance",
input=VM_CAPTURE_SCHEMA) input=NODE_CAPTURE_SCHEMA)
def start_capture(request, response): def start_capture(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
adapter_number = int(request.match_info["adapter_number"]) adapter_number = int(request.match_info["adapter_number"])
pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"])
yield from vm.start_capture(adapter_number, pcap_file_path) yield from vm.start_capture(adapter_number, pcap_file_path)
response.json({"pcap_file_path": pcap_file_path}) response.json({"pcap_file_path": pcap_file_path})
@Route.post( @Route.post(
r"/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture", r"/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to stop a packet capture", "adapter_number": "Adapter to stop a packet capture",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -369,6 +369,6 @@ class VirtualBoxHandler:
def stop_capture(request, response): def stop_capture(request, response):
vbox_manager = VirtualBox.instance() vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
vm.stop_capture(int(request.match_info["adapter_number"])) vm.stop_capture(int(request.match_info["adapter_number"]))
response.set_status(204) response.set_status(204)

View File

@ -22,7 +22,7 @@ from ....web.route import Route
from ....schemas.vmware import VMWARE_CREATE_SCHEMA from ....schemas.vmware import VMWARE_CREATE_SCHEMA
from ....schemas.vmware import VMWARE_UPDATE_SCHEMA from ....schemas.vmware import VMWARE_UPDATE_SCHEMA
from ....schemas.vmware import VMWARE_OBJECT_SCHEMA from ....schemas.vmware import VMWARE_OBJECT_SCHEMA
from ....schemas.vm import VM_CAPTURE_SCHEMA from ....schemas.node import NODE_CAPTURE_SCHEMA
from ....schemas.nio import NIO_SCHEMA from ....schemas.nio import NIO_SCHEMA
from ....compute.vmware import VMware from ....compute.vmware import VMware
from ....compute.project_manager import ProjectManager from ....compute.project_manager import ProjectManager
@ -49,7 +49,7 @@ class VMwareHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms", r"/projects/{project_id}/vmware/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
@ -64,15 +64,15 @@ class VMwareHandler:
def create(request, response): def create(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = yield from vmware_manager.create_vm(request.json.pop("name"), vm = yield from vmware_manager.create_node(request.json.pop("name"),
request.match_info["project_id"], request.match_info["project_id"],
request.json.get("vm_id"), request.json.get("node_id"),
request.json.pop("vmx_path"), request.json.pop("vmx_path"),
request.json.pop("linked_clone"), request.json.pop("linked_clone"),
console=request.json.get("console", None)) console=request.json.get("console", None))
for name, value in request.json.items(): for name, value in request.json.items():
if name != "vm_id": if name != "node_id":
if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
setattr(vm, name, value) setattr(vm, name, value)
@ -81,10 +81,10 @@ class VMwareHandler:
@classmethod @classmethod
@Route.get( @Route.get(
r"/projects/{project_id}/vmware/vms/{vm_id}", r"/projects/{project_id}/vmware/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Success", 200: "Success",
@ -96,15 +96,15 @@ class VMwareHandler:
def show(request, response): def show(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
response.json(vm) response.json(vm)
@classmethod @classmethod
@Route.put( @Route.put(
r"/projects/{project_id}/vmware/vms/{vm_id}", r"/projects/{project_id}/vmware/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance updated", 200: "Instance updated",
@ -118,7 +118,7 @@ class VMwareHandler:
def update(request, response): def update(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
for name, value in request.json.items(): for name, value in request.json.items():
if hasattr(vm, name) and getattr(vm, name) != value: if hasattr(vm, name) and getattr(vm, name) != value:
@ -128,10 +128,10 @@ class VMwareHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/vmware/vms/{vm_id}", r"/projects/{project_id}/vmware/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance deleted", 204: "Instance deleted",
@ -143,15 +143,15 @@ class VMwareHandler:
# check the project_id exists # check the project_id exists
ProjectManager.instance().get_project(request.match_info["project_id"]) ProjectManager.instance().get_project(request.match_info["project_id"])
yield from VMware.instance().delete_vm(request.match_info["vm_id"]) yield from VMware.instance().delete_node(request.match_info["node_id"])
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/start", r"/projects/{project_id}/vmware/nodes/{node_id}/start",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance started", 204: "Instance started",
@ -162,7 +162,7 @@ class VMwareHandler:
def start(request, response): def start(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
if vm.check_hw_virtualization(): if vm.check_hw_virtualization():
pm = ProjectManager.instance() pm = ProjectManager.instance()
if pm.check_hardware_virtualization(vm) is False: if pm.check_hardware_virtualization(vm) is False:
@ -172,10 +172,10 @@ class VMwareHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/stop", r"/projects/{project_id}/vmware/nodes/{node_id}/stop",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance stopped", 204: "Instance stopped",
@ -186,16 +186,16 @@ class VMwareHandler:
def stop(request, response): def stop(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.stop() yield from vm.stop()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/suspend", r"/projects/{project_id}/vmware/nodes/{node_id}/suspend",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance suspended", 204: "Instance suspended",
@ -206,16 +206,16 @@ class VMwareHandler:
def suspend(request, response): def suspend(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.suspend() yield from vm.suspend()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/resume", r"/projects/{project_id}/vmware/nodes/{node_id}/resume",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance resumed", 204: "Instance resumed",
@ -226,16 +226,16 @@ class VMwareHandler:
def resume(request, response): def resume(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.resume() yield from vm.resume()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/reload", r"/projects/{project_id}/vmware/nodes/{node_id}/reload",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance reloaded", 204: "Instance reloaded",
@ -246,15 +246,15 @@ class VMwareHandler:
def reload(request, response): def reload(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.reload() yield from vm.reload()
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter where the nio should be added", "adapter_number": "Adapter where the nio should be added",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -269,7 +269,7 @@ class VMwareHandler:
def create_nio(request, response): def create_nio(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
nio_type = request.json["type"] nio_type = request.json["type"]
if nio_type not in ("nio_udp", "nio_vmnet", "nio_nat"): if nio_type not in ("nio_udp", "nio_vmnet", "nio_nat"):
raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
@ -280,10 +280,10 @@ class VMwareHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/vmware/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter from where the nio should be removed", "adapter_number": "Adapter from where the nio should be removed",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -296,15 +296,15 @@ class VMwareHandler:
def delete_nio(request, response): def delete_nio(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"])) yield from vm.adapter_remove_nio_binding(int(request.match_info["adapter_number"]))
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture", r"/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/start_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to start a packet capture", "adapter_number": "Adapter to start a packet capture",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -314,21 +314,21 @@ class VMwareHandler:
404: "Instance doesn't exist", 404: "Instance doesn't exist",
}, },
description="Start a packet capture on a VMware VM instance", description="Start a packet capture on a VMware VM instance",
input=VM_CAPTURE_SCHEMA) input=NODE_CAPTURE_SCHEMA)
def start_capture(request, response): def start_capture(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
adapter_number = int(request.match_info["adapter_number"]) adapter_number = int(request.match_info["adapter_number"])
pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"]) pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"])
yield from vm.start_capture(adapter_number, pcap_file_path) yield from vm.start_capture(adapter_number, pcap_file_path)
response.json({"pcap_file_path": pcap_file_path}) response.json({"pcap_file_path": pcap_file_path})
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture", r"/projects/{project_id}/vmware/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/stop_capture",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Adapter to stop a packet capture", "adapter_number": "Adapter to stop a packet capture",
"port_number": "Port on the adapter (always 0)" "port_number": "Port on the adapter (always 0)"
}, },
@ -341,17 +341,17 @@ class VMwareHandler:
def stop_capture(request, response): def stop_capture(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
adapter_number = int(request.match_info["adapter_number"]) adapter_number = int(request.match_info["adapter_number"])
yield from vm.stop_capture(adapter_number) yield from vm.stop_capture(adapter_number)
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vmware/vms/{vm_id}/interfaces/vmnet", r"/projects/{project_id}/vmware/nodes/{node_id}/interfaces/vmnet",
parameters={ parameters={
"project_id": "The UUID of the project", "project_id": "The UUID of the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
}, },
status_codes={ status_codes={
201: "VMnet interface allocated", 201: "VMnet interface allocated",
@ -360,7 +360,7 @@ class VMwareHandler:
def allocate_vmnet(request, response): def allocate_vmnet(request, response):
vmware_manager = VMware.instance() vmware_manager = VMware.instance()
vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
vmware_manager.refresh_vmnet_list(ubridge=False) vmware_manager.refresh_vmnet_list(ubridge=False)
vmnet = vmware_manager.allocate_vmnet() vmnet = vmware_manager.allocate_vmnet()
vm.vmnets.append(vmnet) vm.vmnets.append(vmnet)

View File

@ -32,7 +32,7 @@ class VPCSHandler:
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vpcs/vms", r"/projects/{project_id}/vpcs/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
@ -47,20 +47,20 @@ class VPCSHandler:
def create(request, response): def create(request, response):
vpcs = VPCS.instance() vpcs = VPCS.instance()
vm = yield from vpcs.create_vm(request.json["name"], node = yield from vpcs.create_node(request.json["name"],
request.match_info["project_id"], request.match_info["project_id"],
request.json.get("vm_id"), request.json.get("node_id"),
console=request.json.get("console"), console=request.json.get("console"),
startup_script=request.json.get("startup_script")) startup_script=request.json.get("startup_script"))
response.set_status(201) response.set_status(201)
response.json(vm) response.json(node)
@classmethod @classmethod
@Route.get( @Route.get(
r"/projects/{project_id}/vpcs/vms/{vm_id}", r"/projects/{project_id}/vpcs/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Success", 200: "Success",
@ -72,15 +72,15 @@ class VPCSHandler:
def show(request, response): def show(request, response):
vpcs_manager = VPCS.instance() vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
response.json(vm) response.json(vm)
@classmethod @classmethod
@Route.put( @Route.put(
r"/projects/{project_id}/vpcs/vms/{vm_id}", r"/projects/{project_id}/vpcs/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
200: "Instance updated", 200: "Instance updated",
@ -94,7 +94,7 @@ class VPCSHandler:
def update(request, response): def update(request, response):
vpcs_manager = VPCS.instance() vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
vm.name = request.json.get("name", vm.name) vm.name = request.json.get("name", vm.name)
vm.console = request.json.get("console", vm.console) vm.console = request.json.get("console", vm.console)
vm.startup_script = request.json.get("startup_script", vm.startup_script) vm.startup_script = request.json.get("startup_script", vm.startup_script)
@ -102,10 +102,10 @@ class VPCSHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/vpcs/vms/{vm_id}", r"/projects/{project_id}/vpcs/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance deleted", 204: "Instance deleted",
@ -115,15 +115,15 @@ class VPCSHandler:
description="Delete a VPCS instance") description="Delete a VPCS instance")
def delete(request, response): def delete(request, response):
yield from VPCS.instance().delete_vm(request.match_info["vm_id"]) yield from VPCS.instance().delete_node(request.match_info["node_id"])
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vpcs/vms/{vm_id}/start", r"/projects/{project_id}/vpcs/nodes/{node_id}/start",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance started", 204: "Instance started",
@ -135,16 +135,16 @@ class VPCSHandler:
def start(request, response): def start(request, response):
vpcs_manager = VPCS.instance() vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.start() yield from vm.start()
response.json(vm) response.json(vm)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vpcs/vms/{vm_id}/stop", r"/projects/{project_id}/vpcs/nodes/{node_id}/stop",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance" "node_id": "UUID for the instance"
}, },
status_codes={ status_codes={
204: "Instance stopped", 204: "Instance stopped",
@ -155,16 +155,16 @@ class VPCSHandler:
def stop(request, response): def stop(request, response):
vpcs_manager = VPCS.instance() vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.stop() yield from vm.stop()
response.set_status(204) response.set_status(204)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vpcs/vms/{vm_id}/reload", r"/projects/{project_id}/vpcs/nodes/{node_id}/reload",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
}, },
status_codes={ status_codes={
204: "Instance reloaded", 204: "Instance reloaded",
@ -175,15 +175,15 @@ class VPCSHandler:
def reload(request, response): def reload(request, response):
vpcs_manager = VPCS.instance() vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
yield from vm.reload() yield from vm.reload()
response.set_status(204) response.set_status(204)
@Route.post( @Route.post(
r"/projects/{project_id}/vpcs/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Network adapter where the nio is located", "adapter_number": "Network adapter where the nio is located",
"port_number": "Port where the nio should be added" "port_number": "Port where the nio should be added"
}, },
@ -198,7 +198,7 @@ class VPCSHandler:
def create_nio(request, response): def create_nio(request, response):
vpcs_manager = VPCS.instance() vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
nio_type = request.json["type"] nio_type = request.json["type"]
if nio_type not in ("nio_udp", "nio_tap"): if nio_type not in ("nio_udp", "nio_tap"):
raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type)) raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
@ -209,10 +209,10 @@ class VPCSHandler:
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/vpcs/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio", r"/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the instance", "node_id": "UUID for the instance",
"adapter_number": "Network adapter where the nio is located", "adapter_number": "Network adapter where the nio is located",
"port_number": "Port from where the nio should be removed" "port_number": "Port from where the nio should be removed"
}, },
@ -225,6 +225,6 @@ class VPCSHandler:
def delete_nio(request, response): def delete_nio(request, response):
vpcs_manager = VPCS.instance() vpcs_manager = VPCS.instance()
vm = vpcs_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"]) vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
vm.port_remove_nio_binding(int(request.match_info["port_number"])) vm.port_remove_nio_binding(int(request.match_info["port_number"]))
response.set_status(204) response.set_status(204)

View File

@ -18,5 +18,5 @@
from .compute_handler import ComputeHandler from .compute_handler import ComputeHandler
from .project_handler import ProjectHandler from .project_handler import ProjectHandler
from .version_handler import VersionHandler from .version_handler import VersionHandler
from .vm_handler import VMHandler from .node_handler import NodeHandler
from .link_handler import LinkHandler from .link_handler import LinkHandler

View File

@ -44,7 +44,7 @@ class ComputeHandler:
output=COMPUTE_OBJECT_SCHEMA) output=COMPUTE_OBJECT_SCHEMA)
def create(request, response): def create(request, response):
compute = yield from Controller.instance().addCompute(**request.json) compute = yield from Controller.instance().add_compute(**request.json)
response.set_status(201) response.set_status(201)
response.json(compute) response.json(compute)

View File

@ -16,11 +16,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import aiohttp import aiohttp
import asyncio
from ....web.route import Route from ....web.route import Route
from ....schemas.link import LINK_OBJECT_SCHEMA, LINK_CAPTURE_SCHEMA from ....schemas.link import LINK_OBJECT_SCHEMA, LINK_CAPTURE_SCHEMA
from ....controller.project import Project
from ....controller import Controller from ....controller import Controller
@ -45,12 +43,10 @@ class LinkHandler:
def create(request, response): def create(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
link = yield from project.addLink() link = yield from project.add_link()
for vm in request.json["vms"]: for node in request.json["nodes"]:
yield from link.addVM(project.getVM(vm["vm_id"]), yield from link.add_node(project.get_node(node["node_id"]), node["adapter_number"], node["port_number"])
vm["adapter_number"],
vm["port_number"])
yield from link.create() yield from link.create()
response.set_status(201) response.set_status(201)
response.json(link) response.json(link)
@ -72,8 +68,8 @@ class LinkHandler:
def start_capture(request, response): def start_capture(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
link = project.getLink(request.match_info["link_id"]) link = project.get_link(request.match_info["link_id"])
yield from link.start_capture(data_link_type=request.json.get("data_link_type", "DLT_EN10MB"), capture_file_name=request.json.get("capture_file_name")) yield from link.start_capture(data_link_type=request.json.get("data_link_type", "DLT_EN10MB"), capture_file_name=request.json.get("capture_file_name"))
response.set_status(201) response.set_status(201)
response.json(link) response.json(link)
@ -93,8 +89,8 @@ class LinkHandler:
def stop_capture(request, response): def stop_capture(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
link = project.getLink(request.match_info["link_id"]) link = project.get_link(request.match_info["link_id"])
yield from link.stop_capture() yield from link.stop_capture()
response.set_status(201) response.set_status(201)
response.json(link) response.json(link)
@ -114,8 +110,8 @@ class LinkHandler:
def delete(request, response): def delete(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
link = project.getLink(request.match_info["link_id"]) link = project.get_link(request.match_info["link_id"])
yield from link.delete() yield from link.delete()
response.set_status(204) response.set_status(204)
response.json(link) response.json(link)
@ -136,8 +132,8 @@ class LinkHandler:
def pcap(request, response): def pcap(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
link = project.getLink(request.match_info["link_id"]) link = project.get_link(request.match_info["link_id"])
if link.capture_file_path is None: if link.capture_file_path is None:
raise aiohttp.web.HTTPNotFound(text="pcap file not found") raise aiohttp.web.HTTPNotFound(text="pcap file not found")

View File

@ -16,19 +16,18 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from ....web.route import Route from ....web.route import Route
from ....schemas.vm import VM_OBJECT_SCHEMA, VM_UPDATE_SCHEMA from ....schemas.node import NODE_OBJECT_SCHEMA, NODE_UPDATE_SCHEMA
from ....controller.project import Project
from ....controller import Controller from ....controller import Controller
class VMHandler: class NodeHandler:
""" """
API entry point for VM API entry point for node
""" """
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vms", r"/projects/{project_id}/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
@ -36,155 +35,155 @@ class VMHandler:
201: "Instance created", 201: "Instance created",
400: "Invalid request" 400: "Invalid request"
}, },
description="Create a new VM instance", description="Create a new node instance",
input=VM_OBJECT_SCHEMA, input=NODE_OBJECT_SCHEMA,
output=VM_OBJECT_SCHEMA) output=NODE_OBJECT_SCHEMA)
def create(request, response): def create(request, response):
controller = Controller.instance() controller = Controller.instance()
compute = controller.getCompute(request.json.pop("compute_id")) compute = controller.getCompute(request.json.pop("compute_id"))
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
vm = yield from project.addVM(compute, request.json.pop("vm_id", None), **request.json) node = yield from project.add_node(compute, request.json.pop("node_id", None), **request.json)
response.set_status(201) response.set_status(201)
response.json(vm) response.json(node)
@classmethod @classmethod
@Route.get( @Route.get(
r"/projects/{project_id}/vms", r"/projects/{project_id}/nodes",
parameters={ parameters={
"project_id": "UUID for the project" "project_id": "UUID for the project"
}, },
status_codes={ status_codes={
200: "List of VMS", 200: "List of nodes",
}, },
description="List VMs of a project") description="List nodes of a project")
def list_vms(request, response): def list_nodes(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
response.json([ v for v in project.vms.values() ]) response.json([ v for v in project.nodes.values() ])
@classmethod @classmethod
@Route.put( @Route.put(
r"/projects/{project_id}/vms/{vm_id}", r"/projects/{project_id}/nodes/{node_id}",
status_codes={ status_codes={
201: "Instance created", 201: "Instance created",
400: "Invalid request" 400: "Invalid request"
}, },
description="Update a VM instance", description="Update a node instance",
input=VM_UPDATE_SCHEMA, input=NODE_UPDATE_SCHEMA,
output=VM_OBJECT_SCHEMA) output=NODE_OBJECT_SCHEMA)
def update(request, response): def update(request, response):
project = Controller.instance().getProject(request.match_info["project_id"]) project = Controller.instance().get_project(request.match_info["project_id"])
vm = project.getVM(request.match_info["vm_id"]) node = project.get_node(request.match_info["node_id"])
# Ignore this, because we use it only in create # Ignore this, because we use it only in create
request.json.pop("vm_id", None) request.json.pop("node_id", None)
request.json.pop("vm_type", None) request.json.pop("node_type", None)
request.json.pop("compute_id", None) request.json.pop("compute_id", None)
yield from vm.update(**request.json) yield from node.update(**request.json)
response.set_status(201) response.set_status(201)
response.json(vm) response.json(node)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vms/{vm_id}/start", r"/projects/{project_id}/nodes/{node_id}/start",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the VM" "node_id": "UUID for the node"
}, },
status_codes={ status_codes={
201: "Instance created", 201: "Instance created",
400: "Invalid request" 400: "Invalid request"
}, },
description="Start a VM instance", description="Start a node instance",
output=VM_OBJECT_SCHEMA) output=NODE_OBJECT_SCHEMA)
def start(request, response): def start(request, response):
project = Controller.instance().getProject(request.match_info["project_id"]) project = Controller.instance().get_project(request.match_info["project_id"])
vm = project.getVM(request.match_info["vm_id"]) node = project.get_node(request.match_info["node_id"])
yield from vm.start() yield from node.start()
response.set_status(201) response.set_status(201)
response.json(vm) response.json(node)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vms/{vm_id}/stop", r"/projects/{project_id}/nodes/{node_id}/stop",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the VM" "node_id": "UUID for the node"
}, },
status_codes={ status_codes={
201: "Instance created", 201: "Instance created",
400: "Invalid request" 400: "Invalid request"
}, },
description="Start a VM instance", description="Start a node instance",
output=VM_OBJECT_SCHEMA) output=NODE_OBJECT_SCHEMA)
def stop(request, response): def stop(request, response):
project = Controller.instance().getProject(request.match_info["project_id"]) project = Controller.instance().get_project(request.match_info["project_id"])
vm = project.getVM(request.match_info["vm_id"]) node = project.get_node(request.match_info["node_id"])
yield from vm.stop() yield from node.stop()
response.set_status(201) response.set_status(201)
response.json(vm) response.json(node)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vms/{vm_id}/suspend", r"/projects/{project_id}/nodes/{node_id}/suspend",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the VM" "node_id": "UUID for the node"
}, },
status_codes={ status_codes={
201: "Instance created", 201: "Instance created",
400: "Invalid request" 400: "Invalid request"
}, },
description="Start a VM instance", description="Start a node instance",
output=VM_OBJECT_SCHEMA) output=NODE_OBJECT_SCHEMA)
def suspend(request, response): def suspend(request, response):
project = Controller.instance().getProject(request.match_info["project_id"]) project = Controller.instance().get_project(request.match_info["project_id"])
vm = project.getVM(request.match_info["vm_id"]) node = project.get_node(request.match_info["node_id"])
yield from vm.suspend() yield from node.suspend()
response.set_status(201) response.set_status(201)
response.json(vm) response.json(node)
@classmethod @classmethod
@Route.post( @Route.post(
r"/projects/{project_id}/vms/{vm_id}/reload", r"/projects/{project_id}/nodes/{node_id}/reload",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the VM" "node_id": "UUID for the node"
}, },
status_codes={ status_codes={
201: "Instance created", 201: "Instance created",
400: "Invalid request" 400: "Invalid request"
}, },
description="Reload a VM instance", description="Reload a node instance",
output=VM_OBJECT_SCHEMA) output=NODE_OBJECT_SCHEMA)
def reload(request, response): def reload(request, response):
project = Controller.instance().getProject(request.match_info["project_id"]) project = Controller.instance().get_project(request.match_info["project_id"])
vm = project.getVM(request.match_info["vm_id"]) node = project.get_node(request.match_info["node_id"])
yield from vm.reload() yield from node.reload()
response.set_status(201) response.set_status(201)
response.json(vm) response.json(node)
@classmethod @classmethod
@Route.delete( @Route.delete(
r"/projects/{project_id}/vms/{vm_id}", r"/projects/{project_id}/nodes/{node_id}",
parameters={ parameters={
"project_id": "UUID for the project", "project_id": "UUID for the project",
"vm_id": "UUID for the VM" "node_id": "UUID for the node"
}, },
status_codes={ status_codes={
201: "Instance deleted", 201: "Instance deleted",
400: "Invalid request" 400: "Invalid request"
}, },
description="Delete a VM instance") description="Delete a node instance")
def delete(request, response): def delete(request, response):
project = Controller.instance().getProject(request.match_info["project_id"]) project = Controller.instance().get_project(request.match_info["project_id"])
vm = project.getVM(request.match_info["vm_id"]) node = project.get_node(request.match_info["node_id"])
yield from vm.destroy() yield from node.destroy()
response.set_status(201) response.set_status(201)

View File

@ -75,7 +75,7 @@ class ProjectHandler:
}) })
def get(request, response): def get(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
response.json(project) response.json(project)
@classmethod @classmethod
@ -92,7 +92,7 @@ class ProjectHandler:
def commit(request, response): def commit(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
yield from project.commit() yield from project.commit()
response.set_status(204) response.set_status(204)
@ -110,7 +110,7 @@ class ProjectHandler:
def close(request, response): def close(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
yield from project.close() yield from project.close()
controller.removeProject(project) controller.removeProject(project)
response.set_status(204) response.set_status(204)
@ -129,7 +129,7 @@ class ProjectHandler:
def delete(request, response): def delete(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
yield from project.delete() yield from project.delete()
controller.removeProject(project) controller.removeProject(project)
response.set_status(204) response.set_status(204)
@ -148,7 +148,7 @@ class ProjectHandler:
def notification(request, response): def notification(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
response.content_type = "application/json" response.content_type = "application/json"
response.set_status(200) response.set_status(200)
@ -179,7 +179,7 @@ class ProjectHandler:
def notification_ws(request, response): def notification_ws(request, response):
controller = Controller.instance() controller = Controller.instance()
project = controller.getProject(request.match_info["project_id"]) project = controller.get_project(request.match_info["project_id"])
ws = aiohttp.web.WebSocketResponse() ws = aiohttp.web.WebSocketResponse()
yield from ws.prepare(request) yield from ws.prepare(request)

View File

@ -61,7 +61,7 @@ class IndexHandler:
def project(request, response): def project(request, response):
controller = Controller.instance() controller = Controller.instance()
response.template("project.html", response.template("project.html",
project=controller.getProject(request.match_info["project_id"])) project=controller.get_project(request.match_info["project_id"]))
@classmethod @classmethod
@Route.get( @Route.get(

View File

@ -21,7 +21,7 @@ DOCKER_CREATE_SCHEMA = {
"description": "Request validation to create a new Docker container", "description": "Request validation to create a new Docker container",
"type": "object", "type": "object",
"properties": { "properties": {
"vm_id": { "node_id": {
"description": "Docker VM instance identifier", "description": "Docker VM instance identifier",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
@ -158,7 +158,7 @@ DOCKER_OBJECT_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"vm_id": { "node_id": {
"description": "Docker container instance UUID", "description": "Docker container instance UUID",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
@ -235,7 +235,7 @@ DOCKER_OBJECT_SCHEMA = {
} }
}, },
"additionalProperties": False, "additionalProperties": False,
"required": ["vm_id", "project_id", "image", "container_id", "adapters", "aux", "console", "console_type", "console_resolution", "start_command", "environment", "vm_directory"] "required": ["node_id", "project_id", "image", "container_id", "adapters", "aux", "console", "console_type", "console_resolution", "start_command", "environment", "vm_directory"]
} }

View File

@ -21,8 +21,8 @@ VM_CREATE_SCHEMA = {
"description": "Request validation to create a new Dynamips VM instance", "description": "Request validation to create a new Dynamips VM instance",
"type": "object", "type": "object",
"properties": { "properties": {
"vm_id": { "node_id": {
"description": "Dynamips VM instance identifier", "description": "Node identifier",
"oneOf": [ "oneOf": [
{"type": "string", {"type": "string",
"minLength": 36, "minLength": 36,
@ -509,15 +509,15 @@ VM_OBJECT_SCHEMA = {
"description": "ID to use with Dynamips", "description": "ID to use with Dynamips",
"type": "integer" "type": "integer"
}, },
"vm_id": { "node_id": {
"description": "Dynamips router instance UUID", "description": "Node instance UUID",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
"maxLength": 36, "maxLength": 36,
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
}, },
"vm_directory": { "node_directory": {
"decription": "Path to the VM working directory", "decription": "Path to the node working directory",
"type": "string" "type": "string"
}, },
"project_id": { "project_id": {
@ -749,7 +749,7 @@ VM_OBJECT_SCHEMA = {
}, },
}, },
"additionalProperties": False, "additionalProperties": False,
"required": ["name", "vm_id", "project_id", "dynamips_id", "console", "console_type"] "required": ["name", "node_id", "project_id", "dynamips_id", "console", "console_type"]
} }
VM_CONFIGS_SCHEMA = { VM_CONFIGS_SCHEMA = {

View File

@ -26,7 +26,7 @@ IOU_CREATE_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"vm_id": { "node_id": {
"description": "IOU VM identifier", "description": "IOU VM identifier",
"oneOf": [ "oneOf": [
{"type": "string", {"type": "string",
@ -187,7 +187,7 @@ IOU_OBJECT_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"vm_id": { "node_id": {
"description": "IOU VM UUID", "description": "IOU VM UUID",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
@ -261,7 +261,7 @@ IOU_OBJECT_SCHEMA = {
} }
}, },
"additionalProperties": False, "additionalProperties": False,
"required": ["name", "vm_id", "console", "project_id", "path", "md5sum", "serial_adapters", "ethernet_adapters", "required": ["name", "node_id", "console", "project_id", "path", "md5sum", "serial_adapters", "ethernet_adapters",
"ram", "nvram", "l1_keepalives", "startup_config", "private_config", "use_default_iou_values", "ram", "nvram", "l1_keepalives", "startup_config", "private_config", "use_default_iou_values",
"command_line"] "command_line"]
} }

View File

@ -28,13 +28,13 @@ LINK_OBJECT_SCHEMA = {
"maxLength": 36, "maxLength": 36,
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
}, },
"vms": { "nodes": {
"description": "List of the VMS", "description": "List of the VMS",
"type": "array", "type": "array",
"items": { "items": {
"type": "object", "type": "object",
"properties": { "properties": {
"vm_id": { "node_id": {
"description": "VM identifier", "description": "VM identifier",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
@ -50,7 +50,7 @@ LINK_OBJECT_SCHEMA = {
"type": "integer" "type": "integer"
} }
}, },
"required": ["vm_id", "adapter_number", "port_number"], "required": ["node_id", "adapter_number", "port_number"],
"additionalProperties": False "additionalProperties": False
} }
}, },
@ -67,7 +67,7 @@ LINK_OBJECT_SCHEMA = {
"type": ["string", "null"] "type": ["string", "null"]
} }
}, },
"required": ["vms"], "required": ["nodes"],
"additionalProperties": False "additionalProperties": False
} }

View File

@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
VM_LIST_IMAGES_SCHEMA = { NODE_LIST_IMAGES_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"description": "List of disk images", "description": "List of disk images",
"type": "array", "type": "array",
@ -43,7 +43,7 @@ VM_LIST_IMAGES_SCHEMA = {
} }
VM_CAPTURE_SCHEMA = { NODE_CAPTURE_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"description": "Request validation to start a packet capture on a port", "description": "Request validation to start a packet capture on a port",
"type": "object", "type": "object",
@ -63,9 +63,9 @@ VM_CAPTURE_SCHEMA = {
} }
VM_OBJECT_SCHEMA = { NODE_OBJECT_SCHEMA = {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"description": "A VM object", "description": "A node object",
"type": "object", "type": "object",
"properties": { "properties": {
"compute_id": { "compute_id": {
@ -76,19 +76,19 @@ VM_OBJECT_SCHEMA = {
"description": "Project identifier", "description": "Project identifier",
"type": "string" "type": "string"
}, },
"vm_id": { "node_id": {
"description": "VM identifier", "description": "Node identifier",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
"maxLength": 36, "maxLength": 36,
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$" "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
}, },
"vm_type": { "node_type": {
"description": "Type of VM", "description": "Type of node",
"enum": ["docker", "dynamips", "vpcs", "virtualbox", "vmware", "iou", "qemu"] "enum": ["docker", "dynamips", "vpcs", "virtualbox", "vmware", "iou", "qemu"]
}, },
"name": { "name": {
"description": "VM name", "description": "Node name",
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
@ -108,8 +108,8 @@ VM_OBJECT_SCHEMA = {
} }
}, },
"additionalProperties": False, "additionalProperties": False,
"required": ["name", "vm_type", "compute_id"] "required": ["name", "node_type", "compute_id"]
} }
VM_UPDATE_SCHEMA = VM_OBJECT_SCHEMA NODE_UPDATE_SCHEMA = NODE_OBJECT_SCHEMA
del VM_UPDATE_SCHEMA["required"] del NODE_UPDATE_SCHEMA["required"]

View File

@ -23,7 +23,7 @@ QEMU_CREATE_SCHEMA = {
"description": "Request validation to create a new QEMU VM instance", "description": "Request validation to create a new QEMU VM instance",
"type": "object", "type": "object",
"properties": { "properties": {
"vm_id": { "node_id": {
"description": "QEMU VM identifier", "description": "QEMU VM identifier",
"oneOf": [ "oneOf": [
{"type": "string", {"type": "string",
@ -382,7 +382,7 @@ QEMU_OBJECT_SCHEMA = {
"description": "Request validation for a QEMU VM instance", "description": "Request validation for a QEMU VM instance",
"type": "object", "type": "object",
"properties": { "properties": {
"vm_id": { "node_id": {
"description": "QEMU VM uuid", "description": "QEMU VM uuid",
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
@ -564,7 +564,7 @@ QEMU_OBJECT_SCHEMA = {
} }
}, },
"additionalProperties": False, "additionalProperties": False,
"required": ["vm_id", "required": ["node_id",
"project_id", "project_id",
"name", "name",
"usage", "usage",

View File

@ -21,7 +21,7 @@ VBOX_CREATE_SCHEMA = {
"description": "Request validation to create a new VirtualBox VM instance", "description": "Request validation to create a new VirtualBox VM instance",
"type": "object", "type": "object",
"properties": { "properties": {
"vm_id": { "node_id": {
"description": "VirtualBox VM instance identifier", "description": "VirtualBox VM instance identifier",
"oneOf": [ "oneOf": [
{"type": "string", {"type": "string",
@ -158,7 +158,7 @@ VBOX_OBJECT_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"vm_id": { "node_id": {
"description": "VirtualBox VM instance UUID", "description": "VirtualBox VM instance UUID",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
@ -222,5 +222,5 @@ VBOX_OBJECT_SCHEMA = {
}, },
}, },
"additionalProperties": False, "additionalProperties": False,
"required": ["name", "vm_id", "project_id", "vm_directory"] "required": ["name", "node_id", "project_id", "vm_directory"]
} }

View File

@ -21,7 +21,7 @@ VMWARE_CREATE_SCHEMA = {
"description": "Request validation to create a new VMware VM instance", "description": "Request validation to create a new VMware VM instance",
"type": "object", "type": "object",
"properties": { "properties": {
"vm_id": { "node_id": {
"description": "VMware VM instance identifier", "description": "VMware VM instance identifier",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
@ -151,7 +151,7 @@ VMWARE_OBJECT_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"vm_id": { "node_id": {
"description": "VMware VM instance UUID", "description": "VMware VM instance UUID",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
@ -213,5 +213,5 @@ VMWARE_OBJECT_SCHEMA = {
}, },
}, },
"additionalProperties": False, "additionalProperties": False,
"required": ["name", "vm_id", "project_id"] "required": ["name", "node_id", "project_id"]
} }

View File

@ -26,7 +26,7 @@ VPCS_CREATE_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"vm_id": { "node_id": {
"description": "VPCS VM identifier", "description": "VPCS VM identifier",
"oneOf": [ "oneOf": [
{"type": "string", {"type": "string",
@ -97,7 +97,7 @@ VPCS_OBJECT_SCHEMA = {
"type": "string", "type": "string",
"minLength": 1, "minLength": 1,
}, },
"vm_id": { "node_id": {
"description": "VPCS VM UUID", "description": "VPCS VM UUID",
"type": "string", "type": "string",
"minLength": 36, "minLength": 36,
@ -143,5 +143,5 @@ VPCS_OBJECT_SCHEMA = {
} }
}, },
"additionalProperties": False, "additionalProperties": False,
"required": ["name", "vm_id", "status", "console", "console_type", "project_id", "startup_script_path", "command_line"] "required": ["name", "node_id", "status", "console", "console_type", "project_id", "startup_script_path", "command_line"]
} }

View File

@ -19,21 +19,21 @@ socket.onmessage = function (event) {
Compute status Compute status
</h1> </h1>
The purpose of this page is to help for GNS3 debug. This can be dropped The purpose of this page is to help for GNS3 debug. This can be dropped
in futur GNS3 versions. in future GNS3 versions.
<h2>Opened projects</h2> <h2>Opened projects</h2>
<table border="1"> <table border="1">
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>ID</td> <th>ID</td>
<th>VMs</th> <th>Nodes</th>
<th>Clients connected</th> <th>Clients connected</th>
</tr> </tr>
{% for project in project_manager.projects %} {% for project in project_manager.projects %}
<tr> <tr>
<td>{{project.name}}</td> <td>{{project.name}}</td>
<td>{{project.id}}</td> <td>{{project.id}}</td>
<td>{{project.vms|length}}</td> <td>{{project.nodes|length}}</td>
<td>{{project.listeners|length}}</td> <td>{{project.listeners|length}}</td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -12,14 +12,14 @@ in futur GNS3 versions.
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>ID</td> <th>ID</td>
<th>VMs</th> <th>Nodes</th>
<th>Links</th> <th>Links</th>
</tr> </tr>
{% for project in controller.projects.values() %} {% for project in controller.projects.values() %}
<tr> <tr>
<td><a href="/projects/{{project.id}}">{{project.name}}</a></td> <td><a href="/projects/{{project.id}}">{{project.name}}</a></td>
<td><a href="/projects/{{project.id}}">{{project.id}}</a></td> <td><a href="/projects/{{project.id}}">{{project.id}}</a></td>
<td>{{project.vms|length}}</td> <td>{{project.nodes|length}}</td>
<td>{{project.links|length}}</td> <td>{{project.links|length}}</td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -22,7 +22,7 @@ socket.onmessage = function (event) {
The purpose of this page is to help for GNS3 debug. This can be dropped The purpose of this page is to help for GNS3 debug. This can be dropped
in futur GNS3 versions. in futur GNS3 versions.
<h2>VMs</h2> <h2>Nodes</h2>
<table border="1"> <table border="1">
<tr> <tr>
<th>Name</th> <th>Name</th>
@ -30,12 +30,12 @@ in futur GNS3 versions.
<th>Compute</th> <th>Compute</th>
<th>Console</th> <th>Console</th>
</tr> </tr>
{% for vm in project.vms.values() %} {% for node in project.nodes.values() %}
<tr> <tr>
<td>{{vm.name}}</td> <td>{{node.name}}</td>
<td>{{vm.id}}</td> <td>{{node.id}}</td>
<td>{{vm.compute.id}}</td> <td>{{node.compute.id}}</td>
<td><a href="{{vm.console_type}}://{{vm.host}}:{{vm.console}}">Console</a> <td><a href="{{node.console_type}}://{{node.host}}:{{node.console}}">Console</a>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View File

@ -36,16 +36,16 @@ class TelnetServer(threading.Thread):
""" """
Mini Telnet Server. Mini Telnet Server.
:param vm_name: Virtual machine name :param node_name: node name
:param pipe_path: path to VM pipe (UNIX socket on Linux/UNIX, Named Pipe on Windows) :param pipe_path: path to node pipe (UNIX socket on Linux/UNIX, Named Pipe on Windows)
:param host: server host :param host: server host
:param port: server port :param port: server port
""" """
def __init__(self, vm_name, pipe_path, host, port): def __init__(self, node_name, pipe_path, host, port):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self._vm_name = vm_name self._node_name = node_name
self._pipe = pipe_path self._pipe = pipe_path
self._host = host self._host = host
self._port = port self._port = port
@ -101,7 +101,7 @@ class TelnetServer(threading.Thread):
return False return False
if not self._alive: if not self._alive:
log.info("Telnet server for {} is exiting".format(self._vm_name)) log.info("Telnet server for {} is exiting".format(self._node_name))
return True return True
for sock_fileno in rlist: for sock_fileno in rlist:
@ -117,7 +117,7 @@ class TelnetServer(threading.Thread):
log.error("could not accept new client: {}".format(e)) log.error("could not accept new client: {}".format(e))
continue continue
new_client = TelnetClient(self._vm_name, sock, host, port) new_client = TelnetClient(self._node_name, sock, host, port)
self._clients[sock.fileno()] = new_client self._clients[sock.fileno()] = new_client
if self._use_thread and not self._reader_thread: if self._use_thread and not self._reader_thread:
@ -258,13 +258,13 @@ class TelnetClient(object):
""" """
Represents a Telnet client connection. Represents a Telnet client connection.
:param vm_name: VM name :param node_name: Node name
:param sock: socket connection :param sock: socket connection
:param host: IP of the Telnet client :param host: IP of the Telnet client
:param port: port of the Telnet client :param port: port of the Telnet client
""" """
def __init__(self, vm_name, sock, host, port): def __init__(self, node_name, sock, host, port):
self._active = True self._active = True
self._sock = sock self._sock = sock
@ -276,7 +276,7 @@ class TelnetClient(object):
IAC, WILL, BINARY, IAC, WILL, BINARY,
IAC, DO, BINARY])) IAC, DO, BINARY]))
welcome_msg = "{} console is now available... Press RETURN to get started.\r\n".format(vm_name) welcome_msg = "{} console is now available... Press RETURN to get started.\r\n".format(node_name)
sock.send(welcome_msg.encode('utf-8')) sock.send(welcome_msg.encode('utf-8'))
def is_active(self): def is_active(self):

View File

@ -25,7 +25,7 @@ import traceback
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
from ..compute.vm_error import VMError from ..compute.node_error import NodeError
from ..controller.controller_error import ControllerError from ..controller.controller_error import ControllerError
from ..ubridge.ubridge_error import UbridgeError from ..ubridge.ubridge_error import UbridgeError
from .response import Response from .response import Response
@ -67,7 +67,7 @@ class Route(object):
_routes = [] _routes = []
_documentation = {} _documentation = {}
_vm_locks = {} _node_locks = {}
@classmethod @classmethod
def get(cls, path, *args, **kw): def get(cls, path, *args, **kw):
@ -197,8 +197,8 @@ class Route(object):
response = Response(request=request, route=route) response = Response(request=request, route=route)
response.set_status(409) response.set_status(409)
response.json({"message": str(e), "status": 409}) response.json({"message": str(e), "status": 409})
except (VMError, UbridgeError) as e: except (NodeError, UbridgeError) as e:
log.error("VM error detected: {type}".format(type=type(e)), exc_info=1) log.error("Node error detected: {type}".format(type=type(e)), exc_info=1)
response = Response(request=request, route=route) response = Response(request=request, route=route)
response.set_status(409) response.set_status(409)
response.json({"message": str(e), "status": 409}) response.json({"message": str(e), "status": 409})
@ -234,39 +234,39 @@ class Route(object):
return response return response
@asyncio.coroutine @asyncio.coroutine
def vm_concurrency(request): def node_concurrency(request):
""" """
To avoid strange effect we prevent concurrency To avoid strange effect we prevent concurrency
between the same instance of the vm between the same instance of the node
""" """
if "vm_id" in request.match_info or "device_id" in request.match_info: if "node_id" in request.match_info or "device_id" in request.match_info:
vm_id = request.match_info.get("vm_id") node_id = request.match_info.get("node_id")
if vm_id is None: if node_id is None:
vm_id = request.match_info["device_id"] node_id = request.match_info["device_id"]
if "compute" in request.path: if "compute" in request.path:
type = "compute" type = "compute"
else: else:
type = "controller" type = "controller"
lock_key = "{}:{}:{}".format(type, request.match_info["project_id"], vm_id) lock_key = "{}:{}:{}".format(type, request.match_info["project_id"], node_id)
cls._vm_locks.setdefault(lock_key, {"lock": asyncio.Lock(), "concurrency": 0}) cls._node_locks.setdefault(lock_key, {"lock": asyncio.Lock(), "concurrency": 0})
cls._vm_locks[lock_key]["concurrency"] += 1 cls._node_locks[lock_key]["concurrency"] += 1
with (yield from cls._vm_locks[lock_key]["lock"]): with (yield from cls._node_locks[lock_key]["lock"]):
response = yield from control_schema(request) response = yield from control_schema(request)
cls._vm_locks[lock_key]["concurrency"] -= 1 cls._node_locks[lock_key]["concurrency"] -= 1
# No more waiting requests, garbage collect the lock # No more waiting requests, garbage collect the lock
if cls._vm_locks[lock_key]["concurrency"] <= 0: if cls._node_locks[lock_key]["concurrency"] <= 0:
del cls._vm_locks[lock_key] del cls._node_locks[lock_key]
else: else:
response = yield from control_schema(request) response = yield from control_schema(request)
return response return response
cls._routes.append((method, route, vm_concurrency)) cls._routes.append((method, route, node_concurrency))
return vm_concurrency return node_concurrency
return register return register
@classmethod @classmethod

View File

@ -53,7 +53,7 @@ def test_json(vm, project):
'image': 'ubuntu', 'image': 'ubuntu',
'name': 'test', 'name': 'test',
'project_id': project.id, 'project_id': project.id,
'vm_id': vm.id, 'node_id': vm.id,
'adapters': 1, 'adapters': 1,
'console': vm.console, 'console': vm.console,
'console_type': 'telnet', 'console_type': 'telnet',

View File

@ -44,13 +44,13 @@ def test_get_application_id(loop, project, iou):
vm1_id = str(uuid.uuid4()) vm1_id = str(uuid.uuid4())
vm2_id = str(uuid.uuid4()) vm2_id = str(uuid.uuid4())
vm3_id = str(uuid.uuid4()) vm3_id = str(uuid.uuid4())
loop.run_until_complete(iou.create_vm("PC 1", project.id, vm1_id)) loop.run_until_complete(iou.create_node("PC 1", project.id, vm1_id))
loop.run_until_complete(iou.create_vm("PC 2", project.id, vm2_id)) loop.run_until_complete(iou.create_node("PC 2", project.id, vm2_id))
assert iou.get_application_id(vm1_id) == 1 assert iou.get_application_id(vm1_id) == 1
assert iou.get_application_id(vm1_id) == 1 assert iou.get_application_id(vm1_id) == 1
assert iou.get_application_id(vm2_id) == 2 assert iou.get_application_id(vm2_id) == 2
loop.run_until_complete(iou.delete_vm(vm1_id)) loop.run_until_complete(iou.delete_node(vm1_id))
loop.run_until_complete(iou.create_vm("PC 3", project.id, vm3_id)) loop.run_until_complete(iou.create_node("PC 3", project.id, vm3_id))
assert iou.get_application_id(vm3_id) == 1 assert iou.get_application_id(vm3_id) == 1
@ -60,9 +60,9 @@ def test_get_application_id_multiple_project(loop, iou):
vm3_id = str(uuid.uuid4()) vm3_id = str(uuid.uuid4())
project1 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4())) project1 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4()))
project2 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4())) project2 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4()))
loop.run_until_complete(iou.create_vm("PC 1", project1.id, vm1_id)) loop.run_until_complete(iou.create_node("PC 1", project1.id, vm1_id))
loop.run_until_complete(iou.create_vm("PC 2", project1.id, vm2_id)) loop.run_until_complete(iou.create_node("PC 2", project1.id, vm2_id))
loop.run_until_complete(iou.create_vm("PC 2", project2.id, vm3_id)) loop.run_until_complete(iou.create_node("PC 2", project2.id, vm3_id))
assert iou.get_application_id(vm1_id) == 1 assert iou.get_application_id(vm1_id) == 1
assert iou.get_application_id(vm2_id) == 2 assert iou.get_application_id(vm2_id) == 2
assert iou.get_application_id(vm3_id) == 3 assert iou.get_application_id(vm3_id) == 3
@ -71,9 +71,9 @@ def test_get_application_id_multiple_project(loop, iou):
def test_get_application_id_no_id_available(loop, project, iou): def test_get_application_id_no_id_available(loop, project, iou):
with pytest.raises(IOUError): with pytest.raises(IOUError):
for i in range(1, 513): for i in range(1, 513):
vm_id = str(uuid.uuid4()) node_id = str(uuid.uuid4())
loop.run_until_complete(iou.create_vm("PC {}".format(i), project.id, vm_id)) loop.run_until_complete(iou.create_node("PC {}".format(i), project.id, node_id))
assert iou.get_application_id(vm_id) == i assert iou.get_application_id(node_id) == i
def test_get_images_directory(iou, tmpdir): def test_get_images_directory(iou, tmpdir):

View File

@ -148,7 +148,7 @@ def test_termination_callback(vm, async_run):
async_run(queue.get(0)) #  Ping async_run(queue.get(0)) #  Ping
(action, event, kwargs) = async_run(queue.get(0)) (action, event, kwargs) = async_run(queue.get(0))
assert action == "vm.stopped" assert action == "node.stopped"
assert event == vm assert event == vm
@ -167,7 +167,7 @@ def test_termination_callback_error(vm, tmpdir, async_run):
async_run(queue.get(0)) #  Ping async_run(queue.get(0)) #  Ping
(action, event, kwargs) = queue.get_nowait() (action, event, kwargs) = queue.get_nowait()
assert action == "vm.stopped" assert action == "node.stopped"
assert event == vm assert event == vm
(action, event, kwargs) = queue.get_nowait() (action, event, kwargs) = queue.get_nowait()

View File

@ -0,0 +1,123 @@
# -*- 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/>.
import pytest
import aiohttp
import asyncio
import os
from tests.utils import asyncio_patch
from unittest.mock import patch, MagicMock
from gns3server.compute.vpcs.vpcs_vm import VPCSVM
from gns3server.compute.docker.docker_vm import DockerVM
from gns3server.compute.vpcs.vpcs_error import VPCSError
from gns3server.compute.node_error import NodeError
from gns3server.compute.vpcs import VPCS
@pytest.fixture(scope="module")
def manager(port_manager):
m = VPCS.instance()
m.port_manager = port_manager
return m
@pytest.fixture(scope="function")
def node(project, manager):
return VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
def test_temporary_directory(project, manager):
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
assert isinstance(node.temporary_directory, str)
def test_console(project, manager):
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
node.console = 5011
assert node.console == 5011
node.console = None
assert node.console is None
def test_change_console_port(node, port_manager):
port1 = port_manager.get_free_tcp_port(node.project)
port2 = port_manager.get_free_tcp_port(node.project)
port_manager.release_tcp_port(port1, node.project)
port_manager.release_tcp_port(port2, node.project)
node.console = port1
node.console = port2
assert node.console == port2
port_manager.reserve_tcp_port(port1, node.project)
def test_console_vnc_invalid(project, manager):
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
node.console_type = "vnc"
with pytest.raises(NodeError):
node.console = 2012
def test_close(node, loop, port_manager):
assert node.console is not None
aux = port_manager.get_free_tcp_port(node.project)
port_manager.release_tcp_port(aux, node.project)
node.aux = aux
port = node.console
assert loop.run_until_complete(asyncio.async(node.close()))
# Raise an exception if the port is not free
port_manager.reserve_tcp_port(port, node.project)
# Raise an exception if the port is not free
port_manager.reserve_tcp_port(aux, node.project)
assert node.console is None
assert node.aux is None
# Called twice closed should return False
assert loop.run_until_complete(asyncio.async(node.close())) is False
def test_aux(project, manager, port_manager):
aux = port_manager.get_free_tcp_port(project)
port_manager.release_tcp_port(aux, project)
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "ubuntu", aux=aux)
assert node.aux == aux
node.aux = None
assert node.aux is None
def test_allocate_aux(project, manager):
node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
assert node.aux is None
# Docker has an aux port by default
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "ubuntu")
assert node.aux is not None
def test_change_aux_port(node, port_manager):
port1 = port_manager.get_free_tcp_port(node.project)
port2 = port_manager.get_free_tcp_port(node.project)
port_manager.release_tcp_port(port1, node.project)
port_manager.release_tcp_port(port2, node.project)
node.aux = port1
node.aux = port2
assert node.aux == port2
port_manager.reserve_tcp_port(port1, node.project)

View File

@ -1,123 +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/>.
import pytest
import aiohttp
import asyncio
import os
from tests.utils import asyncio_patch
from unittest.mock import patch, MagicMock
from gns3server.compute.vpcs.vpcs_vm import VPCSVM
from gns3server.compute.docker.docker_vm import DockerVM
from gns3server.compute.vpcs.vpcs_error import VPCSError
from gns3server.compute.vm_error import VMError
from gns3server.compute.vpcs import VPCS
@pytest.fixture(scope="module")
def manager(port_manager):
m = VPCS.instance()
m.port_manager = port_manager
return m
@pytest.fixture(scope="function")
def vm(project, manager):
return VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
def test_temporary_directory(project, manager):
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
assert isinstance(vm.temporary_directory, str)
def test_console(project, manager):
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
vm.console = 5011
assert vm.console == 5011
vm.console = None
assert vm.console is None
def test_change_console_port(vm, port_manager):
port1 = port_manager.get_free_tcp_port(vm.project)
port2 = port_manager.get_free_tcp_port(vm.project)
port_manager.release_tcp_port(port1, vm.project)
port_manager.release_tcp_port(port2, vm.project)
vm.console = port1
vm.console = port2
assert vm.console == port2
port_manager.reserve_tcp_port(port1, vm.project)
def test_console_vnc_invalid(project, manager):
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
vm.console_type = "vnc"
with pytest.raises(VMError):
vm.console = 2012
def test_close(vm, loop, port_manager):
assert vm.console is not None
aux = port_manager.get_free_tcp_port(vm.project)
port_manager.release_tcp_port(aux, vm.project)
vm.aux = aux
port = vm.console
assert loop.run_until_complete(asyncio.async(vm.close()))
# Raise an exception if the port is not free
port_manager.reserve_tcp_port(port, vm.project)
# Raise an exception if the port is not free
port_manager.reserve_tcp_port(aux, vm.project)
assert vm.console is None
assert vm.aux is None
# Called twice closed should return False
assert loop.run_until_complete(asyncio.async(vm.close())) is False
def test_aux(project, manager, port_manager):
aux = port_manager.get_free_tcp_port(project)
port_manager.release_tcp_port(aux, project)
vm = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "ubuntu", aux=aux)
assert vm.aux == aux
vm.aux = None
assert vm.aux is None
def test_allocate_aux(project, manager):
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
assert vm.aux is None
# Docker has an aux port by default
vm = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "ubuntu")
assert vm.aux is not None
def test_change_aux_port(vm, port_manager):
port1 = port_manager.get_free_tcp_port(vm.project)
port2 = port_manager.get_free_tcp_port(vm.project)
port_manager.release_tcp_port(port1, vm.project)
port_manager.release_tcp_port(port2, vm.project)
vm.aux = port1
vm.aux = port2
assert vm.aux == port2
port_manager.reserve_tcp_port(port1, vm.project)

View File

@ -23,7 +23,7 @@ from unittest.mock import patch
from gns3server.compute.vpcs import VPCS from gns3server.compute.vpcs import VPCS
from gns3server.compute.qemu import Qemu from gns3server.compute.qemu import Qemu
from gns3server.compute.vm_error import VMError from gns3server.compute.node_error import NodeError
from gns3server.utils import force_unix_path from gns3server.utils import force_unix_path
@ -43,48 +43,48 @@ def qemu(port_manager):
return qemu return qemu
def test_create_vm_new_topology(loop, project, vpcs): def test_create_node_new_topology(loop, project, vpcs):
vm_id = str(uuid.uuid4()) node_id = str(uuid.uuid4())
vm = loop.run_until_complete(vpcs.create_vm("PC 1", project.id, vm_id)) node = loop.run_until_complete(vpcs.create_node("PC 1", project.id, node_id))
assert vm in project.vms assert node in project.nodes
def test_create_twice_same_vm_new_topology(loop, project, vpcs): def test_create_twice_same_node_new_topology(loop, project, vpcs):
project._vms = set() project._nodes = set()
vm_id = str(uuid.uuid4()) node_id = str(uuid.uuid4())
vm = loop.run_until_complete(vpcs.create_vm("PC 1", project.id, vm_id, console=2222)) node = loop.run_until_complete(vpcs.create_node("PC 1", project.id, node_id, console=2222))
assert vm in project.vms assert node in project.nodes
assert len(project.vms) == 1 assert len(project.nodes) == 1
vm = loop.run_until_complete(vpcs.create_vm("PC 2", project.id, vm_id, console=2222)) node = loop.run_until_complete(vpcs.create_node("PC 2", project.id, node_id, console=2222))
assert len(project.vms) == 1 assert len(project.nodes) == 1
def test_create_vm_new_topology_without_uuid(loop, project, vpcs): def test_create_node_new_topology_without_uuid(loop, project, vpcs):
vm = loop.run_until_complete(vpcs.create_vm("PC 1", project.id, None)) node = loop.run_until_complete(vpcs.create_node("PC 1", project.id, None))
assert vm in project.vms assert node in project.nodes
assert len(vm.id) == 36 assert len(node.id) == 36
def test_create_vm_old_topology(loop, project, tmpdir, vpcs): def test_create_node_old_topology(loop, project, tmpdir, vpcs):
with patch("gns3server.compute.project.Project.is_local", return_value=True): with patch("gns3server.compute.project.Project.is_local", return_value=True):
# Create an old topology directory # Create an old topology directory
project_dir = str(tmpdir / "testold") project_dir = str(tmpdir / "testold")
vm_dir = os.path.join(project_dir, "testold-files", "vpcs", "pc-1") node_dir = os.path.join(project_dir, "testold-files", "vpcs", "pc-1")
project.path = project_dir project.path = project_dir
project.name = "testold" project.name = "testold"
os.makedirs(vm_dir, exist_ok=True) os.makedirs(node_dir, exist_ok=True)
with open(os.path.join(vm_dir, "startup.vpc"), "w+") as f: with open(os.path.join(node_dir, "startup.vpc"), "w+") as f:
f.write("1") f.write("1")
vm_id = 1 node_id = 1
vm = loop.run_until_complete(vpcs.create_vm("PC 1", project.id, vm_id)) node = loop.run_until_complete(vpcs.create_node("PC 1", project.id, node_id))
assert len(vm.id) == 36 assert len(node.id) == 36
assert os.path.exists(os.path.join(project_dir, "testold-files")) is False assert os.path.exists(os.path.join(project_dir, "testold-files")) is False
vm_dir = os.path.join(project_dir, "project-files", "vpcs", vm.id) node_dir = os.path.join(project_dir, "project-files", "vpcs", node.id)
with open(os.path.join(vm_dir, "startup.vpc")) as f: with open(os.path.join(node_dir, "startup.vpc")) as f:
assert f.read() == "1" assert f.read() == "1"
@ -116,9 +116,9 @@ def test_get_abs_image_path_non_local(qemu, tmpdir):
# If non local we can't use path outside images directory # If non local we can't use path outside images directory
with patch("gns3server.config.Config.get_section_config", return_value={"images_path": str(tmpdir / "images"), "local": False}): with patch("gns3server.config.Config.get_section_config", return_value={"images_path": str(tmpdir / "images"), "local": False}):
assert qemu.get_abs_image_path(path1) == path1 assert qemu.get_abs_image_path(path1) == path1
with pytest.raises(VMError): with pytest.raises(NodeError):
qemu.get_abs_image_path(path2) qemu.get_abs_image_path(path2)
with pytest.raises(VMError): with pytest.raises(NodeError):
qemu.get_abs_image_path("C:\\test2.bin") qemu.get_abs_image_path("C:\\test2.bin")
with patch("gns3server.config.Config.get_section_config", return_value={"images_path": str(tmpdir / "images"), "local": True}): with patch("gns3server.config.Config.get_section_config", return_value={"images_path": str(tmpdir / "images"), "local": True}):

View File

@ -41,9 +41,9 @@ def manager(port_manager):
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def vm(project, manager, loop): def node(project, manager, loop):
vm = manager.create_vm("test", project.id, "00010203-0405-0607-0809-0a0b0c0d0e0f") node = manager.create_node("test", project.id, "00010203-0405-0607-0809-0a0b0c0d0e0f")
return loop.run_until_complete(asyncio.async(vm)) return loop.run_until_complete(asyncio.async(node))
def test_affect_uuid(): def test_affect_uuid():
@ -123,44 +123,44 @@ def test_json(tmpdir):
assert p.__json__() == {"name": p.name, "project_id": p.id, "temporary": False} assert p.__json__() == {"name": p.name, "project_id": p.id, "temporary": False}
def test_vm_working_directory(tmpdir, vm): def test_vm_working_directory(tmpdir, node):
directory = Config.instance().get_section_config("Server").get("project_directory") directory = Config.instance().get_section_config("Server").get("project_directory")
with patch("gns3server.compute.project.Project.is_local", return_value=True): with patch("gns3server.compute.project.Project.is_local", return_value=True):
p = Project(project_id=str(uuid4())) p = Project(project_id=str(uuid4()))
assert p.vm_working_directory(vm) == os.path.join(directory, p.id, 'project-files', vm.module_name, vm.id) assert p.node_working_directory(node) == os.path.join(directory, p.id, 'project-files', node.module_name, node.id)
assert os.path.exists(p.vm_working_directory(vm)) assert os.path.exists(p.node_working_directory(node))
def test_mark_vm_for_destruction(vm): def test_mark_node_for_destruction(node):
project = Project(project_id=str(uuid4())) project = Project(project_id=str(uuid4()))
project.add_vm(vm) project.add_node(node)
project.mark_vm_for_destruction(vm) project.mark_node_for_destruction(node)
assert len(project._vms_to_destroy) == 1 assert len(project._nodes_to_destroy) == 1
assert len(project.vms) == 0 assert len(project.nodes) == 0
def test_commit(manager, loop): def test_commit(manager, loop):
project = Project(project_id=str(uuid4())) project = Project(project_id=str(uuid4()))
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager) node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
project.add_vm(vm) project.add_node(node)
directory = project.vm_working_directory(vm) directory = project.node_working_directory(node)
project.mark_vm_for_destruction(vm) project.mark_node_for_destruction(node)
assert len(project._vms_to_destroy) == 1 assert len(project._nodes_to_destroy) == 1
assert os.path.exists(directory) assert os.path.exists(directory)
loop.run_until_complete(asyncio.async(project.commit())) loop.run_until_complete(asyncio.async(project.commit()))
assert len(project._vms_to_destroy) == 0 assert len(project._nodes_to_destroy) == 0
assert os.path.exists(directory) is False assert os.path.exists(directory) is False
assert len(project.vms) == 0 assert len(project.nodes) == 0
def test_commit_permission_issue(manager, loop): def test_commit_permission_issue(manager, loop):
project = Project(project_id=str(uuid4())) project = Project(project_id=str(uuid4()))
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager) node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
project.add_vm(vm) project.add_node(node)
directory = project.vm_working_directory(vm) directory = project.node_working_directory(node)
project.mark_vm_for_destruction(vm) project.mark_node_for_destruction(node)
assert len(project._vms_to_destroy) == 1 assert len(project._nodes_to_destroy) == 1
assert os.path.exists(directory) assert os.path.exists(directory)
os.chmod(directory, 0) os.chmod(directory, 0)
with pytest.raises(aiohttp.web.HTTPInternalServerError): with pytest.raises(aiohttp.web.HTTPInternalServerError):
@ -188,17 +188,17 @@ def test_project_delete_permission_issue(loop):
def test_project_add_vm(manager): def test_project_add_vm(manager):
project = Project(project_id=str(uuid4())) project = Project(project_id=str(uuid4()))
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager) node = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
project.add_vm(vm) project.add_node(node)
assert len(project.vms) == 1 assert len(project.nodes) == 1
def test_project_close(loop, vm, project): def test_project_close(loop, node, project):
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.close") as mock: with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.close") as mock:
loop.run_until_complete(asyncio.async(project.close())) loop.run_until_complete(asyncio.async(project.close()))
assert mock.called assert mock.called
assert vm.id not in vm.manager._vms assert node.id not in node.manager._nodes
def test_project_close_temporary_project(loop, manager): def test_project_close_temporary_project(loop, manager):

View File

@ -33,13 +33,13 @@ def test_get_mac_id(loop, project, port_manager):
vm1_id = str(uuid.uuid4()) vm1_id = str(uuid.uuid4())
vm2_id = str(uuid.uuid4()) vm2_id = str(uuid.uuid4())
vm3_id = str(uuid.uuid4()) vm3_id = str(uuid.uuid4())
loop.run_until_complete(vpcs.create_vm("PC 1", project.id, vm1_id)) loop.run_until_complete(vpcs.create_node("PC 1", project.id, vm1_id))
loop.run_until_complete(vpcs.create_vm("PC 2", project.id, vm2_id)) loop.run_until_complete(vpcs.create_node("PC 2", project.id, vm2_id))
assert vpcs.get_mac_id(vm1_id) == 0 assert vpcs.get_mac_id(vm1_id) == 0
assert vpcs.get_mac_id(vm1_id) == 0 assert vpcs.get_mac_id(vm1_id) == 0
assert vpcs.get_mac_id(vm2_id) == 1 assert vpcs.get_mac_id(vm2_id) == 1
loop.run_until_complete(vpcs.delete_vm(vm1_id)) loop.run_until_complete(vpcs.delete_node(vm1_id))
loop.run_until_complete(vpcs.create_vm("PC 3", project.id, vm3_id)) loop.run_until_complete(vpcs.create_node("PC 3", project.id, vm3_id))
assert vpcs.get_mac_id(vm3_id) == 0 assert vpcs.get_mac_id(vm3_id) == 0
@ -53,9 +53,9 @@ def test_get_mac_id_multiple_project(loop, port_manager):
vm3_id = str(uuid.uuid4()) vm3_id = str(uuid.uuid4())
project1 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4())) project1 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4()))
project2 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4())) project2 = ProjectManager.instance().create_project(project_id=str(uuid.uuid4()))
loop.run_until_complete(vpcs.create_vm("PC 1", project1.id, vm1_id)) loop.run_until_complete(vpcs.create_node("PC 1", project1.id, vm1_id))
loop.run_until_complete(vpcs.create_vm("PC 2", project1.id, vm2_id)) loop.run_until_complete(vpcs.create_node("PC 2", project1.id, vm2_id))
loop.run_until_complete(vpcs.create_vm("PC 2", project2.id, vm3_id)) loop.run_until_complete(vpcs.create_node("PC 2", project2.id, vm3_id))
assert vpcs.get_mac_id(vm1_id) == 0 assert vpcs.get_mac_id(vm1_id) == 0
assert vpcs.get_mac_id(vm2_id) == 1 assert vpcs.get_mac_id(vm2_id) == 1
assert vpcs.get_mac_id(vm3_id) == 0 assert vpcs.get_mac_id(vm3_id) == 0
@ -68,6 +68,6 @@ def test_get_mac_id_no_id_available(loop, project, port_manager):
vpcs.port_manager = port_manager vpcs.port_manager = port_manager
with pytest.raises(VPCSError): with pytest.raises(VPCSError):
for i in range(0, 256): for i in range(0, 256):
vm_id = str(uuid.uuid4()) node_id = str(uuid.uuid4())
loop.run_until_complete(vpcs.create_vm("PC {}".format(i), project.id, vm_id)) loop.run_until_complete(vpcs.create_node("PC {}".format(i), project.id, node_id))
assert vpcs.get_mac_id(vm_id) == i assert vpcs.get_mac_id(node_id) == i

View File

@ -112,7 +112,7 @@ def test_start(loop, vm, async_run):
assert vm.is_running() assert vm.is_running()
assert vm.command_line == ' '.join(mock_exec.call_args[0]) assert vm.command_line == ' '.join(mock_exec.call_args[0])
(action, event, kwargs) = async_run(queue.get(0)) (action, event, kwargs) = async_run(queue.get(0))
assert action == "vm.started" assert action == "node.started"
assert event == vm assert event == vm
@ -177,7 +177,7 @@ def test_stop(loop, vm, async_run):
async_run(queue.get(0)) #  Started async_run(queue.get(0)) #  Started
(action, event, kwargs) = async_run(queue.get(0)) (action, event, kwargs) = async_run(queue.get(0))
assert action == "vm.stopped" assert action == "node.stopped"
assert event == vm assert event == vm

View File

@ -75,16 +75,16 @@ def test_isEnabled(controller):
def test_addCompute(controller, controller_config_path, async_run): def test_addCompute(controller, controller_config_path, async_run):
async_run(controller.addCompute("test1")) async_run(controller.add_compute("test1"))
assert len(controller.computes) == 1 assert len(controller.computes) == 1
async_run(controller.addCompute("test1")) async_run(controller.add_compute("test1"))
assert len(controller.computes) == 1 assert len(controller.computes) == 1
async_run(controller.addCompute("test2")) async_run(controller.add_compute("test2"))
assert len(controller.computes) == 2 assert len(controller.computes) == 2
def test_addComputeConfigFile(controller, controller_config_path, async_run): def test_addComputeConfigFile(controller, controller_config_path, async_run):
async_run(controller.addCompute("test1")) async_run(controller.add_compute("test1"))
assert len(controller.computes) == 1 assert len(controller.computes) == 1
with open(controller_config_path) as f: with open(controller_config_path) as f:
data = json.load(f) data = json.load(f)
@ -101,7 +101,7 @@ def test_addComputeConfigFile(controller, controller_config_path, async_run):
def test_getCompute(controller, async_run): def test_getCompute(controller, async_run):
compute = async_run(controller.addCompute("test1")) compute = async_run(controller.add_compute("test1"))
assert controller.getCompute("test1") == compute assert controller.getCompute("test1") == compute
with pytest.raises(aiohttp.web.HTTPNotFound): with pytest.raises(aiohttp.web.HTTPNotFound):
@ -145,9 +145,9 @@ def test_getProject(controller, async_run):
uuid1 = str(uuid.uuid4()) uuid1 = str(uuid.uuid4())
project = async_run(controller.addProject(project_id=uuid1)) project = async_run(controller.addProject(project_id=uuid1))
assert controller.getProject(uuid1) == project assert controller.get_project(uuid1) == project
with pytest.raises(aiohttp.web.HTTPNotFound): with pytest.raises(aiohttp.web.HTTPNotFound):
assert controller.getProject("dsdssd") assert controller.get_project("dsdssd")
def test_emit(controller, async_run): def test_emit(controller, async_run):

View File

@ -22,7 +22,7 @@ from unittest.mock import MagicMock
from gns3server.controller.link import Link from gns3server.controller.link import Link
from gns3server.controller.vm import VM from gns3server.controller.node import Node
from gns3server.controller.compute import Compute from gns3server.controller.compute import Compute
from gns3server.controller.project import Project from gns3server.controller.project import Project
@ -41,23 +41,23 @@ def compute():
@pytest.fixture @pytest.fixture
def link(async_run, project, compute): def link(async_run, project, compute):
vm1 = VM(project, compute) node1 = Node(project, compute)
vm2 = VM(project, compute) node2 = Node(project, compute)
link = Link(project) link = Link(project)
async_run(link.addVM(vm1, 0, 4)) async_run(link.add_node(node1, 0, 4))
async_run(link.addVM(vm2, 1, 3)) async_run(link.add_node(node2, 1, 3))
return link return link
def test_addVM(async_run, project, compute): def test_addNode(async_run, project, compute):
vm1 = VM(project, compute) node1 = Node(project, compute)
link = Link(project) link = Link(project)
async_run(link.addVM(vm1, 0, 4)) async_run(link.add_node(node1, 0, 4))
assert link._vms == [ assert link._nodes == [
{ {
"vm": vm1, "node": node1,
"adapter_number": 0, "adapter_number": 0,
"port_number": 4 "port_number": 4
} }
@ -65,22 +65,22 @@ def test_addVM(async_run, project, compute):
def test_json(async_run, project, compute): def test_json(async_run, project, compute):
vm1 = VM(project, compute) node1 = Node(project, compute)
vm2 = VM(project, compute) node2 = Node(project, compute)
link = Link(project) link = Link(project)
async_run(link.addVM(vm1, 0, 4)) async_run(link.add_node(node1, 0, 4))
async_run(link.addVM(vm2, 1, 3)) async_run(link.add_node(node2, 1, 3))
assert link.__json__() == { assert link.__json__() == {
"link_id": link.id, "link_id": link.id,
"vms": [ "nodes": [
{ {
"vm_id": vm1.id, "node_id": node1.id,
"adapter_number": 0, "adapter_number": 0,
"port_number": 4 "port_number": 4
}, },
{ {
"vm_id": vm2.id, "node_id": node2.id,
"adapter_number": 1, "adapter_number": 1,
"port_number": 3 "port_number": 3
} }
@ -109,10 +109,10 @@ def test_start_streaming_pcap(link, async_run, tmpdir, project):
def test_default_capture_file_name(project, compute, async_run): def test_default_capture_file_name(project, compute, async_run):
vm1 = VM(project, compute, name="Hello@") node1 = Node(project, compute, name="Hello@")
vm2 = VM(project, compute, name="w0.rld") node2 = Node(project, compute, name="w0.rld")
link = Link(project) link = Link(project)
async_run(link.addVM(vm1, 0, 4)) async_run(link.add_node(node1, 0, 4))
async_run(link.addVM(vm2, 1, 3)) async_run(link.add_node(node2, 1, 3))
assert link.default_capture_file_name() == "Hello_0-4_to_w0rld_1-3.pcap" assert link.default_capture_file_name() == "Hello_0-4_to_w0rld_1-3.pcap"

View File

@ -0,0 +1,171 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
import uuid
import asyncio
from unittest.mock import MagicMock
from tests.utils import AsyncioMagicMock
from gns3server.controller.node import Node
from gns3server.controller.project import Project
@pytest.fixture
def compute():
s = AsyncioMagicMock()
s.id = "http://test.com:42"
return s
@pytest.fixture
def node(compute):
project = Project(str(uuid.uuid4()))
node = Node(project, compute,
name="demo",
node_id=str(uuid.uuid4()),
node_type="vpcs",
console_type="vnc",
properties={"startup_script": "echo test"})
return node
def test_json(node, compute):
assert node.__json__() == {
"compute_id": compute.id,
"project_id": node.project.id,
"node_id": node.id,
"node_type": node.node_type,
"name": "demo",
"console": node.console,
"console_type": node.console_type,
"properties": node.properties
}
def test_init_without_uuid(project, compute):
node = Node(project, compute,
node_type="vpcs",
console_type="vnc")
assert node.id is not None
def test_create(node, compute, project, async_run):
node._console = 2048
response = MagicMock()
response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response)
async_run(node.create())
data = {
"console": 2048,
"console_type": "vnc",
"node_id": node.id,
"startup_script": "echo test",
"name": "demo"
}
compute.post.assert_called_with("/projects/{}/vpcs/nodes".format(node.project.id), data=data)
assert node._console == 2048
assert node._properties == {"startup_script": "echo test"}
def test_update(node, compute, project, async_run):
response = MagicMock()
response.json = {"console": 2048}
compute.put = AsyncioMagicMock(return_value=response)
async_run(node.update(console=2048, console_type="vnc", properties={"startup_script": "echo test"}, name="demo"))
data = {
"console": 2048,
"console_type": "vnc",
"startup_script": "echo test",
"name": "demo"
}
compute.put.assert_called_with("/projects/{}/vpcs/nodes/{}".format(node.project.id, node.id), data=data)
assert node._console == 2048
assert node._properties == {"startup_script": "echo test"}
def test_start(node, compute, project, async_run):
compute.post = AsyncioMagicMock()
async_run(node.start())
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/start".format(node.project.id, node.id))
def test_stop(node, compute, project, async_run):
compute.post = AsyncioMagicMock()
async_run(node.stop())
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/stop".format(node.project.id, node.id))
def test_suspend(node, compute, project, async_run):
compute.post = AsyncioMagicMock()
async_run(node.suspend())
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/suspend".format(node.project.id, node.id))
def test_reload(node, compute, project, async_run):
compute.post = AsyncioMagicMock()
async_run(node.reload())
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/reload".format(node.project.id, node.id))
def test_create_without_console(node, compute, project, async_run):
"""
None properties should be send. Because it can mean the emulator doesn"t support it
"""
response = MagicMock()
response.json = {"console": 2048, "test_value": "success"}
compute.post = AsyncioMagicMock(return_value=response)
async_run(node.create())
data = {
"console_type": "vnc",
"node_id": node.id,
"startup_script": "echo test",
"name": "demo"
}
compute.post.assert_called_with("/projects/{}/vpcs/nodes".format(node.project.id), data=data)
assert node._console == 2048
assert node._properties == {"test_value": "success", "startup_script": "echo test"}
def test_delete(node, compute, async_run):
async_run(node.destroy())
compute.delete.assert_called_with("/projects/{}/vpcs/nodes/{}".format(node.project.id, node.id))
def test_post(node, compute, async_run):
async_run(node.post("/test", {"a": "b"}))
compute.post.assert_called_with("/projects/{}/vpcs/nodes/{}/test".format(node.project.id, node.id), data={"a": "b"})
def test_delete(node, compute, async_run):
async_run(node.delete("/test"))
compute.delete.assert_called_with("/projects/{}/vpcs/nodes/{}/test".format(node.project.id, node.id))

View File

@ -77,10 +77,10 @@ def test_addVM(async_run):
response.json = {"console": 2048} response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response) compute.post = AsyncioMagicMock(return_value=response)
vm = async_run(project.addVM(compute, None, name="test", vm_type="vpcs", properties={"startup_config": "test.cfg"})) vm = async_run(project.add_node(compute, None, name="test", node_type="vpcs", properties={"startup_config": "test.cfg"}))
compute.post.assert_called_with('/projects/{}/vpcs/vms'.format(project.id), compute.post.assert_called_with('/projects/{}/vpcs/nodes'.format(project.id),
data={'vm_id': vm.id, data={'node_id': vm.id,
'console_type': 'telnet', 'console_type': 'telnet',
'startup_config': 'test.cfg', 'startup_config': 'test.cfg',
'name': 'test'}) 'name': 'test'})
@ -94,11 +94,11 @@ def test_getVM(async_run):
response.json = {"console": 2048} response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response) compute.post = AsyncioMagicMock(return_value=response)
vm = async_run(project.addVM(compute, None, name="test", vm_type="vpcs", properties={"startup_config": "test.cfg"})) vm = async_run(project.add_node(compute, None, name="test", node_type="vpcs", properties={"startup_config": "test.cfg"}))
assert project.getVM(vm.id) == vm assert project.get_node(vm.id) == vm
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound): with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
project.getVM("test") project.get_node("test")
def test_addLink(async_run): def test_addLink(async_run):
@ -109,12 +109,12 @@ def test_addLink(async_run):
response.json = {"console": 2048} response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response) compute.post = AsyncioMagicMock(return_value=response)
vm1 = async_run(project.addVM(compute, None, name="test1", vm_type="vpcs", properties={"startup_config": "test.cfg"})) vm1 = async_run(project.add_node(compute, None, name="test1", node_type="vpcs", properties={"startup_config": "test.cfg"}))
vm2 = async_run(project.addVM(compute, None, name="test2", vm_type="vpcs", properties={"startup_config": "test.cfg"})) vm2 = async_run(project.add_node(compute, None, name="test2", node_type="vpcs", properties={"startup_config": "test.cfg"}))
link = async_run(project.addLink()) link = async_run(project.add_link())
async_run(link.addVM(vm1, 3, 1)) async_run(link.add_node(vm1, 3, 1))
async_run(link.addVM(vm2, 4, 2)) async_run(link.add_node(vm2, 4, 2))
assert len(link._vms) == 2 assert len(link._nodes) == 2
def test_getLink(async_run): def test_getLink(async_run):
@ -125,11 +125,11 @@ def test_getLink(async_run):
response.json = {"console": 2048} response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response) compute.post = AsyncioMagicMock(return_value=response)
link = async_run(project.addLink()) link = async_run(project.add_link())
assert project.getLink(link.id) == link assert project.get_link(link.id) == link
with pytest.raises(aiohttp.web_exceptions.HTTPNotFound): with pytest.raises(aiohttp.web_exceptions.HTTPNotFound):
project.getLink("test") project.get_link("test")
def test_emit(async_run): def test_emit(async_run):

View File

@ -22,9 +22,8 @@ from unittest.mock import MagicMock
from tests.utils import asyncio_patch from tests.utils import asyncio_patch
from gns3server.controller.project import Project from gns3server.controller.project import Project
from gns3server.controller.compute import Compute
from gns3server.controller.udp_link import UDPLink from gns3server.controller.udp_link import UDPLink
from gns3server.controller.vm import VM from gns3server.controller.node import Node
@pytest.fixture @pytest.fixture
@ -36,12 +35,12 @@ def test_create(async_run, project):
compute1 = MagicMock() compute1 = MagicMock()
compute2 = MagicMock() compute2 = MagicMock()
vm1 = VM(project, compute1, vm_type="vpcs") node1 = Node(project, compute1, node_type="vpcs")
vm2 = VM(project, compute2, vm_type="vpcs") node2 = Node(project, compute2, node_type="vpcs")
link = UDPLink(project) link = UDPLink(project)
async_run(link.addVM(vm1, 0, 4)) async_run(link.add_node(node1, 0, 4))
async_run(link.addVM(vm2, 3, 1)) async_run(link.add_node(node2, 3, 1))
@asyncio.coroutine @asyncio.coroutine
def compute1_callback(path, data={}): def compute1_callback(path, data={}):
@ -69,13 +68,13 @@ def test_create(async_run, project):
compute2.host = "example.org" compute2.host = "example.org"
async_run(link.create()) async_run(link.create())
compute1.post.assert_any_call("/projects/{}/vpcs/vms/{}/adapters/0/ports/4/nio".format(project.id, vm1.id), data={ compute1.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id), data={
"lport": 1024, "lport": 1024,
"rhost": compute2.host, "rhost": compute2.host,
"rport": 2048, "rport": 2048,
"type": "nio_udp" "type": "nio_udp"
}) })
compute2.post.assert_any_call("/projects/{}/vpcs/vms/{}/adapters/3/ports/1/nio".format(project.id, vm2.id), data={ compute2.post.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id), data={
"lport": 2048, "lport": 2048,
"rhost": compute1.host, "rhost": compute1.host,
"rport": 1024, "rport": 1024,
@ -87,17 +86,17 @@ def test_delete(async_run, project):
compute1 = MagicMock() compute1 = MagicMock()
compute2 = MagicMock() compute2 = MagicMock()
vm1 = VM(project, compute1, vm_type="vpcs") node1 = Node(project, compute1, node_type="vpcs")
vm2 = VM(project, compute2, vm_type="vpcs") node2 = Node(project, compute2, node_type="vpcs")
link = UDPLink(project) link = UDPLink(project)
async_run(link.addVM(vm1, 0, 4)) async_run(link.add_node(node1, 0, 4))
async_run(link.addVM(vm2, 3, 1)) async_run(link.add_node(node2, 3, 1))
async_run(link.delete()) async_run(link.delete())
compute1.delete.assert_any_call("/projects/{}/vpcs/vms/{}/adapters/0/ports/4/nio".format(project.id, vm1.id)) compute1.delete.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/0/ports/4/nio".format(project.id, node1.id))
compute2.delete.assert_any_call("/projects/{}/vpcs/vms/{}/adapters/3/ports/1/nio".format(project.id, vm2.id)) compute2.delete.assert_any_call("/projects/{}/vpcs/nodes/{}/adapters/3/ports/1/nio".format(project.id, node2.id))
def test_choose_capture_side(async_run, project): def test_choose_capture_side(async_run, project):
@ -108,51 +107,51 @@ def test_choose_capture_side(async_run, project):
compute2 = MagicMock() compute2 = MagicMock()
compute2.id = "local" compute2.id = "local"
vm_vpcs = VM(project, compute1, vm_type="vpcs") node_vpcs = Node(project, compute1, node_type="vpcs")
vm_iou = VM(project, compute2, vm_type="iou") node_iou = Node(project, compute2, node_type="iou")
link = UDPLink(project) link = UDPLink(project)
async_run(link.addVM(vm_vpcs, 0, 4)) async_run(link.add_node(node_vpcs, 0, 4))
async_run(link.addVM(vm_iou, 3, 1)) async_run(link.add_node(node_iou, 3, 1))
assert link._choose_capture_side()["vm"] == vm_iou assert link._choose_capture_side()["node"] == node_iou
vm_vpcs = VM(project, compute1, vm_type="vpcs") node_vpcs = Node(project, compute1, node_type="vpcs")
vm_vpcs2 = VM(project, compute1, vm_type="vpcs") node_vpcs2 = Node(project, compute1, node_type="vpcs")
link = UDPLink(project) link = UDPLink(project)
async_run(link.addVM(vm_vpcs, 0, 4)) async_run(link.add_node(node_vpcs, 0, 4))
async_run(link.addVM(vm_vpcs2, 3, 1)) async_run(link.add_node(node_vpcs2, 3, 1))
# VPCS doesn't support capture # VPCS doesn't support capture
with pytest.raises(aiohttp.web.HTTPConflict): with pytest.raises(aiohttp.web.HTTPConflict):
link._choose_capture_side()["vm"] link._choose_capture_side()["node"]
# Capture should run on the local node # Capture should run on the local node
vm_iou = VM(project, compute1, vm_type="iou") node_iou = Node(project, compute1, node_type="iou")
vm_iou2 = VM(project, compute2, vm_type="iou") node_iou2 = Node(project, compute2, node_type="iou")
link = UDPLink(project) link = UDPLink(project)
async_run(link.addVM(vm_iou, 0, 4)) async_run(link.add_node(node_iou, 0, 4))
async_run(link.addVM(vm_iou2, 3, 1)) async_run(link.add_node(node_iou2, 3, 1))
assert link._choose_capture_side()["vm"] == vm_iou2 assert link._choose_capture_side()["node"] == node_iou2
def test_capture(async_run, project): def test_capture(async_run, project):
compute1 = MagicMock() compute1 = MagicMock()
vm_vpcs = VM(project, compute1, vm_type="vpcs", name="V1") node_vpcs = Node(project, compute1, node_type="vpcs", name="V1")
vm_iou = VM(project, compute1, vm_type="iou", name="I1") node_iou = Node(project, compute1, node_type="iou", name="I1")
link = UDPLink(project) link = UDPLink(project)
async_run(link.addVM(vm_vpcs, 0, 4)) async_run(link.add_node(node_vpcs, 0, 4))
async_run(link.addVM(vm_iou, 3, 1)) async_run(link.add_node(node_iou, 3, 1))
capture = async_run(link.start_capture()) capture = async_run(link.start_capture())
assert link.capturing assert link.capturing
compute1.post.assert_any_call("/projects/{}/iou/vms/{}/adapters/3/ports/1/start_capture".format(project.id, vm_iou.id), data={ compute1.post.assert_any_call("/projects/{}/iou/nodes/{}/adapters/3/ports/1/start_capture".format(project.id, node_iou.id), data={
"capture_file_name": link.default_capture_file_name(), "capture_file_name": link.default_capture_file_name(),
"data_link_type": "DLT_EN10MB" "data_link_type": "DLT_EN10MB"
}) })
@ -160,18 +159,18 @@ def test_capture(async_run, project):
capture = async_run(link.stop_capture()) capture = async_run(link.stop_capture())
assert link.capturing is False assert link.capturing is False
compute1.post.assert_any_call("/projects/{}/iou/vms/{}/adapters/3/ports/1/stop_capture".format(project.id, vm_iou.id)) compute1.post.assert_any_call("/projects/{}/iou/nodes/{}/adapters/3/ports/1/stop_capture".format(project.id, node_iou.id))
def test_read_pcap_from_source(project, async_run): def test_read_pcap_from_source(project, async_run):
compute1 = MagicMock() compute1 = MagicMock()
link = UDPLink(project) link = UDPLink(project)
async_run(link.addVM(compute1, 0, 4)) async_run(link.add_node(compute1, 0, 4))
async_run(link.addVM(compute1, 3, 1)) async_run(link.add_node(compute1, 3, 1))
capture = async_run(link.start_capture()) capture = async_run(link.start_capture())
assert link._capture_vm is not None assert link._capture_node is not None
async_run(link.read_pcap_from_source()) async_run(link.read_pcap_from_source())
link._capture_vm["vm"].compute.streamFile.assert_called_with(project, "tmp/captures/" + link._capture_file_name) link._capture_node["node"].compute.streamFile.assert_called_with(project, "tmp/captures/" + link._capture_file_name)

View File

@ -1,171 +0,0 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
import uuid
import asyncio
from unittest.mock import MagicMock
from tests.utils import AsyncioMagicMock
from gns3server.controller.vm import VM
from gns3server.controller.project import Project
@pytest.fixture
def compute():
s = AsyncioMagicMock()
s.id = "http://test.com:42"
return s
@pytest.fixture
def vm(compute):
project = Project(str(uuid.uuid4()))
vm = VM(project, compute,
name="demo",
vm_id=str(uuid.uuid4()),
vm_type="vpcs",
console_type="vnc",
properties={"startup_script": "echo test"})
return vm
def test_json(vm, compute):
assert vm.__json__() == {
"compute_id": compute.id,
"project_id": vm.project.id,
"vm_id": vm.id,
"vm_type": vm.vm_type,
"name": "demo",
"console": vm.console,
"console_type": vm.console_type,
"properties": vm.properties
}
def test_init_without_uuid(project, compute):
vm = VM(project, compute,
vm_type="vpcs",
console_type="vnc")
assert vm.id is not None
def test_create(vm, compute, project, async_run):
vm._console = 2048
response = MagicMock()
response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response)
async_run(vm.create())
data = {
"console": 2048,
"console_type": "vnc",
"vm_id": vm.id,
"startup_script": "echo test",
"name": "demo"
}
compute.post.assert_called_with("/projects/{}/vpcs/vms".format(vm.project.id), data=data)
assert vm._console == 2048
assert vm._properties == {"startup_script": "echo test"}
def test_update(vm, compute, project, async_run):
response = MagicMock()
response.json = {"console": 2048}
compute.put = AsyncioMagicMock(return_value=response)
async_run(vm.update(console=2048, console_type="vnc", properties={"startup_script": "echo test"}, name="demo"))
data = {
"console": 2048,
"console_type": "vnc",
"startup_script": "echo test",
"name": "demo"
}
compute.put.assert_called_with("/projects/{}/vpcs/vms/{}".format(vm.project.id, vm.id), data=data)
assert vm._console == 2048
assert vm._properties == {"startup_script": "echo test"}
def test_start(vm, compute, project, async_run):
compute.post = AsyncioMagicMock()
async_run(vm.start())
compute.post.assert_called_with("/projects/{}/vpcs/vms/{}/start".format(vm.project.id, vm.id))
def test_stop(vm, compute, project, async_run):
compute.post = AsyncioMagicMock()
async_run(vm.stop())
compute.post.assert_called_with("/projects/{}/vpcs/vms/{}/stop".format(vm.project.id, vm.id))
def test_suspend(vm, compute, project, async_run):
compute.post = AsyncioMagicMock()
async_run(vm.suspend())
compute.post.assert_called_with("/projects/{}/vpcs/vms/{}/suspend".format(vm.project.id, vm.id))
def test_reload(vm, compute, project, async_run):
compute.post = AsyncioMagicMock()
async_run(vm.reload())
compute.post.assert_called_with("/projects/{}/vpcs/vms/{}/reload".format(vm.project.id, vm.id))
def test_create_without_console(vm, compute, project, async_run):
"""
None properties should be send. Because it can mean the emulator doesn"t support it
"""
response = MagicMock()
response.json = {"console": 2048, "test_value": "success"}
compute.post = AsyncioMagicMock(return_value=response)
async_run(vm.create())
data = {
"console_type": "vnc",
"vm_id": vm.id,
"startup_script": "echo test",
"name": "demo"
}
compute.post.assert_called_with("/projects/{}/vpcs/vms".format(vm.project.id), data=data)
assert vm._console == 2048
assert vm._properties == {"test_value": "success", "startup_script": "echo test"}
def test_delete(vm, compute, async_run):
async_run(vm.destroy())
compute.delete.assert_called_with("/projects/{}/vpcs/vms/{}".format(vm.project.id, vm.id))
def test_post(vm, compute, async_run):
async_run(vm.post("/test", {"a": "b"}))
compute.post.assert_called_with("/projects/{}/vpcs/vms/{}/test".format(vm.project.id, vm.id), data={"a": "b"})
def test_delete(vm, compute, async_run):
async_run(vm.delete("/test"))
compute.delete.assert_called_with("/projects/{}/vpcs/vms/{}/test".format(vm.project.id, vm.id))

View File

@ -46,7 +46,7 @@ def mock_connection():
def vm(http_compute, project, base_params): def vm(http_compute, project, base_params):
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]) as mock_list: with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]) as mock_list:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}) as mock: with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}) as mock:
response = http_compute.post("/projects/{project_id}/docker/vms".format(project_id=project.id), base_params) response = http_compute.post("/projects/{project_id}/docker/nodes".format(project_id=project.id), base_params)
if response.status != 201: if response.status != 201:
print(response.body) print(response.body)
assert response.status == 201 assert response.status == 201
@ -56,9 +56,9 @@ def vm(http_compute, project, base_params):
def test_docker_create(http_compute, project, base_params): def test_docker_create(http_compute, project, base_params):
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]) as mock_list: with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]) as mock_list:
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}) as mock: with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}) as mock:
response = http_compute.post("/projects/{project_id}/docker/vms".format(project_id=project.id), base_params) response = http_compute.post("/projects/{project_id}/docker/nodes".format(project_id=project.id), base_params)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/docker/vms" assert response.route == "/projects/{project_id}/docker/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["container_id"] == "8bd8153ea8f5" assert response.json["container_id"] == "8bd8153ea8f5"
@ -70,63 +70,63 @@ def test_docker_create(http_compute, project, base_params):
def test_docker_start(http_compute, vm): def test_docker_start(http_compute, vm):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_docker_stop(http_compute, vm): def test_docker_stop(http_compute, vm):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop", return_value=True) as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_docker_reload(http_compute, vm): def test_docker_reload(http_compute, vm):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.restart", return_value=True) as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.restart", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_docker_delete(http_compute, vm): def test_docker_delete(http_compute, vm):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.delete", return_value=True) as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.delete", return_value=True) as mock:
response = http_compute.delete("/projects/{project_id}/docker/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.delete("/projects/{project_id}/docker/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_docker_reload(http_compute, vm): def test_docker_reload(http_compute, vm):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.pause", return_value=True) as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.pause", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_docker_nio_create_udp(http_compute, vm): def test_docker_nio_create_udp(http_compute, vm):
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp", response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}, "rhost": "127.0.0.1"},
example=True) example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/docker/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp" assert response.json["type"] == "nio_udp"
def test_docker_delete_nio(http_compute, vm): def test_docker_delete_nio(http_compute, vm):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_remove_nio_binding") as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_remove_nio_binding") as mock:
response = http_compute.delete("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.delete("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 204 assert response.status == 204
assert response.route == "/projects/{project_id}/docker/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/docker/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_docker_update(http_compute, vm, tmpdir, free_console_port): def test_docker_update(http_compute, vm, tmpdir, free_console_port):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.update") as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.update") as mock:
response = http_compute.put("/projects/{project_id}/docker/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test", response = http_compute.put("/projects/{project_id}/docker/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
"console": free_console_port, "console": free_console_port,
"start_command": "yes", "start_command": "yes",
"environment": "GNS3=1\nGNS4=0"}, "environment": "GNS3=1\nGNS4=0"},
example=True) example=True)
assert mock.called assert mock.called
assert response.status == 200 assert response.status == 200
@ -142,7 +142,7 @@ def test_docker_start_capture(http_compute, vm, tmpdir, project):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start_capture") as start_capture: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start_capture") as start_capture:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"} params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=params, example=True) response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
assert response.status == 200 assert response.status == 200
@ -156,7 +156,7 @@ def test_docker_start_capture_not_started(http_compute, vm, tmpdir):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start_capture") as start_capture: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start_capture") as start_capture:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"} params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=params) response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params)
assert not start_capture.called assert not start_capture.called
assert response.status == 409 assert response.status == 409
@ -167,7 +167,7 @@ def test_docker_stop_capture(http_compute, vm, tmpdir, project):
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True) as mock: with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True) as mock:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop_capture") as stop_capture: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop_capture") as stop_capture:
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 204 assert response.status == 204
@ -179,7 +179,7 @@ def test_docker_stop_capture_not_started(http_compute, vm, tmpdir):
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=False) as mock: with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=False) as mock:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop_capture") as stop_capture: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop_capture") as stop_capture:
response = http_compute.post("/projects/{project_id}/docker/vms/{vm_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.post("/projects/{project_id}/docker/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert not stop_capture.called assert not stop_capture.called
assert response.status == 409 assert response.status == 409

View File

@ -28,7 +28,7 @@ from tests.utils import asyncio_patch
# #
# dynamips_path = "/fake/dynamips" # dynamips_path = "/fake/dynamips"
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True) as mock:
# response = http_compute.post("/projects/{project_id}/dynamips/vms".format(project_id=project.id), {"name": "My router", # response = http_compute.post("/projects/{project_id}/dynamips/nodes".format(project_id=project.id), {"name": "My router",
# "platform": "c3745", # "platform": "c3745",
# "image": "somewhere", # "image": "somewhere",
# "ram": 128}) # "ram": 128})
@ -42,7 +42,7 @@ from tests.utils import asyncio_patch
# def test_dynamips_vm_create(http_compute, project): # def test_dynamips_vm_create(http_compute, project):
# #
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True): # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True):
# response = http_compute.post("/projects/{project_id}/dynamips/vms".format(project_id=project.id), {"name": "My router", # response = http_compute.post("/projects/{project_id}/dynamips/nodes".format(project_id=project.id), {"name": "My router",
# "platform": "c3745", # "platform": "c3745",
# "image": "somewhere", # "image": "somewhere",
# "ram": 128}, # "ram": 128},
@ -54,37 +54,37 @@ from tests.utils import asyncio_patch
# #
# #
# def test_dynamips_vm_get(http_compute, project, vm): # def test_dynamips_vm_get(http_compute, project, vm):
# response = http_compute.get("/projects/{project_id}/dynamips/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) # response = http_compute.get("/projects/{project_id}/dynamips/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
# assert response.status == 200 # assert response.status == 200
# assert response.route == "/projects/{project_id}/dynamips/vms/{vm_id}" # assert response.route == "/projects/{project_id}/dynamips/nodes/{node_id}"
# assert response.json["name"] == "My router" # assert response.json["name"] == "My router"
# assert response.json["project_id"] == project.id # assert response.json["project_id"] == project.id
# #
# #
# def test_dynamips_vm_start(http_compute, vm): # def test_dynamips_vm_start(http_compute, vm):
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.start", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.start", return_value=True) as mock:
# response = http_compute.post("/projects/{project_id}/dynamips/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) # response = http_compute.post("/projects/{project_id}/dynamips/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
# assert mock.called # assert mock.called
# assert response.status == 204 # assert response.status == 204
# #
# #
# def test_dynamips_vm_stop(http_compute, vm): # def test_dynamips_vm_stop(http_compute, vm):
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.stop", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.stop", return_value=True) as mock:
# response = http_compute.post("/projects/{project_id}/dynamips/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) # response = http_compute.post("/projects/{project_id}/dynamips/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
# assert mock.called # assert mock.called
# assert response.status == 204 # assert response.status == 204
# #
# #
# def test_dynamips_vm_suspend(http_compute, vm): # def test_dynamips_vm_suspend(http_compute, vm):
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.suspend", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.suspend", return_value=True) as mock:
# response = http_compute.post("/projects/{project_id}/dynamips/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) # response = http_compute.post("/projects/{project_id}/dynamips/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]))
# assert mock.called # assert mock.called
# assert response.status == 204 # assert response.status == 204
# #
# #
# def test_dynamips_vm_resume(http_compute, vm): # def test_dynamips_vm_resume(http_compute, vm):
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.resume", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.resume", return_value=True) as mock:
# response = http_compute.post("/projects/{project_id}/dynamips/vms/{vm_id}/resume".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) # response = http_compute.post("/projects/{project_id}/dynamips/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]))
# assert mock.called # assert mock.called
# assert response.status == 204 # assert response.status == 204
@ -92,8 +92,8 @@ from tests.utils import asyncio_patch
# def test_vbox_nio_create_udp(http_compute, vm): # def test_vbox_nio_create_udp(http_compute, vm):
# #
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock: # with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
# response = http_compute.post("/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/0/nio".format(project_id=vm["project_id"], # response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"],
# vm_id=vm["vm_id"]), {"type": "nio_udp", # node_id=vm["node_id"]), {"type": "nio_udp",
# "lport": 4242, # "lport": 4242,
# "rport": 4343, # "rport": 4343,
# "rhost": "127.0.0.1"}, # "rhost": "127.0.0.1"},
@ -104,25 +104,25 @@ from tests.utils import asyncio_patch
# assert args[0] == 0 # assert args[0] == 0
# #
# assert response.status == 201 # assert response.status == 201
# assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio" # assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_id:\d+}/nio"
# assert response.json["type"] == "nio_udp" # assert response.json["type"] == "nio_udp"
# #
# #
# def test_vbox_delete_nio(http_compute, vm): # def test_vbox_delete_nio(http_compute, vm):
# #
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock: # with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
# response = http_compute.delete("/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) # response = http_compute.delete("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
# #
# assert mock.called # assert mock.called
# args, kwgars = mock.call_args # args, kwgars = mock.call_args
# assert args[0] == 0 # assert args[0] == 0
# #
# assert response.status == 204 # assert response.status == 204
# assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_id:\d+}/nio" # assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_id:\d+}/nio"
# #
# #
# def test_vbox_update(http_compute, vm, free_console_port): # def test_vbox_update(http_compute, vm, free_console_port):
# response = http_compute.put("/projects/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test", # response = http_compute.put("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
# "console": free_console_port}) # "console": free_console_port})
# assert response.status == 200 # assert response.status == 200
# assert response.json["name"] == "test" # assert response.json["name"] == "test"
@ -154,14 +154,14 @@ def fake_file(tmpdir):
def test_vms(http_compute, tmpdir, fake_dynamips, fake_file): def test_vms(http_compute, tmpdir, fake_dynamips, fake_file):
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir), example=True): with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir), example=True):
response = http_compute.get("/dynamips/vms") response = http_compute.get("/dynamips/nodes")
assert response.status == 200 assert response.status == 200
assert response.json == [{"filename": "7200.bin", "path": "7200.bin"}] assert response.json == [{"filename": "7200.bin", "path": "7200.bin"}]
def test_upload_vm(http_compute, tmpdir): def test_upload_vm(http_compute, tmpdir):
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir),): with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir),):
response = http_compute.post("/dynamips/vms/test2", body="TEST", raw=True) response = http_compute.post("/dynamips/nodes/test2", body="TEST", raw=True)
assert response.status == 204 assert response.status == 204
with open(str(tmpdir / "test2")) as f: with open(str(tmpdir / "test2")) as f:
@ -178,5 +178,5 @@ def test_upload_vm_permission_denied(http_compute, tmpdir):
os.chmod(str(tmpdir / "test2.tmp"), 0) os.chmod(str(tmpdir / "test2.tmp"), 0)
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir),): with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir),):
response = http_compute.post("/dynamips/vms/test2", body="TEST", raw=True) response = http_compute.post("/dynamips/nodes/test2", body="TEST", raw=True)
assert response.status == 409 assert response.status == 409

View File

@ -47,21 +47,21 @@ def base_params(tmpdir, fake_iou_bin):
@pytest.fixture @pytest.fixture
def vm(http_compute, project, base_params): def vm(http_compute, project, base_params):
response = http_compute.post("/projects/{project_id}/iou/vms".format(project_id=project.id), base_params) response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), base_params)
assert response.status == 201 assert response.status == 201
return response.json return response.json
def startup_config_file(project, vm): def startup_config_file(project, vm):
directory = os.path.join(project.path, "project-files", "iou", vm["vm_id"]) directory = os.path.join(project.path, "project-files", "iou", vm["node_id"])
os.makedirs(directory, exist_ok=True) os.makedirs(directory, exist_ok=True)
return os.path.join(directory, "startup-config.cfg") return os.path.join(directory, "startup-config.cfg")
def test_iou_create(http_compute, project, base_params): def test_iou_create(http_compute, project, base_params):
response = http_compute.post("/projects/{project_id}/iou/vms".format(project_id=project.id), base_params) response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), base_params)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms" assert response.route == "/projects/{project_id}/iou/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["serial_adapters"] == 2 assert response.json["serial_adapters"] == 2
@ -82,9 +82,9 @@ def test_iou_create_with_params(http_compute, project, base_params):
params["use_default_iou_values"] = True params["use_default_iou_values"] = True
params["iourc_content"] = "test" params["iourc_content"] = "test"
response = http_compute.post("/projects/{project_id}/iou/vms".format(project_id=project.id), params, example=True) response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), params, example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms" assert response.route == "/projects/{project_id}/iou/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["serial_adapters"] == 4 assert response.json["serial_adapters"] == 4
@ -104,18 +104,18 @@ def test_iou_create_with_params(http_compute, project, base_params):
def test_iou_create_startup_config_already_exist(http_compute, project, base_params): def test_iou_create_startup_config_already_exist(http_compute, project, base_params):
"""We don't erase a startup-config if already exist at project creation""" """We don't erase a startup-config if already exist at project creation"""
vm_id = str(uuid.uuid4()) node_id = str(uuid.uuid4())
startup_config_file_path = startup_config_file(project, {'vm_id': vm_id}) startup_config_file_path = startup_config_file(project, {'node_id': node_id})
with open(startup_config_file_path, 'w+') as f: with open(startup_config_file_path, 'w+') as f:
f.write("echo hello") f.write("echo hello")
params = base_params params = base_params
params["vm_id"] = vm_id params["node_id"] = node_id
params["startup_config_content"] = "hostname test" params["startup_config_content"] = "hostname test"
response = http_compute.post("/projects/{project_id}/iou/vms".format(project_id=project.id), params, example=True) response = http_compute.post("/projects/{project_id}/iou/nodes".format(project_id=project.id), params, example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms" assert response.route == "/projects/{project_id}/iou/nodes"
assert "startup-config.cfg" in response.json["startup_config"] assert "startup-config.cfg" in response.json["startup_config"]
with open(startup_config_file(project, response.json)) as f: with open(startup_config_file(project, response.json)) as f:
@ -123,9 +123,9 @@ def test_iou_create_startup_config_already_exist(http_compute, project, base_par
def test_iou_get(http_compute, project, vm): def test_iou_get(http_compute, project, vm):
response = http_compute.get("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.get("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 200 assert response.status == 200
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}" assert response.route == "/projects/{project_id}/iou/nodes/{node_id}"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["serial_adapters"] == 2 assert response.json["serial_adapters"] == 2
@ -137,7 +137,7 @@ def test_iou_get(http_compute, project, vm):
def test_iou_start(http_compute, vm): def test_iou_start(http_compute, vm):
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status == 200 assert response.status == 200
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
@ -147,11 +147,11 @@ def test_iou_start_with_iourc(http_compute, vm, tmpdir):
body = {"iourc_content": "test"} body = {"iourc_content": "test"}
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=body, example=True) response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=body, example=True)
assert mock.called assert mock.called
assert response.status == 200 assert response.status == 200
response = http_compute.get("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.get("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert response.status == 200 assert response.status == 200
with open(response.json["iourc_path"]) as f: with open(response.json["iourc_path"]) as f:
assert f.read() == "test" assert f.read() == "test"
@ -159,21 +159,21 @@ def test_iou_start_with_iourc(http_compute, vm, tmpdir):
def test_iou_stop(http_compute, vm): def test_iou_stop(http_compute, vm):
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_iou_reload(http_compute, vm): def test_iou_reload(http_compute, vm):
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.reload", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.reload", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_iou_delete(http_compute, vm): def test_iou_delete(http_compute, vm):
with asyncio_patch("gns3server.compute.iou.IOU.delete_vm", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.IOU.delete_node", return_value=True) as mock:
response = http_compute.delete("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.delete("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
@ -191,7 +191,7 @@ def test_iou_update(http_compute, vm, tmpdir, free_console_port, project):
"use_default_iou_values": True, "use_default_iou_values": True,
"iourc_content": "test" "iourc_content": "test"
} }
response = http_compute.put("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), params, example=True) response = http_compute.put("/projects/{project_id}/iou/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params, example=True)
assert response.status == 200 assert response.status == 200
assert response.json["name"] == "test" assert response.json["name"] == "test"
assert response.json["console"] == free_console_port assert response.json["console"] == free_console_port
@ -209,55 +209,55 @@ def test_iou_update(http_compute, vm, tmpdir, free_console_port, project):
def test_iou_nio_create_udp(http_compute, vm): def test_iou_nio_create_udp(http_compute, vm):
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp", response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}, "rhost": "127.0.0.1"},
example=True) example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp" assert response.json["type"] == "nio_udp"
def test_iou_nio_create_ethernet(http_compute, vm, ethernet_device): def test_iou_nio_create_ethernet(http_compute, vm, ethernet_device):
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_generic_ethernet", response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_generic_ethernet",
"ethernet_device": ethernet_device, "ethernet_device": ethernet_device,
}, },
example=True) example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_generic_ethernet" assert response.json["type"] == "nio_generic_ethernet"
assert response.json["ethernet_device"] == ethernet_device assert response.json["ethernet_device"] == ethernet_device
def test_iou_nio_create_ethernet_different_port(http_compute, vm, ethernet_device): def test_iou_nio_create_ethernet_different_port(http_compute, vm, ethernet_device):
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/3/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_generic_ethernet", response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/3/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_generic_ethernet",
"ethernet_device": ethernet_device, "ethernet_device": ethernet_device,
}, },
example=False) example=False)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_generic_ethernet" assert response.json["type"] == "nio_generic_ethernet"
assert response.json["ethernet_device"] == ethernet_device assert response.json["ethernet_device"] == ethernet_device
def test_iou_nio_create_tap(http_compute, vm, ethernet_device): def test_iou_nio_create_tap(http_compute, vm, ethernet_device):
with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True): with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True):
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_tap", response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_tap",
"tap_device": ethernet_device}) "tap_device": ethernet_device})
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_tap" assert response.json["type"] == "nio_tap"
def test_iou_delete_nio(http_compute, vm): def test_iou_delete_nio(http_compute, vm):
http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp", http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}) "rhost": "127.0.0.1"})
response = http_compute.delete("/projects/{project_id}/iou/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.delete("/projects/{project_id}/iou/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 204 assert response.status == 204
assert response.route == "/projects/{project_id}/iou/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/iou/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_iou_start_capture(http_compute, vm, tmpdir, project): def test_iou_start_capture(http_compute, vm, tmpdir, project):
@ -266,7 +266,7 @@ def test_iou_start_capture(http_compute, vm, tmpdir, project):
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start_capture") as start_capture: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start_capture") as start_capture:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"} params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=params, example=True) response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params, example=True)
assert response.status == 200 assert response.status == 200
@ -280,7 +280,7 @@ def test_iou_start_capture_not_started(http_compute, vm, tmpdir):
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start_capture") as start_capture: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start_capture") as start_capture:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"} params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), body=params) response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/start_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), body=params)
assert not start_capture.called assert not start_capture.called
assert response.status == 409 assert response.status == 409
@ -291,7 +291,7 @@ def test_iou_stop_capture(http_compute, vm, tmpdir, project):
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True) as mock: with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True) as mock:
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop_capture") as stop_capture: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop_capture") as stop_capture:
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 204 assert response.status == 204
@ -303,7 +303,7 @@ def test_iou_stop_capture_not_started(http_compute, vm, tmpdir):
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=False) as mock: with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=False) as mock:
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop_capture") as stop_capture: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop_capture") as stop_capture:
response = http_compute.post("/projects/{project_id}/iou/vms/{vm_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], vm_id=vm["vm_id"])) response = http_compute.post("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/stop_capture".format(project_id=vm["project_id"], node_id=vm["node_id"]))
assert not stop_capture.called assert not stop_capture.called
assert response.status == 409 assert response.status == 409
@ -311,7 +311,7 @@ def test_iou_stop_capture_not_started(http_compute, vm, tmpdir):
def test_get_configs_without_configs_file(http_compute, vm): def test_get_configs_without_configs_file(http_compute, vm):
response = http_compute.get("/projects/{project_id}/iou/vms/{vm_id}/configs".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.get("/projects/{project_id}/iou/nodes/{node_id}/configs".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 200 assert response.status == 200
assert "startup_config" not in response.json assert "startup_config" not in response.json
assert "private_config" not in response.json assert "private_config" not in response.json
@ -323,7 +323,7 @@ def test_get_configs_with_startup_config_file(http_compute, project, vm):
with open(path, "w+") as f: with open(path, "w+") as f:
f.write("TEST") f.write("TEST")
response = http_compute.get("/projects/{project_id}/iou/vms/{vm_id}/configs".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.get("/projects/{project_id}/iou/nodes/{node_id}/configs".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 200 assert response.status == 200
assert response.json["startup_config_content"] == "TEST" assert response.json["startup_config_content"] == "TEST"
@ -331,14 +331,14 @@ def test_get_configs_with_startup_config_file(http_compute, project, vm):
def test_vms(http_compute, tmpdir, fake_iou_bin): def test_vms(http_compute, tmpdir, fake_iou_bin):
with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir)): with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir)):
response = http_compute.get("/iou/vms", example=True) response = http_compute.get("/iou/nodes", example=True)
assert response.status == 200 assert response.status == 200
assert response.json == [{"filename": "iou.bin", "path": "iou.bin"}] assert response.json == [{"filename": "iou.bin", "path": "iou.bin"}]
def test_upload_vm(http_compute, tmpdir): def test_upload_vm(http_compute, tmpdir):
with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir),): with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir),):
response = http_compute.post("/iou/vms/test2", body="TEST", raw=True) response = http_compute.post("/iou/nodes/test2", body="TEST", raw=True)
assert response.status == 204 assert response.status == 204
with open(str(tmpdir / "test2")) as f: with open(str(tmpdir / "test2")) as f:

View File

@ -58,15 +58,15 @@ def base_params(tmpdir, fake_qemu_bin):
@pytest.fixture @pytest.fixture
def vm(http_compute, project, base_params): def vm(http_compute, project, base_params):
response = http_compute.post("/projects/{project_id}/qemu/vms".format(project_id=project.id), base_params) response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), base_params)
assert response.status == 201 assert response.status == 201
return response.json return response.json
def test_qemu_create(http_compute, project, base_params, fake_qemu_bin): def test_qemu_create(http_compute, project, base_params, fake_qemu_bin):
response = http_compute.post("/projects/{project_id}/qemu/vms".format(project_id=project.id), base_params) response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), base_params)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/qemu/vms" assert response.route == "/projects/{project_id}/qemu/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["qemu_path"] == fake_qemu_bin assert response.json["qemu_path"] == fake_qemu_bin
@ -77,9 +77,9 @@ def test_qemu_create_platform(http_compute, project, base_params, fake_qemu_bin)
base_params["qemu_path"] = None base_params["qemu_path"] = None
base_params["platform"] = "x86_64" base_params["platform"] = "x86_64"
response = http_compute.post("/projects/{project_id}/qemu/vms".format(project_id=project.id), base_params) response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), base_params)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/qemu/vms" assert response.route == "/projects/{project_id}/qemu/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["qemu_path"] == fake_qemu_bin assert response.json["qemu_path"] == fake_qemu_bin
@ -91,10 +91,10 @@ def test_qemu_create_with_params(http_compute, project, base_params, fake_qemu_v
params["ram"] = 1024 params["ram"] = 1024
params["hda_disk_image"] = "linux载.img" params["hda_disk_image"] = "linux载.img"
response = http_compute.post("/projects/{project_id}/qemu/vms".format(project_id=project.id), params, example=True) response = http_compute.post("/projects/{project_id}/qemu/nodes".format(project_id=project.id), params, example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/qemu/vms" assert response.route == "/projects/{project_id}/qemu/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["ram"] == 1024 assert response.json["ram"] == 1024
@ -103,17 +103,17 @@ def test_qemu_create_with_params(http_compute, project, base_params, fake_qemu_v
def test_qemu_get(http_compute, project, vm): def test_qemu_get(http_compute, project, vm):
response = http_compute.get("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.get("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"],node_id=vm["node_id"]), example=True)
assert response.status == 200 assert response.status == 200
assert response.route == "/projects/{project_id}/qemu/vms/{vm_id}" assert response.route == "/projects/{project_id}/qemu/nodes/{node_id}"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["vm_directory"] == os.path.join(project.path, "project-files", "qemu", vm["vm_id"]) assert response.json["vm_directory"] == os.path.join(project.path, "project-files", "qemu", vm["node_id"])
def test_qemu_start(http_compute, vm): def test_qemu_start(http_compute, vm):
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.start", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/qemu/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 200 assert response.status == 200
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
@ -121,35 +121,35 @@ def test_qemu_start(http_compute, vm):
def test_qemu_stop(http_compute, vm): def test_qemu_stop(http_compute, vm):
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.stop", return_value=True) as mock: with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.stop", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/qemu/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_qemu_reload(http_compute, vm): def test_qemu_reload(http_compute, vm):
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.reload", return_value=True) as mock: with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.reload", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/qemu/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_qemu_suspend(http_compute, vm): def test_qemu_suspend(http_compute, vm):
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.suspend", return_value=True) as mock: with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.suspend", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/qemu/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_qemu_resume(http_compute, vm): def test_qemu_resume(http_compute, vm):
with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.resume", return_value=True) as mock: with asyncio_patch("gns3server.compute.qemu.qemu_vm.QemuVM.resume", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/qemu/vms/{vm_id}/resume".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_qemu_delete(http_compute, vm): def test_qemu_delete(http_compute, vm):
with asyncio_patch("gns3server.compute.qemu.Qemu.delete_vm", return_value=True) as mock: with asyncio_patch("gns3server.compute.qemu.Qemu.delete_node", return_value=True) as mock:
response = http_compute.delete("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.delete("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
@ -161,7 +161,7 @@ def test_qemu_update(http_compute, vm, tmpdir, free_console_port, project, fake_
"ram": 1024, "ram": 1024,
"hdb_disk_image": "linux.img" "hdb_disk_image": "linux.img"
} }
response = http_compute.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), params, example=True) response = http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), params, example=True)
assert response.status == 200 assert response.status == 200
assert response.json["name"] == "test" assert response.json["name"] == "test"
assert response.json["console"] == free_console_port assert response.json["console"] == free_console_port
@ -170,35 +170,35 @@ def test_qemu_update(http_compute, vm, tmpdir, free_console_port, project, fake_
def test_qemu_nio_create_udp(http_compute, vm): def test_qemu_nio_create_udp(http_compute, vm):
http_compute.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"adapters": 2}) http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
response = http_compute.post("/projects/{project_id}/qemu/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp", response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}, "rhost": "127.0.0.1"},
example=True) example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/qemu/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp" assert response.json["type"] == "nio_udp"
def test_qemu_nio_create_ethernet(http_compute, vm): def test_qemu_nio_create_ethernet(http_compute, vm):
http_compute.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"adapters": 2}) http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
response = http_compute.post("/projects/{project_id}/qemu/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_generic_ethernet", response = http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_generic_ethernet",
"ethernet_device": "eth0", "ethernet_device": "eth0",
}, },
example=True) example=True)
assert response.status == 409 assert response.status == 409
def test_qemu_delete_nio(http_compute, vm): def test_qemu_delete_nio(http_compute, vm):
http_compute.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"adapters": 2}) http_compute.put("/projects/{project_id}/qemu/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"adapters": 2})
http_compute.post("/projects/{project_id}/qemu/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp", http_compute.post("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}) "rhost": "127.0.0.1"})
response = http_compute.delete("/projects/{project_id}/qemu/vms/{vm_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.delete("/projects/{project_id}/qemu/nodes/{node_id}/adapters/1/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 204 assert response.status == 204
assert response.route == "/projects/{project_id}/qemu/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/qemu/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_qemu_list_binaries(http_compute, vm): def test_qemu_list_binaries(http_compute, vm):
@ -226,14 +226,14 @@ def test_qemu_list_binaries_filter(http_compute, vm):
def test_vms(http_compute, tmpdir, fake_qemu_vm): def test_vms(http_compute, tmpdir, fake_qemu_vm):
response = http_compute.get("/qemu/vms") response = http_compute.get("/qemu/nodes")
assert response.status == 200 assert response.status == 200
assert response.json == [{"filename": "linux载.img", "path": "linux载.img"}] assert response.json == [{"filename": "linux载.img", "path": "linux载.img"}]
def test_upload_vm(http_compute, tmpdir): def test_upload_vm(http_compute, tmpdir):
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),): with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),):
response = http_compute.post("/qemu/vms/test2", body="TEST", raw=True) response = http_compute.post("/qemu/nodes/test2", body="TEST", raw=True)
assert response.status == 204 assert response.status == 204
with open(str(tmpdir / "test2")) as f: with open(str(tmpdir / "test2")) as f:
@ -246,7 +246,7 @@ def test_upload_vm(http_compute, tmpdir):
def test_upload_vm_ova(http_compute, tmpdir): def test_upload_vm_ova(http_compute, tmpdir):
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),): with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),):
response = http_compute.post("/qemu/vms/test2.ova/test2.vmdk", body="TEST", raw=True) response = http_compute.post("/qemu/nodes/test2.ova/test2.vmdk", body="TEST", raw=True)
assert response.status == 204 assert response.status == 204
with open(str(tmpdir / "test2.ova" / "test2.vmdk")) as f: with open(str(tmpdir / "test2.ova" / "test2.vmdk")) as f:
@ -259,7 +259,7 @@ def test_upload_vm_ova(http_compute, tmpdir):
def test_upload_vm_forbiden_location(http_compute, tmpdir): def test_upload_vm_forbiden_location(http_compute, tmpdir):
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),): with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),):
response = http_compute.post("/qemu/vms/../../test2", body="TEST", raw=True) response = http_compute.post("/qemu/nodes/../../test2", body="TEST", raw=True)
assert response.status == 403 assert response.status == 403
@ -269,7 +269,7 @@ def test_upload_vm_permission_denied(http_compute, tmpdir):
os.chmod(str(tmpdir / "test2.tmp"), 0) os.chmod(str(tmpdir / "test2.tmp"), 0)
with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),): with patch("gns3server.compute.Qemu.get_images_directory", return_value=str(tmpdir),):
response = http_compute.post("/qemu/vms/test2", body="TEST", raw=True) response = http_compute.post("/qemu/nodes/test2", body="TEST", raw=True)
assert response.status == 409 assert response.status == 409

View File

@ -26,7 +26,7 @@ def vm(http_compute, project, monkeypatch):
vboxmanage_path = "/fake/VboxManage" vboxmanage_path = "/fake/VboxManage"
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True) as mock: with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/virtualbox/vms".format(project_id=project.id), {"name": "VMTEST", response = http_compute.post("/projects/{project_id}/virtualbox/nodes".format(project_id=project.id), {"name": "VMTEST",
"vmname": "VMTEST", "vmname": "VMTEST",
"linked_clone": False}) "linked_clone": False})
assert mock.called assert mock.called
@ -39,7 +39,7 @@ def vm(http_compute, project, monkeypatch):
def test_vbox_create(http_compute, project): def test_vbox_create(http_compute, project):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True): with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True):
response = http_compute.post("/projects/{project_id}/virtualbox/vms".format(project_id=project.id), {"name": "VM1", response = http_compute.post("/projects/{project_id}/virtualbox/nodes".format(project_id=project.id), {"name": "VM1",
"vmname": "VM1", "vmname": "VM1",
"linked_clone": False}, "linked_clone": False},
example=True) example=True)
@ -49,9 +49,9 @@ def test_vbox_create(http_compute, project):
def test_vbox_get(http_compute, project, vm): def test_vbox_get(http_compute, project, vm):
response = http_compute.get("/projects/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.get("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 200 assert response.status == 200
assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}" assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}"
assert response.json["name"] == "VMTEST" assert response.json["name"] == "VMTEST"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
@ -59,35 +59,35 @@ def test_vbox_get(http_compute, project, vm):
def test_vbox_start(http_compute, vm): def test_vbox_start(http_compute, vm):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.check_hw_virtualization", return_value=True) as mock: with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.check_hw_virtualization", return_value=True) as mock:
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/virtualbox/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_vbox_stop(http_compute, vm): def test_vbox_stop(http_compute, vm):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop", return_value=True) as mock: with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/virtualbox/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_vbox_suspend(http_compute, vm): def test_vbox_suspend(http_compute, vm):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.suspend", return_value=True) as mock: with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.suspend", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/virtualbox/vms/{vm_id}/suspend".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_vbox_resume(http_compute, vm): def test_vbox_resume(http_compute, vm):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.resume", return_value=True) as mock: with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.resume", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/virtualbox/vms/{vm_id}/resume".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_vbox_reload(http_compute, vm): def test_vbox_reload(http_compute, vm):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.reload", return_value=True) as mock: with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.reload", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/virtualbox/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
@ -95,11 +95,11 @@ def test_vbox_reload(http_compute, vm):
def test_vbox_nio_create_udp(http_compute, vm): def test_vbox_nio_create_udp(http_compute, vm):
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock: with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
response = http_compute.post("/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], response = http_compute.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"],
vm_id=vm["vm_id"]), {"type": "nio_udp", node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}, "rhost": "127.0.0.1"},
example=True) example=True)
assert mock.called assert mock.called
@ -107,26 +107,26 @@ def test_vbox_nio_create_udp(http_compute, vm):
assert args[0] == 0 assert args[0] == 0
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp" assert response.json["type"] == "nio_udp"
def test_vbox_delete_nio(http_compute, vm): def test_vbox_delete_nio(http_compute, vm):
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock: with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
response = http_compute.delete("/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.delete("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
args, kwgars = mock.call_args args, kwgars = mock.call_args
assert args[0] == 0 assert args[0] == 0
assert response.status == 204 assert response.status == 204
assert response.route == "/projects/{project_id}/virtualbox/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_vbox_update(http_compute, vm, free_console_port): def test_vbox_update(http_compute, vm, free_console_port):
response = http_compute.put("/projects/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test", response = http_compute.put("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
"console": free_console_port}, "console": free_console_port},
example=True) example=True)
assert response.status == 200 assert response.status == 200
assert response.json["name"] == "test" assert response.json["name"] == "test"

View File

@ -24,23 +24,23 @@ from unittest.mock import patch
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def vm(http_compute, project): def vm(http_compute, project):
response = http_compute.post("/projects/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1"}) response = http_compute.post("/projects/{project_id}/vpcs/nodes".format(project_id=project.id), {"name": "PC TEST 1"})
assert response.status == 201 assert response.status == 201
return response.json return response.json
def test_vpcs_create(http_compute, project): def test_vpcs_create(http_compute, project):
response = http_compute.post("/projects/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1"}, example=True) response = http_compute.post("/projects/{project_id}/vpcs/nodes".format(project_id=project.id), {"name": "PC TEST 1"}, example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms" assert response.route == "/projects/{project_id}/vpcs/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
def test_vpcs_get(http_compute, project, vm): def test_vpcs_get(http_compute, project, vm):
response = http_compute.get("/projects/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.get("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 200 assert response.status == 200
assert response.route == "/projects/{project_id}/vpcs/vms/{vm_id}" assert response.route == "/projects/{project_id}/vpcs/nodes/{node_id}"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["startup_script_path"] is None assert response.json["startup_script_path"] is None
@ -48,9 +48,9 @@ def test_vpcs_get(http_compute, project, vm):
def test_vpcs_create_startup_script(http_compute, project): def test_vpcs_create_startup_script(http_compute, project):
response = http_compute.post("/projects/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1", "startup_script": "ip 192.168.1.2\necho TEST"}) response = http_compute.post("/projects/{project_id}/vpcs/nodes".format(project_id=project.id), {"name": "PC TEST 1", "startup_script": "ip 192.168.1.2\necho TEST"})
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms" assert response.route == "/projects/{project_id}/vpcs/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["startup_script"] == os.linesep.join(["ip 192.168.1.2", "echo TEST"]) assert response.json["startup_script"] == os.linesep.join(["ip 192.168.1.2", "echo TEST"])
@ -58,49 +58,49 @@ def test_vpcs_create_startup_script(http_compute, project):
def test_vpcs_create_port(http_compute, project, free_console_port): def test_vpcs_create_port(http_compute, project, free_console_port):
response = http_compute.post("/projects/{project_id}/vpcs/vms".format(project_id=project.id), {"name": "PC TEST 1", "console": free_console_port}) response = http_compute.post("/projects/{project_id}/vpcs/nodes".format(project_id=project.id), {"name": "PC TEST 1", "console": free_console_port})
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms" assert response.route == "/projects/{project_id}/vpcs/nodes"
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
assert response.json["project_id"] == project.id assert response.json["project_id"] == project.id
assert response.json["console"] == free_console_port assert response.json["console"] == free_console_port
def test_vpcs_nio_create_udp(http_compute, vm): def test_vpcs_nio_create_udp(http_compute, vm):
response = http_compute.post("/projects/{project_id}/vpcs/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp", response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}, "rhost": "127.0.0.1"},
example=True) example=True)
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_udp" assert response.json["type"] == "nio_udp"
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows") @pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
def test_vpcs_nio_create_tap(http_compute, vm, ethernet_device): def test_vpcs_nio_create_tap(http_compute, vm, ethernet_device):
with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True): with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True):
response = http_compute.post("/projects/{project_id}/vpcs/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_tap", response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_tap",
"tap_device": ethernet_device}) "tap_device": ethernet_device})
assert response.status == 201 assert response.status == 201
assert response.route == "/projects/{project_id}/vpcs/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
assert response.json["type"] == "nio_tap" assert response.json["type"] == "nio_tap"
def test_vpcs_delete_nio(http_compute, vm): def test_vpcs_delete_nio(http_compute, vm):
http_compute.post("/projects/{project_id}/vpcs/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"type": "nio_udp", http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"}) "rhost": "127.0.0.1"})
response = http_compute.delete("/projects/{project_id}/vpcs/vms/{vm_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.delete("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert response.status == 204 assert response.status == 204
assert response.route == "/projects/{project_id}/vpcs/vms/{vm_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio" assert response.route == "/projects/{project_id}/vpcs/nodes/{node_id}/adapters/{adapter_number:\d+}/ports/{port_number:\d+}/nio"
def test_vpcs_start(http_compute, vm): def test_vpcs_start(http_compute, vm):
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/vpcs/vms/{vm_id}/start".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 200 assert response.status == 200
assert response.json["name"] == "PC TEST 1" assert response.json["name"] == "PC TEST 1"
@ -108,27 +108,27 @@ def test_vpcs_start(http_compute, vm):
def test_vpcs_stop(http_compute, vm): def test_vpcs_stop(http_compute, vm):
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop", return_value=True) as mock: with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/vpcs/vms/{vm_id}/stop".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_vpcs_reload(http_compute, vm): def test_vpcs_reload(http_compute, vm):
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.reload", return_value=True) as mock: with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.reload", return_value=True) as mock:
response = http_compute.post("/projects/{project_id}/vpcs/vms/{vm_id}/reload".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.post("/projects/{project_id}/vpcs/nodes/{node_id}/reload".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_vpcs_delete(http_compute, vm): def test_vpcs_delete(http_compute, vm):
with asyncio_patch("gns3server.compute.vpcs.VPCS.delete_vm", return_value=True) as mock: with asyncio_patch("gns3server.compute.vpcs.VPCS.delete_node", return_value=True) as mock:
response = http_compute.delete("/projects/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), example=True) response = http_compute.delete("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
assert mock.called assert mock.called
assert response.status == 204 assert response.status == 204
def test_vpcs_update(http_compute, vm, tmpdir, free_console_port): def test_vpcs_update(http_compute, vm, tmpdir, free_console_port):
response = http_compute.put("/projects/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test", response = http_compute.put("/projects/{project_id}/vpcs/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
"console": free_console_port, "console": free_console_port,
"startup_script": "ip 192.168.1.1"}, "startup_script": "ip 192.168.1.1"},
example=True) example=True)

View File

@ -31,7 +31,7 @@ from tests.utils import asyncio_patch, AsyncioMagicMock
from gns3server.handlers.api.controller.project_handler import ProjectHandler from gns3server.handlers.api.controller.project_handler import ProjectHandler
from gns3server.controller import Controller from gns3server.controller import Controller
from gns3server.controller.vm import VM from gns3server.controller.node import Node
from gns3server.controller.link import Link from gns3server.controller.link import Link
@ -53,19 +53,19 @@ def test_create_link(http_controller, tmpdir, project, compute, async_run):
response.json = {"console": 2048} response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response) compute.post = AsyncioMagicMock(return_value=response)
vm1 = async_run(project.addVM(compute, None)) node1 = async_run(project.add_node(compute, None))
vm2 = async_run(project.addVM(compute, None)) node2 = async_run(project.add_node(compute, None))
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock: with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = http_controller.post("/projects/{}/links".format(project.id), { response = http_controller.post("/projects/{}/links".format(project.id), {
"vms": [ "nodes": [
{ {
"vm_id": vm1.id, "node_id": node1.id,
"adapter_number": 0, "adapter_number": 0,
"port_number": 3 "port_number": 3
}, },
{ {
"vm_id": vm2.id, "node_id": node2.id,
"adapter_number": 2, "adapter_number": 2,
"port_number": 4 "port_number": 4
} }
@ -74,7 +74,7 @@ def test_create_link(http_controller, tmpdir, project, compute, async_run):
assert mock.called assert mock.called
assert response.status == 201 assert response.status == 201
assert response.json["link_id"] is not None assert response.json["link_id"] is not None
assert len(response.json["vms"]) == 2 assert len(response.json["nodes"]) == 2
def test_start_capture(http_controller, tmpdir, project, compute, async_run): def test_start_capture(http_controller, tmpdir, project, compute, async_run):

Some files were not shown because too many files have changed in this diff Show More