Revision a3d99af0

b/snf-cyclades-app/synnefo/api/floating_ips.py
40 40
from snf_django.lib.api import faults, utils
41 41
from synnefo.api import util
42 42
from synnefo import quotas
43
from synnefo.db.models import Network, FloatingIP
43
from synnefo.db.models import Network, FloatingIP, NetworkInterface
44 44

  
45 45

  
46 46
from logging import getLogger
......
137 137
    except Network.DoesNotExist:
138 138
        raise faults.ItemNotFound("Pool '%s' does not exist." % pool)
139 139

  
140
    address = req.get("address", None)
141
    machine = None
140 142
    try:
141
        address = util.get_network_free_address(network)
143
        if address is None:
144
            address = util.get_network_free_address(network)  # Get X-Lock
145
        else:
146
            if FloatingIP.objects.filter(network=network,
147
                                         ipv4=address).exists():
148
                msg = "Floating IP '%s' is reserved" % address
149
                raise faults.Conflict(msg)
150
            pool = network.get_pool()  # Gets X-Lock
151
            if not pool.contains(address):
152
                raise faults.BadRequest("Invalid address")
153
            if not pool.is_available(address):
154
                try:
155
                    network.nics.get(ipv4=address,
156
                                     machine__userid=userid)
157
                except NetworkInterface.DoesNotExist:
158
                    msg = "Address '%s' is already in use" % address
159
                    raise faults.Conflict(msg)
160
            pool.reserve(address)
161
            pool.save()
142 162
        floating_ip = FloatingIP.objects.create(ipv4=address, network=network,
143
                                                userid=userid)
163
                                                userid=userid, machine=machine)
144 164
        quotas.issue_and_accept_commission(floating_ip)
145 165
    except:
146 166
        transaction.rollback()
b/snf-cyclades-app/synnefo/api/test/floating_ips.py
108 108
            response = self.post(URL, "test_user", json.dumps(request), "json")
109 109
        self.assertEqual(response.status_code, 413)
110 110

  
111
    def test_reserve_with_address(self):
112
        net = NetworkFactory(userid="test_user", subnet="192.168.2.0/24",
113
                             gateway=None, public=True)
114
        request = {'pool': net.id, "address": "192.168.2.10"}
115
        with mocked_quotaholder():
116
            response = self.post(URL, "test_user", json.dumps(request), "json")
117
        self.assertSuccess(response)
118
        self.assertEqual(json.loads(response.content)["floating_ip"],
119
                         {"instance_id": None, "ip": "192.168.2.10",
120
                          "fixed_ip": None, "id": "1", "pool": "1"})
121

  
122
        # Already reserved
123
        FloatingIPFactory(network=net, ipv4="192.168.2.3")
124
        request = {'pool': net.id, "address": "192.168.2.3"}
125
        with mocked_quotaholder():
126
            response = self.post(URL, "test_user", json.dumps(request), "json")
127
        self.assertFault(response, 409, "conflict")
128

  
129
        # Already used
130
        pool = net.get_pool()
131
        pool.reserve("192.168.2.5")
132
        pool.save()
133
        # ..by another_user
134
        nic = NetworkInterfaceFactory(network=net, ipv4="192.168.2.5",
135
                                      machine__userid="test2")
136
        request = {'pool': net.id, "address": "192.168.2.5"}
137
        with mocked_quotaholder():
138
            response = self.post(URL, "test_user", json.dumps(request), "json")
139
        self.assertFault(response, 409, "conflict")
140
        # ..and by him
141
        nic.delete()
142
        NetworkInterfaceFactory(network=net, ipv4="192.168.2.5",
143
                                machine__userid="test_user")
144
        request = {'pool': net.id, "address": "192.168.2.5"}
145
        with mocked_quotaholder():
146
            response = self.post(URL, "test_user", json.dumps(request), "json")
147
        self.assertSuccess(response)
148

  
149
        # Address out of pool
150
        request = {'pool': net.id, "address": "192.168.3.5"}
151
        with mocked_quotaholder():
152
            response = self.post(URL, "test_user", json.dumps(request), "json")
153
        self.assertBadRequest(response)
154

  
111 155
    def test_release_in_use(self):
112 156
        ip = FloatingIPFactory()
113 157
        vm = ip.machine
b/snf-cyclades-app/synnefo/db/pools/__init__.py
264 264

  
265 265
    def index_to_value(self, index):
266 266
        return str(self.net[index])
267

  
268
    def contains(self, address):
269
        addr = ipaddr.IPAddress(address)
270
        return addr in self.net
b/snf-cyclades-app/synnefo/db/pools/tests.py
220 220
        self.assertEqual(pool.is_available('192.168.2.255'), False)
221 221
        self.assertEqual(pool.count_available(), 253)
222 222
        self.assertEqual(pool.get(), '192.168.2.2')
223
        self.assertTrue(pool.contains("192.168.2.10"))
224
        self.assertFalse(pool.contains("192.168.3.10"))
223 225

  
224 226
    def test_auto_reservations_2(self):
225 227
        obj = DummyObject(0)

Also available in: Unified diff