Implement cinder client plugin

This moves the client creation code out of Clients._cinder() into
its own client plugin.

Cinder is a core project, and python-cinderclient is a dependency,
so the import is now mandatory (including the volume_backups import).

Change-Id: I6b937422cd8e20fa620a7e875ae8b4c61e8f9cf8
This commit is contained in:
Steve Baker 2014-06-04 15:12:03 +12:00
parent 7d3111f941
commit d234e26131
6 changed files with 66 additions and 62 deletions

View File

@ -12,7 +12,6 @@
# under the License.
from ceilometerclient import client as ceilometerclient
from cinderclient import client as cinderclient
from heatclient import client as heatclient
from oslo.config import cfg
from stevedore import extension
@ -116,29 +115,6 @@ class OpenStackClients(object):
'Replace with calls to client("cinder")')
return self.client('cinder')
def _cinder(self):
con = self.context
endpoint_type = self._get_client_option('cinder', 'endpoint_type')
args = {
'service_type': 'volume',
'auth_url': con.auth_url,
'project_id': con.tenant,
'username': None,
'api_key': None,
'endpoint_type': endpoint_type,
'cacert': self._get_client_option('cinder', 'ca_file'),
'insecure': self._get_client_option('cinder', 'insecure')
}
client = cinderclient.Client('1', **args)
management_url = self.url_for(service_type='volume',
endpoint_type=endpoint_type)
client.client.auth_token = self.auth_token
client.client.management_url = management_url
return client
def trove(self):
warnings.warn('trove() is deprecated. '
'Replace with calls to client("trove")')

View File

@ -0,0 +1,42 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from cinderclient import client as cc
from heat.engine.clients import client_plugin
class CinderClientPlugin(client_plugin.ClientPlugin):
def _create(self):
con = self.context
endpoint_type = self._get_client_option('cinder', 'endpoint_type')
args = {
'service_type': 'volume',
'auth_url': con.auth_url,
'project_id': con.tenant,
'username': None,
'api_key': None,
'endpoint_type': endpoint_type,
'cacert': self._get_client_option('cinder', 'ca_file'),
'insecure': self._get_client_option('cinder', 'insecure')
}
client = cc.Client('1', **args)
management_url = self.url_for(service_type='volume',
endpoint_type=endpoint_type)
client.client.auth_token = self.auth_token
client.client.management_url = management_url
return client

View File

@ -11,23 +11,21 @@
# License for the specific language governing permissions and limitations
# under the License.
from cinderclient import client as cinderclient
from cinderclient.v1 import volume_backups
import json
from novaclient import exceptions as nova_exceptions
from heat.common import exception
from heat.engine import attributes
from heat.engine import clients
from heat.engine import constraints
from heat.engine import properties
from heat.engine import resource
from heat.engine.resources import glance_utils
from heat.engine import scheduler
from heat.engine import support
from heat.openstack.common.importutils import try_import
from heat.openstack.common import log as logging
volume_backups = try_import('cinderclient.v1.volume_backups')
LOG = logging.getLogger(__name__)
@ -163,7 +161,7 @@ class Volume(resource.Resource):
while True:
yield
vol.get()
except clients.cinderclient.exceptions.NotFound:
except cinderclient.exceptions.NotFound:
self.resource_id_set(None)
if volume_backups is not None:
@ -256,7 +254,7 @@ class VolumeExtendTask(object):
try:
cinder.extend(self.volume_id, self.size)
except clients.cinderclient.exceptions.ClientException as ex:
except cinderclient.exceptions.ClientException as ex:
raise exception.Error(_(
"Failed to extend volume %(vol)s - %(err)s") % {
'vol': vol.id, 'err': str(ex)})
@ -362,7 +360,7 @@ class VolumeDetachTask(object):
nova_vol = server_api.get_server_volume(self.server_id,
self.attachment_id)
vol = self.clients.client('cinder').volumes.get(nova_vol.id)
except (clients.cinderclient.exceptions.NotFound,
except (cinderclient.exceptions.NotFound,
nova_exceptions.BadRequest,
nova_exceptions.NotFound):
LOG.warning(_('%s - volume not found') % str(self))
@ -389,7 +387,7 @@ class VolumeDetachTask(object):
if vol.status != 'available':
raise exception.Error(vol.status)
except clients.cinderclient.exceptions.NotFound:
except cinderclient.exceptions.NotFound:
LOG.warning(_('%s - volume not found') % str(self))
# The next check is needed for immediate reattachment when updating:

View File

@ -13,7 +13,6 @@
from glanceclient import exc as glance_exceptions
import mock
from testtools import skipIf
from heat.common import exception
from heat.common import template_format
@ -25,7 +24,6 @@ from heat.engine import parser
from heat.engine import resources
from heat.engine.resources import glance_utils
from heat.engine import service
from heat.openstack.common.importutils import try_import
from heat.tests.common import HeatTestCase
from heat.tests import utils
from heat.tests.v1_1 import fakes
@ -1064,8 +1062,6 @@ class validateTest(HeatTestCase):
self.assertEqual(
{'Error': '"Snapshot" deletion policy not supported'}, res)
@skipIf(try_import('cinderclient.v1.volume_backups') is None,
'unable to import volume_backups')
def test_volume_snapshot_deletion_policy(self):
t = template_format.parse(test_template_volume_snapshot)
engine = service.EngineService('a', 't')

View File

@ -14,14 +14,14 @@
import copy
import json
from cinderclient import exceptions as cinder_exp
from cinderclient.v1 import client as cinderclient
import mox
import six
from testtools import skipIf
from heat.common import exception
from heat.common import template_format
from heat.engine import clients
from heat.engine.clients.os import cinder
from heat.engine.clients.os import glance
from heat.engine.clients.os import nova
from heat.engine.resources import glance_utils
@ -31,14 +31,11 @@ from heat.engine.resources import volume as vol
from heat.engine import rsrc_defn
from heat.engine import scheduler
from heat.engine import template
from heat.openstack.common.importutils import try_import
from heat.tests.common import HeatTestCase
from heat.tests import utils
from heat.tests.v1_1 import fakes
volume_backups = try_import('cinderclient.v1.volume_backups')
volume_template = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
@ -102,7 +99,7 @@ class VolumeTest(HeatTestCase):
super(VolumeTest, self).setUp()
self.fc = fakes.FakeClient()
self.cinder_fc = cinderclient.Client('username', 'password')
self.m.StubOutWithMock(clients.OpenStackClients, '_cinder')
self.m.StubOutWithMock(cinder.CinderClientPlugin, '_create')
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
self.m.StubOutWithMock(self.cinder_fc.volumes, 'create')
self.m.StubOutWithMock(self.cinder_fc.volumes, 'get')
@ -146,7 +143,7 @@ class VolumeTest(HeatTestCase):
return rsrc
def _mock_create_volume(self, fv, stack_name, size=1):
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
vol_name = utils.PhysName(stack_name, 'DataVolume')
self.cinder_fc.volumes.create(
@ -161,7 +158,7 @@ class VolumeTest(HeatTestCase):
self.m.StubOutWithMock(fv, 'get')
fv.get().AndReturn(None)
fv.get().AndRaise(
clients.cinderclient.exceptions.NotFound('Not found'))
cinder_exp.NotFound('Not found'))
self.m.ReplayAll()
def _mock_create_server_volume_script(self, fva,
@ -221,7 +218,7 @@ class VolumeTest(HeatTestCase):
self.m.StubOutWithMock(image.ImageConstraint, "validate")
instance.Instance.handle_create().AndReturn(None)
instance.Instance.check_create_complete(None).AndReturn(True)
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
image.ImageConstraint.validate(
mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(True)
@ -239,7 +236,7 @@ class VolumeTest(HeatTestCase):
self.m.StubOutWithMock(vol.VolumeAttachment, 'handle_delete')
instance.Instance.handle_delete().AndReturn(None)
self.cinder_fc.volumes.get('vol-123').AndRaise(
clients.cinderclient.exceptions.NotFound('Not found'))
cinder_exp.NotFound('Not found'))
vol.VolumeAttachment.handle_delete().AndReturn(None)
self.m.ReplayAll()
@ -401,7 +398,7 @@ class VolumeTest(HeatTestCase):
self.fc.volumes.get_server_volume(u'WikiDatabase',
'vol-123').AndReturn(fva)
self.cinder_fc.volumes.get(fva.id).AndRaise(
clients.cinderclient.exceptions.NotFound('Not found'))
cinder_exp.NotFound('Not found'))
self.m.ReplayAll()
@ -673,7 +670,6 @@ class VolumeTest(HeatTestCase):
self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
@skipIf(volume_backups is None, 'unable to import volume_backups')
def test_snapshot(self):
stack_name = 'test_volume_stack'
fv = FakeVolume('creating', 'available')
@ -699,7 +695,6 @@ class VolumeTest(HeatTestCase):
self.m.VerifyAll()
@skipIf(volume_backups is None, 'unable to import volume_backups')
def test_snapshot_error(self):
stack_name = 'test_volume_stack'
fv = FakeVolume('creating', 'available')
@ -724,7 +719,6 @@ class VolumeTest(HeatTestCase):
self.m.VerifyAll()
@skipIf(volume_backups is None, 'unable to import volume_backups')
def test_snapshot_no_volume(self):
stack_name = 'test_volume_stack'
fv = FakeVolume('creating', 'error')
@ -752,14 +746,13 @@ class VolumeTest(HeatTestCase):
self.m.VerifyAll()
@skipIf(volume_backups is None, 'unable to import volume_backups')
def test_create_from_snapshot(self):
stack_name = 'test_volume_stack'
fv = FakeVolumeWithStateTransition('restoring-backup', 'available')
fvbr = FakeBackupRestore('vol-123')
# create script
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
self.m.StubOutWithMock(self.cinder_fc.restores, 'restore')
self.cinder_fc.restores.restore('backup-123').AndReturn(fvbr)
@ -781,14 +774,13 @@ class VolumeTest(HeatTestCase):
self.m.VerifyAll()
@skipIf(volume_backups is None, 'unable to import volume_backups')
def test_create_from_snapshot_error(self):
stack_name = 'test_volume_stack'
fv = FakeVolumeWithStateTransition('restoring-backup', 'error')
fvbr = FakeBackupRestore('vol-123')
# create script
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
self.m.StubOutWithMock(self.cinder_fc.restores, 'restore')
self.cinder_fc.restores.restore('backup-123').AndReturn(fvbr)
@ -819,7 +811,7 @@ class VolumeTest(HeatTestCase):
fv = FakeVolume('creating', 'available')
stack_name = 'test_volume_stack'
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
self.cinder_fc.volumes.create(
size=1, availability_zone='nova',
@ -891,7 +883,7 @@ class VolumeTest(HeatTestCase):
fv = FakeVolumeWithStateTransition('downloading', 'available')
stack_name = 'test_volume_stack'
image_id = '46988116-6703-4623-9dbc-2bc6d284021b'
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
g_cli_mock = self.m.CreateMockAnything()
self.m.StubOutWithMock(glance.GlanceClientPlugin, '_create')
@ -934,7 +926,7 @@ class VolumeTest(HeatTestCase):
fv = FakeVolume('creating', 'available')
stack_name = 'test_volume_stack'
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
vol_name = utils.PhysName(stack_name, 'DataVolume')
self.cinder_fc.volumes.create(
@ -971,7 +963,7 @@ class VolumeTest(HeatTestCase):
created_at='2013-02-25T02:40:21.000000')
stack_name = 'test_volume_stack'
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
vol_name = utils.PhysName(stack_name, 'DataVolume')
self.cinder_fc.volumes.create(
@ -1136,7 +1128,7 @@ class VolumeTest(HeatTestCase):
self.cinder_fc.volumes.get(fv.id).AndReturn(fv2)
self.cinder_fc.volumes.extend(fv.id, 2).AndRaise(
clients.cinderclient.exceptions.OverLimit)
cinder_exp.OverLimit)
self.m.ReplayAll()
@ -1248,7 +1240,6 @@ class VolumeTest(HeatTestCase):
self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
@skipIf(volume_backups is None, 'unable to import volume_backups')
def test_volume_extend_created_from_snapshot_with_same_size(self):
stack_name = 'test_volume_stack'
fv = FakeVolumeWithStateTransition('restoring-backup', 'available',
@ -1256,7 +1247,7 @@ class VolumeTest(HeatTestCase):
fvbr = FakeBackupRestore('vol-123')
# create script
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
self.m.StubOutWithMock(self.cinder_fc.restores, 'restore')
self.cinder_fc.restores.restore('backup-123').AndReturn(fvbr)
@ -1304,7 +1295,7 @@ class VolumeTest(HeatTestCase):
'display_description': update_description
}
clients.OpenStackClients._cinder().MultipleTimes().AndReturn(
cinder.CinderClientPlugin._create().MultipleTimes().AndReturn(
self.cinder_fc)
self.cinder_fc.volumes.create(
availability_zone=None,

View File

@ -38,6 +38,7 @@ oslo.config.opts =
heat.common.wsgi = heat.common.wsgi:list_opts
heat.clients =
cinder = heat.engine.clients.os.cinder:CinderClientPlugin
glance = heat.engine.clients.os.glance:GlanceClientPlugin
nova = heat.engine.clients.os.nova:NovaClientPlugin
neutron = heat.engine.clients.os.neutron:NeutronClientPlugin