fix issue with Nova passthrough deprecation
Nova Networking was deprecated in Newton and some of the API calls that were part of NN were still in use by Trove. With the arrival of python-novaclient 8.0.0, this caused a failure. Nova also deprecated the image pass through capability. The management API uses some of that to test whether an image id is valid or not. This change fixes the management API, and the attendant scenario tests. Depends-On: I142f97d691fa55e9824714c9c224f998ad72337e Change-Id: I2f2a12207581a94fb8561a6d65a3a79b4a29b063 Closes-Bug: #1690936
This commit is contained in:
parent
012da9a334
commit
3ed3ea94bb
@ -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"]
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -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.'),
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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):
|
||||
|
@ -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])
|
||||
|
@ -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()
|
||||
|
@ -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(
|
||||
|
@ -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'])
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user