-
Notifications
You must be signed in to change notification settings - Fork 244
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Virtual Machines Management(VMM)
Signed-off-by: Yongxue Hong <[email protected]>
- Loading branch information
1 parent
aa3836f
commit 3fecc93
Showing
13 changed files
with
694 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import json | ||
import signal | ||
from functools import partial | ||
|
||
import six | ||
|
||
from abc import ABCMeta | ||
from abc import abstractmethod | ||
|
||
import aexpect | ||
|
||
from . import qemu | ||
from . import libvirt | ||
|
||
|
||
@six.add_metaclass(ABCMeta) | ||
class InstanceDriver(object): | ||
def __init__(self, kind, spec): | ||
self._kind = kind | ||
self._params = json.loads(spec) | ||
self._process = None | ||
self._cmd = None | ||
self._devices = None | ||
|
||
@abstractmethod | ||
def create_devices(self): | ||
raise NotImplementedError | ||
|
||
@abstractmethod | ||
def make_cmdline(self): | ||
raise NotImplementedError | ||
|
||
def run_cmdline(self, command, termination_func=None, output_func=None, | ||
output_prefix="", timeout=1.0, auto_close=True, pass_fds=(), | ||
encoding=None): | ||
self._process = aexpect.run_tail( | ||
command, termination_func, output_func, output_prefix, | ||
timeout, auto_close, pass_fds, encoding) | ||
|
||
def get_pid(self): | ||
return self._process.get_pid() | ||
|
||
def get_status(self): | ||
return self._process.get_status() | ||
|
||
def get_output(self): | ||
return self._process.get_output() | ||
|
||
def is_alive(self): | ||
return self._process.is_alive() | ||
|
||
def kill(self, sig=signal.SIGKILL): | ||
self._process.kill(sig) | ||
|
||
|
||
def get_instance_driver(kind, spec): | ||
instance_drivers = { | ||
"qemu": qemu.QemuInstanceDriver(spec), | ||
"libvirt": libvirt.LibvirtInstanceDriver(spec), | ||
} | ||
|
||
if kind not in instance_drivers: | ||
raise OSError("No support the %s instance driver" % kind) | ||
return instance_drivers.get(kind, spec) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from . import InstanceDriver | ||
|
||
|
||
class LibvirtInstanceDriver(InstanceDriver): | ||
def __init__(self, spec): | ||
super(LibvirtInstanceDriver, self).__init__("libvirt", spec) | ||
|
||
def create_devices(self): | ||
pass | ||
|
||
def make_cmdline(self): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import logging | ||
|
||
from virttest.qemu_devices import qdevices, qcontainer | ||
|
||
from . import InstanceDriver | ||
|
||
LOG = logging.getLogger("avocado.agent." + __name__) | ||
|
||
|
||
class QemuInstanceDriver(InstanceDriver): | ||
def __init__(self, spec): | ||
super(QemuInstanceDriver, self).__init__("qemu", spec) | ||
|
||
def create_devices(self): | ||
|
||
def _add_name(name): | ||
return " -name '%s'" % name | ||
|
||
def _process_sandbox(devices, action): | ||
if action == "add": | ||
if devices.has_option("sandbox"): | ||
return " -sandbox on " | ||
elif action == "rem": | ||
if devices.has_option("sandbox"): | ||
return " -sandbox off " | ||
|
||
qemu_binary = "/usr/libexec/qemu-kvm" | ||
name = self._params.get("name") | ||
self._devices = qcontainer.DevContainer(qemu_binary, name) | ||
StrDev = qdevices.QStringDevice | ||
|
||
self._devices.insert(StrDev('qemu', cmdline=qemu_binary)) | ||
|
||
qemu_preconfig = self._params.get("qemu_preconfig") | ||
if qemu_preconfig: | ||
self._devices.insert(StrDev('preconfig', cmdline="--preconfig")) | ||
|
||
self._devices.insert(StrDev('vmname', cmdline=_add_name(name))) | ||
|
||
qemu_sandbox = self._params.get("qemu_sandbox") | ||
if qemu_sandbox == "on": | ||
self._devices.insert( | ||
StrDev('qemu_sandbox', cmdline=_process_sandbox(self._devices, "add"))) | ||
elif qemu_sandbox == "off": | ||
self.devices.insert( | ||
StrDev('qemu_sandbox', cmdline=_process_sandbox(self._devices, "rem"))) | ||
|
||
defaults = self._params.get("defaults", "no") | ||
if self._devices.has_option("nodefaults") and defaults != "yes": | ||
self._devices.insert(StrDev('nodefaults', cmdline=" -nodefaults")) | ||
|
||
return self._devices | ||
|
||
def make_cmdline(self): | ||
self._cmd = self._devices.cmdline() | ||
return self._cmd |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import json | ||
import logging | ||
|
||
from .. import instance_drivers | ||
|
||
LOG = logging.getLogger("avocado.agent." + __name__) | ||
|
||
|
||
class VMMError(Exception): | ||
pass | ||
|
||
|
||
class VirtualMachinesManager(object): | ||
def __init__(self): | ||
self._filename = "/var/instances" | ||
self._instances = self._load() | ||
|
||
@property | ||
def instances(self): | ||
return self._load() | ||
|
||
def _dump_instances(self): | ||
with open(self._filename, "w") as details: | ||
json.dump(self._instances, details) | ||
|
||
def _load_instances(self): | ||
try: | ||
with open(self._filename, 'r') as instances: | ||
return json.load(instances) | ||
except Exception: | ||
return {} | ||
|
||
def _save(self): | ||
self._dump_instances() | ||
|
||
def _load(self): | ||
return self._load_instances() | ||
|
||
def register_instance(self, name, info): | ||
if name in self._instances: | ||
LOG.error("The instance %s is already registered.", name) | ||
return False | ||
self._instances[name] = info | ||
self._save() | ||
return True | ||
|
||
def unregister_instance(self, name): | ||
if name in self._instances: | ||
del self._instances[name] | ||
self._save() | ||
return True | ||
LOG.error("The instance %s is not registered" % name) | ||
return False | ||
|
||
def get_instance(self, name): | ||
return self._instances.get(name) | ||
|
||
def update_instance(self, name, info): | ||
self._instances.get(name).update(info) | ||
self._save() | ||
|
||
@staticmethod | ||
def build_instance(driver_kind, spec): | ||
instance_info = {} | ||
instance_driver = instance_drivers.get_instance_driver(driver_kind, spec) | ||
instance_info["devices"] = instance_driver.create_devices() | ||
instance_info["driver"] = instance_driver | ||
return instance_info | ||
|
||
def run_instance(self, instance_id): | ||
instance_info = self.get_instance(instance_id) | ||
instance_driver = instance_info["driver"] | ||
cmdline = instance_driver.make_cmdline() | ||
instance_info["cmdline"] = cmdline | ||
process = instance_driver.run_cmdline(cmdline) | ||
instance_info["process"] = process | ||
|
||
def stop_instance(self, instance_id): | ||
instance_info = self.get_instance(instance_id) | ||
instance_driver = instance_info["driver"] | ||
if instance_driver.is_alive(): | ||
pass | ||
|
||
def get_instance_status(self, instance_id): | ||
pass | ||
|
||
def get_instance_pid(self, instance_id): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import logging | ||
|
||
from ...managers import vmm | ||
|
||
VMM = vmm.VirtualMachinesManager() | ||
|
||
LOG = logging.getLogger('avocado.service.' + __name__) | ||
|
||
|
||
def build_instance(instance_id, instance_driver, instance_spec): | ||
if instance_id in VMM.instances: | ||
raise vmm.VMMError(f"The instance {instance_id} was registered.") | ||
|
||
LOG.info(f"Build the instance {instance_id} by {instance_spec}") | ||
|
||
instance_info = VMM.build_instance(instance_driver, instance_spec) | ||
VMM.register_instance(instance_id, instance_info) | ||
|
||
|
||
def run_instance(instance_id): | ||
VMM.run_instance(instance_id) | ||
|
||
|
||
def stop_instance(instance_id): | ||
VMM.stop_instance(instance_id) | ||
|
||
|
||
def get_instance_status(instance_id): | ||
return VMM.get_instance_status(instance_id) | ||
|
||
|
||
def get_instance_pid(instance_id): | ||
return VMM.get_instance_pid(instance_id) | ||
|
||
|
||
def get_instance_monitors(instance_id): | ||
return [] | ||
|
Empty file.
Oops, something went wrong.