Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / tests / servers.py @ ba777b02

History | View | Annotate | Download (12.1 kB)

1 0208770b Christos Stavrakakis
# vim: set fileencoding=utf-8 :
2 0208770b Christos Stavrakakis
# Copyright 2013 GRNET S.A. All rights reserved.
3 0208770b Christos Stavrakakis
#
4 0208770b Christos Stavrakakis
# Redistribution and use in source and binary forms, with or without
5 0208770b Christos Stavrakakis
# modification, are permitted provided that the following conditions
6 0208770b Christos Stavrakakis
# are met:
7 0208770b Christos Stavrakakis
#
8 0208770b Christos Stavrakakis
#   1. Redistributions of source code must retain the above copyright
9 0208770b Christos Stavrakakis
#      notice, this list of conditions and the following disclaimer.
10 0208770b Christos Stavrakakis
#
11 0208770b Christos Stavrakakis
#  2. Redistributions in binary form must reproduce the above copyright
12 0208770b Christos Stavrakakis
#     notice, this list of conditions and the following disclaimer in the
13 0208770b Christos Stavrakakis
#     documentation and/or other materials provided with the distribution.
14 0208770b Christos Stavrakakis
#
15 0208770b Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
16 0208770b Christos Stavrakakis
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 0208770b Christos Stavrakakis
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 0208770b Christos Stavrakakis
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19 0208770b Christos Stavrakakis
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 0208770b Christos Stavrakakis
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 0208770b Christos Stavrakakis
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 0208770b Christos Stavrakakis
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 0208770b Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 0208770b Christos Stavrakakis
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 0208770b Christos Stavrakakis
# SUCH DAMAGE.
26 0208770b Christos Stavrakakis
#
27 0208770b Christos Stavrakakis
# The views and conclusions contained in the software and documentation are
28 0208770b Christos Stavrakakis
# those of the authors and should not be interpreted as representing official
29 0208770b Christos Stavrakakis
# policies, either expressed or implied, of GRNET S.A.
30 0208770b Christos Stavrakakis
31 0208770b Christos Stavrakakis
# Provides automated tests for logic module
32 562bf712 Christos Stavrakakis
from django.test import TransactionTestCase
33 0208770b Christos Stavrakakis
#from snf_django.utils.testing import mocked_quotaholder
34 0208770b Christos Stavrakakis
from synnefo.logic import servers
35 fb540e3a Giorgos Korfiatis
from synnefo import quotas
36 562bf712 Christos Stavrakakis
from synnefo.db import models_factory as mfactory, models
37 0208770b Christos Stavrakakis
from mock import patch
38 0208770b Christos Stavrakakis
39 0208770b Christos Stavrakakis
from snf_django.lib.api import faults
40 0208770b Christos Stavrakakis
from snf_django.utils.testing import mocked_quotaholder, override_settings
41 728e8923 Christos Stavrakakis
from django.conf import settings
42 562bf712 Christos Stavrakakis
from copy import deepcopy
43 0208770b Christos Stavrakakis
44 0208770b Christos Stavrakakis
45 0208770b Christos Stavrakakis
@patch("synnefo.logic.rapi_pool.GanetiRapiClient")
46 562bf712 Christos Stavrakakis
class ServerCreationTest(TransactionTestCase):
47 0208770b Christos Stavrakakis
    def test_create(self, mrapi):
48 0208770b Christos Stavrakakis
        flavor = mfactory.FlavorFactory()
49 0208770b Christos Stavrakakis
        kwargs = {
50 0208770b Christos Stavrakakis
            "userid": "test",
51 0208770b Christos Stavrakakis
            "name": "test_vm",
52 0208770b Christos Stavrakakis
            "password": "1234",
53 0208770b Christos Stavrakakis
            "flavor": flavor,
54 0208770b Christos Stavrakakis
            "image": {"id": "foo", "backend_id": "foo", "format": "diskdump",
55 00429c48 Christos Stavrakakis
                      "checksum": "test_checksum",
56 0208770b Christos Stavrakakis
                      "metadata": "{}"},
57 2e19e7dc Christos Stavrakakis
            "networks": [],
58 0208770b Christos Stavrakakis
            "metadata": {"foo": "bar"},
59 0208770b Christos Stavrakakis
            "personality": [],
60 0208770b Christos Stavrakakis
        }
61 562bf712 Christos Stavrakakis
        # no backend!
62 562bf712 Christos Stavrakakis
        mfactory.BackendFactory(offline=True)
63 562bf712 Christos Stavrakakis
        self.assertRaises(faults.ServiceUnavailable, servers.create, **kwargs)
64 562bf712 Christos Stavrakakis
        self.assertEqual(models.VirtualMachine.objects.count(), 0)
65 0208770b Christos Stavrakakis
66 3aecadc8 Christos Stavrakakis
        mfactory.IPv4SubnetFactory(network__public=True)
67 3aecadc8 Christos Stavrakakis
        mfactory.IPv6SubnetFactory(network__public=True)
68 00429c48 Christos Stavrakakis
        backend = mfactory.BackendFactory()
69 562bf712 Christos Stavrakakis
70 562bf712 Christos Stavrakakis
        # error in nics
71 562bf712 Christos Stavrakakis
        req = deepcopy(kwargs)
72 99988465 Christos Stavrakakis
        req["networks"] = [{"uuid": 42}]
73 562bf712 Christos Stavrakakis
        self.assertRaises(faults.ItemNotFound, servers.create, **req)
74 562bf712 Christos Stavrakakis
        self.assertEqual(models.VirtualMachine.objects.count(), 0)
75 562bf712 Christos Stavrakakis
76 562bf712 Christos Stavrakakis
        # error in enqueue. check the vm is deleted and resources released
77 562bf712 Christos Stavrakakis
        mrapi().CreateInstance.side_effect = Exception("ganeti is down")
78 562bf712 Christos Stavrakakis
        with mocked_quotaholder():
79 9dcfad23 Christos Stavrakakis
            servers.create(**kwargs)
80 562bf712 Christos Stavrakakis
        vm = models.VirtualMachine.objects.get()
81 9dcfad23 Christos Stavrakakis
        self.assertFalse(vm.deleted)
82 9dcfad23 Christos Stavrakakis
        self.assertEqual(vm.operstate, "ERROR")
83 9dcfad23 Christos Stavrakakis
        for nic in vm.nics.all():
84 9dcfad23 Christos Stavrakakis
            self.assertEqual(nic.state, "ERROR")
85 562bf712 Christos Stavrakakis
86 00429c48 Christos Stavrakakis
        # test ext settings:
87 00429c48 Christos Stavrakakis
        req = deepcopy(kwargs)
88 00429c48 Christos Stavrakakis
        ext_flavor = mfactory.FlavorFactory(disk_template="ext_archipelago",
89 00429c48 Christos Stavrakakis
                                            disk=1)
90 00429c48 Christos Stavrakakis
        req["flavor"] = ext_flavor
91 00429c48 Christos Stavrakakis
        mrapi().CreateInstance.return_value = 42
92 00429c48 Christos Stavrakakis
        backend.disk_templates = ["ext"]
93 00429c48 Christos Stavrakakis
        backend.save()
94 00429c48 Christos Stavrakakis
        osettings = {
95 00429c48 Christos Stavrakakis
            "GANETI_DISK_PROVIDER_KWARGS": {
96 00429c48 Christos Stavrakakis
                "archipelago": {
97 00429c48 Christos Stavrakakis
                    "foo": "mpaz",
98 00429c48 Christos Stavrakakis
                    "lala": "lolo"
99 00429c48 Christos Stavrakakis
                }
100 00429c48 Christos Stavrakakis
            }
101 00429c48 Christos Stavrakakis
        }
102 00429c48 Christos Stavrakakis
        with mocked_quotaholder():
103 00429c48 Christos Stavrakakis
            with override_settings(settings, **osettings):
104 00429c48 Christos Stavrakakis
                vm = servers.create(**req)
105 00429c48 Christos Stavrakakis
        name, args, kwargs = mrapi().CreateInstance.mock_calls[-1]
106 00429c48 Christos Stavrakakis
        self.assertEqual(kwargs["disks"][0], {"provider": "archipelago",
107 00429c48 Christos Stavrakakis
                                              "origin": "test_checksum",
108 00429c48 Christos Stavrakakis
                                              "foo": "mpaz",
109 00429c48 Christos Stavrakakis
                                              "lala": "lolo",
110 00429c48 Christos Stavrakakis
                                              "size": 1024})
111 00429c48 Christos Stavrakakis
112 562bf712 Christos Stavrakakis
113 562bf712 Christos Stavrakakis
@patch("synnefo.logic.rapi_pool.GanetiRapiClient")
114 562bf712 Christos Stavrakakis
class ServerTest(TransactionTestCase):
115 0208770b Christos Stavrakakis
    def test_connect_network(self, mrapi):
116 0208770b Christos Stavrakakis
        # Common connect
117 710b1c43 Christos Stavrakakis
        for dhcp in [True, False]:
118 710b1c43 Christos Stavrakakis
            subnet = mfactory.IPv4SubnetFactory(network__flavor="CUSTOM",
119 710b1c43 Christos Stavrakakis
                                                cidr="192.168.2.0/24",
120 710b1c43 Christos Stavrakakis
                                                gateway="192.168.2.1",
121 3b2984dc Christos Stavrakakis
                                                dhcp=dhcp)
122 710b1c43 Christos Stavrakakis
            net = subnet.network
123 710b1c43 Christos Stavrakakis
            vm = mfactory.VirtualMachineFactory(operstate="STARTED")
124 710b1c43 Christos Stavrakakis
            mfactory.BackendNetworkFactory(network=net, backend=vm.backend)
125 710b1c43 Christos Stavrakakis
            mrapi().ModifyInstance.return_value = 42
126 e8234183 Christos Stavrakakis
            with override_settings(settings, GANETI_USE_HOTPLUG=True):
127 e8234183 Christos Stavrakakis
                servers.connect(vm, net)
128 3b2984dc Christos Stavrakakis
            pool = net.get_ip_pools(locked=False)[0]
129 710b1c43 Christos Stavrakakis
            self.assertFalse(pool.is_available("192.168.2.2"))
130 710b1c43 Christos Stavrakakis
            args, kwargs = mrapi().ModifyInstance.call_args
131 710b1c43 Christos Stavrakakis
            nics = kwargs["nics"][0]
132 710b1c43 Christos Stavrakakis
            self.assertEqual(kwargs["instance"], vm.backend_vm_id)
133 710b1c43 Christos Stavrakakis
            self.assertEqual(nics[0], "add")
134 710b1c43 Christos Stavrakakis
            self.assertEqual(nics[1], "-1")
135 710b1c43 Christos Stavrakakis
            self.assertEqual(nics[2]["ip"], "192.168.2.2")
136 710b1c43 Christos Stavrakakis
            self.assertEqual(nics[2]["network"], net.backend_id)
137 0208770b Christos Stavrakakis
138 0208770b Christos Stavrakakis
        # Test connect to IPv6 only network
139 9599e997 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
140 8764d304 Christos Stavrakakis
        subnet = mfactory.IPv6SubnetFactory(cidr="2000::/64",
141 8764d304 Christos Stavrakakis
                                            gateway="2000::1")
142 8764d304 Christos Stavrakakis
        net = subnet.network
143 0208770b Christos Stavrakakis
        mfactory.BackendNetworkFactory(network=net, backend=vm.backend)
144 e8234183 Christos Stavrakakis
        with override_settings(settings, GANETI_USE_HOTPLUG=True):
145 e8234183 Christos Stavrakakis
            servers.connect(vm, net)
146 0208770b Christos Stavrakakis
        args, kwargs = mrapi().ModifyInstance.call_args
147 0208770b Christos Stavrakakis
        nics = kwargs["nics"][0]
148 6488097c Christos Stavrakakis
        self.assertEqual(kwargs["instance"], vm.backend_vm_id)
149 0208770b Christos Stavrakakis
        self.assertEqual(nics[0], "add")
150 a1baa42b Christos Stavrakakis
        self.assertEqual(nics[1], "-1")
151 a1baa42b Christos Stavrakakis
        self.assertEqual(nics[2]["ip"], None)
152 a1baa42b Christos Stavrakakis
        self.assertEqual(nics[2]["network"], net.backend_id)
153 0208770b Christos Stavrakakis
154 0208770b Christos Stavrakakis
155 0208770b Christos Stavrakakis
@patch("synnefo.logic.rapi_pool.GanetiRapiClient")
156 562bf712 Christos Stavrakakis
class ServerCommandTest(TransactionTestCase):
157 0208770b Christos Stavrakakis
    def test_pending_task(self, mrapi):
158 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(task="REBOOT", task_job_id=1)
159 0208770b Christos Stavrakakis
        self.assertRaises(faults.BadRequest, servers.start, vm)
160 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(task="BUILD", task_job_id=1)
161 0208770b Christos Stavrakakis
        self.assertRaises(faults.BuildInProgress, servers.start, vm)
162 0208770b Christos Stavrakakis
        # Assert always succeeds
163 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(task="BUILD", task_job_id=1)
164 0208770b Christos Stavrakakis
        mrapi().DeleteInstance.return_value = 1
165 0208770b Christos Stavrakakis
        with mocked_quotaholder():
166 0208770b Christos Stavrakakis
            servers.destroy(vm)
167 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(task="REBOOT", task_job_id=1)
168 0208770b Christos Stavrakakis
        with mocked_quotaholder():
169 0208770b Christos Stavrakakis
            servers.destroy(vm)
170 0208770b Christos Stavrakakis
171 0208770b Christos Stavrakakis
    def test_deleted_vm(self, mrapi):
172 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(deleted=True)
173 0208770b Christos Stavrakakis
        self.assertRaises(faults.BadRequest, servers.start, vm)
174 0208770b Christos Stavrakakis
175 0208770b Christos Stavrakakis
    def test_invalid_operstate_for_action(self, mrapi):
176 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
177 0208770b Christos Stavrakakis
        self.assertRaises(faults.BadRequest, servers.start, vm)
178 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="STOPPED")
179 0208770b Christos Stavrakakis
        self.assertRaises(faults.BadRequest, servers.stop, vm)
180 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
181 64bca363 Giorgos Korfiatis
        flavor = mfactory.FlavorFactory()
182 64bca363 Giorgos Korfiatis
        self.assertRaises(faults.BadRequest, servers.resize, vm, flavor)
183 9599e997 Christos Stavrakakis
        # Check that connect/disconnect is allowed only in STOPPED vms
184 9599e997 Christos Stavrakakis
        # if hotplug is disabled.
185 9599e997 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
186 9599e997 Christos Stavrakakis
        network = mfactory.NetworkFactory(state="ACTIVE")
187 9599e997 Christos Stavrakakis
        with override_settings(settings, GANETI_USE_HOTPLUG=False):
188 9599e997 Christos Stavrakakis
            self.assertRaises(faults.BadRequest, servers.connect, vm, network)
189 9599e997 Christos Stavrakakis
            self.assertRaises(faults.BadRequest, servers.disconnect, vm,
190 9599e997 Christos Stavrakakis
                              network)
191 0208770b Christos Stavrakakis
        #test valid
192 9599e997 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="STOPPED")
193 0208770b Christos Stavrakakis
        mrapi().StartupInstance.return_value = 1
194 0208770b Christos Stavrakakis
        with mocked_quotaholder():
195 0208770b Christos Stavrakakis
            servers.start(vm)
196 0208770b Christos Stavrakakis
        vm.task = None
197 0208770b Christos Stavrakakis
        vm.task_job_id = None
198 0208770b Christos Stavrakakis
        vm.save()
199 fb540e3a Giorgos Korfiatis
        with mocked_quotaholder():
200 ba777b02 Giorgos Korfiatis
            quotas.accept_resource_serial(vm)
201 0208770b Christos Stavrakakis
        mrapi().RebootInstance.return_value = 1
202 0208770b Christos Stavrakakis
        with mocked_quotaholder():
203 0208770b Christos Stavrakakis
            servers.reboot(vm, "HARD")
204 0208770b Christos Stavrakakis
205 0208770b Christos Stavrakakis
    def test_commission(self, mrapi):
206 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate="STOPPED")
207 0208770b Christos Stavrakakis
        # Still pending
208 0208770b Christos Stavrakakis
        vm.serial = mfactory.QuotaHolderSerialFactory(serial=200,
209 0208770b Christos Stavrakakis
                                                      resolved=False,
210 0208770b Christos Stavrakakis
                                                      pending=True)
211 0208770b Christos Stavrakakis
        serial = vm.serial
212 0208770b Christos Stavrakakis
        mrapi().StartupInstance.return_value = 1
213 0208770b Christos Stavrakakis
        with mocked_quotaholder() as m:
214 fb540e3a Giorgos Korfiatis
            with self.assertRaises(quotas.ResolveError):
215 fb540e3a Giorgos Korfiatis
                servers.start(vm)
216 0208770b Christos Stavrakakis
        # Not pending, rejct
217 0208770b Christos Stavrakakis
        vm.task = None
218 0208770b Christos Stavrakakis
        vm.serial = mfactory.QuotaHolderSerialFactory(serial=400,
219 0208770b Christos Stavrakakis
                                                      resolved=False,
220 0208770b Christos Stavrakakis
                                                      pending=False,
221 0208770b Christos Stavrakakis
                                                      accept=False)
222 0208770b Christos Stavrakakis
        serial = vm.serial
223 0208770b Christos Stavrakakis
        mrapi().StartupInstance.return_value = 1
224 0208770b Christos Stavrakakis
        with mocked_quotaholder() as m:
225 0208770b Christos Stavrakakis
            servers.start(vm)
226 e407f159 Ilias Tsitsimpis
            m.resolve_commissions.assert_called_once_with([],
227 0208770b Christos Stavrakakis
                                                          [serial.serial])
228 0208770b Christos Stavrakakis
            self.assertTrue(m.issue_one_commission.called)
229 0208770b Christos Stavrakakis
        # Not pending, accept
230 0208770b Christos Stavrakakis
        vm.task = None
231 0208770b Christos Stavrakakis
        vm.serial = mfactory.QuotaHolderSerialFactory(serial=600,
232 0208770b Christos Stavrakakis
                                                      resolved=False,
233 0208770b Christos Stavrakakis
                                                      pending=False,
234 0208770b Christos Stavrakakis
                                                      accept=True)
235 0208770b Christos Stavrakakis
        serial = vm.serial
236 0208770b Christos Stavrakakis
        mrapi().StartupInstance.return_value = 1
237 0208770b Christos Stavrakakis
        with mocked_quotaholder() as m:
238 0208770b Christos Stavrakakis
            servers.start(vm)
239 e407f159 Ilias Tsitsimpis
            m.resolve_commissions.assert_called_once_with([serial.serial],
240 0208770b Christos Stavrakakis
                                                          [])
241 0208770b Christos Stavrakakis
            self.assertTrue(m.issue_one_commission.called)
242 0208770b Christos Stavrakakis
243 0208770b Christos Stavrakakis
        mrapi().StartupInstance.side_effect = ValueError
244 0208770b Christos Stavrakakis
        vm.task = None
245 0208770b Christos Stavrakakis
        vm.serial = None
246 0208770b Christos Stavrakakis
        # Test reject if Ganeti erro
247 0208770b Christos Stavrakakis
        with mocked_quotaholder() as m:
248 0208770b Christos Stavrakakis
            try:
249 0208770b Christos Stavrakakis
                servers.start(vm)
250 0208770b Christos Stavrakakis
            except:
251 0208770b Christos Stavrakakis
                m.resolve_commissions\
252 e407f159 Ilias Tsitsimpis
                 .assert_called_once_with([], [vm.serial.serial])
253 0208770b Christos Stavrakakis
254 0208770b Christos Stavrakakis
    def test_task_after(self, mrapi):
255 0208770b Christos Stavrakakis
        return
256 0208770b Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
257 0208770b Christos Stavrakakis
        mrapi().StartupInstance.return_value = 1
258 0208770b Christos Stavrakakis
        mrapi().ShutdownInstance.return_value = 2
259 0208770b Christos Stavrakakis
        mrapi().RebootInstance.return_value = 2
260 0208770b Christos Stavrakakis
        with mocked_quotaholder():
261 0208770b Christos Stavrakakis
            vm.task = None
262 0208770b Christos Stavrakakis
            vm.operstate = "STOPPED"
263 0208770b Christos Stavrakakis
            servers.start(vm)
264 0208770b Christos Stavrakakis
            self.assertEqual(vm.task, "START")
265 0208770b Christos Stavrakakis
            self.assertEqual(vm.task_job_id, 1)
266 0208770b Christos Stavrakakis
        with mocked_quotaholder():
267 0208770b Christos Stavrakakis
            vm.task = None
268 0208770b Christos Stavrakakis
            vm.operstate = "STARTED"
269 0208770b Christos Stavrakakis
            servers.stop(vm)
270 0208770b Christos Stavrakakis
            self.assertEqual(vm.task, "STOP")
271 0208770b Christos Stavrakakis
            self.assertEqual(vm.task_job_id, 2)
272 0208770b Christos Stavrakakis
        with mocked_quotaholder():
273 0208770b Christos Stavrakakis
            vm.task = None
274 0208770b Christos Stavrakakis
            servers.reboot(vm)
275 0208770b Christos Stavrakakis
            self.assertEqual(vm.task, "REBOOT")
276 0208770b Christos Stavrakakis
            self.assertEqual(vm.task_job_id, 3)