mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-01 04:38:12 +00:00
Some spring cleaning.
This commit is contained in:
parent
1c4202187a
commit
7d7972afb3
@ -25,7 +25,8 @@ class EthernetAdapter(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, interfaces=1):
|
def __init__(self, interfaces=1):
|
||||||
Adapter.__init__(self, interfaces=interfaces)
|
|
||||||
|
super().__init__(interfaces)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class SerialAdapter(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, interfaces=1):
|
def __init__(self, interfaces=1):
|
||||||
Adapter.__init__(self, interfaces=interfaces)
|
|
||||||
|
super().__init__(interfaces)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ from .nios.nio_generic_ethernet import NIOGenericEthernet
|
|||||||
class BaseManager:
|
class BaseManager:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Base class for all Manager.
|
Base class for all Manager classes.
|
||||||
Responsible of management of a VM pool
|
Responsible of management of a VM pool of the same type.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_convert_lock = None
|
_convert_lock = None
|
||||||
|
@ -54,19 +54,17 @@ class BaseVM:
|
|||||||
else:
|
else:
|
||||||
self._console = self._manager.port_manager.get_free_tcp_port(self._project)
|
self._console = self._manager.port_manager.get_free_tcp_port(self._project)
|
||||||
|
|
||||||
log.debug("{module}: {name} [{id}] initialized. Console port {console}".format(
|
log.debug("{module}: {name} [{id}] initialized. Console port {console}".format(module=self.manager.module_name,
|
||||||
module=self.manager.module_name,
|
|
||||||
name=self.name,
|
name=self.name,
|
||||||
id=self.id,
|
id=self.id,
|
||||||
console=self._console
|
console=self._console))
|
||||||
))
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
|
|
||||||
self.close()
|
self.close()
|
||||||
if self._temporary_directory is not None:
|
if self._temporary_directory is not None:
|
||||||
if os.path.exists(self._temporary_directory):
|
if os.path.exists(self._temporary_directory):
|
||||||
shutil.rmtree(self._temporary_directory)
|
shutil.rmtree(self._temporary_directory, ignore_errors=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def project(self):
|
def project(self):
|
||||||
@ -195,7 +193,7 @@ class BaseVM:
|
|||||||
@console.setter
|
@console.setter
|
||||||
def console(self, console):
|
def console(self, console):
|
||||||
"""
|
"""
|
||||||
Change console port
|
Changes the console port
|
||||||
|
|
||||||
:params console: Console port (integer)
|
:params console: Console port (integer)
|
||||||
"""
|
"""
|
||||||
@ -205,8 +203,7 @@ class BaseVM:
|
|||||||
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)
|
||||||
self._console = self._manager.port_manager.reserve_tcp_port(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(
|
log.info("{module}: '{name}' [{id}]: console port set to {port}".format(module=self.manager.module_name,
|
||||||
module=self.manager.module_name,
|
|
||||||
name=self.name,
|
name=self.name,
|
||||||
id=self.id,
|
id=self.id,
|
||||||
port=console))
|
port=console))
|
||||||
|
@ -25,7 +25,8 @@ class C1700_MB_1FE(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1, wics=2)
|
|
||||||
|
super().__init__(interfaces=1, wics=2)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -26,7 +26,8 @@ class C1700_MB_WIC1(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=0, wics=2)
|
|
||||||
|
super().__init__(interfaces=0, wics=2)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class C2600_MB_1E(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1, wics=3)
|
|
||||||
|
super().__init__(interfaces=1, wics=3)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class C2600_MB_1FE(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1, wics=3)
|
|
||||||
|
super().__init__(interfaces=1, wics=3)
|
||||||
self._interfaces = 1
|
self._interfaces = 1
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -25,7 +25,8 @@ class C2600_MB_2E(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=2, wics=3)
|
|
||||||
|
super().__init__(interfaces=2, wics=3)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class C2600_MB_2FE(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=2, wics=3)
|
|
||||||
|
super().__init__(interfaces=2, wics=3)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class C7200_IO_2FE(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=2)
|
|
||||||
|
super().__init__(interfaces=2)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class C7200_IO_FE(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1)
|
|
||||||
|
super().__init__(interfaces=1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class C7200_IO_GE_E(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1)
|
|
||||||
|
super().__init__(interfaces=1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ from .adapter import Adapter
|
|||||||
class GT96100_FE(Adapter):
|
class GT96100_FE(Adapter):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=2, wics=3)
|
|
||||||
|
super().__init__(interfaces=2, wics=3)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class Leopard_2FE(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=2)
|
|
||||||
|
super().__init__(interfaces=2)
|
||||||
self._interfaces = 2
|
self._interfaces = 2
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -25,7 +25,8 @@ class NM_16ESW(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=16)
|
|
||||||
|
super().__init__(interfaces=16)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class NM_1E(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1)
|
|
||||||
|
super().__init__(interfaces=1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class NM_1FE_TX(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1)
|
|
||||||
|
super().__init__(interfaces=1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class NM_4E(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=4)
|
|
||||||
|
super().__init__(interfaces=4)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class NM_4T(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=4)
|
|
||||||
|
super().__init__(interfaces=4)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_2FE_TX(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=2)
|
|
||||||
|
super().__init__(interfaces=2)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_4E(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=4)
|
|
||||||
|
super().__init__(interfaces=4)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_4T(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=4)
|
|
||||||
|
super().__init__(interfaces=4)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_8E(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=8)
|
|
||||||
|
super().__init__(interfaces=8)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_8T(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=8)
|
|
||||||
|
super().__init__(interfaces=8)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_A1(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1)
|
|
||||||
|
super().__init__(interfaces=1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_FE_TX(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1)
|
|
||||||
|
super().__init__(interfaces=1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_GE(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1)
|
|
||||||
|
super().__init__(interfaces=1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@ class PA_POS_OC3(Adapter):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Adapter.__init__(self, interfaces=1)
|
|
||||||
|
super().__init__(interfaces=1)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
|
@ -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/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Custom exceptions for Dynamips module.
|
Custom exceptions for the Dynamips module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ..vm_error import VMError
|
from ..vm_error import VMError
|
||||||
|
@ -47,7 +47,7 @@ class Hypervisor(DynamipsHypervisor):
|
|||||||
|
|
||||||
def __init__(self, path, working_dir, host, port, console_host):
|
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
|
# create an unique ID
|
||||||
self._id = Hypervisor._instance_count
|
self._id = Hypervisor._instance_count
|
||||||
|
@ -42,7 +42,7 @@ class NIOFIFO(NIO):
|
|||||||
nio_id = NIOFIFO._instance_count
|
nio_id = NIOFIFO._instance_count
|
||||||
NIOFIFO._instance_count += 1
|
NIOFIFO._instance_count += 1
|
||||||
name = 'nio_fifo' + str(nio_id)
|
name = 'nio_fifo' + str(nio_id)
|
||||||
NIO.__init__(name, self, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -44,7 +44,7 @@ class NIOGenericEthernet(NIO):
|
|||||||
NIOGenericEthernet._instance_count += 1
|
NIOGenericEthernet._instance_count += 1
|
||||||
name = 'nio_gen_eth' + str(nio_id)
|
name = 'nio_gen_eth' + str(nio_id)
|
||||||
self._ethernet_device = ethernet_device
|
self._ethernet_device = ethernet_device
|
||||||
NIO.__init__(self, name, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -44,7 +44,7 @@ class NIOLinuxEthernet(NIO):
|
|||||||
NIOLinuxEthernet._instance_count += 1
|
NIOLinuxEthernet._instance_count += 1
|
||||||
name = 'nio_linux_eth' + str(nio_id)
|
name = 'nio_linux_eth' + str(nio_id)
|
||||||
self._ethernet_device = ethernet_device
|
self._ethernet_device = ethernet_device
|
||||||
NIO.__init__(self, name, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -47,7 +47,7 @@ class NIOMcast(NIO):
|
|||||||
self._group = group
|
self._group = group
|
||||||
self._port = port
|
self._port = port
|
||||||
self._ttl = 1 # default TTL
|
self._ttl = 1 # default TTL
|
||||||
NIO.__init__(self, name, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -42,7 +42,7 @@ class NIONull(NIO):
|
|||||||
nio_id = NIONull._instance_count
|
nio_id = NIONull._instance_count
|
||||||
NIONull._instance_count += 1
|
NIONull._instance_count += 1
|
||||||
name = 'nio_null' + str(nio_id)
|
name = 'nio_null' + str(nio_id)
|
||||||
NIO.__init__(self, name, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -44,7 +44,7 @@ class NIOTAP(NIO):
|
|||||||
NIOTAP._instance_count += 1
|
NIOTAP._instance_count += 1
|
||||||
name = 'nio_tap' + str(nio_id)
|
name = 'nio_tap' + str(nio_id)
|
||||||
self._tap_device = tap_device
|
self._tap_device = tap_device
|
||||||
NIO.__init__(self, name, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -48,7 +48,7 @@ class NIOUDP(NIO):
|
|||||||
self._lport = lport
|
self._lport = lport
|
||||||
self._rhost = rhost
|
self._rhost = rhost
|
||||||
self._rport = rport
|
self._rport = rport
|
||||||
NIO.__init__(self, name, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -46,7 +46,7 @@ class NIOUNIX(NIO):
|
|||||||
name = 'nio_unix' + str(nio_id)
|
name = 'nio_unix' + str(nio_id)
|
||||||
self._local_file = local_file
|
self._local_file = local_file
|
||||||
self._remote_file = remote_file
|
self._remote_file = remote_file
|
||||||
NIO.__init__(self, name, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -46,7 +46,7 @@ class NIOVDE(NIO):
|
|||||||
name = 'nio_vde' + str(nio_id)
|
name = 'nio_vde' + str(nio_id)
|
||||||
self._control_file = control_file
|
self._control_file = control_file
|
||||||
self._local_file = local_file
|
self._local_file = local_file
|
||||||
NIO.__init__(self, name, hypervisor)
|
super().__init__(name, hypervisor)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
|
@ -47,7 +47,8 @@ class C1700(Router):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="1720"):
|
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)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 64
|
self._ram = 64
|
||||||
|
@ -62,7 +62,8 @@ class C2600(Router):
|
|||||||
"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, 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)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 64
|
self._ram = 64
|
||||||
|
@ -44,7 +44,8 @@ class C2691(Router):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
|
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)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 128
|
self._ram = 128
|
||||||
|
@ -45,7 +45,8 @@ class C3600(Router):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis="3640"):
|
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)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 128
|
self._ram = 128
|
||||||
|
@ -44,7 +44,8 @@ class C3725(Router):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
|
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)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 128
|
self._ram = 128
|
||||||
|
@ -44,7 +44,8 @@ class C3745(Router):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, vm_id, project, manager, dynamips_id, console=None, aux=None, chassis=None):
|
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)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 128
|
self._ram = 128
|
||||||
|
@ -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):
|
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)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 256
|
self._ram = 256
|
||||||
|
@ -43,7 +43,7 @@ class EthernetHub(Bridge):
|
|||||||
|
|
||||||
def __init__(self, name, device_id, project, manager, hypervisor=None):
|
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 = {}
|
self._mappings = {}
|
||||||
|
|
||||||
def __json__(self):
|
def __json__(self):
|
||||||
|
@ -28,25 +28,37 @@ from .iou_vm import IOUVM
|
|||||||
|
|
||||||
|
|
||||||
class IOU(BaseManager):
|
class IOU(BaseManager):
|
||||||
|
|
||||||
_VM_CLASS = IOUVM
|
_VM_CLASS = IOUVM
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._free_application_ids = list(range(1, 512))
|
self._free_application_ids = list(range(1, 512))
|
||||||
self._used_application_ids = {}
|
self._used_application_ids = {}
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create_vm(self, *args, **kwargs):
|
def create_vm(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Creates a new IOU VM.
|
||||||
|
|
||||||
|
:returns: IOUVM instance
|
||||||
|
"""
|
||||||
|
|
||||||
vm = yield from super().create_vm(*args, **kwargs)
|
vm = yield from super().create_vm(*args, **kwargs)
|
||||||
try:
|
try:
|
||||||
self._used_application_ids[vm.id] = self._free_application_ids.pop(0)
|
self._used_application_ids[vm.id] = self._free_application_ids.pop(0)
|
||||||
except IndexError:
|
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
|
return vm
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def close_vm(self, vm_id, *args, **kwargs):
|
def close_vm(self, vm_id, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Closes an IOU VM.
|
||||||
|
|
||||||
|
:returns: IOUVM instance
|
||||||
|
"""
|
||||||
|
|
||||||
vm = self.get_vm(vm_id)
|
vm = self.get_vm(vm_id)
|
||||||
if vm_id in self._used_application_ids:
|
if vm_id in self._used_application_ids:
|
||||||
@ -58,10 +70,11 @@ class IOU(BaseManager):
|
|||||||
|
|
||||||
def get_application_id(self, vm_id):
|
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
|
:param vm_id: IOU VM identifier
|
||||||
:returns: IOU MAC id
|
|
||||||
|
:returns: IOU application identifier
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._used_application_ids.get(vm_id, 1)
|
return self._used_application_ids.get(vm_id, 1)
|
||||||
|
@ -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/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Custom exceptions for IOU module.
|
Custom exceptions for the IOU module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ..vm_error import VMError
|
from ..vm_error import VMError
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
IOU VM management (creates command line, processes, files etc.) in
|
IOU VM management (creates command line, processes, files etc.) in
|
||||||
order to run an IOU instance.
|
order to run an IOU VM.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -54,20 +54,20 @@ class IOUVM(BaseVM):
|
|||||||
module_name = 'iou'
|
module_name = 'iou'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
IOU vm implementation.
|
IOU VM implementation.
|
||||||
|
|
||||||
:param name: name of this IOU vm
|
:param name: IOU VM name
|
||||||
:param vm_id: IOU instance identifier
|
:param vm_id: IOU VM identifier
|
||||||
:param project: Project instance
|
:param project: Project instance
|
||||||
:param manager: parent VM Manager
|
:param manager: Manager instance
|
||||||
:param console: TCP console port
|
:param console: TCP console port
|
||||||
:params ethernet_adapters: Number of ethernet adapters
|
:params ethernet_adapters: number of ethernet adapters
|
||||||
:params serial_adapters: Number of serial adapters
|
:params serial_adapters: number of serial adapters
|
||||||
:params ram: Ram MB
|
:params ram: amount of RAM in MB
|
||||||
:params nvram: Nvram KB
|
:params nvram: amount of NVRAM in KB
|
||||||
:params l1_keepalives: Always up ethernet interface:
|
:params l1_keepalives: always keep the Ethernet interfaces up
|
||||||
:params initial_config: Content of the initial configuration file
|
: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 iourc_content: content of the iourc file if no licence is installed on the machine
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, vm_id, project, manager,
|
def __init__(self, name, vm_id, project, manager,
|
||||||
@ -108,6 +108,9 @@ class IOUVM(BaseVM):
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def close(self):
|
def close(self):
|
||||||
|
"""
|
||||||
|
Closes this IOU VM.
|
||||||
|
"""
|
||||||
|
|
||||||
log.debug('IOU "{name}" [{id}] is closing'.format(name=self._name, id=self._id))
|
log.debug('IOU "{name}" [{id}] is closing'.format(name=self._name, id=self._id))
|
||||||
|
|
||||||
@ -126,16 +129,20 @@ class IOUVM(BaseVM):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
"""Path of the iou binary"""
|
"""
|
||||||
|
Path of the IOU executable.
|
||||||
|
|
||||||
|
:returns: path to the IOU image executable
|
||||||
|
"""
|
||||||
|
|
||||||
return self._path
|
return self._path
|
||||||
|
|
||||||
@path.setter
|
@path.setter
|
||||||
def path(self, path):
|
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):
|
if not os.path.isabs(path):
|
||||||
@ -171,6 +178,7 @@ class IOUVM(BaseVM):
|
|||||||
def use_default_iou_values(self):
|
def use_default_iou_values(self):
|
||||||
"""
|
"""
|
||||||
Returns if this device uses the default IOU image values.
|
Returns if this device uses the default IOU image values.
|
||||||
|
|
||||||
:returns: boolean
|
:returns: boolean
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -180,28 +188,30 @@ class IOUVM(BaseVM):
|
|||||||
def use_default_iou_values(self, state):
|
def use_default_iou_values(self, state):
|
||||||
"""
|
"""
|
||||||
Sets if this device uses the default IOU image values.
|
Sets if this device uses the default IOU image values.
|
||||||
|
|
||||||
:param state: boolean
|
:param state: boolean
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._use_default_iou_values = state
|
self._use_default_iou_values = state
|
||||||
if 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:
|
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):
|
def _check_requirements(self):
|
||||||
"""
|
"""
|
||||||
Check if IOUYAP is available
|
Checks if IOUYAP executable is available.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
path = self.iouyap_path
|
path = self.iouyap_path
|
||||||
if not 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):
|
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):
|
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):
|
def __json__(self):
|
||||||
|
|
||||||
@ -243,7 +253,7 @@ class IOUVM(BaseVM):
|
|||||||
@property
|
@property
|
||||||
def iourc_path(self):
|
def iourc_path(self):
|
||||||
"""
|
"""
|
||||||
Returns the IOURC path.
|
Returns the IOURC file path.
|
||||||
|
|
||||||
:returns: path to IOURC
|
:returns: path to IOURC
|
||||||
"""
|
"""
|
||||||
@ -267,8 +277,9 @@ class IOUVM(BaseVM):
|
|||||||
@property
|
@property
|
||||||
def ram(self):
|
def ram(self):
|
||||||
"""
|
"""
|
||||||
Returns the amount of RAM allocated to this IOU instance.
|
Returns the amount of RAM allocated to this IOU VM.
|
||||||
:returns: amount of RAM in Mbytes (integer)
|
|
||||||
|
:returns: amount of RAM in MBytes (integer)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._ram
|
return self._ram
|
||||||
@ -277,13 +288,14 @@ class IOUVM(BaseVM):
|
|||||||
def ram(self, ram):
|
def ram(self, ram):
|
||||||
"""
|
"""
|
||||||
Sets amount of RAM allocated to this IOU instance.
|
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:
|
if self._ram == ram:
|
||||||
return
|
return
|
||||||
|
|
||||||
log.info("IOU {name} [id={id}]: RAM updated from {old_ram}MB to {new_ram}MB".format(name=self._name,
|
log.info('IOU "{name}" [{id}]: RAM updated from {old_ram}MB to {new_ram}MB'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
old_ram=self._ram,
|
old_ram=self._ram,
|
||||||
new_ram=ram))
|
new_ram=ram))
|
||||||
@ -294,7 +306,8 @@ class IOUVM(BaseVM):
|
|||||||
def nvram(self):
|
def nvram(self):
|
||||||
"""
|
"""
|
||||||
Returns the mount of NVRAM allocated to this IOU instance.
|
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
|
return self._nvram
|
||||||
@ -303,13 +316,14 @@ class IOUVM(BaseVM):
|
|||||||
def nvram(self, nvram):
|
def nvram(self, nvram):
|
||||||
"""
|
"""
|
||||||
Sets amount of NVRAM allocated to this IOU instance.
|
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:
|
if self._nvram == nvram:
|
||||||
return
|
return
|
||||||
|
|
||||||
log.info("IOU {name} [id={id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB".format(name=self._name,
|
log.info('IOU "{name}" [{id}]: NVRAM updated from {old_nvram}KB to {new_nvram}KB'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
old_nvram=self._nvram,
|
old_nvram=self._nvram,
|
||||||
new_nvram=nvram))
|
new_nvram=nvram))
|
||||||
@ -318,7 +332,7 @@ class IOUVM(BaseVM):
|
|||||||
@BaseVM.name.setter
|
@BaseVM.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.
|
||||||
|
|
||||||
:param new_name: name
|
:param new_name: name
|
||||||
"""
|
"""
|
||||||
@ -332,10 +346,12 @@ class IOUVM(BaseVM):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def application_id(self):
|
def application_id(self):
|
||||||
|
|
||||||
return self._manager.get_application_id(self.id)
|
return self._manager.get_application_id(self.id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def iourc_content(self):
|
def iourc_content(self):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(self.temporary_directory, "iourc")) as f:
|
with open(os.path.join(self.temporary_directory, "iourc")) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
@ -344,13 +360,14 @@ class IOUVM(BaseVM):
|
|||||||
|
|
||||||
@iourc_content.setter
|
@iourc_content.setter
|
||||||
def iourc_content(self, value):
|
def iourc_content(self, value):
|
||||||
|
|
||||||
if value is not None:
|
if value is not None:
|
||||||
path = os.path.join(self.temporary_directory, "iourc")
|
path = os.path.join(self.temporary_directory, "iourc")
|
||||||
try:
|
try:
|
||||||
with open(path, "w+") as f:
|
with open(path, "w+") as f:
|
||||||
f.write(value)
|
f.write(value)
|
||||||
except OSError as e:
|
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
|
@asyncio.coroutine
|
||||||
def _library_check(self):
|
def _library_check(self):
|
||||||
@ -468,11 +485,11 @@ class IOUVM(BaseVM):
|
|||||||
log.info("IOU instance {} started PID={}".format(self._id, self._iou_process.pid))
|
log.info("IOU instance {} started PID={}".format(self._id, self._iou_process.pid))
|
||||||
self._started = True
|
self._started = True
|
||||||
except FileNotFoundError as e:
|
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:
|
except (OSError, subprocess.SubprocessError) as e:
|
||||||
iou_stdout = self.read_iou_stdout()
|
iou_stdout = self.read_iou_stdout()
|
||||||
log.error("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))
|
raise IOUError("Could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout))
|
||||||
|
|
||||||
# start console support
|
# start console support
|
||||||
self._start_ioucon()
|
self._start_ioucon()
|
||||||
@ -481,7 +498,7 @@ class IOUVM(BaseVM):
|
|||||||
|
|
||||||
def _rename_nvram_file(self):
|
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))
|
destination = os.path.join(self.working_dir, "nvram_{:05d}".format(self.application_id))
|
||||||
@ -494,7 +511,7 @@ class IOUVM(BaseVM):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _start_iouyap(self):
|
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:
|
try:
|
||||||
@ -512,7 +529,7 @@ class IOUVM(BaseVM):
|
|||||||
log.info("iouyap started PID={}".format(self._iouyap_process.pid))
|
log.info("iouyap started PID={}".format(self._iouyap_process.pid))
|
||||||
except (OSError, subprocess.SubprocessError) as e:
|
except (OSError, subprocess.SubprocessError) as e:
|
||||||
iouyap_stdout = self.read_iouyap_stdout()
|
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))
|
raise IOUError("Could not start iouyap: {}\n{}".format(e, iouyap_stdout))
|
||||||
|
|
||||||
def _update_iouyap_config(self):
|
def _update_iouyap_config(self):
|
||||||
@ -614,29 +631,33 @@ class IOUVM(BaseVM):
|
|||||||
self._started = False
|
self._started = False
|
||||||
|
|
||||||
def _terminate_process_iouyap(self):
|
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:
|
try:
|
||||||
self._iouyap_process.terminate()
|
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:
|
except ProcessLookupError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _terminate_process_iou(self):
|
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:
|
try:
|
||||||
self._iou_process.terminate()
|
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:
|
except ProcessLookupError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def reload(self):
|
def reload(self):
|
||||||
"""
|
"""
|
||||||
Reload the IOU process. (Stop / Start)
|
Reloads the IOU process (stop & start).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self.stop()
|
yield from self.stop()
|
||||||
@ -688,6 +709,7 @@ class IOUVM(BaseVM):
|
|||||||
"""
|
"""
|
||||||
Command to start the IOU process.
|
Command to start the IOU process.
|
||||||
(to be passed to subprocess.Popen())
|
(to be passed to subprocess.Popen())
|
||||||
|
|
||||||
IOU command line:
|
IOU command line:
|
||||||
Usage: <image> [options] <application id>
|
Usage: <image> [options] <application id>
|
||||||
<image>: unix-js-m | unix-is-m | unix-i-m | ...
|
<image>: unix-js-m | unix-is-m | unix-i-m | ...
|
||||||
@ -777,7 +799,8 @@ class IOUVM(BaseVM):
|
|||||||
@property
|
@property
|
||||||
def ethernet_adapters(self):
|
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
|
:returns: number of adapters
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -786,7 +809,8 @@ class IOUVM(BaseVM):
|
|||||||
@ethernet_adapters.setter
|
@ethernet_adapters.setter
|
||||||
def ethernet_adapters(self, ethernet_adapters):
|
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
|
:param ethernet_adapters: number of adapters
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -794,7 +818,7 @@ class IOUVM(BaseVM):
|
|||||||
for _ in range(0, ethernet_adapters):
|
for _ in range(0, ethernet_adapters):
|
||||||
self._ethernet_adapters.append(EthernetAdapter(interfaces=4))
|
self._ethernet_adapters.append(EthernetAdapter(interfaces=4))
|
||||||
|
|
||||||
log.info("IOU {name} [id={id}]: number of Ethernet adapters changed to {adapters}".format(name=self._name,
|
log.info('IOU "{name}" [{id}]: number of Ethernet adapters changed to {adapters}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
adapters=len(self._ethernet_adapters)))
|
adapters=len(self._ethernet_adapters)))
|
||||||
|
|
||||||
@ -803,7 +827,8 @@ class IOUVM(BaseVM):
|
|||||||
@property
|
@property
|
||||||
def serial_adapters(self):
|
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
|
:returns: number of adapters
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -812,7 +837,8 @@ class IOUVM(BaseVM):
|
|||||||
@serial_adapters.setter
|
@serial_adapters.setter
|
||||||
def serial_adapters(self, serial_adapters):
|
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
|
:param serial_adapters: number of adapters
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -820,7 +846,7 @@ class IOUVM(BaseVM):
|
|||||||
for _ in range(0, serial_adapters):
|
for _ in range(0, serial_adapters):
|
||||||
self._serial_adapters.append(SerialAdapter(interfaces=4))
|
self._serial_adapters.append(SerialAdapter(interfaces=4))
|
||||||
|
|
||||||
log.info("IOU {name} [id={id}]: number of Serial adapters changed to {adapters}".format(name=self._name,
|
log.info('IOU "{name}" [{id}]: number of Serial adapters changed to {adapters}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
adapters=len(self._serial_adapters)))
|
adapters=len(self._serial_adapters)))
|
||||||
|
|
||||||
@ -829,23 +855,24 @@ class IOUVM(BaseVM):
|
|||||||
def adapter_add_nio_binding(self, adapter_number, port_number, nio):
|
def adapter_add_nio_binding(self, adapter_number, port_number, nio):
|
||||||
"""
|
"""
|
||||||
Adds a adapter NIO binding.
|
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
|
:param nio: NIO instance to add to the adapter/port
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._adapters[adapter_number]
|
adapter = self._adapters[adapter_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise IOUError("Adapter {adapter_number} doesn't exist on IOU {name}".format(name=self._name,
|
raise IOUError('Adapter {adapter_number} does not exist for IOU "{name}"'.format(name=self._name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
if not adapter.port_exists(port_number):
|
if not adapter.port_exists(port_number):
|
||||||
raise IOUError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter,
|
raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
adapter.add_nio(port_number, nio)
|
adapter.add_nio(port_number, nio)
|
||||||
log.info("IOU {name} [id={id}]: {nio} added to {adapter_number}/{port_number}".format(name=self._name,
|
log.info('IOU "{name}" [{id}]: {nio} added to {adapter_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
adapter_number=adapter_number,
|
adapter_number=adapter_number,
|
||||||
@ -856,27 +883,28 @@ class IOUVM(BaseVM):
|
|||||||
|
|
||||||
def adapter_remove_nio_binding(self, adapter_number, port_number):
|
def adapter_remove_nio_binding(self, adapter_number, port_number):
|
||||||
"""
|
"""
|
||||||
Removes a adapter NIO binding.
|
Removes an adapter NIO binding.
|
||||||
:param adapter_number: adapter ID
|
|
||||||
:param port_number: port ID
|
:param adapter_number: adapter number
|
||||||
|
:param port_number: port number
|
||||||
:returns: NIO instance
|
:returns: NIO instance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._adapters[adapter_number]
|
adapter = self._adapters[adapter_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise IOUError("Adapter {adapter_number} doesn't exist on IOU {name}".format(name=self._name,
|
raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
if not adapter.port_exists(port_number):
|
if not adapter.port_exists(port_number):
|
||||||
raise IOUError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter,
|
raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
nio = adapter.get_nio(port_number)
|
nio = adapter.get_nio(port_number)
|
||||||
if isinstance(nio, NIOUDP):
|
if isinstance(nio, NIOUDP):
|
||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
adapter.remove_nio(port_number)
|
adapter.remove_nio(port_number)
|
||||||
log.info("IOU {name} [id={id}]: {nio} removed from {adapter_number}/{port_number}".format(name=self._name,
|
log.info('IOU "{name}" [{id}]: {nio} removed from {adapter_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
adapter_number=adapter_number,
|
adapter_number=adapter_number,
|
||||||
@ -891,6 +919,7 @@ class IOUVM(BaseVM):
|
|||||||
def l1_keepalives(self):
|
def l1_keepalives(self):
|
||||||
"""
|
"""
|
||||||
Returns either layer 1 keepalive messages option is enabled or disabled.
|
Returns either layer 1 keepalive messages option is enabled or disabled.
|
||||||
|
|
||||||
:returns: boolean
|
:returns: boolean
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -900,19 +929,21 @@ class IOUVM(BaseVM):
|
|||||||
def l1_keepalives(self, state):
|
def l1_keepalives(self, state):
|
||||||
"""
|
"""
|
||||||
Enables or disables layer 1 keepalive messages.
|
Enables or disables layer 1 keepalive messages.
|
||||||
|
|
||||||
:param state: boolean
|
:param state: boolean
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._l1_keepalives = state
|
self._l1_keepalives = state
|
||||||
if 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:
|
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
|
@asyncio.coroutine
|
||||||
def _enable_l1_keepalives(self, command):
|
def _enable_l1_keepalives(self, command):
|
||||||
"""
|
"""
|
||||||
Enables L1 keepalive messages if supported.
|
Enables L1 keepalive messages if supported.
|
||||||
|
|
||||||
:param command: command line
|
:param command: command line
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -930,7 +961,9 @@ class IOUVM(BaseVM):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def initial_config(self):
|
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
|
config_file = self.initial_config_file
|
||||||
if config_file is None:
|
if config_file is None:
|
||||||
@ -947,7 +980,7 @@ class IOUVM(BaseVM):
|
|||||||
"""
|
"""
|
||||||
Update the initial config
|
Update the initial config
|
||||||
|
|
||||||
:param initial_config: The content of the initial configuration file
|
:param initial_config: content of the initial configuration file
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -964,7 +997,7 @@ class IOUVM(BaseVM):
|
|||||||
@property
|
@property
|
||||||
def initial_config_file(self):
|
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
|
: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):
|
def relative_initial_config_file(self):
|
||||||
"""
|
"""
|
||||||
Returns the initial config file relative to the project directory.
|
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
|
: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"):
|
def start_capture(self, adapter_number, port_number, output_file, data_link_type="DLT_EN10MB"):
|
||||||
"""
|
"""
|
||||||
Starts a packet capture.
|
Starts a packet capture.
|
||||||
:param adapter_number: adapter ID
|
|
||||||
:param port_number: port ID
|
:param adapter_number: adapter number
|
||||||
:param port: allocated port
|
:param port_number: port number
|
||||||
:param output_file: PCAP destination file for the capture
|
:param output_file: PCAP destination file for the capture
|
||||||
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
:param data_link_type: PCAP data link type (DLT_*), default is DLT_EN10MB
|
||||||
"""
|
"""
|
||||||
@ -1004,32 +1037,25 @@ class IOUVM(BaseVM):
|
|||||||
try:
|
try:
|
||||||
adapter = self._adapters[adapter_number]
|
adapter = self._adapters[adapter_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise IOUError("Adapter {adapter_number} doesn't exist on IOU {name}".format(name=self._name,
|
raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
if not adapter.port_exists(port_number):
|
if not adapter.port_exists(port_number):
|
||||||
raise IOUError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter,
|
raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
nio = adapter.get_nio(port_number)
|
nio = adapter.get_nio(port_number)
|
||||||
if not nio:
|
if not nio:
|
||||||
raise IOUError("NIO {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter,
|
raise IOUError("NIO {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
if nio.capturing:
|
if nio.capturing:
|
||||||
raise IOUError("Packet capture is already activated on {adapter_number}/{port_number}".format(adapter_number=adapter_number,
|
raise IOUError("Packet capture is already activated on {adapter_number}/{port_number}".format(adapter_number=adapter_number,
|
||||||
port_number=port_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)
|
nio.startPacketCapture(output_file, data_link_type)
|
||||||
|
log.info('IOU "{name}" [{id}]: starting packet capture on {adapter_number}/{port_number}'.format(name=self._name,
|
||||||
log.info("IOU {name} [id={id}]: starting packet capture on {adapter_number}/{port_number}".format(name=self._name,
|
|
||||||
id=self._id,
|
id=self._id,
|
||||||
adapter_number=adapter_number,
|
adapter_number=adapter_number,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
@ -1042,23 +1068,24 @@ class IOUVM(BaseVM):
|
|||||||
def stop_capture(self, adapter_number, port_number):
|
def stop_capture(self, adapter_number, port_number):
|
||||||
"""
|
"""
|
||||||
Stops a packet capture.
|
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:
|
try:
|
||||||
adapter = self._adapters[adapter_number]
|
adapter = self._adapters[adapter_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise IOUError("Adapter {adapter_number} doesn't exist on IOU {name}".format(name=self._name,
|
raise IOUError('Adapter {adapter_number} does not exist on IOU "{name}"'.format(name=self._name,
|
||||||
adapter_number=adapter_number))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
if not adapter.port_exists(port_number):
|
if not adapter.port_exists(port_number):
|
||||||
raise IOUError("Port {port_number} doesn't exist in adapter {adapter}".format(adapter=adapter,
|
raise IOUError("Port {port_number} does not exist in adapter {adapter}".format(adapter=adapter,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
nio = adapter.get_nio(port_number)
|
nio = adapter.get_nio(port_number)
|
||||||
nio.stopPacketCapture()
|
nio.stopPacketCapture()
|
||||||
log.info("IOU {name} [id={id}]: stopping packet capture on {adapter_number}/{port_number}".format(name=self._name,
|
log.info('IOU "{name}" [{id}]: stopping packet capture on {adapter_number}/{port_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
adapter_number=adapter_number,
|
adapter_number=adapter_number,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
@ -32,7 +32,7 @@ class NIOGenericEthernet(NIO):
|
|||||||
|
|
||||||
def __init__(self, ethernet_device):
|
def __init__(self, ethernet_device):
|
||||||
|
|
||||||
NIO.__init__(self)
|
super().__init__()
|
||||||
self._ethernet_device = ethernet_device
|
self._ethernet_device = ethernet_device
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -261,7 +261,7 @@ class PortManager:
|
|||||||
:param force_remove: Force port removal even on Darwnin
|
: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:
|
if sys.platform.startswith("darwin") and force_remove is False:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@ class Project:
|
|||||||
A project contains a list of VM.
|
A project contains a list of VM.
|
||||||
In theory VM are isolated project/project.
|
In theory VM 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)
|
||||||
:param location: Parent path of the project. (None should create a tmp 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 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):
|
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):
|
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.
|
If the directory doesn't exist, the directory is created.
|
||||||
|
|
||||||
:param module_name: name for the module
|
:param module_name: name for the module
|
||||||
@ -247,18 +247,20 @@ class Project:
|
|||||||
|
|
||||||
def module_working_path(self, module_name):
|
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:
|
to be sure to have the directory on disk take a look on:
|
||||||
module_working_directory
|
module_working_directory
|
||||||
"""
|
"""
|
||||||
|
|
||||||
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 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.
|
If the directory doesn't exist, the directory is created.
|
||||||
|
|
||||||
:param vm: VM instance
|
:param vm: VM instance
|
||||||
|
|
||||||
:returns: VM working directory
|
:returns: VM working directory
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -271,7 +273,7 @@ class Project:
|
|||||||
|
|
||||||
def capture_working_directory(self):
|
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
|
:returns: path to the directory
|
||||||
"""
|
"""
|
||||||
@ -293,7 +295,7 @@ class Project:
|
|||||||
|
|
||||||
def add_vm(self, vm):
|
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.
|
In theory this should be called by the VM manager.
|
||||||
|
|
||||||
:param vm: VM instance
|
:param vm: VM instance
|
||||||
@ -303,7 +305,7 @@ class Project:
|
|||||||
|
|
||||||
def remove_vm(self, vm):
|
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.
|
In theory this should be called by the VM manager.
|
||||||
|
|
||||||
:param vm: VM instance
|
:param vm: VM instance
|
||||||
@ -314,7 +316,9 @@ class Project:
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Close the project, but keep information on disk"""
|
"""
|
||||||
|
Closes the project, but keep information on disk
|
||||||
|
"""
|
||||||
|
|
||||||
for module in self.modules():
|
for module in self.modules():
|
||||||
yield from module.instance().project_closing(self)
|
yield from module.instance().project_closing(self)
|
||||||
@ -325,7 +329,7 @@ class Project:
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _close_and_clean(self, cleanup):
|
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
|
:param cleanup: If True drop the project directory
|
||||||
"""
|
"""
|
||||||
@ -365,7 +369,9 @@ class Project:
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def commit(self):
|
def commit(self):
|
||||||
"""Write project changes on disk"""
|
"""
|
||||||
|
Writes project changes on disk
|
||||||
|
"""
|
||||||
|
|
||||||
while self._vms_to_destroy:
|
while self._vms_to_destroy:
|
||||||
vm = self._vms_to_destroy.pop()
|
vm = self._vms_to_destroy.pop()
|
||||||
@ -376,7 +382,9 @@ class Project:
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def delete(self):
|
def delete(self):
|
||||||
"""Remove project from disk"""
|
"""
|
||||||
|
Removes project from disk
|
||||||
|
"""
|
||||||
|
|
||||||
for module in self.modules():
|
for module in self.modules():
|
||||||
yield from module.instance().project_closing(self)
|
yield from module.instance().project_closing(self)
|
||||||
@ -386,7 +394,9 @@ class Project:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def clean_project_directory(cls):
|
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")
|
config = Config.instance().get_section_config("Server")
|
||||||
directory = config.get("project_directory", cls._get_default_project_directory())
|
directory = config.get("project_directory", cls._get_default_project_directory())
|
||||||
@ -398,7 +408,9 @@ class Project:
|
|||||||
shutil.rmtree(path)
|
shutil.rmtree(path)
|
||||||
|
|
||||||
def modules(self):
|
def modules(self):
|
||||||
"""Return VM modules loaded"""
|
"""
|
||||||
|
Returns all loaded VM modules.
|
||||||
|
"""
|
||||||
|
|
||||||
# We import it at the last time to avoid circular dependencies
|
# We import it at the last time to avoid circular dependencies
|
||||||
from ..modules import MODULES
|
from ..modules import MODULES
|
||||||
|
@ -32,14 +32,15 @@ from .qemu_vm import QemuVM
|
|||||||
|
|
||||||
|
|
||||||
class Qemu(BaseManager):
|
class Qemu(BaseManager):
|
||||||
|
|
||||||
_VM_CLASS = QemuVM
|
_VM_CLASS = QemuVM
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def binary_list():
|
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 = []
|
qemus = []
|
||||||
@ -82,7 +83,8 @@ class Qemu(BaseManager):
|
|||||||
def _get_qemu_version(qemu_path):
|
def _get_qemu_version(qemu_path):
|
||||||
"""
|
"""
|
||||||
Gets the Qemu version.
|
Gets the Qemu version.
|
||||||
:param qemu_path: path to Qemu
|
|
||||||
|
:param qemu_path: path to Qemu executable.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
|
@ -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/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Custom exceptions for Qemu module.
|
Custom exceptions for the Qemu module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ..vm_error import VMError
|
from ..vm_error import VMError
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
QEMU VM instance.
|
QEMU VM management (creates command line, processes, files etc.) in
|
||||||
|
order to run a QEMU VM.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@ -44,26 +45,18 @@ class QemuVM(BaseVM):
|
|||||||
"""
|
"""
|
||||||
QEMU VM implementation.
|
QEMU VM implementation.
|
||||||
|
|
||||||
:param name: name of this Qemu vm
|
:param name: Qemu VM name
|
||||||
:param vm_id: IOU instance identifier
|
:param vm_id: Qemu VM identifier
|
||||||
:param project: Project instance
|
:param project: Project instance
|
||||||
:param manager: parent VM Manager
|
:param manager: Manager instance
|
||||||
:param console: TCP console port
|
:param console: TCP console port
|
||||||
:param qemu_path: path to the QEMU binary
|
:param qemu_path: path to the QEMU binary
|
||||||
:param qemu_id: QEMU VM instance ID
|
|
||||||
:param console: TCP console port
|
:param console: TCP console port
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self, name, vm_id, project, manager, qemu_path=None, console=None):
|
||||||
name,
|
|
||||||
vm_id,
|
|
||||||
project,
|
|
||||||
manager,
|
|
||||||
qemu_path=None,
|
|
||||||
console=None):
|
|
||||||
|
|
||||||
super().__init__(name, vm_id, project, manager, console=console)
|
super().__init__(name, vm_id, project, manager, console=console)
|
||||||
|
|
||||||
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")
|
||||||
@ -74,7 +67,7 @@ class QemuVM(BaseVM):
|
|||||||
self._monitor = None
|
self._monitor = None
|
||||||
self._stdout_file = ""
|
self._stdout_file = ""
|
||||||
|
|
||||||
# QEMU settings
|
# QEMU VM settings
|
||||||
self._qemu_path = qemu_path
|
self._qemu_path = qemu_path
|
||||||
self._hda_disk_image = ""
|
self._hda_disk_image = ""
|
||||||
self._hdb_disk_image = ""
|
self._hdb_disk_image = ""
|
||||||
@ -92,8 +85,7 @@ class QemuVM(BaseVM):
|
|||||||
self._process_priority = "low"
|
self._process_priority = "low"
|
||||||
|
|
||||||
self.adapters = 1 # creates 1 adapter by default
|
self.adapters = 1 # creates 1 adapter by default
|
||||||
log.info("QEMU VM {name} [id={id}] has been created".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}] has been created'.format(name=self._name, id=self._id))
|
||||||
id=self._id))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def monitor(self):
|
def monitor(self):
|
||||||
@ -134,7 +126,7 @@ class QemuVM(BaseVM):
|
|||||||
raise QemuError("QEMU binary '{}' is not executable".format(qemu_path))
|
raise QemuError("QEMU binary '{}' is not executable".format(qemu_path))
|
||||||
|
|
||||||
self._qemu_path = 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,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU path to {qemu_path}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
qemu_path=qemu_path))
|
qemu_path=qemu_path))
|
||||||
|
|
||||||
@ -160,7 +152,7 @@ class QemuVM(BaseVM):
|
|||||||
server_config = self.manager.config.get_section_config("Server")
|
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)
|
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,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU hda disk image path to {disk_image}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
disk_image=hda_disk_image))
|
disk_image=hda_disk_image))
|
||||||
self._hda_disk_image = hda_disk_image
|
self._hda_disk_image = hda_disk_image
|
||||||
@ -187,7 +179,7 @@ class QemuVM(BaseVM):
|
|||||||
server_config = self.manager.config.get_section_config("Server")
|
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)
|
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,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU hdb disk image path to {disk_image}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
disk_image=hdb_disk_image))
|
disk_image=hdb_disk_image))
|
||||||
self._hdb_disk_image = hdb_disk_image
|
self._hdb_disk_image = hdb_disk_image
|
||||||
@ -214,7 +206,7 @@ class QemuVM(BaseVM):
|
|||||||
server_config = self.manager.config.get_section_config("Server")
|
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)
|
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,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU hdc disk image path to {disk_image}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
disk_image=hdc_disk_image))
|
disk_image=hdc_disk_image))
|
||||||
self._hdc_disk_image = hdc_disk_image
|
self._hdc_disk_image = hdc_disk_image
|
||||||
@ -241,7 +233,7 @@ class QemuVM(BaseVM):
|
|||||||
server_config = self.manager.config.get_section_config("Server")
|
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)
|
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,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU hdd disk image path to {disk_image}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
disk_image=hdd_disk_image))
|
disk_image=hdd_disk_image))
|
||||||
self._hdd_disk_image = hdd_disk_image
|
self._hdd_disk_image = hdd_disk_image
|
||||||
@ -249,7 +241,7 @@ class QemuVM(BaseVM):
|
|||||||
@property
|
@property
|
||||||
def adapters(self):
|
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
|
:returns: number of adapters
|
||||||
"""
|
"""
|
||||||
@ -259,23 +251,23 @@ class QemuVM(BaseVM):
|
|||||||
@adapters.setter
|
@adapters.setter
|
||||||
def adapters(self, adapters):
|
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
|
:param adapters: number of adapters
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._ethernet_adapters.clear()
|
self._ethernet_adapters.clear()
|
||||||
for adapter_id in range(0, adapters):
|
for adapter_number in range(0, adapters):
|
||||||
self._ethernet_adapters.append(EthernetAdapter())
|
self._ethernet_adapters.append(EthernetAdapter())
|
||||||
|
|
||||||
log.info("QEMU VM {name} [id={id}]: number of Ethernet adapters changed to {adapters}".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}]: number of Ethernet adapters changed to {adapters}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
adapters=adapters))
|
adapters=adapters))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def adapter_type(self):
|
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)
|
:returns: adapter type (string)
|
||||||
"""
|
"""
|
||||||
@ -285,14 +277,14 @@ class QemuVM(BaseVM):
|
|||||||
@adapter_type.setter
|
@adapter_type.setter
|
||||||
def adapter_type(self, adapter_type):
|
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)
|
:param adapter_type: adapter type (string)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._adapter_type = adapter_type
|
self._adapter_type = adapter_type
|
||||||
|
|
||||||
log.info("QEMU VM {name} [id={id}]: adapter type changed to {adapter_type}".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}]: adapter type changed to {adapter_type}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
adapter_type=adapter_type))
|
adapter_type=adapter_type))
|
||||||
|
|
||||||
@ -315,9 +307,9 @@ class QemuVM(BaseVM):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if legacy_networking:
|
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:
|
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
|
self._legacy_networking = legacy_networking
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -338,7 +330,7 @@ class QemuVM(BaseVM):
|
|||||||
:param cpu_throttling: integer
|
:param cpu_throttling: integer
|
||||||
"""
|
"""
|
||||||
|
|
||||||
log.info("QEMU VM {name} [id={id}] has set the percentage of CPU allowed to {cpu}".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}] has set the percentage of CPU allowed to {cpu}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
cpu=cpu_throttling))
|
cpu=cpu_throttling))
|
||||||
self._cpu_throttling = cpu_throttling
|
self._cpu_throttling = cpu_throttling
|
||||||
@ -364,7 +356,7 @@ class QemuVM(BaseVM):
|
|||||||
:param process_priority: string
|
:param process_priority: string
|
||||||
"""
|
"""
|
||||||
|
|
||||||
log.info("QEMU VM {name} [id={id}] has set the process priority to {priority}".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}] has set the process priority to {priority}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
priority=process_priority))
|
priority=process_priority))
|
||||||
self._process_priority = process_priority
|
self._process_priority = process_priority
|
||||||
@ -387,9 +379,7 @@ class QemuVM(BaseVM):
|
|||||||
:param ram: RAM amount in MB
|
:param ram: RAM amount in MB
|
||||||
"""
|
"""
|
||||||
|
|
||||||
log.info("QEMU VM {name} [id={id}] has set the RAM to {ram}".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}] has set the RAM to {ram}'.format(name=self._name, id=self._id, ram=ram))
|
||||||
id=self._id,
|
|
||||||
ram=ram))
|
|
||||||
self._ram = ram
|
self._ram = ram
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -410,7 +400,7 @@ class QemuVM(BaseVM):
|
|||||||
:param options: QEMU options
|
:param options: QEMU options
|
||||||
"""
|
"""
|
||||||
|
|
||||||
log.info("QEMU VM {name} [id={id}] has set the QEMU options to {options}".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU options to {options}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
options=options))
|
options=options))
|
||||||
self._options = options
|
self._options = options
|
||||||
@ -437,7 +427,7 @@ class QemuVM(BaseVM):
|
|||||||
server_config = self.manager.config.get_section_config("Server")
|
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)
|
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,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU initrd path to {initrd}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
initrd=initrd))
|
initrd=initrd))
|
||||||
self._initrd = initrd
|
self._initrd = initrd
|
||||||
@ -464,7 +454,7 @@ class QemuVM(BaseVM):
|
|||||||
server_config = self.manager.config.get_section_config("Server")
|
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)
|
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,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU kernel image path to {kernel_image}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
kernel_image=kernel_image))
|
kernel_image=kernel_image))
|
||||||
self._kernel_image = kernel_image
|
self._kernel_image = kernel_image
|
||||||
@ -487,7 +477,7 @@ class QemuVM(BaseVM):
|
|||||||
:param kernel_command_line: QEMU kernel command line
|
: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,
|
log.info('QEMU VM "{name}" [{id}] has set the QEMU kernel command line to {kernel_command_line}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
kernel_command_line=kernel_command_line))
|
kernel_command_line=kernel_command_line))
|
||||||
self._kernel_command_line = kernel_command_line
|
self._kernel_command_line = kernel_command_line
|
||||||
@ -538,7 +528,7 @@ class QemuVM(BaseVM):
|
|||||||
process = yield from asyncio.create_subprocess_exec('renice', '-n', str(priority), '-p', str(self._process.pid))
|
process = yield from asyncio.create_subprocess_exec('renice', '-n', str(priority), '-p', str(self._process.pid))
|
||||||
yield from process.wait()
|
yield from process.wait()
|
||||||
except (OSError, subprocess.SubprocessError) as e:
|
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):
|
def _stop_cpulimit(self):
|
||||||
"""
|
"""
|
||||||
@ -550,7 +540,7 @@ class QemuVM(BaseVM):
|
|||||||
try:
|
try:
|
||||||
self._process.wait(3)
|
self._process.wait(3)
|
||||||
except subprocess.TimeoutExpired:
|
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):
|
def _set_cpu_throttling(self):
|
||||||
"""
|
"""
|
||||||
@ -579,7 +569,6 @@ class QemuVM(BaseVM):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
|
|
||||||
# resume the VM if it is paused
|
# resume the VM if it is paused
|
||||||
yield from self.resume()
|
yield from self.resume()
|
||||||
return
|
return
|
||||||
@ -597,7 +586,7 @@ class QemuVM(BaseVM):
|
|||||||
|
|
||||||
self._command = yield from self._build_command()
|
self._command = yield from self._build_command()
|
||||||
try:
|
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")
|
self._stdout_file = os.path.join(self.working_dir, "qemu.log")
|
||||||
log.info("logging to {}".format(self._stdout_file))
|
log.info("logging to {}".format(self._stdout_file))
|
||||||
with open(self._stdout_file, "w") as fd:
|
with open(self._stdout_file, "w") as fd:
|
||||||
@ -605,12 +594,12 @@ class QemuVM(BaseVM):
|
|||||||
stdout=fd,
|
stdout=fd,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
cwd=self.working_dir)
|
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
|
self._started = True
|
||||||
except (OSError, subprocess.SubprocessError) as e:
|
except (OSError, subprocess.SubprocessError) as e:
|
||||||
stdout = self.read_stdout()
|
stdout = self.read_stdout()
|
||||||
log.error("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))
|
raise QemuError("Could not start QEMU {}: {}\n{}".format(self.qemu_path, e, stdout))
|
||||||
|
|
||||||
self._set_process_priority()
|
self._set_process_priority()
|
||||||
if self._cpu_throttling:
|
if self._cpu_throttling:
|
||||||
@ -624,15 +613,14 @@ class QemuVM(BaseVM):
|
|||||||
|
|
||||||
# stop the QEMU process
|
# stop the QEMU process
|
||||||
if self.is_running():
|
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:
|
try:
|
||||||
self._process.terminate()
|
self._process.terminate()
|
||||||
self._process.wait()
|
self._process.wait()
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
self._process.kill()
|
self._process.kill()
|
||||||
if self._process.returncode is None:
|
if self._process.returncode is None:
|
||||||
log.warn("QEMU VM instance {} PID={} is still running".format(self._id,
|
log.warn('QEMU VM "{}" PID={} is still running'.format(self._name, self._process.pid))
|
||||||
self._process.pid))
|
|
||||||
self._process = None
|
self._process = None
|
||||||
self._started = False
|
self._started = False
|
||||||
self._stop_cpulimit()
|
self._stop_cpulimit()
|
||||||
@ -643,9 +631,9 @@ class QemuVM(BaseVM):
|
|||||||
Executes a command with QEMU monitor when this VM is running.
|
Executes a command with QEMU monitor when this VM is running.
|
||||||
|
|
||||||
:param command: QEMU monitor command (e.g. info status, stop etc.)
|
: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
|
result = None
|
||||||
@ -680,6 +668,9 @@ class QemuVM(BaseVM):
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def close(self):
|
def close(self):
|
||||||
|
"""
|
||||||
|
Closes this QEMU VM.
|
||||||
|
"""
|
||||||
|
|
||||||
log.debug('QEMU VM "{name}" [{id}] is closing'.format(name=self._name, id=self._id))
|
log.debug('QEMU VM "{name}" [{id}] is closing'.format(name=self._name, id=self._id))
|
||||||
yield from self.stop()
|
yield from self.stop()
|
||||||
@ -690,7 +681,7 @@ class QemuVM(BaseVM):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _get_vm_status(self):
|
def _get_vm_status(self):
|
||||||
"""
|
"""
|
||||||
Returns this VM suspend status (running|paused)
|
Returns this VM suspend status.
|
||||||
|
|
||||||
Status are extracted from:
|
Status are extracted from:
|
||||||
https://github.com/qemu/qemu/blob/master/qapi-schema.json#L152
|
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))
|
log.info("QEMU VM is not paused to be resumed, current status is {}".format(vm_status))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@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.
|
Adds a port NIO binding.
|
||||||
|
|
||||||
:param adapter_id: adapter ID
|
:param adapter_number: adapter number
|
||||||
:param nio: NIO instance to add to the adapter
|
:param nio: NIO instance to add to the adapter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._ethernet_adapters[adapter_id]
|
adapter = self._ethernet_adapters[adapter_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise QemuError("Adapter {adapter_id} doesn't exist on QEMU VM {name}".format(name=self._name,
|
raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name,
|
||||||
adapter_id=adapter_id))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
# dynamically configure an UDP tunnel on the QEMU VM adapter
|
# dynamically configure an UDP tunnel on the QEMU VM adapter
|
||||||
if nio and isinstance(nio, NIOUDP):
|
if nio and isinstance(nio, NIOUDP):
|
||||||
if self._legacy_networking:
|
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_remove {} gns3-{}".format(adapter_number, adapter_number))
|
||||||
yield from self._control_vm("host_net_add udp vlan={},name=gns3-{},sport={},dport={},daddr={}".format(adapter_id,
|
yield from self._control_vm("host_net_add udp vlan={},name=gns3-{},sport={},dport={},daddr={}".format(adapter_number,
|
||||||
adapter_id,
|
adapter_number,
|
||||||
nio.lport,
|
nio.lport,
|
||||||
nio.rport,
|
nio.rport,
|
||||||
nio.rhost))
|
nio.rhost))
|
||||||
@ -778,48 +769,48 @@ class QemuVM(BaseVM):
|
|||||||
# Apparently there is a bug in Qemu...
|
# Apparently there is a bug in Qemu...
|
||||||
# netdev_add [user|tap|socket|hubport|netmap],id=str[,prop=value][,...] -- add host network device
|
# netdev_add [user|tap|socket|hubport|netmap],id=str[,prop=value][,...] -- add host network device
|
||||||
# netdev_del id -- remove 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_del gns3-{}".format(adapter_number))
|
||||||
yield from self._control_vm("netdev_add socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_id,
|
yield from self._control_vm("netdev_add socket,id=gns3-{},udp={}:{},localaddr={}:{}".format(adapter_number,
|
||||||
nio.rhost,
|
nio.rhost,
|
||||||
nio.rport,
|
nio.rport,
|
||||||
self._host,
|
self._host,
|
||||||
nio.lport))
|
nio.lport))
|
||||||
|
|
||||||
adapter.add_nio(0, nio)
|
adapter.add_nio(0, nio)
|
||||||
log.info("QEMU VM {name} [id={id}]: {nio} added to adapter {adapter_id}".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}]: {nio} added to adapter {adapter_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
adapter_id=adapter_id))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def adapter_remove_nio_binding(self, adapter_id):
|
def adapter_remove_nio_binding(self, adapter_number):
|
||||||
"""
|
"""
|
||||||
Removes a port NIO binding.
|
Removes a port NIO binding.
|
||||||
|
|
||||||
:param adapter_id: adapter ID
|
:param adapter_number: adapter number
|
||||||
|
|
||||||
:returns: NIO instance
|
:returns: NIO instance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
adapter = self._ethernet_adapters[adapter_id]
|
adapter = self._ethernet_adapters[adapter_number]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise QemuError("Adapter {adapter_id} doesn't exist on QEMU VM {name}".format(name=self._name,
|
raise QemuError('Adapter {adapter_number} does not exist on QEMU VM "{name}"'.format(name=self._name,
|
||||||
adapter_id=adapter_id))
|
adapter_number=adapter_number))
|
||||||
|
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
# dynamically disable the QEMU VM adapter
|
# 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_remove {} gns3-{}".format(adapter_number, adapter_number))
|
||||||
yield from self._control_vm("host_net_add user vlan={},name=gns3-{}".format(adapter_id, adapter_id))
|
yield from self._control_vm("host_net_add user vlan={},name=gns3-{}".format(adapter_number, adapter_number))
|
||||||
|
|
||||||
nio = adapter.get_nio(0)
|
nio = adapter.get_nio(0)
|
||||||
if isinstance(nio, NIOUDP):
|
if isinstance(nio, NIOUDP):
|
||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
adapter.remove_nio(0)
|
adapter.remove_nio(0)
|
||||||
log.info("QEMU VM {name} [id={id}]: {nio} removed from adapter {adapter_id}".format(name=self._name,
|
log.info('QEMU VM "{name}" [{id}]: {nio} removed from adapter {adapter_number}'.format(name=self._name,
|
||||||
id=self._id,
|
id=self._id,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
adapter_id=adapter_id))
|
adapter_number=adapter_number))
|
||||||
return nio
|
return nio
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -844,7 +835,7 @@ class QemuVM(BaseVM):
|
|||||||
with open(self._stdout_file, errors="replace") as file:
|
with open(self._stdout_file, errors="replace") as file:
|
||||||
output = file.read()
|
output = file.read()
|
||||||
except OSError as e:
|
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
|
return output
|
||||||
|
|
||||||
def is_running(self):
|
def is_running(self):
|
||||||
@ -1004,47 +995,48 @@ class QemuVM(BaseVM):
|
|||||||
|
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def _get_random_mac(self, adapter_id):
|
def _get_random_mac(self, adapter_number):
|
||||||
# TODO: let users specify a base mac address
|
# 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):
|
def _network_options(self):
|
||||||
|
|
||||||
network_options = []
|
network_options = []
|
||||||
adapter_id = 0
|
adapter_number = 0
|
||||||
for adapter in self._ethernet_adapters:
|
for adapter in self._ethernet_adapters:
|
||||||
mac = self._get_random_mac(adapter_id)
|
mac = self._get_random_mac(adapter_number)
|
||||||
if self._legacy_networking:
|
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:
|
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)
|
nio = adapter.get_nio(0)
|
||||||
if nio and isinstance(nio, NIOUDP):
|
if nio and isinstance(nio, NIOUDP):
|
||||||
if self._legacy_networking:
|
if self._legacy_networking:
|
||||||
network_options.extend(["-net", "udp,vlan={},name=gns3-{},sport={},dport={},daddr={}".format(adapter_id,
|
network_options.extend(["-net", "udp,vlan={},name=gns3-{},sport={},dport={},daddr={}".format(adapter_number,
|
||||||
adapter_id,
|
adapter_number,
|
||||||
nio.lport,
|
nio.lport,
|
||||||
nio.rport,
|
nio.rport,
|
||||||
nio.rhost)])
|
nio.rhost)])
|
||||||
else:
|
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.rhost,
|
||||||
nio.rport,
|
nio.rport,
|
||||||
self._host,
|
self._host,
|
||||||
nio.lport)])
|
nio.lport)])
|
||||||
else:
|
else:
|
||||||
if self._legacy_networking:
|
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:
|
else:
|
||||||
network_options.extend(["-netdev", "user,id=gns3-{}".format(adapter_id)])
|
network_options.extend(["-netdev", "user,id=gns3-{}".format(adapter_number)])
|
||||||
adapter_id += 1
|
adapter_number += 1
|
||||||
|
|
||||||
return network_options
|
return network_options
|
||||||
|
|
||||||
def _graphic(self):
|
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"):
|
if sys.platform.startswith("win"):
|
||||||
return []
|
return []
|
||||||
if len(os.environ.get("DISPLAY", "")) > 0:
|
if len(os.environ.get("DISPLAY", "")) > 0:
|
||||||
@ -1086,7 +1078,7 @@ class QemuVM(BaseVM):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if disk_image:
|
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")
|
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)
|
relative_image = os.path.join(os.path.expanduser(server_config.get("images_path", "~/GNS3/images")), "QEMU", disk_image)
|
||||||
if os.path.exists(relative_image):
|
if os.path.exists(relative_image):
|
||||||
|
@ -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/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Custom exceptions for VirtualBox module.
|
Custom exceptions for the VirtualBox module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ..vm_error import VMError
|
from ..vm_error import VMError
|
||||||
|
@ -28,26 +28,38 @@ from .vpcs_vm import VPCSVM
|
|||||||
|
|
||||||
|
|
||||||
class VPCS(BaseManager):
|
class VPCS(BaseManager):
|
||||||
|
|
||||||
_VM_CLASS = VPCSVM
|
_VM_CLASS = VPCSVM
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._free_mac_ids = {}
|
self._free_mac_ids = {}
|
||||||
self._used_mac_ids = {}
|
self._used_mac_ids = {}
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def create_vm(self, *args, **kwargs):
|
def create_vm(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Creates a new VPCS VM.
|
||||||
|
|
||||||
|
:returns: VPCSVM instance
|
||||||
|
"""
|
||||||
|
|
||||||
vm = yield from super().create_vm(*args, **kwargs)
|
vm = yield from super().create_vm(*args, **kwargs)
|
||||||
self._free_mac_ids.setdefault(vm.project.id, list(range(0, 255)))
|
self._free_mac_ids.setdefault(vm.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[vm.id] = self._free_mac_ids[vm.project.id].pop(0)
|
||||||
except IndexError:
|
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
|
return vm
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def close_vm(self, vm_id, *args, **kwargs):
|
def close_vm(self, vm_id, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Closes a VPCS VM.
|
||||||
|
|
||||||
|
:returns: VPCSVM instance
|
||||||
|
"""
|
||||||
|
|
||||||
vm = self.get_vm(vm_id)
|
vm = self.get_vm(vm_id)
|
||||||
i = self._used_mac_ids[vm_id]
|
i = self._used_mac_ids[vm_id]
|
||||||
@ -59,10 +71,11 @@ class VPCS(BaseManager):
|
|||||||
|
|
||||||
def get_mac_id(self, vm_id):
|
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
|
:param vm_id: VPCS VM identifier
|
||||||
:returns: VPCS MAC id
|
|
||||||
|
:returns: VPCS MAC identifier
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._used_mac_ids.get(vm_id, 1)
|
return self._used_mac_ids.get(vm_id, 1)
|
||||||
|
@ -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/>.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Custom exceptions for VPCS module.
|
Custom exceptions for the VPCS module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ..vm_error import VMError
|
from ..vm_error import VMError
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
VPCS VM management (creates command line, processes, files etc.) in
|
VPCS VM management (creates command line, processes, files etc.) in
|
||||||
order to run an VPCS instance.
|
order to run a VPCS VM.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -45,20 +45,19 @@ class VPCSVM(BaseVM):
|
|||||||
module_name = 'vpcs'
|
module_name = 'vpcs'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
VPCS vm implementation.
|
VPCS VM implementation.
|
||||||
|
|
||||||
:param name: The name of this VM
|
:param name: VPCS VM name
|
||||||
:param vm_id: VPCS instance identifier
|
:param vm_id: VPCS VM identifier
|
||||||
:param project: Project instance
|
:param project: Project instance
|
||||||
:param manager: Parent VM Manager
|
:param manager: Manager instance
|
||||||
:param console: TCP console port
|
: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):
|
def __init__(self, name, vm_id, project, manager, console=None, startup_script=None):
|
||||||
|
|
||||||
super().__init__(name, vm_id, project, manager, console=console)
|
super().__init__(name, vm_id, project, manager, console=console)
|
||||||
|
|
||||||
self._command = []
|
self._command = []
|
||||||
self._process = None
|
self._process = None
|
||||||
self._vpcs_stdout_file = ""
|
self._vpcs_stdout_file = ""
|
||||||
@ -71,8 +70,11 @@ class VPCSVM(BaseVM):
|
|||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def close(self):
|
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:
|
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)
|
||||||
self._console = None
|
self._console = None
|
||||||
@ -87,8 +89,9 @@ class VPCSVM(BaseVM):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _check_requirements(self):
|
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
|
path = self.vpcs_path
|
||||||
if not path:
|
if not path:
|
||||||
raise VPCSError("No path to a VPCS executable has been set")
|
raise VPCSError("No path to a VPCS executable has been set")
|
||||||
@ -140,7 +143,7 @@ class VPCSVM(BaseVM):
|
|||||||
@BaseVM.name.setter
|
@BaseVM.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.
|
||||||
|
|
||||||
:param new_name: name
|
:param new_name: name
|
||||||
"""
|
"""
|
||||||
@ -154,7 +157,9 @@ class VPCSVM(BaseVM):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def startup_script(self):
|
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
|
script_file = self.script_file
|
||||||
if script_file is None:
|
if script_file is None:
|
||||||
@ -164,14 +169,14 @@ class VPCSVM(BaseVM):
|
|||||||
with open(script_file) as f:
|
with open(script_file) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
except OSError as e:
|
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
|
@startup_script.setter
|
||||||
def startup_script(self, startup_script):
|
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:
|
try:
|
||||||
@ -183,7 +188,7 @@ class VPCSVM(BaseVM):
|
|||||||
startup_script = startup_script.replace("%h", self._name)
|
startup_script = startup_script.replace("%h", self._name)
|
||||||
f.write(startup_script)
|
f.write(startup_script)
|
||||||
except OSError as e:
|
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
|
@asyncio.coroutine
|
||||||
def _check_vpcs_version(self):
|
def _check_vpcs_version(self):
|
||||||
@ -209,7 +214,6 @@ class VPCSVM(BaseVM):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self._check_requirements()
|
yield from self._check_requirements()
|
||||||
|
|
||||||
if not self.is_running():
|
if not self.is_running():
|
||||||
if not self._ethernet_adapter.get_nio(0):
|
if not self._ethernet_adapter.get_nio(0):
|
||||||
raise VPCSError("This VPCS instance must be connected in order to start")
|
raise VPCSError("This VPCS instance must be connected in order to start")
|
||||||
@ -256,14 +260,16 @@ class VPCSVM(BaseVM):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def reload(self):
|
def reload(self):
|
||||||
"""
|
"""
|
||||||
Reload the VPCS process. (Stop / Start)
|
Reloads the VPCS process (stop & start).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self.stop()
|
yield from self.stop()
|
||||||
yield from self.start()
|
yield from self.start()
|
||||||
|
|
||||||
def _terminate_process(self):
|
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))
|
log.info("Stopping VPCS instance {} PID={}".format(self.name, self._process.pid))
|
||||||
if sys.platform.startswith("win32"):
|
if sys.platform.startswith("win32"):
|
||||||
@ -271,7 +277,7 @@ class VPCSVM(BaseVM):
|
|||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self._process.terminate()
|
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:
|
except ProcessLookupError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -280,13 +286,14 @@ class VPCSVM(BaseVM):
|
|||||||
Reads the standard output of the VPCS process.
|
Reads the standard output of the VPCS process.
|
||||||
Only use when the process has been stopped or has crashed.
|
Only use when the process has been stopped or has crashed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
output = ""
|
output = ""
|
||||||
if self._vpcs_stdout_file:
|
if self._vpcs_stdout_file:
|
||||||
try:
|
try:
|
||||||
with open(self._vpcs_stdout_file, errors="replace") as file:
|
with open(self._vpcs_stdout_file, errors="replace") as file:
|
||||||
output = file.read()
|
output = file.read()
|
||||||
except OSError as e:
|
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
|
return output
|
||||||
|
|
||||||
def is_running(self):
|
def is_running(self):
|
||||||
@ -313,7 +320,7 @@ class VPCSVM(BaseVM):
|
|||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
|
|
||||||
self._ethernet_adapter.add_nio(port_number, nio)
|
self._ethernet_adapter.add_nio(port_number, nio)
|
||||||
log.info("VPCS {name} [{id}]: {nio} added to port {port_number}".format(name=self._name,
|
log.info('VPCS "{name}" [{id}]: {nio} added to port {port_number}'.format(name=self._name,
|
||||||
id=self.id,
|
id=self.id,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
@ -337,7 +344,7 @@ class VPCSVM(BaseVM):
|
|||||||
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
self.manager.port_manager.release_udp_port(nio.lport, self._project)
|
||||||
self._ethernet_adapter.remove_nio(port_number)
|
self._ethernet_adapter.remove_nio(port_number)
|
||||||
|
|
||||||
log.info("VPCS {name} [{id}]: {nio} removed from port {port_number}".format(name=self._name,
|
log.info('VPCS "{name}" [{id}]: {nio} removed from port {port_number}'.format(name=self._name,
|
||||||
id=self.id,
|
id=self.id,
|
||||||
nio=nio,
|
nio=nio,
|
||||||
port_number=port_number))
|
port_number=port_number))
|
||||||
@ -406,12 +413,12 @@ class VPCSVM(BaseVM):
|
|||||||
@property
|
@property
|
||||||
def script_file(self):
|
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')
|
path = os.path.join(self.working_dir, 'startup.vpc')
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return path
|
return path
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import shutil
|
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
|
Loading…
Reference in New Issue
Block a user