Commit 4a96ab00 authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

cyclades: Get floating IP without specifying pools

Extend GET /floatingips API method, to allow requests that do not
specify the 'floating_network_id' attribute. In this case it will try
to allocate a floating IP address from one of the available floating IP
pools. If there is no available floating IP, it will return 409.
parent c7a20bd6
......@@ -143,27 +143,33 @@ def allocate_floating_ip(request):
userid = request.user_uniq
# the network_pool is a mandatory field
network_pool = api.utils.get_attribute(floating_ip_dict,
"floating_network_id",
required=True)
address = api.utils.get_attribute(floating_ip_dict, "floating_ip_address",
required=False)
try:
network_id = int(network_pool)
except ValueError:
raise faults.BadRequest("Invalid networkd ID.")
network = util.get_network(network_id, userid, for_update=True,
non_deleted=True)
if not network.floating_ip_pool:
# Check that it is a floating IP pool
raise faults.ItemNotFound("Floating IP pool %s does not exist." %
network_id)
# Allocate the floating IP
floating_ip = util.allocate_ip(network, userid, address=address,
floating_ip=True)
network_id = api.utils.get_attribute(floating_ip_dict,
"floating_network_id",
required=False)
if network_id is None:
floating_ip = util.allocate_public_ip(userid, floating_ip=True)
else:
try:
network_id = int(network_id)
except ValueError:
raise faults.BadRequest("Invalid networkd ID.")
network = util.get_network(network_id, userid, for_update=True,
non_deleted=True)
if not network.floating_ip_pool:
# TODO: Maybe 409 ??
# Check that it is a floating IP pool
raise faults.ItemNotFound("Floating IP pool %s does not exist." %
network_id)
address = api.utils.get_attribute(floating_ip_dict,
"floating_ip_address",
required=False)
# Allocate the floating IP
floating_ip = util.allocate_ip(network, userid, address=address,
floating_ip=True)
# Issue commission (quotas)
quotas.issue_and_accept_commission(floating_ip)
transaction.commit()
......
......@@ -33,13 +33,10 @@
from django.utils import simplejson as json
from snf_django.utils.testing import BaseAPITest, mocked_quotaholder
from synnefo.db.models import IPAddress
from synnefo.db.models import IPAddress, Network
from synnefo.db import models_factory as mf
from synnefo.db.models_factory import (NetworkFactory,
VirtualMachineFactory)
from mock import patch, Mock
from functools import partial
from synnefo.cyclades_settings import cyclades_services
from synnefo.lib.services import get_service_path
......@@ -53,8 +50,6 @@ SERVERS_URL = join_urls(compute_path, "servers")
floating_ips = IPAddress.objects.filter(floating_ip=True)
FloatingIPPoolFactory = partial(NetworkFactory, public=True, deleted=False,
floating_ip_pool=True)
class FloatingIPAPITest(BaseAPITest):
......@@ -128,6 +123,36 @@ class FloatingIPAPITest(BaseAPITest):
"port_id": None,
"floating_network_id": str(self.pool.id)})
def test_reserve_empty_body(self):
"""Test reserve FIP without specifying network."""
request = {"floatingip": {}}
# delete all pools..
Network.objects.all().delete()
# CASE: no floating IP pool
with mocked_quotaholder():
response = self.post(URL, "test_user", json.dumps(request), "json")
self.assertConflict(response)
# CASE: Full floating IP pool
mf.NetworkWithSubnetFactory(floating_ip_pool=True, public=True,
subnet__pool__size=0)
with mocked_quotaholder():
response = self.post(URL, "test_user", json.dumps(request), "json")
self.assertConflict(response)
# CASE: Available floating IP pool
p1 = mf.NetworkWithSubnetFactory(floating_ip_pool=True, public=True,
subnet__cidr="192.168.2.0/30",
subnet__pool__size=1)
with mocked_quotaholder():
response = self.post(URL, "test_user", json.dumps(request), "json")
self.assertSuccess(response)
floating_ip = json.loads(response.content)["floatingip"]
db_fip = IPAddress.objects.get(id=floating_ip["id"])
self.assertEqual(db_fip.address, floating_ip["floating_ip_address"])
self.assertTrue(db_fip.floating_ip)
# Test that address is reserved
ip_pool = p1.get_ip_pools()[0]
self.assertFalse(ip_pool.is_available(db_fip.address))
def test_reserve_no_pool(self):
# Network is not a floating IP pool
pool2 = mf.NetworkWithSubnetFactory(floating_ip_pool=False,
......
......@@ -358,7 +358,10 @@ def allocate_public_ip(userid, floating_ip=False, backend=None):
log_msg += " Backend: %s" % backend
log.error(log_msg)
exception_msg = "Can not allocate a %s IP address." % ip_type
raise faults.ServiceUnavailable(exception_msg)
if floating_ip:
raise faults.Conflict(exception_msg)
else:
raise faults.ServiceUnavailable(exception_msg)
def backend_has_free_public_ip(backend):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment