summaryrefslogtreecommitdiffstats
path: root/nova/tests
diff options
context:
space:
mode:
Diffstat (limited to 'nova/tests')
-rw-r--r--nova/tests/api/openstack/test_images.py12
-rw-r--r--nova/tests/api/openstack/test_limits.py121
-rw-r--r--nova/tests/api/openstack/test_servers.py224
-rw-r--r--nova/tests/test_exception.py34
-rw-r--r--nova/tests/test_instance_types.py6
-rw-r--r--nova/tests/test_misc.py49
-rw-r--r--nova/tests/test_scheduler.py10
-rw-r--r--nova/tests/test_virt.py183
8 files changed, 558 insertions, 81 deletions
diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py
index ae86d0686..e5dd93c3f 100644
--- a/nova/tests/api/openstack/test_images.py
+++ b/nova/tests/api/openstack/test_images.py
@@ -538,7 +538,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
},
{
'id': 127,
- 'name': 'killed backup', 'serverId': 42,
+ 'name': 'killed backup',
+ 'serverId': 42,
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'FAILED',
@@ -584,7 +585,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
{
'id': 124,
'name': 'queued backup',
- 'serverId': 42,
+ 'serverRef': "http://localhost/v1.1/servers/42",
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'QUEUED',
@@ -606,7 +607,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
{
'id': 125,
'name': 'saving backup',
- 'serverId': 42,
+ 'serverRef': "http://localhost/v1.1/servers/42",
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'SAVING',
@@ -629,7 +630,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
{
'id': 126,
'name': 'active backup',
- 'serverId': 42,
+ 'serverRef': "http://localhost/v1.1/servers/42",
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'ACTIVE',
@@ -650,7 +651,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
},
{
'id': 127,
- 'name': 'killed backup', 'serverId': 42,
+ 'name': 'killed backup',
+ 'serverRef': "http://localhost/v1.1/servers/42",
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'FAILED',
diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py
index df367005d..45bd4d501 100644
--- a/nova/tests/api/openstack/test_limits.py
+++ b/nova/tests/api/openstack/test_limits.py
@@ -28,15 +28,14 @@ import webob
from xml.dom.minidom import parseString
from nova.api.openstack import limits
-from nova.api.openstack.limits import Limit
TEST_LIMITS = [
- Limit("GET", "/delayed", "^/delayed", 1, limits.PER_MINUTE),
- Limit("POST", "*", ".*", 7, limits.PER_MINUTE),
- Limit("POST", "/servers", "^/servers", 3, limits.PER_MINUTE),
- Limit("PUT", "*", "", 10, limits.PER_MINUTE),
- Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE),
+ limits.Limit("GET", "/delayed", "^/delayed", 1, limits.PER_MINUTE),
+ limits.Limit("POST", "*", ".*", 7, limits.PER_MINUTE),
+ limits.Limit("POST", "/servers", "^/servers", 3, limits.PER_MINUTE),
+ limits.Limit("PUT", "*", "", 10, limits.PER_MINUTE),
+ limits.Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE),
]
@@ -58,15 +57,15 @@ class BaseLimitTestSuite(unittest.TestCase):
return self.time
-class LimitsControllerTest(BaseLimitTestSuite):
+class LimitsControllerV10Test(BaseLimitTestSuite):
"""
- Tests for `limits.LimitsController` class.
+ Tests for `limits.LimitsControllerV10` class.
"""
def setUp(self):
"""Run before each test."""
BaseLimitTestSuite.setUp(self)
- self.controller = limits.LimitsController()
+ self.controller = limits.LimitsControllerV10()
def _get_index_request(self, accept_header="application/json"):
"""Helper to set routing arguments."""
@@ -81,8 +80,8 @@ class LimitsControllerTest(BaseLimitTestSuite):
def _populate_limits(self, request):
"""Put limit info into a request."""
_limits = [
- Limit("GET", "*", ".*", 10, 60).display(),
- Limit("POST", "*", ".*", 5, 60 * 60).display(),
+ limits.Limit("GET", "*", ".*", 10, 60).display(),
+ limits.Limit("POST", "*", ".*", 5, 60 * 60).display(),
]
request.environ["nova.limits"] = _limits
return request
@@ -171,6 +170,100 @@ class LimitsControllerTest(BaseLimitTestSuite):
self.assertEqual(expected.toxml(), body.toxml())
+class LimitsControllerV11Test(BaseLimitTestSuite):
+ """
+ Tests for `limits.LimitsControllerV11` class.
+ """
+
+ def setUp(self):
+ """Run before each test."""
+ BaseLimitTestSuite.setUp(self)
+ self.controller = limits.LimitsControllerV11()
+
+ def _get_index_request(self, accept_header="application/json"):
+ """Helper to set routing arguments."""
+ request = webob.Request.blank("/")
+ request.accept = accept_header
+ request.environ["wsgiorg.routing_args"] = (None, {
+ "action": "index",
+ "controller": "",
+ })
+ return request
+
+ def _populate_limits(self, request):
+ """Put limit info into a request."""
+ _limits = [
+ limits.Limit("GET", "*", ".*", 10, 60).display(),
+ limits.Limit("POST", "*", ".*", 5, 60 * 60).display(),
+ limits.Limit("GET", "changes-since*", "changes-since",
+ 5, 60).display(),
+ ]
+ request.environ["nova.limits"] = _limits
+ return request
+
+ def test_empty_index_json(self):
+ """Test getting empty limit details in JSON."""
+ request = self._get_index_request()
+ response = request.get_response(self.controller)
+ expected = {
+ "limits": {
+ "rate": [],
+ "absolute": {},
+ },
+ }
+ body = json.loads(response.body)
+ self.assertEqual(expected, body)
+
+ def test_index_json(self):
+ """Test getting limit details in JSON."""
+ request = self._get_index_request()
+ request = self._populate_limits(request)
+ response = request.get_response(self.controller)
+ expected = {
+ "limits": {
+ "rate": [
+ {
+ "regex": ".*",
+ "uri": "*",
+ "limit": [
+ {
+ "verb": "GET",
+ "next-available": 0,
+ "unit": "MINUTE",
+ "value": 10,
+ "remaining": 10,
+ },
+ {
+ "verb": "POST",
+ "next-available": 0,
+ "unit": "HOUR",
+ "value": 5,
+ "remaining": 5,
+ },
+ ],
+ },
+ {
+ "regex": "changes-since",
+ "uri": "changes-since*",
+ "limit": [
+ {
+ "verb": "GET",
+ "next-available": 0,
+ "unit": "MINUTE",
+ "value": 5,
+ "remaining": 5,
+ },
+ ],
+ },
+
+ ],
+ "absolute": {},
+ },
+ }
+ body = json.loads(response.body)
+ self.assertEqual(expected, body)
+
+
class LimitMiddlewareTest(BaseLimitTestSuite):
"""
Tests for the `limits.RateLimitingMiddleware` class.
@@ -185,7 +278,7 @@ class LimitMiddlewareTest(BaseLimitTestSuite):
"""Prepare middleware for use through fake WSGI app."""
BaseLimitTestSuite.setUp(self)
_limits = [
- Limit("GET", "*", ".*", 1, 60),
+ limits.Limit("GET", "*", ".*", 1, 60),
]
self.app = limits.RateLimitingMiddleware(self._empty_app, _limits)
@@ -238,7 +331,7 @@ class LimitTest(BaseLimitTestSuite):
def test_GET_no_delay(self):
"""Test a limit handles 1 GET per second."""
- limit = Limit("GET", "*", ".*", 1, 1)
+ limit = limits.Limit("GET", "*", ".*", 1, 1)
delay = limit("GET", "/anything")
self.assertEqual(None, delay)
self.assertEqual(0, limit.next_request)
@@ -246,7 +339,7 @@ class LimitTest(BaseLimitTestSuite):
def test_GET_delay(self):
"""Test two calls to 1 GET per second limit."""
- limit = Limit("GET", "*", ".*", 1, 1)
+ limit = limits.Limit("GET", "*", ".*", 1, 1)
delay = limit("GET", "/anything")
self.assertEqual(None, delay)
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index 556046e9d..5c643fcef 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -33,6 +33,7 @@ import nova.api.openstack
from nova.api.openstack import servers
import nova.compute.api
from nova.compute import instance_types
+from nova.compute import power_state
import nova.db.api
from nova.db.sqlalchemy.models import Instance
from nova.db.sqlalchemy.models import InstanceMetadata
@@ -56,6 +57,12 @@ def return_server_with_addresses(private, public):
return _return_server
+def return_server_with_power_state(power_state):
+ def _return_server(context, id):
+ return stub_instance(id, power_state=power_state)
+ return _return_server
+
+
def return_servers(context, user_id=1):
return [stub_instance(i, user_id) for i in xrange(5)]
@@ -73,7 +80,7 @@ def instance_address(context, instance_id):
def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
- host=None):
+ host=None, power_state=0):
metadata = []
metadata.append(InstanceMetadata(key='seq', value=id))
@@ -96,7 +103,7 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
"launch_index": 0,
"key_name": "",
"key_data": "",
- "state": 0,
+ "state": power_state,
"state_description": "",
"memory_mb": 0,
"vcpus": 0,
@@ -613,6 +620,33 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
+ def test_create_instance_v11_local_href(self):
+ self._setup_for_create_instance()
+
+ imageRef = 'http://localhost/v1.1/images/2'
+ imageRefLocal = '2'
+ flavorRef = 'http://localhost/v1.1/flavors/3'
+ body = {
+ 'server': {
+ 'name': 'server_test',
+ 'imageRef': imageRefLocal,
+ 'flavorRef': flavorRef,
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/servers')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+
+ res = req.get_response(fakes.wsgi_app())
+
+ server = json.loads(res.body)['server']
+ self.assertEqual(1, server['id'])
+ self.assertEqual(flavorRef, server['flavorRef'])
+ self.assertEqual(imageRef, server['imageRef'])
+ self.assertEqual(res.status_int, 200)
+
def test_create_instance_with_admin_pass_v10(self):
self._setup_for_create_instance()
@@ -1024,15 +1058,175 @@ class ServersTest(test.TestCase):
req.body = json.dumps(body)
res = req.get_response(fakes.wsgi_app())
- def test_server_rebuild(self):
- body = dict(server=dict(
- name='server_test', imageId=2, flavorId=2, metadata={},
- personality={}))
+ def test_server_rebuild_accepted(self):
+ body = {
+ "rebuild": {
+ "imageId": 2,
+ },
+ }
+
req = webob.Request.blank('/v1.0/servers/1/action')
req.method = 'POST'
req.content_type = 'application/json'
req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 202)
+ self.assertEqual(res.body, "")
+
+ def test_server_rebuild_rejected_when_building(self):
+ body = {
+ "rebuild": {
+ "imageId": 2,
+ },
+ }
+
+ state = power_state.BUILDING
+ new_return_server = return_server_with_power_state(state)
+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
+
+ req = webob.Request.blank('/v1.0/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 409)
+
+ def test_server_rebuild_bad_entity(self):
+ body = {
+ "rebuild": {
+ },
+ }
+
+ req = webob.Request.blank('/v1.0/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 400)
+
+ def test_server_rebuild_accepted_minimum_v11(self):
+ body = {
+ "rebuild": {
+ "imageRef": "http://localhost/images/2",
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 202)
+
+ def test_server_rebuild_rejected_when_building_v11(self):
+ body = {
+ "rebuild": {
+ "imageRef": "http://localhost/images/2",
+ },
+ }
+
+ state = power_state.BUILDING
+ new_return_server = return_server_with_power_state(state)
+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
+
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 409)
+
+ def test_server_rebuild_accepted_with_metadata_v11(self):
+ body = {
+ "rebuild": {
+ "imageRef": "http://localhost/images/2",
+ "metadata": {
+ "new": "metadata",
+ },
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 202)
+
+ def test_server_rebuild_accepted_with_bad_metadata_v11(self):
+ body = {
+ "rebuild": {
+ "imageRef": "http://localhost/images/2",
+ "metadata": "stack",
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 400)
+
+ def test_server_rebuild_bad_entity_v11(self):
+ body = {
+ "rebuild": {
+ "imageId": 2,
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 400)
+
+ def test_server_rebuild_bad_personality_v11(self):
+ body = {
+ "rebuild": {
+ "imageRef": "http://localhost/images/2",
+ "personality": [{
+ "path": "/path/to/file",
+ "contents": "INVALID b64",
+ }]
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 400)
+
+ def test_server_rebuild_personality_v11(self):
+ body = {
+ "rebuild": {
+ "imageRef": "http://localhost/images/2",
+ "personality": [{
+ "path": "/path/to/file",
+ "contents": base64.b64encode("Test String"),
+ }]
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 202)
def test_delete_server_instance(self):
req = webob.Request.blank('/v1.0/servers/1')
@@ -1155,6 +1349,24 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
+ def test_shutdown_status(self):
+ new_server = return_server_with_power_state(power_state.SHUTDOWN)
+ self.stubs.Set(nova.db.api, 'instance_get', new_server)
+ req = webob.Request.blank('/v1.0/servers/1')
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 200)
+ res_dict = json.loads(res.body)
+ self.assertEqual(res_dict['server']['status'], 'SHUTDOWN')
+
+ def test_shutoff_status(self):
+ new_server = return_server_with_power_state(power_state.SHUTOFF)
+ self.stubs.Set(nova.db.api, 'instance_get', new_server)
+ req = webob.Request.blank('/v1.0/servers/1')
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 200)
+ res_dict = json.loads(res.body)
+ self.assertEqual(res_dict['server']['status'], 'SHUTOFF')
+
class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
diff --git a/nova/tests/test_exception.py b/nova/tests/test_exception.py
new file mode 100644
index 000000000..4d3b9cc73
--- /dev/null
+++ b/nova/tests/test_exception.py
@@ -0,0 +1,34 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# 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 test
+from nova import exception
+
+
+class ApiErrorTestCase(test.TestCase):
+ def test_return_valid_error(self):
+ # without 'code' arg
+ err = exception.ApiError('fake error')
+ self.assertEqual(err.__str__(), 'fake error')
+ self.assertEqual(err.code, None)
+ self.assertEqual(err.msg, 'fake error')
+ # with 'code' arg
+ err = exception.ApiError('fake error', 'blah code')
+ self.assertEqual(err.__str__(), 'blah code: fake error')
+ self.assertEqual(err.code, 'blah code')
+ self.assertEqual(err.msg, 'fake error')
diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py
index dd7d0737e..ef271518c 100644
--- a/nova/tests/test_instance_types.py
+++ b/nova/tests/test_instance_types.py
@@ -75,13 +75,13 @@ class InstanceTypeTestCase(test.TestCase):
def test_invalid_create_args_should_fail(self):
"""Ensures that instance type creation fails with invalid args"""
self.assertRaises(
- exception.InvalidInputException,
+ exception.InvalidInput,
instance_types.create, self.name, 0, 1, 120, self.flavorid)
self.assertRaises(
- exception.InvalidInputException,
+ exception.InvalidInput,
instance_types.create, self.name, 256, -1, 120, self.flavorid)
self.assertRaises(
- exception.InvalidInputException,
+ exception.InvalidInput,
instance_types.create, self.name, 256, 1, "aa", self.flavorid)
def test_non_existant_inst_type_shouldnt_delete(self):
diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py
index 4e17e1ce0..cf8f4c05e 100644
--- a/nova/tests/test_misc.py
+++ b/nova/tests/test_misc.py
@@ -29,11 +29,12 @@ from nova.utils import parse_mailmap, str_dict_replace
class ProjectTestCase(test.TestCase):
def test_authors_up_to_date(self):
topdir = os.path.normpath(os.path.dirname(__file__) + '/../../')
- if os.path.exists(os.path.join(topdir, '.bzr')):
- contributors = set()
-
- mailmap = parse_mailmap(os.path.join(topdir, '.mailmap'))
+ missing = set()
+ contributors = set()
+ mailmap = parse_mailmap(os.path.join(topdir, '.mailmap'))
+ authors_file = open(os.path.join(topdir, 'Authors'), 'r').read()
+ if os.path.exists(os.path.join(topdir, '.bzr')):
import bzrlib.workingtree
tree = bzrlib.workingtree.WorkingTree.open(topdir)
tree.lock_read()
@@ -47,22 +48,36 @@ class ProjectTestCase(test.TestCase):
for r in revs:
for author in r.get_apparent_authors():
email = author.split(' ')[-1]
- contributors.add(str_dict_replace(email, mailmap))
+ contributors.add(str_dict_replace(email,
+ mailmap))
+ finally:
+ tree.unlock()
- authors_file = open(os.path.join(topdir, 'Authors'),
- 'r').read()
+ elif os.path.exists(os.path.join(topdir, '.git')):
+ import git
+ repo = git.Repo(topdir)
+ for commit in repo.head.commit.iter_parents():
+ email = commit.author.email
+ if email is None:
+ email = commit.author.name
+ if 'nova-core' in email:
+ continue
+ if email.split(' ')[-1] == '<>':
+ email = email.split(' ')[-2]
+ email = '<' + email + '>'
+ contributors.add(str_dict_replace(email, mailmap))
- missing = set()
- for contributor in contributors:
- if contributor == 'nova-core':
- continue
- if not contributor in authors_file:
- missing.add(contributor)
+ else:
+ return
- self.assertTrue(len(missing) == 0,
- '%r not listed in Authors' % missing)
- finally:
- tree.unlock()
+ for contributor in contributors:
+ if contributor == 'nova-core':
+ continue
+ if not contributor in authors_file:
+ missing.add(contributor)
+
+ self.assertTrue(len(missing) == 0,
+ '%r not listed in Authors' % missing)
class LockTestCase(test.TestCase):
diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py
index efd12f930..968ef9d6c 100644
--- a/nova/tests/test_scheduler.py
+++ b/nova/tests/test_scheduler.py
@@ -768,14 +768,10 @@ class SimpleDriverTestCase(test.TestCase):
s_ref = self._create_compute_service(host='somewhere',
memory_mb_used=12)
- try:
- self.scheduler.driver._live_migration_dest_check(self.context,
- i_ref,
- 'somewhere')
- except exception.NotEmpty, e:
- c = (e.message.find('Unable to migrate') >= 0)
+ self.assertRaises(exception.MigrationError,
+ self.scheduler.driver._live_migration_dest_check,
+ self.context, i_ref, 'somewhere')
- self.assertTrue(c)
db.instance_destroy(self.context, instance_id)
db.service_destroy(self.context, s_ref['id'])
diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py
index 498ec7012..1311ba361 100644
--- a/nova/tests/test_virt.py
+++ b/nova/tests/test_virt.py
@@ -31,9 +31,7 @@ from nova import test
from nova import utils
from nova.api.ec2 import cloud
from nova.auth import manager
-from nova.compute import manager as compute_manager
from nova.compute import power_state
-from nova.db.sqlalchemy import models
from nova.virt import libvirt_conn
libvirt = None
@@ -46,6 +44,27 @@ def _concurrency(wait, done, target):
done.send()
+def _create_network_info(count=1, ipv6=None):
+ if ipv6 is None:
+ ipv6 = FLAGS.use_ipv6
+ fake = 'fake'
+ fake_ip = '0.0.0.0/0'
+ fake_ip_2 = '0.0.0.1/0'
+ fake_ip_3 = '0.0.0.1/0'
+ network = {'gateway': fake,
+ 'gateway_v6': fake,
+ 'bridge': fake,
+ 'cidr': fake_ip,
+ 'cidr_v6': fake_ip}
+ mapping = {'mac': fake,
+ 'ips': [{'ip': fake_ip}, {'ip': fake_ip}]}
+ if ipv6:
+ mapping['ip6s'] = [{'ip': fake_ip},
+ {'ip': fake_ip_2},
+ {'ip': fake_ip_3}]
+ return [(network, mapping) for x in xrange(0, count)]
+
+
class CacheConcurrencyTestCase(test.TestCase):
def setUp(self):
super(CacheConcurrencyTestCase, self).setUp()
@@ -194,6 +213,37 @@ class LibvirtConnTestCase(test.TestCase):
return db.service_create(context.get_admin_context(), service_ref)
+ def test_preparing_xml_info(self):
+ conn = libvirt_conn.LibvirtConnection(True)
+ instance_ref = db.instance_create(self.context, self.test_instance)
+
+ result = conn._prepare_xml_info(instance_ref, False)
+ self.assertFalse(result['nics'])
+
+ result = conn._prepare_xml_info(instance_ref, False,
+ _create_network_info())
+ self.assertTrue(len(result['nics']) == 1)
+
+ result = conn._prepare_xml_info(instance_ref, False,
+ _create_network_info(2))
+ self.assertTrue(len(result['nics']) == 2)
+
+ def test_get_nic_for_xml_v4(self):
+ conn = libvirt_conn.LibvirtConnection(True)
+ network, mapping = _create_network_info()[0]
+ self.flags(use_ipv6=False)
+ params = conn._get_nic_for_xml(network, mapping)['extra_params']
+ self.assertTrue(params.find('PROJNETV6') == -1)
+ self.assertTrue(params.find('PROJMASKV6') == -1)
+
+ def test_get_nic_for_xml_v6(self):
+ conn = libvirt_conn.LibvirtConnection(True)
+ network, mapping = _create_network_info()[0]
+ self.flags(use_ipv6=True)
+ params = conn._get_nic_for_xml(network, mapping)['extra_params']
+ self.assertTrue(params.find('PROJNETV6') > -1)
+ self.assertTrue(params.find('PROJMASKV6') > -1)
+
def test_xml_and_uri_no_ramdisk_no_kernel(self):
instance_data = dict(self.test_instance)
self._check_xml_and_uri(instance_data,
@@ -229,6 +279,22 @@ class LibvirtConnTestCase(test.TestCase):
instance_data = dict(self.test_instance)
self._check_xml_and_container(instance_data)
+ def test_multi_nic(self):
+ instance_data = dict(self.test_instance)
+ network_info = _create_network_info(2)
+ conn = libvirt_conn.LibvirtConnection(True)
+ instance_ref = db.instance_create(self.context, instance_data)
+ xml = conn.to_xml(instance_ref, False, network_info)
+ tree = xml_to_tree(xml)
+ interfaces = tree.findall("./devices/interface")
+ self.assertEquals(len(interfaces), 2)
+ parameters = interfaces[0].findall('./filterref/parameter')
+ self.assertEquals(interfaces[0].get('type'), 'bridge')
+ self.assertEquals(parameters[0].get('name'), 'IP')
+ self.assertEquals(parameters[0].get('value'), '0.0.0.0/0')
+ self.assertEquals(parameters[1].get('name'), 'DHCPSERVER')
+ self.assertEquals(parameters[1].get('value'), 'fake')
+
def _check_xml_and_container(self, instance):
user_context = context.RequestContext(project=self.project,
user=self.user)
@@ -327,19 +393,13 @@ class LibvirtConnTestCase(test.TestCase):
check = (lambda t: t.find('./os/initrd'), None)
check_list.append(check)
+ parameter = './devices/interface/filterref/parameter'
common_checks = [
(lambda t: t.find('.').tag, 'domain'),
- (lambda t: t.find(
- './devices/interface/filterref/parameter').get('name'), 'IP'),
- (lambda t: t.find(
- './devices/interface/filterref/parameter').get(
- 'value'), '10.11.12.13'),
- (lambda t: t.findall(
- './devices/interface/filterref/parameter')[1].get(
- 'name'), 'DHCPSERVER'),
- (lambda t: t.findall(
- './devices/interface/filterref/parameter')[1].get(
- 'value'), '10.0.0.1'),
+ (lambda t: t.find(parameter).get('name'), 'IP'),
+ (lambda t: t.find(parameter).get('value'), '10.11.12.13'),
+ (lambda t: t.findall(parameter)[1].get('name'), 'DHCPSERVER'),
+ (lambda t: t.findall(parameter)[1].get('value'), '10.0.0.1'),
(lambda t: t.find('./devices/serial/source').get(
'path').split('/')[1], 'console.log'),
(lambda t: t.find('./memory').text, '2097152')]
@@ -586,6 +646,11 @@ class LibvirtConnTestCase(test.TestCase):
self.assertTrue(count)
+ def test_get_host_ip_addr(self):
+ conn = libvirt_conn.LibvirtConnection(False)
+ ip = conn.get_host_ip_addr()
+ self.assertEquals(ip, FLAGS.my_ip)
+
def tearDown(self):
self.manager.delete_project(self.project)
self.manager.delete_user(self.user)
@@ -651,12 +716,15 @@ class IptablesFirewallTestCase(test.TestCase):
'# Completed on Tue Jan 18 23:47:56 2011',
]
+ def _create_instance_ref(self):
+ return db.instance_create(self.context,
+ {'user_id': 'fake',
+ 'project_id': 'fake',
+ 'mac_address': '56:12:12:12:12:12',
+ 'instance_type_id': 1})
+
def test_static_filters(self):
- instance_ref = db.instance_create(self.context,
- {'user_id': 'fake',
- 'project_id': 'fake',
- 'mac_address': '56:12:12:12:12:12',
- 'instance_type_id': 1})
+ instance_ref = self._create_instance_ref()
ip = '10.11.12.13'
network_ref = db.project_get_network(self.context,
@@ -767,6 +835,40 @@ class IptablesFirewallTestCase(test.TestCase):
"TCP port 80/81 acceptance rule wasn't added")
db.instance_destroy(admin_ctxt, instance_ref['id'])
+ def test_filters_for_instance_with_ip_v6(self):
+ self.flags(use_ipv6=True)
+ network_info = _create_network_info()
+ rulesv4, rulesv6 = self.fw._filters_for_instance("fake", network_info)
+ self.assertEquals(len(rulesv4), 2)
+ self.assertEquals(len(rulesv6), 3)
+
+ def test_filters_for_instance_without_ip_v6(self):
+ self.flags(use_ipv6=False)
+ network_info = _create_network_info()
+ rulesv4, rulesv6 = self.fw._filters_for_instance("fake", network_info)
+ self.assertEquals(len(rulesv4), 2)
+ self.assertEquals(len(rulesv6), 0)
+
+ def multinic_iptables_test(self):
+ ipv4_rules_per_network = 2
+ ipv6_rules_per_network = 3
+ networks_count = 5
+ instance_ref = self._create_instance_ref()
+ network_info = _create_network_info(networks_count)
+ ipv4_len = len(self.fw.iptables.ipv4['filter'].rules)
+ ipv6_len = len(self.fw.iptables.ipv6['filter'].rules)
+ inst_ipv4, inst_ipv6 = self.fw.instance_rules(instance_ref,
+ network_info)
+ self.fw.add_filters_for_instance(instance_ref, network_info)
+ ipv4 = self.fw.iptables.ipv4['filter'].rules
+ ipv6 = self.fw.iptables.ipv6['filter'].rules
+ ipv4_network_rules = len(ipv4) - len(inst_ipv4) - ipv4_len
+ ipv6_network_rules = len(ipv6) - len(inst_ipv6) - ipv6_len
+ self.assertEquals(ipv4_network_rules,
+ ipv4_rules_per_network * networks_count)
+ self.assertEquals(ipv6_network_rules,
+ ipv6_rules_per_network * networks_count)
+
class NWFilterTestCase(test.TestCase):
def setUp(self):
@@ -848,6 +950,28 @@ class NWFilterTestCase(test.TestCase):
return db.security_group_get_by_name(self.context, 'fake', 'testgroup')
+ def _create_instance(self):
+ return db.instance_create(self.context,
+ {'user_id': 'fake',
+ 'project_id': 'fake',
+ 'mac_address': '00:A0:C9:14:C8:29',
+ 'instance_type_id': 1})
+
+ def _create_instance_type(self, params={}):
+ """Create a test instance"""
+ context = self.context.elevated()
+ inst = {}
+ inst['name'] = 'm1.small'
+ inst['memory_mb'] = '1024'
+ inst['vcpus'] = '1'
+ inst['local_gb'] = '20'
+ inst['flavorid'] = '1'
+ inst['swap'] = '2048'
+ inst['rxtx_quota'] = 100
+ inst['rxtx_cap'] = 200
+ inst.update(params)
+ return db.instance_type_create(context, inst)['id']
+
def test_creates_base_rule_first(self):
# These come pre-defined by libvirt
self.defined_filters = ['no-mac-spoofing',
@@ -876,25 +1000,18 @@ class NWFilterTestCase(test.TestCase):
self.fake_libvirt_connection.nwfilterDefineXML = _filterDefineXMLMock
- instance_ref = db.instance_create(self.context,
- {'user_id': 'fake',
- 'project_id': 'fake',
- 'mac_address': '00:A0:C9:14:C8:29',
- 'instance_type_id': 1})
+ instance_ref = self._create_instance()
inst_id = instance_ref['id']
ip = '10.11.12.13'
- network_ref = db.project_get_network(self.context,
- 'fake')
-
- fixed_ip = {'address': ip,
- 'network_id': network_ref['id']}
+ network_ref = db.project_get_network(self.context, 'fake')
+ fixed_ip = {'address': ip, 'network_id': network_ref['id']}
admin_ctxt = context.get_admin_context()
db.fixed_ip_create(admin_ctxt, fixed_ip)
db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
- 'instance_id': instance_ref['id']})
+ 'instance_id': inst_id})
def _ensure_all_called():
instance_filter = 'nova-instance-%s-%s' % (instance_ref['name'],
@@ -920,3 +1037,11 @@ class NWFilterTestCase(test.TestCase):
_ensure_all_called()
self.teardown_security_group()
db.instance_destroy(admin_ctxt, instance_ref['id'])
+
+ def test_create_network_filters(self):
+ instance_ref = self._create_instance()
+ network_info = _create_network_info(3)
+ result = self.fw._create_network_filters(instance_ref,
+ network_info,
+ "fake")
+ self.assertEquals(len(result), 3)