Skip to content

Commit

Permalink
Merge "libvirt: move domain info to guest"
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenkins authored and openstack-gerrit committed Aug 28, 2015
2 parents 8124bde + 13505fa commit 5d54e3d
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 71 deletions.
17 changes: 9 additions & 8 deletions nova/tests/unit/virt/libvirt/test_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -8693,11 +8693,11 @@ def wait(self):
# Mock domain
mock_domain = self.mox.CreateMock(fakelibvirt.virDomain)
mock_domain.info().AndReturn(
(libvirt_driver.VIR_DOMAIN_RUNNING,) + info_tuple)
(libvirt_guest.VIR_DOMAIN_RUNNING,) + info_tuple)
mock_domain.ID().AndReturn('some_fake_id')
mock_domain.shutdown()
mock_domain.info().AndReturn(
(libvirt_driver.VIR_DOMAIN_CRASHED,) + info_tuple)
(libvirt_guest.VIR_DOMAIN_CRASHED,) + info_tuple)
mock_domain.ID().AndReturn('some_other_fake_id')

self.mox.ReplayAll()
Expand Down Expand Up @@ -8739,8 +8739,8 @@ def wait(self):

# Mock domain
mock_domain = mock.Mock(fakelibvirt.virDomain)
return_values = [(libvirt_driver.VIR_DOMAIN_RUNNING,) + info_tuple,
(libvirt_driver.VIR_DOMAIN_CRASHED,) + info_tuple]
return_values = [(libvirt_guest.VIR_DOMAIN_RUNNING,) + info_tuple,
(libvirt_guest.VIR_DOMAIN_CRASHED,) + info_tuple]
mock_domain.info.side_effect = return_values
mock_domain.ID.return_value = 'some_fake_id'
mock_domain.shutdown.side_effect = mock.Mock()
Expand All @@ -8767,7 +8767,7 @@ def test_soft_reboot_libvirt_exception(self, mock_get_domain,
# setup mocks
mock_virDomain = mock.Mock(fakelibvirt.virDomain)
mock_virDomain.info.return_value = (
(libvirt_driver.VIR_DOMAIN_RUNNING,) + info_tuple)
(libvirt_guest.VIR_DOMAIN_RUNNING,) + info_tuple)
mock_virDomain.ID.return_value = 'some_fake_id'
mock_virDomain.shutdown.side_effect = fakelibvirt.libvirtError('Err')

Expand Down Expand Up @@ -8948,12 +8948,12 @@ def _test_clean_shutdown(self, mock_get_domain, mock_create_domain,

# Mock domain
mock_domain = mock.Mock(fakelibvirt.virDomain)
return_infos = [(libvirt_driver.VIR_DOMAIN_RUNNING,) + info_tuple]
return_infos = [(libvirt_guest.VIR_DOMAIN_RUNNING,) + info_tuple]
return_shutdowns = [shutdown_count.append("shutdown")]
retry_countdown = retry_interval
for x in range(min(seconds_to_shutdown, timeout)):
return_infos.append(
(libvirt_driver.VIR_DOMAIN_RUNNING,) + info_tuple)
(libvirt_guest.VIR_DOMAIN_RUNNING,) + info_tuple)
if retry_countdown == 0:
return_shutdowns.append(shutdown_count.append("shutdown"))
retry_countdown = retry_interval
Expand All @@ -8962,7 +8962,7 @@ def _test_clean_shutdown(self, mock_get_domain, mock_create_domain,

if seconds_to_shutdown < timeout:
return_infos.append(
(libvirt_driver.VIR_DOMAIN_SHUTDOWN,) + info_tuple)
(libvirt_guest.VIR_DOMAIN_SHUTDOWN,) + info_tuple)

mock_domain.info.side_effect = return_infos
mock_domain.shutdown.side_effect = return_shutdowns
Expand Down Expand Up @@ -9266,6 +9266,7 @@ def test_private_destroy_not_found(self):
mock.ID()
mock.destroy().AndRaise(ex)
mock.info().AndRaise(ex)
mock.UUIDString()
self.mox.ReplayAll()

def fake_get_domain(instance):
Expand Down
12 changes: 12 additions & 0 deletions nova/tests/unit/virt/libvirt/test_guest.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,18 @@ def test_get_devices(self):
self.assertIsInstance(devs[0], vconfig.LibvirtConfigGuestHostdev)
self.assertIsInstance(devs[1], vconfig.LibvirtConfigGuestHostdev)

def test_get_info(self):
self.domain.info.return_value = (1, 2, 3, 4, 5)
self.domain.ID.return_value = 6
info = self.guest.get_info(self.host)
self.domain.info.assert_called_once_with()
self.assertEqual(1, info.state)
self.assertEqual(2, info.max_mem_kb)
self.assertEqual(3, info.mem_kb)
self.assertEqual(4, info.num_cpu)
self.assertEqual(5, info.cpu_time_ns)
self.assertEqual(6, info.id)


class GuestBlockTestCase(test.NoDBTestCase):

Expand Down
69 changes: 13 additions & 56 deletions nova/virt/libvirt/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,34 +356,6 @@ def repr_method(self):

patch_tpool_proxy()

VIR_DOMAIN_NOSTATE = 0
VIR_DOMAIN_RUNNING = 1
VIR_DOMAIN_BLOCKED = 2
VIR_DOMAIN_PAUSED = 3
VIR_DOMAIN_SHUTDOWN = 4
VIR_DOMAIN_SHUTOFF = 5
VIR_DOMAIN_CRASHED = 6
VIR_DOMAIN_PMSUSPENDED = 7

LIBVIRT_POWER_STATE = {
VIR_DOMAIN_NOSTATE: power_state.NOSTATE,
VIR_DOMAIN_RUNNING: power_state.RUNNING,
# NOTE(maoy): The DOMAIN_BLOCKED state is only valid in Xen.
# It means that the VM is running and the vCPU is idle. So,
# we map it to RUNNING
VIR_DOMAIN_BLOCKED: power_state.RUNNING,
VIR_DOMAIN_PAUSED: power_state.PAUSED,
# NOTE(maoy): The libvirt API doc says that DOMAIN_SHUTDOWN
# means the domain is being shut down. So technically the domain
# is still running. SHUTOFF is the real powered off state.
# But we will map both to SHUTDOWN anyway.
# http://libvirt.org/html/libvirt-libvirt.html
VIR_DOMAIN_SHUTDOWN: power_state.SHUTDOWN,
VIR_DOMAIN_SHUTOFF: power_state.SHUTDOWN,
VIR_DOMAIN_CRASHED: power_state.CRASHED,
VIR_DOMAIN_PMSUSPENDED: power_state.SUSPENDED,
}

# This is effectively the min version for i686/x86_64 + KVM/QEMU
# TODO(berrange) find out what min version ppc64 needs as it
# almost certainly wants something newer than this....
Expand Down Expand Up @@ -4382,31 +4354,9 @@ def get_info(self, instance):
"""
guest = self._host.get_guest(instance)

# TODO(sahid): We are converting all calls from a
# virDomain object to use nova.virt.libvirt.Guest.
# We should be able to remove virt_dom at the end.
virt_dom = guest._domain
try:
dom_info = self._host.get_domain_info(virt_dom)
except libvirt.libvirtError as ex:
error_code = ex.get_error_code()
if error_code == libvirt.VIR_ERR_NO_DOMAIN:
raise exception.InstanceNotFound(instance_id=instance.uuid)

msg = (_('Error from libvirt while getting domain info for '
'%(instance_name)s: [Error Code %(error_code)s] %(ex)s') %
{'instance_name': instance.name,
'error_code': error_code,
'ex': ex})
raise exception.NovaException(msg)

return hardware.InstanceInfo(state=LIBVIRT_POWER_STATE[dom_info[0]],
max_mem_kb=dom_info[1],
mem_kb=dom_info[2],
num_cpu=dom_info[3],
cpu_time_ns=dom_info[4],
id=virt_dom.ID())
# Kind of ugly but we need to pass host to get_info as for a
# workaround, see libvirt/compat.py
return guest.get_info(self._host)

def _create_domain_setup_lxc(self, instance, image_meta,
block_device_info, disk_info):
Expand Down Expand Up @@ -7028,8 +6978,11 @@ def get_instance_diagnostics(self, instance):
xml = guest.get_xml_desc()
xml_doc = etree.fromstring(xml)

# TODO(sahid): Needs to use get_info but more changes have to
# be done since a mapping STATE_MAP LIBVIRT_POWER_STATE is
# needed.
(state, max_mem, mem, num_cpu, cpu_time) = \
self._host.get_domain_info(domain)
guest._get_domain_info(self._host)
config_drive = configdrive.required_by(instance)
launched_at = timeutils.normalize_time(instance.launched_at)
uptime = timeutils.delta_seconds(launched_at,
Expand Down Expand Up @@ -7226,5 +7179,9 @@ def is_supported_fs_format(self, fs_type):
disk.FS_FORMAT_EXT4, disk.FS_FORMAT_XFS]

def _get_power_state(self, virt_dom):
dom_info = self._host.get_domain_info(virt_dom)
return LIBVIRT_POWER_STATE[dom_info[0]]
# TODO(sahid): We should pass a guest object.
guest = libvirt_guest.Guest(virt_dom)
# TODO(sahid): Need to use guest.get_info. currently to many
# tests to have to be updated, will do the change soon.
info = guest._get_domain_info(self._host)
return libvirt_guest.LIBVIRT_POWER_STATE[info[0]]
72 changes: 72 additions & 0 deletions nova/virt/libvirt/guest.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,46 @@
from oslo_utils import excutils
from oslo_utils import importutils

from nova.compute import power_state
from nova import exception
from nova.i18n import _
from nova.i18n import _LE
from nova import utils
from nova.virt import hardware
from nova.virt.libvirt import compat
from nova.virt.libvirt import config as vconfig

libvirt = None

LOG = logging.getLogger(__name__)

VIR_DOMAIN_NOSTATE = 0
VIR_DOMAIN_RUNNING = 1
VIR_DOMAIN_BLOCKED = 2
VIR_DOMAIN_PAUSED = 3
VIR_DOMAIN_SHUTDOWN = 4
VIR_DOMAIN_SHUTOFF = 5
VIR_DOMAIN_CRASHED = 6
VIR_DOMAIN_PMSUSPENDED = 7

LIBVIRT_POWER_STATE = {
VIR_DOMAIN_NOSTATE: power_state.NOSTATE,
VIR_DOMAIN_RUNNING: power_state.RUNNING,
# The DOMAIN_BLOCKED state is only valid in Xen. It means that
# the VM is running and the vCPU is idle. So, we map it to RUNNING
VIR_DOMAIN_BLOCKED: power_state.RUNNING,
VIR_DOMAIN_PAUSED: power_state.PAUSED,
# The libvirt API doc says that DOMAIN_SHUTDOWN means the domain
# is being shut down. So technically the domain is still
# running. SHUTOFF is the real powered off state. But we will map
# both to SHUTDOWN anyway.
# http://libvirt.org/html/libvirt-libvirt.html
VIR_DOMAIN_SHUTDOWN: power_state.SHUTDOWN,
VIR_DOMAIN_SHUTOFF: power_state.SHUTDOWN,
VIR_DOMAIN_CRASHED: power_state.CRASHED,
VIR_DOMAIN_PMSUSPENDED: power_state.SUSPENDED,
}


class Guest(object):

Expand Down Expand Up @@ -290,6 +320,48 @@ def set_user_password(self, user, new_pass):
"""Configures a new user password."""
self._domain.setUserPassword(user, new_pass, 0)

def _get_domain_info(self, host):
"""Returns information on Guest
:param host: a host.Host object with current
connection. Unfortunatly we need to pass it
because of a workaround with < version 1.2..11
:returns list: [state, maxMem, memory, nrVirtCpu, cpuTime]
"""
return compat.get_domain_info(libvirt, host, self._domain)

def get_info(self, host):
"""Retrieve information from libvirt for a specific instance name.
If a libvirt error is encountered during lookup, we might raise a
NotFound exception or Error exception depending on how severe the
libvirt error is.
:returns hardware.InstanceInfo:
"""
try:
dom_info = self._get_domain_info(host)
except libvirt.libvirtError as ex:
error_code = ex.get_error_code()
if error_code == libvirt.VIR_ERR_NO_DOMAIN:
raise exception.InstanceNotFound(instance_id=self.uuid)

msg = (_('Error from libvirt while getting domain info for '
'%(instance_name)s: [Error Code %(error_code)s] %(ex)s') %
{'instance_name': self.name,
'error_code': error_code,
'ex': ex})
raise exception.NovaException(msg)

return hardware.InstanceInfo(
state=LIBVIRT_POWER_STATE[dom_info[0]],
max_mem_kb=dom_info[1],
mem_kb=dom_info[2],
num_cpu=dom_info[3],
cpu_time_ns=dom_info[4],
id=self.id)


class BlockDevice(object):
"""Wrapper around block device API"""
Expand Down
14 changes: 7 additions & 7 deletions nova/virt/libvirt/host.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@
from nova import rpc
from nova import utils
from nova.virt import event as virtevent
from nova.virt.libvirt import compat
from nova.virt.libvirt import config as vconfig
from nova.virt.libvirt import guest
from nova.virt.libvirt import guest as libvirt_guest

libvirt = None

Expand Down Expand Up @@ -613,7 +612,7 @@ def get_guest(self, instance):
:returns: a nova.virt.libvirt.Guest object
"""
return guest.Guest(
return libvirt_guest.Guest(
self.get_domain(instance))

def _get_domain_by_id(self, instance_id):
Expand Down Expand Up @@ -887,9 +886,6 @@ def delete_secret(self, usage_type, usage_id):
if secret is not None:
secret.undefine()

def get_domain_info(self, virt_dom):
return compat.get_domain_info(libvirt, self, virt_dom)

def _get_hardware_info(self):
"""Returns hardware information about the Node.
Expand Down Expand Up @@ -925,7 +921,11 @@ def get_memory_mb_used(self):
used = 0
for dom in self.list_instance_domains(only_guests=False):
try:
dom_mem = int(self.get_domain_info(dom)[2])
# TODO(sahid): we should have method list_guests()
# which returns Guest's objects
guest = libvirt_guest.Guest(dom)
# TODO(sahid): Use get_info...
dom_mem = int(guest._get_domain_info(self)[2])
except libvirt.libvirtError as e:
LOG.warn(_LW("couldn't obtain the memory from domain:"
" %(uuid)s, exception: %(ex)s") %
Expand Down

0 comments on commit 5d54e3d

Please sign in to comment.