07d81d7
From 015744e92e601036ddcd77bd2fbed966172cb759 Mon Sep 17 00:00:00 2001
07d81d7
From: Vishvananda Ishaya <vishvananda@gmail.com>
07d81d7
Date: Tue, 3 Apr 2012 11:30:57 -0700
07d81d7
Subject: [PATCH] Delete fixed_ips when network is deleted
07d81d7
07d81d7
 * adds failing test
07d81d7
 * adds exception that is raised when network is in use
07d81d7
 * fixes bug 754900
07d81d7
07d81d7
Change-Id: Ib95dc5927561b979b1eea237d4d6dc323483d4a5
07d81d7
---
07d81d7
 nova/db/sqlalchemy/api.py |   13 +++++++++++++
07d81d7
 nova/exception.py         |    4 ++++
07d81d7
 nova/tests/test_db_api.py |   19 +++++++++++++++++++
07d81d7
 3 files changed, 36 insertions(+), 0 deletions(-)
07d81d7
07d81d7
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
07d81d7
index f2c3062..03ac987 100644
07d81d7
--- a/nova/db/sqlalchemy/api.py
07d81d7
+++ b/nova/db/sqlalchemy/api.py
07d81d7
@@ -1898,8 +1898,21 @@ def network_create_safe(context, values):
07d81d7
 def network_delete_safe(context, network_id):
07d81d7
     session = get_session()
07d81d7
     with session.begin():
07d81d7
+        result = session.query(models.FixedIp).\
07d81d7
+                         filter_by(network_id=network_id).\
07d81d7
+                         filter_by(deleted=False).\
07d81d7
+                         filter_by(allocated=True).\
07d81d7
+                         all()
07d81d7
+        if result:
07d81d7
+            raise exception.NetworkInUse(network_id=network_id)
07d81d7
         network_ref = network_get(context, network_id=network_id,
07d81d7
                                   session=session)
07d81d7
+        session.query(models.FixedIp).\
07d81d7
+                filter_by(network_id=network_id).\
07d81d7
+                filter_by(deleted=False).\
07d81d7
+                update({'deleted': True,
07d81d7
+                        'updated_at': literal_column('updated_at'),
07d81d7
+                        'deleted_at': utils.utcnow()})
07d81d7
         session.delete(network_ref)
07d81d7
 
07d81d7
 
07d81d7
diff --git a/nova/exception.py b/nova/exception.py
07d81d7
index eb0bf38..da067b6 100644
07d81d7
--- a/nova/exception.py
07d81d7
+++ b/nova/exception.py
07d81d7
@@ -525,6 +525,10 @@ class StorageRepositoryNotFound(NotFound):
07d81d7
     message = _("Cannot find SR to read/write VDI.")
07d81d7
 
07d81d7
 
07d81d7
+class NetworkInUse(NovaException):
07d81d7
+    message = _("Network %(network_id)s is still in use.")
07d81d7
+
07d81d7
+
07d81d7
 class NetworkNotCreated(NovaException):
07d81d7
     message = _("%(req)s is required to create a network.")
07d81d7
 
07d81d7
diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py
07d81d7
index 8b73580..28f3558 100644
07d81d7
--- a/nova/tests/test_db_api.py
07d81d7
+++ b/nova/tests/test_db_api.py
07d81d7
@@ -136,6 +136,25 @@ class DbApiTestCase(test.TestCase):
07d81d7
         db_network = db.network_get(ctxt, network.id)
07d81d7
         self.assertEqual(network.uuid, db_network.uuid)
07d81d7
 
07d81d7
+    def test_network_delete_safe(self):
07d81d7
+        ctxt = context.get_admin_context()
07d81d7
+        values = {'host': 'localhost', 'project_id': 'project1'}
07d81d7
+        network = db.network_create_safe(ctxt, values)
07d81d7
+        db_network = db.network_get(ctxt, network.id)
07d81d7
+        values = {'network_id': network['id'], 'address': 'fake1'}
07d81d7
+        address1 = db.fixed_ip_create(ctxt, values)
07d81d7
+        values = {'network_id': network['id'],
07d81d7
+                  'address': 'fake2',
07d81d7
+                  'allocated': True}
07d81d7
+        address2 = db.fixed_ip_create(ctxt, values)
07d81d7
+        self.assertRaises(exception.NetworkInUse,
07d81d7
+                          db.network_delete_safe, ctxt, network['id'])
07d81d7
+        db.fixed_ip_update(ctxt, address2, {'allocated': False})
07d81d7
+        network = db.network_delete_safe(ctxt, network['id'])
07d81d7
+        ctxt = ctxt.elevated(read_deleted='yes')
07d81d7
+        fixed_ip = db.fixed_ip_get_by_address(ctxt, address1)
07d81d7
+        self.assertTrue(fixed_ip['deleted'])
07d81d7
+
07d81d7
     def test_network_create_with_duplicate_vlan(self):
07d81d7
         ctxt = context.get_admin_context()
07d81d7
         values1 = {'host': 'localhost', 'project_id': 'project1', 'vlan': 1}