diff options
Diffstat (limited to 'nova')
6 files changed, 292 insertions, 34 deletions
diff --git a/nova/api/openstack/compute/plugins/v3/fixed_ips.py b/nova/api/openstack/compute/plugins/v3/fixed_ips.py new file mode 100644 index 0000000000..ad795ab719 --- /dev/null +++ b/nova/api/openstack/compute/plugins/v3/fixed_ips.py @@ -0,0 +1,106 @@ +# Copyright 2012 IBM Corp. +# +# 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 +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import webob +import webob.exc + +from nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova import exception +from nova.i18n import _ +from nova import objects + +ALIAS = 'os-fixed-ips' +authorize = extensions.extension_authorizer('compute', 'v3:' + ALIAS) + + +class FixedIPController(wsgi.Controller): + @extensions.expected_errors((400, 404)) + def show(self, req, id): + """Return data about the given fixed ip.""" + context = req.environ['nova.context'] + authorize(context) + + attrs = ['network', 'instance'] + try: + fixed_ip = objects.FixedIP.get_by_address(context, id, + expected_attrs=attrs) + except exception.FixedIpNotFoundForAddress as ex: + raise webob.exc.HTTPNotFound(explanation=ex.format_message()) + except exception.FixedIpInvalid as ex: + raise webob.exc.HTTPBadRequest(explanation=ex.format_message()) + + fixed_ip_info = {"fixed_ip": {}} + if fixed_ip is None: + msg = _("Fixed IP %s has been deleted") % id + raise webob.exc.HTTPNotFound(explanation=msg) + + fixed_ip_info['fixed_ip']['cidr'] = str(fixed_ip.network.cidr) + fixed_ip_info['fixed_ip']['address'] = str(fixed_ip.address) + + if fixed_ip.instance: + fixed_ip_info['fixed_ip']['hostname'] = fixed_ip.instance.hostname + fixed_ip_info['fixed_ip']['host'] = fixed_ip.instance.host + else: + fixed_ip_info['fixed_ip']['hostname'] = None + fixed_ip_info['fixed_ip']['host'] = None + + return fixed_ip_info + + @wsgi.response(202) + @extensions.expected_errors((400, 404)) + @wsgi.action('reserve') + def reserve(self, req, id, body): + context = req.environ['nova.context'] + authorize(context) + + return self._set_reserved(context, id, True) + + @wsgi.response(202) + @extensions.expected_errors((400, 404)) + @wsgi.action('unreserve') + def unreserve(self, req, id, body): + context = req.environ['nova.context'] + authorize(context) + return self._set_reserved(context, id, False) + + def _set_reserved(self, context, address, reserved): + try: + fixed_ip = objects.FixedIP.get_by_address(context, address) + fixed_ip.reserved = reserved + fixed_ip.save() + except exception.FixedIpNotFoundForAddress: + msg = _("Fixed IP %s not found") % address + raise webob.exc.HTTPNotFound(explanation=msg) + except exception.FixedIpInvalid: + msg = _("Fixed IP %s not valid") % address + raise webob.exc.HTTPBadRequest(explanation=msg) + + +class FixedIps(extensions.V3APIExtensionBase): + """Fixed IPs support.""" + + name = "FixedIPs" + alias = ALIAS + version = 1 + + def get_resources(self): + member_actions = {'action': 'POST'} + resources = extensions.ResourceExtension(ALIAS, + FixedIPController(), + member_actions=member_actions) + return [resources] + + def get_controller_extensions(self): + return [] diff --git a/nova/tests/api/openstack/compute/contrib/test_fixed_ips.py b/nova/tests/api/openstack/compute/contrib/test_fixed_ips.py index 1d6bac494d..9e97c294b3 100644 --- a/nova/tests/api/openstack/compute/contrib/test_fixed_ips.py +++ b/nova/tests/api/openstack/compute/contrib/test_fixed_ips.py @@ -14,7 +14,8 @@ import webob -from nova.api.openstack.compute.contrib import fixed_ips +from nova.api.openstack.compute.contrib import fixed_ips as fixed_ips_v2 +from nova.api.openstack.compute.plugins.v3 import fixed_ips as fixed_ips_v21 from nova import context from nova import db from nova import exception @@ -124,10 +125,13 @@ def fake_network_get_all(context): return [FakeModel(network)] -class FixedIpTest(test.NoDBTestCase): +class FixedIpTestV21(test.NoDBTestCase): + + fixed_ips = fixed_ips_v21 + url = '/v2/fake/os-fixed-ips' def setUp(self): - super(FixedIpTest, self).setUp() + super(FixedIpTestV21, self).setUp() self.stubs.Set(db, "fixed_ip_get_by_address", fake_fixed_ip_get_by_address) @@ -136,10 +140,19 @@ class FixedIpTest(test.NoDBTestCase): self.stubs.Set(db, "fixed_ip_update", fake_fixed_ip_update) self.context = context.get_admin_context() - self.controller = fixed_ips.FixedIPController() + self.controller = self.fixed_ips.FixedIPController() + + def _assert_equal(self, ret, exp): + self.assertEqual(ret.wsgi_code, exp) + + def _get_reserve_action(self): + return self.controller.reserve + + def _get_unreserve_action(self): + return self.controller.unreserve def test_fixed_ips_get(self): - req = fakes.HTTPRequest.blank('/v2/fake/os-fixed-ips/192.168.1.1') + req = fakes.HTTPRequest.blank('%s/192.168.1.1' % self.url) res_dict = self.controller.show(req, '192.168.1.1') response = {'fixed_ip': {'cidr': '192.168.1.0/24', 'hostname': None, @@ -148,78 +161,96 @@ class FixedIpTest(test.NoDBTestCase): self.assertEqual(response, res_dict) def test_fixed_ips_get_bad_ip_fail(self): - req = fakes.HTTPRequest.blank('/v2/fake/os-fixed-ips/10.0.0.1') + req = fakes.HTTPRequest.blank('%s/10.0.0.1' % self.url) self.assertRaises(webob.exc.HTTPNotFound, self.controller.show, req, '10.0.0.1') def test_fixed_ips_get_invalid_ip_address(self): - req = fakes.HTTPRequest.blank('/v2/fake/os-fixed-ips/inv.ali.d.ip') + req = fakes.HTTPRequest.blank('%s/inv.ali.d.ip' % self.url) self.assertRaises(webob.exc.HTTPBadRequest, self.controller.show, req, 'inv.ali.d.ip') def test_fixed_ips_get_deleted_ip_fail(self): - req = fakes.HTTPRequest.blank('/v2/fake/os-fixed-ips/10.0.0.2') + req = fakes.HTTPRequest.blank('%s/10.0.0.2' % self.url) self.assertRaises(webob.exc.HTTPNotFound, self.controller.show, req, '10.0.0.2') def test_fixed_ip_reserve(self): fake_fixed_ips[0]['reserved'] = False body = {'reserve': None} - req = fakes.HTTPRequest.blank( - '/v2/fake/os-fixed-ips/192.168.1.1/action') - result = self.controller.action(req, "192.168.1.1", body) + req = fakes.HTTPRequest.blank('%s/192.168.1.1/action' % self.url) + action = self._get_reserve_action() + result = action(req, "192.168.1.1", body) - self.assertEqual('202 Accepted', result.status) + self._assert_equal(result or action, 202) self.assertEqual(fake_fixed_ips[0]['reserved'], True) def test_fixed_ip_reserve_bad_ip(self): body = {'reserve': None} - req = fakes.HTTPRequest.blank( - '/v2/fake/os-fixed-ips/10.0.0.1/action') - self.assertRaises(webob.exc.HTTPNotFound, self.controller.action, req, + req = fakes.HTTPRequest.blank('%s/10.0.0.1/action' % self.url) + action = self._get_reserve_action() + + self.assertRaises(webob.exc.HTTPNotFound, action, req, '10.0.0.1', body) def test_fixed_ip_reserve_invalid_ip_address(self): body = {'reserve': None} - req = fakes.HTTPRequest.blank( - '/v2/fake/os-fixed-ips/inv.ali.d.ip/action') + req = fakes.HTTPRequest.blank('%s/inv.ali.d.ip/action' % self.url) + action = self._get_reserve_action() + self.assertRaises(webob.exc.HTTPBadRequest, - self.controller.action, req, 'inv.ali.d.ip', body) + action, req, 'inv.ali.d.ip', body) def test_fixed_ip_reserve_deleted_ip(self): body = {'reserve': None} - req = fakes.HTTPRequest.blank( - '/v2/fake/os-fixed-ips/10.0.0.2/action') - self.assertRaises(webob.exc.HTTPNotFound, self.controller.action, req, + action = self._get_reserve_action() + + req = fakes.HTTPRequest.blank('%s/10.0.0.2/action' % self.url) + self.assertRaises(webob.exc.HTTPNotFound, action, req, '10.0.0.2', body) def test_fixed_ip_unreserve(self): fake_fixed_ips[0]['reserved'] = True body = {'unreserve': None} - req = fakes.HTTPRequest.blank( - '/v2/fake/os-fixed-ips/192.168.1.1/action') - result = self.controller.action(req, "192.168.1.1", body) + req = fakes.HTTPRequest.blank('%s/192.168.1.1/action' % self.url) + action = self._get_unreserve_action() + result = action(req, "192.168.1.1", body) - self.assertEqual('202 Accepted', result.status) + self._assert_equal(result or action, 202) self.assertEqual(fake_fixed_ips[0]['reserved'], False) def test_fixed_ip_unreserve_bad_ip(self): body = {'unreserve': None} - req = fakes.HTTPRequest.blank( - '/v2/fake/os-fixed-ips/10.0.0.1/action') - self.assertRaises(webob.exc.HTTPNotFound, self.controller.action, req, + req = fakes.HTTPRequest.blank('%s/10.0.0.1/action' % self.url) + action = self._get_unreserve_action() + + self.assertRaises(webob.exc.HTTPNotFound, action, req, '10.0.0.1', body) def test_fixed_ip_unreserve_invalid_ip_address(self): body = {'unreserve': None} - req = fakes.HTTPRequest.blank( - '/v2/fake/os-fixed-ips/inv.ali.d.ip/action') + req = fakes.HTTPRequest.blank('%s/inv.ali.d.ip/action' % self.url) + action = self._get_unreserve_action() self.assertRaises(webob.exc.HTTPBadRequest, - self.controller.action, req, 'inv.ali.d.ip', body) + action, req, 'inv.ali.d.ip', body) def test_fixed_ip_unreserve_deleted_ip(self): body = {'unreserve': None} - req = fakes.HTTPRequest.blank( - '/v2/fake/os-fixed-ips/10.0.0.2/action') - self.assertRaises(webob.exc.HTTPNotFound, self.controller.action, req, + req = fakes.HTTPRequest.blank('%s/10.0.0.2/action' % self.url) + action = self._get_unreserve_action() + self.assertRaises(webob.exc.HTTPNotFound, action, req, '10.0.0.2', body) + + +class FixedIpTestV2(FixedIpTestV21): + + fixed_ips = fixed_ips_v2 + + def _assert_equal(self, ret, exp): + self.assertEqual(ret.status, '202 Accepted') + + def _get_reserve_action(self): + return self.controller.action + + def _get_unreserve_action(self): + return self.controller.action diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py index d2cd13fcdb..bb1ad52231 100644 --- a/nova/tests/fake_policy.py +++ b/nova/tests/fake_policy.py @@ -185,6 +185,7 @@ policy_data = """ "compute_extension:v3:os-extended-volumes:detach": "", "compute_extension:v3:extensions:discoverable": "", "compute_extension:fixed_ips": "", + "compute_extension:v3:os-fixed-ips": "", "compute_extension:flavor_access": "", "compute_extension:flavor_access:addTenantAccess": "rule:admin_api", "compute_extension:flavor_access:removeTenantAccess": "rule:admin_api", diff --git a/nova/tests/integrated/v3/api_samples/os-fixed-ips/fixedip-post-req.json.tpl b/nova/tests/integrated/v3/api_samples/os-fixed-ips/fixedip-post-req.json.tpl new file mode 100644 index 0000000000..85ae4890ad --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-fixed-ips/fixedip-post-req.json.tpl @@ -0,0 +1,3 @@ +{ + "reserve": "%(reserve)s" +} diff --git a/nova/tests/integrated/v3/api_samples/os-fixed-ips/fixedips-get-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-fixed-ips/fixedips-get-resp.json.tpl new file mode 100644 index 0000000000..a3d11475bf --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-fixed-ips/fixedips-get-resp.json.tpl @@ -0,0 +1,8 @@ +{ + "fixed_ip": { + "cidr": "%(cidr)s", + "hostname": "%(hostname)s", + "host": "%(host)s", + "address": "%(address)s" + } +} diff --git a/nova/tests/integrated/v3/test_fixed_ips.py b/nova/tests/integrated/v3/test_fixed_ips.py new file mode 100644 index 0000000000..347aacfbc3 --- /dev/null +++ b/nova/tests/integrated/v3/test_fixed_ips.py @@ -0,0 +1,109 @@ +# Copyright 2014 IBM Corp. +# +# 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 +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from nova import db +from nova import exception +from nova.tests.integrated.v3 import test_servers +from nova.tests.objects import test_network +from nova.tests import utils as test_utils + + +class FixedIpTest(test_servers.ServersSampleBase): + extension_name = "os-fixed-ips" + + def setUp(self): + super(FixedIpTest, self).setUp() + + instance = dict(test_utils.get_test_instance(), + hostname='openstack', host='host') + fake_fixed_ips = [{'id': 1, + 'address': '192.168.1.1', + 'network_id': 1, + 'virtual_interface_id': 1, + 'instance_uuid': '1', + 'allocated': False, + 'leased': False, + 'reserved': False, + 'created_at': None, + 'deleted_at': None, + 'updated_at': None, + 'deleted': None, + 'instance': instance, + 'network': test_network.fake_network, + 'host': None}, + {'id': 2, + 'address': '192.168.1.2', + 'network_id': 1, + 'virtual_interface_id': 2, + 'instance_uuid': '2', + 'allocated': False, + 'leased': False, + 'reserved': False, + 'created_at': None, + 'deleted_at': None, + 'updated_at': None, + 'deleted': None, + 'instance': instance, + 'network': test_network.fake_network, + 'host': None}, + ] + + def fake_fixed_ip_get_by_address(context, address, + columns_to_join=None): + for fixed_ip in fake_fixed_ips: + if fixed_ip['address'] == address: + return fixed_ip + raise exception.FixedIpNotFoundForAddress(address=address) + + def fake_fixed_ip_get_by_address_detailed(context, address): + network = {'id': 1, + 'cidr': "192.168.1.0/24"} + host = {'host': "host", + 'hostname': 'openstack'} + for fixed_ip in fake_fixed_ips: + if fixed_ip['address'] == address: + return (fixed_ip, network, host) + raise exception.FixedIpNotFoundForAddress(address=address) + + def fake_fixed_ip_update(context, address, values): + fixed_ip = fake_fixed_ip_get_by_address(context, address) + if fixed_ip is None: + raise exception.FixedIpNotFoundForAddress(address=address) + else: + for key in values: + fixed_ip[key] = values[key] + + self.stubs.Set(db, "fixed_ip_get_by_address", + fake_fixed_ip_get_by_address) + self.stubs.Set(db, "fixed_ip_get_by_address_detailed", + fake_fixed_ip_get_by_address_detailed) + self.stubs.Set(db, "fixed_ip_update", fake_fixed_ip_update) + + def test_fixed_ip_reserve(self): + # Reserve a Fixed IP. + project = {'reserve': None} + response = self._do_post('os-fixed-ips/192.168.1.1/action', + 'fixedip-post-req', + project) + self.assertEqual(response.status_code, 202) + self.assertEqual(response.content, "") + + def test_get_fixed_ip(self): + # Return data about the given fixed ip. + response = self._do_get('os-fixed-ips/192.168.1.1') + project = {'cidr': '192.168.1.0/24', + 'hostname': 'openstack', + 'host': 'host', + 'address': '192.168.1.1'} + self._verify_response('fixedips-get-resp', project, response, 200) |