From 542958fac7445a14deaae146b0d4047aa90a2fab Mon Sep 17 00:00:00 2001
From: Dan Smith <dansmith@redhat.com>
Date: Thu, 16 Jan 2014 14:36:32 -0800
Subject: [PATCH] Make nova-network use FixedIP object for updates

This makes nova-network manager use the FixedIP object for
updates instead of direct database calls.

Related to blueprint nova-network-objects

Change-Id: Ia191148cf7510ffdb0fbd4186fa34bb4c5ab1b0f
---
 nova/network/manager.py            | 45 ++++++++++++++----------------
 nova/tests/network/test_manager.py |  8 +++++-
 2 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/nova/network/manager.py b/nova/network/manager.py
index e442393bd353..bce1d557f238 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -857,9 +857,9 @@ class NetworkManager(manager.Manager):
                         context.elevated(), network['id'], instance_id)
                 vif = vif_obj.VirtualInterface.get_by_instance_and_network(
                         context, instance_id, network['id'])
-                values = {'allocated': True,
-                          'virtual_interface_id': vif['id']}
-                self.db.fixed_ip_update(context, str(fip.address), values)
+                fip.allocated = True
+                fip.virtual_interface_id = vif.id
+                fip.save()
                 self._do_trigger_security_group_members_refresh_for_instance(
                     instance_id)
 
@@ -916,9 +916,9 @@ class NetworkManager(manager.Manager):
                 self.instance_dns_manager.delete_entry(n,
                                                       self.instance_dns_domain)
 
-        self.db.fixed_ip_update(context, address,
-                                {'allocated': False,
-                                 'virtual_interface_id': None})
+        fixed_ip_ref.allocated = False
+        fixed_ip_ref.virtual_interface_id = None
+        fixed_ip_ref.save()
 
         if teardown:
             network = fixed_ip_ref.network
@@ -974,11 +974,8 @@ class NetworkManager(manager.Manager):
             LOG.warn(_('IP %s leased that is not associated'), address,
                        context=context)
             return
-        now = timeutils.utcnow()
-        self.db.fixed_ip_update(context,
-                                fixed_ip.address,
-                                {'leased': True,
-                                 'updated_at': now})
+        fixed_ip.leased = True
+        fixed_ip.save()
         if not fixed_ip.allocated:
             LOG.warn(_('IP |%s| leased that isn\'t allocated'), address,
                      context=context)
@@ -995,9 +992,8 @@ class NetworkManager(manager.Manager):
         if not fixed_ip.leased:
             LOG.warn(_('IP %s released that was not leased'), address,
                      context=context)
-        self.db.fixed_ip_update(context,
-                                fixed_ip.address,
-                                {'leased': False})
+        fixed_ip.leased = False
+        fixed_ip.save()
         if not fixed_ip.allocated:
             fixed_ip.disassociate()
 
@@ -1725,8 +1721,8 @@ class VlanManager(RPCAllocateFixedIP, floating_ips.FloatingIP, NetworkManager):
 
         if kwargs.get('vpn', None):
             address = network['vpn_private_address']
-            fixed_ip_obj.FixedIP.associate(context, address, instance_id,
-                                           network['id'], reserved=True)
+            fip = fixed_ip_obj.FixedIP.associate(context, address, instance_id,
+                                                 network['id'], reserved=True)
         else:
             address = kwargs.get('address', None)
             if address:
@@ -1737,13 +1733,13 @@ class VlanManager(RPCAllocateFixedIP, floating_ips.FloatingIP, NetworkManager):
                 fip = fixed_ip_obj.FixedIP.associate_pool(context,
                                                           network['id'],
                                                           instance_id)
-            address = fip.address
+        address = fip.address
 
         vif = vif_obj.VirtualInterface.get_by_instance_and_network(
             context, instance_id, network['id'])
-        values = {'allocated': True,
-                  'virtual_interface_id': vif.id}
-        self.db.fixed_ip_update(context, str(address), values)
+        fip.allocated = True
+        fip.virtual_interface_id = vif.id
+        fip.save()
 
         if not kwargs.get('vpn', None):
             self._do_trigger_security_group_members_refresh_for_instance(
@@ -1903,10 +1899,11 @@ class VlanManager(RPCAllocateFixedIP, floating_ips.FloatingIP, NetworkManager):
                 self.driver.kill_dhcp(dev)
                 self.l3driver.remove_gateway(network)
                 if not CONF.share_dhcp_address:
-                    values = {'allocated': False,
-                              'host': None}
-                    self.db.fixed_ip_update(context, network['dhcp_server'],
-                                            values)
+                    fip = fixed_ip_obj.FixedIP.get_by_address(
+                        context, network.dhcp_server)
+                    fip.allocated = False
+                    fip.host = None
+                    fip.save()
             else:
                 self.driver.update_dhcp(elevated, dev, network)
 
diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py
index df07ce5753f6..a7d96a7f6c5c 100644
--- a/nova/tests/network/test_manager.py
+++ b/nova/tests/network/test_manager.py
@@ -1364,7 +1364,8 @@ class VlanNetworkTestCase(test.TestCase):
 
     @mock.patch('nova.db.fixed_ip_get_by_address')
     @mock.patch('nova.db.network_get')
-    def test_deallocate_fixed_no_vif(self, net_get, fixed_get):
+    @mock.patch('nova.db.fixed_ip_update')
+    def test_deallocate_fixed_no_vif(self, fixed_update, net_get, fixed_get):
         """Verify that deallocate doesn't raise when no vif is returned.
 
         Ensures https://bugs.launchpad.net/nova/+bug/968457 doesn't return
@@ -1384,13 +1385,18 @@ class VlanNetworkTestCase(test.TestCase):
         elevated = context1.elevated()
         fix_addr = db.fixed_ip_associate_pool(elevated, 1, instance['uuid'])
         fixed_get.return_value = dict(test_fixed_ip.fake_fixed_ip,
+                                      address=fix_addr.address,
                                       allocated=True,
                                       virtual_interface_id=3,
                                       instance_uuid=instance.uuid,
                                       network=dict(test_network.fake_network,
                                                    **networks[1]))
         self.flags(force_dhcp_release=True)
+        fixed_update.return_value = fixed_get.return_value
         self.network.deallocate_fixed_ip(context1, fix_addr.address, 'fake')
+        fixed_update.assert_called_once_with(context1, fix_addr.address,
+                                             {'allocated': False,
+                                              'virtual_interface_id': None})
 
     @mock.patch('nova.db.fixed_ip_get_by_address')
     @mock.patch('nova.db.network_get')