Skip to content

Commit 6b44628

Browse files
committed
nova-net: Remove use of legacy 'FloatingIP' object
We want to get rid of the 'FloatingIP' object. Alas, that's easier said than done because there are still a few users of this. The 'get_floating_ip', 'get_floating_ip_by_address', and 'get_floating_ips_by_project' methods are examples. These are only called by the legacy 'os-floating-ips' API and the 'FloatingIP' object is simply used as an unnecessary container between the two. Convert things so the aforementioned API can handle mostly intact responses from neutron instead, eliminating this user of the 'FloatingIP' object. Change-Id: I77b1cfeab3c00c6c3d7743ba51e12414806b71d2 Signed-off-by: Stephen Finucane <[email protected]>
1 parent e10c612 commit 6b44628

File tree

9 files changed

+112
-402
lines changed

9 files changed

+112
-402
lines changed

nova/api/openstack/compute/floating_ip_pools.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@
1919
from nova.policies import floating_ip_pools as fip_policies
2020

2121

22-
def _translate_floating_ip_view(pool_name):
22+
def _translate_floating_ip_view(pool):
2323
return {
24-
'name': pool_name,
24+
'name': pool['name'] or pool['id'],
2525
}
2626

2727

2828
def _translate_floating_ip_pools_view(pools):
2929
return {
30-
'floating_ip_pools': [_translate_floating_ip_view(pool_name)
31-
for pool_name in pools]
30+
'floating_ip_pools': [_translate_floating_ip_view(pool)
31+
for pool in pools]
3232
}
3333

3434

nova/api/openstack/compute/floating_ips.py

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
from oslo_log import log as logging
1919
from oslo_utils import netutils
20-
from oslo_utils import uuidutils
2120
import webob
2221

2322
from nova.api.openstack.api_version_request \
@@ -37,45 +36,21 @@
3736

3837

3938
def _translate_floating_ip_view(floating_ip):
40-
result = {
41-
'id': floating_ip['id'],
42-
'ip': floating_ip['address'],
43-
'pool': floating_ip['pool'],
39+
instance_id = None
40+
if floating_ip['port_details']:
41+
instance_id = floating_ip['port_details']['device_id']
42+
43+
return {
44+
'floating_ip': {
45+
'id': floating_ip['id'],
46+
'ip': floating_ip['floating_ip_address'],
47+
'pool': floating_ip['network_details']['name'] or (
48+
floating_ip['network_details']['id']),
49+
'fixed_ip': floating_ip['fixed_ip_address'],
50+
'instance_id': instance_id,
51+
}
4452
}
4553

46-
# If fixed_ip is unset on floating_ip, then we can't get any of the next
47-
# stuff, so we'll just short-circuit
48-
if 'fixed_ip' not in floating_ip:
49-
result['fixed_ip'] = None
50-
result['instance_id'] = None
51-
return {'floating_ip': result}
52-
53-
# TODO(rlrossit): These look like dicts, but they're actually versioned
54-
# objects, so we need to do these contain checks because they will not be
55-
# caught by the exceptions below (it raises NotImplementedError and
56-
# OrphanedObjectError. This comment can probably be removed when
57-
# the dict syntax goes away.
58-
try:
59-
if 'address' in floating_ip['fixed_ip']:
60-
result['fixed_ip'] = floating_ip['fixed_ip']['address']
61-
else:
62-
result['fixed_ip'] = None
63-
except (TypeError, KeyError, AttributeError):
64-
result['fixed_ip'] = None
65-
try:
66-
if 'instance_uuid' in floating_ip['fixed_ip']:
67-
result['instance_id'] = floating_ip['fixed_ip']['instance_uuid']
68-
else:
69-
result['instance_id'] = None
70-
except (TypeError, KeyError, AttributeError):
71-
result['instance_id'] = None
72-
return {'floating_ip': result}
73-
74-
75-
def _translate_floating_ips_view(floating_ips):
76-
return {'floating_ips': [_translate_floating_ip_view(ip)['floating_ip']
77-
for ip in floating_ips]}
78-
7954

8055
def get_instance_by_floating_ip_addr(self, context, address):
8156
try:
@@ -136,7 +111,8 @@ def index(self, req):
136111

137112
floating_ips = self.network_api.get_floating_ips_by_project(context)
138113

139-
return _translate_floating_ips_view(floating_ips)
114+
return {'floating_ips': [_translate_floating_ip_view(ip)['floating_ip']
115+
for ip in floating_ips]}
140116

141117
@wsgi.Controller.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
142118
@wsgi.expected_errors((400, 403, 404))
@@ -185,7 +161,7 @@ def delete(self, req, id):
185161
except exception.InvalidID as e:
186162
raise webob.exc.HTTPBadRequest(explanation=e.format_message())
187163

188-
address = floating_ip['address']
164+
address = floating_ip['floating_ip_address']
189165

190166
# get the associated instance object (if any)
191167
instance = get_instance_by_floating_ip_addr(self, context, address)
@@ -311,11 +287,7 @@ def _remove_floating_ip(self, req, id, body):
311287
instance = get_instance_by_floating_ip_addr(self, context, address)
312288

313289
# disassociate if associated
314-
if (instance and
315-
floating_ip.get('fixed_ip_id') and
316-
(uuidutils.is_uuid_like(id) and
317-
[instance.uuid == id] or
318-
[instance.id == id])[0]):
290+
if instance and floating_ip['port_id'] and instance.uuid == id:
319291
try:
320292
disassociate_floating_ip(self, context, instance, address)
321293
except exception.FloatingIpNotAssociated:

nova/network/neutron.py

Lines changed: 53 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2578,27 +2578,6 @@ def get_fixed_ip_by_address(self, context, address):
25782578
raise exception.FixedIpAssociatedWithMultipleInstances(
25792579
address=address)
25802580

2581-
def _setup_net_dict(self, client, network_id):
2582-
if not network_id:
2583-
return {}
2584-
pool = client.show_network(network_id)['network']
2585-
return {pool['id']: pool}
2586-
2587-
def _setup_port_dict(self, context, client, port_id):
2588-
if not port_id:
2589-
return {}
2590-
port = self._show_port(context, port_id, neutron_client=client)
2591-
return {port['id']: port}
2592-
2593-
def _setup_pools_dict(self, client):
2594-
pools = self._get_floating_ip_pools(client)
2595-
return {i['id']: i for i in pools}
2596-
2597-
def _setup_ports_dict(self, client, project_id=None):
2598-
search_opts = {'tenant_id': project_id} if project_id else {}
2599-
ports = client.list_ports(**search_opts)['ports']
2600-
return {p['id']: p for p in ports}
2601-
26022581
def get_floating_ip(self, context, id):
26032582
"""Return floating IP object given the floating IP id."""
26042583
client = get_client(context)
@@ -2607,72 +2586,64 @@ def get_floating_ip(self, context, id):
26072586
except neutron_client_exc.NeutronClientException as e:
26082587
if e.status_code == 404:
26092588
raise exception.FloatingIpNotFound(id=id)
2610-
else:
2611-
with excutils.save_and_reraise_exception():
2612-
LOG.exception('Unable to access floating IP %s', id)
2613-
pool_dict = self._setup_net_dict(client,
2614-
fip['floating_network_id'])
2615-
port_dict = self._setup_port_dict(context, client, fip['port_id'])
2616-
return self._make_floating_ip_obj(context, fip, pool_dict, port_dict)
2617-
2618-
def _get_floating_ip_pools(self, client, project_id=None):
2619-
search_opts = {constants.NET_EXTERNAL: True}
2620-
if project_id:
2621-
search_opts.update({'tenant_id': project_id})
2622-
data = client.list_networks(**search_opts)
2623-
return data['networks']
2589+
2590+
with excutils.save_and_reraise_exception():
2591+
LOG.exception('Unable to access floating IP %s', id)
2592+
2593+
# retrieve and cache the network details now since many callers need
2594+
# the network name which isn't present in the response from neutron
2595+
network_uuid = fip['floating_network_id']
2596+
try:
2597+
fip['network_details'] = client.show_network(
2598+
network_uuid)['network']
2599+
except neutron_client_exc.NetworkNotFoundClient:
2600+
raise exception.NetworkNotFound(network_id=network_uuid)
2601+
2602+
return fip
26242603

26252604
def get_floating_ip_pools(self, context):
2626-
"""Return floating IP pool names."""
2605+
"""Return floating IP pools a.k.a. external networks."""
26272606
client = get_client(context)
2628-
pools = self._get_floating_ip_pools(client)
2629-
return [n['name'] or n['id'] for n in pools]
2630-
2631-
def _make_floating_ip_obj(self, context, fip, pool_dict, port_dict):
2632-
pool = pool_dict[fip['floating_network_id']]
2633-
# NOTE(danms): Don't give these objects a context, since they're
2634-
# not lazy-loadable anyway
2635-
floating = objects.floating_ip.NeutronFloatingIP(
2636-
id=fip['id'], address=fip['floating_ip_address'],
2637-
pool=(pool['name'] or pool['id']), project_id=fip['tenant_id'],
2638-
fixed_ip_id=fip['port_id'])
2639-
# In Neutron v2 API fixed_ip_address and instance uuid
2640-
# (= device_id) are known here, so pass it as a result.
2641-
if fip['fixed_ip_address']:
2642-
floating.fixed_ip = objects.FixedIP(
2643-
address=fip['fixed_ip_address'])
2644-
else:
2645-
floating.fixed_ip = None
2646-
if fip['port_id']:
2647-
instance_uuid = port_dict[fip['port_id']]['device_id']
2648-
# NOTE(danms): This could be .refresh()d, so give it context
2649-
floating.instance = objects.Instance(context=context,
2650-
uuid=instance_uuid)
2651-
if floating.fixed_ip:
2652-
floating.fixed_ip.instance_uuid = instance_uuid
2653-
else:
2654-
floating.instance = None
2655-
return floating
2607+
data = client.list_networks(**{constants.NET_EXTERNAL: True})
2608+
return data['networks']
26562609

26572610
def get_floating_ip_by_address(self, context, address):
26582611
"""Return a floating IP given an address."""
26592612
client = get_client(context)
26602613
fip = self._get_floating_ip_by_address(client, address)
2661-
pool_dict = self._setup_net_dict(client,
2662-
fip['floating_network_id'])
2663-
port_dict = self._setup_port_dict(context, client, fip['port_id'])
2664-
return self._make_floating_ip_obj(context, fip, pool_dict, port_dict)
2614+
2615+
# retrieve and cache the network details now since many callers need
2616+
# the network name which isn't present in the response from neutron
2617+
network_uuid = fip['floating_network_id']
2618+
try:
2619+
fip['network_details'] = client.show_network(
2620+
network_uuid)['network']
2621+
except neutron_client_exc.NetworkNotFoundClient:
2622+
raise exception.NetworkNotFound(network_id=network_uuid)
2623+
2624+
return fip
26652625

26662626
def get_floating_ips_by_project(self, context):
26672627
client = get_client(context)
26682628
project_id = context.project_id
26692629
fips = self._safe_get_floating_ips(client, tenant_id=project_id)
2670-
if not fips:
2671-
return []
2672-
pool_dict = self._setup_pools_dict(client)
2673-
port_dict = self._setup_ports_dict(client, project_id)
2674-
return [self._make_floating_ip_obj(context, fip, pool_dict, port_dict)
2675-
for fip in fips]
2630+
2631+
# retrieve and cache the network details now since many callers need
2632+
# the network name which isn't present in the response from neutron
2633+
networks = {}
2634+
for fip in fips:
2635+
network_uuid = fip['floating_network_id']
2636+
if network_uuid not in networks:
2637+
try:
2638+
network = client.show_network(network_uuid)['network']
2639+
except neutron_client_exc.NetworkNotFoundClient:
2640+
raise exception.NetworkNotFound(network_id=network_uuid)
2641+
2642+
networks[network['id']] = network
2643+
2644+
fip['network_details'] = networks[network_uuid]
2645+
2646+
return fips
26762647

26772648
def get_instance_id_by_floating_address(self, context, address):
26782649
"""Return the instance id a floating IP's fixed IP is allocated to."""
@@ -2787,7 +2758,7 @@ def release_floating_ip(self, context, address,
27872758
self._release_floating_ip(context, address)
27882759

27892760
def disassociate_and_release_floating_ip(self, context, instance,
2790-
floating_ip):
2761+
floating_ip):
27912762
"""Removes (deallocates) and deletes the floating IP.
27922763
27932764
This api call was added to allow this to be done in one operation
@@ -2797,14 +2768,17 @@ def disassociate_and_release_floating_ip(self, context, instance,
27972768
@refresh_cache
27982769
def _release_floating_ip_and_refresh_cache(self, context, instance,
27992770
floating_ip):
2800-
self._release_floating_ip(context, floating_ip['address'],
2801-
raise_if_associated=False)
2771+
self._release_floating_ip(
2772+
context, floating_ip['floating_ip_address'],
2773+
raise_if_associated=False)
2774+
28022775
if instance:
28032776
_release_floating_ip_and_refresh_cache(self, context, instance,
28042777
floating_ip)
28052778
else:
2806-
self._release_floating_ip(context, floating_ip['address'],
2807-
raise_if_associated=False)
2779+
self._release_floating_ip(
2780+
context, floating_ip['floating_ip_address'],
2781+
raise_if_associated=False)
28082782

28092783
def _release_floating_ip(self, context, address,
28102784
raise_if_associated=True):

nova/tests/functional/api_sample_tests/test_floating_ip_pools.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ class FloatingIPPoolsSampleTests(api_sample_base.ApiSampleTestBaseV21):
1919
sample_dir = "os-floating-ip-pools"
2020

2121
def test_list_floatingippools(self):
22-
pool_list = ["pool1", "pool2"]
22+
pool_list = [
23+
{'name': 'pool1'},
24+
{'name': 'pool2'},
25+
]
2326

2427
def fake_get_floating_ip_pools(self, context):
2528
return pool_list
@@ -28,7 +31,7 @@ def fake_get_floating_ip_pools(self, context):
2831
fake_get_floating_ip_pools)
2932
response = self._do_get('os-floating-ip-pools')
3033
subs = {
31-
'pool1': pool_list[0],
32-
'pool2': pool_list[1]
34+
'pool1': pool_list[0]['name'],
35+
'pool2': pool_list[1]['name'],
3336
}
3437
self._verify_response('floatingippools-list-resp', subs, response, 200)

nova/tests/functional/api_sample_tests/test_servers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ def test_server_remove_floating_ip(self):
785785
self.stub_out(
786786
'nova.network.neutron.API.get_floating_ip_by_address',
787787
lambda *a, **k: {
788-
'fixed_ip_id': 'a0c566f0-faab-406f-b77f-2b286dc6dd7e'})
788+
'port_id': 'a0c566f0-faab-406f-b77f-2b286dc6dd7e'})
789789
self.stub_out(
790790
'nova.network.neutron.API.'
791791
'get_instance_id_by_floating_address',

nova/tests/unit/api/openstack/compute/test_floating_ip_pools.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424

2525

2626
def fake_get_floating_ip_pools(*args, **kwargs):
27-
return ['nova', 'other']
27+
return [
28+
{'name': 'nova'},
29+
{'name': 'other'},
30+
]
2831

2932

3033
class FloatingIpPoolTestV21(test.NoDBTestCase):
@@ -42,9 +45,9 @@ def test_translate_floating_ip_pools_view(self):
4245
view = self.floating_ip_pools._translate_floating_ip_pools_view(pools)
4346
self.assertIn('floating_ip_pools', view)
4447
self.assertEqual(view['floating_ip_pools'][0]['name'],
45-
pools[0])
48+
pools[0]['name'])
4649
self.assertEqual(view['floating_ip_pools'][1]['name'],
47-
pools[1])
50+
pools[1]['name'])
4851

4952
def test_floating_ips_pools_list(self):
5053
with mock.patch.object(self.controller.network_api,
@@ -53,8 +56,10 @@ def test_floating_ips_pools_list(self):
5356
res_dict = self.controller.index(self.req)
5457

5558
pools = fake_get_floating_ip_pools(None, self.context)
56-
response = {'floating_ip_pools': [{'name': name} for name in pools]}
57-
self.assertEqual(res_dict, response)
59+
response = {
60+
'floating_ip_pools': [{'name': pool['name']} for pool in pools],
61+
}
62+
self.assertEqual(response, res_dict)
5863

5964

6065
class FloatingIPPoolsPolicyEnforcementV21(test.NoDBTestCase):

0 commit comments

Comments
 (0)