diff --git a/gns3server/modules/adapters/ethernet_adapter.py b/gns3server/modules/adapters/ethernet_adapter.py index d5b5373f..1f2c815e 100644 --- a/gns3server/modules/adapters/ethernet_adapter.py +++ b/gns3server/modules/adapters/ethernet_adapter.py @@ -25,7 +25,8 @@ class EthernetAdapter(Adapter): """ def __init__(self, interfaces=1): - Adapter.__init__(self, interfaces=interfaces) + + super().__init__(interfaces) def __str__(self): diff --git a/gns3server/modules/adapters/serial_adapter.py b/gns3server/modules/adapters/serial_adapter.py index 6a674c21..9305b4fd 100644 --- a/gns3server/modules/adapters/serial_adapter.py +++ b/gns3server/modules/adapters/serial_adapter.py @@ -25,7 +25,8 @@ class SerialAdapter(Adapter): """ def __init__(self, interfaces=1): - Adapter.__init__(self, interfaces=interfaces) + + super().__init__(interfaces) def __str__(self): diff --git a/gns3server/modules/base_manager.py b/gns3server/modules/base_manager.py index c41463a7..9238aaad 100644 --- a/gns3server/modules/base_manager.py +++ b/gns3server/modules/base_manager.py @@ -40,8 +40,8 @@ from .nios.nio_generic_ethernet import NIOGenericEthernet class BaseManager: """ - Base class for all Manager. - Responsible of management of a VM pool + Base class for all Manager classes. + Responsible of management of a VM pool of the same type. """ _convert_lock = None diff --git a/gns3server/modules/base_vm.py b/gns3server/modules/base_vm.py index 1dac9d02..ffea595e 100644 --- a/gns3server/modules/base_vm.py +++ b/gns3server/modules/base_vm.py @@ -54,19 +54,17 @@ class BaseVM: else: self._console = self._manager.port_manager.get_free_tcp_port(self._project) - log.debug("{module}: {name} [{id}] initialized. Console port {console}".format( - module=self.manager.module_name, - name=self.name, - id=self.id, - console=self._console - )) + log.debug("{module}: {name} [{id}] initialized. Console port {console}".format(module=self.manager.module_name, + name=self.name, + id=self.id, + console=self._console)) def __del__(self): self.close() if self._temporary_directory is not None: if os.path.exists(self._temporary_directory): - shutil.rmtree(self._temporary_directory) + shutil.rmtree(self._temporary_directory, ignore_errors=True) @property def project(self): @@ -195,7 +193,7 @@ class BaseVM: @console.setter def console(self, console): """ - Change console port + Changes the console port :params console: Console port (integer) """ @@ -205,8 +203,7 @@ class BaseVM: if self._console: self._manager.port_manager.release_tcp_port(self._console, self._project) self._console = self._manager.port_manager.reserve_tcp_port(console, self._project) - log.info("{module}: '{name}' [{id}]: console port set to {port}".format( - module=self.manager.module_name, - name=self.name, - id=self.id, - port=console)) + log.info("{module}: '{name}' [{id}]: console port set to {port}".format(module=self.manager.module_name, + name=self.name, + id=self.id, + port=console)) diff --git a/gns3server/modules/dynamips/adapters/c1700_mb_1fe.py b/gns3server/modules/dynamips/adapters/c1700_mb_1fe.py index c94f551d..4a77efb5 100644 --- a/gns3server/modules/dynamips/adapters/c1700_mb_1fe.py +++ b/gns3server/modules/dynamips/adapters/c1700_mb_1fe.py @@ -25,7 +25,8 @@ class C1700_MB_1FE(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1, wics=2) + + super().__init__(interfaces=1, wics=2) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/c1700_mb_wic1.py b/gns3server/modules/dynamips/adapters/c1700_mb_wic1.py index 9c6d2190..70a7149f 100644 --- a/gns3server/modules/dynamips/adapters/c1700_mb_wic1.py +++ b/gns3server/modules/dynamips/adapters/c1700_mb_wic1.py @@ -26,7 +26,8 @@ class C1700_MB_WIC1(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=0, wics=2) + + super().__init__(interfaces=0, wics=2) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/c2600_mb_1e.py b/gns3server/modules/dynamips/adapters/c2600_mb_1e.py index bebe7fa9..addb1f9b 100644 --- a/gns3server/modules/dynamips/adapters/c2600_mb_1e.py +++ b/gns3server/modules/dynamips/adapters/c2600_mb_1e.py @@ -25,7 +25,8 @@ class C2600_MB_1E(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1, wics=3) + + super().__init__(interfaces=1, wics=3) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/c2600_mb_1fe.py b/gns3server/modules/dynamips/adapters/c2600_mb_1fe.py index 1ad294f2..8f0f199d 100644 --- a/gns3server/modules/dynamips/adapters/c2600_mb_1fe.py +++ b/gns3server/modules/dynamips/adapters/c2600_mb_1fe.py @@ -25,7 +25,8 @@ class C2600_MB_1FE(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1, wics=3) + + super().__init__(interfaces=1, wics=3) self._interfaces = 1 def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/c2600_mb_2e.py b/gns3server/modules/dynamips/adapters/c2600_mb_2e.py index 1e42d5dd..78921c83 100644 --- a/gns3server/modules/dynamips/adapters/c2600_mb_2e.py +++ b/gns3server/modules/dynamips/adapters/c2600_mb_2e.py @@ -25,7 +25,8 @@ class C2600_MB_2E(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=2, wics=3) + + super().__init__(interfaces=2, wics=3) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/c2600_mb_2fe.py b/gns3server/modules/dynamips/adapters/c2600_mb_2fe.py index dcd96581..0ed67f5d 100644 --- a/gns3server/modules/dynamips/adapters/c2600_mb_2fe.py +++ b/gns3server/modules/dynamips/adapters/c2600_mb_2fe.py @@ -25,7 +25,8 @@ class C2600_MB_2FE(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=2, wics=3) + + super().__init__(interfaces=2, wics=3) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/c7200_io_2fe.py b/gns3server/modules/dynamips/adapters/c7200_io_2fe.py index 8b545e99..d250fe89 100644 --- a/gns3server/modules/dynamips/adapters/c7200_io_2fe.py +++ b/gns3server/modules/dynamips/adapters/c7200_io_2fe.py @@ -25,7 +25,8 @@ class C7200_IO_2FE(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=2) + + super().__init__(interfaces=2) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/c7200_io_fe.py b/gns3server/modules/dynamips/adapters/c7200_io_fe.py index 784b154d..230b0f6f 100644 --- a/gns3server/modules/dynamips/adapters/c7200_io_fe.py +++ b/gns3server/modules/dynamips/adapters/c7200_io_fe.py @@ -25,7 +25,8 @@ class C7200_IO_FE(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1) + + super().__init__(interfaces=1) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/c7200_io_ge_e.py b/gns3server/modules/dynamips/adapters/c7200_io_ge_e.py index f233dffd..42f975c3 100644 --- a/gns3server/modules/dynamips/adapters/c7200_io_ge_e.py +++ b/gns3server/modules/dynamips/adapters/c7200_io_ge_e.py @@ -25,7 +25,8 @@ class C7200_IO_GE_E(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1) + + super().__init__(interfaces=1) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/gt96100_fe.py b/gns3server/modules/dynamips/adapters/gt96100_fe.py index 35af37aa..5551ebcd 100644 --- a/gns3server/modules/dynamips/adapters/gt96100_fe.py +++ b/gns3server/modules/dynamips/adapters/gt96100_fe.py @@ -21,7 +21,8 @@ from .adapter import Adapter class GT96100_FE(Adapter): def __init__(self): - Adapter.__init__(self, interfaces=2, wics=3) + + super().__init__(interfaces=2, wics=3) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/leopard_2fe.py b/gns3server/modules/dynamips/adapters/leopard_2fe.py index db6ad9c2..a8e8ff5c 100644 --- a/gns3server/modules/dynamips/adapters/leopard_2fe.py +++ b/gns3server/modules/dynamips/adapters/leopard_2fe.py @@ -25,7 +25,8 @@ class Leopard_2FE(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=2) + + super().__init__(interfaces=2) self._interfaces = 2 def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/nm_16esw.py b/gns3server/modules/dynamips/adapters/nm_16esw.py index 31e74565..1cc01880 100644 --- a/gns3server/modules/dynamips/adapters/nm_16esw.py +++ b/gns3server/modules/dynamips/adapters/nm_16esw.py @@ -25,7 +25,8 @@ class NM_16ESW(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=16) + + super().__init__(interfaces=16) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/nm_1e.py b/gns3server/modules/dynamips/adapters/nm_1e.py index 59ac5569..4c29097e 100644 --- a/gns3server/modules/dynamips/adapters/nm_1e.py +++ b/gns3server/modules/dynamips/adapters/nm_1e.py @@ -25,7 +25,8 @@ class NM_1E(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1) + + super().__init__(interfaces=1) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/nm_1fe_tx.py b/gns3server/modules/dynamips/adapters/nm_1fe_tx.py index 26568306..2e734236 100644 --- a/gns3server/modules/dynamips/adapters/nm_1fe_tx.py +++ b/gns3server/modules/dynamips/adapters/nm_1fe_tx.py @@ -25,7 +25,8 @@ class NM_1FE_TX(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1) + + super().__init__(interfaces=1) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/nm_4e.py b/gns3server/modules/dynamips/adapters/nm_4e.py index 086b04ee..f13309ee 100644 --- a/gns3server/modules/dynamips/adapters/nm_4e.py +++ b/gns3server/modules/dynamips/adapters/nm_4e.py @@ -25,7 +25,8 @@ class NM_4E(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=4) + + super().__init__(interfaces=4) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/nm_4t.py b/gns3server/modules/dynamips/adapters/nm_4t.py index 77c3ecc8..02773ab0 100644 --- a/gns3server/modules/dynamips/adapters/nm_4t.py +++ b/gns3server/modules/dynamips/adapters/nm_4t.py @@ -25,7 +25,8 @@ class NM_4T(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=4) + + super().__init__(interfaces=4) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_2fe_tx.py b/gns3server/modules/dynamips/adapters/pa_2fe_tx.py index 09b677f3..9b914d76 100644 --- a/gns3server/modules/dynamips/adapters/pa_2fe_tx.py +++ b/gns3server/modules/dynamips/adapters/pa_2fe_tx.py @@ -25,7 +25,8 @@ class PA_2FE_TX(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=2) + + super().__init__(interfaces=2) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_4e.py b/gns3server/modules/dynamips/adapters/pa_4e.py index d5981860..f379d53d 100644 --- a/gns3server/modules/dynamips/adapters/pa_4e.py +++ b/gns3server/modules/dynamips/adapters/pa_4e.py @@ -25,7 +25,8 @@ class PA_4E(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=4) + + super().__init__(interfaces=4) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_4t.py b/gns3server/modules/dynamips/adapters/pa_4t.py index 5a1393bc..ddc14fcd 100644 --- a/gns3server/modules/dynamips/adapters/pa_4t.py +++ b/gns3server/modules/dynamips/adapters/pa_4t.py @@ -25,7 +25,8 @@ class PA_4T(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=4) + + super().__init__(interfaces=4) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_8e.py b/gns3server/modules/dynamips/adapters/pa_8e.py index 96684055..38311742 100644 --- a/gns3server/modules/dynamips/adapters/pa_8e.py +++ b/gns3server/modules/dynamips/adapters/pa_8e.py @@ -25,7 +25,8 @@ class PA_8E(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=8) + + super().__init__(interfaces=8) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_8t.py b/gns3server/modules/dynamips/adapters/pa_8t.py index 723e026f..8a48c145 100644 --- a/gns3server/modules/dynamips/adapters/pa_8t.py +++ b/gns3server/modules/dynamips/adapters/pa_8t.py @@ -25,7 +25,8 @@ class PA_8T(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=8) + + super().__init__(interfaces=8) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_a1.py b/gns3server/modules/dynamips/adapters/pa_a1.py index 469d9ce4..fe320de8 100644 --- a/gns3server/modules/dynamips/adapters/pa_a1.py +++ b/gns3server/modules/dynamips/adapters/pa_a1.py @@ -25,7 +25,8 @@ class PA_A1(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1) + + super().__init__(interfaces=1) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_fe_tx.py b/gns3server/modules/dynamips/adapters/pa_fe_tx.py index 6434d2b4..4a90536e 100644 --- a/gns3server/modules/dynamips/adapters/pa_fe_tx.py +++ b/gns3server/modules/dynamips/adapters/pa_fe_tx.py @@ -25,7 +25,8 @@ class PA_FE_TX(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1) + + super().__init__(interfaces=1) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_ge.py b/gns3server/modules/dynamips/adapters/pa_ge.py index e466d905..d1c330e4 100644 --- a/gns3server/modules/dynamips/adapters/pa_ge.py +++ b/gns3server/modules/dynamips/adapters/pa_ge.py @@ -25,7 +25,8 @@ class PA_GE(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1) + + super().__init__(interfaces=1) def __str__(self): diff --git a/gns3server/modules/dynamips/adapters/pa_pos_oc3.py b/gns3server/modules/dynamips/adapters/pa_pos_oc3.py index de0bc5d1..bfd35df3 100644 --- a/gns3server/modules/dynamips/adapters/pa_pos_oc3.py +++ b/gns3server/modules/dynamips/adapters/pa_pos_oc3.py @@ -25,7 +25,8 @@ class PA_POS_OC3(Adapter): """ def __init__(self): - Adapter.__init__(self, interfaces=1) + + super().__init__(interfaces=1) def __str__(self): diff --git a/gns3server/modules/dynamips/dynamips_error.py b/gns3server/modules/dynamips/dynamips_error.py index 265b22e6..be33428e 100644 --- a/gns3server/modules/dynamips/dynamips_error.py +++ b/gns3server/modules/dynamips/dynamips_error.py @@ -16,7 +16,7 @@ # along with this program. If not, see . """ -Custom exceptions for Dynamips module. +Custom exceptions for the Dynamips module. """ from ..vm_error import VMError diff --git a/gns3server/modules/dynamips/hypervisor.py b/gns3server/modules/dynamips/hypervisor.py index ce1b4ade..407072ca 100644 --- a/gns3server/modules/dynamips/hypervisor.py +++ b/gns3server/modules/dynamips/hypervisor.py @@ -47,7 +47,7 @@ class Hypervisor(DynamipsHypervisor): def __init__(self, path, working_dir, host, port, console_host): - DynamipsHypervisor.__init__(self, working_dir, host, port) + super().__init__(working_dir, host, port) # create an unique ID self._id = Hypervisor._instance_count diff --git a/gns3server/modules/dynamips/nios/nio_fifo.py b/gns3server/modules/dynamips/nios/nio_fifo.py index fd10e40f..f1d763fc 100644 --- a/gns3server/modules/dynamips/nios/nio_fifo.py +++ b/gns3server/modules/dynamips/nios/nio_fifo.py @@ -42,7 +42,7 @@ class NIOFIFO(NIO): nio_id = NIOFIFO._instance_count NIOFIFO._instance_count += 1 name = 'nio_fifo' + str(nio_id) - NIO.__init__(name, self, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nios/nio_generic_ethernet.py b/gns3server/modules/dynamips/nios/nio_generic_ethernet.py index 9690237a..dcc13bae 100644 --- a/gns3server/modules/dynamips/nios/nio_generic_ethernet.py +++ b/gns3server/modules/dynamips/nios/nio_generic_ethernet.py @@ -44,7 +44,7 @@ class NIOGenericEthernet(NIO): NIOGenericEthernet._instance_count += 1 name = 'nio_gen_eth' + str(nio_id) self._ethernet_device = ethernet_device - NIO.__init__(self, name, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nios/nio_linux_ethernet.py b/gns3server/modules/dynamips/nios/nio_linux_ethernet.py index f121dbb6..500123b5 100644 --- a/gns3server/modules/dynamips/nios/nio_linux_ethernet.py +++ b/gns3server/modules/dynamips/nios/nio_linux_ethernet.py @@ -44,7 +44,7 @@ class NIOLinuxEthernet(NIO): NIOLinuxEthernet._instance_count += 1 name = 'nio_linux_eth' + str(nio_id) self._ethernet_device = ethernet_device - NIO.__init__(self, name, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nios/nio_mcast.py b/gns3server/modules/dynamips/nios/nio_mcast.py index 95a9f2ae..f59dc280 100644 --- a/gns3server/modules/dynamips/nios/nio_mcast.py +++ b/gns3server/modules/dynamips/nios/nio_mcast.py @@ -47,7 +47,7 @@ class NIOMcast(NIO): self._group = group self._port = port self._ttl = 1 # default TTL - NIO.__init__(self, name, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nios/nio_null.py b/gns3server/modules/dynamips/nios/nio_null.py index e36fb0e5..4d46137c 100644 --- a/gns3server/modules/dynamips/nios/nio_null.py +++ b/gns3server/modules/dynamips/nios/nio_null.py @@ -42,7 +42,7 @@ class NIONull(NIO): nio_id = NIONull._instance_count NIONull._instance_count += 1 name = 'nio_null' + str(nio_id) - NIO.__init__(self, name, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nios/nio_tap.py b/gns3server/modules/dynamips/nios/nio_tap.py index 0e3b5683..b4bd172f 100644 --- a/gns3server/modules/dynamips/nios/nio_tap.py +++ b/gns3server/modules/dynamips/nios/nio_tap.py @@ -44,7 +44,7 @@ class NIOTAP(NIO): NIOTAP._instance_count += 1 name = 'nio_tap' + str(nio_id) self._tap_device = tap_device - NIO.__init__(self, name, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nios/nio_udp.py b/gns3server/modules/dynamips/nios/nio_udp.py index c7016e6a..eeb15e32 100644 --- a/gns3server/modules/dynamips/nios/nio_udp.py +++ b/gns3server/modules/dynamips/nios/nio_udp.py @@ -48,7 +48,7 @@ class NIOUDP(NIO): self._lport = lport self._rhost = rhost self._rport = rport - NIO.__init__(self, name, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nios/nio_unix.py b/gns3server/modules/dynamips/nios/nio_unix.py index dddfaf82..45fa41c0 100644 --- a/gns3server/modules/dynamips/nios/nio_unix.py +++ b/gns3server/modules/dynamips/nios/nio_unix.py @@ -46,7 +46,7 @@ class NIOUNIX(NIO): name = 'nio_unix' + str(nio_id) self._local_file = local_file self._remote_file = remote_file - NIO.__init__(self, name, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nios/nio_vde.py b/gns3server/modules/dynamips/nios/nio_vde.py index c62ce2ca..17a85524 100644 --- a/gns3server/modules/dynamips/nios/nio_vde.py +++ b/gns3server/modules/dynamips/nios/nio_vde.py @@ -46,7 +46,7 @@ class NIOVDE(NIO): name = 'nio_vde' + str(nio_id) self._control_file = control_file self._local_file = local_file - NIO.__init__(self, name, hypervisor) + super().__init__(name, hypervisor) @classmethod def reset(cls): diff --git a/gns3server/modules/dynamips/nodes/c1700.py b/gns3server/modules/dynamips/nodes/c1700.py index 1f7db1a0..e775df5a 100644 --- a/gns3server/modules/dynamips/nodes/c1700.py +++ b/gns3server/modules/dynamips/nodes/c1700.py @@ -47,7 +47,8 @@ class C1700(Router): """ def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="1720"): - Router.__init__(self, name, vm_id, project, manager, dynamips_id, console, aux, platform="c1700") + + super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c1700") # Set default values for this platform (must be the same as Dynamips) self._ram = 64 diff --git a/gns3server/modules/dynamips/nodes/c2600.py b/gns3server/modules/dynamips/nodes/c2600.py index ce5721d1..d39dcc98 100644 --- a/gns3server/modules/dynamips/nodes/c2600.py +++ b/gns3server/modules/dynamips/nodes/c2600.py @@ -62,7 +62,8 @@ class C2600(Router): "2651XM": C2600_MB_2FE} def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="2610"): - Router.__init__(self, name, vm_id, project, manager, dynamips_id, console, aux, platform="c2600") + + super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c2600") # Set default values for this platform (must be the same as Dynamips) self._ram = 64 diff --git a/gns3server/modules/dynamips/nodes/c2691.py b/gns3server/modules/dynamips/nodes/c2691.py index bafca2e0..8aed7c72 100644 --- a/gns3server/modules/dynamips/nodes/c2691.py +++ b/gns3server/modules/dynamips/nodes/c2691.py @@ -44,7 +44,8 @@ class C2691(Router): """ def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): - Router.__init__(self, name, vm_id, project, manager, dynamips_id, console, aux, platform="c2691") + + super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c2691") # Set default values for this platform (must be the same as Dynamips) self._ram = 128 diff --git a/gns3server/modules/dynamips/nodes/c3600.py b/gns3server/modules/dynamips/nodes/c3600.py index 9eff5964..07d1af5d 100644 --- a/gns3server/modules/dynamips/nodes/c3600.py +++ b/gns3server/modules/dynamips/nodes/c3600.py @@ -45,7 +45,8 @@ class C3600(Router): """ def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="3640"): - Router.__init__(self, name, vm_id, project, manager, dynamips_id, console, aux, platform="c3600") + + super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3600") # Set default values for this platform (must be the same as Dynamips) self._ram = 128 diff --git a/gns3server/modules/dynamips/nodes/c3725.py b/gns3server/modules/dynamips/nodes/c3725.py index 69bab887..14af51bb 100644 --- a/gns3server/modules/dynamips/nodes/c3725.py +++ b/gns3server/modules/dynamips/nodes/c3725.py @@ -44,7 +44,8 @@ class C3725(Router): """ def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): - Router.__init__(self, name, vm_id, project, manager, dynamips_id, console, aux, platform="c3725") + + super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3725") # Set default values for this platform (must be the same as Dynamips) self._ram = 128 diff --git a/gns3server/modules/dynamips/nodes/c3745.py b/gns3server/modules/dynamips/nodes/c3745.py index 53e4b1e3..1e81d51f 100644 --- a/gns3server/modules/dynamips/nodes/c3745.py +++ b/gns3server/modules/dynamips/nodes/c3745.py @@ -44,7 +44,8 @@ class C3745(Router): """ def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None): - Router.__init__(self, name, vm_id, project, manager, dynamips_id, console, aux, platform="c3745") + + super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c3745") # Set default values for this platform (must be the same as Dynamips) self._ram = 128 diff --git a/gns3server/modules/dynamips/nodes/c7200.py b/gns3server/modules/dynamips/nodes/c7200.py index 07e2ff4e..1a9d140f 100644 --- a/gns3server/modules/dynamips/nodes/c7200.py +++ b/gns3server/modules/dynamips/nodes/c7200.py @@ -47,7 +47,8 @@ class C7200(Router): """ def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, npe="npe-400", chassis=None): - Router.__init__(self, name, vm_id, project, manager, dynamips_id, console, aux, platform="c7200") + + super().__init__(name, vm_id, project, manager, dynamips_id, console, aux, platform="c7200") # Set default values for this platform (must be the same as Dynamips) self._ram = 256 diff --git a/gns3server/modules/dynamips/nodes/ethernet_hub.py b/gns3server/modules/dynamips/nodes/ethernet_hub.py index 92cfccab..776ec944 100644 --- a/gns3server/modules/dynamips/nodes/ethernet_hub.py +++ b/gns3server/modules/dynamips/nodes/ethernet_hub.py @@ -43,7 +43,7 @@ class EthernetHub(Bridge): def __init__(self, name, device_id, project, manager, hypervisor=None): - Bridge.__init__(self, name, device_id, project, manager, hypervisor) + super().__init__(name, device_id, project, manager, hypervisor) self._mappings = {} def __json__(self): diff --git a/gns3server/modules/iou/__init__.py b/gns3server/modules/iou/__init__.py index 7b80107a..764d6475 100644 --- a/gns3server/modules/iou/__init__.py +++ b/gns3server/modules/iou/__init__.py @@ -28,25 +28,37 @@ from .iou_vm import IOUVM class IOU(BaseManager): + _VM_CLASS = IOUVM def __init__(self): + super().__init__() self._free_application_ids = list(range(1, 512)) self._used_application_ids = {} @asyncio.coroutine def create_vm(self, *args, **kwargs): + """ + Creates a new IOU VM. + + :returns: IOUVM instance + """ vm = yield from super().create_vm(*args, **kwargs) try: self._used_application_ids[vm.id] = self._free_application_ids.pop(0) except IndexError: - raise IOUError("No mac address available") + raise IOUError("Cannot create a new IOU VM (limit of 512 VMs reached on this host)") return vm @asyncio.coroutine def close_vm(self, vm_id, *args, **kwargs): + """ + Closes an IOU VM. + + :returns: IOUVM instance + """ vm = self.get_vm(vm_id) if vm_id in self._used_application_ids: @@ -58,10 +70,11 @@ class IOU(BaseManager): def get_application_id(self, vm_id): """ - Get an unique IOU mac id + Get an unique application identifier for IOU. - :param vm_id: ID of the IOU VM - :returns: IOU MAC id + :param vm_id: IOU VM identifier + + :returns: IOU application identifier """ return self._used_application_ids.get(vm_id, 1) diff --git a/gns3server/modules/iou/iou_error.py b/gns3server/modules/iou/iou_error.py index cd43bdb9..3d4a719e 100644 --- a/gns3server/modules/iou/iou_error.py +++ b/gns3server/modules/iou/iou_error.py @@ -16,7 +16,7 @@ # along with this program. If not, see . """ -Custom exceptions for IOU module. +Custom exceptions for the IOU module. """ from ..vm_error import VMError diff --git a/gns3server/modules/iou/iou_vm.py b/gns3server/modules/iou/iou_vm.py index ee8cc1ed..6f05f5b1 100644 --- a/gns3server/modules/iou/iou_vm.py +++ b/gns3server/modules/iou/iou_vm.py @@ -17,7 +17,7 @@ """ IOU VM management (creates command line, processes, files etc.) in -order to run an IOU instance. +order to run an IOU VM. """ import os @@ -54,20 +54,20 @@ class IOUVM(BaseVM): module_name = 'iou' """ - IOU vm implementation. + IOU VM implementation. - :param name: name of this IOU vm - :param vm_id: IOU instance identifier + :param name: IOU VM name + :param vm_id: IOU VM identifier :param project: Project instance - :param manager: parent VM Manager + :param manager: Manager instance :param console: TCP console port - :params ethernet_adapters: Number of ethernet adapters - :params serial_adapters: Number of serial adapters - :params ram: Ram MB - :params nvram: Nvram KB - :params l1_keepalives: Always up ethernet interface: - :params initial_config: Content of the initial configuration file - :params iourc_content: Content of the iourc file if no licence is installed on server + :params ethernet_adapters: number of ethernet adapters + :params serial_adapters: number of serial adapters + :params ram: amount of RAM in MB + :params nvram: amount of NVRAM in KB + :params l1_keepalives: always keep the Ethernet interfaces up + :params initial_config: content of the initial configuration file + :params iourc_content: content of the iourc file if no licence is installed on the machine """ def __init__(self, name, vm_id, project, manager, @@ -108,6 +108,9 @@ class IOUVM(BaseVM): @asyncio.coroutine def close(self): + """ + Closes this IOU VM. + """ log.debug('IOU "{name}" [{id}] is closing'.format(name=self._name, id=self._id)) @@ -126,16 +129,20 @@ class IOUVM(BaseVM): @property def path(self): - """Path of the iou binary""" + """ + Path of the IOU executable. + + :returns: path to the IOU image executable + """ return self._path @path.setter def path(self, path): """ - Path of the iou binary + Path of the IOU executable. - :params path: Path to the binary + :param path: path to the IOU image executable """ if not os.path.isabs(path): @@ -171,6 +178,7 @@ class IOUVM(BaseVM): def use_default_iou_values(self): """ Returns if this device uses the default IOU image values. + :returns: boolean """ @@ -180,28 +188,30 @@ class IOUVM(BaseVM): def use_default_iou_values(self, state): """ Sets if this device uses the default IOU image values. + :param state: boolean """ self._use_default_iou_values = state if state: - log.info("IOU {name} [id={id}]: uses the default IOU image values".format(name=self._name, id=self._id)) + log.info('IOU "{name}" [{id}]: uses the default IOU image values'.format(name=self._name, id=self._id)) else: - log.info("IOU {name} [id={id}]: does not use the default IOU image values".format(name=self._name, id=self._id)) + log.info('IOU "{name}" [{id}]: does not use the default IOU image values'.format(name=self._name, id=self._id)) def _check_requirements(self): """ - Check if IOUYAP is available + Checks if IOUYAP executable is available. """ + path = self.iouyap_path if not path: - raise IOUError("No path to a IOU executable has been set") + raise IOUError("No path to iouyap program has been set") if not os.path.isfile(path): - raise IOUError("IOU program '{}' is not accessible".format(path)) + raise IOUError("iouyap program '{}' is not accessible".format(path)) if not os.access(path, os.X_OK): - raise IOUError("IOU program '{}' is not executable".format(path)) + raise IOUError("iouyap program '{}' is not executable".format(path)) def __json__(self): @@ -243,7 +253,7 @@ class IOUVM(BaseVM): @property def iourc_path(self): """ - Returns the IOURC path. + Returns the IOURC file path. :returns: path to IOURC """ @@ -267,8 +277,9 @@ class IOUVM(BaseVM): @property def ram(self): """ - Returns the amount of RAM allocated to this IOU instance. - :returns: amount of RAM in Mbytes (integer) + Returns the amount of RAM allocated to this IOU VM. + + :returns: amount of RAM in MBytes (integer) """ return self._ram @@ -277,16 +288,17 @@ class IOUVM(BaseVM): def ram(self, ram): """ Sets amount of RAM allocated to this IOU instance. - :param ram: amount of RAM in Mbytes (integer) + + :param ram: amount of RAM in MBytes (integer) """ if self._ram == ram: return - log.info("IOU {name} [id={id}]: RAM updated from {old_ram}MB to {new_ram}MB".format(name=self._name, - id=self._id, - old_ram=self._ram, - new_ram=ram)) + log.info('IOU "{name}" [{id}]: RAM updated from {old_ram}MB to {new_ram}MB'.format(name=self._name, + id=self._id, + old_ram=self._ram, + new_ram=ram)) self._ram = ram @@ -294,7 +306,8 @@ class IOUVM(BaseVM): def nvram(self): """ Returns the mount of NVRAM allocated to this IOU instance. - :returns: amount of NVRAM in Kbytes (integer) + + :returns: amount of NVRAM in KBytes (integer) """ return self._nvram @@ -303,22 +316,23 @@ class IOUVM(BaseVM): def nvram(self, nvram): """ Sets amount of NVRAM allocated to this IOU instance. - :param nvram: amount of NVRAM in Kbytes (integer) + + :param nvram: amount of NVRAM in KBytes (integer) """ if self._nvram == nvram: return - log.info("IOU {name} [id={id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB".format(name=self._name, - id=self._id, - old_nvram=self._nvram, - new_nvram=nvram)) + log.info('IOU "{name}" [{id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB'.format(name=self._name, + id=self._id, + old_nvram=self._nvram, + new_nvram=nvram)) self._nvram = nvram @BaseVM.name.setter def name(self, new_name): """ - Sets the name of this IOU vm. + Sets the name of this IOU VM. :param new_name: name """ @@ -332,10 +346,12 @@ class IOUVM(BaseVM): @property def application_id(self): + return self._manager.get_application_id(self.id) @property def iourc_content(self): + try: with open(os.path.join(self.temporary_directory, "iourc")) as f: return f.read() @@ -344,13 +360,14 @@ class IOUVM(BaseVM): @iourc_content.setter def iourc_content(self, value): + if value is not None: path = os.path.join(self.temporary_directory, "iourc") try: with open(path, "w+") as f: f.write(value) except OSError as e: - raise IOUError("Could not write iourc file {}: {}".format(path, e)) + raise IOUError("Could not write the iourc file {}: {}".format(path, e)) @asyncio.coroutine def _library_check(self): @@ -468,11 +485,11 @@ class IOUVM(BaseVM): log.info("IOU instance {} started PID={}".format(self._id, self._iou_process.pid)) self._started = True except FileNotFoundError as e: - raise IOUError("could not start IOU: {}: 32-bit binary support is probably not installed".format(e)) + raise IOUError("Could not start IOU: {}: 32-bit binary support is probably not installed".format(e)) except (OSError, subprocess.SubprocessError) as e: iou_stdout = self.read_iou_stdout() - log.error("could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout)) - raise IOUError("could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout)) + log.error("Could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout)) + raise IOUError("Could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout)) # start console support self._start_ioucon() @@ -481,7 +498,7 @@ class IOUVM(BaseVM): def _rename_nvram_file(self): """ - Before start the VM rename the nvram file to the correct application id + Before starting the VM, rename the nvram and vlan.dat files with the correct IOU application identifier. """ destination = os.path.join(self.working_dir, "nvram_{:05d}".format(self.application_id)) @@ -494,7 +511,7 @@ class IOUVM(BaseVM): @asyncio.coroutine def _start_iouyap(self): """ - Starts iouyap (handles connections to and from this IOU device). + Starts iouyap (handles connections to and from this IOU VM). """ try: @@ -512,7 +529,7 @@ class IOUVM(BaseVM): log.info("iouyap started PID={}".format(self._iouyap_process.pid)) except (OSError, subprocess.SubprocessError) as e: iouyap_stdout = self.read_iouyap_stdout() - log.error("could not start iouyap: {}\n{}".format(e, iouyap_stdout)) + log.error("Could not start iouyap: {}\n{}".format(e, iouyap_stdout)) raise IOUError("Could not start iouyap: {}\n{}".format(e, iouyap_stdout)) def _update_iouyap_config(self): @@ -614,29 +631,33 @@ class IOUVM(BaseVM): self._started = False def _terminate_process_iouyap(self): - """Terminate the process if running""" + """ + Terminate the IOUYAP process if running. + """ - log.info("Stopping IOUYAP instance {} PID={}".format(self.name, self._iouyap_process.pid)) + log.info('Stopping IOUYAP process for IOU VM "{}" PID={}'.format(self.name, self._iouyap_process.pid)) try: self._iouyap_process.terminate() - # Sometime the process can already be dead when we garbage collect + # Sometime the process may already be dead when we garbage collect except ProcessLookupError: pass def _terminate_process_iou(self): - """Terminate the process if running""" + """ + Terminate the IOU process if running + """ - log.info("Stopping IOU instance {} PID={}".format(self.name, self._iou_process.pid)) + log.info('Stopping IOU process for IOU VM "{}" PID={}'.format(self.name, self._iou_process.pid)) try: self._iou_process.terminate() - # Sometime the process can already be dead when we garbage collect + # Sometime the process may already be dead when we garbage collect except ProcessLookupError: pass @asyncio.coroutine def reload(self): """ - Reload the IOU process. (Stop / Start) + Reloads the IOU process (stop & start). """ yield from self.stop() @@ -688,6 +709,7 @@ class IOUVM(BaseVM): """ Command to start the IOU process. (to be passed to subprocess.Popen()) + IOU command line: Usage: [options] : unix-js-m | unix-is-m | unix-i-m | ... @@ -777,7 +799,8 @@ class IOUVM(BaseVM): @property def ethernet_adapters(self): """ - Returns the number of Ethernet adapters for this IOU instance. + Returns the number of Ethernet adapters for this IOU VM. + :returns: number of adapters """ @@ -786,7 +809,8 @@ class IOUVM(BaseVM): @ethernet_adapters.setter def ethernet_adapters(self, ethernet_adapters): """ - Sets the number of Ethernet adapters for this IOU instance. + Sets the number of Ethernet adapters for this IOU VM. + :param ethernet_adapters: number of adapters """ @@ -794,16 +818,17 @@ class IOUVM(BaseVM): for _ in range(0, ethernet_adapters): self._ethernet_adapters.append(EthernetAdapter(interfaces=4)) - log.info("IOU {name} [id={id}]: number of Ethernet adapters changed to {adapters}".format(name=self._name, - id=self._id, - adapters=len(self._ethernet_adapters))) + log.info('IOU "{name}" [{id}]: number of Ethernet adapters changed to {adapters}'.format(name=self._name, + id=self._id, + adapters=len(self._ethernet_adapters))) self._adapters = self._ethernet_adapters + self._serial_adapters @property def serial_adapters(self): """ - Returns the number of Serial adapters for this IOU instance. + Returns the number of Serial adapters for this IOU VM. + :returns: number of adapters """ @@ -812,7 +837,8 @@ class IOUVM(BaseVM): @serial_adapters.setter def serial_adapters(self, serial_adapters): """ - Sets the number of Serial adapters for this IOU instance. + Sets the number of Serial adapters for this IOU VM. + :param serial_adapters: number of adapters """ @@ -820,67 +846,69 @@ class IOUVM(BaseVM): for _ in range(0, serial_adapters): self._serial_adapters.append(SerialAdapter(interfaces=4)) - log.info("IOU {name} [id={id}]: number of Serial adapters changed to {adapters}".format(name=self._name, - id=self._id, - adapters=len(self._serial_adapters))) + log.info('IOU "{name}" [{id}]: number of Serial adapters changed to {adapters}'.format(name=self._name, + id=self._id, + adapters=len(self._serial_adapters))) self._adapters = self._ethernet_adapters + self._serial_adapters def adapter_add_nio_binding(self, adapter_number, port_number, nio): """ Adds a adapter NIO binding. - :param adapter_number: adapter ID - :param port_number: port ID + + :param adapter_number: adapter number + :param port_number: port number :param nio: NIO instance to add to the adapter/port """ try: adapter = self._adapters[adapter_number] except IndexError: - raise IOUError("Adapter {adapter_number} doesn't exist on IOU {name}".format(name=self._name, - adapter_number=adapter_number)) + raise IOUError('Adapter {adapter_number} does not exist for IOU "{name}"'.format(name=self._name, + adapter_number=adapter_number)) if not adapter.port_exists(port_number): - raise IOUError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) + raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + port_number=port_number)) adapter.add_nio(port_number, nio) - log.info("IOU {name} [id={id}]: {nio} added to {adapter_number}/{port_number}".format(name=self._name, - id=self._id, - nio=nio, - adapter_number=adapter_number, - port_number=port_number)) + log.info('IOU "{name}" [{id}]: {nio} added to {adapter_number}/{port_number}'.format(name=self._name, + id=self._id, + nio=nio, + adapter_number=adapter_number, + port_number=port_number)) if self.is_iouyap_running(): self._update_iouyap_config() os.kill(self._iouyap_process.pid, signal.SIGHUP) def adapter_remove_nio_binding(self, adapter_number, port_number): """ - Removes a adapter NIO binding. - :param adapter_number: adapter ID - :param port_number: port ID + Removes an adapter NIO binding. + + :param adapter_number: adapter number + :param port_number: port number :returns: NIO instance """ try: adapter = self._adapters[adapter_number] except IndexError: - raise IOUError("Adapter {adapter_number} doesn't exist on IOU {name}".format(name=self._name, - adapter_number=adapter_number)) + raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name, + adapter_number=adapter_number)) if not adapter.port_exists(port_number): - raise IOUError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) + raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + port_number=port_number)) nio = adapter.get_nio(port_number) if isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) adapter.remove_nio(port_number) - log.info("IOU {name} [id={id}]: {nio} removed from {adapter_number}/{port_number}".format(name=self._name, - id=self._id, - nio=nio, - adapter_number=adapter_number, - port_number=port_number)) + log.info('IOU "{name}" [{id}]: {nio} removed from {adapter_number}/{port_number}'.format(name=self._name, + id=self._id, + nio=nio, + adapter_number=adapter_number, + port_number=port_number)) if self.is_iouyap_running(): self._update_iouyap_config() os.kill(self._iouyap_process.pid, signal.SIGHUP) @@ -891,6 +919,7 @@ class IOUVM(BaseVM): def l1_keepalives(self): """ Returns either layer 1 keepalive messages option is enabled or disabled. + :returns: boolean """ @@ -900,19 +929,21 @@ class IOUVM(BaseVM): def l1_keepalives(self, state): """ Enables or disables layer 1 keepalive messages. + :param state: boolean """ self._l1_keepalives = state if state: - log.info("IOU {name} [id={id}]: has activated layer 1 keepalive messages".format(name=self._name, id=self._id)) + log.info('IOU "{name}" [{id}]: has activated layer 1 keepalive messages'.format(name=self._name, id=self._id)) else: - log.info("IOU {name} [id={id}]: has deactivated layer 1 keepalive messages".format(name=self._name, id=self._id)) + log.info('IOU "{name}" [{id}]: has deactivated layer 1 keepalive messages'.format(name=self._name, id=self._id)) @asyncio.coroutine def _enable_l1_keepalives(self, command): """ Enables L1 keepalive messages if supported. + :param command: command line """ @@ -930,7 +961,9 @@ class IOUVM(BaseVM): @property def initial_config(self): - """Return the content of the current initial-config file""" + """ + Returns the content of the current initial-config file. + """ config_file = self.initial_config_file if config_file is None: @@ -947,7 +980,7 @@ class IOUVM(BaseVM): """ Update the initial config - :param initial_config: The content of the initial configuration file + :param initial_config: content of the initial configuration file """ try: @@ -964,7 +997,7 @@ class IOUVM(BaseVM): @property def initial_config_file(self): """ - Returns the initial config file for this IOU instance. + Returns the initial config file for this IOU VM. :returns: path to config file. None if the file doesn't exist """ @@ -979,7 +1012,7 @@ class IOUVM(BaseVM): def relative_initial_config_file(self): """ Returns the initial config file relative to the project directory. - It's compatible with pre 1.3 topologies. + It's compatible with pre 1.3 projects. :returns: path to config file. None if the file doesn't exist """ @@ -994,9 +1027,9 @@ class IOUVM(BaseVM): def start_capture(self, adapter_number, port_number, output_file, data_link_type="DLT_EN10MB"): """ Starts a packet capture. - :param adapter_number: adapter ID - :param port_number: port ID - :param port: allocated port + + :param adapter_number: adapter number + :param port_number: port number :param output_file: PCAP destination file for the capture :param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB """ @@ -1004,35 +1037,28 @@ class IOUVM(BaseVM): try: adapter = self._adapters[adapter_number] except IndexError: - raise IOUError("Adapter {adapter_number} doesn't exist on IOU {name}".format(name=self._name, - adapter_number=adapter_number)) + raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name, + adapter_number=adapter_number)) if not adapter.port_exists(port_number): - raise IOUError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) + raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + port_number=port_number)) nio = adapter.get_nio(port_number) if not nio: - raise IOUError("NIO {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) + raise IOUError("NIO {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + port_number=port_number)) if nio.capturing: raise IOUError("Packet capture is already activated on {adapter_number}/{port_number}".format(adapter_number=adapter_number, port_number=port_number)) - try: - os.makedirs(os.path.dirname(output_file)) - except FileExistsError: - pass - except OSError as e: - raise IOUError("Could not create captures directory {}".format(e)) nio.startPacketCapture(output_file, data_link_type) - - log.info("IOU {name} [id={id}]: starting packet capture on {adapter_number}/{port_number}".format(name=self._name, - id=self._id, - adapter_number=adapter_number, - port_number=port_number)) + log.info('IOU "{name}" [{id}]: starting packet capture on {adapter_number}/{port_number}'.format(name=self._name, + id=self._id, + adapter_number=adapter_number, + port_number=port_number)) if self.is_iouyap_running(): self._update_iouyap_config() @@ -1042,26 +1068,27 @@ class IOUVM(BaseVM): def stop_capture(self, adapter_number, port_number): """ Stops a packet capture. - :param adapter_number: adapter ID - :param port_number: port ID + + :param adapter_number: adapter number + :param port_number: port number """ try: adapter = self._adapters[adapter_number] except IndexError: - raise IOUError("Adapter {adapter_number} doesn't exist on IOU {name}".format(name=self._name, - adapter_number=adapter_number)) + raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name, + adapter_number=adapter_number)) if not adapter.port_exists(port_number): - raise IOUError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter, - port_number=port_number)) + raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter, + port_number=port_number)) nio = adapter.get_nio(port_number) nio.stopPacketCapture() - log.info("IOU {name} [id={id}]: stopping packet capture on {adapter_number}/{port_number}".format(name=self._name, - id=self._id, - adapter_number=adapter_number, - port_number=port_number)) + log.info('IOU "{name}" [{id}]: stopping packet capture on {adapter_number}/{port_number}'.format(name=self._name, + id=self._id, + adapter_number=adapter_number, + port_number=port_number)) if self.is_iouyap_running(): self._update_iouyap_config() os.kill(self._iouyap_process.pid, signal.SIGHUP) diff --git a/gns3server/modules/nios/nio_generic_ethernet.py b/gns3server/modules/nios/nio_generic_ethernet.py index da729565..fee02d1a 100644 --- a/gns3server/modules/nios/nio_generic_ethernet.py +++ b/gns3server/modules/nios/nio_generic_ethernet.py @@ -32,7 +32,7 @@ class NIOGenericEthernet(NIO): def __init__(self, ethernet_device): - NIO.__init__(self) + super().__init__() self._ethernet_device = ethernet_device @property diff --git a/gns3server/modules/port_manager.py b/gns3server/modules/port_manager.py index 8283e5e5..f1af09f8 100644 --- a/gns3server/modules/port_manager.py +++ b/gns3server/modules/port_manager.py @@ -261,7 +261,7 @@ class PortManager: :param force_remove: Force port removal even on Darwnin """ - # A bug with dynamips on darwin doesn't correctly free the port we free it only when changing project + # A bug with Dynamips on Darwin which doesn't correctly free UDP ports, they are freed only when changing the project if sys.platform.startswith("darwin") and force_remove is False: return diff --git a/gns3server/modules/project.py b/gns3server/modules/project.py index 6e7281eb..fa71ab51 100644 --- a/gns3server/modules/project.py +++ b/gns3server/modules/project.py @@ -35,10 +35,10 @@ class Project: A project contains a list of VM. In theory VM are isolated project/project. - :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 location: Parent path of the project. (None should create a tmp directory) - :param temporary: Boolean the project is a temporary project (destroy when closed) + :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 location: parent path of the project. (None should create a tmp directory) + :param temporary: boolean to tell if the project is a temporary project (destroy when closed) """ def __init__(self, name=None, project_id=None, path=None, location=None, temporary=False): @@ -231,7 +231,7 @@ class Project: def module_working_directory(self, module_name): """ - Return a working directory for the module + Returns a working directory for the module If the directory doesn't exist, the directory is created. :param module_name: name for the module @@ -247,18 +247,20 @@ class Project: def module_working_path(self, module_name): """ - Return the working direcotory for the module. If you want + Returns the working directory for the module. If you want to be sure to have the directory on disk take a look on: module_working_directory """ + return os.path.join(self._path, "project-files", module_name) def vm_working_directory(self, vm): """ - Return a working directory for a specific VM. + Returns a working directory for a specific VM. If the directory doesn't exist, the directory is created. :param vm: VM instance + :returns: VM working directory """ @@ -271,7 +273,7 @@ class Project: def capture_working_directory(self): """ - Return a working directory where to store packet capture files. + Returns a working directory where to store packet capture files. :returns: path to the directory """ @@ -293,7 +295,7 @@ class Project: def add_vm(self, vm): """ - Add a VM to the project. + Adds a VM to the project. In theory this should be called by the VM manager. :param vm: VM instance @@ -303,7 +305,7 @@ class Project: def remove_vm(self, vm): """ - Remove a VM from the project. + Removes a VM from the project. In theory this should be called by the VM manager. :param vm: VM instance @@ -314,7 +316,9 @@ class Project: @asyncio.coroutine def close(self): - """Close the project, but keep information on disk""" + """ + Closes the project, but keep information on disk + """ for module in self.modules(): yield from module.instance().project_closing(self) @@ -325,7 +329,7 @@ class Project: @asyncio.coroutine def _close_and_clean(self, cleanup): """ - Close the project, and cleanup the disk if cleanup is True + Closes the project, and cleanup the disk if cleanup is True :param cleanup: If True drop the project directory """ @@ -365,7 +369,9 @@ class Project: @asyncio.coroutine def commit(self): - """Write project changes on disk""" + """ + Writes project changes on disk + """ while self._vms_to_destroy: vm = self._vms_to_destroy.pop() @@ -376,7 +382,9 @@ class Project: @asyncio.coroutine def delete(self): - """Remove project from disk""" + """ + Removes project from disk + """ for module in self.modules(): yield from module.instance().project_closing(self) @@ -386,7 +394,9 @@ class Project: @classmethod def clean_project_directory(cls): - """At startup drop old temporary project. After a crash for example""" + """ + At startup drop old temporary project. After a crash for example + """ config = Config.instance().get_section_config("Server") directory = config.get("project_directory", cls._get_default_project_directory()) @@ -398,7 +408,9 @@ class Project: shutil.rmtree(path) def modules(self): - """Return VM modules loaded""" + """ + Returns all loaded VM modules. + """ # We import it at the last time to avoid circular dependencies from ..modules import MODULES diff --git a/gns3server/modules/qemu/__init__.py b/gns3server/modules/qemu/__init__.py index aa9e2f90..d348894f 100644 --- a/gns3server/modules/qemu/__init__.py +++ b/gns3server/modules/qemu/__init__.py @@ -32,14 +32,15 @@ from .qemu_vm import QemuVM class Qemu(BaseManager): + _VM_CLASS = QemuVM @staticmethod def binary_list(): """ - Gets QEMU binaries list available on the matchine + Gets QEMU binaries list available on the host. - :returns: Array of dictionnary {"path": Qemu binaries path, "version": Version of Qemu} + :returns: Array of dictionary {"path": Qemu binary path, "version": version of Qemu} """ qemus = [] @@ -82,7 +83,8 @@ class Qemu(BaseManager): def _get_qemu_version(qemu_path): """ Gets the Qemu version. - :param qemu_path: path to Qemu + + :param qemu_path: path to Qemu executable. """ if sys.platform.startswith("win"): diff --git a/gns3server/modules/qemu/qemu_error.py b/gns3server/modules/qemu/qemu_error.py index 48aca696..d5ee236c 100644 --- a/gns3server/modules/qemu/qemu_error.py +++ b/gns3server/modules/qemu/qemu_error.py @@ -16,7 +16,7 @@ # along with this program. If not, see . """ -Custom exceptions for Qemu module. +Custom exceptions for the Qemu module. """ from ..vm_error import VMError diff --git a/gns3server/modules/qemu/qemu_vm.py b/gns3server/modules/qemu/qemu_vm.py index 46727cad..75731d24 100644 --- a/gns3server/modules/qemu/qemu_vm.py +++ b/gns3server/modules/qemu/qemu_vm.py @@ -16,7 +16,8 @@ # along with this program. If not, see . """ -QEMU VM instance. +QEMU VM management (creates command line, processes, files etc.) in +order to run a QEMU VM. """ import sys @@ -44,26 +45,18 @@ class QemuVM(BaseVM): """ QEMU VM implementation. - :param name: name of this Qemu vm - :param vm_id: IOU instance identifier + :param name: Qemu VM name + :param vm_id: Qemu VM identifier :param project: Project instance - :param manager: parent VM Manager + :param manager: Manager instance :param console: TCP console port :param qemu_path: path to the QEMU binary - :param qemu_id: QEMU VM instance ID :param console: TCP console port """ - def __init__(self, - name, - vm_id, - project, - manager, - qemu_path=None, - console=None): + def __init__(self, name, vm_id, project, manager, qemu_path=None, console=None): super().__init__(name, vm_id, project, manager, console=console) - server_config = manager.config.get_section_config("Server") self._host = server_config.get("host", "127.0.0.1") self._monitor_host = server_config.get("monitor_host", "127.0.0.1") @@ -74,7 +67,7 @@ class QemuVM(BaseVM): self._monitor = None self._stdout_file = "" - # QEMU settings + # QEMU VM settings self._qemu_path = qemu_path self._hda_disk_image = "" self._hdb_disk_image = "" @@ -92,8 +85,7 @@ class QemuVM(BaseVM): self._process_priority = "low" self.adapters = 1 # creates 1 adapter by default - log.info("QEMU VM {name} [id={id}] has been created".format(name=self._name, - id=self._id)) + log.info('QEMU VM "{name}" [{id}] has been created'.format(name=self._name, id=self._id)) @property def monitor(self): @@ -134,9 +126,9 @@ class QemuVM(BaseVM): raise QemuError("QEMU binary '{}' is not executable".format(qemu_path)) self._qemu_path = qemu_path - log.info("QEMU VM {name} [id={id}] has set the QEMU path to {qemu_path}".format(name=self._name, - id=self._id, - qemu_path=qemu_path)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU path to {qemu_path}'.format(name=self._name, + id=self._id, + qemu_path=qemu_path)) @property def hda_disk_image(self): @@ -160,9 +152,9 @@ class QemuVM(BaseVM): server_config = self.manager.config.get_section_config("Server") hda_disk_image = os.path.join(os.path.expanduser(server_config.get("images_path", "~/GNS3/images")), "QEMU", hda_disk_image) - log.info("QEMU VM {name} [id={id}] has set the QEMU hda disk image path to {disk_image}".format(name=self._name, - id=self._id, - disk_image=hda_disk_image)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU hda disk image path to {disk_image}'.format(name=self._name, + id=self._id, + disk_image=hda_disk_image)) self._hda_disk_image = hda_disk_image @property @@ -187,9 +179,9 @@ class QemuVM(BaseVM): server_config = self.manager.config.get_section_config("Server") hdb_disk_image = os.path.join(os.path.expanduser(server_config.get("images_path", "~/GNS3/images")), "QEMU", hdb_disk_image) - log.info("QEMU VM {name} [id={id}] has set the QEMU hdb disk image path to {disk_image}".format(name=self._name, - id=self._id, - disk_image=hdb_disk_image)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU hdb disk image path to {disk_image}'.format(name=self._name, + id=self._id, + disk_image=hdb_disk_image)) self._hdb_disk_image = hdb_disk_image @property @@ -214,9 +206,9 @@ class QemuVM(BaseVM): server_config = self.manager.config.get_section_config("Server") hdc_disk_image = os.path.join(os.path.expanduser(server_config.get("images_path", "~/GNS3/images")), "QEMU", hdc_disk_image) - log.info("QEMU VM {name} [id={id}] has set the QEMU hdc disk image path to {disk_image}".format(name=self._name, - id=self._id, - disk_image=hdc_disk_image)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU hdc disk image path to {disk_image}'.format(name=self._name, + id=self._id, + disk_image=hdc_disk_image)) self._hdc_disk_image = hdc_disk_image @property @@ -241,15 +233,15 @@ class QemuVM(BaseVM): server_config = self.manager.config.get_section_config("Server") hdd_disk_image = os.path.join(os.path.expanduser(server_config.get("images_path", "~/GNS3/images")), "QEMU", hdd_disk_image) - log.info("QEMU VM {name} [id={id}] has set the QEMU hdd disk image path to {disk_image}".format(name=self._name, - id=self._id, - disk_image=hdd_disk_image)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU hdd disk image path to {disk_image}'.format(name=self._name, + id=self._id, + disk_image=hdd_disk_image)) self._hdd_disk_image = hdd_disk_image @property def adapters(self): """ - Returns the number of Ethernet adapters for this QEMU VM instance. + Returns the number of Ethernet adapters for this QEMU VM. :returns: number of adapters """ @@ -259,23 +251,23 @@ class QemuVM(BaseVM): @adapters.setter def adapters(self, adapters): """ - Sets the number of Ethernet adapters for this QEMU VM instance. + Sets the number of Ethernet adapters for this QEMU VM. :param adapters: number of adapters """ self._ethernet_adapters.clear() - for adapter_id in range(0, adapters): + for adapter_number in range(0, adapters): self._ethernet_adapters.append(EthernetAdapter()) - log.info("QEMU VM {name} [id={id}]: number of Ethernet adapters changed to {adapters}".format(name=self._name, - id=self._id, - adapters=adapters)) + log.info('QEMU VM "{name}" [{id}]: number of Ethernet adapters changed to {adapters}'.format(name=self._name, + id=self._id, + adapters=adapters)) @property def adapter_type(self): """ - Returns the adapter type for this QEMU VM instance. + Returns the adapter type for this QEMU VM. :returns: adapter type (string) """ @@ -285,16 +277,16 @@ class QemuVM(BaseVM): @adapter_type.setter def adapter_type(self, adapter_type): """ - Sets the adapter type for this QEMU VM instance. + Sets the adapter type for this QEMU VM. :param adapter_type: adapter type (string) """ self._adapter_type = adapter_type - log.info("QEMU VM {name} [id={id}]: adapter type changed to {adapter_type}".format(name=self._name, - id=self._id, - adapter_type=adapter_type)) + log.info('QEMU VM "{name}" [{id}]: adapter type changed to {adapter_type}'.format(name=self._name, + id=self._id, + adapter_type=adapter_type)) @property def legacy_networking(self): @@ -315,9 +307,9 @@ class QemuVM(BaseVM): """ if legacy_networking: - log.info("QEMU VM {name} [id={id}] has enabled legacy networking".format(name=self._name, id=self._id)) + log.info('QEMU VM "{name}" [{id}] has enabled legacy networking'.format(name=self._name, id=self._id)) else: - log.info("QEMU VM {name} [id={id}] has disabled legacy networking".format(name=self._name, id=self._id)) + log.info('QEMU VM "{name}" [{id}] has disabled legacy networking'.format(name=self._name, id=self._id)) self._legacy_networking = legacy_networking @property @@ -338,9 +330,9 @@ class QemuVM(BaseVM): :param cpu_throttling: integer """ - log.info("QEMU VM {name} [id={id}] has set the percentage of CPU allowed to {cpu}".format(name=self._name, - id=self._id, - cpu=cpu_throttling)) + log.info('QEMU VM "{name}" [{id}] has set the percentage of CPU allowed to {cpu}'.format(name=self._name, + id=self._id, + cpu=cpu_throttling)) self._cpu_throttling = cpu_throttling self._stop_cpulimit() if cpu_throttling: @@ -364,9 +356,9 @@ class QemuVM(BaseVM): :param process_priority: string """ - log.info("QEMU VM {name} [id={id}] has set the process priority to {priority}".format(name=self._name, - id=self._id, - priority=process_priority)) + log.info('QEMU VM "{name}" [{id}] has set the process priority to {priority}'.format(name=self._name, + id=self._id, + priority=process_priority)) self._process_priority = process_priority @property @@ -387,9 +379,7 @@ class QemuVM(BaseVM): :param ram: RAM amount in MB """ - log.info("QEMU VM {name} [id={id}] has set the RAM to {ram}".format(name=self._name, - id=self._id, - ram=ram)) + log.info('QEMU VM "{name}" [{id}] has set the RAM to {ram}'.format(name=self._name, id=self._id, ram=ram)) self._ram = ram @property @@ -410,9 +400,9 @@ class QemuVM(BaseVM): :param options: QEMU options """ - log.info("QEMU VM {name} [id={id}] has set the QEMU options to {options}".format(name=self._name, - id=self._id, - options=options)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU options to {options}'.format(name=self._name, + id=self._id, + options=options)) self._options = options @property @@ -437,9 +427,9 @@ class QemuVM(BaseVM): server_config = self.manager.config.get_section_config("Server") initrd = os.path.join(os.path.expanduser(server_config.get("images_path", "~/GNS3/images")), "QEMU", initrd) - log.info("QEMU VM {name} [id={id}] has set the QEMU initrd path to {initrd}".format(name=self._name, - id=self._id, - initrd=initrd)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU initrd path to {initrd}'.format(name=self._name, + id=self._id, + initrd=initrd)) self._initrd = initrd @property @@ -464,9 +454,9 @@ class QemuVM(BaseVM): server_config = self.manager.config.get_section_config("Server") kernel_image = os.path.join(os.path.expanduser(server_config.get("images_path", "~/GNS3/images")), "QEMU", kernel_image) - log.info("QEMU VM {name} [id={id}] has set the QEMU kernel image path to {kernel_image}".format(name=self._name, - id=self._id, - kernel_image=kernel_image)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU kernel image path to {kernel_image}'.format(name=self._name, + id=self._id, + kernel_image=kernel_image)) self._kernel_image = kernel_image @property @@ -487,9 +477,9 @@ class QemuVM(BaseVM): :param kernel_command_line: QEMU kernel command line """ - log.info("QEMU VM {name} [id={id}] has set the QEMU kernel command line to {kernel_command_line}".format(name=self._name, - id=self._id, - kernel_command_line=kernel_command_line)) + log.info('QEMU VM "{name}" [{id}] has set the QEMU kernel command line to {kernel_command_line}'.format(name=self._name, + id=self._id, + kernel_command_line=kernel_command_line)) self._kernel_command_line = kernel_command_line @asyncio.coroutine @@ -538,7 +528,7 @@ class QemuVM(BaseVM): process = yield from asyncio.create_subprocess_exec('renice', '-n', str(priority), '-p', str(self._process.pid)) yield from process.wait() except (OSError, subprocess.SubprocessError) as e: - log.error("could not change process priority for QEMU VM {}: {}".format(self._name, e)) + log.error('Could not change process priority for QEMU VM "{}": {}'.format(self._name, e)) def _stop_cpulimit(self): """ @@ -550,7 +540,7 @@ class QemuVM(BaseVM): try: self._process.wait(3) except subprocess.TimeoutExpired: - log.error("could not kill cpulimit process {}".format(self._cpulimit_process.pid)) + log.error("Could not kill cpulimit process {}".format(self._cpulimit_process.pid)) def _set_cpu_throttling(self): """ @@ -579,7 +569,6 @@ class QemuVM(BaseVM): """ if self.is_running(): - # resume the VM if it is paused yield from self.resume() return @@ -597,7 +586,7 @@ class QemuVM(BaseVM): self._command = yield from self._build_command() try: - log.info("starting QEMU: {}".format(self._command)) + log.info("Starting QEMU: {}".format(self._command)) self._stdout_file = os.path.join(self.working_dir, "qemu.log") log.info("logging to {}".format(self._stdout_file)) with open(self._stdout_file, "w") as fd: @@ -605,12 +594,12 @@ class QemuVM(BaseVM): stdout=fd, stderr=subprocess.STDOUT, cwd=self.working_dir) - log.info("QEMU VM instance {} started PID={}".format(self._id, self._process.pid)) + log.info('QEMU VM "{}" started PID={}'.format(self._name, self._process.pid)) self._started = True except (OSError, subprocess.SubprocessError) as e: stdout = self.read_stdout() - log.error("could not start QEMU {}: {}\n{}".format(self.qemu_path, e, stdout)) - raise QemuError("could not start QEMU {}: {}\n{}".format(self.qemu_path, e, stdout)) + log.error("Could not start QEMU {}: {}\n{}".format(self.qemu_path, e, stdout)) + raise QemuError("Could not start QEMU {}: {}\n{}".format(self.qemu_path, e, stdout)) self._set_process_priority() if self._cpu_throttling: @@ -624,15 +613,14 @@ class QemuVM(BaseVM): # stop the QEMU process if self.is_running(): - log.info("stopping QEMU VM instance {} PID={}".format(self._id, self._process.pid)) + log.info('Stopping QEMU VM "{}" PID={}'.format(self._name, self._process.pid)) try: self._process.terminate() self._process.wait() except subprocess.TimeoutExpired: self._process.kill() if self._process.returncode is None: - log.warn("QEMU VM instance {} PID={} is still running".format(self._id, - self._process.pid)) + log.warn('QEMU VM "{}" PID={} is still running'.format(self._name, self._process.pid)) self._process = None self._started = False self._stop_cpulimit() @@ -643,9 +631,9 @@ class QemuVM(BaseVM): Executes a command with QEMU monitor when this VM is running. :param command: QEMU monitor command (e.g. info status, stop etc.) - :params expected: An array with the string attended (Default None) + :param expected: An array of expected strings - :returns: result of the command (Match object or None) + :returns: result of the command (matched object or None) """ result = None @@ -680,6 +668,9 @@ class QemuVM(BaseVM): @asyncio.coroutine def close(self): + """ + Closes this QEMU VM. + """ log.debug('QEMU VM "{name}" [{id}] is closing'.format(name=self._name, id=self._id)) yield from self.stop() @@ -690,7 +681,7 @@ class QemuVM(BaseVM): @asyncio.coroutine def _get_vm_status(self): """ - Returns this VM suspend status (running|paused) + Returns this VM suspend status. Status are extracted from: https://github.com/qemu/qemu/blob/master/qapi-schema.json#L152 @@ -749,27 +740,27 @@ class QemuVM(BaseVM): log.info("QEMU VM is not paused to be resumed, current status is {}".format(vm_status)) @asyncio.coroutine - def adapter_add_nio_binding(self, adapter_id, nio): + def adapter_add_nio_binding(self, adapter_number, nio): """ Adds a port NIO binding. - :param adapter_id: adapter ID + :param adapter_number: adapter number :param nio: NIO instance to add to the adapter """ try: - adapter = self._ethernet_adapters[adapter_id] + adapter = self._ethernet_adapters[adapter_number] except IndexError: - raise QemuError("Adapter {adapter_id} doesn't exist on QEMU VM {name}".format(name=self._name, - adapter_id=adapter_id)) + raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name, + adapter_number=adapter_number)) if self.is_running(): # dynamically configure an UDP tunnel on the QEMU VM adapter if nio and isinstance(nio, NIOUDP): if self._legacy_networking: - yield from self._control_vm("host_net_remove {} gns3-{}".format(adapter_id, adapter_id)) - yield from self._control_vm("host_net_add udp vlan={},name=gns3-{},sport={},dport={},daddr={}".format(adapter_id, - adapter_id, + yield from self._control_vm("host_net_remove {} gns3-{}".format(adapter_number, adapter_number)) + yield from self._control_vm("host_net_add udp vlan={},name=gns3-{},sport={},dport={},daddr={}".format(adapter_number, + adapter_number, nio.lport, nio.rport, nio.rhost)) @@ -778,48 +769,48 @@ class QemuVM(BaseVM): # Apparently there is a bug in Qemu... # netdev_add [user|tap|socket|hubport|netmap],id=str[,prop=value][,...] -- add host network device # netdev_del id -- remove host network device - yield from self._control_vm("netdev_del gns3-{}".format(adapter_id)) - yield from self._control_vm("netdev_add socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_id, + yield from self._control_vm("netdev_del gns3-{}".format(adapter_number)) + yield from self._control_vm("netdev_add socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_number, nio.rhost, nio.rport, self._host, nio.lport)) adapter.add_nio(0, nio) - log.info("QEMU VM {name} [id={id}]: {nio} added to adapter {adapter_id}".format(name=self._name, - id=self._id, - nio=nio, - adapter_id=adapter_id)) + log.info('QEMU VM "{name}" [{id}]: {nio} added to adapter {adapter_number}'.format(name=self._name, + id=self._id, + nio=nio, + adapter_number=adapter_number)) @asyncio.coroutine - def adapter_remove_nio_binding(self, adapter_id): + def adapter_remove_nio_binding(self, adapter_number): """ Removes a port NIO binding. - :param adapter_id: adapter ID + :param adapter_number: adapter number :returns: NIO instance """ try: - adapter = self._ethernet_adapters[adapter_id] + adapter = self._ethernet_adapters[adapter_number] except IndexError: - raise QemuError("Adapter {adapter_id} doesn't exist on QEMU VM {name}".format(name=self._name, - adapter_id=adapter_id)) + raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name, + adapter_number=adapter_number)) if self.is_running(): # dynamically disable the QEMU VM adapter - yield from self._control_vm("host_net_remove {} gns3-{}".format(adapter_id, adapter_id)) - yield from self._control_vm("host_net_add user vlan={},name=gns3-{}".format(adapter_id, adapter_id)) + yield from self._control_vm("host_net_remove {} gns3-{}".format(adapter_number, adapter_number)) + yield from self._control_vm("host_net_add user vlan={},name=gns3-{}".format(adapter_number, adapter_number)) nio = adapter.get_nio(0) if isinstance(nio, NIOUDP): self.manager.port_manager.release_udp_port(nio.lport, self._project) adapter.remove_nio(0) - log.info("QEMU VM {name} [id={id}]: {nio} removed from adapter {adapter_id}".format(name=self._name, - id=self._id, - nio=nio, - adapter_id=adapter_id)) + log.info('QEMU VM "{name}" [{id}]: {nio} removed from adapter {adapter_number}'.format(name=self._name, + id=self._id, + nio=nio, + adapter_number=adapter_number)) return nio @property @@ -844,7 +835,7 @@ class QemuVM(BaseVM): with open(self._stdout_file, errors="replace") as file: output = file.read() except OSError as e: - log.warn("could not read {}: {}".format(self._stdout_file, e)) + log.warn("Could not read {}: {}".format(self._stdout_file, e)) return output def is_running(self): @@ -1004,47 +995,48 @@ class QemuVM(BaseVM): return options - def _get_random_mac(self, adapter_id): + def _get_random_mac(self, adapter_number): # TODO: let users specify a base mac address - return "00:00:ab:%02x:%02x:%02d" % (random.randint(0x00, 0xff), random.randint(0x00, 0xff), adapter_id) + return "00:00:ab:%02x:%02x:%02d" % (random.randint(0x00, 0xff), random.randint(0x00, 0xff), adapter_number) def _network_options(self): network_options = [] - adapter_id = 0 + adapter_number = 0 for adapter in self._ethernet_adapters: - mac = self._get_random_mac(adapter_id) + mac = self._get_random_mac(adapter_number) if self._legacy_networking: - network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_id, mac, self._adapter_type)]) + network_options.extend(["-net", "nic,vlan={},macaddr={},model={}".format(adapter_number, mac, self._adapter_type)]) else: - network_options.extend(["-device", "{},mac={},netdev=gns3-{}".format(self._adapter_type, mac, adapter_id)]) + network_options.extend(["-device", "{},mac={},netdev=gns3-{}".format(self._adapter_type, mac, adapter_number)]) nio = adapter.get_nio(0) if nio and isinstance(nio, NIOUDP): if self._legacy_networking: - network_options.extend(["-net", "udp,vlan={},name=gns3-{},sport={},dport={},daddr={}".format(adapter_id, - adapter_id, + network_options.extend(["-net", "udp,vlan={},name=gns3-{},sport={},dport={},daddr={}".format(adapter_number, + adapter_number, nio.lport, nio.rport, nio.rhost)]) else: - network_options.extend(["-netdev", "socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_id, + network_options.extend(["-netdev", "socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_number, nio.rhost, nio.rport, self._host, nio.lport)]) else: if self._legacy_networking: - network_options.extend(["-net", "user,vlan={},name=gns3-{}".format(adapter_id, adapter_id)]) + network_options.extend(["-net", "user,vlan={},name=gns3-{}".format(adapter_number, adapter_number)]) else: - network_options.extend(["-netdev", "user,id=gns3-{}".format(adapter_id)]) - adapter_id += 1 + network_options.extend(["-netdev", "user,id=gns3-{}".format(adapter_number)]) + adapter_number += 1 return network_options def _graphic(self): """ - Add the correct graphic options depending of the OS + Adds the correct graphic options depending of the OS """ + if sys.platform.startswith("win"): return [] if len(os.environ.get("DISPLAY", "")) > 0: @@ -1086,7 +1078,7 @@ class QemuVM(BaseVM): """ if disk_image: - # return the relative path if disks images are in the images_path directory + # return the relative path if the disk image is in the images_path directory server_config = self.manager.config.get_section_config("Server") relative_image = os.path.join(os.path.expanduser(server_config.get("images_path", "~/GNS3/images")), "QEMU", disk_image) if os.path.exists(relative_image): diff --git a/gns3server/modules/virtualbox/virtualbox_error.py b/gns3server/modules/virtualbox/virtualbox_error.py index df481c21..3d6b58a1 100644 --- a/gns3server/modules/virtualbox/virtualbox_error.py +++ b/gns3server/modules/virtualbox/virtualbox_error.py @@ -16,7 +16,7 @@ # along with this program. If not, see . """ -Custom exceptions for VirtualBox module. +Custom exceptions for the VirtualBox module. """ from ..vm_error import VMError diff --git a/gns3server/modules/vpcs/__init__.py b/gns3server/modules/vpcs/__init__.py index f79e2b8d..eb6cbe11 100644 --- a/gns3server/modules/vpcs/__init__.py +++ b/gns3server/modules/vpcs/__init__.py @@ -28,26 +28,38 @@ from .vpcs_vm import VPCSVM class VPCS(BaseManager): + _VM_CLASS = VPCSVM def __init__(self): + super().__init__() self._free_mac_ids = {} self._used_mac_ids = {} @asyncio.coroutine def create_vm(self, *args, **kwargs): + """ + Creates a new VPCS VM. + + :returns: VPCSVM instance + """ vm = yield from super().create_vm(*args, **kwargs) self._free_mac_ids.setdefault(vm.project.id, list(range(0, 255))) try: self._used_mac_ids[vm.id] = self._free_mac_ids[vm.project.id].pop(0) except IndexError: - raise VPCSError("No mac address available") + raise VPCSError("Cannot create a new VPCS VM (limit of 255 VMs reached on this host)") return vm @asyncio.coroutine def close_vm(self, vm_id, *args, **kwargs): + """ + Closes a VPCS VM. + + :returns: VPCSVM instance + """ vm = self.get_vm(vm_id) i = self._used_mac_ids[vm_id] @@ -59,10 +71,11 @@ class VPCS(BaseManager): def get_mac_id(self, vm_id): """ - Get an unique VPCS mac id + Get an unique VPCS MAC id (offset) - :param vm_id: ID of the VPCS VM - :returns: VPCS MAC id + :param vm_id: VPCS VM identifier + + :returns: VPCS MAC identifier """ return self._used_mac_ids.get(vm_id, 1) diff --git a/gns3server/modules/vpcs/vpcs_error.py b/gns3server/modules/vpcs/vpcs_error.py index b8e99d4b..7f014eff 100644 --- a/gns3server/modules/vpcs/vpcs_error.py +++ b/gns3server/modules/vpcs/vpcs_error.py @@ -16,7 +16,7 @@ # along with this program. If not, see . """ -Custom exceptions for VPCS module. +Custom exceptions for the VPCS module. """ from ..vm_error import VMError diff --git a/gns3server/modules/vpcs/vpcs_vm.py b/gns3server/modules/vpcs/vpcs_vm.py index a19e4647..4475b97c 100644 --- a/gns3server/modules/vpcs/vpcs_vm.py +++ b/gns3server/modules/vpcs/vpcs_vm.py @@ -17,7 +17,7 @@ """ VPCS VM management (creates command line, processes, files etc.) in -order to run an VPCS instance. +order to run a VPCS VM. """ import os @@ -45,20 +45,19 @@ class VPCSVM(BaseVM): module_name = 'vpcs' """ - VPCS vm implementation. + VPCS VM implementation. - :param name: The name of this VM - :param vm_id: VPCS instance identifier + :param name: VPCS VM name + :param vm_id: VPCS VM identifier :param project: Project instance - :param manager: Parent VM Manager + :param manager: Manager instance :param console: TCP console port - :param startup_script: Content of vpcs 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): super().__init__(name, vm_id, project, manager, console=console) - self._command = [] self._process = None self._vpcs_stdout_file = "" @@ -71,8 +70,11 @@ class VPCSVM(BaseVM): @asyncio.coroutine def close(self): + """ + Closes this VPCS VM. + """ - log.debug("VPCS {name} [{id}] is closing".format(name=self._name, id=self._id)) + log.debug('VPCS "{name}" [{id}] is closing'.format(name=self._name, id=self._id)) if self._console: self._manager.port_manager.release_tcp_port(self._console, self._project) self._console = None @@ -87,8 +89,9 @@ class VPCSVM(BaseVM): @asyncio.coroutine def _check_requirements(self): """ - Check if VPCS is available with the correct version + Check if VPCS is available with the correct version. """ + path = self.vpcs_path if not path: raise VPCSError("No path to a VPCS executable has been set") @@ -140,7 +143,7 @@ class VPCSVM(BaseVM): @BaseVM.name.setter def name(self, new_name): """ - Sets the name of this VPCS vm. + Sets the name of this VPCS VM. :param new_name: name """ @@ -154,7 +157,9 @@ class VPCSVM(BaseVM): @property def startup_script(self): - """Return the content of the current startup script""" + """ + Returns the content of the current startup script + """ script_file = self.script_file if script_file is None: @@ -164,14 +169,14 @@ class VPCSVM(BaseVM): with open(script_file) as f: return f.read() except OSError as e: - raise VPCSError("Can't read VPCS startup file '{}'".format(script_file)) + raise VPCSError('Cannot read the startup script file "{}": {}'.format(script_file, e)) @startup_script.setter def startup_script(self, startup_script): """ - Update the startup script + Updates the startup script. - :param startup_script The content of the vpcs startup script + :param startup_script: content of the startup script """ try: @@ -183,7 +188,7 @@ class VPCSVM(BaseVM): startup_script = startup_script.replace("%h", self._name) f.write(startup_script) except OSError as e: - raise VPCSError("Can't write VPCS startup file '{}'".format(self.script_file)) + raise VPCSError('Cannot write the startup script file "{}": {}'.format(self.script_file, e)) @asyncio.coroutine def _check_vpcs_version(self): @@ -209,7 +214,6 @@ class VPCSVM(BaseVM): """ yield from self._check_requirements() - if not self.is_running(): if not self._ethernet_adapter.get_nio(0): raise VPCSError("This VPCS instance must be connected in order to start") @@ -256,14 +260,16 @@ class VPCSVM(BaseVM): @asyncio.coroutine def reload(self): """ - Reload the VPCS process. (Stop / Start) + Reloads the VPCS process (stop & start). """ yield from self.stop() yield from self.start() def _terminate_process(self): - """Terminate the process if running""" + """ + Terminate the process if running + """ log.info("Stopping VPCS instance {} PID={}".format(self.name, self._process.pid)) if sys.platform.startswith("win32"): @@ -271,7 +277,7 @@ class VPCSVM(BaseVM): else: try: self._process.terminate() - # Sometime the process can already be dead when we garbage collect + # Sometime the process may already be dead when we garbage collect except ProcessLookupError: pass @@ -280,13 +286,14 @@ class VPCSVM(BaseVM): Reads the standard output of the VPCS process. Only use when the process has been stopped or has crashed. """ + output = "" if self._vpcs_stdout_file: try: with open(self._vpcs_stdout_file, errors="replace") as file: output = file.read() except OSError as e: - log.warn("could not read {}: {}".format(self._vpcs_stdout_file, e)) + log.warn("Could not read {}: {}".format(self._vpcs_stdout_file, e)) return output def is_running(self): @@ -313,10 +320,10 @@ class VPCSVM(BaseVM): port_number=port_number)) self._ethernet_adapter.add_nio(port_number, nio) - log.info("VPCS {name} [{id}]: {nio} added to port {port_number}".format(name=self._name, - id=self.id, - nio=nio, - port_number=port_number)) + log.info('VPCS "{name}" [{id}]: {nio} added to port {port_number}'.format(name=self._name, + id=self.id, + nio=nio, + port_number=port_number)) return nio def port_remove_nio_binding(self, port_number): @@ -337,10 +344,10 @@ class VPCSVM(BaseVM): self.manager.port_manager.release_udp_port(nio.lport, self._project) self._ethernet_adapter.remove_nio(port_number) - log.info("VPCS {name} [{id}]: {nio} removed from port {port_number}".format(name=self._name, - id=self.id, - nio=nio, - port_number=port_number)) + log.info('VPCS "{name}" [{id}]: {nio} removed from port {port_number}'.format(name=self._name, + id=self.id, + nio=nio, + port_number=port_number)) return nio def _build_command(self): @@ -406,12 +413,12 @@ class VPCSVM(BaseVM): @property def script_file(self): """ - Returns the script-file for this VPCS instance. + Returns the startup script file for this VPCS VM. - :returns: path to script-file + :returns: path to startup script file """ - # If the default VPCS file exist we use it + # use the default VPCS file if it exists path = os.path.join(self.working_dir, 'startup.vpc') if os.path.exists(path): return path diff --git a/gns3server/utils/asyncio.py b/gns3server/utils/asyncio.py index a977b717..c84e0fbe 100644 --- a/gns3server/utils/asyncio.py +++ b/gns3server/utils/asyncio.py @@ -17,7 +17,6 @@ import asyncio -import shutil @asyncio.coroutine