diff --git a/integration/scripts/conf/test_begin.conf b/integration/scripts/conf/test_begin.conf index b997943014..1352ecc55e 100644 --- a/integration/scripts/conf/test_begin.conf +++ b/integration/scripts/conf/test_begin.conf @@ -13,6 +13,10 @@ "volume_service_type":"volume" }, + "glance_client": { + "auth_url":"http://%service_host%/identity/v2.0" + }, + "flavors": null, "white_box":false, @@ -74,7 +78,7 @@ "tenant_id":"%demo_tenant_id%", "requirements": { "is_admin":false, - "services": ["nova", "trove"] + "services": ["nova", "glance", "trove"] } } ], diff --git a/trove/common/cfg.py b/trove/common/cfg.py index eefe9e97b4..6f001a15f7 100644 --- a/trove/common/cfg.py +++ b/trove/common/cfg.py @@ -66,6 +66,8 @@ common_opts = [ help='Service endpoint type to use when searching catalog.'), cfg.StrOpt('nova_client_version', default='2.12', help="The version of the compute service client."), + cfg.StrOpt('glance_client_version', default='2', + help="The version of the image service client."), cfg.URIOpt('neutron_url', help='URL without the tenant segment.'), cfg.StrOpt('neutron_service_type', default='network', help='Service type to use when searching catalog.'), diff --git a/trove/common/glance_remote.py b/trove/common/glance_remote.py index 0bcde97b1a..d2f9fdd98b 100644 --- a/trove/common/glance_remote.py +++ b/trove/common/glance_remote.py @@ -47,7 +47,8 @@ def glance_client(context, region_name=None): auth = v3.Token(CONF.trove_auth_url, context.auth_token) session = ka_session.Session(auth=auth) - return Client('2', endpoint=endpoint_url, session=session) + return Client(CONF.glance_client_version, endpoint=endpoint_url, + session=session) create_glance_client = import_class(CONF.remote_glance_client) diff --git a/trove/extensions/mgmt/datastores/service.py b/trove/extensions/mgmt/datastores/service.py index 7cf5d94da4..8090cbb87b 100644 --- a/trove/extensions/mgmt/datastores/service.py +++ b/trove/extensions/mgmt/datastores/service.py @@ -13,14 +13,14 @@ # limitations under the License. -from novaclient import exceptions as nova_exceptions +from glanceclient import exc as glance_exceptions from oslo_log import log as logging from trove.common import apischema as apischema from trove.common.auth import admin_context from trove.common import exception +from trove.common import glance_remote from trove.common.i18n import _ -from trove.common import remote from trove.common import utils from trove.common import wsgi from trove.datastore import models @@ -53,10 +53,10 @@ class DatastoreVersionController(wsgi.Controller): {'tenant': tenant_id, 'version': version_name, 'datastore': datastore_name}) - client = remote.create_nova_client(context) + client = glance_remote.create_glance_client(context) try: client.images.get(image_id) - except nova_exceptions.NotFound: + except glance_exceptions.HTTPNotFound: raise exception.ImageNotFound(uuid=image_id) try: @@ -119,10 +119,10 @@ class DatastoreVersionController(wsgi.Controller): if type(packages) is list: packages = ','.join(packages) - client = remote.create_nova_client(context) + client = glance_remote.create_glance_client(context) try: client.images.get(image_id) - except nova_exceptions.NotFound: + except glance_exceptions.HTTPNotFound: raise exception.ImageNotFound(uuid=image_id) models.update_datastore_version(datastore_version.datastore_name, diff --git a/trove/taskmanager/models.py b/trove/taskmanager/models.py index f7470103f9..5eb421693c 100755 --- a/trove/taskmanager/models.py +++ b/trove/taskmanager/models.py @@ -1345,8 +1345,11 @@ class BuiltInstanceTasks(BuiltInstance, NotifyMixin, ConfigurationMixin): def _get_floating_ips(self): """Returns floating ips as a dict indexed by the ip.""" floating_ips = {} - for ip in self.nova_client.floating_ips.list(): - floating_ips.update({ip.ip: ip}) + neutron_client = remote.create_neutron_client(self.context) + network_floating_ips = neutron_client.list_floatingips() + for ip in network_floating_ips.get('floatingips'): + floating_ips.update({ip.get('floating_ip_address'): ip}) + LOG.debug("In _get_floating_ips(), returning %s" % floating_ips) return floating_ips def detach_public_ips(self): diff --git a/trove/tests/api/mgmt/datastore_versions.py b/trove/tests/api/mgmt/datastore_versions.py index 94cf30ae3a..5ae4770c08 100644 --- a/trove/tests/api/mgmt/datastore_versions.py +++ b/trove/tests/api/mgmt/datastore_versions.py @@ -25,7 +25,7 @@ from troveclient.compat import exceptions from trove.tests.config import CONFIG from trove.tests.util import create_client from trove.tests.util import create_dbaas_client -from trove.tests.util import create_nova_client +from trove.tests.util import create_glance_client from trove.tests.util import test_config from trove.tests.util.users import Requirements @@ -49,11 +49,14 @@ class MgmtDataStoreVersion(object): reqs = Requirements(is_admin=True) self.user = CONFIG.users.find_user(reqs) self.client = create_dbaas_client(self.user) - if test_config.nova_client is not None: - nova_user = test_config.users.find_user( - Requirements(services=["nova"])) - self.nova_client = create_nova_client(nova_user) - self.images = self.nova_client.images.list() + self.images = [] + if test_config.glance_client is not None: + glance_user = test_config.users.find_user( + Requirements(services=["glance"])) + self.glance_client = create_glance_client(glance_user) + images = self.glance_client.images.list() + for image in images: + self.images.append(image.id) def _find_ds_version_by_name(self, ds_version_name): ds_versions = self.client.mgmt_datastore_versions.list() @@ -112,7 +115,7 @@ class MgmtDataStoreVersion(object): """Tests the mgmt datastore version create method.""" response = self.client.mgmt_datastore_versions.create( 'test_version1', 'test_ds', 'test_mgr', - self.images[0].id, ['vertica-7.1']) + self.images[0], ['vertica-7.1']) assert_equal(None, response) assert_equal(202, self.client.last_http_code) @@ -127,7 +130,7 @@ class MgmtDataStoreVersion(object): assert_equal('test_version1', self.created_version.name) assert_equal('test_ds', self.created_version.datastore_name) assert_equal('test_mgr', self.created_version.datastore_manager) - assert_equal(self.images[0].id, self.created_version.image) + assert_equal(self.images[0], self.created_version.image) assert_equal(['vertica-7.1'], self.created_version.packages) assert_true(self.created_version.active) assert_false(self.created_version.default) @@ -136,13 +139,13 @@ class MgmtDataStoreVersion(object): def test_mgmt_ds_version_patch(self): """Tests the mgmt datastore version edit method.""" self.client.mgmt_datastore_versions.edit( - self.created_version.id, image=self.images[1].id, + self.created_version.id, image=self.images[1], packages=['pkg1']) assert_equal(202, self.client.last_http_code) # Lets match the content of patched datastore patched_ds_version = self._find_ds_version_by_name('test_version1') - assert_equal(self.images[1].id, patched_ds_version.image) + assert_equal(self.images[1], patched_ds_version.image) assert_equal(['pkg1'], patched_ds_version.packages) @test(depends_on=[test_mgmt_ds_version_patch]) diff --git a/trove/tests/unittests/mgmt/test_datastore_controller.py b/trove/tests/unittests/mgmt/test_datastore_controller.py index d24cf1f824..9b59487980 100644 --- a/trove/tests/unittests/mgmt/test_datastore_controller.py +++ b/trove/tests/unittests/mgmt/test_datastore_controller.py @@ -18,7 +18,7 @@ from mock import Mock, patch, MagicMock, PropertyMock from testtools.matchers import Is, Equals from trove.common import exception -from trove.common import remote +from trove.common import glance_remote from trove.datastore import models as datastore_models from trove.extensions.mgmt.datastores.service import DatastoreVersionController from trove.tests.unittests import trove_testtools @@ -81,14 +81,14 @@ class TestDatastoreVersionController(trove_testtools.TestCase): self.assertIn("'' is too short", error_messages) self.assertIn("'' does not match '^.*[0-9a-zA-Z]+.*$'", error_messages) - @patch.object(remote, 'create_nova_client') + @patch.object(glance_remote, 'create_glance_client') @patch.object(datastore_models.Datastore, 'load') @patch.object(datastore_models.DatastoreVersion, 'load', side_effect=exception.DatastoreVersionNotFound) @patch.object(datastore_models, 'update_datastore_version') def test_create_datastore_versions(self, mock_ds_version_create, mock_ds_version_load, - mock_ds_load, mock_nova_client): + mock_ds_load, mock_glance_client): body = self.version mock_ds_load.return_value.name = 'test_dsx' @@ -127,12 +127,12 @@ class TestDatastoreVersionController(trove_testtools.TestCase): mock_ds_version_load_all.assert_called_with(only_active=False) mock_ds_version_load_by_uuid.assert_called_with(mock_id) - @patch.object(remote, 'create_nova_client') + @patch.object(glance_remote, 'create_glance_client') @patch.object(datastore_models.DatastoreVersion, 'load_by_uuid') @patch.object(datastore_models, 'update_datastore_version') def test_edit_datastore_versions(self, mock_ds_version_update, mock_ds_version_load, - mock_nova_client): + mock_glance_client): body = {'image': '21c8805a-a800-4bca-a192-3a5a2519044d'} mock_ds_version = MagicMock() diff --git a/trove/tests/unittests/mgmt/test_datastores.py b/trove/tests/unittests/mgmt/test_datastores.py index 3d1ea179f7..4fe8318345 100644 --- a/trove/tests/unittests/mgmt/test_datastores.py +++ b/trove/tests/unittests/mgmt/test_datastores.py @@ -13,10 +13,10 @@ # limitations under the License. from mock import Mock, patch -from novaclient import exceptions as nova_exceptions +from glanceclient import exc as glance_exceptions from trove.common import exception -from trove.common import remote +from trove.common import glance_remote from trove.datastore import models from trove.extensions.mgmt.datastores.service import DatastoreVersionController from trove.tests.unittests import trove_testtools @@ -48,8 +48,8 @@ class TestDatastoreVersion(trove_testtools.TestCase): def tearDown(self): super(TestDatastoreVersion, self).tearDown() - @patch.object(remote, 'create_nova_client') - def test_version_create(self, mock_nova_client): + @patch.object(glance_remote, 'create_glance_client') + def test_version_create(self, mock_glance_client): body = {"version": { "datastore_name": "test_ds", "name": "test_vr", @@ -62,10 +62,10 @@ class TestDatastoreVersion(trove_testtools.TestCase): self.req, body, self.tenant_id) self.assertEqual(202, output.status) - @patch.object(remote, 'create_nova_client') + @patch.object(glance_remote, 'create_glance_client') @patch.object(models.DatastoreVersion, 'load') def test_fail_already_exists_version_create(self, mock_load, - mock_nova_client): + mock_glance_client): body = {"version": { "datastore_name": "test_ds", "name": "test_new_vr", @@ -79,12 +79,10 @@ class TestDatastoreVersion(trove_testtools.TestCase): "A datastore version with the name 'test_new_vr' already exists", self.version_controller.create, self.req, body, self.tenant_id) - @patch.object(remote, 'create_nova_client') - def test_fail_image_not_found_version_create(self, mock_nova_client): - mock_nova_client.return_value.images.get = Mock( - side_effect=nova_exceptions.NotFound(404, - "Image id not found image-id" - )) + @patch.object(glance_remote, 'create_glance_client') + def test_fail_image_not_found_version_create(self, mock_glance_client): + mock_glance_client.return_value.images.get = Mock( + side_effect=glance_exceptions.HTTPNotFound()) body = {"version": { "datastore_name": "test_ds", "name": "test_vr", @@ -114,7 +112,7 @@ class TestDatastoreVersion(trove_testtools.TestCase): exception.DatastoreVersionNotFound, err_msg, models.DatastoreVersion.load_by_uuid, ds_version1.id) - @patch.object(remote, 'create_nova_client') + @patch.object(glance_remote, 'create_glance_client') def test_version_update(self, mock_client): body = {"image": "c022f4dc-76ed-4e3f-a25e-33e031f43f8b"} output = self.version_controller.edit(self.req, body, @@ -127,12 +125,10 @@ class TestDatastoreVersion(trove_testtools.TestCase): self.ds_version2.id) self.assertEqual(body['image'], test_ds_version.image_id) - @patch.object(remote, 'create_nova_client') - def test_version_update_fail_image_not_found(self, mock_nova_client): - mock_nova_client.return_value.images.get = Mock( - side_effect=nova_exceptions.NotFound(404, - "Image id not found image-id" - )) + @patch.object(glance_remote, 'create_glance_client') + def test_version_update_fail_image_not_found(self, mock_glance_client): + mock_glance_client.return_value.images.get = Mock( + side_effect=glance_exceptions.HTTPNotFound()) body = {"image": "non-existent-image-id"} self.assertRaisesRegexp( diff --git a/trove/tests/unittests/taskmanager/test_models.py b/trove/tests/unittests/taskmanager/test_models.py index 1140eaf3cb..7fbba5dd20 100644 --- a/trove/tests/unittests/taskmanager/test_models.py +++ b/trove/tests/unittests/taskmanager/test_models.py @@ -59,6 +59,11 @@ INST_ID = 'dbinst-id-1' VOLUME_ID = 'volume-id-1' +class _fake_neutron_client(object): + def list_floatingips(self): + return {'floatingips': [{'floating_ip_address': '192.168.10.1'}]} + + class FakeOptGroup(object): def __init__(self, tcp_ports=['3306', '3301-3307'], udp_ports=[], icmp=False): @@ -740,14 +745,6 @@ class BuiltInstanceTasksTest(trove_testtools.TestCase): if 'volume' in self._testMethodName: self._stub_volume_client() - stub_floating_ips_manager = MagicMock( - spec=novaclient.v2.floating_ips.FloatingIPManager) - self.instance_task._nova_client.floating_ips = ( - stub_floating_ips_manager) - floatingip = novaclient.v2.floating_ips.FloatingIP( - stub_floating_ips_manager, {'ip': '192.168.10.1'}, True) - stub_floating_ips_manager.list = MagicMock(return_value=[floatingip]) - def tearDown(self): super(BuiltInstanceTasksTest, self).tearDown() @@ -878,14 +875,20 @@ class BuiltInstanceTasksTest(trove_testtools.TestCase): Mock()) def test_get_floating_ips(self): - floating_ips = self.instance_task._get_floating_ips() - self.assertEqual('192.168.10.1', floating_ips['192.168.10.1'].ip) + with patch.object(remote, 'create_neutron_client', + return_value=_fake_neutron_client()): + floating_ips = self.instance_task._get_floating_ips() + self.assertEqual('192.168.10.1', + floating_ips['192.168.10.1'].get( + 'floating_ip_address')) @patch.object(BaseInstance, 'get_visible_ip_addresses', return_value=['192.168.10.1']) def test_detach_public_ips(self, mock_address): - removed_ips = self.instance_task.detach_public_ips() - self.assertEqual(['192.168.10.1'], removed_ips) + with patch.object(remote, 'create_neutron_client', + return_value=_fake_neutron_client()): + removed_ips = self.instance_task.detach_public_ips() + self.assertEqual(['192.168.10.1'], removed_ips) def test_attach_public_ips(self): self.instance_task.attach_public_ips(['192.168.10.1']) diff --git a/trove/tests/util/__init__.py b/trove/tests/util/__init__.py index f0b8fc265d..9ffee23f7f 100644 --- a/trove/tests/util/__init__.py +++ b/trove/tests/util/__init__.py @@ -177,6 +177,24 @@ def create_nova_client(user, service_type=None): return TestClient(openstack) +def create_glance_client(user): + """Creates a rich client for the Glance API using the test config.""" + if test_config.glance_client is None: + raise SkipTest("No glance_client info specified in the Test Config " + "so this test will be skipped.") + from glanceclient import Client + from keystoneauth1.identity import v2 + from keystoneauth1 import session + + auth = v2.Password(username=user.auth_user, + password=user.auth_key, + tenant_name=user.tenant, + auth_url=test_config.glance_client['auth_url']) + session = session.Session(auth=auth) + glance = Client(CONF.glance_client_version, session=session) + return TestClient(glance) + + def dns_checker(mgmt_instance): """Given a MGMT instance, ensures DNS provisioning worked.