Fix tips jobs and convert Nova Floating IP calls

The script to install the git versions of the libraries wasn't working
because it wasn't installing over top of the versions already installed
by pip. So by adding an uninstall first, we ensure that the git version
is actually installed.

Also, add a pbr freeze to the end so that we can verify, and some +x so
that we can see the output of our scripts.

And: novaclient 8.0 doesn't have these calls anymore. However, the tests we
had on legacy clouds were erroneously installing the wrong version of
novaclient so we did not catch it. Doh. This has to do the tests and the
calls in the same patch because the fix to the gate job to install the
correct verison of the library exposed the fact that we had be broken
for these for a few minutes.

Depends-On: I208e8c009d0438de19cd3eb08dc45ddebb45d3e9
Change-Id: I4fd882aeb8373b94c7f6b54d97b457042b324361
This commit is contained in:
Monty Taylor 2017-04-27 18:46:04 -05:00
parent 33aa7948b6
commit a88d41e302
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
7 changed files with 207 additions and 187 deletions

View File

@ -15,16 +15,21 @@
# limitations under the License.
for lib in \
os-client-config \
python-novaclient \
python-keystoneclient \
python-cinderclient \
python-ironicclient \
python-designateclient \
os-client-config \
keystoneauth
do
egg=$(echo $lib | tr '-' '_' | sed 's/python-//')
if [ -d /opt/stack/new/$lib ] ; then
pip install -q -U -e "git+file:///opt/stack/new/$lib#egg=$egg"
tip_location="git+file:///opt/stack/new/$lib#egg=$egg"
echo "$(which pip) install -U -e $tip_location"
pip uninstall -y $lib
pip install -U -e $tip_location
else
echo "$lib not found in /opt/stack/new/$lib"
fi
done

View File

@ -212,31 +212,6 @@ class NovaImageList(task_manager.Task):
return client.nova_client.images.list()
class NovaFloatingIPList(task_manager.Task):
def main(self, client):
return client.nova_client.floating_ips.list()
class NovaFloatingIPCreate(task_manager.Task):
def main(self, client):
return client.nova_client.floating_ips.create(**self.args)
class NovaFloatingIPDelete(task_manager.Task):
def main(self, client):
return client.nova_client.floating_ips.delete(**self.args)
class NovaFloatingIPAttach(task_manager.Task):
def main(self, client):
return client.nova_client.servers.add_floating_ip(**self.args)
class NovaFloatingIPDetach(task_manager.Task):
def main(self, client):
return client.nova_client.servers.remove_floating_ip(**self.args)
class MachineCreate(task_manager.Task):
def main(self, client):
return client.ironic_client.node.create(**self.args)

View File

@ -2012,8 +2012,7 @@ class OpenStackCloud(
return self._network_client.get('/floatingips.json', params=filters)
def _nova_list_floating_ips(self):
with _utils.shade_exceptions("Error fetching floating IPs list"):
return self.manager.submit_task(_tasks.NovaFloatingIPList())
return self._compute_client.get('/os-floating-ips')
def use_external_network(self):
return self._use_external_network
@ -4553,8 +4552,11 @@ class OpenStackCloud(
"unable to find a floating ip pool")
pool = pools[0]['name']
pool_ip = self.manager.submit_task(
_tasks.NovaFloatingIPCreate(pool=pool))
pool_ip = self._compute_client.post(
'/os-floating-ips', json=dict(pool=pool))
# TODO(mordred) Remove this - it's just for compat
pool_ip = self._compute_client.get('/os-floating-ips/{id}'.format(
id=pool_ip['id']))
return pool_ip
def delete_floating_ip(self, floating_ip_id, retry=1):
@ -4622,16 +4624,12 @@ class OpenStackCloud(
def _nova_delete_floating_ip(self, floating_ip_id):
try:
self.manager.submit_task(
_tasks.NovaFloatingIPDelete(floating_ip=floating_ip_id))
except nova_exceptions.NotFound:
self._compute_client.delete(
'/os-floating-ips/{id}'.format(id=floating_ip_id),
error_message='Unable to delete floating IP {fip_id}'.format(
fip_id=floating_ip_id))
except OpenStackCloudURINotFound:
return False
except OpenStackCloudException:
raise
except Exception as e:
raise OpenStackCloudException(
"Unable to delete floating IP ID {fip_id}: {msg}".format(
fip_id=floating_ip_id, msg=str(e)))
return True
def delete_unattached_floating_ips(self, retry=1):
@ -4853,13 +4851,22 @@ class OpenStackCloud(
def _nova_attach_ip_to_server(self, server_id, floating_ip_id,
fixed_address=None):
with _utils.shade_exceptions(
"Error attaching IP {ip} to instance {id}".format(
ip=floating_ip_id, id=server_id)):
f_ip = self.get_floating_ip(id=floating_ip_id)
return self.manager.submit_task(_tasks.NovaFloatingIPAttach(
server=server_id, address=f_ip['floating_ip_address'],
fixed_address=fixed_address))
f_ip = self.get_floating_ip(
id=floating_ip_id)
if f_ip is None:
raise OpenStackCloudException(
"unable to find floating IP {0}".format(floating_ip_id))
error_message = "Error attaching IP {ip} to instance {id}".format(
ip=floating_ip_id, id=server_id)
body = {
'address': f_ip['floating_ip_address']
}
if fixed_address:
body['fixed_address'] = fixed_address
return self._compute_client.post(
'/servers/{server_id}/action'.format(server_id=server_id),
json=dict(addFloatingIp=body),
error_message=error_message)
def detach_ip_from_server(self, server_id, floating_ip_id):
"""Detach a floating IP from a server.
@ -4900,24 +4907,18 @@ class OpenStackCloud(
return True
def _nova_detach_ip_from_server(self, server_id, floating_ip_id):
try:
f_ip = self.get_floating_ip(id=floating_ip_id)
if f_ip is None:
raise OpenStackCloudException(
"unable to find floating IP {0}".format(floating_ip_id))
self.manager.submit_task(_tasks.NovaFloatingIPDetach(
server=server_id, address=f_ip['floating_ip_address']))
except nova_exceptions.Conflict as e:
self.log.debug(
"nova floating IP detach failed: %(msg)s", {'msg': str(e)},
exc_info=True)
return False
except OpenStackCloudException:
raise
except Exception as e:
f_ip = self.get_floating_ip(id=floating_ip_id)
if f_ip is None:
raise OpenStackCloudException(
"Error detaching IP {ip} from instance {id}: {msg}".format(
ip=floating_ip_id, id=server_id, msg=str(e)))
"unable to find floating IP {0}".format(floating_ip_id))
error_message = "Error detaching IP {ip} from instance {id}".format(
ip=floating_ip_id, id=server_id)
return self._compute_client.post(
'/servers/{server_id}/action'.format(server_id=server_id),
json=dict(removeFloatingIp=dict(
address=f_ip['floating_ip_address'])),
error_message=error_message)
return True

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash -x
# 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
@ -46,6 +46,7 @@ set +e
sudo -E -H -u jenkins tox -e$tox_env
EXIT_CODE=$?
sudo testr last --subunit > $WORKSPACE/tempest.subunit
.tox/$tox_env/bin/pbr freeze
set -e
exit $EXIT_CODE

View File

@ -166,8 +166,8 @@ class TestFloatingIP(base.BaseFunctionalTestCase):
content.text_content(pprint.pformat(
self.user_cloud.list_networks())))
else:
# ToDo: remove once we have list/get methods for nova networks
nets = self.user_cloud.nova_client.networks.list()
# Find network names for nova-net
nets = self.user_cloud._compute_client.get('/os-tenant-networks')
self.addDetail(
'networks-nova',
content.text_content(pprint.pformat(

View File

@ -19,22 +19,20 @@ test_floating_ip_nova
Tests Floating IP resource methods for nova-network
"""
from mock import patch
from novaclient import exceptions as n_exc
from shade import meta
from shade import OpenStackCloud
from shade.tests import fakes
from shade.tests.unit import base
def has_service_side_effect(s):
if s == 'network':
return False
return True
def get_fake_has_service(has_service):
def fake_has_service(s):
if s == 'network':
return False
return has_service(s)
return fake_has_service
class TestFloatingIP(base.TestCase):
class TestFloatingIP(base.RequestsMockTestCase):
mock_floating_ip_list_rep = [
{
'fixed_ip': None,
@ -69,9 +67,6 @@ class TestFloatingIP(base.TestCase):
def setUp(self):
super(TestFloatingIP, self).setUp()
self.floating_ips = [
fakes.FakeFloatingIP(**ip) for ip in self.mock_floating_ip_list_rep
]
self.fake_server = meta.obj_to_dict(
fakes.FakeServer(
@ -83,172 +78,223 @@ class TestFloatingIP(base.TestCase):
u'OS-EXT-IPS-MAC:mac_addr':
u'fa:16:3e:ae:7d:42'}]}))
self.floating_ip = self.cloud._normalize_floating_ips(
meta.obj_list_to_dict(self.floating_ips))[0]
self.cloud.has_service = get_fake_has_service(self.cloud.has_service)
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_list_floating_ips(self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.list.return_value = self.floating_ips
def test_list_floating_ips(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep}),
])
floating_ips = self.cloud.list_floating_ips()
mock_nova_client.floating_ips.list.assert_called_with()
self.assertIsInstance(floating_ips, list)
self.assertEqual(3, len(floating_ips))
self.assertAreInstances(floating_ips, dict)
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_list_floating_ips_with_filters(self, mock_has_service,
mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
self.assert_calls()
def test_list_floating_ips_with_filters(self):
self.assertRaisesRegex(
ValueError, "Nova-network don't support server-side",
self.cloud.list_floating_ips, filters={'Foo': 42}
)
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_search_floating_ips(self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.list.return_value = self.floating_ips
def test_search_floating_ips(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep}),
])
floating_ips = self.cloud.search_floating_ips(
filters={'attached': False})
mock_nova_client.floating_ips.list.assert_called_with()
self.assertIsInstance(floating_ips, list)
self.assertEqual(2, len(floating_ips))
self.assertAreInstances(floating_ips, dict)
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_get_floating_ip(self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.list.return_value = self.floating_ips
self.assert_calls()
def test_get_floating_ip(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep}),
])
floating_ip = self.cloud.get_floating_ip(id='29')
mock_nova_client.floating_ips.list.assert_called_with()
self.assertIsInstance(floating_ip, dict)
self.assertEqual('198.51.100.29', floating_ip['floating_ip_address'])
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_get_floating_ip_not_found(
self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.list.return_value = self.floating_ips
self.assert_calls()
def test_get_floating_ip_not_found(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep}),
])
floating_ip = self.cloud.get_floating_ip(id='666')
self.assertIsNone(floating_ip)
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_create_floating_ip(self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.create.return_value =\
fakes.FakeFloatingIP(**self.mock_floating_ip_list_rep[1])
self.assert_calls()
def test_create_floating_ip(self):
self.register_uris([
dict(method='POST',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ip': self.mock_floating_ip_list_rep[1]},
validate=dict(
json={'pool': 'nova'})),
dict(method='GET',
uri=self.get_mock_url(
'compute',
append=['os-floating-ips', '2']),
json={'floating_ips': self.mock_floating_ip_list_rep[1]}),
])
self.cloud.create_floating_ip(network='nova')
mock_nova_client.floating_ips.create.assert_called_with(pool='nova')
self.assert_calls()
@patch.object(OpenStackCloud, '_nova_list_floating_ips')
@patch.object(OpenStackCloud, 'has_service')
def test_available_floating_ip_existing(
self, mock_has_service, mock__nova_list_floating_ips):
mock_has_service.side_effect = has_service_side_effect
mock__nova_list_floating_ips.return_value = \
self.mock_floating_ip_list_rep[:1]
def test_available_floating_ip_existing(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep[:1]}),
])
ip = self.cloud.available_floating_ip(network='nova')
self.assertEqual(self.mock_floating_ip_list_rep[0]['ip'],
ip['floating_ip_address'])
self.assert_calls()
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, '_nova_list_floating_ips')
@patch.object(OpenStackCloud, 'has_service')
def test_available_floating_ip_new(
self, mock_has_service, mock__nova_list_floating_ips,
mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock__nova_list_floating_ips.return_value = []
mock_nova_client.floating_ips.create.return_value = \
fakes.FakeFloatingIP(**self.mock_floating_ip_list_rep[0])
def test_available_floating_ip_new(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': []}),
dict(method='POST',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ip': self.mock_floating_ip_list_rep[0]},
validate=dict(
json={'pool': 'nova'})),
dict(method='GET',
uri=self.get_mock_url(
'compute',
append=['os-floating-ips', '1']),
json={'floating_ip': self.mock_floating_ip_list_rep[0]}),
])
ip = self.cloud.available_floating_ip(network='nova')
self.assertEqual(self.mock_floating_ip_list_rep[0]['ip'],
ip['floating_ip_address'])
self.assert_calls()
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_delete_floating_ip_existing(
self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.delete.return_value = None
def test_delete_floating_ip_existing(self):
self.register_uris([
dict(method='DELETE',
uri=self.get_mock_url(
'compute',
append=['os-floating-ips', 'a-wild-id-appears'])),
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': []}),
])
ret = self.cloud.delete_floating_ip(
floating_ip_id='a-wild-id-appears')
mock_nova_client.floating_ips.delete.assert_called_with(
floating_ip='a-wild-id-appears')
self.assertTrue(ret)
self.assert_calls()
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'get_floating_ip')
@patch.object(OpenStackCloud, '_use_neutron_floating')
def test_delete_floating_ip_not_found(
self, mock_use_floating, mock_get_floating_ip, mock_nova_client):
mock_use_floating.return_value = False
mock_get_floating_ip.return_value = None
mock_nova_client.floating_ips.delete.side_effect = n_exc.NotFound(
code=404)
def test_delete_floating_ip_not_found(self):
self.register_uris([
dict(method='DELETE',
uri=self.get_mock_url(
'compute',
append=['os-floating-ips', 'a-wild-id-appears']),
status_code=404),
])
ret = self.cloud.delete_floating_ip(
floating_ip_id='a-wild-id-appears')
self.assertFalse(ret)
self.assert_calls()
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_attach_ip_to_server(self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.list.return_value = self.floating_ips
def test_attach_ip_to_server(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep}),
dict(method='POST',
uri=self.get_mock_url(
'compute',
append=['servers', self.fake_server.id, 'action']),
validate=dict(
json={
"addFloatingIp": {
"address": "203.0.113.1",
"fixed_address": "192.0.2.129",
}})),
])
self.cloud._attach_ip_to_server(
server=self.fake_server, floating_ip=self.floating_ip,
server=self.fake_server,
floating_ip=self.cloud._normalize_floating_ip(
self.mock_floating_ip_list_rep[0]),
fixed_address='192.0.2.129')
mock_nova_client.servers.add_floating_ip.assert_called_with(
server='server-id', address='203.0.113.1',
fixed_address='192.0.2.129')
self.assert_calls()
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_detach_ip_from_server(self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.list.return_value = [
fakes.FakeFloatingIP(**ip) for ip in self.mock_floating_ip_list_rep
]
def test_detach_ip_from_server(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep}),
dict(method='POST',
uri=self.get_mock_url(
'compute',
append=['servers', self.fake_server.id, 'action']),
validate=dict(
json={
"removeFloatingIp": {
"address": "203.0.113.1",
}})),
])
self.cloud.detach_ip_from_server(
server_id='server-id', floating_ip_id=1)
self.assert_calls()
mock_nova_client.servers.remove_floating_ip.assert_called_with(
server='server-id', address='203.0.113.1')
@patch.object(OpenStackCloud, 'nova_client')
@patch.object(OpenStackCloud, 'has_service')
def test_add_ip_from_pool(self, mock_has_service, mock_nova_client):
mock_has_service.side_effect = has_service_side_effect
mock_nova_client.floating_ips.list.return_value = self.floating_ips
def test_add_ip_from_pool(self):
self.register_uris([
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep}),
dict(method='GET',
uri=self.get_mock_url('compute', append=['os-floating-ips']),
json={'floating_ips': self.mock_floating_ip_list_rep}),
dict(method='POST',
uri=self.get_mock_url(
'compute',
append=['servers', self.fake_server.id, 'action']),
validate=dict(
json={
"addFloatingIp": {
"address": "203.0.113.1",
"fixed_address": "192.0.2.129",
}})),
])
server = self.cloud._add_ip_from_pool(
server=self.fake_server,
@ -256,16 +302,8 @@ class TestFloatingIP(base.TestCase):
fixed_address='192.0.2.129')
self.assertEqual(server, self.fake_server)
self.assert_calls()
@patch.object(OpenStackCloud, 'delete_floating_ip')
@patch.object(OpenStackCloud, 'list_floating_ips')
@patch.object(OpenStackCloud, '_use_neutron_floating')
def test_cleanup_floating_ips(
self, mock_use_neutron_floating, mock_list_floating_ips,
mock_delete_floating_ip):
mock_use_neutron_floating.return_value = False
def test_cleanup_floating_ips(self):
# This should not call anything because it's unsafe on nova.
self.cloud.delete_unattached_floating_ips()
mock_delete_floating_ip.assert_not_called()
mock_list_floating_ips.assert_not_called()

View File

@ -26,7 +26,7 @@ setenv =
passenv = OS_* SHADE_*
whitelist_externals = bash
commands =
bash extras/install-tips.sh
bash -x {toxinidir}/extras/install-tips.sh
python setup.py testr --slowest --testr-args='--concurrency=1 {posargs}'
[testenv:pep8]