summaryrefslogtreecommitdiff
path: root/nova
diff options
context:
space:
mode:
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/compute/plugins/v3/fixed_ips.py106
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_fixed_ips.py99
-rw-r--r--nova/tests/fake_policy.py1
-rw-r--r--nova/tests/integrated/v3/api_samples/os-fixed-ips/fixedip-post-req.json.tpl3
-rw-r--r--nova/tests/integrated/v3/api_samples/os-fixed-ips/fixedips-get-resp.json.tpl8
-rw-r--r--nova/tests/integrated/v3/test_fixed_ips.py109
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)