summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-01-17 08:15:48 +0000
committerGerrit Code Review <review@openstack.org>2012-01-17 08:15:48 +0000
commit2dd52511cf8b7b9e5c7c7cd8564b0fec8acd03cb (patch)
tree728474d02ca657ce7cd50d5a8bcacf91f7a6f51e /nova
parent3972390d286ba487a53a27fa59a6cc1b0e2573ba (diff)
parent918d9998e1855879e35b039430b71277e3200814 (diff)
downloadnova-2dd52511cf8b7b9e5c7c7cd8564b0fec8acd03cb.tar.gz
nova-2dd52511cf8b7b9e5c7c7cd8564b0fec8acd03cb.tar.xz
nova-2dd52511cf8b7b9e5c7c7cd8564b0fec8acd03cb.zip
Merge "Add ipv4 and ipv6 validation"
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/compute/servers.py35
-rw-r--r--nova/tests/api/openstack/compute/test_servers.py164
2 files changed, 197 insertions, 2 deletions
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index 3a0cc3683..274589696 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -16,6 +16,7 @@
import base64
import os
+import socket
from xml.dom import minidom
from webob import exc
@@ -568,6 +569,20 @@ class Controller(wsgi.Controller):
expl = _('Userdata content cannot be decoded')
raise exc.HTTPBadRequest(explanation=expl)
+ def _validate_access_ipv4(self, address):
+ try:
+ socket.inet_aton(address)
+ except socket.error:
+ expl = _('accessIPv4 is not proper IPv4 format')
+ raise exc.HTTPBadRequest(explanation=expl)
+
+ def _validate_access_ipv6(self, address):
+ try:
+ socket.inet_pton(socket.AF_INET6, address)
+ except socket.error:
+ expl = _('accessIPv4 is not proper IPv4 format')
+ raise exc.HTTPBadRequest(explanation=expl)
+
@wsgi.serializers(xml=ServerTemplate)
@exception.novaclient_converter
@scheduler_api.redirect_handler
@@ -634,6 +649,14 @@ class Controller(wsgi.Controller):
requested_networks = self._get_requested_networks(
requested_networks)
+ (access_ip_v4, ) = server_dict.get('accessIPv4'),
+ if access_ip_v4 is not None:
+ self._validate_access_ipv4(access_ip_v4)
+
+ (access_ip_v6, ) = server_dict.get('accessIPv6'),
+ if access_ip_v6 is not None:
+ self._validate_access_ipv6(access_ip_v6)
+
try:
flavor_id = self._flavor_id_from_req_data(body)
except ValueError as error:
@@ -687,8 +710,8 @@ class Controller(wsgi.Controller):
display_description=name,
key_name=key_name,
metadata=server_dict.get('metadata', {}),
- access_ip_v4=server_dict.get('accessIPv4'),
- access_ip_v6=server_dict.get('accessIPv6'),
+ access_ip_v4=access_ip_v4,
+ access_ip_v6=access_ip_v6,
injected_files=injected_files,
admin_password=password,
zone_blob=zone_blob,
@@ -767,10 +790,12 @@ class Controller(wsgi.Controller):
if 'accessIPv4' in body['server']:
access_ipv4 = body['server']['accessIPv4']
+ self._validate_access_ipv4(access_ipv4)
update_dict['access_ip_v4'] = access_ipv4.strip()
if 'accessIPv6' in body['server']:
access_ipv6 = body['server']['accessIPv6']
+ self._validate_access_ipv6(access_ipv6)
update_dict['access_ip_v6'] = access_ipv6.strip()
if 'auto_disk_config' in body['server']:
@@ -1008,6 +1033,12 @@ class Controller(wsgi.Controller):
'metadata': 'metadata',
}
+ if 'accessIPv4' in body:
+ self._validate_access_ipv4(body['accessIPv4'])
+
+ if 'accessIPv6' in body:
+ self._validate_access_ipv6(body['accessIPv6'])
+
kwargs = {}
for request_attribute, instance_attribute in attr_map.items():
diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py
index 80ac9baa6..0cc8a7706 100644
--- a/nova/tests/api/openstack/compute/test_servers.py
+++ b/nova/tests/api/openstack/compute/test_servers.py
@@ -1169,6 +1169,17 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res_dict['server']['id'], FAKE_UUID)
self.assertEqual(res_dict['server']['accessIPv4'], '0.0.0.0')
+ def test_update_server_access_ipv4_bad_format(self):
+ self.stubs.Set(nova.db, 'instance_get',
+ return_server_with_attributes(access_ipv4='0.0.0.0'))
+ req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req.method = 'PUT'
+ req.content_type = 'application/json'
+ body = {'server': {'accessIPv4': 'bad_format'}}
+ req.body = json.dumps(body)
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+ req, FAKE_UUID, body)
+
def test_update_server_access_ipv6(self):
self.stubs.Set(nova.db, 'instance_get',
return_server_with_attributes(access_ipv6='beef::0123'))
@@ -1182,6 +1193,17 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res_dict['server']['id'], FAKE_UUID)
self.assertEqual(res_dict['server']['accessIPv6'], 'beef::0123')
+ def test_update_server_access_ipv6_bad_format(self):
+ self.stubs.Set(nova.db, 'instance_get',
+ return_server_with_attributes(access_ipv6='beef::0123'))
+ req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req.method = 'PUT'
+ req.content_type = 'application/json'
+ body = {'server': {'accessIPv6': 'bad_format'}}
+ req.body = json.dumps(body)
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+ req, FAKE_UUID, body)
+
def test_update_server_adminPass_ignored(self):
inst_dict = dict(name='server_test', adminPass='bacon')
body = dict(server=inst_dict)
@@ -1206,6 +1228,80 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(res_dict['server']['id'], FAKE_UUID)
self.assertEqual(res_dict['server']['name'], 'server_test')
+ def test_rebuild_instance_with_access_ipv4_bad_format(self):
+
+ def fake_get_instance(*args, **kwargs):
+ return fakes.stub_instance(1, vm_state=vm_states.ACTIVE)
+
+ self.stubs.Set(nova.db, 'instance_get', fake_get_instance)
+ # proper local hrefs must start with 'http://localhost/v2/'
+ image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
+ image_href = 'http://localhost/v2/fake/images/%s' % image_uuid
+ access_ipv4 = 'bad_format'
+ access_ipv6 = 'fead::1234'
+ body = {
+ 'rebuild': {
+ 'name': 'new_name',
+ 'imageRef': image_href,
+ 'accessIPv4': access_ipv4,
+ 'accessIPv6': access_ipv6,
+ 'metadata': {
+ 'hello': 'world',
+ 'open': 'stack',
+ },
+ 'personality': [
+ {
+ "path": "/etc/banner.txt",
+ "contents": "MQ==",
+ },
+ ],
+ },
+ }
+
+ req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller._action_rebuild, req, 1, body)
+
+ def test_rebuild_instance_with_access_ipv6_bad_format(self):
+
+ def fake_get_instance(*args, **kwargs):
+ return fakes.stub_instance(1, vm_state=vm_states.ACTIVE)
+
+ self.stubs.Set(nova.db, 'instance_get', fake_get_instance)
+ # proper local hrefs must start with 'http://localhost/v2/'
+ image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
+ image_href = 'http://localhost/v2/fake/images/%s' % image_uuid
+ access_ipv4 = '1.2.3.4'
+ access_ipv6 = 'bad_format'
+ body = {
+ 'rebuild': {
+ 'name': 'new_name',
+ 'imageRef': image_href,
+ 'accessIPv4': access_ipv4,
+ 'accessIPv6': access_ipv6,
+ 'metadata': {
+ 'hello': 'world',
+ 'open': 'stack',
+ },
+ 'personality': [
+ {
+ "path": "/etc/banner.txt",
+ "contents": "MQ==",
+ },
+ ],
+ },
+ }
+
+ req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ self.assertRaises(webob.exc.HTTPBadRequest,
+ self.controller._action_rebuild, req, 1, body)
+
def test_get_all_server_details(self):
expected_flavor = {
"id": "1",
@@ -1637,6 +1733,74 @@ class ServersControllerCreateTest(test.TestCase):
self.assertEqual(FLAGS.password_length, len(server['adminPass']))
self.assertEqual(FAKE_UUID, server['id'])
+ def test_create_instance_bad_format_access_ip_v4(self):
+ # proper local hrefs must start with 'http://localhost/v2/'
+ image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
+ image_href = 'http://localhost/v2/fake/images/%s' % image_uuid
+ flavor_ref = 'http://localhost/fake/flavors/3'
+ access_ipv4 = 'bad_format'
+ access_ipv6 = 'fead::1234'
+ body = {
+ 'server': {
+ 'name': 'server_test',
+ 'imageRef': image_href,
+ 'flavorRef': flavor_ref,
+ 'accessIPv4': access_ipv4,
+ 'accessIPv6': access_ipv6,
+ 'metadata': {
+ 'hello': 'world',
+ 'open': 'stack',
+ },
+ 'personality': [
+ {
+ "path": "/etc/banner.txt",
+ "contents": "MQ==",
+ },
+ ],
+ },
+ }
+
+ req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
+ req, body)
+
+ def test_create_instance_bad_format_access_ip_v6(self):
+ # proper local hrefs must start with 'http://localhost/v2/'
+ image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
+ image_href = 'http://localhost/v2/fake/images/%s' % image_uuid
+ flavor_ref = 'http://localhost/fake/flavors/3'
+ access_ipv4 = '1.2.3.4'
+ access_ipv6 = 'bad_format'
+ body = {
+ 'server': {
+ 'name': 'server_test',
+ 'imageRef': image_href,
+ 'flavorRef': flavor_ref,
+ 'accessIPv4': access_ipv4,
+ 'accessIPv6': access_ipv6,
+ 'metadata': {
+ 'hello': 'world',
+ 'open': 'stack',
+ },
+ 'personality': [
+ {
+ "path": "/etc/banner.txt",
+ "contents": "MQ==",
+ },
+ ],
+ },
+ }
+
+ req = fakes.HTTPRequest.blank('/v2/fake/servers')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
+ req, body)
+
def test_create_instance(self):
# proper local hrefs must start with 'http://localhost/v2/'
image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'