Report ZFS pool capacity and usage statistics
When LXD is using a ZFS backend, correctly report disk stats based on the usage of the ZFS pool rather than the usage of the filesystem at /var/lib/lxd. Change-Id: I2f2b843156cdc47c2f3324d69c384f943a0e1499 Closes-Bug: 1680869
This commit is contained in:
parent
a91cdd62ce
commit
02ce341738
|
@ -6,6 +6,7 @@
|
|||
|
||||
# Packages
|
||||
*.egg
|
||||
*.eggs
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
|
||||
[Filters]
|
||||
zfs: CommandFilter, zfs, root
|
||||
zpool: CommandFilter, zpool, root
|
||||
btrfs: CommandFilter, btrfs, root
|
||||
|
|
|
@ -1040,8 +1040,84 @@ class LXDDriverTest(test.NoDBTestCase):
|
|||
'\n'),
|
||||
meminfo,
|
||||
]
|
||||
|
||||
lxd_config = {
|
||||
'environment': {
|
||||
'storage': 'dir',
|
||||
},
|
||||
'config': {}
|
||||
}
|
||||
lxd_driver = driver.LXDDriver(None)
|
||||
lxd_driver.client = mock.MagicMock()
|
||||
lxd_driver.client.host_info = lxd_config
|
||||
value = lxd_driver.get_available_resource(None)
|
||||
# This is funky, but json strings make for fragile tests.
|
||||
value['cpu_info'] = json.loads(value['cpu_info'])
|
||||
|
||||
self.assertEqual(expected, value)
|
||||
|
||||
@mock.patch('socket.gethostname', mock.Mock(return_value='fake_hostname'))
|
||||
@mock.patch('nova.virt.lxd.driver.open')
|
||||
@mock.patch.object(driver.utils, 'execute')
|
||||
def test_get_available_resource_zfs(self, execute, open):
|
||||
expected = {
|
||||
'cpu_info': {
|
||||
"features": "fake flag goes here",
|
||||
"model": "Fake CPU",
|
||||
"topology": {"sockets": "10", "threads": "4", "cores": "5"},
|
||||
"arch": "x86_64", "vendor": "FakeVendor"
|
||||
},
|
||||
'hypervisor_hostname': 'fake_hostname',
|
||||
'hypervisor_type': 'lxd',
|
||||
'hypervisor_version': '011',
|
||||
'local_gb': 2222,
|
||||
'local_gb_used': 200,
|
||||
'memory_mb': 10000,
|
||||
'memory_mb_used': 8000,
|
||||
'numa_topology': None,
|
||||
'supported_instances': [
|
||||
('i686', 'lxd', 'exe'),
|
||||
('x86_64', 'lxd', 'exe'),
|
||||
('i686', 'lxc', 'exe'),
|
||||
('x86_64', 'lxc', 'exe')],
|
||||
'vcpus': 200,
|
||||
'vcpus_used': 0}
|
||||
|
||||
execute.side_effect = [
|
||||
('Model name: Fake CPU\n'
|
||||
'Vendor ID: FakeVendor\n'
|
||||
'Socket(s): 10\n'
|
||||
'Core(s) per socket: 5\n'
|
||||
'Thread(s) per core: 4\n\n',
|
||||
None),
|
||||
('2.17T\n', None),
|
||||
('200.4G\n', None),
|
||||
('1.8T\n', None)
|
||||
]
|
||||
|
||||
meminfo = mock.MagicMock()
|
||||
meminfo.__enter__.return_value = six.moves.cStringIO(
|
||||
'MemTotal: 10240000 kB\n'
|
||||
'MemFree: 2000000 kB\n'
|
||||
'Buffers: 24000 kB\n'
|
||||
'Cached: 24000 kB\n')
|
||||
|
||||
open.side_effect = [
|
||||
six.moves.cStringIO('flags: fake flag goes here\n'
|
||||
'processor: 2\n'
|
||||
'\n'),
|
||||
meminfo,
|
||||
]
|
||||
lxd_config = {
|
||||
'environment': {
|
||||
'storage': 'zfs',
|
||||
},
|
||||
'config': {
|
||||
'storage.zfs_pool_name': 'lxd',
|
||||
}
|
||||
}
|
||||
lxd_driver = driver.LXDDriver(None)
|
||||
lxd_driver.client = mock.MagicMock()
|
||||
lxd_driver.client.host_info = lxd_config
|
||||
value = lxd_driver.get_available_resource(None)
|
||||
# This is funky, but json strings make for fragile tests.
|
||||
value['cpu_info'] = json.loads(value['cpu_info'])
|
||||
|
|
|
@ -62,6 +62,7 @@ import psutil
|
|||
from oslo_concurrency import lockutils
|
||||
from nova.compute import task_states
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import strutils
|
||||
from nova.virt import firewall
|
||||
|
||||
_ = i18n._
|
||||
|
@ -160,6 +161,28 @@ def _get_fs_info(path):
|
|||
'used': used}
|
||||
|
||||
|
||||
def _get_zpool_info(pool):
|
||||
"""Get free/used/total disk space in a zfs pool."""
|
||||
def _get_zpool_attribute(attribute):
|
||||
value, err = utils.execute('zpool', 'list',
|
||||
'-o', attribute,
|
||||
'-H', pool,
|
||||
run_as_root=True)
|
||||
if err:
|
||||
msg = _('Unable to parse zpool output.')
|
||||
raise exception.NovaException(msg)
|
||||
value = strutils.string_to_bytes('{}B'.format(value.strip()),
|
||||
return_int=True)
|
||||
return value
|
||||
|
||||
total = _get_zpool_attribute('size')
|
||||
used = _get_zpool_attribute('alloc')
|
||||
available = _get_zpool_attribute('free')
|
||||
return {'total': total,
|
||||
'available': available,
|
||||
'used': used}
|
||||
|
||||
|
||||
def _get_power_state(lxd_state):
|
||||
"""Take a lxd state code and translate it to nova power state."""
|
||||
state_map = [
|
||||
|
@ -858,7 +881,19 @@ class LXDDriver(driver.ComputeDriver):
|
|||
int(cpu_topology['threads']))
|
||||
|
||||
local_memory_info = _get_ram_usage()
|
||||
local_disk_info = _get_fs_info(CONF.lxd.root_dir)
|
||||
|
||||
lxd_config = self.client.host_info
|
||||
|
||||
# NOTE(jamespage): ZFS storage report is very LXD 2.0.x
|
||||
# centric and will need to be updated
|
||||
# to support LXD storage pools
|
||||
storage_driver = lxd_config['environment']['storage']
|
||||
if storage_driver == 'zfs':
|
||||
local_disk_info = _get_zpool_info(
|
||||
lxd_config['config']['storage.zfs_pool_name']
|
||||
)
|
||||
else:
|
||||
local_disk_info = _get_fs_info(CONF.lxd.root_dir)
|
||||
|
||||
data = {
|
||||
'vcpus': vcpus,
|
||||
|
|
Loading…
Reference in New Issue