Merge "Replace deprecated nova calls for floatingip"

This commit is contained in:
Zuul 2018-03-01 12:51:47 +00:00 committed by Gerrit Code Review
commit 930a93fdc1
4 changed files with 134 additions and 122 deletions

View File

@ -25,3 +25,7 @@ class EntityMatchNotFound(exception.HeatException):
class EntityUniqueMatchNotFound(EntityMatchNotFound):
msg_fmt = _("No %(entity)s unique match found for %(args)s.")
class InterfaceNotFound(exception.HeatException):
msg_fmt = _("No network interface found for server %(id)s.")

View File

@ -19,17 +19,20 @@ import os
import pkgutil
import string
from neutronclient.common import exceptions as q_exceptions
from novaclient import client as nc
from novaclient import exceptions
from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import netutils
import six
from six.moves.urllib import parse as urlparse
import tenacity
from heat.common import exception
from heat.common.i18n import _
from heat.engine.clients import client_exception
from heat.engine.clients import client_plugin
from heat.engine.clients import os as os_client
from heat.engine import constraints
@ -100,7 +103,8 @@ class NovaClientPlugin(client_plugin.ClientPlugin):
return client
def is_not_found(self, ex):
return isinstance(ex, exceptions.NotFound)
return isinstance(ex, (exceptions.NotFound,
q_exceptions.NotFound))
def is_over_limit(self, ex):
return isinstance(ex, exceptions.OverLimit)
@ -672,6 +676,34 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
{'att': attach_id, 'srv': server_id})
return False
def associate_floatingip(self, server_id, floatingip_id):
iface_list = self.fetch_server(server_id).interface_list()
if len(iface_list) == 0:
raise client_exception.InterfaceNotFound(id=server_id)
if len(iface_list) > 1:
LOG.warning("Multiple interfaces found for server %s, "
"using the first one.", server_id)
port_id = iface_list[0].port_id
fixed_ips = iface_list[0].fixed_ips
fixed_address = next(ip['ip_address'] for ip in fixed_ips
if netutils.is_valid_ipv4(ip['ip_address']))
request_body = {
'floatingip': {
'port_id': port_id,
'fixed_ip_address': fixed_address}}
self.clients.client('neutron').update_floatingip(floatingip_id,
request_body)
def dissociate_floatingip(self, floatingip_id):
request_body = {
'floatingip': {
'port_id': None,
'fixed_ip_address': None}}
self.clients.client('neutron').update_floatingip(floatingip_id,
request_body)
def interface_detach(self, server_id, port_id):
with self.ignore_not_found:
server = self.fetch_server(server_id)

View File

@ -109,7 +109,6 @@ class NovaFloatingIp(resource.Resource):
def handle_delete(self):
with self.client_plugin('neutron').ignore_not_found:
self.neutron().delete_floatingip(self.resource_id)
return True
def _resolve_attribute(self, key):
if self.resource_id is None:
@ -167,49 +166,29 @@ class NovaFloatingIpAssociation(resource.Resource):
return self.physical_resource_name_or_FnGetRefId()
def handle_create(self):
server = self.client().servers.get(self.properties[self.SERVER])
fl_ip = self.neutron().show_floatingip(
self.properties[self.FLOATING_IP])
ip_address = fl_ip['floatingip']['floating_ip_address']
self.client().servers.add_floating_ip(server, ip_address)
self.client_plugin().associate_floatingip(
self.properties[self.SERVER], self.properties[self.FLOATING_IP])
self.resource_id_set(self.id)
def handle_delete(self):
if self.resource_id is None:
return
try:
server = self.client().servers.get(self.properties[self.SERVER])
if server:
fl_ip = self.neutron().show_floatingip(
self.properties[self.FLOATING_IP])
ip_address = fl_ip['floatingip']['floating_ip_address']
self.client().servers.remove_floating_ip(server, ip_address)
except Exception as e:
if not (self.client_plugin().is_not_found(e)
or self.client_plugin().is_conflict(e)
or self.client_plugin('neutron').is_not_found(e)):
raise
with self.client_plugin().ignore_not_found:
self.client_plugin().dissociate_floatingip(
self.properties[self.FLOATING_IP])
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
if prop_diff:
# If floating_ip in prop_diff, we need to remove the old floating
# ip from the old server, and then to add the new floating ip
# to the old/new(if the server_id is changed) server.
# If prop_diff only has the server_id, no need to remove the
# floating ip from the old server, nova does this automatically
# when calling add_floating_ip().
if self.FLOATING_IP in prop_diff:
self.handle_delete()
server_id = (prop_diff.get(self.SERVER) or
self.properties[self.SERVER])
fl_ip_id = (prop_diff.get(self.FLOATING_IP) or
self.properties[self.FLOATING_IP])
server = self.client().servers.get(server_id)
fl_ip = self.neutron().show_floatingip(fl_ip_id)
ip_address = fl_ip['floatingip']['floating_ip_address']
self.client().servers.add_floating_ip(server, ip_address)
self.client_plugin().associate_floatingip(server_id, fl_ip_id)
self.resource_id_set(self.id)

View File

@ -63,28 +63,27 @@ floating_ip_template_with_assoc = '''
class NovaFloatingIPTest(common.HeatTestCase):
def setUp(self):
super(NovaFloatingIPTest, self).setUp()
self.novaclient = mock.Mock()
self.m.StubOutWithMock(nova.NovaClientPlugin, '_create')
self.m.StubOutWithMock(self.novaclient.servers, 'get')
self.m.StubOutWithMock(neutronclient.Client, 'list_networks')
self.novaclient = fakes_nova.FakeClient()
self.patchobject(nova.NovaClientPlugin, '_create',
return_value=self.novaclient)
self.m.StubOutWithMock(neutronclient.Client,
'create_floatingip')
self.m.StubOutWithMock(neutronclient.Client,
'show_floatingip')
self.m.StubOutWithMock(neutronclient.Client,
'update_floatingip')
self.m.StubOutWithMock(neutronclient.Client,
'delete_floatingip')
self.m.StubOutWithMock(self.novaclient.servers, 'add_floating_ip')
self.m.StubOutWithMock(self.novaclient.servers, 'remove_floating_ip')
self.patchobject(nova.NovaClientPlugin, 'get_server',
return_value=mock.MagicMock())
self.patchobject(nova.NovaClientPlugin, 'has_extension',
return_value=True)
self.patchobject(neutron.NeutronClientPlugin,
'find_resourceid_by_name_or_id',
return_value='eeee')
def mock_interface(self, port, ip):
class MockIface(object):
def __init__(self, port_id, fixed_ip):
self.port_id = port_id
self.fixed_ips = [{'ip_address': fixed_ip}]
return MockIface(port, ip)
def mock_create_floatingip(self):
neutronclient.Client.create_floatingip({
'floatingip': {'floating_network_id': u'eeee'}
@ -95,22 +94,28 @@ class NovaFloatingIPTest(common.HeatTestCase):
"floating_ip_address": "11.0.0.1"
}})
def mock_show_floatingip(self, refid):
if refid == 'fc68ea2c-b60b-4b4f-bd82-94ec81110766':
address = '11.0.0.1'
def mock_update_floatingip(self,
fip='fc68ea2c-b60b-4b4f-bd82-94ec81110766',
ex=None, fip_request=None,
delete_assc=False):
if fip_request:
request_body = fip_request
elif delete_assc:
request_body = {
'floatingip': {
'port_id': None,
'fixed_ip_address': None}}
else:
address = '11.0.0.2'
neutronclient.Client.show_floatingip(
refid,
).AndReturn({'floatingip': {
'router_id': None,
'tenant_id': 'e936e6cd3e0b48dcb9ff853a8f253257',
'floating_network_id': 'eeee',
'fixed_ip_address': None,
'floating_ip_address': address,
'port_id': None,
'id': 'ffff'
}})
request_body = {
'floatingip': {
'port_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
'fixed_ip_address': '1.2.3.4'}}
if ex:
neutronclient.Client.update_floatingip(
fip, request_body).AndRaise(ex)
else:
neutronclient.Client.update_floatingip(
fip, request_body).AndReturn(None)
def mock_delete_floatingip(self):
id = 'fc68ea2c-b60b-4b4f-bd82-94ec81110766'
@ -127,10 +132,12 @@ class NovaFloatingIPTest(common.HeatTestCase):
self.stack)
def prepare_floating_ip_assoc(self):
nova.NovaClientPlugin._create().AndReturn(
self.novaclient)
self.novaclient.servers.get('67dc62f9-efde-4c8b-94af-013e00f5dc57')
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
return_server = self.novaclient.servers.list()[1]
self.patchobject(self.novaclient.servers, 'get',
return_value=return_server)
iface = self.mock_interface('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
'1.2.3.4')
self.patchobject(return_server, 'interface_list', return_value=[iface])
template = template_format.parse(floating_ip_template_with_assoc)
self.stack = utils.parse_stack(template)
resource_defns = self.stack.t.resource_definitions(self.stack)
@ -169,9 +176,7 @@ class NovaFloatingIPTest(common.HeatTestCase):
def test_delete_floating_ip_assoc_successful_if_create_failed(self):
rsrc = self.prepare_floating_ip_assoc()
self.novaclient.servers.add_floating_ip(None, '11.0.0.1').AndRaise(
fakes_nova.fake_exception(400))
self.mock_update_floatingip(fakes_nova.fake_exception(400))
self.m.ReplayAll()
rsrc.validate()
@ -185,7 +190,7 @@ class NovaFloatingIPTest(common.HeatTestCase):
def test_floating_ip_assoc_create(self):
rsrc = self.prepare_floating_ip_assoc()
self.novaclient.servers.add_floating_ip(None, '11.0.0.1')
self.mock_update_floatingip()
self.m.ReplayAll()
rsrc.validate()
@ -200,12 +205,8 @@ class NovaFloatingIPTest(common.HeatTestCase):
def test_floating_ip_assoc_delete(self):
rsrc = self.prepare_floating_ip_assoc()
self.novaclient.servers.add_floating_ip(None, '11.0.0.1')
self.novaclient.servers.get(
'67dc62f9-efde-4c8b-94af-013e00f5dc57').AndReturn('server')
self.novaclient.servers.remove_floating_ip('server', '11.0.0.1')
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
self.mock_update_floatingip()
self.mock_update_floatingip(delete_assc=True)
self.m.ReplayAll()
rsrc.validate()
@ -216,46 +217,43 @@ class NovaFloatingIPTest(common.HeatTestCase):
self.m.VerifyAll()
def create_delete_assoc_with_exc(self, exc_code):
rsrc = self.prepare_floating_ip_assoc()
self.novaclient.servers.add_floating_ip(None, '11.0.0.1')
self.novaclient.servers.get(
"67dc62f9-efde-4c8b-94af-013e00f5dc57").AndReturn("server")
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
self.novaclient.servers.remove_floating_ip("server",
"11.0.0.1").AndRaise(
fakes_nova.fake_exception(exc_code))
self.m.ReplayAll()
rsrc.validate()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_floating_ip_assoc_delete_conflict(self):
self.create_delete_assoc_with_exc(exc_code=409)
def test_floating_ip_assoc_delete_not_found(self):
self.create_delete_assoc_with_exc(exc_code=404)
rsrc = self.prepare_floating_ip_assoc()
self.mock_update_floatingip()
self.mock_update_floatingip(ex=fakes_nova.fake_exception(404),
delete_assc=True)
self.m.ReplayAll()
rsrc.validate()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
scheduler.TaskRunner(rsrc.delete)()
self.assertEqual((rsrc.DELETE, rsrc.COMPLETE), rsrc.state)
self.m.VerifyAll()
def test_floating_ip_assoc_update_server_id(self):
rsrc = self.prepare_floating_ip_assoc()
# for create
self.novaclient.servers.add_floating_ip(None, '11.0.0.1')
# for update
self.novaclient.servers.get(
'2146dfbf-ba77-4083-8e86-d052f671ece5').AndReturn('server')
self.novaclient.servers.add_floating_ip('server', '11.0.0.1')
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
self.mock_update_floatingip()
fip_request = {'floatingip': {
'fixed_ip_address': '4.5.6.7',
'port_id': 'bbbbb-bbbb-bbbb-bbbbbbbbb'}
}
self.mock_update_floatingip(fip_request=fip_request)
self.m.ReplayAll()
rsrc.validate()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
# for update
return_server = self.novaclient.servers.list()[2]
self.patchobject(self.novaclient.servers, 'get',
return_value=return_server)
iface = self.mock_interface('bbbbb-bbbb-bbbb-bbbbbbbbb',
'4.5.6.7')
self.patchobject(return_server, 'interface_list', return_value=[iface])
# update with the new server_id
props = copy.deepcopy(rsrc.properties.data)
update_server_id = '2146dfbf-ba77-4083-8e86-d052f671ece5'
@ -270,17 +268,11 @@ class NovaFloatingIPTest(common.HeatTestCase):
def test_floating_ip_assoc_update_fl_ip(self):
rsrc = self.prepare_floating_ip_assoc()
# for create
self.novaclient.servers.add_floating_ip(None, '11.0.0.1')
self.mock_update_floatingip()
# mock for delete the old association
self.novaclient.servers.get(
'67dc62f9-efde-4c8b-94af-013e00f5dc57').AndReturn('server')
self.novaclient.servers.remove_floating_ip('server', '11.0.0.1')
self.mock_update_floatingip(delete_assc=True)
# mock for new association
self.novaclient.servers.get(
'67dc62f9-efde-4c8b-94af-013e00f5dc57').AndReturn('server')
self.novaclient.servers.add_floating_ip('server', '11.0.0.2')
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
self.mock_show_floatingip('fc68ea2c-cccc-4b4f-bd82-94ec81110766')
self.mock_update_floatingip(fip='fc68ea2c-dddd-4b4f-bd82-94ec81110766')
self.m.ReplayAll()
rsrc.validate()
@ -288,7 +280,7 @@ class NovaFloatingIPTest(common.HeatTestCase):
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
# update with the new floatingip
props = copy.deepcopy(rsrc.properties.data)
props['floating_ip'] = 'fc68ea2c-cccc-4b4f-bd82-94ec81110766'
props['floating_ip'] = 'fc68ea2c-dddd-4b4f-bd82-94ec81110766'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()
@ -299,28 +291,33 @@ class NovaFloatingIPTest(common.HeatTestCase):
def test_floating_ip_assoc_update_both(self):
rsrc = self.prepare_floating_ip_assoc()
# for create
self.novaclient.servers.add_floating_ip(None, '11.0.0.1')
self.mock_update_floatingip()
# mock for delete the old association
self.novaclient.servers.get(
'67dc62f9-efde-4c8b-94af-013e00f5dc57').AndReturn('server')
self.novaclient.servers.remove_floating_ip('server', '11.0.0.1')
self.mock_update_floatingip(delete_assc=True)
# mock for new association
self.novaclient.servers.get(
'2146dfbf-ba77-4083-8e86-d052f671ece5').AndReturn('new_server')
self.novaclient.servers.add_floating_ip('new_server', '11.0.0.2')
self.mock_show_floatingip('fc68ea2c-b60b-4b4f-bd82-94ec81110766')
self.mock_show_floatingip('fc68ea2c-cccc-4b4f-bd82-94ec81110766')
fip_request = {'floatingip': {
'fixed_ip_address': '4.5.6.7',
'port_id': 'bbbbb-bbbb-bbbb-bbbbbbbbb'}
}
self.mock_update_floatingip(fip='fc68ea2c-dddd-4b4f-bd82-94ec81110766',
fip_request=fip_request)
self.m.ReplayAll()
rsrc.validate()
scheduler.TaskRunner(rsrc.create)()
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
# update with the new floatingip
# update with the new floatingip and server
return_server = self.novaclient.servers.list()[2]
self.patchobject(self.novaclient.servers, 'get',
return_value=return_server)
iface = self.mock_interface('bbbbb-bbbb-bbbb-bbbbbbbbb',
'4.5.6.7')
self.patchobject(return_server, 'interface_list', return_value=[iface])
props = copy.deepcopy(rsrc.properties.data)
update_server_id = '2146dfbf-ba77-4083-8e86-d052f671ece5'
props['server_id'] = update_server_id
props['floating_ip'] = 'fc68ea2c-cccc-4b4f-bd82-94ec81110766'
props['floating_ip'] = 'fc68ea2c-dddd-4b4f-bd82-94ec81110766'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()