Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (19.5 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 4edfc376 Christos Stavrakakis
from synnefo.db.models import IPAddress, Network
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 4edfc376 Christos Stavrakakis
        Network.objects.all().delete()
131 4edfc376 Christos Stavrakakis
        # CASE: no floating IP pool
132 4edfc376 Christos Stavrakakis
        with mocked_quotaholder():
133 4edfc376 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
134 4edfc376 Christos Stavrakakis
        self.assertConflict(response)
135 4edfc376 Christos Stavrakakis
        # CASE: Full floating IP pool
136 4edfc376 Christos Stavrakakis
        mf.NetworkWithSubnetFactory(floating_ip_pool=True, public=True,
137 4edfc376 Christos Stavrakakis
                                    subnet__pool__size=0)
138 4edfc376 Christos Stavrakakis
        with mocked_quotaholder():
139 4edfc376 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
140 4edfc376 Christos Stavrakakis
        self.assertConflict(response)
141 4edfc376 Christos Stavrakakis
        # CASE: Available floating IP pool
142 4edfc376 Christos Stavrakakis
        p1 = mf.NetworkWithSubnetFactory(floating_ip_pool=True, public=True,
143 4edfc376 Christos Stavrakakis
                                         subnet__cidr="192.168.2.0/30",
144 4edfc376 Christos Stavrakakis
                                         subnet__pool__size=1)
145 4edfc376 Christos Stavrakakis
        with mocked_quotaholder():
146 4edfc376 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
147 4edfc376 Christos Stavrakakis
        self.assertSuccess(response)
148 4edfc376 Christos Stavrakakis
        floating_ip = json.loads(response.content)["floatingip"]
149 4edfc376 Christos Stavrakakis
        db_fip = IPAddress.objects.get(id=floating_ip["id"])
150 4edfc376 Christos Stavrakakis
        self.assertEqual(db_fip.address, floating_ip["floating_ip_address"])
151 4edfc376 Christos Stavrakakis
        self.assertTrue(db_fip.floating_ip)
152 4edfc376 Christos Stavrakakis
        # Test that address is reserved
153 4edfc376 Christos Stavrakakis
        ip_pool = p1.get_ip_pools()[0]
154 4edfc376 Christos Stavrakakis
        self.assertFalse(ip_pool.is_available(db_fip.address))
155 4edfc376 Christos Stavrakakis
156 9e8be4fb Christos Stavrakakis
    def test_reserve_no_pool(self):
157 e4f484da Marios Kogias
        # Network is not a floating IP pool
158 e4f484da Marios Kogias
        pool2 = mf.NetworkWithSubnetFactory(floating_ip_pool=False,
159 e4f484da Marios Kogias
                                            public=True,
160 e4f484da Marios Kogias
                                            subnet__cidr="192.168.2.0/24",
161 e4f484da Marios Kogias
                                            subnet__gateway="192.168.2.1")
162 e4f484da Marios Kogias
        request = {"floatingip": {
163 e4f484da Marios Kogias
            'floating_network_id': pool2.id}
164 e4f484da Marios Kogias
            }
165 e4f484da Marios Kogias
        response = self.post(URL, "test_user", json.dumps(request), "json")
166 7421d45e Christos Stavrakakis
        self.assertConflict(response)
167 fde2c1f7 Christos Stavrakakis
168 9e8be4fb Christos Stavrakakis
        # Full network
169 0711e5aa Christos Stavrakakis
        net = mf.NetworkWithSubnetFactory(floating_ip_pool=True,
170 0711e5aa Christos Stavrakakis
                                          public=True,
171 0711e5aa Christos Stavrakakis
                                          subnet__cidr="192.168.2.0/31",
172 0711e5aa Christos Stavrakakis
                                          subnet__gateway="192.168.2.1",
173 0711e5aa Christos Stavrakakis
                                          subnet__pool__size=0)
174 e4f484da Marios Kogias
        request = {"floatingip": {
175 e4f484da Marios Kogias
            'floating_network_id': net.id}
176 e4f484da Marios Kogias
            }
177 fde2c1f7 Christos Stavrakakis
        response = self.post(URL, "test_user", json.dumps(request), "json")
178 fde2c1f7 Christos Stavrakakis
        self.assertConflict(response)
179 acda838e Christos Stavrakakis
180 a3d99af0 Christos Stavrakakis
    def test_reserve_with_address(self):
181 e4f484da Marios Kogias
        request = {"floatingip": {
182 e4f484da Marios Kogias
            "floating_network_id": self.pool.id,
183 e4f484da Marios Kogias
            "floating_ip_address": "192.168.2.10"}
184 e4f484da Marios Kogias
            }
185 a3d99af0 Christos Stavrakakis
        with mocked_quotaholder():
186 a3d99af0 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
187 a3d99af0 Christos Stavrakakis
        self.assertSuccess(response)
188 92d2d1ce Christos Stavrakakis
        ip = floating_ips.get()
189 9a73f94d Marios Kogias
        self.assertEqual(json.loads(response.content)["floatingip"],
190 e4f484da Marios Kogias
                         {"instance_id": None,
191 e4f484da Marios Kogias
                          "floating_ip_address": "192.168.2.10",
192 e4f484da Marios Kogias
                          "fixed_ip_address": None,
193 e4f484da Marios Kogias
                          "id": str(ip.id),
194 e4f484da Marios Kogias
                          "port_id": None,
195 e4f484da Marios Kogias
                          "floating_network_id": str(self.pool.id)})
196 a3d99af0 Christos Stavrakakis
197 a3d99af0 Christos Stavrakakis
        # Already reserved
198 a3d99af0 Christos Stavrakakis
        with mocked_quotaholder():
199 a3d99af0 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
200 a3d99af0 Christos Stavrakakis
        self.assertFault(response, 409, "conflict")
201 a3d99af0 Christos Stavrakakis
202 fde2c1f7 Christos Stavrakakis
        # Used by instance
203 fde2c1f7 Christos Stavrakakis
        self.pool.reserve_address("192.168.2.20")
204 e4f484da Marios Kogias
        request = {"floatingip": {
205 e4f484da Marios Kogias
            "floating_network_id": self.pool.id,
206 e4f484da Marios Kogias
            "floating_ip_address": "192.168.2.20"}
207 e4f484da Marios Kogias
            }
208 a3d99af0 Christos Stavrakakis
        with mocked_quotaholder():
209 a3d99af0 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
210 a3d99af0 Christos Stavrakakis
        self.assertFault(response, 409, "conflict")
211 a3d99af0 Christos Stavrakakis
212 a3d99af0 Christos Stavrakakis
        # Address out of pool
213 e4f484da Marios Kogias
        request = {"floatingip": {
214 e4f484da Marios Kogias
            "floating_network_id": self.pool.id,
215 e4f484da Marios Kogias
            "floating_ip_address": "192.168.3.5"}
216 e4f484da Marios Kogias
            }
217 a3d99af0 Christos Stavrakakis
        with mocked_quotaholder():
218 a3d99af0 Christos Stavrakakis
            response = self.post(URL, "test_user", json.dumps(request), "json")
219 a3d99af0 Christos Stavrakakis
        self.assertBadRequest(response)
220 a3d99af0 Christos Stavrakakis
221 9a73f94d Marios Kogias
    '''
222 e4f484da Marios Kogias
    @patch("synnefo.db.models.get_rapi_client")
223 e4f484da Marios Kogias
    def test_reserve_and_connect(self, mrapi):
224 e4f484da Marios Kogias
        vm = mf.VirtualMachineFactory(userid="test_user")
225 e4f484da Marios Kogias
        request = {"floatingip": {
226 e4f484da Marios Kogias
            "floating_network_id": self.pool.id,
227 e4f484da Marios Kogias
            "floating_ip_address": "192.168.2.12",
228 e4f484da Marios Kogias
            "device_id": vm.id}
229 e4f484da Marios Kogias
            }
230 e4f484da Marios Kogias
        response = self.post(URL, "test_user", json.dumps(request), "json")
231 e4f484da Marios Kogias
        ip = floating_ips.get()
232 9a73f94d Marios Kogias
        api_ip = json.loads(response.content, "utf-8")["floatingip"]
233 e4f484da Marios Kogias
        self.assertEqual(api_ip,
234 e4f484da Marios Kogias
                         {"instance_id": str(vm.id),
235 e4f484da Marios Kogias
                          "floating_ip_address": "192.168.2.12",
236 e4f484da Marios Kogias
                          "fixed_ip_address": None,
237 e4f484da Marios Kogias
                          "id": str(ip.id),
238 e4f484da Marios Kogias
                          "port_id": str(vm.nics.all()[0].id),
239 e4f484da Marios Kogias
                          "floating_network_id": str(self.pool.id)})
240 e4f484da Marios Kogias

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

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

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

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

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

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

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

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

361 7d368e73 Christos Stavrakakis

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

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

383 a95c82a9 Christos Stavrakakis

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

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

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

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