summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-08-15 07:56:20 +0000
committerGerrit Code Review <review@openstack.org>2012-08-15 07:56:20 +0000
commite5a8033888fa3e772598eb856fa7ac9c7189f45f (patch)
tree2ec601b9313b9f90dc7074ba958eff8754022b4b
parenta301ff6dfd2a43ddb712eb69f4fb266dd3bc2b25 (diff)
parent8c2daea590df4fb3f6877c21007afedc889e1416 (diff)
downloadnova-e5a8033888fa3e772598eb856fa7ac9c7189f45f.tar.gz
nova-e5a8033888fa3e772598eb856fa7ac9c7189f45f.tar.xz
nova-e5a8033888fa3e772598eb856fa7ac9c7189f45f.zip
Merge "Uniqueness checks for floating ip addresses."
-rwxr-xr-xbin/nova-manage16
-rw-r--r--nova/db/api.py5
-rw-r--r--nova/db/sqlalchemy/api.py28
-rw-r--r--nova/exception.py14
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_floating_ips.py47
5 files changed, 90 insertions, 20 deletions
diff --git a/bin/nova-manage b/bin/nova-manage
index 14861b826..7005c7fcf 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -431,11 +431,17 @@ class FloatingIpCommands(object):
pool = FLAGS.default_floating_pool
if not interface:
interface = FLAGS.public_interface
- for address in self.address_to_hosts(ip_range):
- db.floating_ip_create(admin_context,
- {'address': str(address),
- 'pool': pool,
- 'interface': interface})
+
+ ips = ({'address': str(address), 'pool': pool, 'interface': interface}
+ for address in self.address_to_hosts(ip_range))
+ try:
+ db.floating_ip_bulk_create(admin_context, ips)
+ except exception.FloatingIpExists as exc:
+ # NOTE(simplylizz): Maybe logging would be better here
+ # instead of printing, but logging isn't used here and I
+ # don't know why.
+ print('error: %s' % exc)
+ sys.exit(1)
@args('--ip_range', dest="ip_range", metavar='<range>', help='IP range')
def delete(self, ip_range):
diff --git a/nova/db/api.py b/nova/db/api.py
index 1df1e970c..ceb361722 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -282,6 +282,11 @@ def floating_ip_allocate_address(context, project_id, pool):
return IMPL.floating_ip_allocate_address(context, project_id, pool)
+def floating_ip_bulk_create(context, ips):
+ """Create a lot of floating ips from the values dictionary."""
+ return IMPL.floating_ip_bulk_create(context, ips)
+
+
def floating_ip_create(context, values):
"""Create a floating ip from the values dictionary."""
return IMPL.floating_ip_create(context, values)
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 1c8248a53..85f5d8f48 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -757,10 +757,34 @@ def floating_ip_allocate_address(context, project_id, pool):
@require_context
-def floating_ip_create(context, values):
+def floating_ip_bulk_create(context, ips):
+ session = get_session()
+ with session.begin():
+ for ip in ips:
+ floating_ip_create(context, ip, session)
+
+
+@require_context
+def floating_ip_create(context, values, session=None):
+ if not session:
+ session = get_session()
+
floating_ip_ref = models.FloatingIp()
floating_ip_ref.update(values)
- floating_ip_ref.save()
+
+ # check uniqueness for not deleted addresses
+ if not floating_ip_ref.deleted:
+ try:
+ floating_ip = floating_ip_get_by_address(context,
+ floating_ip_ref.address,
+ session)
+ except exception.FloatingIpNotFoundForAddress:
+ pass
+ else:
+ if floating_ip.id != floating_ip_ref.id:
+ raise exception.FloatingIpExists(**dict(floating_ip_ref))
+
+ floating_ip_ref.save(session=session)
return floating_ip_ref['address']
diff --git a/nova/exception.py b/nova/exception.py
index de8982488..9beadd2df 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -639,6 +639,15 @@ class NoFixedIpsDefined(NotFound):
message = _("Zero fixed ips could be found.")
+#TODO(bcwaldon): EOL this exception!
+class Duplicate(NovaException):
+ pass
+
+
+class FloatingIpExists(Duplicate):
+ message = _("Floating ip %(address)s already exists.")
+
+
class FloatingIpNotFound(NotFound):
message = _("Floating ip not found for id %(id)s.")
@@ -907,11 +916,6 @@ class RotationRequiredForBackup(NovaException):
message = _("Rotation param is required for backup image_type")
-#TODO(bcwaldon): EOL this exception!
-class Duplicate(NovaException):
- pass
-
-
class KeyPairExists(Duplicate):
message = _("Key pair %(key_name)s already exists.")
diff --git a/nova/tests/api/openstack/compute/contrib/test_floating_ips.py b/nova/tests/api/openstack/compute/contrib/test_floating_ips.py
index db1364c3b..ce43c0ffa 100644
--- a/nova/tests/api/openstack/compute/contrib/test_floating_ips.py
+++ b/nova/tests/api/openstack/compute/contrib/test_floating_ips.py
@@ -105,14 +105,23 @@ def get_instance_by_floating_ip_addr(self, context, address):
class FloatingIpTest(test.TestCase):
floating_ip = "10.10.10.10"
+ floating_ip_2 = "10.10.10.11"
- def _create_floating_ip(self):
+ def _create_floating_ips(self, floating_ips=None):
"""Create a floating ip object."""
- host = "fake_host"
- return db.floating_ip_create(self.context,
- {'address': self.floating_ip,
- 'pool': 'nova',
- 'host': host})
+ if floating_ips is None:
+ floating_ips = [self.floating_ip]
+ elif not isinstance(floating_ips, (list, tuple)):
+ floating_ips = [floating_ips]
+
+ def make_ip_dict(ip):
+ """Shortcut for creating floating ip dict."""
+ return
+
+ dict_ = {'pool': 'nova', 'host': 'fake_host'}
+ return db.floating_ip_bulk_create(
+ self.context, [dict(address=ip, **dict_) for ip in floating_ips],
+ )
def _delete_floating_ip(self):
db.floating_ip_destroy(self.context, self.floating_ip)
@@ -144,7 +153,7 @@ class FloatingIpTest(test.TestCase):
fake_instance_get)
self.context = context.get_admin_context()
- self._create_floating_ip()
+ self._create_floating_ips()
self.controller = floating_ips.FloatingIPController()
self.manager = floating_ips.FloatingIPActionController()
@@ -154,7 +163,7 @@ class FloatingIpTest(test.TestCase):
super(FloatingIpTest, self).tearDown()
def test_translate_floating_ip_view(self):
- floating_ip_address = self._create_floating_ip()
+ floating_ip_address = self.floating_ip
floating_ip = db.floating_ip_get_by_address(self.context,
floating_ip_address)
floating_ip['fixed_ip'] = None
@@ -226,6 +235,28 @@ class FloatingIpTest(test.TestCase):
self.assertEqual(res_dict['floating_ip']['ip'], '10.10.10.10')
self.assertEqual(res_dict['floating_ip']['instance_id'], FAKE_UUID)
+ def test_recreation_of_floating_ip(self):
+ self._delete_floating_ip()
+ self._create_floating_ips()
+
+ def test_floating_ip_in_bulk_creation(self):
+ self._delete_floating_ip()
+
+ self._create_floating_ips([self.floating_ip, self.floating_ip_2])
+ all_ips = db.floating_ip_get_all(self.context)
+ ip_list = [ip['address'] for ip in all_ips]
+ self.assertIn(self.floating_ip, ip_list)
+ self.assertIn(self.floating_ip_2, ip_list)
+
+ def test_fail_floating_ip_in_bulk_creation(self):
+ self.assertRaises(exception.FloatingIpExists,
+ self._create_floating_ips,
+ [self.floating_ip, self.floating_ip_2])
+ all_ips = db.floating_ip_get_all(self.context)
+ ip_list = [ip['address'] for ip in all_ips]
+ self.assertIn(self.floating_ip, ip_list)
+ self.assertNotIn(self.floating_ip_2, ip_list)
+
# test floating ip allocate/release(deallocate)
def test_floating_ip_allocate_no_free_ips(self):
def fake_call(*args, **kwargs):