Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / tests / floating_ips.py @ ddffd973

History | View | Annotate | Download (19.6 kB)

1 acda838e Christos Stavrakakis
# Copyright 2012 GRNET S.A. All rights reserved.
2 acda838e Christos Stavrakakis
#
3 acda838e Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 acda838e Christos Stavrakakis
# without modification, are permitted provided that the following
5 acda838e Christos Stavrakakis
# conditions are met:
6 acda838e Christos Stavrakakis
#
7 acda838e Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 acda838e Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 acda838e Christos Stavrakakis
#      disclaimer.
10 acda838e Christos Stavrakakis
#
11 acda838e Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 acda838e Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 acda838e Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 acda838e Christos Stavrakakis
#      provided with the distribution.
15 acda838e Christos Stavrakakis
#
16 acda838e Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 acda838e Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 acda838e Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 acda838e Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 acda838e Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 acda838e Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 acda838e Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 acda838e Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 acda838e Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 acda838e Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 acda838e Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 acda838e Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 acda838e Christos Stavrakakis
#
29 acda838e Christos Stavrakakis
# The views and conclusions contained in the software and
30 acda838e Christos Stavrakakis
# documentation are those of the authors and should not be
31 acda838e Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 acda838e Christos Stavrakakis
# or implied, of GRNET S.A.
33 acda838e Christos Stavrakakis
34 e4f484da Marios Kogias
from django.utils import simplejson as json
35 acda838e Christos Stavrakakis
from snf_django.utils.testing import BaseAPITest, mocked_quotaholder
36 ddffd973 Christos Stavrakakis
from synnefo.db.models import IPAddress, Network, Subnet, IPPoolTable
37 fde2c1f7 Christos Stavrakakis
from synnefo.db import models_factory as mf
38 e4f484da Marios Kogias
39 b9364b15 Marios Kogias
from mock import patch, Mock
40 acda838e Christos Stavrakakis
41 2cd55da6 Christos Stavrakakis
from synnefo.cyclades_settings import cyclades_services
42 2cd55da6 Christos Stavrakakis
from synnefo.lib.services import get_service_path
43 2cd55da6 Christos Stavrakakis
from synnefo.lib import join_urls
44 acda838e Christos Stavrakakis
45 2cd55da6 Christos Stavrakakis
46 cdd6fc06 Christos Stavrakakis
network_path = get_service_path(cyclades_services, "network", version="v2.0")
47 cdd6fc06 Christos Stavrakakis
URL = join_urls(network_path, "floatingips")
48 cdd6fc06 Christos Stavrakakis
NETWORKS_URL = join_urls(network_path, "networks")
49 cdd6fc06 Christos Stavrakakis
SERVERS_URL = join_urls(network_path, "servers")
50 acda838e Christos Stavrakakis
51 92d2d1ce Christos Stavrakakis
52 92d2d1ce Christos Stavrakakis
floating_ips = IPAddress.objects.filter(floating_ip=True)
53 9115d567 Christos Stavrakakis
54 acda838e Christos Stavrakakis
55 92d2d1ce Christos Stavrakakis
class FloatingIPAPITest(BaseAPITest):
56 fde2c1f7 Christos Stavrakakis
    def setUp(self):
57 fde2c1f7 Christos Stavrakakis
        self.pool = mf.NetworkWithSubnetFactory(floating_ip_pool=True,
58 fde2c1f7 Christos Stavrakakis
                                                public=True,
59 fde2c1f7 Christos Stavrakakis
                                                subnet__cidr="192.168.2.0/24",
60 fde2c1f7 Christos Stavrakakis
                                                subnet__gateway="192.168.2.1")
61 fde2c1f7 Christos Stavrakakis
62 acda838e Christos Stavrakakis
    def test_no_floating_ip(self):
63 acda838e Christos Stavrakakis
        response = self.get(URL)
64 acda838e Christos Stavrakakis
        self.assertSuccess(response)
65 9a73f94d Marios Kogias
        self.assertEqual(json.loads(response.content)["floatingips"], [])
66 acda838e Christos Stavrakakis
67 acda838e Christos Stavrakakis
    def test_list_ips(self):
68 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True)
69 acda838e Christos Stavrakakis
        with mocked_quotaholder():
70 acda838e Christos Stavrakakis
            response = self.get(URL, "user1")
71 acda838e Christos Stavrakakis
        self.assertSuccess(response)
72 9a73f94d Marios Kogias
        api_ip = json.loads(response.content)["floatingips"][0]
73 acda838e Christos Stavrakakis
        self.assertEqual(api_ip,
74 fde2c1f7 Christos Stavrakakis
                         {"instance_id": str(ip.nic.machine_id),
75 e4f484da Marios Kogias
                          "floating_ip_address": ip.address,
76 e4f484da Marios Kogias
                          "fixed_ip_address": None,
77 fde2c1f7 Christos Stavrakakis
                          "id": str(ip.id),
78 e4f484da Marios Kogias
                          "port_id": str(ip.nic.id),
79 e4f484da Marios Kogias
                          "floating_network_id": str(ip.network_id)})
80 acda838e Christos Stavrakakis
81 acda838e Christos Stavrakakis
    def test_get_ip(self):
82 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True)
83 acda838e Christos Stavrakakis
        with mocked_quotaholder():
84 acda838e Christos Stavrakakis
            response = self.get(URL + "/%s" % ip.id, "user1")
85 acda838e Christos Stavrakakis
        self.assertSuccess(response)
86 9a73f94d Marios Kogias
        api_ip = json.loads(response.content)["floatingip"]
87 acda838e Christos Stavrakakis
        self.assertEqual(api_ip,
88 fde2c1f7 Christos Stavrakakis
                         {"instance_id": str(ip.nic.machine_id),
89 e4f484da Marios Kogias
                          "floating_ip_address": ip.address,
90 e4f484da Marios Kogias
                          "fixed_ip_address": None,
91 fde2c1f7 Christos Stavrakakis
                          "id": str(ip.id),
92 e4f484da Marios Kogias
                          "port_id": str(ip.nic.id),
93 e4f484da Marios Kogias
                          "floating_network_id": str(ip.network_id)})
94 acda838e Christos Stavrakakis
95 acda838e Christos Stavrakakis
    def test_wrong_user(self):
96 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True)
97 fde2c1f7 Christos Stavrakakis
        response = self.delete(URL + "/%s" % ip.id, "user2")
98 acda838e Christos Stavrakakis
        self.assertItemNotFound(response)
99 acda838e Christos Stavrakakis
100 acda838e Christos Stavrakakis
    def test_deleted_ip(self):
101 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True,
102 fde2c1f7 Christos Stavrakakis
                                   deleted=True)
103 fde2c1f7 Christos Stavrakakis
        response = self.delete(URL + "/%s" % ip.id, "user1")
104 acda838e Christos Stavrakakis
        self.assertItemNotFound(response)
105 acda838e Christos Stavrakakis
106 acda838e Christos Stavrakakis
    def test_reserve(self):
107 e4f484da Marios Kogias
        request = {"floatingip": {
108 e4f484da Marios Kogias
            "floating_network_id": self.pool.id}
109 e4f484da Marios Kogias
            }
110 acda838e Christos Stavrakakis
        with mocked_quotaholder():
111 acda838e Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
112 acda838e Christos Stavrakakis
        self.assertSuccess(response)
113 9a73f94d Marios Kogias
        api_ip = json.loads(response.content, encoding="utf-8")["floatingip"]
114 92d2d1ce Christos Stavrakakis
        ip = floating_ips.get()
115 fde2c1f7 Christos Stavrakakis
        self.assertEqual(ip.address, "192.168.2.2")
116 fde2c1f7 Christos Stavrakakis
        self.assertEqual(ip.nic, None)
117 fde2c1f7 Christos Stavrakakis
        self.assertEqual(ip.network, self.pool)
118 e4f484da Marios Kogias
        self.assertEqual(api_ip,
119 e4f484da Marios Kogias
                         {"instance_id": None,
120 e4f484da Marios Kogias
                          "floating_ip_address": "192.168.2.2",
121 e4f484da Marios Kogias
                          "fixed_ip_address": None,
122 e4f484da Marios Kogias
                          "id": str(ip.id),
123 e4f484da Marios Kogias
                          "port_id": None,
124 e4f484da Marios Kogias
                          "floating_network_id": str(self.pool.id)})
125 acda838e Christos Stavrakakis
126 4edfc376 Christos Stavrakakis
    def test_reserve_empty_body(self):
127 4edfc376 Christos Stavrakakis
        """Test reserve FIP without specifying network."""
128 4edfc376 Christos Stavrakakis
        request = {"floatingip": {}}
129 4edfc376 Christos Stavrakakis
        # delete all pools..
130 ddffd973 Christos Stavrakakis
        IPPoolTable.objects.all().delete()
131 ddffd973 Christos Stavrakakis
        Subnet.objects.all().delete()
132 4edfc376 Christos Stavrakakis
        Network.objects.all().delete()
133 4edfc376 Christos Stavrakakis
        # CASE: no floating IP pool
134 4edfc376 Christos Stavrakakis
        with mocked_quotaholder():
135 4edfc376 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
136 4edfc376 Christos Stavrakakis
        self.assertConflict(response)
137 4edfc376 Christos Stavrakakis
        # CASE: Full floating IP pool
138 4edfc376 Christos Stavrakakis
        mf.NetworkWithSubnetFactory(floating_ip_pool=True, public=True,
139 4edfc376 Christos Stavrakakis
                                    subnet__pool__size=0)
140 4edfc376 Christos Stavrakakis
        with mocked_quotaholder():
141 4edfc376 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
142 4edfc376 Christos Stavrakakis
        self.assertConflict(response)
143 4edfc376 Christos Stavrakakis
        # CASE: Available floating IP pool
144 4edfc376 Christos Stavrakakis
        p1 = mf.NetworkWithSubnetFactory(floating_ip_pool=True, public=True,
145 4edfc376 Christos Stavrakakis
                                         subnet__cidr="192.168.2.0/30",
146 4edfc376 Christos Stavrakakis
                                         subnet__pool__size=1)
147 4edfc376 Christos Stavrakakis
        with mocked_quotaholder():
148 4edfc376 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
149 4edfc376 Christos Stavrakakis
        self.assertSuccess(response)
150 4edfc376 Christos Stavrakakis
        floating_ip = json.loads(response.content)["floatingip"]
151 4edfc376 Christos Stavrakakis
        db_fip = IPAddress.objects.get(id=floating_ip["id"])
152 4edfc376 Christos Stavrakakis
        self.assertEqual(db_fip.address, floating_ip["floating_ip_address"])
153 4edfc376 Christos Stavrakakis
        self.assertTrue(db_fip.floating_ip)
154 4edfc376 Christos Stavrakakis
        # Test that address is reserved
155 4edfc376 Christos Stavrakakis
        ip_pool = p1.get_ip_pools()[0]
156 4edfc376 Christos Stavrakakis
        self.assertFalse(ip_pool.is_available(db_fip.address))
157 4edfc376 Christos Stavrakakis
158 9e8be4fb Christos Stavrakakis
    def test_reserve_no_pool(self):
159 e4f484da Marios Kogias
        # Network is not a floating IP pool
160 e4f484da Marios Kogias
        pool2 = mf.NetworkWithSubnetFactory(floating_ip_pool=False,
161 e4f484da Marios Kogias
                                            public=True,
162 e4f484da Marios Kogias
                                            subnet__cidr="192.168.2.0/24",
163 e4f484da Marios Kogias
                                            subnet__gateway="192.168.2.1")
164 e4f484da Marios Kogias
        request = {"floatingip": {
165 e4f484da Marios Kogias
            'floating_network_id': pool2.id}
166 e4f484da Marios Kogias
            }
167 e4f484da Marios Kogias
        response = self.post(URL, "test_user", json.dumps(request), "json")
168 7421d45e Christos Stavrakakis
        self.assertConflict(response)
169 fde2c1f7 Christos Stavrakakis
170 9e8be4fb Christos Stavrakakis
        # Full network
171 0711e5aa Christos Stavrakakis
        net = mf.NetworkWithSubnetFactory(floating_ip_pool=True,
172 0711e5aa Christos Stavrakakis
                                          public=True,
173 0711e5aa Christos Stavrakakis
                                          subnet__cidr="192.168.2.0/31",
174 0711e5aa Christos Stavrakakis
                                          subnet__gateway="192.168.2.1",
175 0711e5aa Christos Stavrakakis
                                          subnet__pool__size=0)
176 e4f484da Marios Kogias
        request = {"floatingip": {
177 e4f484da Marios Kogias
            'floating_network_id': net.id}
178 e4f484da Marios Kogias
            }
179 fde2c1f7 Christos Stavrakakis
        response = self.post(URL, "test_user", json.dumps(request), "json")
180 fde2c1f7 Christos Stavrakakis
        self.assertConflict(response)
181 acda838e Christos Stavrakakis
182 a3d99af0 Christos Stavrakakis
    def test_reserve_with_address(self):
183 e4f484da Marios Kogias
        request = {"floatingip": {
184 e4f484da Marios Kogias
            "floating_network_id": self.pool.id,
185 e4f484da Marios Kogias
            "floating_ip_address": "192.168.2.10"}
186 e4f484da Marios Kogias
            }
187 a3d99af0 Christos Stavrakakis
        with mocked_quotaholder():
188 a3d99af0 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
189 a3d99af0 Christos Stavrakakis
        self.assertSuccess(response)
190 92d2d1ce Christos Stavrakakis
        ip = floating_ips.get()
191 9a73f94d Marios Kogias
        self.assertEqual(json.loads(response.content)["floatingip"],
192 e4f484da Marios Kogias
                         {"instance_id": None,
193 e4f484da Marios Kogias
                          "floating_ip_address": "192.168.2.10",
194 e4f484da Marios Kogias
                          "fixed_ip_address": None,
195 e4f484da Marios Kogias
                          "id": str(ip.id),
196 e4f484da Marios Kogias
                          "port_id": None,
197 e4f484da Marios Kogias
                          "floating_network_id": str(self.pool.id)})
198 a3d99af0 Christos Stavrakakis
199 a3d99af0 Christos Stavrakakis
        # Already reserved
200 a3d99af0 Christos Stavrakakis
        with mocked_quotaholder():
201 a3d99af0 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
202 a3d99af0 Christos Stavrakakis
        self.assertFault(response, 409, "conflict")
203 a3d99af0 Christos Stavrakakis
204 fde2c1f7 Christos Stavrakakis
        # Used by instance
205 fde2c1f7 Christos Stavrakakis
        self.pool.reserve_address("192.168.2.20")
206 e4f484da Marios Kogias
        request = {"floatingip": {
207 e4f484da Marios Kogias
            "floating_network_id": self.pool.id,
208 e4f484da Marios Kogias
            "floating_ip_address": "192.168.2.20"}
209 e4f484da Marios Kogias
            }
210 a3d99af0 Christos Stavrakakis
        with mocked_quotaholder():
211 a3d99af0 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
212 a3d99af0 Christos Stavrakakis
        self.assertFault(response, 409, "conflict")
213 a3d99af0 Christos Stavrakakis
214 a3d99af0 Christos Stavrakakis
        # Address out of pool
215 e4f484da Marios Kogias
        request = {"floatingip": {
216 e4f484da Marios Kogias
            "floating_network_id": self.pool.id,
217 e4f484da Marios Kogias
            "floating_ip_address": "192.168.3.5"}
218 e4f484da Marios Kogias
            }
219 a3d99af0 Christos Stavrakakis
        with mocked_quotaholder():
220 a3d99af0 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
221 a3d99af0 Christos Stavrakakis
        self.assertBadRequest(response)
222 a3d99af0 Christos Stavrakakis
223 9a73f94d Marios Kogias
    '''
224 e4f484da Marios Kogias
    @patch("synnefo.db.models.get_rapi_client")
225 e4f484da Marios Kogias
    def test_reserve_and_connect(self, mrapi):
226 e4f484da Marios Kogias
        vm = mf.VirtualMachineFactory(userid="test_user")
227 e4f484da Marios Kogias
        request = {"floatingip": {
228 e4f484da Marios Kogias
            "floating_network_id": self.pool.id,
229 e4f484da Marios Kogias
            "floating_ip_address": "192.168.2.12",
230 e4f484da Marios Kogias
            "device_id": vm.id}
231 e4f484da Marios Kogias
            }
232 e4f484da Marios Kogias
        response = self.post(URL, "test_user", json.dumps(request), "json")
233 e4f484da Marios Kogias
        ip = floating_ips.get()
234 9a73f94d Marios Kogias
        api_ip = json.loads(response.content, "utf-8")["floatingip"]
235 e4f484da Marios Kogias
        self.assertEqual(api_ip,
236 e4f484da Marios Kogias
                         {"instance_id": str(vm.id),
237 e4f484da Marios Kogias
                          "floating_ip_address": "192.168.2.12",
238 e4f484da Marios Kogias
                          "fixed_ip_address": None,
239 e4f484da Marios Kogias
                          "id": str(ip.id),
240 e4f484da Marios Kogias
                          "port_id": str(vm.nics.all()[0].id),
241 e4f484da Marios Kogias
                          "floating_network_id": str(self.pool.id)})
242 e4f484da Marios Kogias

243 e4f484da Marios Kogias
    @patch("synnefo.db.models.get_rapi_client")
244 e4f484da Marios Kogias
    def test_update_attach(self, mrapi):
245 e4f484da Marios Kogias
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True, nic=None)
246 e4f484da Marios Kogias
        vm = mf.VirtualMachineFactory(userid="user1")
247 e4f484da Marios Kogias
        request = {"floatingip": {
248 e4f484da Marios Kogias
            "device_id": vm.id}
249 e4f484da Marios Kogias
            }
250 e4f484da Marios Kogias
        with mocked_quotaholder():
251 e4f484da Marios Kogias
            response = self.put(URL + "/%s" % ip.id, "user1",
252 e4f484da Marios Kogias
                                json.dumps(request), "json")
253 e4f484da Marios Kogias
        self.assertEqual(response.status_code, 202)
254 e4f484da Marios Kogias

255 e4f484da Marios Kogias
    def test_update_attach_conflict(self):
256 e4f484da Marios Kogias
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True)
257 e4f484da Marios Kogias
        vm = mf.VirtualMachineFactory(userid="user1")
258 e4f484da Marios Kogias
        request = {"floatingip": {
259 e4f484da Marios Kogias
            "device_id": vm.id}
260 e4f484da Marios Kogias
            }
261 e4f484da Marios Kogias
        with mocked_quotaholder():
262 e4f484da Marios Kogias
            response = self.put(URL + "/%s" % ip.id, "user1",
263 e4f484da Marios Kogias
                                json.dumps(request), "json")
264 e4f484da Marios Kogias
        self.assertEqual(response.status_code, 409)
265 e4f484da Marios Kogias

266 e4f484da Marios Kogias
    @patch("synnefo.db.models.get_rapi_client")
267 e4f484da Marios Kogias
    def test_update_dettach(self, mrapi):
268 e4f484da Marios Kogias
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True)
269 e4f484da Marios Kogias
        request = {"floatingip": {
270 e4f484da Marios Kogias
            "device_id": None}
271 e4f484da Marios Kogias
            }
272 e4f484da Marios Kogias
        mrapi().ModifyInstance.return_value = 42
273 e4f484da Marios Kogias
        with mocked_quotaholder():
274 e4f484da Marios Kogias
            response = self.put(URL + "/%s" % ip.id, "user1",
275 e4f484da Marios Kogias
                                json.dumps(request), "json")
276 e4f484da Marios Kogias
        self.assertEqual(response.status_code, 202)
277 e4f484da Marios Kogias

278 e4f484da Marios Kogias
    def test_update_dettach_unassociated(self):
279 e4f484da Marios Kogias
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True, nic=None)
280 e4f484da Marios Kogias
        request = {"floatingip": {}}
281 e4f484da Marios Kogias
        with mocked_quotaholder():
282 e4f484da Marios Kogias
            response = self.put(URL + "/%s" % ip.id, "user1",
283 e4f484da Marios Kogias
                                json.dumps(request), "json")
284 e4f484da Marios Kogias
        self.assertEqual(response.status_code, 400)
285 e4f484da Marios Kogias

286 acda838e Christos Stavrakakis
    def test_release_in_use(self):
287 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True)
288 b9364b15 Marios Kogias
        vm = mf.VirtualMachineFactory(userid="user1")
289 b9364b15 Marios Kogias
        request = {"floatingip": {
290 b9364b15 Marios Kogias
            "device_id": vm.id}
291 b9364b15 Marios Kogias
            }
292 a95c82a9 Christos Stavrakakis
        with mocked_quotaholder():
293 b9364b15 Marios Kogias
            response = self.put(URL + "/%s" % ip.id, "user1",
294 b9364b15 Marios Kogias
                                json.dumps(request), "json")
295 b9364b15 Marios Kogias
        self.assertEqual(response.status_code, 409)
296 b9364b15 Marios Kogias

297 b9364b15 Marios Kogias
    @patch("synnefo.db.models.get_rapi_client")
298 b9364b15 Marios Kogias
    def test_update_dettach(self, mrapi):
299 b9364b15 Marios Kogias
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True)
300 b9364b15 Marios Kogias
        request = {"floatingip": {
301 b9364b15 Marios Kogias
            "device_id": None}
302 b9364b15 Marios Kogias
            }
303 b9364b15 Marios Kogias
        mrapi().ModifyInstance.return_value = 42
304 b9364b15 Marios Kogias
        with mocked_quotaholder():
305 b9364b15 Marios Kogias
            response = self.put(URL + "/%s" % ip.id, "user1",
306 b9364b15 Marios Kogias
                                json.dumps(request), "json")
307 a95c82a9 Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
308 b9364b15 Marios Kogias

309 b9364b15 Marios Kogias
    def test_update_dettach_unassociated(self):
310 b9364b15 Marios Kogias
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True, nic=None)
311 b9364b15 Marios Kogias
        request = {"floatingip": {}}
312 b9364b15 Marios Kogias
        with mocked_quotaholder():
313 b9364b15 Marios Kogias
            response = self.put(URL + "/%s" % ip.id, "user1",
314 b9364b15 Marios Kogias
                                json.dumps(request), "json")
315 b9364b15 Marios Kogias
        self.assertEqual(response.status_code, 400)
316 b9364b15 Marios Kogias

317 b9364b15 Marios Kogias
    def test_release_in_use(self):
318 b9364b15 Marios Kogias
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True)
319 b9364b15 Marios Kogias
        vm = ip.nic.machine
320 acda838e Christos Stavrakakis
        with mocked_quotaholder():
321 acda838e Christos Stavrakakis
            response = self.delete(URL + "/%s" % ip.id, ip.userid)
322 acda838e Christos Stavrakakis
        self.assertFault(response, 409, "conflict")
323 9a73f94d Marios Kogias
    '''
324 9a73f94d Marios Kogias
325 9a73f94d Marios Kogias
    def test_update(self):
326 9a73f94d Marios Kogias
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True, nic=None)
327 9a73f94d Marios Kogias
        with mocked_quotaholder():
328 9a73f94d Marios Kogias
            response = self.put(URL + "/%s" % ip.id, ip.userid)
329 9a73f94d Marios Kogias
        self.assertEqual(response.status_code, 501)
330 acda838e Christos Stavrakakis
331 acda838e Christos Stavrakakis
    def test_release(self):
332 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True, nic=None)
333 acda838e Christos Stavrakakis
        with mocked_quotaholder():
334 acda838e Christos Stavrakakis
            response = self.delete(URL + "/%s" % ip.id, ip.userid)
335 acda838e Christos Stavrakakis
        self.assertSuccess(response)
336 92d2d1ce Christos Stavrakakis
        ips_after = floating_ips.filter(id=ip.id)
337 acda838e Christos Stavrakakis
        self.assertEqual(len(ips_after), 0)
338 b9364b15 Marios Kogias
339 e57893cd Christos Stavrakakis
    @patch("synnefo.logic.backend", Mock())
340 e57893cd Christos Stavrakakis
    def test_delete_network_with_floating_ips(self):
341 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(userid="user1", floating_ip=True,
342 fde2c1f7 Christos Stavrakakis
                                   network=self.pool, nic=None)
343 fde2c1f7 Christos Stavrakakis
        # Mark the network as non-pubic to not get 403
344 fde2c1f7 Christos Stavrakakis
        network = ip.network
345 fde2c1f7 Christos Stavrakakis
        network.public = False
346 fde2c1f7 Christos Stavrakakis
        network.save()
347 8d5795b4 Christos Stavrakakis
        # Cannot remove network with floating IPs
348 e57893cd Christos Stavrakakis
        with mocked_quotaholder():
349 fde2c1f7 Christos Stavrakakis
            response = self.delete(NETWORKS_URL + "/%s" % self.pool.id,
350 fde2c1f7 Christos Stavrakakis
                                   self.pool.userid)
351 fde2c1f7 Christos Stavrakakis
        self.assertConflict(response)
352 e57893cd Christos Stavrakakis
        # But we can with only deleted Floating Ips
353 e57893cd Christos Stavrakakis
        ip.deleted = True
354 e57893cd Christos Stavrakakis
        ip.save()
355 e57893cd Christos Stavrakakis
        with mocked_quotaholder():
356 fde2c1f7 Christos Stavrakakis
            response = self.delete(NETWORKS_URL + "/%s" % self.pool.id,
357 fde2c1f7 Christos Stavrakakis
                                   self.pool.userid)
358 e57893cd Christos Stavrakakis
        self.assertSuccess(response)
359 e57893cd Christos Stavrakakis
360 b9364b15 Marios Kogias
'''
361 2cd55da6 Christos Stavrakakis
POOLS_URL = join_urls(compute_path, "os-floating-ip-pools")
362 7d368e73 Christos Stavrakakis

363 7d368e73 Christos Stavrakakis

364 92d2d1ce Christos Stavrakakis
class FloatingIPPoolsAPITest(BaseAPITest):
365 7d368e73 Christos Stavrakakis
    def test_no_pool(self):
366 7d368e73 Christos Stavrakakis
        response = self.get(POOLS_URL)
367 7d368e73 Christos Stavrakakis
        self.assertSuccess(response)
368 7d368e73 Christos Stavrakakis
        self.assertEqual(json.loads(response.content)["floating_ip_pools"], [])
369 7d368e73 Christos Stavrakakis

370 7d368e73 Christos Stavrakakis
    def test_list_pools(self):
371 fde2c1f7 Christos Stavrakakis
        net = mf.NetworkWithSubnetFactory(floating_ip_pool=True,
372 fde2c1f7 Christos Stavrakakis
                                          public=True,
373 fde2c1f7 Christos Stavrakakis
                                          subnet__cidr="192.168.2.0/30",
374 0711e5aa Christos Stavrakakis
                                          subnet__gateway="192.168.2.1",
375 0711e5aa Christos Stavrakakis
                                          subnet__pool__size=1,
376 0711e5aa Christos Stavrakakis
                                          subnet__pool__offset=1)
377 fde2c1f7 Christos Stavrakakis
        mf.NetworkWithSubnetFactory(public=True, deleted=True)
378 fde2c1f7 Christos Stavrakakis
        mf.NetworkWithSubnetFactory(public=False, deleted=False)
379 fde2c1f7 Christos Stavrakakis
        mf.NetworkWithSubnetFactory(public=True, floating_ip_pool=False)
380 7d368e73 Christos Stavrakakis
        response = self.get(POOLS_URL)
381 7d368e73 Christos Stavrakakis
        self.assertSuccess(response)
382 7d368e73 Christos Stavrakakis
        self.assertEqual(json.loads(response.content)["floating_ip_pools"],
383 0711e5aa Christos Stavrakakis
                         [{"name": str(net.id), "size": 1, "free": 1}])
384 a95c82a9 Christos Stavrakakis

385 a95c82a9 Christos Stavrakakis

386 92d2d1ce Christos Stavrakakis
class FloatingIPActionsTest(BaseAPITest):
387 a95c82a9 Christos Stavrakakis
    def setUp(self):
388 fde2c1f7 Christos Stavrakakis
        self.vm = VirtualMachineFactory()
389 fde2c1f7 Christos Stavrakakis
        self.vm.operstate = "ACTIVE"
390 fde2c1f7 Christos Stavrakakis
        self.vm.save()
391 a95c82a9 Christos Stavrakakis

392 a95c82a9 Christos Stavrakakis
    def test_bad_request(self):
393 2cd55da6 Christos Stavrakakis
        url = SERVERS_URL + "/%s/action" % self.vm.id
394 a95c82a9 Christos Stavrakakis
        response = self.post(url, self.vm.userid, json.dumps({}), "json")
395 a95c82a9 Christos Stavrakakis
        self.assertBadRequest(response)
396 a95c82a9 Christos Stavrakakis
        response = self.post(url, self.vm.userid,
397 a95c82a9 Christos Stavrakakis
                             json.dumps({"addFloatingIp": {}}),
398 a95c82a9 Christos Stavrakakis
                             "json")
399 a95c82a9 Christos Stavrakakis
        self.assertBadRequest(response)
400 a95c82a9 Christos Stavrakakis

401 a95c82a9 Christos Stavrakakis
    @patch('synnefo.logic.rapi_pool.GanetiRapiClient')
402 a95c82a9 Christos Stavrakakis
    def test_add_floating_ip(self, mock):
403 a95c82a9 Christos Stavrakakis
        # Not exists
404 2cd55da6 Christos Stavrakakis
        url = SERVERS_URL + "/%s/action" % self.vm.id
405 a95c82a9 Christos Stavrakakis
        request = {"addFloatingIp": {"address": "10.0.0.1"}}
406 a95c82a9 Christos Stavrakakis
        response = self.post(url, self.vm.userid, json.dumps(request), "json")
407 a95c82a9 Christos Stavrakakis
        self.assertItemNotFound(response)
408 a95c82a9 Christos Stavrakakis
        # In use
409 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(floating_ip=True, userid=self.vm.userid)
410 fde2c1f7 Christos Stavrakakis
        request = {"addFloatingIp": {"address": ip.address}}
411 a95c82a9 Christos Stavrakakis
        response = self.post(url, self.vm.userid, json.dumps(request), "json")
412 fde2c1f7 Christos Stavrakakis
        self.assertConflict(response)
413 a95c82a9 Christos Stavrakakis
        # Success
414 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(floating_ip=True, nic=None,
415 fde2c1f7 Christos Stavrakakis
                                   userid=self.vm.userid)
416 fde2c1f7 Christos Stavrakakis
        request = {"addFloatingIp": {"address": ip.address}}
417 f8675683 Christos Stavrakakis
        mock().ModifyInstance.return_value = 1
418 a95c82a9 Christos Stavrakakis
        response = self.post(url, self.vm.userid, json.dumps(request), "json")
419 a95c82a9 Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
420 fde2c1f7 Christos Stavrakakis
        ip_after = floating_ips.get(id=ip.id)
421 fde2c1f7 Christos Stavrakakis
        self.assertEqual(ip_after.nic.machine, self.vm)
422 fde2c1f7 Christos Stavrakakis
        nic = self.vm.nics.get()
423 c4ed6248 Christos Stavrakakis
        nic.state = "ACTIVE"
424 c4ed6248 Christos Stavrakakis
        nic.save()
425 78c165cf Christos Stavrakakis
        response = self.get(SERVERS_URL + "/%s" % self.vm.id,
426 78c165cf Christos Stavrakakis
                            self.vm.userid)
427 78c165cf Christos Stavrakakis
        self.assertSuccess(response)
428 78c165cf Christos Stavrakakis
        nic = json.loads(response.content)["server"]["attachments"][0]
429 78c165cf Christos Stavrakakis
        self.assertEqual(nic["OS-EXT-IPS:type"], "floating")
430 a95c82a9 Christos Stavrakakis

431 a95c82a9 Christos Stavrakakis
    @patch('synnefo.logic.rapi_pool.GanetiRapiClient')
432 a95c82a9 Christos Stavrakakis
    def test_remove_floating_ip(self, mock):
433 a95c82a9 Christos Stavrakakis
        # Not exists
434 2cd55da6 Christos Stavrakakis
        url = SERVERS_URL + "/%s/action" % self.vm.id
435 a95c82a9 Christos Stavrakakis
        request = {"removeFloatingIp": {"address": "10.0.0.1"}}
436 a95c82a9 Christos Stavrakakis
        response = self.post(url, self.vm.userid, json.dumps(request), "json")
437 fde2c1f7 Christos Stavrakakis
        self.assertBadRequest(response)
438 a95c82a9 Christos Stavrakakis
        # Not In Use
439 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(floating_ip=True, nic=None,
440 fde2c1f7 Christos Stavrakakis
                                   userid=self.vm.userid)
441 fde2c1f7 Christos Stavrakakis
        request = {"removeFloatingIp": {"address": ip.address}}
442 a95c82a9 Christos Stavrakakis
        response = self.post(url, self.vm.userid, json.dumps(request), "json")
443 fde2c1f7 Christos Stavrakakis
        self.assertBadRequest(response)
444 a95c82a9 Christos Stavrakakis
        # Success
445 fde2c1f7 Christos Stavrakakis
        ip = mf.IPv4AddressFactory(floating_ip=True,
446 fde2c1f7 Christos Stavrakakis
                                   userid=self.vm.userid, nic__machine=self.vm)
447 fde2c1f7 Christos Stavrakakis
        request = {"removeFloatingIp": {"address": ip.address}}
448 f8675683 Christos Stavrakakis
        mock().ModifyInstance.return_value = 2
449 a95c82a9 Christos Stavrakakis
        response = self.post(url, self.vm.userid, json.dumps(request), "json")
450 a95c82a9 Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
451 a95c82a9 Christos Stavrakakis
        # Yet used. Wait for the callbacks
452 fde2c1f7 Christos Stavrakakis
        ip_after = floating_ips.get(id=ip.id)
453 fde2c1f7 Christos Stavrakakis
        self.assertEqual(ip_after.nic.machine, self.vm)
454 e4f484da Marios Kogias
'''