Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (35.8 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 7c714455 Christos Stavrakakis
        self.assertEqual(api_nic['id'], 'nic-%s-%s' % (db_vm.id, nic.id))
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 d0545590 Christos Stavrakakis
        self.assertBadRequest(response)
676 d0545590 Christos Stavrakakis
        request = {'firewallProfile': {'profile': 'PROTECTED', "nic": "10"}}
677 d0545590 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
678 d0545590 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
679 d0545590 Christos Stavrakakis
        self.assertItemNotFound(response)
680 d0545590 Christos Stavrakakis
        nic = mfactory.NetworkInterfaceFactory(machine=vm)
681 d0545590 Christos Stavrakakis
        request = {'firewallProfile': {'profile': 'PROTECTED', "nic": nic.id}}
682 d0545590 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
683 d0545590 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
684 d0545590 Christos Stavrakakis
        self.assertSuccess(response)
685 039e3e61 Christos Stavrakakis
        mrapi().ModifyInstance.assert_called_once()
686 039e3e61 Christos Stavrakakis
687 039e3e61 Christos Stavrakakis
    def test_unsupported_firewall(self, mrapi, mimage):
688 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
689 039e3e61 Christos Stavrakakis
        vm.operstate = "STOPPED"
690 039e3e61 Christos Stavrakakis
        vm.save()
691 039e3e61 Christos Stavrakakis
        request = {'firewallProfile': {'profile': 'FOO'}}
692 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/action' % vm.id,
693 a26e5a4d Georgios D. Tsoukalas
                               vm.userid, json.dumps(request), 'json')
694 039e3e61 Christos Stavrakakis
        self.assertBadRequest(response)
695 039e3e61 Christos Stavrakakis
        self.assertFalse(mrapi.mock_calls)
696 039e3e61 Christos Stavrakakis
697 1af851fd Christos Stavrakakis
    def test_resize_vm(self, mrapi, mimage):
698 1af851fd Christos Stavrakakis
        flavor = mfactory.FlavorFactory(cpu=1, ram=1024)
699 1af851fd Christos Stavrakakis
        # Check building VM
700 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor, operstate="BUILD")
701 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor.id}}
702 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
703 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
704 1af851fd Christos Stavrakakis
        self.assertFault(response, 409, "buildInProgress")
705 1af851fd Christos Stavrakakis
        # Check same Flavor
706 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor, operstate="STOPPED")
707 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor.id}}
708 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
709 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
710 41a7fae7 Christos Stavrakakis
        self.assertBadRequest(response)
711 1af851fd Christos Stavrakakis
        # Check flavor with different disk
712 1af851fd Christos Stavrakakis
        flavor2 = mfactory.FlavorFactory(disk=1024)
713 1af851fd Christos Stavrakakis
        flavor3 = mfactory.FlavorFactory(disk=2048)
714 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor2, operstate="STOPPED")
715 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor3.id}}
716 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
717 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
718 1af851fd Christos Stavrakakis
        self.assertBadRequest(response)
719 1af851fd Christos Stavrakakis
        flavor2 = mfactory.FlavorFactory(disk_template="foo")
720 1af851fd Christos Stavrakakis
        flavor3 = mfactory.FlavorFactory(disk_template="baz")
721 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor2, operstate="STOPPED")
722 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor3.id}}
723 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
724 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
725 1af851fd Christos Stavrakakis
        self.assertBadRequest(response)
726 1af851fd Christos Stavrakakis
        # Check success
727 1af851fd Christos Stavrakakis
        vm = self.get_vm(flavor=flavor, operstate="STOPPED")
728 1af851fd Christos Stavrakakis
        flavor4 = mfactory.FlavorFactory(disk_template=flavor.disk_template,
729 1af851fd Christos Stavrakakis
                                         disk=flavor.disk,
730 1af851fd Christos Stavrakakis
                                         cpu=4, ram=2048)
731 1af851fd Christos Stavrakakis
        request = {'resize': {'flavorRef': flavor4.id}}
732 1af851fd Christos Stavrakakis
        mrapi().ModifyInstance.return_value = 42
733 2cd55da6 Christos Stavrakakis
        response = self.mypost('servers/%d/action' % vm.id,
734 e368ad39 Christos Stavrakakis
                               vm.userid, json.dumps(request), 'json')
735 1af851fd Christos Stavrakakis
        self.assertEqual(response.status_code, 202)
736 1af851fd Christos Stavrakakis
        vm = VirtualMachine.objects.get(id=vm.id)
737 41a7fae7 Christos Stavrakakis
        self.assertEqual(vm.task_job_id, 42)
738 1af851fd Christos Stavrakakis
        name, args, kwargs = mrapi().ModifyInstance.mock_calls[0]
739 1af851fd Christos Stavrakakis
        self.assertEqual(kwargs["beparams"]["vcpus"], 4)
740 1af851fd Christos Stavrakakis
        self.assertEqual(kwargs["beparams"]["minmem"], 2048)
741 1af851fd Christos Stavrakakis
        self.assertEqual(kwargs["beparams"]["maxmem"], 2048)
742 1af851fd Christos Stavrakakis
743 41a7fae7 Christos Stavrakakis
    def test_action_on_resizing_vm(self, mrapi, mimage):
744 41a7fae7 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
745 41a7fae7 Christos Stavrakakis
        vm.operstate = "RESIZE"
746 41a7fae7 Christos Stavrakakis
        vm.save()
747 41a7fae7 Christos Stavrakakis
        for action in VirtualMachine.ACTIONS:
748 41a7fae7 Christos Stavrakakis
            request = {action[0]: ""}
749 2cd55da6 Christos Stavrakakis
            response = self.mypost('servers/%d/action' % vm.id,
750 e368ad39 Christos Stavrakakis
                                   vm.userid, json.dumps(request), 'json')
751 41a7fae7 Christos Stavrakakis
            self.assertBadRequest(response)
752 41a7fae7 Christos Stavrakakis
        # however you can destroy
753 41a7fae7 Christos Stavrakakis
        mrapi().DeleteInstance.return_value = 42
754 2cd55da6 Christos Stavrakakis
        response = self.mydelete('servers/%d' % vm.id,
755 2cd55da6 Christos Stavrakakis
                                 vm.userid)
756 41a7fae7 Christos Stavrakakis
        self.assertSuccess(response)
757 41a7fae7 Christos Stavrakakis
758 1af851fd Christos Stavrakakis
    def get_vm(self, flavor, operstate):
759 1af851fd Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(flavor=flavor)
760 1af851fd Christos Stavrakakis
        vm.operstate = operstate
761 1af851fd Christos Stavrakakis
        vm.backendjobstatus = "success"
762 1af851fd Christos Stavrakakis
        vm.save()
763 1af851fd Christos Stavrakakis
        return vm
764 1af851fd Christos Stavrakakis
765 039e3e61 Christos Stavrakakis
766 a26e5a4d Georgios D. Tsoukalas
class ServerVNCConsole(ComputeAPITest):
767 039e3e61 Christos Stavrakakis
    def test_not_active_server(self):
768 039e3e61 Christos Stavrakakis
        """Test console req for not ACTIVE server returns badRequest"""
769 41a7fae7 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="BUILD")
770 039e3e61 Christos Stavrakakis
        data = json.dumps({'console': {'type': 'vnc'}})
771 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/action' % vm.id,
772 a26e5a4d Georgios D. Tsoukalas
                               vm.userid, data, 'json')
773 039e3e61 Christos Stavrakakis
        self.assertBadRequest(response)
774 039e3e61 Christos Stavrakakis
775 039e3e61 Christos Stavrakakis
    def test_active_server(self):
776 039e3e61 Christos Stavrakakis
        """Test console req for ACTIVE server"""
777 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
778 039e3e61 Christos Stavrakakis
        vm.operstate = 'STARTED'
779 039e3e61 Christos Stavrakakis
        vm.save()
780 039e3e61 Christos Stavrakakis
781 039e3e61 Christos Stavrakakis
        data = json.dumps({'console': {'type': 'vnc'}})
782 41a7fae7 Christos Stavrakakis
        with override_settings(settings, TEST=True):
783 2cd55da6 Christos Stavrakakis
            response = self.mypost('servers/%d/action' % vm.id,
784 41a7fae7 Christos Stavrakakis
                                   vm.userid, data, 'json')
785 039e3e61 Christos Stavrakakis
        self.assertEqual(response.status_code, 200)
786 039e3e61 Christos Stavrakakis
        reply = json.loads(response.content)
787 039e3e61 Christos Stavrakakis
        self.assertEqual(reply.keys(), ['console'])
788 039e3e61 Christos Stavrakakis
        console = reply['console']
789 039e3e61 Christos Stavrakakis
        self.assertEqual(console['type'], 'vnc')
790 039e3e61 Christos Stavrakakis
        self.assertEqual(set(console.keys()),
791 039e3e61 Christos Stavrakakis
                         set(['type', 'host', 'port', 'password']))
792 039e3e61 Christos Stavrakakis
793 039e3e61 Christos Stavrakakis
    def test_wrong_console_type(self):
794 039e3e61 Christos Stavrakakis
        """Test console req for ACTIVE server"""
795 039e3e61 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
796 039e3e61 Christos Stavrakakis
        vm.operstate = 'STARTED'
797 039e3e61 Christos Stavrakakis
        vm.save()
798 039e3e61 Christos Stavrakakis
799 039e3e61 Christos Stavrakakis
        data = json.dumps({'console': {'type': 'foo'}})
800 a26e5a4d Georgios D. Tsoukalas
        response = self.mypost('servers/%d/action' % vm.id,
801 a26e5a4d Georgios D. Tsoukalas
                               vm.userid, data, 'json')
802 039e3e61 Christos Stavrakakis
        self.assertBadRequest(response)