Revision 0c50c760

b/snf-cyclades-app/synnefo/api/floating_ips.py
138 138
            network, address = util.get_free_ip(net_objects)
139 139
        else:
140 140
            try:
141
                network = Network.objects.select_for_update()\
142
                                         .get(id=pool, public=True,
143
                                              deleted=False,
144
                                              floating_ip_pool=True)
145

  
146
            except Network.DoesNotExist:
141
                network_id = int(pool)
142
            except ValueErrorx:
143
                raise faults.BadRequest("Invalid pool ID.")
144
            network = next((n for n in net_objects if n.id==pool), None)
145
            if network is None:
147 146
                raise faults.ItemNotFound("Pool '%s' does not exist." % pool)
148 147
            if address is None:
149 148
                # User did not specified an IP address. Choose a random one
b/snf-cyclades-app/synnefo/db/models.py
708 708
            (self.index, self.machine_id, self.network_id, self.ipv4,
709 709
             self.ipv6)
710 710

  
711
    @property
712
    def is_floating_ip(self):
713
        network = self.network
714
        if self.ipv4 and network.floating_ip_pool:
715
            return network.floating_ips.filter(machine=self.machine,
716
                                               ipv4=self.ipv4,
717
                                               deleted=False).exists()
718
        return False
719

  
711 720

  
712 721
class FloatingIP(models.Model):
713 722
    userid = models.CharField("UUID of the owner", max_length=128,
b/snf-cyclades-app/synnefo/logic/backend.py
300 300
    to_release = old_addresses - new_addresses
301 301
    for (network_id, ipv4) in to_release:
302 302
        if ipv4:
303
            net = Network.objects.get(id=network_id)
304
            # Important: Take exclusive lock in pool before checking if there
305
            # is a floating IP with this ipv4 address, otherwise there is a
306
            # race condition, where you may release a floating IP that has been
307
            # created after search floating IPs and before you get exclusively
308
            # the pool
309
            pool = net.get_pool()
310
            try:
311
                floating_ip = net.floating_ips.select_for_update()\
312
                                              .get(ipv4=ipv4, machine=vm,
313
                                                   deleted=False)
314
                floating_ip.machine = None
315
                floating_ip.save()
316
            except FloatingIP.DoesNotExist:
303
            # Get X-Lock before searching floating IP, to exclusively search
304
            # and release floating IP. Otherwise you may release a floating IP
305
            # that has been just reserved.
306
            net = Network.objects.select_for_update().get(id=network_id)
307
            if net.floating_ip_pool:
308
                try:
309
                    floating_ip = net.floating_ips.select_for_update()\
310
                                                  .get(ipv4=ipv4, machine=vm,
311
                                                       deleted=False)
312
                    floating_ip.machine = None
313
                    floating_ip.save()
314
                except FloatingIP.DoesNotExist:
315
                    net.release_address(ipv4)
316
            else:
317 317
                net.release_address(ipv4)
318
                pool.save()
319 318

  
320 319

  
321 320
@transaction.commit_on_success
b/snf-cyclades-app/synnefo/logic/tests.py
268 268
        self.assertFalse(db_vm.nics.all())
269 269
        self.assertTrue(nic.network.get_pool().is_available(nic.ipv4))
270 270
        vm2 = mfactory.VirtualMachineFactory()
271
        network = mfactory.NetworkFactory()
271
        network = mfactory.NetworkFactory(floating_ip_pool=True)
272 272
        fp1 = mfactory.FloatingIPFactory(machine=vm2, network=network)
273 273
        fp2 = mfactory.FloatingIPFactory(machine=vm2, network=network)
274 274
        mfactory.NetworkInterfaceFactory(machine=vm2, network=network,

Also available in: Unified diff