Revision 660b9f3b snf-cyclades-app/synnefo/api/util.py

b/snf-cyclades-app/synnefo/api/util.py
284 284

  
285 285

  
286 286
def allocate_public_address(backend):
287
    """Allocate a public IP for a vm."""
288
    for network in backend_public_networks(backend):
289
        try:
290
            address = get_network_free_address(network)
291
        except faults.OverLimit:
292
            pass
293
        else:
294
            return (network, address)
295
    return (None, None)
296

  
297

  
298
def get_public_ip(backend):
299
    """Reserve an IP from a public network.
300

  
301
    This method should run inside a transaction.
302

  
303
    """
304

  
287
    """Get a public IP for any available network of a backend."""
305 288
    # Guarantee exclusive access to backend, because accessing the IP pools of
306 289
    # the backend networks may result in a deadlock with backend allocator
307 290
    # which also checks that backend networks have a free IP.
308 291
    backend = Backend.objects.select_for_update().get(id=backend.id)
309

  
310
    address = None
311
    if settings.PUBLIC_USE_POOL:
312
        (network, address) = allocate_public_address(backend)
313
    else:
314
        for net in list(backend_public_networks(backend)):
315
            pool = net.get_pool()
316
            if not pool.empty():
317
                address = 'pool'
318
                network = net
319
                break
320
    if address is None:
321
        log.error("Public networks of backend %s are full", backend)
322
        raise faults.OverLimit("Can not allocate IP for new machine."
323
                        " Public networks are full.")
324
    return (network, address)
292
    public_networks = backend_public_networks(backend)
293
    return get_free_ip(public_networks)
325 294

  
326 295

  
327 296
def backend_public_networks(backend):
......
331 300
    to the specified backend.
332 301

  
333 302
    """
334
    for network in Network.objects.filter(public=True, deleted=False,
335
                                          drained=False):
336
        if BackendNetwork.objects.filter(network=network,
337
                                         backend=backend).exists():
338
            yield network
303
    bnets = BackendNetwork.objects.filter(backend=backend,
304
                                          network__public=True,
305
                                          network__deleted=False,
306
                                          network__drained=False)
307
    return [b.network for b in bnets]
308

  
309

  
310
def get_free_ip(networks):
311
    for network in networks:
312
        try:
313
            address = get_network_free_address(network)
314
            return network, address
315
        except faults.OverLimit:
316
            pass
317
    msg = "Can not allocate public IP. Public networks are full."
318
    log.error(msg)
319
    raise faults.OverLimit(msg)
339 320

  
340 321

  
341 322
def get_network_free_address(network):
......
346 327
        address = pool.get()
347 328
    except EmptyPool:
348 329
        raise faults.OverLimit("Network %s is full." % network.backend_id)
349
        address = None
350 330
    pool.save()
351 331
    return address
352 332

  
353 333

  
354
def allocate_public_ip(networks=None):
355
    """Allocate an IP address from public networks."""
356
    if networks is None:
357
        networks = Network.objects.select_for_update().filter(public=True,
358
                                                              deleted=False)
359
    for network in networks:
360
        try:
361
            address = get_network_free_address(network)
362
        except:
363
            pass
364
        else:
365
            return network, address
366
    msg = "Can not allocate public IP. Public networks are full."
367
    log.error(msg)
368
    raise faults.OverLimit(msg)
369

  
370

  
371 334
def get_nic(machine, network):
372 335
    try:
373 336
        return NetworkInterface.objects.get(machine=machine, network=network)

Also available in: Unified diff