Merge "SF remove deprecated sf_allow_template_caching"

This commit is contained in:
Zuul
2019-08-21 14:13:47 +00:00
committed by Gerrit Code Review
3 changed files with 16 additions and 383 deletions
@@ -347,6 +347,8 @@ class SolidFireVolumeTestCase(test.TestCase):
}]
}
}
elif method == 'ListSnapshots':
raise exception.VolumeNotFound('test clone unconfigured image')
else:
# Crap, unimplemented API call in Fake
return None
@@ -380,12 +382,9 @@ class SolidFireVolumeTestCase(test.TestCase):
return {'fake': 'fake-model'}
@mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request')
@mock.patch.object(solidfire.SolidFireDriver, '_create_template_account')
def test_create_volume_with_qos_type(self,
_mock_create_template_account,
_mock_issue_api_request):
_mock_issue_api_request.side_effect = self.fake_issue_api_request
_mock_create_template_account.return_value = 1
testvol = {'project_id': 'testprjid',
'name': 'testvol',
'size': 1,
@@ -444,12 +443,9 @@ class SolidFireVolumeTestCase(test.TestCase):
sfv.create_volume(testvol)['qos'])
@mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request')
@mock.patch.object(solidfire.SolidFireDriver, '_create_template_account')
def test_create_volume(self,
_mock_create_template_account,
_mock_issue_api_request):
_mock_issue_api_request.side_effect = self.fake_issue_api_request
_mock_create_template_account.return_value = 1
testvol = {'project_id': 'testprjid',
'name': 'testvol',
'size': 1,
@@ -473,12 +469,9 @@ class SolidFireVolumeTestCase(test.TestCase):
self.assertNotIn('provider_geometry', model_update)
@mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request')
@mock.patch.object(solidfire.SolidFireDriver, '_create_template_account')
def test_create_volume_non_512e(self,
_mock_create_template_account,
_mock_issue_api_request):
_mock_issue_api_request.side_effect = self.fake_issue_api_request
_mock_create_template_account.return_value = 1
testvol = {'project_id': 'testprjid',
'name': 'testvol',
'size': 1,
@@ -533,12 +526,9 @@ class SolidFireVolumeTestCase(test.TestCase):
sfv.delete_snapshot(testsnap)
@mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request')
@mock.patch.object(solidfire.SolidFireDriver, '_create_template_account')
def test_create_clone(self,
_mock_create_template_account,
_mock_issue_api_request):
_mock_issue_api_request.side_effect = self.fake_issue_api_request
_mock_create_template_account.return_value = 1
_fake_get_snaps = [{'snapshotID': 5, 'name': 'testvol'}]
_fake_get_volume = (
{'volumeID': 99,
@@ -1335,12 +1325,9 @@ class SolidFireVolumeTestCase(test.TestCase):
self.assertEqual(2, size)
@mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request')
@mock.patch.object(solidfire.SolidFireDriver, '_create_template_account')
def test_create_volume_for_migration(self,
_mock_create_template_account,
_mock_issue_api_request):
_mock_issue_api_request.side_effect = self.fake_issue_api_request
_mock_create_template_account.return_value = 1
testvol = {'project_id': 'testprjid',
'name': 'testvol',
'size': 1,
@@ -1375,81 +1362,6 @@ class SolidFireVolumeTestCase(test.TestCase):
self.assertEqual('UUID-a720b3c0-d1f0-11e1-9b23-0800200c9a66',
sf_vol_object['name'])
@mock.patch.object(solidfire.SolidFireDriver, '_update_cluster_status')
@mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request')
@mock.patch.object(solidfire.SolidFireDriver, '_get_sfaccount')
@mock.patch.object(solidfire.SolidFireDriver, '_get_sf_volume')
@mock.patch.object(solidfire.SolidFireDriver, '_create_image_volume')
def test_verify_image_volume_out_of_date(self,
_mock_create_image_volume,
_mock_get_sf_volume,
_mock_get_sfaccount,
_mock_issue_api_request,
_mock_update_cluster_status):
fake_sf_vref = {
'status': 'active', 'volumeID': 1,
'attributes': {
'image_info':
{'image_updated_at': '2014-12-17T00:16:23+00:00',
'image_id': '17c550bb-a411-44c0-9aaf-0d96dd47f501',
'image_name': 'fake-image',
'image_created_at': '2014-12-17T00:16:23+00:00'}}}
_mock_update_cluster_status.return_value = None
_mock_issue_api_request.side_effect = (
self.fake_issue_api_request)
_mock_get_sfaccount.return_value = {'username': 'openstack-vtemplate',
'accountID': 7777}
_mock_get_sf_volume.return_value = fake_sf_vref
_mock_create_image_volume.return_value = fake_sf_vref
image_meta = {'id': '17c550bb-a411-44c0-9aaf-0d96dd47f501',
'updated_at': datetime.datetime(2013, 9, 28,
15, 27, 36,
325355)}
image_service = 'null'
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
sfv._verify_image_volume(self.ctxt, image_meta, image_service)
self.assertTrue(_mock_create_image_volume.called)
@mock.patch.object(solidfire.SolidFireDriver, '_update_cluster_status')
@mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request')
@mock.patch.object(solidfire.SolidFireDriver, '_get_sfaccount')
@mock.patch.object(solidfire.SolidFireDriver, '_get_sf_volume')
@mock.patch.object(solidfire.SolidFireDriver, '_create_image_volume')
def test_verify_image_volume_ok(self,
_mock_create_image_volume,
_mock_get_sf_volume,
_mock_get_sfaccount,
_mock_issue_api_request,
_mock_update_cluster_status):
_mock_issue_api_request.side_effect = self.fake_issue_api_request
_mock_update_cluster_status.return_value = None
_mock_get_sfaccount.return_value = {'username': 'openstack-vtemplate',
'accountID': 7777}
_mock_get_sf_volume.return_value =\
{'status': 'active', 'volumeID': 1,
'attributes': {
'image_info':
{'image_updated_at': '2013-09-28T15:27:36.325355',
'image_id': '17c550bb-a411-44c0-9aaf-0d96dd47f501',
'image_name': 'fake-image',
'image_created_at': '2014-12-17T00:16:23+00:00'}}}
_mock_create_image_volume.return_value = None
image_meta = {'id': '17c550bb-a411-44c0-9aaf-0d96dd47f501',
'updated_at': datetime.datetime(2013, 9, 28,
15, 27, 36,
325355)}
image_service = 'null'
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
sfv._verify_image_volume(self.ctxt, image_meta, image_service)
self.assertFalse(_mock_create_image_volume.called)
@mock.patch.object(solidfire.SolidFireDriver, '_issue_api_request')
def test_clone_image_not_configured(self, _mock_issue_api_request):
_mock_issue_api_request.side_effect = self.fake_issue_api_request
@@ -1462,129 +1374,6 @@ class SolidFireVolumeTestCase(test.TestCase):
self.fake_image_meta,
'fake'))
@mock.patch.object(solidfire.SolidFireDriver, '_create_template_account')
@mock.patch.object(solidfire.SolidFireDriver, '_create_image_volume')
def test_clone_image_authorization(self,
_mock_create_image_volume,
_mock_create_template_account):
fake_sf_vref = {
'status': 'active', 'volumeID': 1,
'attributes': {
'image_info':
{'image_updated_at': '2014-12-17T00:16:23+00:00',
'image_id': '155d900f-4e14-4e4c-a73d-069cbf4541e6',
'image_name': 'fake-image',
'image_created_at': '2014-12-17T00:16:23+00:00'}}}
_mock_create_image_volume.return_value = fake_sf_vref
_mock_create_template_account.return_value = 1
self.configuration.sf_allow_template_caching = True
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
# Make sure if it's NOT public and we're NOT the owner it
# doesn't try and cache
timestamp = datetime.datetime(2011, 1, 1, 1, 2, 3)
_fake_image_meta = {
'id': '155d900f-4e14-4e4c-a73d-069cbf4541e6',
'name': 'fakeimage123456',
'created_at': timestamp,
'updated_at': timestamp,
'deleted_at': None,
'deleted': False,
'status': 'active',
'visibility': 'private',
'protected': False,
'container_format': 'raw',
'disk_format': 'raw',
'owner': 'wrong-owner',
'properties': {'kernel_id': 'nokernel',
'ramdisk_id': 'nokernel',
'architecture': 'x86_64'}}
with mock.patch.object(sfv, '_do_clone_volume',
return_value=('fe', 'fi', 'fo')):
self.assertEqual((None, False),
sfv.clone_image(self.ctxt,
self.mock_volume,
'fake',
_fake_image_meta,
self.fake_image_service))
# And is_public False, but the correct owner does work
_fake_image_meta['owner'] = 'testprjid'
self.assertEqual(
('fo', True),
sfv.clone_image(
self.ctxt,
self.mock_volume,
'fake',
_fake_image_meta,
self.fake_image_service))
# And is_public True, even if not the correct owner
_fake_image_meta['is_public'] = True
_fake_image_meta['owner'] = 'wrong-owner'
self.assertEqual(
('fo', True),
sfv.clone_image(self.ctxt,
self.mock_volume,
'fake',
_fake_image_meta,
self.fake_image_service))
# And using the new V2 visibility tag
_fake_image_meta['visibility'] = 'public'
_fake_image_meta['owner'] = 'wrong-owner'
self.assertEqual(
('fo', True),
sfv.clone_image(self.ctxt,
self.mock_volume,
'fake',
_fake_image_meta,
self.fake_image_service))
def test_create_template_no_account(self):
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
def _fake_issue_api_req(method, params, version=0):
if 'GetAccountByName' in method:
raise solidfire.SolidFireAPIException
return {'result': {'accountID': 1}}
with mock.patch.object(sfv,
'_issue_api_request',
side_effect=_fake_issue_api_req):
self.assertEqual(1,
sfv._create_template_account('foo'))
def test_configured_svip(self):
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
def _fake_get_volumes(account_id, endpoint=None):
return [{'volumeID': 1,
'iqn': ''}]
def _fake_get_cluster_info():
return {'clusterInfo': {'svip': '10.10.10.10',
'mvip': '1.1.1.1'}}
with mock.patch.object(sfv,
'_get_volumes_by_sfaccount',
side_effect=_fake_get_volumes),\
mock.patch.object(sfv,
'_issue_api_request',
side_effect=self.fake_issue_api_request):
sfaccount = {'targetSecret': 'yakitiyak',
'accountID': 5,
'username': 'bobthebuilder'}
v = sfv._get_model_info(sfaccount, 1)
self.assertEqual('1.1.1.1:3260 0', v['provider_location'])
configured_svip = '9.9.9.9:6500'
sfv.active_cluster['svip'] = configured_svip
v = sfv._get_model_info(sfaccount, 1)
self.assertEqual('%s 0' % configured_svip, v['provider_location'])
def test_init_volume_mappings(self):
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
+5 -170
View File
@@ -34,7 +34,6 @@ import six
from cinder import context
from cinder import exception
from cinder.i18n import _
from cinder.image import image_utils
from cinder import interface
from cinder.objects import fields
from cinder import utils
@@ -68,21 +67,6 @@ sf_opts = [
'are of the form <sf_volume_prefix><cinder-volume-id>. '
'The default is to use a prefix of \'UUID-\'.'),
cfg.StrOpt('sf_template_account_name',
default='openstack-vtemplate',
help='Account name on the SolidFire Cluster to use as owner of '
'template/cache volumes (created if does not exist).'),
cfg.BoolOpt('sf_allow_template_caching',
deprecated_for_removal=True,
deprecated_reason='The Cinder caching feature should be '
'used rather than this driver specific '
'implementation.',
default=False,
help='This option is deprecated and will be removed in '
'the next OpenStack release. Please use the general '
'cinder image-caching feature instead.'),
cfg.StrOpt('sf_svip',
help='Overrides default cluster SVIP with the one specified. '
'This is required or deployments that have implemented '
@@ -311,10 +295,6 @@ class SolidFireDriver(san.SanISCSIDriver):
except SolidFireAPIException:
pass
if self.configuration.sf_allow_template_caching:
account = self.configuration.sf_template_account_name
self.template_account_id = self._create_template_account(account)
self._set_cluster_pairs()
@staticmethod
@@ -497,27 +477,6 @@ class SolidFireDriver(san.SanISCSIDriver):
snapshot_updates = self._init_snapshot_mappings(snaprefs)
return (volume_updates, snapshot_updates)
def _create_template_account(self, account_name):
# We raise an API exception if the account doesn't exist
# We need to take account_prefix settings into consideration
# This just uses the same method to do template account create
# as we use for any other OpenStack account
account_name = self._get_sf_account_name(account_name)
try:
id = self._issue_api_request(
'GetAccountByName',
{'username': account_name})['result']['account']['accountID']
except SolidFireAPIException:
chap_secret = self._generate_random_string(12)
params = {'username': account_name,
'initiatorSecret': chap_secret,
'targetSecret': chap_secret,
'attributes': {}}
id = self._issue_api_request('AddAccount',
params)['result']['accountID']
return id
def _build_endpoint_info(self, **kwargs):
endpoint = {}
@@ -1001,122 +960,6 @@ class SolidFireDriver(san.SanISCSIDriver):
return self._issue_api_request(
'ListSnapshots', params, version='6.0')['result']['snapshots']
def _create_image_volume(self, context,
image_meta, image_service,
image_id):
with image_utils.TemporaryImages.fetch(image_service,
context,
image_id) as tmp_image:
data = image_utils.qemu_img_info(tmp_image)
fmt = data.file_format
if fmt is None:
raise exception.ImageUnacceptable(
reason=_("'qemu-img info' parsing failed."),
image_id=image_id)
backing_file = data.backing_file
if backing_file is not None:
raise exception.ImageUnacceptable(
image_id=image_id,
reason=_("fmt=%(fmt)s backed by:%(backing_file)s")
% {'fmt': fmt, 'backing_file': backing_file, })
virtual_size = int(math.ceil(float(data.virtual_size) / units.Gi))
attributes = {}
attributes['image_info'] = {}
attributes['image_info']['image_updated_at'] = (
image_meta['updated_at'].isoformat())
attributes['image_info']['image_name'] = (
image_meta['name'])
attributes['image_info']['image_created_at'] = (
image_meta['created_at'].isoformat())
attributes['image_info']['image_id'] = image_meta['id']
params = {'name': 'OpenStackIMG-%s' % image_id,
'accountID': self.template_account_id,
'sliceCount': 1,
'totalSize': int(virtual_size * units.Gi),
'enable512e': self.configuration.sf_emulate_512,
'attributes': attributes,
'qos': {}}
sf_account = self._issue_api_request(
'GetAccountByID',
{'accountID': self.template_account_id})['result']['account']
template_vol = self._do_volume_create(sf_account, params)
tvol = {}
tvol['id'] = image_id
tvol['provider_location'] = template_vol['provider_location']
tvol['provider_auth'] = template_vol['provider_auth']
attach_info = None
try:
connector = {'multipath': False}
conn = self.initialize_connection(tvol, connector)
attach_info = super(SolidFireDriver, self)._connect_device(
conn)
properties = 'na'
image_utils.convert_image(tmp_image,
attach_info['device']['path'],
'raw',
run_as_root=True)
data = image_utils.qemu_img_info(attach_info['device']['path'],
run_as_root=True)
if data.file_format != 'raw':
raise exception.ImageUnacceptable(
image_id=image_id,
reason=_("Converted to %(vol_format)s, but format is "
"now %(file_format)s") % {'vol_format': 'raw',
'file_format': data.
file_format})
except Exception as exc:
vol = self._get_sf_volume(image_id)
LOG.error('Failed image conversion during '
'cache creation: %s',
exc)
LOG.debug('Removing SolidFire Cache Volume (SF ID): %s',
vol['volumeID'])
if attach_info is not None:
self._detach_volume(context, attach_info, tvol, properties)
self._issue_api_request('DeleteVolume', params)
self._issue_api_request('PurgeDeletedVolume', params)
return
self._detach_volume(context, attach_info, tvol, properties)
sf_vol = self._get_sf_volume(image_id, params)
LOG.debug('Successfully created SolidFire Image Template '
'for image-id: %s', image_id)
return sf_vol
def _verify_image_volume(self, context, image_meta, image_service):
# This method just verifies that IF we have a cache volume that
# it's still up to date and current WRT the image in Glance
# ie an image-update hasn't occurred since we grabbed it
# If it's out of date, just delete it and we'll create a new one
# Any other case we don't care and just return without doing anything
params = {'accountID': self.template_account_id}
sf_vol = self._get_sf_volume(image_meta['id'], params)
if not sf_vol:
self._create_image_volume(context,
image_meta,
image_service,
image_meta['id'])
return
if sf_vol['attributes']['image_info']['image_updated_at'] != (
image_meta['updated_at'].isoformat()):
params = {'accountID': self.template_account_id}
params['volumeID'] = sf_vol['volumeID']
self._issue_api_request('DeleteVolume', params)
self._issue_api_request('PurgeDeletedVolume', params)
self._create_image_volume(context,
image_meta,
image_service,
image_meta['id'])
def _get_sfaccounts_for_tenant(self, cinder_project_id):
accounts = self._issue_api_request(
'ListAccounts', {})['result']['accounts']
@@ -1341,11 +1184,6 @@ class SolidFireDriver(san.SanISCSIDriver):
image_meta, image_service):
"""Clone an existing image volume."""
public = False
# Check out pre-requisites:
# Is template caching enabled?
if not self.configuration.sf_allow_template_caching:
return None, False
# NOTE(jdg): Glance V2 moved from is_public to visibility
# so we check both, as we don't necessarily know or want
# to care which we're using. Will need to look at
@@ -1363,17 +1201,14 @@ class SolidFireDriver(san.SanISCSIDriver):
LOG.warning("Requested image is not "
"accessible by current Tenant.")
return None, False
# If we don't have the image-volume to clone from return failure
# cinder driver will then create source for clone first
try:
self._verify_image_volume(context,
image_meta,
image_service)
except SolidFireAPIException:
(data, sfaccount, model) = self._do_clone_volume(image_meta['id'],
volume)
except exception.VolumeNotFound:
return None, False
# Ok, should be good to go now, try it again
(data, sfaccount, model) = self._do_clone_volume(image_meta['id'],
volume)
return model, True
# extended_size > 0 when we are extending a volume
@@ -0,0 +1,9 @@
---
prelude: >
SolidFire cinder driver deprecate sf_allow_template_caching
deprecations:
- |
The configuration option sf_allow_template_caching for the
SolidFire cinder driver has been removed. Use image_volume_cache_enabled
equals True for a better template image cache that is managed from
cinder.