RBD: get manageable volumes

This patch adds the ability to get manageable volumes to RBD driver.

Co-Authored-By: qtlu<qtlu@fiberhome.com>
Partial-Implements: blueprint list-manage-existing
Change-Id: I0621358b13fc3f5a4acfb8d66232fb953d94b274
This commit is contained in:
jeremy.zhang 2017-12-14 12:46:20 +08:00
parent 466ab2bf8f
commit 164246094e
3 changed files with 77 additions and 1 deletions

View File

@ -557,6 +557,33 @@ class RBDTestCase(test.TestCase):
self.assertEqual([self.mock_rbd.ImageNotFound], self.assertEqual([self.mock_rbd.ImageNotFound],
RAISED_EXCEPTIONS) RAISED_EXCEPTIONS)
@common_mocks
@mock.patch.object(driver.RBDDriver, '_get_image_status')
def test_get_manageable_volumes(self, mock_get_image_status):
cinder_vols = [{'id': '00000000-0000-0000-0000-000000000000'}]
vols = ['volume-00000000-0000-0000-0000-000000000000', 'vol1', 'vol2']
self.mock_rbd.RBD.return_value.list.return_value = vols
image = self.mock_proxy.return_value.__enter__.return_value
image.size.side_effect = [2 * units.Gi, 4 * units.Gi, 6 * units.Gi]
mock_get_image_status.side_effect = [
{'watchers': []},
{'watchers': [{"address": "192.168.120.61:0\/3012034728",
"client": 44431941, "cookie": 94077162321152}]}]
res = self.driver.get_manageable_volumes(
cinder_vols, None, 1000, 0, ['size'], ['asc'])
exp = [{'size': 2, 'reason_not_safe': 'already managed',
'extra_info': None, 'safe_to_manage': False,
'reference': {'source-name':
'volume-00000000-0000-0000-0000-000000000000'},
'cinder_id': '00000000-0000-0000-0000-000000000000'},
{'size': 4, 'reason_not_safe': None,
'safe_to_manage': True, 'reference': {'source-name': 'vol1'},
'cinder_id': None, 'extra_info': None},
{'size': 6, 'reason_not_safe': 'volume in use',
'safe_to_manage': False, 'reference': {'source-name': 'vol2'},
'cinder_id': None, 'extra_info': None}]
self.assertEqual(exp, res)
@common_mocks @common_mocks
def test_delete_backup_snaps(self): def test_delete_backup_snaps(self):
self.driver.rbd.Image.remove_snap = mock.Mock() self.driver.rbd.Image.remove_snap = mock.Mock()

View File

@ -37,7 +37,7 @@ from cinder.objects import fields
from cinder import utils from cinder import utils
from cinder.volume import configuration from cinder.volume import configuration
from cinder.volume import driver from cinder.volume import driver
from cinder.volume import utils as volume_utils
try: try:
import rados import rados
@ -1389,6 +1389,52 @@ class RBDDriver(driver.CloneableImageVD,
raise exception.VolumeBackendAPIException( raise exception.VolumeBackendAPIException(
data=exception_message) data=exception_message)
def _get_image_status(self, image_name):
args = ['rbd', 'status',
'--pool', self.configuration.rbd_pool,
'--format=json',
image_name]
args.extend(self._ceph_args())
out, _ = self._execute(*args)
return json.loads(out)
def get_manageable_volumes(self, cinder_volumes, marker, limit, offset,
sort_keys, sort_dirs):
manageable_volumes = []
cinder_ids = [resource['id'] for resource in cinder_volumes]
with RADOSClient(self) as client:
for image_name in self.RBDProxy().list(client.ioctx):
image_id = volume_utils.extract_id_from_volume_name(image_name)
with RBDVolumeProxy(self, image_name, read_only=True) as image:
try:
image_info = {
'reference': {'source-name': image_name},
'size': int(math.ceil(
float(image.size()) / units.Gi)),
'cinder_id': None,
'extra_info': None
}
if image_id in cinder_ids:
image_info['cinder_id'] = image_id
image_info['safe_to_manage'] = False
image_info['reason_not_safe'] = 'already managed'
elif len(self._get_image_status(
image_name)['watchers']) > 0:
# If the num of watchers of image is >= 1, then the
# image is considered to be used by client(s).
image_info['safe_to_manage'] = False
image_info['reason_not_safe'] = 'volume in use'
else:
image_info['safe_to_manage'] = True
image_info['reason_not_safe'] = None
manageable_volumes.append(image_info)
except self.rbd.ImageNotFound:
LOG.debug("Image %s is not found.", image_name)
return volume_utils.paginate_entries_list(
manageable_volumes, marker, limit, offset, sort_keys, sort_dirs)
def unmanage(self, volume): def unmanage(self, volume):
pass pass

View File

@ -0,0 +1,3 @@
---
features:
- Allow rbd driver to list manageable volumes.