mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-04 06:21:15 +02:00
Drop Python 3.4 and switch to async / await syntax for asyncio. Fixes #1425
This commit is contained in:
1 parent
8baa480b79
commit
76af98404a
119 files changed
+2432
-3084
No files matched your search
@@ -34,9 +34,8 @@ import re
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
from gns3server.utils.interfaces import interfaces, is_interface_up
|
||||
from gns3server.utils.asyncio import wait_run_in_executor, asyncio_ensure_future
|
||||
from gns3server.utils.asyncio import wait_run_in_executor
|
||||
from gns3server.utils import parse_version
|
||||
from gns3server.utils.asyncio import asyncio_ensure_future
|
||||
from uuid import uuid4
|
||||
from ..base_manager import BaseManager
|
||||
from ..port_manager import PortManager
|
||||
@@ -166,17 +165,16 @@ class Dynamips(BaseManager):
|
||||
if dynamips_id in self._dynamips_ids[project_id]:
|
||||
self._dynamips_ids[project_id].remove(dynamips_id)
|
||||
|
||||
@asyncio.coroutine
|
||||
def unload(self):
|
||||
async def unload(self):
|
||||
|
||||
yield from BaseManager.unload(self)
|
||||
await BaseManager.unload(self)
|
||||
|
||||
tasks = []
|
||||
for device in self._devices.values():
|
||||
tasks.append(asyncio_ensure_future(device.hypervisor.stop()))
|
||||
tasks.append(asyncio.ensure_future(device.hypervisor.stop()))
|
||||
|
||||
if tasks:
|
||||
done, _ = yield from asyncio.wait(tasks)
|
||||
done, _ = await asyncio.wait(tasks)
|
||||
for future in done:
|
||||
try:
|
||||
future.result()
|
||||
@@ -184,37 +182,35 @@ class Dynamips(BaseManager):
|
||||
log.error("Could not stop device hypervisor {}".format(e), exc_info=1)
|
||||
continue
|
||||
|
||||
@asyncio.coroutine
|
||||
def project_closing(self, project):
|
||||
async def project_closing(self, project):
|
||||
"""
|
||||
Called when a project is about to be closed.
|
||||
|
||||
:param project: Project instance
|
||||
"""
|
||||
|
||||
yield from super().project_closing(project)
|
||||
await super().project_closing(project)
|
||||
# delete the Dynamips devices corresponding to the project
|
||||
tasks = []
|
||||
for device in self._devices.values():
|
||||
if device.project.id == project.id:
|
||||
tasks.append(asyncio_ensure_future(device.delete()))
|
||||
tasks.append(asyncio.ensure_future(device.delete()))
|
||||
|
||||
if tasks:
|
||||
done, _ = yield from asyncio.wait(tasks)
|
||||
done, _ = await asyncio.wait(tasks)
|
||||
for future in done:
|
||||
try:
|
||||
future.result()
|
||||
except (Exception, GeneratorExit) as e:
|
||||
log.error("Could not delete device {}".format(e), exc_info=1)
|
||||
|
||||
@asyncio.coroutine
|
||||
def project_closed(self, project):
|
||||
async def project_closed(self, project):
|
||||
"""
|
||||
Called when a project is closed.
|
||||
|
||||
:param project: Project instance
|
||||
"""
|
||||
yield from super().project_closed(project)
|
||||
await super().project_closed(project)
|
||||
# delete useless Dynamips files
|
||||
project_dir = project.module_working_path(self.module_name.lower())
|
||||
|
||||
@@ -230,7 +226,7 @@ class Dynamips(BaseManager):
|
||||
log.debug("Deleting file {}".format(file))
|
||||
if file in self._ghost_files:
|
||||
self._ghost_files.remove(file)
|
||||
yield from wait_run_in_executor(os.remove, file)
|
||||
await wait_run_in_executor(os.remove, file)
|
||||
except OSError as e:
|
||||
log.warning("Could not delete file {}: {}".format(file, e))
|
||||
continue
|
||||
@@ -267,8 +263,7 @@ class Dynamips(BaseManager):
|
||||
self._dynamips_path = dynamips_path
|
||||
return dynamips_path
|
||||
|
||||
@asyncio.coroutine
|
||||
def start_new_hypervisor(self, working_dir=None):
|
||||
async def start_new_hypervisor(self, working_dir=None):
|
||||
"""
|
||||
Creates a new Dynamips process and start it.
|
||||
|
||||
@@ -306,27 +301,25 @@ class Dynamips(BaseManager):
|
||||
hypervisor = Hypervisor(self._dynamips_path, working_dir, server_host, port, port_manager.console_host)
|
||||
|
||||
log.info("Creating new hypervisor {}:{} with working directory {}".format(hypervisor.host, hypervisor.port, working_dir))
|
||||
yield from hypervisor.start()
|
||||
await hypervisor.start()
|
||||
log.info("Hypervisor {}:{} has successfully started".format(hypervisor.host, hypervisor.port))
|
||||
yield from hypervisor.connect()
|
||||
await hypervisor.connect()
|
||||
if parse_version(hypervisor.version) < parse_version('0.2.11'):
|
||||
raise DynamipsError("Dynamips version must be >= 0.2.11, detected version is {}".format(hypervisor.version))
|
||||
|
||||
return hypervisor
|
||||
|
||||
@asyncio.coroutine
|
||||
def ghost_ios_support(self, vm):
|
||||
async def ghost_ios_support(self, vm):
|
||||
|
||||
ghost_ios_support = self.config.get_section_config("Dynamips").getboolean("ghost_ios_support", True)
|
||||
if ghost_ios_support:
|
||||
with (yield from Dynamips._ghost_ios_lock):
|
||||
async with Dynamips._ghost_ios_lock:
|
||||
try:
|
||||
yield from self._set_ghost_ios(vm)
|
||||
await self._set_ghost_ios(vm)
|
||||
except GeneratorExit:
|
||||
log.warning("Could not create ghost IOS image {} (GeneratorExit)".format(vm.name))
|
||||
|
||||
@asyncio.coroutine
|
||||
def create_nio(self, node, nio_settings):
|
||||
async def create_nio(self, node, nio_settings):
|
||||
"""
|
||||
Creates a new NIO.
|
||||
|
||||
@@ -394,11 +387,10 @@ class Dynamips(BaseManager):
|
||||
else:
|
||||
raise aiohttp.web.HTTPConflict(text="NIO of type {} is not supported".format(nio_settings["type"]))
|
||||
|
||||
yield from nio.create()
|
||||
await nio.create()
|
||||
return nio
|
||||
|
||||
@asyncio.coroutine
|
||||
def _set_ghost_ios(self, vm):
|
||||
async def _set_ghost_ios(self, vm):
|
||||
"""
|
||||
Manages Ghost IOS support.
|
||||
|
||||
@@ -421,29 +413,28 @@ class Dynamips(BaseManager):
|
||||
ghost_id = str(uuid4())
|
||||
ghost = Router("ghost-" + ghost_file, ghost_id, vm.project, vm.manager, platform=vm.platform, hypervisor=vm.hypervisor, ghost_flag=True)
|
||||
try:
|
||||
yield from ghost.create()
|
||||
yield from ghost.set_image(vm.image)
|
||||
yield from ghost.set_ghost_status(1)
|
||||
yield from ghost.set_ghost_file(ghost_file_path)
|
||||
yield from ghost.set_ram(vm.ram)
|
||||
await ghost.create()
|
||||
await ghost.set_image(vm.image)
|
||||
await ghost.set_ghost_status(1)
|
||||
await ghost.set_ghost_file(ghost_file_path)
|
||||
await ghost.set_ram(vm.ram)
|
||||
try:
|
||||
yield from ghost.start()
|
||||
yield from ghost.stop()
|
||||
await ghost.start()
|
||||
await ghost.stop()
|
||||
self._ghost_files.add(ghost_file_path)
|
||||
except DynamipsError:
|
||||
raise
|
||||
finally:
|
||||
yield from ghost.clean_delete()
|
||||
await ghost.clean_delete()
|
||||
except DynamipsError as e:
|
||||
log.warning("Could not create ghost instance: {}".format(e))
|
||||
|
||||
if vm.ghost_file != ghost_file and os.path.isfile(ghost_file_path):
|
||||
# set the ghost file to the router
|
||||
yield from vm.set_ghost_status(2)
|
||||
yield from vm.set_ghost_file(ghost_file_path)
|
||||
await vm.set_ghost_status(2)
|
||||
await vm.set_ghost_file(ghost_file_path)
|
||||
|
||||
@asyncio.coroutine
|
||||
def update_vm_settings(self, vm, settings):
|
||||
async def update_vm_settings(self, vm, settings):
|
||||
"""
|
||||
Updates the VM settings.
|
||||
|
||||
@@ -455,23 +446,23 @@ class Dynamips(BaseManager):
|
||||
if hasattr(vm, name) and getattr(vm, name) != value:
|
||||
if hasattr(vm, "set_{}".format(name)):
|
||||
setter = getattr(vm, "set_{}".format(name))
|
||||
yield from setter(value)
|
||||
await setter(value)
|
||||
elif name.startswith("slot") and value in ADAPTER_MATRIX:
|
||||
slot_id = int(name[-1])
|
||||
adapter_name = value
|
||||
adapter = ADAPTER_MATRIX[adapter_name]()
|
||||
try:
|
||||
if vm.slots[slot_id] and not isinstance(vm.slots[slot_id], type(adapter)):
|
||||
yield from vm.slot_remove_binding(slot_id)
|
||||
await vm.slot_remove_binding(slot_id)
|
||||
if not isinstance(vm.slots[slot_id], type(adapter)):
|
||||
yield from vm.slot_add_binding(slot_id, adapter)
|
||||
await vm.slot_add_binding(slot_id, adapter)
|
||||
except IndexError:
|
||||
raise DynamipsError("Slot {} doesn't exist on this router".format(slot_id))
|
||||
elif name.startswith("slot") and (value is None or value is ""):
|
||||
slot_id = int(name[-1])
|
||||
try:
|
||||
if vm.slots[slot_id]:
|
||||
yield from vm.slot_remove_binding(slot_id)
|
||||
await vm.slot_remove_binding(slot_id)
|
||||
except IndexError:
|
||||
raise DynamipsError("Slot {} doesn't exist on this router".format(slot_id))
|
||||
elif name.startswith("wic") and value in WIC_MATRIX:
|
||||
@@ -480,32 +471,31 @@ class Dynamips(BaseManager):
|
||||
wic = WIC_MATRIX[wic_name]()
|
||||
try:
|
||||
if vm.slots[0].wics[wic_slot_id] and not isinstance(vm.slots[0].wics[wic_slot_id], type(wic)):
|
||||
yield from vm.uninstall_wic(wic_slot_id)
|
||||
await vm.uninstall_wic(wic_slot_id)
|
||||
if not isinstance(vm.slots[0].wics[wic_slot_id], type(wic)):
|
||||
yield from vm.install_wic(wic_slot_id, wic)
|
||||
await vm.install_wic(wic_slot_id, wic)
|
||||
except IndexError:
|
||||
raise DynamipsError("WIC slot {} doesn't exist on this router".format(wic_slot_id))
|
||||
elif name.startswith("wic") and (value is None or value is ""):
|
||||
wic_slot_id = int(name[-1])
|
||||
try:
|
||||
if vm.slots[0].wics and vm.slots[0].wics[wic_slot_id]:
|
||||
yield from vm.uninstall_wic(wic_slot_id)
|
||||
await vm.uninstall_wic(wic_slot_id)
|
||||
except IndexError:
|
||||
raise DynamipsError("WIC slot {} doesn't exist on this router".format(wic_slot_id))
|
||||
|
||||
mmap_support = self.config.get_section_config("Dynamips").getboolean("mmap_support", True)
|
||||
if mmap_support is False:
|
||||
yield from vm.set_mmap(False)
|
||||
await vm.set_mmap(False)
|
||||
|
||||
sparse_memory_support = self.config.get_section_config("Dynamips").getboolean("sparse_memory_support", True)
|
||||
if sparse_memory_support is False:
|
||||
yield from vm.set_sparsemem(False)
|
||||
await vm.set_sparsemem(False)
|
||||
|
||||
# update the configs if needed
|
||||
yield from self.set_vm_configs(vm, settings)
|
||||
await self.set_vm_configs(vm, settings)
|
||||
|
||||
@asyncio.coroutine
|
||||
def set_vm_configs(self, vm, settings):
|
||||
async def set_vm_configs(self, vm, settings):
|
||||
"""
|
||||
Set VM configs from pushed content or existing config files.
|
||||
|
||||
@@ -554,25 +544,24 @@ class Dynamips(BaseManager):
|
||||
|
||||
return os.path.join("configs", os.path.basename(path))
|
||||
|
||||
@asyncio.coroutine
|
||||
def auto_idlepc(self, vm):
|
||||
async def auto_idlepc(self, vm):
|
||||
"""
|
||||
Try to find the best possible idle-pc value.
|
||||
|
||||
:param vm: VM instance
|
||||
"""
|
||||
|
||||
yield from vm.set_idlepc("0x0")
|
||||
await vm.set_idlepc("0x0")
|
||||
was_auto_started = False
|
||||
old_priority = None
|
||||
try:
|
||||
status = yield from vm.get_status()
|
||||
status = await vm.get_status()
|
||||
if status != "running":
|
||||
yield from vm.start()
|
||||
await vm.start()
|
||||
was_auto_started = True
|
||||
yield from asyncio.sleep(20) # leave time to the router to boot
|
||||
await asyncio.sleep(20) # leave time to the router to boot
|
||||
validated_idlepc = None
|
||||
idlepcs = yield from vm.get_idle_pc_prop()
|
||||
idlepcs = await vm.get_idle_pc_prop()
|
||||
if not idlepcs:
|
||||
raise DynamipsError("No Idle-PC values found")
|
||||
|
||||
@@ -582,14 +571,14 @@ class Dynamips(BaseManager):
|
||||
match = re.search(r"^0x[0-9a-f]{8}$", idlepc.split()[0])
|
||||
if not match:
|
||||
continue
|
||||
yield from vm.set_idlepc(idlepc.split()[0])
|
||||
await vm.set_idlepc(idlepc.split()[0])
|
||||
log.debug("Auto Idle-PC: trying idle-PC value {}".format(vm.idlepc))
|
||||
start_time = time.time()
|
||||
initial_cpu_usage = yield from vm.get_cpu_usage()
|
||||
initial_cpu_usage = await vm.get_cpu_usage()
|
||||
log.debug("Auto Idle-PC: initial CPU usage is {}%".format(initial_cpu_usage))
|
||||
yield from asyncio.sleep(3) # wait 3 seconds to probe the cpu again
|
||||
await asyncio.sleep(3) # wait 3 seconds to probe the cpu again
|
||||
elapsed_time = time.time() - start_time
|
||||
cpu_usage = yield from vm.get_cpu_usage()
|
||||
cpu_usage = await vm.get_cpu_usage()
|
||||
cpu_elapsed_usage = cpu_usage - initial_cpu_usage
|
||||
cpu_usage = abs(cpu_elapsed_usage * 100.0 / elapsed_time)
|
||||
if cpu_usage > 100:
|
||||
@@ -609,11 +598,10 @@ class Dynamips(BaseManager):
|
||||
if old_priority is not None:
|
||||
vm.set_process_priority_windows(vm.hypervisor.process.pid, old_priority)
|
||||
if was_auto_started:
|
||||
yield from vm.stop()
|
||||
await vm.stop()
|
||||
return validated_idlepc
|
||||
|
||||
@asyncio.coroutine
|
||||
def duplicate_node(self, source_node_id, destination_node_id):
|
||||
async def duplicate_node(self, source_node_id, destination_node_id):
|
||||
"""
|
||||
Duplicate a node
|
||||
|
||||
@@ -626,7 +614,7 @@ class Dynamips(BaseManager):
|
||||
|
||||
# Not a Dynamips router
|
||||
if not hasattr(source_node, "startup_config_path"):
|
||||
return (yield from super().duplicate_node(source_node_id, destination_node_id))
|
||||
return (await super().duplicate_node(source_node_id, destination_node_id))
|
||||
|
||||
try:
|
||||
with open(source_node.startup_config_path) as f:
|
||||
@@ -638,13 +626,13 @@ class Dynamips(BaseManager):
|
||||
private_config = f.read()
|
||||
except OSError:
|
||||
private_config = None
|
||||
yield from self.set_vm_configs(destination_node, {
|
||||
await self.set_vm_configs(destination_node, {
|
||||
"startup_config_content": startup_config,
|
||||
"private_config_content": private_config
|
||||
})
|
||||
|
||||
# Force refresh of the name in configuration files
|
||||
new_name = destination_node.name
|
||||
yield from destination_node.set_name(source_node.name)
|
||||
yield from destination_node.set_name(new_name)
|
||||
await destination_node.set_name(source_node.name)
|
||||
await destination_node.set_name(new_name)
|
||||
return destination_node
|
||||
Reference in new issue
Block a user