Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / tests / servers.py @ 9dcfad23

History | View | Annotate | Download (35.3 kB)

1 039e3e61 Christos Stavrakakis
# Copyright 2012 GRNET S.A. All rights reserved.
2 039e3e61 Christos Stavrakakis
#
3 039e3e61 Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 039e3e61 Christos Stavrakakis
# without modification, are permitted provided that the following
5 039e3e61 Christos Stavrakakis
# conditions are met:
6 039e3e61 Christos Stavrakakis
#
7 039e3e61 Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 039e3e61 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 039e3e61 Christos Stavrakakis
#      disclaimer.
10 039e3e61 Christos Stavrakakis
#
11 039e3e61 Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 039e3e61 Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 039e3e61 Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 039e3e61 Christos Stavrakakis
#      provided with the distribution.
15 039e3e61 Christos Stavrakakis
#
16 039e3e61 Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 039e3e61 Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 039e3e61 Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 039e3e61 Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 039e3e61 Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 039e3e61 Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 039e3e61 Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 039e3e61 Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 039e3e61 Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 039e3e61 Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 039e3e61 Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 039e3e61 Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 039e3e61 Christos Stavrakakis
#
29 039e3e61 Christos Stavrakakis
# The views and conclusions contained in the software and
30 039e3e61 Christos Stavrakakis
# documentation are those of the authors and should not be
31 039e3e61 Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 039e3e61 Christos Stavrakakis
# or implied, of GRNET S.A.
33 039e3e61 Christos Stavrakakis
34 039e3e61 Christos Stavrakakis
import json
35 cb66110b Christos Stavrakakis
from copy import deepcopy
36 039e3e61 Christos Stavrakakis
37 41a7fae7 Christos Stavrakakis
from snf_django.utils.testing import (BaseAPITest, mocked_quotaholder,
38 41a7fae7 Christos Stavrakakis
                                      override_settings)
39 816d7588 Christos Stavrakakis
from synnefo.db.models import (VirtualMachine, VirtualMachineMetadata,
40 816d7588 Christos Stavrakakis
                               FloatingIP)
41 039e3e61 Christos Stavrakakis
from synnefo.db import models_factory as mfactory
42 039e3e61 Christos Stavrakakis
from synnefo.logic.utils import get_rsapi_state
43 a26e5a4d Georgios D. Tsoukalas
from synnefo.cyclades_settings import cyclades_services
44 a26e5a4d Georgios D. Tsoukalas
from synnefo.lib.services import get_service_path
45 a26e5a4d Georgios D. Tsoukalas
from synnefo.lib import join_urls
46 7e82ac17 Christos Stavrakakis
from django.conf import settings
47 f2080d16 Christos Stavrakakis
from synnefo.logic.rapi import GanetiApiError
48 039e3e61 Christos Stavrakakis
49 816d7588 Christos Stavrakakis
from mock import patch, Mock
50 039e3e61 Christos Stavrakakis
51 039e3e61 Christos Stavrakakis
52 a26e5a4d Georgios D. Tsoukalas
class ComputeAPITest(BaseAPITest):
53 2cd55da6 Christos Stavrakakis
    def __init__(self, *args, **kwargs):
54 2cd55da6 Christos Stavrakakis
        super(ComputeAPITest, self).__init__(*args, **kwargs)
55 a26e5a4d Georgios D. Tsoukalas
        self.compute_path = get_service_path(cyclades_services, 'compute',
56 a26e5a4d Georgios D. Tsoukalas
                                             version='v2.0')
57 41a7fae7 Christos Stavrakakis
58 a26e5a4d Georgios D. Tsoukalas
    def myget(self, path, *args, **kwargs):
59 a26e5a4d Georgios D. Tsoukalas
        path = join_urls(self.compute_path, path)
60 a26e5a4d Georgios D. Tsoukalas
        return self.get(path, *args, **kwargs)
61 a26e5a4d Georgios D. Tsoukalas
62 a26e5a4d Georgios D. Tsoukalas
    def myput(self, path, *args, **kwargs):
63 a26e5a4d Georgios D. Tsoukalas
        path = join_urls(self.compute_path, path)
64 a26e5a4d Georgios D. Tsoukalas
        return self.put(path, *args, **kwargs)
65 a26e5a4d Georgios D. Tsoukalas
66 a26e5a4d Georgios D. Tsoukalas
    def mypost(self, path, *args, **kwargs):
67 a26e5a4d Georgios D. Tsoukalas
        path = join_urls(self.compute_path, path)
68 a26e5a4d Georgios D. Tsoukalas
        return self.post(path, *args, **kwargs)
69 a26e5a4d Georgios D. Tsoukalas
70 a26e5a4d Georgios D. Tsoukalas
    def mydelete(self, path, *args, **kwargs):
71 a26e5a4d Georgios D. Tsoukalas
        path = join_urls(self.compute_path, path)
72 a26e5a4d Georgios D. Tsoukalas
        return self.delete(path, *args, **kwargs)
73 a26e5a4d Georgios D. Tsoukalas
74 a26e5a4d Georgios D. Tsoukalas
75 a26e5a4d Georgios D. Tsoukalas
class ServerAPITest(ComputeAPITest):
76 039e3e61 Christos Stavrakakis
    def setUp(self):
77 039e3e61 Christos Stavrakakis
        self.user1 = 'user1'
78 039e3e61 Christos Stavrakakis
        self.user2 = 'user2'
79 039e3e61 Christos Stavrakakis
        self.vm1 = mfactory.VirtualMachineFactory(userid=self.user1)
80 039e3e61 Christos Stavrakakis
        self.vm2 = mfactory.VirtualMachineFactory(userid=self.user2)
81 039e3e61 Christos Stavrakakis
        self.vm3 = mfactory.VirtualMachineFactory(deleted=True,
82 039e3e61 Christos Stavrakakis
                                                  userid=self.user1)
83 039e3e61 Christos Stavrakakis
        self.vm4 = mfactory.VirtualMachineFactory(userid=self.user2)
84 039e3e61 Christos Stavrakakis
85 039e3e61 Christos Stavrakakis
    def test_server_list_1(self):
86 039e3e61 Christos Stavrakakis
        """Test if the expected list of servers is returned."""
87 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers')
88 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
89 2d04422f Christos Stavrakakis
        servers = json.loads(response.content)['servers']
90 039e3e61 Christos Stavrakakis
        self.assertEqual(servers, [])
91 039e3e61 Christos Stavrakakis
92 039e3e61 Christos Stavrakakis
    def test_server_list_2(self):
93 039e3e61 Christos Stavrakakis
        """Test if the expected list of servers is returned."""
94 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers', self.user1)
95 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
96 2d04422f Christos Stavrakakis
        servers = json.loads(response.content)['servers']
97 039e3e61 Christos Stavrakakis
        db_server = self.vm1
98 1b696c26 Christos Stavrakakis
        server = servers[0]
99 1b696c26 Christos Stavrakakis
        self.assertEqual(server["name"], db_server.name)
100 1b696c26 Christos Stavrakakis
        self.assertEqual(server["id"], db_server.id)
101 039e3e61 Christos Stavrakakis
102 039e3e61 Christos Stavrakakis
    def test_server_list_detail(self):
103 039e3e61 Christos Stavrakakis
        """Test if the servers list details are returned."""
104 039e3e61 Christos Stavrakakis
        user = self.user2
105 039e3e61 Christos Stavrakakis
        user_vms = {self.vm2.id: self.vm2,
106 039e3e61 Christos Stavrakakis
                    self.vm4.id: self.vm4}
107 039e3e61 Christos Stavrakakis
108 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/detail', user)
109 2d04422f Christos Stavrakakis
        servers = json.loads(response.content)['servers']
110 039e3e61 Christos Stavrakakis
        self.assertEqual(len(servers), len(user_vms))
111 039e3e61 Christos Stavrakakis
        for api_vm in servers:
112 039e3e61 Christos Stavrakakis
            db_vm = user_vms[api_vm['id']]
113 1b696c26 Christos Stavrakakis
            self.assertEqual(api_vm['flavor']["id"], db_vm.flavor.id)
114 039e3e61 Christos Stavrakakis
            self.assertEqual(api_vm['hostId'], db_vm.hostid)
115 039e3e61 Christos Stavrakakis
            self.assertEqual(api_vm['id'], db_vm.id)
116 1b696c26 Christos Stavrakakis
            self.assertEqual(api_vm['image']["id"], db_vm.imageid)
117 039e3e61 Christos Stavrakakis
            self.assertEqual(api_vm['name'], db_vm.name)
118 039e3e61 Christos Stavrakakis
            self.assertEqual(api_vm['status'], get_rsapi_state(db_vm))
119 039e3e61 Christos Stavrakakis
            self.assertSuccess(response)
120 039e3e61 Christos Stavrakakis
121 039e3e61 Christos Stavrakakis
    def test_server_detail(self):
122 039e3e61 Christos Stavrakakis
        """Test if a server details are returned."""
123 039e3e61 Christos Stavrakakis
        db_vm = self.vm2
124 039e3e61 Christos Stavrakakis
        user = self.vm2.userid
125 039e3e61 Christos Stavrakakis
        net = mfactory.NetworkFactory()
126 1f638a85 Christos Stavrakakis
        nic = mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net,
127 e368ad39 Christos Stavrakakis
                                               ipv6="::babe")
128 039e3e61 Christos Stavrakakis
129 039e3e61 Christos Stavrakakis
        db_vm_meta = mfactory.VirtualMachineMetadataFactory(vm=db_vm)
130 039e3e61 Christos Stavrakakis
131 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d' % db_vm.id, user)
132 039e3e61 Christos Stavrakakis
        server = json.loads(response.content)['server']
133 039e3e61 Christos Stavrakakis
134 1b696c26 Christos Stavrakakis
        self.assertEqual(server['flavor']["id"], db_vm.flavor.id)
135 039e3e61 Christos Stavrakakis
        self.assertEqual(server['hostId'], db_vm.hostid)
136 039e3e61 Christos Stavrakakis
        self.assertEqual(server['id'], db_vm.id)
137 1b696c26 Christos Stavrakakis
        self.assertEqual(server['image']["id"], db_vm.imageid)
138 039e3e61 Christos Stavrakakis
        self.assertEqual(server['name'], db_vm.name)
139 039e3e61 Christos Stavrakakis
        self.assertEqual(server['status'], get_rsapi_state(db_vm))
140 2d04422f Christos Stavrakakis
        api_nic = server['attachments'][0]
141 039e3e61 Christos Stavrakakis
        self.assertEqual(api_nic['network_id'], str(net.id))
142 039e3e61 Christos Stavrakakis
        self.assertEqual(api_nic['mac_address'], nic.mac)
143 039e3e61 Christos Stavrakakis
        self.assertEqual(api_nic['firewallProfile'], nic.firewall_profile)
144 039e3e61 Christos Stavrakakis
        self.assertEqual(api_nic['ipv4'], nic.ipv4)
145 039e3e61 Christos Stavrakakis
        self.assertEqual(api_nic['ipv6'], nic.ipv6)
146 e368ad39 Christos Stavrakakis
        self.assertEqual(api_nic['OS-EXT-IPS:type'], "fixed")
147 039e3e61 Christos Stavrakakis
        self.assertEqual(api_nic['id'], 'nic-%s-%s' % (db_vm.id, nic.index))
148 1f638a85 Christos Stavrakakis
        api_address = server["addresses"]
149 e368ad39 Christos Stavrakakis
        self.assertEqual(api_address[str(net.id)], [
150 e368ad39 Christos Stavrakakis
            {"version": 4, "addr": nic.ipv4, "OS-EXT-IPS:type": "fixed"},
151 e368ad39 Christos Stavrakakis
            {"version": 6, "addr": nic.ipv6, "OS-EXT-IPS:type": "fixed"}
152 e368ad39 Christos Stavrakakis
        ])
153 039e3e61 Christos Stavrakakis
154 2d04422f Christos Stavrakakis
        metadata = server['metadata']
155 039e3e61 Christos Stavrakakis
        self.assertEqual(len(metadata), 1)
156 039e3e61 Christos Stavrakakis
        self.assertEqual(metadata[db_vm_meta.meta_key], db_vm_meta.meta_value)
157 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
158 039e3e61 Christos Stavrakakis
159 7e82ac17 Christos Stavrakakis
    def test_server_fqdn(self):
160 7e82ac17 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
161 7e82ac17 Christos Stavrakakis
        with override_settings(settings,
162 7e82ac17 Christos Stavrakakis
                               CYCLADES_SERVERS_FQDN="vm.example.org"):
163 7e82ac17 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
164 7e82ac17 Christos Stavrakakis
            server = json.loads(response.content)['server']
165 7e82ac17 Christos Stavrakakis
            self.assertEqual(server["SNF:fqdn"], "vm.example.org")
166 e368ad39 Christos Stavrakakis
        with override_settings(settings, CYCLADES_SERVERS_FQDN=
167 e368ad39 Christos Stavrakakis
                               "snf-%(id)s.vm.example.org"):
168 7e82ac17 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
169 7e82ac17 Christos Stavrakakis
            server = json.loads(response.content)['server']
170 e368ad39 Christos Stavrakakis
            self.assertEqual(server["SNF:fqdn"],
171 e368ad39 Christos Stavrakakis
                             "snf-%d.vm.example.org" % vm.id)
172 7e82ac17 Christos Stavrakakis
        with override_settings(settings,
173 e368ad39 Christos Stavrakakis
                               CYCLADES_SERVERS_FQDN=
174 e368ad39 Christos Stavrakakis
                               "snf-%(id)s.vm-%(id)s.example.org"):
175 7e82ac17 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
176 7e82ac17 Christos Stavrakakis
            server = json.loads(response.content)['server']
177 7e82ac17 Christos Stavrakakis
            self.assertEqual(server["SNF:fqdn"], "snf-%d.vm-%d.example.org" %
178 7e82ac17 Christos Stavrakakis
                             (vm.id, vm.id))
179 7e82ac17 Christos Stavrakakis
        # No setting, no NICs
180 7e82ac17 Christos Stavrakakis
        with override_settings(settings,
181 7e82ac17 Christos Stavrakakis
                               CYCLADES_SERVERS_FQDN=None):
182 7e82ac17 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
183 7e82ac17 Christos Stavrakakis
            server = json.loads(response.content)['server']
184 7e82ac17 Christos Stavrakakis
            self.assertEqual(server["SNF:fqdn"], "")
185 7e82ac17 Christos Stavrakakis
186 7e82ac17 Christos Stavrakakis
        # IPv6 NIC
187 7e82ac17 Christos Stavrakakis
        nic = mfactory.NetworkInterfaceFactory(machine=vm, ipv4=None,
188 7e82ac17 Christos Stavrakakis
                                               ipv6="babe::", state="ACTIVE",
189 7e82ac17 Christos Stavrakakis
                                               network__public=True)
190 7e82ac17 Christos Stavrakakis
        with override_settings(settings,
191 7e82ac17 Christos Stavrakakis
                               CYCLADES_SERVERS_FQDN=None):
192 7e82ac17 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
193 7e82ac17 Christos Stavrakakis
            server = json.loads(response.content)['server']
194 7e82ac17 Christos Stavrakakis
            self.assertEqual(server["SNF:fqdn"], nic.ipv6)
195 7e82ac17 Christos Stavrakakis
196 7e82ac17 Christos Stavrakakis
        # IPv4 NIC
197 e368ad39 Christos Stavrakakis
        nic = mfactory.NetworkInterfaceFactory(machine=vm,
198 e368ad39 Christos Stavrakakis
                                               network__public=True,
199 e368ad39 Christos Stavrakakis
                                               state="ACTIVE")
200 7e82ac17 Christos Stavrakakis
        with override_settings(settings,
201 7e82ac17 Christos Stavrakakis
                               CYCLADES_SERVERS_FQDN=None):
202 7e82ac17 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
203 7e82ac17 Christos Stavrakakis
            server = json.loads(response.content)['server']
204 7e82ac17 Christos Stavrakakis
            self.assertEqual(server["SNF:fqdn"], nic.ipv4)
205 7e82ac17 Christos Stavrakakis
206 2522e489 Christos Stavrakakis
    def test_server_port_forwarding(self):
207 2522e489 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
208 2522e489 Christos Stavrakakis
        ports = {
209 2522e489 Christos Stavrakakis
            22: ("foo", 61000),
210 2522e489 Christos Stavrakakis
            80: lambda ip, id, fqdn, user: ("bar", 61001)}
211 2522e489 Christos Stavrakakis
        with override_settings(settings,
212 2522e489 Christos Stavrakakis
                               CYCLADES_PORT_FORWARDING=ports):
213 2522e489 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
214 2522e489 Christos Stavrakakis
            server = json.loads(response.content)['server']
215 2522e489 Christos Stavrakakis
            self.assertEqual(server["SNF:port_forwarding"],
216 2522e489 Christos Stavrakakis
                             {"22": {"host": "foo", "port": "61000"},
217 2522e489 Christos Stavrakakis
                              "80": {"host": "bar", "port": "61001"}})
218 2522e489 Christos Stavrakakis
219 2522e489 Christos Stavrakakis
        def _port_from_ip(ip, base):
220 2522e489 Christos Stavrakakis
            fields = ip.split('.', 4)
221 2522e489 Christos Stavrakakis
            return (base + 256*int(fields[2]) + int(fields[3]))
222 2522e489 Christos Stavrakakis
223 2522e489 Christos Stavrakakis
        ports = {
224 2522e489 Christos Stavrakakis
            22: lambda ip, id, fqdn, user:
225 2522e489 Christos Stavrakakis
            ip and ("gate", _port_from_ip(ip, 10000)) or None}
226 2522e489 Christos Stavrakakis
        with override_settings(settings,
227 2522e489 Christos Stavrakakis
                               CYCLADES_PORT_FORWARDING=ports):
228 2522e489 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
229 2522e489 Christos Stavrakakis
            server = json.loads(response.content)['server']
230 2522e489 Christos Stavrakakis
            self.assertEqual(server["SNF:port_forwarding"], {})
231 2522e489 Christos Stavrakakis
232 2522e489 Christos Stavrakakis
        mfactory.NetworkInterfaceFactory(machine=vm, ipv4="192.168.2.2",
233 2522e489 Christos Stavrakakis
                                         network__public=True)
234 2522e489 Christos Stavrakakis
        with override_settings(settings,
235 2522e489 Christos Stavrakakis
                               CYCLADES_PORT_FORWARDING=ports):
236 2522e489 Christos Stavrakakis
            response = self.myget("servers/%d" % vm.id, vm.userid)
237 2522e489 Christos Stavrakakis
            server = json.loads(response.content)['server']
238 2522e489 Christos Stavrakakis
            self.assertEqual(server["SNF:port_forwarding"],
239 2522e489 Christos Stavrakakis
                             {"22": {"host": "gate", "port": "10514"}})
240 2522e489 Christos Stavrakakis
241 939d71dd Christos Stavrakakis
    def test_server_building_nics(self):
242 939d71dd Christos Stavrakakis
        db_vm = self.vm2
243 939d71dd Christos Stavrakakis
        user = self.vm2.userid
244 939d71dd Christos Stavrakakis
        net1 = mfactory.NetworkFactory()
245 939d71dd Christos Stavrakakis
        net2 = mfactory.NetworkFactory()
246 939d71dd Christos Stavrakakis
        net3 = mfactory.NetworkFactory()
247 939d71dd Christos Stavrakakis
        mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net1,
248 939d71dd Christos Stavrakakis
                                         state="BUILDING")
249 939d71dd Christos Stavrakakis
        nic2 = mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net2,
250 939d71dd Christos Stavrakakis
                                                state="ACTIVE")
251 939d71dd Christos Stavrakakis
        mfactory.NetworkInterfaceFactory(machine=self.vm2, network=net3,
252 939d71dd Christos Stavrakakis
                                         state="BUILDING")
253 939d71dd Christos Stavrakakis
254 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d' % db_vm.id, user)
255 939d71dd Christos Stavrakakis
        server = json.loads(response.content)['server']
256 2d04422f Christos Stavrakakis
        nics = server["attachments"]
257 939d71dd Christos Stavrakakis
        self.assertEqual(len(nics), 1)
258 939d71dd Christos Stavrakakis
        self.assertEqual(nics[0]["network_id"], str(nic2.network_id))
259 939d71dd Christos Stavrakakis
260 039e3e61 Christos Stavrakakis
    def test_noauthorized(self):
261 039e3e61 Christos Stavrakakis
        """Test 404 for detail of other user vm"""
262 039e3e61 Christos Stavrakakis
        db_vm = self.vm2
263 039e3e61 Christos Stavrakakis
264 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d' % db_vm.id, 'wrong_user')
265 039e3e61 Christos Stavrakakis
        self.assertItemNotFound(response)
266 039e3e61 Christos Stavrakakis
267 039e3e61 Christos Stavrakakis
    def test_wrong_server(self):
268 039e3e61 Christos Stavrakakis
        """Test 404 response if server does not exist."""
269 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d' % 5000)
270 039e3e61 Christos Stavrakakis
        self.assertItemNotFound(response)
271 039e3e61 Christos Stavrakakis
272 039e3e61 Christos Stavrakakis
    def test_create_server_empty(self):
273 039e3e61 Christos Stavrakakis
        """Test if the create server call returns a 400 badRequest if
274 039e3e61 Christos Stavrakakis
           no attributes are specified."""
275 039e3e61 Christos Stavrakakis
276 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers', params={})
277 039e3e61 Christos Stavrakakis
        self.assertBadRequest(response)
278 039e3e61 Christos Stavrakakis
279 039e3e61 Christos Stavrakakis
    def test_rename_server(self):
280 039e3e61 Christos Stavrakakis
        vm = self.vm2
281 039e3e61 Christos Stavrakakis
        request = {'server': {'name': 'new_name'}}
282 a26e5a4d Georgios D. Tsoukalas
        response = self.myput('servers/%d' % vm.id, vm.userid,
283 a26e5a4d Georgios D. Tsoukalas
                              json.dumps(request), 'json')
284 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
285 039e3e61 Christos Stavrakakis
        self.assertEqual(VirtualMachine.objects.get(id=vm.id).name, "new_name")
286 039e3e61 Christos Stavrakakis
287 a3accf03 Georgios D. Tsoukalas
    def test_catch_wrong_api_paths(self):
288 a3accf03 Georgios D. Tsoukalas
        response = self.myget('nonexistent')
289 a3accf03 Georgios D. Tsoukalas
        self.assertEqual(response.status_code, 400)
290 a3accf03 Georgios D. Tsoukalas
        try:
291 e368ad39 Christos Stavrakakis
            json.loads(response.content)
292 a3accf03 Georgios D. Tsoukalas
        except ValueError:
293 a3accf03 Georgios D. Tsoukalas
            self.assertTrue(False)
294 a3accf03 Georgios D. Tsoukalas
295 16437e4d Kostas Papadimitriou
    def test_method_not_allowed(self, *args):
296 16437e4d Kostas Papadimitriou
        # /servers/ allows only POST, GET
297 16437e4d Kostas Papadimitriou
        response = self.myput('servers', '', '')
298 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
299 16437e4d Kostas Papadimitriou
        response = self.mydelete('servers')
300 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
301 16437e4d Kostas Papadimitriou
302 16437e4d Kostas Papadimitriou
        # /servers/<srvid>/ allows only GET, PUT, DELETE
303 16437e4d Kostas Papadimitriou
        response = self.mypost("servers/42")
304 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
305 16437e4d Kostas Papadimitriou
306 16437e4d Kostas Papadimitriou
        # /imags/<srvid>/metadata/ allows only POST, GET
307 16437e4d Kostas Papadimitriou
        response = self.myput('servers/42/metadata', '', '')
308 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
309 16437e4d Kostas Papadimitriou
        response = self.mydelete('servers/42/metadata')
310 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
311 16437e4d Kostas Papadimitriou
312 16437e4d Kostas Papadimitriou
        # /imags/<srvid>/metadata/ allows only POST, GET
313 16437e4d Kostas Papadimitriou
        response = self.myput('servers/42/metadata', '', '')
314 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
315 16437e4d Kostas Papadimitriou
        response = self.mydelete('servers/42/metadata')
316 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
317 16437e4d Kostas Papadimitriou
318 16437e4d Kostas Papadimitriou
        # /imags/<srvid>/metadata/<key> allows only PUT, GET, DELETE
319 16437e4d Kostas Papadimitriou
        response = self.mypost('servers/42/metadata/foo')
320 16437e4d Kostas Papadimitriou
        self.assertMethodNotAllowed(response)
321 16437e4d Kostas Papadimitriou
322 039e3e61 Christos Stavrakakis
323 cb66110b Christos Stavrakakis
fixed_image = Mock()
324 cb66110b Christos Stavrakakis
fixed_image.return_value = {'location': 'pithos://foo',
325 cb66110b Christos Stavrakakis
                            'checksum': '1234',
326 cb66110b Christos Stavrakakis
                            "id": 1,
327 cb66110b Christos Stavrakakis
                            "name": "test_image",
328 dfcece01 Christos Stavrakakis
                            "size": "41242",
329 cb66110b Christos Stavrakakis
                            'disk_format': 'diskdump'}
330 cb66110b Christos Stavrakakis
331 cb66110b Christos Stavrakakis
332 cb66110b Christos Stavrakakis
@patch('synnefo.api.util.get_image', fixed_image)
333 039e3e61 Christos Stavrakakis
@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
334 a26e5a4d Georgios D. Tsoukalas
class ServerCreateAPITest(ComputeAPITest):
335 cb66110b Christos Stavrakakis
    def setUp(self):
336 cb66110b Christos Stavrakakis
        self.flavor = mfactory.FlavorFactory()
337 039e3e61 Christos Stavrakakis
        # Create public network and backend
338 cb66110b Christos Stavrakakis
        self.network = mfactory.NetworkFactory(public=True)
339 cb66110b Christos Stavrakakis
        self.backend = mfactory.BackendFactory()
340 cb66110b Christos Stavrakakis
        mfactory.BackendNetworkFactory(network=self.network,
341 cb66110b Christos Stavrakakis
                                       backend=self.backend,
342 cb66110b Christos Stavrakakis
                                       operstate="ACTIVE")
343 cb66110b Christos Stavrakakis
        self.request = {
344 e368ad39 Christos Stavrakakis
            "server": {
345 e368ad39 Christos Stavrakakis
                "name": "new-server-test",
346 e368ad39 Christos Stavrakakis
                "userid": "test_user",
347 e368ad39 Christos Stavrakakis
                "imageRef": 1,
348 e368ad39 Christos Stavrakakis
                "flavorRef": self.flavor.id,
349 e368ad39 Christos Stavrakakis
                "metadata": {
350 e368ad39 Christos Stavrakakis
                    "My Server Name": "Apache1"
351 e368ad39 Christos Stavrakakis
                },
352 e368ad39 Christos Stavrakakis
                "personality": []
353 e368ad39 Christos Stavrakakis
            }
354 039e3e61 Christos Stavrakakis
        }
355 cb66110b Christos Stavrakakis
356 cb66110b Christos Stavrakakis
    def test_create_server(self, mrapi):
357 cb66110b Christos Stavrakakis
        """Test if the create server call returns the expected response
358 cb66110b Christos Stavrakakis
           if a valid request has been speficied."""
359 cb66110b Christos Stavrakakis
360 cb66110b Christos Stavrakakis
        mrapi().CreateInstance.return_value = 12
361 cb66110b Christos Stavrakakis
        with override_settings(settings, DEFAULT_INSTANCE_NETWORKS=[]):
362 cb66110b Christos Stavrakakis
            with mocked_quotaholder():
363 2cd55da6 Christos Stavrakakis
                response = self.mypost('servers', 'test_user',
364 cb66110b Christos Stavrakakis
                                       json.dumps(self.request), 'json')
365 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
366 039e3e61 Christos Stavrakakis
        mrapi().CreateInstance.assert_called_once()
367 039e3e61 Christos Stavrakakis
368 039e3e61 Christos Stavrakakis
        api_server = json.loads(response.content)['server']
369 039e3e61 Christos Stavrakakis
        self.assertEqual(api_server['status'], "BUILD")
370 039e3e61 Christos Stavrakakis
        self.assertEqual(api_server['progress'], 0)
371 2d04422f Christos Stavrakakis
        self.assertEqual(api_server['metadata'],
372 e368ad39 Christos Stavrakakis
                         {"My Server Name":  "Apache1"})
373 039e3e61 Christos Stavrakakis
        self.assertTrue('adminPass' in api_server)
374 039e3e61 Christos Stavrakakis
375 039e3e61 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(userid='test_user')
376 039e3e61 Christos Stavrakakis
        self.assertEqual(api_server['name'], db_vm.name)
377 039e3e61 Christos Stavrakakis
        self.assertEqual(api_server['status'], db_vm.operstate)
378 039e3e61 Christos Stavrakakis
379 6dafedf6 Christos Stavrakakis
        # Test drained flag in Network:
380 cb66110b Christos Stavrakakis
        self.network.drained = True
381 cb66110b Christos Stavrakakis
        self.network.save()
382 6dafedf6 Christos Stavrakakis
        with mocked_quotaholder():
383 a26e5a4d Georgios D. Tsoukalas
            response = self.mypost('servers', 'test_user',
384 f8675683 Christos Stavrakakis
                                   json.dumps(self.request), 'json')
385 6dafedf6 Christos Stavrakakis
        self.assertEqual(response.status_code, 503, "serviceUnavailable")
386 6dafedf6 Christos Stavrakakis
387 cb66110b Christos Stavrakakis
    def test_create_network_settings(self, mrapi):
388 cb66110b Christos Stavrakakis
        mrapi().CreateInstance.return_value = 12
389 cb66110b Christos Stavrakakis
        bnet1 = mfactory.BackendNetworkFactory(operstate="ACTIVE",
390 cb66110b Christos Stavrakakis
                                               backend=self.backend)
391 cb66110b Christos Stavrakakis
        bnet2 = mfactory.BackendNetworkFactory(operstate="ACTIVE",
392 cb66110b Christos Stavrakakis
                                               backend=self.backend)
393 cb66110b Christos Stavrakakis
        bnet3 = mfactory.BackendNetworkFactory(network__userid="test_user",
394 cb66110b Christos Stavrakakis
                                               operstate="ACTIVE",
395 cb66110b Christos Stavrakakis
                                               backend=self.backend)
396 cb66110b Christos Stavrakakis
        bnet4 = mfactory.BackendNetworkFactory(network__userid="test_user",
397 cb66110b Christos Stavrakakis
                                               operstate="ACTIVE",
398 cb66110b Christos Stavrakakis
                                               backend=self.backend)
399 cb66110b Christos Stavrakakis
        # User requested private networks
400 cb66110b Christos Stavrakakis
        request = deepcopy(self.request)
401 cb66110b Christos Stavrakakis
        request["server"]["networks"] = [bnet3.network.id, bnet4.network.id]
402 cb66110b Christos Stavrakakis
        with override_settings(settings,
403 e368ad39 Christos Stavrakakis
                               DEFAULT_INSTANCE_NETWORKS=[
404 e368ad39 Christos Stavrakakis
                                   "SNF:ANY_PUBLIC",
405 e368ad39 Christos Stavrakakis
                                   bnet1.network.id,
406 e368ad39 Christos Stavrakakis
                                   bnet2.network.id]):
407 cb66110b Christos Stavrakakis
            with mocked_quotaholder():
408 2cd55da6 Christos Stavrakakis
                response = self.mypost('servers', 'test_user',
409 cb66110b Christos Stavrakakis
                                       json.dumps(request), 'json')
410 cb66110b Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
411 cb66110b Christos Stavrakakis
        name, args, kwargs = mrapi().CreateInstance.mock_calls[0]
412 cb66110b Christos Stavrakakis
        self.assertEqual(len(kwargs["nics"]), 5)
413 cb66110b Christos Stavrakakis
        self.assertEqual(kwargs["nics"][0]["network"],
414 cb66110b Christos Stavrakakis
                         self.network.backend_id)
415 cb66110b Christos Stavrakakis
        self.assertEqual(kwargs["nics"][1]["network"],
416 cb66110b Christos Stavrakakis
                         bnet1.network.backend_id)
417 cb66110b Christos Stavrakakis
        self.assertEqual(kwargs["nics"][2]["network"],
418 cb66110b Christos Stavrakakis
                         bnet2.network.backend_id)
419 cb66110b Christos Stavrakakis
        self.assertEqual(kwargs["nics"][3]["network"],
420 cb66110b Christos Stavrakakis
                         bnet3.network.backend_id)
421 cb66110b Christos Stavrakakis
        self.assertEqual(kwargs["nics"][4]["network"],
422 cb66110b Christos Stavrakakis
                         bnet4.network.backend_id)
423 cb66110b Christos Stavrakakis
424 816d7588 Christos Stavrakakis
        request["server"]["floating_ips"] = []
425 cb66110b Christos Stavrakakis
        with override_settings(settings,
426 e368ad39 Christos Stavrakakis
                               DEFAULT_INSTANCE_NETWORKS=[bnet2.network.id]):
427 cb66110b Christos Stavrakakis
            with mocked_quotaholder():
428 2cd55da6 Christos Stavrakakis
                response = self.mypost('servers', 'test_user',
429 cb66110b Christos Stavrakakis
                                       json.dumps(request), 'json')
430 cb66110b Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
431 cb66110b Christos Stavrakakis
        name, args, kwargs = mrapi().CreateInstance.mock_calls[1]
432 cb66110b Christos Stavrakakis
        self.assertEqual(len(kwargs["nics"]), 3)
433 cb66110b Christos Stavrakakis
        self.assertEqual(kwargs["nics"][0]["network"],
434 cb66110b Christos Stavrakakis
                         bnet2.network.backend_id)
435 cb66110b Christos Stavrakakis
        self.assertEqual(kwargs["nics"][1]["network"],
436 cb66110b Christos Stavrakakis
                         bnet3.network.backend_id)
437 cb66110b Christos Stavrakakis
        self.assertEqual(kwargs["nics"][2]["network"],
438 cb66110b Christos Stavrakakis
                         bnet4.network.backend_id)
439 cb66110b Christos Stavrakakis
440 cb66110b Christos Stavrakakis
        # test invalid network in DEFAULT_INSTANCE_NETWORKS
441 cb66110b Christos Stavrakakis
        with override_settings(settings, DEFAULT_INSTANCE_NETWORKS=[42]):
442 2cd55da6 Christos Stavrakakis
            response = self.mypost('servers', 'test_user',
443 cb66110b Christos Stavrakakis
                                   json.dumps(request), 'json')
444 cb66110b Christos Stavrakakis
        self.assertFault(response, 500, "internalServerError")
445 cb66110b Christos Stavrakakis
446 cb66110b Christos Stavrakakis
        # test connect to public netwok
447 cb66110b Christos Stavrakakis
        request = deepcopy(self.request)
448 cb66110b Christos Stavrakakis
        request["server"]["networks"] = [self.network.id]
449 9446e7e5 Christos Stavrakakis
        with override_settings(settings,
450 9446e7e5 Christos Stavrakakis
                               DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC"]):
451 2cd55da6 Christos Stavrakakis
            response = self.mypost('servers', 'test_user',
452 e368ad39 Christos Stavrakakis
                                   json.dumps(request), 'json')
453 cb66110b Christos Stavrakakis
        self.assertFault(response, 403, "forbidden")
454 cb66110b Christos Stavrakakis
        # test wrong user
455 cb66110b Christos Stavrakakis
        request = deepcopy(self.request)
456 cb66110b Christos Stavrakakis
        request["server"]["networks"] = [bnet3.network.id]
457 9446e7e5 Christos Stavrakakis
        with override_settings(settings,
458 9446e7e5 Christos Stavrakakis
                               DEFAULT_INSTANCE_NETWORKS=["SNF:ANY_PUBLIC"]):
459 cb66110b Christos Stavrakakis
            with mocked_quotaholder():
460 2cd55da6 Christos Stavrakakis
                response = self.mypost('servers', 'dummy_user',
461 cb66110b Christos Stavrakakis
                                       json.dumps(request), 'json')
462 cb66110b Christos Stavrakakis
        self.assertItemNotFound(response)
463 cb66110b Christos Stavrakakis
464 816d7588 Christos Stavrakakis
        # Test floating IPs
465 816d7588 Christos Stavrakakis
        request = deepcopy(self.request)
466 816d7588 Christos Stavrakakis
        request["server"]["networks"] = [bnet4.network.id]
467 816d7588 Christos Stavrakakis
        network = mfactory.NetworkFactory(subnet="10.0.0.0/24")
468 816d7588 Christos Stavrakakis
        mfactory.BackendNetworkFactory(network=network,
469 816d7588 Christos Stavrakakis
                                       backend=self.backend,
470 816d7588 Christos Stavrakakis
                                       operstate="ACTIVE")
471 816d7588 Christos Stavrakakis
        fp1 = mfactory.FloatingIPFactory(ipv4="10.0.0.2",
472 816d7588 Christos Stavrakakis
                                         userid="test_user",
473 816d7588 Christos Stavrakakis
                                         network=network, machine=None)
474 816d7588 Christos Stavrakakis
        fp2 = mfactory.FloatingIPFactory(ipv4="10.0.0.3", network=network,
475 816d7588 Christos Stavrakakis
                                         userid="test_user",
476 816d7588 Christos Stavrakakis
                                         machine=None)
477 816d7588 Christos Stavrakakis
        request["server"]["floating_ips"] = [fp1.ipv4, fp2.ipv4]
478 816d7588 Christos Stavrakakis
        with override_settings(settings,
479 e368ad39 Christos Stavrakakis
                               DEFAULT_INSTANCE_NETWORKS=[bnet3.network.id]):
480 816d7588 Christos Stavrakakis
            with mocked_quotaholder():
481 2cd55da6 Christos Stavrakakis
                response = self.mypost('servers', 'test_user',
482 e368ad39 Christos Stavrakakis
                                       json.dumps(request), 'json')
483 816d7588 Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
484 816d7588 Christos Stavrakakis
        api_server = json.loads(response.content)['server']
485 816d7588 Christos Stavrakakis
        vm = VirtualMachine.objects.get(id=api_server["id"])
486 816d7588 Christos Stavrakakis
        fp1 = FloatingIP.objects.get(id=fp1.id)
487 816d7588 Christos Stavrakakis
        fp2 = FloatingIP.objects.get(id=fp2.id)
488 816d7588 Christos Stavrakakis
        self.assertEqual(fp1.machine, vm)
489 816d7588 Christos Stavrakakis
        self.assertEqual(fp2.machine, vm)
490 816d7588 Christos Stavrakakis
        name, args, kwargs = mrapi().CreateInstance.mock_calls[2]
491 816d7588 Christos Stavrakakis
        self.assertEqual(len(kwargs["nics"]), 4)
492 816d7588 Christos Stavrakakis
        self.assertEqual(kwargs["nics"][0]["network"],
493 816d7588 Christos Stavrakakis
                         bnet3.network.backend_id)
494 816d7588 Christos Stavrakakis
        self.assertEqual(kwargs["nics"][1]["network"], network.backend_id)
495 816d7588 Christos Stavrakakis
        self.assertEqual(kwargs["nics"][1]["ip"], fp1.ipv4)
496 816d7588 Christos Stavrakakis
        self.assertEqual(kwargs["nics"][2]["network"], network.backend_id)
497 816d7588 Christos Stavrakakis
        self.assertEqual(kwargs["nics"][2]["ip"], fp2.ipv4)
498 816d7588 Christos Stavrakakis
        self.assertEqual(kwargs["nics"][3]["network"],
499 816d7588 Christos Stavrakakis
                         bnet4.network.backend_id)
500 816d7588 Christos Stavrakakis
501 cb66110b Christos Stavrakakis
    def test_create_server_no_flavor(self, mrapi):
502 cb66110b Christos Stavrakakis
        request = deepcopy(self.request)
503 cb66110b Christos Stavrakakis
        request["server"]["flavorRef"] = 42
504 cb66110b Christos Stavrakakis
        with mocked_quotaholder():
505 2cd55da6 Christos Stavrakakis
            response = self.mypost('servers', 'test_user',
506 cb66110b Christos Stavrakakis
                                   json.dumps(request), 'json')
507 039e3e61 Christos Stavrakakis
        self.assertItemNotFound(response)
508 039e3e61 Christos Stavrakakis
509 8e67ea28 Christos Stavrakakis
    def test_create_server_error(self, mrapi):
510 f2080d16 Christos Stavrakakis
        """Test if the create server call returns the expected response
511 f2080d16 Christos Stavrakakis
           if a valid request has been speficied."""
512 f2080d16 Christos Stavrakakis
        mrapi().CreateInstance.side_effect = GanetiApiError("..ganeti is down")
513 f2080d16 Christos Stavrakakis
        # Create public network and backend
514 f2080d16 Christos Stavrakakis
        network = mfactory.NetworkFactory(public=True)
515 f2080d16 Christos Stavrakakis
        backend = mfactory.BackendFactory()
516 f2080d16 Christos Stavrakakis
        mfactory.BackendNetworkFactory(network=network, backend=backend)
517 f2080d16 Christos Stavrakakis
518 8e67ea28 Christos Stavrakakis
        request = self.request
519 f2080d16 Christos Stavrakakis
        with mocked_quotaholder():
520 f2080d16 Christos Stavrakakis
            response = self.mypost('servers', 'test_user',
521 f2080d16 Christos Stavrakakis
                                   json.dumps(request), 'json')
522 9dcfad23 Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
523 f2080d16 Christos Stavrakakis
        mrapi().CreateInstance.assert_called_once()
524 f2080d16 Christos Stavrakakis
        vm = VirtualMachine.objects.get()
525 9dcfad23 Christos Stavrakakis
        # The VM has not been deleted
526 9dcfad23 Christos Stavrakakis
        self.assertFalse(vm.deleted)
527 9dcfad23 Christos Stavrakakis
        # but is in "ERROR" operstate
528 9dcfad23 Christos Stavrakakis
        self.assertEqual(vm.operstate, "ERROR")
529 f2080d16 Christos Stavrakakis
530 039e3e61 Christos Stavrakakis
531 039e3e61 Christos Stavrakakis
@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
532 a26e5a4d Georgios D. Tsoukalas
class ServerDestroyAPITest(ComputeAPITest):
533 039e3e61 Christos Stavrakakis
    def test_delete_server(self, mrapi):
534 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
535 41a7fae7 Christos Stavrakakis
        mrapi().DeleteInstance.return_value = 12
536 2cd55da6 Christos Stavrakakis
        response = self.mydelete('servers/%d' % vm.id, vm.userid)
537 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 204)
538 039e3e61 Christos Stavrakakis
        mrapi().DeleteInstance.assert_called_once()
539 039e3e61 Christos Stavrakakis
540 039e3e61 Christos Stavrakakis
    def test_non_existing_delete_server(self, mrapi):
541 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
542 a26e5a4d Georgios D. Tsoukalas
        response = self.mydelete('servers/%d' % 42, vm.userid)
543 039e3e61 Christos Stavrakakis
        self.assertItemNotFound(response)
544 039e3e61 Christos Stavrakakis
        self.assertFalse(mrapi.mock_calls)
545 039e3e61 Christos Stavrakakis
546 039e3e61 Christos Stavrakakis
547 a26e5a4d Georgios D. Tsoukalas
class ServerMetadataAPITest(ComputeAPITest):
548 039e3e61 Christos Stavrakakis
    def setUp(self):
549 039e3e61 Christos Stavrakakis
        self.vm = mfactory.VirtualMachineFactory()
550 039e3e61 Christos Stavrakakis
        self.metadata = mfactory.VirtualMachineMetadataFactory(vm=self.vm)
551 a26e5a4d Georgios D. Tsoukalas
        super(ServerMetadataAPITest, self).setUp()
552 039e3e61 Christos Stavrakakis
553 039e3e61 Christos Stavrakakis
    def test_get_metadata(self):
554 039e3e61 Christos Stavrakakis
        vm = self.vm
555 039e3e61 Christos Stavrakakis
        create_meta = lambda: mfactory.VirtualMachineMetadataFactory(vm=vm)
556 039e3e61 Christos Stavrakakis
        metadata = [create_meta(), create_meta(), create_meta()]
557 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d/metadata' % vm.id, vm.userid)
558 039e3e61 Christos Stavrakakis
        self.assertTrue(response.status_code in [200, 203])
559 2d04422f Christos Stavrakakis
        api_metadata = json.loads(response.content)['metadata']
560 039e3e61 Christos Stavrakakis
        self.assertEqual(len(api_metadata), len(metadata) + 1)
561 039e3e61 Christos Stavrakakis
        for db_m in metadata:
562 039e3e61 Christos Stavrakakis
            self.assertEqual(api_metadata[db_m.meta_key], db_m.meta_value)
563 039e3e61 Christos Stavrakakis
564 e368ad39 Christos Stavrakakis
        request = {
565 e368ad39 Christos Stavrakakis
            'metadata': {
566 e368ad39 Christos Stavrakakis
                'foo': 'bar'
567 e368ad39 Christos Stavrakakis
            },
568 e368ad39 Christos Stavrakakis
            metadata[0].meta_key: 'bar2'
569 e368ad39 Christos Stavrakakis
        }
570 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/metadata' % vm.id,
571 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
572 039e3e61 Christos Stavrakakis
        metadata2 = VirtualMachineMetadata.objects.filter(vm=vm)
573 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d/metadata' % vm.id, vm.userid)
574 039e3e61 Christos Stavrakakis
        self.assertTrue(response.status_code in [200, 203])
575 2d04422f Christos Stavrakakis
        api_metadata2 = json.loads(response.content)['metadata']
576 039e3e61 Christos Stavrakakis
        self.assertTrue('foo' in api_metadata2.keys())
577 039e3e61 Christos Stavrakakis
        self.assertTrue(api_metadata2[metadata[0].meta_key], 'bar2')
578 039e3e61 Christos Stavrakakis
        self.assertEqual(len(api_metadata2), len(metadata2))
579 039e3e61 Christos Stavrakakis
        for db_m in metadata2:
580 039e3e61 Christos Stavrakakis
            self.assertEqual(api_metadata2[db_m.meta_key], db_m.meta_value)
581 039e3e61 Christos Stavrakakis
582 039e3e61 Christos Stavrakakis
        # Create new meta
583 039e3e61 Christos Stavrakakis
        request = {'meta': {'foo2': 'bar2'}}
584 a26e5a4d Georgios D. Tsoukalas
        response = self.myput('servers/%d/metadata/foo2' % vm.id,
585 a26e5a4d Georgios D. Tsoukalas
                              vm.userid, json.dumps(request), 'json')
586 039e3e61 Christos Stavrakakis
587 039e3e61 Christos Stavrakakis
        # Get the new meta
588 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
589 039e3e61 Christos Stavrakakis
        meta = json.loads(response.content)['meta']
590 039e3e61 Christos Stavrakakis
        self.assertEqual(meta['foo2'], 'bar2')
591 039e3e61 Christos Stavrakakis
592 039e3e61 Christos Stavrakakis
        # Delete the new meta
593 a26e5a4d Georgios D. Tsoukalas
        response = self.mydelete('servers/%d/metadata/foo2' % vm.id, vm.userid)
594 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 204)
595 039e3e61 Christos Stavrakakis
596 039e3e61 Christos Stavrakakis
        # Try to get the deleted meta: should raise 404
597 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
598 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 404)
599 039e3e61 Christos Stavrakakis
600 039e3e61 Christos Stavrakakis
    def test_invalid_metadata(self):
601 039e3e61 Christos Stavrakakis
        vm = self.vm
602 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/metadata' % vm.id, vm.userid)
603 039e3e61 Christos Stavrakakis
        self.assertBadRequest(response)
604 039e3e61 Christos Stavrakakis
        self.assertEqual(len(vm.metadata.all()), 1)
605 039e3e61 Christos Stavrakakis
606 039e3e61 Christos Stavrakakis
    def test_invalid_metadata_server(self):
607 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/42/metadata', 'user')
608 039e3e61 Christos Stavrakakis
        self.assertItemNotFound(response)
609 039e3e61 Christos Stavrakakis
610 039e3e61 Christos Stavrakakis
    def test_get_meta_invalid_key(self):
611 039e3e61 Christos Stavrakakis
        vm = self.vm
612 a26e5a4d Georgios D. Tsoukalas
        response = self.myget('servers/%d/metadata/foo2' % vm.id, vm.userid)
613 039e3e61 Christos Stavrakakis
        self.assertItemNotFound(response)
614 039e3e61 Christos Stavrakakis
615 039e3e61 Christos Stavrakakis
616 039e3e61 Christos Stavrakakis
@patch('synnefo.api.util.get_image')
617 039e3e61 Christos Stavrakakis
@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
618 a26e5a4d Georgios D. Tsoukalas
class ServerActionAPITest(ComputeAPITest):
619 039e3e61 Christos Stavrakakis
    def test_actions(self, mrapi, mimage):
620 039e3e61 Christos Stavrakakis
        actions = ['start', 'shutdown', 'reboot']
621 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
622 039e3e61 Christos Stavrakakis
        vm.operstate = "STOPPED"
623 039e3e61 Christos Stavrakakis
        vm.save()
624 41a7fae7 Christos Stavrakakis
        mrapi().StartupInstance.return_value = 0
625 41a7fae7 Christos Stavrakakis
        mrapi().ShutdownInstance.return_value = 1
626 41a7fae7 Christos Stavrakakis
        mrapi().RebootInstance.return_value = 2
627 41a7fae7 Christos Stavrakakis
        for jobId, action in enumerate(actions):
628 41a7fae7 Christos Stavrakakis
            if action in ["shutdown", "reboot"]:
629 41a7fae7 Christos Stavrakakis
                vm.operstate = "STARTED"
630 41a7fae7 Christos Stavrakakis
            else:
631 41a7fae7 Christos Stavrakakis
                vm.operstate = "STOPPED"
632 41a7fae7 Christos Stavrakakis
            vm.task = None
633 41a7fae7 Christos Stavrakakis
            vm.task_job_id = None
634 41a7fae7 Christos Stavrakakis
            vm.save()
635 039e3e61 Christos Stavrakakis
            val = {'type': 'HARD'} if action == 'reboot' else {}
636 039e3e61 Christos Stavrakakis
            request = {action: val}
637 a26e5a4d Georgios D. Tsoukalas
            response = self.mypost('servers/%d/action' % vm.id,
638 a26e5a4d Georgios D. Tsoukalas
                                   vm.userid, json.dumps(request), 'json')
639 039e3e61 Christos Stavrakakis
            self.assertEqual(response.status_code, 202)
640 039e3e61 Christos Stavrakakis
            if action == 'shutdown':
641 41a7fae7 Christos Stavrakakis
                self.assertEqual(VirtualMachine.objects.get(id=vm.id).task,
642 039e3e61 Christos Stavrakakis
                                 "STOP")
643 039e3e61 Christos Stavrakakis
            else:
644 41a7fae7 Christos Stavrakakis
                self.assertEqual(VirtualMachine.objects.get(id=vm.id).task,
645 039e3e61 Christos Stavrakakis
                                 action.upper())
646 41a7fae7 Christos Stavrakakis
            self.assertEqual(VirtualMachine.objects.get(id=vm.id).task_job_id,
647 41a7fae7 Christos Stavrakakis
                             jobId)
648 039e3e61 Christos Stavrakakis
649 039e3e61 Christos Stavrakakis
    def test_action_in_building_vm(self, mrapi, mimage):
650 039e3e61 Christos Stavrakakis
        """Test building in progress"""
651 41a7fae7 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="BUILD")
652 41a7fae7 Christos Stavrakakis
        request = {'start': {}}
653 41a7fae7 Christos Stavrakakis
        with mocked_quotaholder():
654 2cd55da6 Christos Stavrakakis
            response = self.mypost('servers/%d/action' % vm.id,
655 41a7fae7 Christos Stavrakakis
                                   vm.userid, json.dumps(request), 'json')
656 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 409)
657 039e3e61 Christos Stavrakakis
        self.assertFalse(mrapi.mock_calls)
658 039e3e61 Christos Stavrakakis
659 039e3e61 Christos Stavrakakis
    def test_destroy_build_vm(self, mrapi, mimage):
660 039e3e61 Christos Stavrakakis
        """Test building in progress"""
661 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
662 41a7fae7 Christos Stavrakakis
        mrapi().DeleteInstance.return_value = 2
663 2cd55da6 Christos Stavrakakis
        response = self.mydelete('servers/%d' % vm.id,
664 41a7fae7 Christos Stavrakakis
                                 vm.userid)
665 039e3e61 Christos Stavrakakis
        self.assertSuccess(response)
666 039e3e61 Christos Stavrakakis
        mrapi().RemoveInstance.assert_called_once()
667 039e3e61 Christos Stavrakakis
668 039e3e61 Christos Stavrakakis
    def test_firewall(self, mrapi, mimage):
669 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
670 039e3e61 Christos Stavrakakis
        vm.operstate = "STOPPED"
671 039e3e61 Christos Stavrakakis
        vm.save()
672 039e3e61 Christos Stavrakakis
        request = {'firewallProfile': {'profile': 'PROTECTED'}}
673 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/action' % vm.id,
674 a26e5a4d Georgios D. Tsoukalas
                               vm.userid, json.dumps(request), 'json')
675 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
676 039e3e61 Christos Stavrakakis
        mrapi().ModifyInstance.assert_called_once()
677 039e3e61 Christos Stavrakakis
678 039e3e61 Christos Stavrakakis
    def test_unsupported_firewall(self, mrapi, mimage):
679 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
680 039e3e61 Christos Stavrakakis
        vm.operstate = "STOPPED"
681 039e3e61 Christos Stavrakakis
        vm.save()
682 039e3e61 Christos Stavrakakis
        request = {'firewallProfile': {'profile': 'FOO'}}
683 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/action' % vm.id,
684 a26e5a4d Georgios D. Tsoukalas
                               vm.userid, json.dumps(request), 'json')
685 039e3e61 Christos Stavrakakis
        self.assertBadRequest(response)
686 039e3e61 Christos Stavrakakis
        self.assertFalse(mrapi.mock_calls)
687 039e3e61 Christos Stavrakakis
688 1af851fd Christos Stavrakakis
    def test_resize_vm(self, mrapi, mimage):
689 1af851fd Christos Stavrakakis
        flavor = mfactory.FlavorFactory(cpu=1, ram=1024)
690 1af851fd Christos Stavrakakis
        # Check building VM
691 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor, operstate="BUILD")
692 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor.id}}
693 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
694 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
695 1af851fd Christos Stavrakakis
        self.assertFault(response, 409, "buildInProgress")
696 1af851fd Christos Stavrakakis
        # Check same Flavor
697 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor, operstate="STOPPED")
698 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor.id}}
699 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
700 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
701 41a7fae7 Christos Stavrakakis
        self.assertBadRequest(response)
702 1af851fd Christos Stavrakakis
        # Check flavor with different disk
703 1af851fd Christos Stavrakakis
        flavor2 = mfactory.FlavorFactory(disk=1024)
704 1af851fd Christos Stavrakakis
        flavor3 = mfactory.FlavorFactory(disk=2048)
705 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor2, operstate="STOPPED")
706 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor3.id}}
707 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
708 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
709 1af851fd Christos Stavrakakis
        self.assertBadRequest(response)
710 1af851fd Christos Stavrakakis
        flavor2 = mfactory.FlavorFactory(disk_template="foo")
711 1af851fd Christos Stavrakakis
        flavor3 = mfactory.FlavorFactory(disk_template="baz")
712 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor2, operstate="STOPPED")
713 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor3.id}}
714 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
715 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
716 1af851fd Christos Stavrakakis
        self.assertBadRequest(response)
717 1af851fd Christos Stavrakakis
        # Check success
718 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor, operstate="STOPPED")
719 1af851fd Christos Stavrakakis
        flavor4 = mfactory.FlavorFactory(disk_template=flavor.disk_template,
720 1af851fd Christos Stavrakakis
                                         disk=flavor.disk,
721 1af851fd Christos Stavrakakis
                                         cpu=4, ram=2048)
722 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor4.id}}
723 1af851fd Christos Stavrakakis
        mrapi().ModifyInstance.return_value = 42
724 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
725 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
726 1af851fd Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
727 1af851fd Christos Stavrakakis
        vm = VirtualMachine.objects.get(id=vm.id)
728 41a7fae7 Christos Stavrakakis
        self.assertEqual(vm.task_job_id, 42)
729 1af851fd Christos Stavrakakis
        name, args, kwargs = mrapi().ModifyInstance.mock_calls[0]
730 1af851fd Christos Stavrakakis
        self.assertEqual(kwargs["beparams"]["vcpus"], 4)
731 1af851fd Christos Stavrakakis
        self.assertEqual(kwargs["beparams"]["minmem"], 2048)
732 1af851fd Christos Stavrakakis
        self.assertEqual(kwargs["beparams"]["maxmem"], 2048)
733 1af851fd Christos Stavrakakis
734 41a7fae7 Christos Stavrakakis
    def test_action_on_resizing_vm(self, mrapi, mimage):
735 41a7fae7 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
736 41a7fae7 Christos Stavrakakis
        vm.operstate = "RESIZE"
737 41a7fae7 Christos Stavrakakis
        vm.save()
738 41a7fae7 Christos Stavrakakis
        for action in VirtualMachine.ACTIONS:
739 41a7fae7 Christos Stavrakakis
            request = {action[0]: ""}
740 2cd55da6 Christos Stavrakakis
            response = self.mypost('servers/%d/action' % vm.id,
741 e368ad39 Christos Stavrakakis
                                   vm.userid, json.dumps(request), 'json')
742 41a7fae7 Christos Stavrakakis
            self.assertBadRequest(response)
743 41a7fae7 Christos Stavrakakis
        # however you can destroy
744 41a7fae7 Christos Stavrakakis
        mrapi().DeleteInstance.return_value = 42
745 2cd55da6 Christos Stavrakakis
        response = self.mydelete('servers/%d' % vm.id,
746 2cd55da6 Christos Stavrakakis
                                 vm.userid)
747 41a7fae7 Christos Stavrakakis
        self.assertSuccess(response)
748 41a7fae7 Christos Stavrakakis
749 1af851fd Christos Stavrakakis
    def get_vm(self, flavor, operstate):
750 1af851fd Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(flavor=flavor)
751 1af851fd Christos Stavrakakis
        vm.operstate = operstate
752 1af851fd Christos Stavrakakis
        vm.backendjobstatus = "success"
753 1af851fd Christos Stavrakakis
        vm.save()
754 1af851fd Christos Stavrakakis
        return vm
755 1af851fd Christos Stavrakakis
756 039e3e61 Christos Stavrakakis
757 a26e5a4d Georgios D. Tsoukalas
class ServerVNCConsole(ComputeAPITest):
758 039e3e61 Christos Stavrakakis
    def test_not_active_server(self):
759 039e3e61 Christos Stavrakakis
        """Test console req for not ACTIVE server returns badRequest"""
760 41a7fae7 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="BUILD")
761 039e3e61 Christos Stavrakakis
        data = json.dumps({'console': {'type': 'vnc'}})
762 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/action' % vm.id,
763 a26e5a4d Georgios D. Tsoukalas
                               vm.userid, data, 'json')
764 039e3e61 Christos Stavrakakis
        self.assertBadRequest(response)
765 039e3e61 Christos Stavrakakis
766 039e3e61 Christos Stavrakakis
    def test_active_server(self):
767 039e3e61 Christos Stavrakakis
        """Test console req for ACTIVE server"""
768 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
769 039e3e61 Christos Stavrakakis
        vm.operstate = 'STARTED'
770 039e3e61 Christos Stavrakakis
        vm.save()
771 039e3e61 Christos Stavrakakis
772 039e3e61 Christos Stavrakakis
        data = json.dumps({'console': {'type': 'vnc'}})
773 41a7fae7 Christos Stavrakakis
        with override_settings(settings, TEST=True):
774 2cd55da6 Christos Stavrakakis
            response = self.mypost('servers/%d/action' % vm.id,
775 41a7fae7 Christos Stavrakakis
                                   vm.userid, data, 'json')
776 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 200)
777 039e3e61 Christos Stavrakakis
        reply = json.loads(response.content)
778 039e3e61 Christos Stavrakakis
        self.assertEqual(reply.keys(), ['console'])
779 039e3e61 Christos Stavrakakis
        console = reply['console']
780 039e3e61 Christos Stavrakakis
        self.assertEqual(console['type'], 'vnc')
781 039e3e61 Christos Stavrakakis
        self.assertEqual(set(console.keys()),
782 039e3e61 Christos Stavrakakis
                         set(['type', 'host', 'port', 'password']))
783 039e3e61 Christos Stavrakakis
784 039e3e61 Christos Stavrakakis
    def test_wrong_console_type(self):
785 039e3e61 Christos Stavrakakis
        """Test console req for ACTIVE server"""
786 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
787 039e3e61 Christos Stavrakakis
        vm.operstate = 'STARTED'
788 039e3e61 Christos Stavrakakis
        vm.save()
789 039e3e61 Christos Stavrakakis
790 039e3e61 Christos Stavrakakis
        data = json.dumps({'console': {'type': 'foo'}})
791 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/action' % vm.id,
792 a26e5a4d Georgios D. Tsoukalas
                               vm.userid, data, 'json')
793 039e3e61 Christos Stavrakakis
        self.assertBadRequest(response)