mirror of https://github.com/GNS3/gns3-server
parent
6d20a122f8
commit
369cd06279
@ -1,66 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
|
||||
|
||||
#TODO: make this more generic (not json but *args?)
|
||||
class BaseModule(object):
|
||||
_instance = None
|
||||
|
||||
@classmethod
|
||||
def instance(cls):
|
||||
if cls._instance is None:
|
||||
cls._instance = cls()
|
||||
asyncio.async(cls._instance.run())
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
self._queue = asyncio.Queue()
|
||||
|
||||
@classmethod
|
||||
def destroy(cls):
|
||||
future = asyncio.Future()
|
||||
cls._instance._queue.put_nowait((future, None, ))
|
||||
yield from asyncio.wait([future])
|
||||
cls._instance = None
|
||||
|
||||
@asyncio.coroutine
|
||||
def put(self, json):
|
||||
|
||||
future = asyncio.Future()
|
||||
self._queue.put_nowait((future, json, ))
|
||||
yield from asyncio.wait([future])
|
||||
return future.result()
|
||||
|
||||
@asyncio.coroutine
|
||||
def run(self):
|
||||
|
||||
while True:
|
||||
future, json = yield from self._queue.get()
|
||||
if json is None:
|
||||
future.set_result(True)
|
||||
break
|
||||
try:
|
||||
result = yield from self.process(json)
|
||||
future.set_result(result)
|
||||
except Exception as e:
|
||||
future.set_exception(e)
|
||||
|
||||
@asyncio.coroutine
|
||||
def process(self, json):
|
||||
raise NotImplementedError
|
@ -0,0 +1,99 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import asyncio
|
||||
from .vm_error import VMError
|
||||
|
||||
|
||||
class BaseVM:
|
||||
|
||||
def __init__(self, name, identifier):
|
||||
self._queue = asyncio.Queue()
|
||||
self._name = name
|
||||
self._id = identifier
|
||||
self._created = asyncio.Future()
|
||||
self._worker = asyncio.async(self._run())
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
Returns the unique ID for this VM.
|
||||
|
||||
:returns: id (integer)
|
||||
"""
|
||||
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
Returns the name for this VM.
|
||||
|
||||
:returns: name (string)
|
||||
"""
|
||||
|
||||
return self._name
|
||||
|
||||
@asyncio.coroutine
|
||||
def _execute(self, subcommand, args):
|
||||
"""Called when we receive an event"""
|
||||
raise NotImplementedError
|
||||
|
||||
@asyncio.coroutine
|
||||
def _create(self):
|
||||
"""Called when the run loop start"""
|
||||
raise NotImplementedError
|
||||
|
||||
@asyncio.coroutine
|
||||
def _run(self, timeout=60):
|
||||
|
||||
try:
|
||||
yield from self._create()
|
||||
self._created.set_result(True)
|
||||
except VMError as e:
|
||||
self._created.set_exception(e)
|
||||
return
|
||||
|
||||
while True:
|
||||
future, subcommand, args = yield from self._queue.get()
|
||||
try:
|
||||
try:
|
||||
yield from asyncio.wait_for(self._execute(subcommand, args), timeout=timeout)
|
||||
except asyncio.TimeoutError:
|
||||
raise VMError("{} has timed out after {} seconds!".format(subcommand, timeout))
|
||||
future.set_result(True)
|
||||
except Exception as e:
|
||||
future.set_exception(e)
|
||||
|
||||
def wait_for_creation(self):
|
||||
return self._created
|
||||
|
||||
def put(self, *args):
|
||||
"""
|
||||
Add to the processing queue of the VM
|
||||
|
||||
:returns: future
|
||||
"""
|
||||
|
||||
future = asyncio.Future()
|
||||
try:
|
||||
args.insert(0, future)
|
||||
self._queue.put_nowait(args)
|
||||
except asyncio.qeues.QueueFull:
|
||||
raise VMError("Queue is full")
|
||||
return future
|
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
class VMError(Exception):
|
||||
pass
|
@ -0,0 +1,89 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import asyncio
|
||||
import aiohttp
|
||||
|
||||
from .vm_error import VMError
|
||||
|
||||
|
||||
class VMManager:
|
||||
"""
|
||||
Base class for all VMManager.
|
||||
Responsible of management of a VM pool
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._vms = {}
|
||||
|
||||
@classmethod
|
||||
def instance(cls):
|
||||
"""
|
||||
Singleton to return only one instance of Manager.
|
||||
|
||||
:returns: instance of Manager
|
||||
"""
|
||||
|
||||
if not hasattr(cls, "_instance"):
|
||||
cls._instance = cls()
|
||||
return cls._instance
|
||||
|
||||
@classmethod
|
||||
@asyncio.coroutine
|
||||
def destroy(cls):
|
||||
cls._instance = None
|
||||
|
||||
def _get_vm_instance(self, vm_id):
|
||||
"""
|
||||
Returns a VM instance.
|
||||
|
||||
:param vm_id: VM identifier
|
||||
|
||||
:returns: VM instance
|
||||
"""
|
||||
|
||||
if vm_id not in self._vms:
|
||||
raise aiohttp.web.HTTPNotFound(text="ID {} doesn't exist".format(vm_id))
|
||||
return self._vms[vm_id]
|
||||
|
||||
@asyncio.coroutine
|
||||
def create_vm(self, vmname, identifier=None):
|
||||
if not identifier:
|
||||
for i in range(1, 1024):
|
||||
if i not in self._vms:
|
||||
identifier = i
|
||||
break
|
||||
if identifier == 0:
|
||||
raise VMError("Maximum number of VM instances reached")
|
||||
else:
|
||||
if identifier in self._vms:
|
||||
raise VMError("VM identifier {} is already used by another VM instance".format(identifier))
|
||||
vm = self._VM_CLASS(vmname, identifier)
|
||||
yield from vm.wait_for_creation()
|
||||
self._vms[vm.id] = vm
|
||||
return vm
|
||||
|
||||
@asyncio.coroutine
|
||||
def start_vm(self, vm_id):
|
||||
vm = self._get_vm_instance(vm_id)
|
||||
yield from vm.start()
|
||||
|
||||
@asyncio.coroutine
|
||||
def stop_vm(self, vm_id):
|
||||
vm = self._get_vm_instance(vm_id)
|
||||
yield from vm.stop()
|
@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2015 GNS3 Technologies Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from ..base_vm import BaseVM
|
||||
|
||||
|
||||
class VPCSDevice(BaseVM):
|
||||
pass
|
Loading…
Reference in new issue