Merge "rbd: implement get_volume_stats()"
This commit is contained in:
commit
c529b1f6be
@ -30,6 +30,7 @@ from cinder.tests.image import fake as fake_image
|
|||||||
from cinder.tests.test_volume import DriverTestCase
|
from cinder.tests.test_volume import DriverTestCase
|
||||||
from cinder.volume import configuration as conf
|
from cinder.volume import configuration as conf
|
||||||
from cinder.volume.drivers.rbd import RBDDriver
|
from cinder.volume.drivers.rbd import RBDDriver
|
||||||
|
from cinder.volume.drivers.rbd import VERSION as DRIVER_VERSION
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -38,6 +39,38 @@ class FakeImageService:
|
|||||||
def download(self, context, image_id, path):
|
def download(self, context, image_id, path):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
RADOS_DF_OUT = """
|
||||||
|
{
|
||||||
|
"total_space" : "958931232",
|
||||||
|
"total_used" : "123906196",
|
||||||
|
"total_objects" : "4221",
|
||||||
|
"total_avail" : "787024012",
|
||||||
|
"pools" : [
|
||||||
|
{
|
||||||
|
"name" : "volumes",
|
||||||
|
"categories" : [
|
||||||
|
{
|
||||||
|
"write_bytes" : "226833",
|
||||||
|
"size_kb" : "17038386",
|
||||||
|
"read_bytes" : "221865",
|
||||||
|
"num_objects" : "4186",
|
||||||
|
"name" : "",
|
||||||
|
"size_bytes" : "17447306589",
|
||||||
|
"write_kb" : "20302730",
|
||||||
|
"num_object_copies" : "8372",
|
||||||
|
"read_kb" : "30",
|
||||||
|
"num_objects_unfound" : "0",
|
||||||
|
"num_object_clones" : "9",
|
||||||
|
"num_objects_missing_on_primary" : "0",
|
||||||
|
"num_objects_degraded" : "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id" : "4"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class RBDTestCase(test.TestCase):
|
class RBDTestCase(test.TestCase):
|
||||||
|
|
||||||
@ -117,6 +150,36 @@ class RBDTestCase(test.TestCase):
|
|||||||
self.flags(volume_tmp_dir='/var/run/cinder/tmp')
|
self.flags(volume_tmp_dir='/var/run/cinder/tmp')
|
||||||
self._copy_image()
|
self._copy_image()
|
||||||
|
|
||||||
|
def test_update_volume_stats(self):
|
||||||
|
def fake_stats(*args):
|
||||||
|
return RADOS_DF_OUT, ''
|
||||||
|
self.stubs.Set(self.driver, '_execute', fake_stats)
|
||||||
|
expected = dict(
|
||||||
|
volume_backend_name='RBD',
|
||||||
|
vendor_name='Open Source',
|
||||||
|
driver_version=DRIVER_VERSION,
|
||||||
|
storage_protocol='ceph',
|
||||||
|
total_capacity_gb=914,
|
||||||
|
free_capacity_gb=750,
|
||||||
|
reserved_percentage=0)
|
||||||
|
actual = self.driver.get_volume_stats(True)
|
||||||
|
self.assertDictMatch(expected, actual)
|
||||||
|
|
||||||
|
def test_update_volume_stats_error(self):
|
||||||
|
def fake_exc(*args):
|
||||||
|
raise exception.ProcessExecutionError()
|
||||||
|
self.stubs.Set(self.driver, '_execute', fake_exc)
|
||||||
|
expected = dict(
|
||||||
|
volume_backend_name='RBD',
|
||||||
|
vendor_name='Open Source',
|
||||||
|
driver_version=DRIVER_VERSION,
|
||||||
|
storage_protocol='ceph',
|
||||||
|
total_capacity_gb='unknown',
|
||||||
|
free_capacity_gb='unknown',
|
||||||
|
reserved_percentage=0)
|
||||||
|
actual = self.driver.get_volume_stats(True)
|
||||||
|
self.assertDictMatch(expected, actual)
|
||||||
|
|
||||||
|
|
||||||
class ManagedRBDTestCase(DriverTestCase):
|
class ManagedRBDTestCase(DriverTestCase):
|
||||||
driver_name = "cinder.volume.drivers.rbd.RBDDriver"
|
driver_name = "cinder.volume.drivers.rbd.RBDDriver"
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
RADOS Block Device Driver
|
RADOS Block Device Driver
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import urllib
|
import urllib
|
||||||
@ -49,12 +50,22 @@ rbd_opts = [
|
|||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
FLAGS.register_opts(rbd_opts)
|
FLAGS.register_opts(rbd_opts)
|
||||||
|
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
|
||||||
class RBDDriver(driver.VolumeDriver):
|
class RBDDriver(driver.VolumeDriver):
|
||||||
"""Implements RADOS block device (RBD) volume commands"""
|
"""Implements RADOS block device (RBD) volume commands"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(RBDDriver, self).__init__(*args, **kwargs)
|
super(RBDDriver, self).__init__(*args, **kwargs)
|
||||||
self.configuration.append_config_values(rbd_opts)
|
self.configuration.append_config_values(rbd_opts)
|
||||||
|
self._stats = dict(
|
||||||
|
volume_backend_name='RBD',
|
||||||
|
vendor_name='Open Source',
|
||||||
|
driver_version=VERSION,
|
||||||
|
storage_protocol='ceph',
|
||||||
|
total_capacity_gb='unknown',
|
||||||
|
free_capacity_gb='unknown',
|
||||||
|
reserved_percentage=0)
|
||||||
|
|
||||||
def check_for_setup_error(self):
|
def check_for_setup_error(self):
|
||||||
"""Returns an error if prerequisites aren't met"""
|
"""Returns an error if prerequisites aren't met"""
|
||||||
@ -65,6 +76,29 @@ class RBDDriver(driver.VolumeDriver):
|
|||||||
self.configuration.rbd_pool)
|
self.configuration.rbd_pool)
|
||||||
raise exception.VolumeBackendAPIException(data=exception_message)
|
raise exception.VolumeBackendAPIException(data=exception_message)
|
||||||
|
|
||||||
|
def _update_volume_stats(self):
|
||||||
|
stats = dict(
|
||||||
|
total_capacity_gb='unknown',
|
||||||
|
free_capacity_gb='unknown')
|
||||||
|
try:
|
||||||
|
stdout, _err = self._execute('rados', 'df', '--format', 'json')
|
||||||
|
new_stats = json.loads(stdout)
|
||||||
|
total = int(new_stats['total_space']) / 1024 ** 2
|
||||||
|
free = int(new_stats['total_avail']) / 1024 ** 2
|
||||||
|
stats['total_capacity_gb'] = total
|
||||||
|
stats['free_capacity_gb'] = free
|
||||||
|
except exception.ProcessExecutionError:
|
||||||
|
# just log and return unknown capacities
|
||||||
|
LOG.exception(_('error refreshing volume stats'))
|
||||||
|
self._stats.update(stats)
|
||||||
|
|
||||||
|
def get_volume_stats(self, refresh=False):
|
||||||
|
"""Return the current state of the volume service. If 'refresh' is
|
||||||
|
True, run the update first."""
|
||||||
|
if refresh:
|
||||||
|
self._update_volume_stats()
|
||||||
|
return self._stats
|
||||||
|
|
||||||
def _supports_layering(self):
|
def _supports_layering(self):
|
||||||
stdout, _ = self._execute('rbd', '--help')
|
stdout, _ = self._execute('rbd', '--help')
|
||||||
return 'clone' in stdout
|
return 'clone' in stdout
|
||||||
|
Loading…
x
Reference in New Issue
Block a user