Allow admin user to get all tenant's floating IPs

When getting floatingips by Nova API, the results will be filtered
with the 'tenant_id'.
So, we can only get the floatingips belonging the tenant of current
context.
When ceilometer invokes novaclient to list floatingips, it will get an
empty list because the tenant is 'service'.
we should allow an admin user to index all tenants's floatingip by adding a
parameter 'all_tenants'.

Part1:
    part1 try to implement this and part2 will remove the unused codes.

Change-Id: I7ab1d5ff463fc29928f6811f846c9e204390a412
Closes-bug: #1262124
This commit is contained in:
liu-sheng 2014-03-19 11:44:22 +08:00
parent 693223e0d4
commit 6478554f53
9 changed files with 155 additions and 3 deletions

View File

@ -141,6 +141,7 @@
"compute_extension:floating_ip_dns": "",
"compute_extension:floating_ip_pools": "",
"compute_extension:floating_ips": "",
"compute_extension:floating_ips:all_tenants": "rule:admin_api",
"compute_extension:floating_ips_bulk": "rule:admin_api",
"compute_extension:fping": "",
"compute_extension:fping:all_tenants": "rule:admin_api",
@ -292,6 +293,7 @@
"network:get_backdoor_port": "",
"network:get_floating_ip": "",
"network:get_floating_ips": "",
"network:get_floating_ip_pools": "",
"network:get_floating_ip_by_address": "",
"network:get_floating_ips_by_project": "",

View File

@ -1212,7 +1212,7 @@ class CloudController(object):
address)
floatings.append(floating)
else:
floatings = self.network_api.get_floating_ips_by_project(context)
floatings = self.network_api.get_floating_ips(context)
addresses = [self._format_address(context, f) for f in floatings]
return {'addressesSet': addresses}

View File

@ -27,11 +27,14 @@ from nova import exception
from nova import network
from nova.openstack.common.gettextutils import _
from nova.openstack.common import log as logging
from nova.openstack.common import strutils
from nova.openstack.common import uuidutils
LOG = logging.getLogger(__name__)
authorize = extensions.extension_authorizer('compute', 'floating_ips')
authorize_all_tenants = extensions.extension_authorizer(
'compute', 'floating_ips:all_tenants')
def make_float_ip(elem):
@ -135,11 +138,19 @@ class FloatingIPController(object):
@wsgi.serializers(xml=FloatingIPsTemplate)
def index(self, req):
"""Return a list of floating ips allocated to a project."""
"""Return a list of floating ips."""
context = req.environ['nova.context']
authorize(context)
all_tenants = False
if 'all_tenants' in req.GET:
try:
if strutils.bool_from_string(req.GET['all_tenants'], True):
authorize_all_tenants(context)
all_tenants = True
except ValueError as err:
raise webob.exc.HTTPBadRequest(explanation=str(err))
floating_ips = self.network_api.get_floating_ips_by_project(context)
floating_ips = self.network_api.get_floating_ips(context, all_tenants)
for floating_ip in floating_ips:
self._normalize_ip(floating_ip)

View File

@ -128,6 +128,14 @@ class API(base_api.NetworkAPI):
return self.db.floating_ip_get_all_by_project(context,
context.project_id)
@wrap_check_policy
def get_floating_ips(self, context, all_tenants=False):
if all_tenants:
return self.db.floating_ip_get_all(context)
else:
return self.db.floating_ip_get_all_by_project(context,
context.project_id)
@wrap_check_policy
def get_floating_ips_by_fixed_address(self, context, fixed_address):
floating_ips = self.db.floating_ip_get_by_fixed_address(context,

View File

@ -877,6 +877,20 @@ class API(base_api.NetworkAPI):
return [self._format_floating_ip_model(fip, pool_dict, port_dict)
for fip in fips]
def get_floating_ips(self, context, all_tenants=False):
client = neutronv2.get_client(context)
project_id = context.project_id
if all_tenants:
fips = client.list_floatingips()['floatingips']
port_dict = self._setup_ports_dict(client)
else:
fips = client.list_floatingips(
tenant_id=project_id)['floatingips']
port_dict = self._setup_ports_dict(client, project_id)
pool_dict = self._setup_pools_dict(client)
return [self._format_floating_ip_model(fip, pool_dict, port_dict)
for fip in fips]
def get_floating_ips_by_fixed_address(self, context, fixed_address):
raise NotImplementedError()

View File

@ -42,6 +42,24 @@ def network_api_get_floating_ip(self, context, id):
'fixed_ip_id': None}
def network_api_get_floating_ips(self, context, all_tenants=False):
ret = [{'id': 1,
'address': '10.10.10.10',
'pool': 'nova',
'fixed_ip': {'address': '10.0.0.1',
'instance': {'uuid': FAKE_UUID}}},
{'id': 2,
'pool': 'nova', 'interface': 'eth0',
'address': '10.10.10.11',
'fixed_ip': None}]
if all_tenants:
ret.append({'id': 3,
'pool': 'nova', 'interface': 'eth1',
'address': '10.10.10.12',
'fixed_ip': None})
return ret
def network_api_get_floating_ip_by_address(self, context, address):
return {'id': 1, 'address': '10.10.10.10', 'pool': 'nova',
'fixed_ip_id': 10}
@ -132,6 +150,8 @@ class FloatingIpTest(test.TestCase):
compute_api_get)
self.stubs.Set(network.api.API, "get_floating_ip",
network_api_get_floating_ip)
self.stubs.Set(network.api.API, "get_floating_ips",
network_api_get_floating_ips)
self.stubs.Set(network.api.API, "get_floating_ip_by_address",
network_api_get_floating_ip_by_address)
self.stubs.Set(network.api.API, "get_floating_ips_by_project",
@ -202,6 +222,35 @@ class FloatingIpTest(test.TestCase):
'id': 2}]}
self.assertEqual(res_dict, response)
def test_floating_ips_list_all_tenants_admin(self):
req = fakes.HTTPRequest.blank(
'/v2/fake/os-floating-ips/?all_tenants=1',
use_admin_context=True)
res_dict = self.controller.index(req)
response = {'floating_ips': [{'instance_id': FAKE_UUID,
'ip': '10.10.10.10',
'pool': 'nova',
'fixed_ip': '10.0.0.1',
'id': 1},
{'instance_id': None,
'ip': '10.10.10.11',
'pool': 'nova',
'fixed_ip': None,
'id': 2},
{'instance_id': None,
'ip': '10.10.10.12',
'pool': 'nova',
'fixed_ip': None,
'id': 3}]}
self.assertEqual(response, res_dict)
def test_floating_ips_list_all_tenants_not_admin(self):
req = fakes.HTTPRequest.blank(
'/v2/fake/os-floating-ips/?all_tenants=1',
use_admin_context=False)
self.assertRaises(exception.Forbidden, self.controller.index, req)
def test_floating_ip_release_nonexisting(self):
def fake_get_floating_ip(*args, **kwargs):
raise exception.FloatingIpNotFound(id=id)
@ -625,6 +674,8 @@ class ExtendedFloatingIpTest(test.TestCase):
compute_api_get)
self.stubs.Set(network.api.API, "get_floating_ip",
network_api_get_floating_ip)
self.stubs.Set(network.api.API, "get_floating_ips",
network_api_get_floating_ips)
self.stubs.Set(network.api.API, "get_floating_ip_by_address",
network_api_get_floating_ip_by_address)
self.stubs.Set(network.api.API, "get_floating_ips_by_project",

View File

@ -199,6 +199,7 @@ policy_data = """
"compute_extension:floating_ip_dns": "",
"compute_extension:floating_ip_pools": "",
"compute_extension:floating_ips": "",
"compute_extension:floating_ips:all_tenants": "rule:admin_api",
"compute_extension:floating_ips_bulk": "",
"compute_extension:fping": "",
"compute_extension:fping:all_tenants": "is_admin:True",
@ -345,6 +346,7 @@ policy_data = """
"network:setup_networks_on_host": "",
"network:get_floating_ip": "",
"network:get_floating_ips": "",
"network:get_floating_ip_pools": "",
"network:get_floating_ip_by_address": "",
"network:get_floating_ips_by_project": "",

View File

@ -155,6 +155,24 @@ class ApiTestCase(test.TestCase):
def test_associate_unassociated_floating_ip(self):
self._do_test_associate_floating_ip(None)
def test_get_floating_ips(self):
self.mox.StubOutWithMock(self.network_api.db, 'floating_ip_get_all')
self.network_api.db.floating_ip_get_all(self.context).AndReturn(
['project1-floating-ip', 'project2-floating-ip'])
self.mox.StubOutWithMock(self.network_api.db,
'floating_ip_get_all_by_project')
self.network_api.db.\
floating_ip_get_all_by_project(self.context,
self.context.project_id).\
AndReturn(['project1-floating-ip'])
self.mox.ReplayAll()
floating_ips = self.network_api.get_floating_ips(self.context)
floating_ips_all = self.network_api.get_floating_ips(self.context,
all_tenants=True)
self.assertEqual(['project1-floating-ip'], floating_ips)
self.assertEqual(['project1-floating-ip', 'project2-floating-ip'],
floating_ips_all)
def test_get_floating_ip_invalid_id(self):
self.assertRaises(exception.InvalidID,
self.network_api.get_floating_ip,

View File

@ -268,6 +268,14 @@ class TestNeutronv2Base(test.TestCase):
'port_id': None,
'fixed_ip_address': None,
'router_id': None}
self.fip_unassociated_not_my = {'tenant_id': 'not_my_tenantid',
'id': 'fip_id3',
'floating_ip_address': '172.24.4.227',
'floating_network_id': self.fip_pool[
'id'],
'port_id': None,
'fixed_ip_address': None,
'router_id': None}
fixed_ip_address = self.port_data2[1]['fixed_ips'][0]['ip_address']
self.fip_associated = {'tenant_id': 'my_tenantid',
'id': 'fip_id2',
@ -1615,6 +1623,44 @@ class TestNeutronv2(TestNeutronv2Base):
fips = api.get_floating_ips_by_project(self.context)
self.assertEqual(expected, fips)
def test_get_floating_ips(self):
api = neutronapi.API()
project_id = self.context.project_id
self.moxed_client.list_floatingips(tenant_id=project_id).\
AndReturn({'floatingips': [self.fip_unassociated,
self.fip_associated]})
self.moxed_client.list_ports(tenant_id=project_id). \
AndReturn({'ports': self.port_data2})
search_opts = {'router:external': True}
self.moxed_client.list_networks(**search_opts). \
AndReturn({'networks': [self.fip_pool, self.fip_pool_nova]})
self.mox.ReplayAll()
expected = [self._get_expected_fip_model(self.fip_unassociated),
self._get_expected_fip_model(self.fip_associated, idx=1)]
fips = api.get_floating_ips(self.context)
self.assertEqual(expected, fips)
def test_get_floating_ips_all_tenants(self):
api = neutronapi.API()
self.moxed_client.list_floatingips(). \
AndReturn({'floatingips': [self.fip_unassociated,
self.fip_associated,
self.fip_unassociated_not_my]})
self.moxed_client.list_ports().AndReturn({'ports': self.port_data2})
search_opts = {'router:external': True}
self.moxed_client.list_networks(**search_opts). \
AndReturn({'networks': [self.fip_pool, self.fip_pool_nova]})
self.mox.ReplayAll()
expected = [self._get_expected_fip_model(self.fip_unassociated),
self._get_expected_fip_model(self.fip_associated, idx=1),
self._get_expected_fip_model(self.fip_unassociated_not_my,
idx=2)]
fips = api.get_floating_ips(self.context, all_tenants=True)
self.assertEqual(expected, fips)
def _test_get_instance_id_by_floating_address(self, fip_data,
associated=False):
api = neutronapi.API()