Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (11.2 kB)

1
# vim: set fileencoding=utf-8 :
2
# Copyright 2013 GRNET S.A. All rights reserved.
3
#
4
# Redistribution and use in source and binary forms, with or without
5
# modification, are permitted provided that the following conditions
6
# are met:
7
#
8
#   1. Redistributions of source code must retain the above copyright
9
#      notice, this list of conditions and the following disclaimer.
10
#
11
#  2. Redistributions in binary form must reproduce the above copyright
12
#     notice, this list of conditions and the following disclaimer in the
13
#     documentation and/or other materials provided with the distribution.
14
#
15
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
16
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
# SUCH DAMAGE.
26
#
27
# The views and conclusions contained in the software and documentation are
28
# those of the authors and should not be interpreted as representing official
29
# policies, either expressed or implied, of GRNET S.A.
30

    
31
# Provides automated tests for logic module
32
from django.test import TestCase
33
#from snf_django.utils.testing import mocked_quotaholder
34
from synnefo.logic import servers
35
from synnefo.db import models_factory as mfactory
36
from mock import patch
37

    
38
from snf_django.lib.api import faults
39
from snf_django.utils.testing import mocked_quotaholder, override_settings
40
from django.conf import settings
41

    
42

    
43
@patch("synnefo.logic.rapi_pool.GanetiRapiClient")
44
class ServerTest(TestCase):
45
    def test_create(self, mrapi):
46
        flavor = mfactory.FlavorFactory()
47
        backend = mfactory.BackendFactory()
48
        kwargs = {
49
            "userid": "test",
50
            "name": "test_vm",
51
            "password": "1234",
52
            "flavor": flavor,
53
            "image": {"id": "foo", "backend_id": "foo", "format": "diskdump",
54
                      "metadata": "{}"},
55
            "metadata": {"foo": "bar"},
56
            "personality": [],
57
            "use_backend": backend,
58
        }
59

    
60
        mrapi().CreateInstance.return_value = 42
61
        with override_settings(settings,
62
                               DEFAULT_INSTANCE_NETWORKS=[]):
63
            with mocked_quotaholder():
64
                vm = servers.create(**kwargs)
65
        self.assertEqual(vm.nics.count(), 0)
66

    
67
        # test connect in IPv6 only network
68
        net = mfactory.IPv6NetworkFactory(state="ACTIVE")
69
        mfactory.BackendNetworkFactory(network=net)
70
        with override_settings(settings,
71
                               DEFAULT_INSTANCE_NETWORKS=[str(net.id)]):
72
            with mocked_quotaholder():
73
                vm = servers.create(**kwargs)
74
        nics = vm.nics.all()
75
        self.assertEqual(len(nics), 1)
76
        self.assertEqual(nics[0].ipv4, None)
77
        args, kwargs = mrapi().CreateInstance.call_args
78
        ganeti_nic = kwargs["nics"][0]
79
        self.assertEqual(ganeti_nic["ip"], None)
80
        self.assertEqual(ganeti_nic["network"], net.backend_id)
81

    
82
    def test_connect_network(self, mrapi):
83
        # Common connect
84
        net = mfactory.NetworkFactory(subnet="192.168.2.0/24",
85
                                      gateway="192.168.2.1",
86
                                      state="ACTIVE",
87
                                      dhcp=True,
88
                                      flavor="CUSTOM")
89
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
90
        mfactory.BackendNetworkFactory(network=net, backend=vm.backend)
91
        mrapi().ModifyInstance.return_value = 42
92
        servers.connect(vm, net)
93
        pool = net.get_pool(with_lock=False)
94
        self.assertFalse(pool.is_available("192.168.2.2"))
95
        args, kwargs = mrapi().ModifyInstance.call_args
96
        nics = kwargs["nics"][0]
97
        self.assertEqual(args[0], vm.backend_vm_id)
98
        self.assertEqual(nics[0], "add")
99
        self.assertEqual(nics[1]["ip"], "192.168.2.2")
100
        self.assertEqual(nics[1]["network"], net.backend_id)
101

    
102
        # No dhcp
103
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
104
        net = mfactory.NetworkFactory(subnet="192.168.2.0/24",
105
                                      gateway="192.168.2.1",
106
                                      state="ACTIVE",
107
                                      dhcp=False)
108
        mfactory.BackendNetworkFactory(network=net, backend=vm.backend)
109
        servers.connect(vm, net)
110
        pool = net.get_pool(with_lock=False)
111
        self.assertTrue(pool.is_available("192.168.2.2"))
112
        args, kwargs = mrapi().ModifyInstance.call_args
113
        nics = kwargs["nics"][0]
114
        self.assertEqual(args[0], vm.backend_vm_id)
115
        self.assertEqual(nics[0], "add")
116
        self.assertEqual(nics[1]["ip"], None)
117
        self.assertEqual(nics[1]["network"], net.backend_id)
118

    
119
        # Test connect to IPv6 only network
120
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
121
        net = mfactory.NetworkFactory(subnet6="2000::/64",
122
                                      state="ACTIVE",
123
                                      gateway="2000::1")
124
        mfactory.BackendNetworkFactory(network=net, backend=vm.backend)
125
        servers.connect(vm, net)
126
        args, kwargs = mrapi().ModifyInstance.call_args
127
        nics = kwargs["nics"][0]
128
        self.assertEqual(args[0], vm.backend_vm_id)
129
        self.assertEqual(nics[0], "add")
130
        self.assertEqual(nics[1]["ip"], None)
131
        self.assertEqual(nics[1]["network"], net.backend_id)
132

    
133

    
134
@patch("synnefo.logic.rapi_pool.GanetiRapiClient")
135
class ServerCommandTest(TestCase):
136
    def test_pending_task(self, mrapi):
137
        vm = mfactory.VirtualMachineFactory(task="REBOOT", task_job_id=1)
138
        self.assertRaises(faults.BadRequest, servers.start, vm)
139
        vm = mfactory.VirtualMachineFactory(task="BUILD", task_job_id=1)
140
        self.assertRaises(faults.BuildInProgress, servers.start, vm)
141
        # Assert always succeeds
142
        vm = mfactory.VirtualMachineFactory(task="BUILD", task_job_id=1)
143
        mrapi().DeleteInstance.return_value = 1
144
        with mocked_quotaholder():
145
            servers.destroy(vm)
146
        vm = mfactory.VirtualMachineFactory(task="REBOOT", task_job_id=1)
147
        with mocked_quotaholder():
148
            servers.destroy(vm)
149

    
150
    def test_deleted_vm(self, mrapi):
151
        vm = mfactory.VirtualMachineFactory(deleted=True)
152
        self.assertRaises(faults.BadRequest, servers.start, vm)
153

    
154
    def test_invalid_operstate_for_action(self, mrapi):
155
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
156
        self.assertRaises(faults.BadRequest, servers.start, vm)
157
        vm = mfactory.VirtualMachineFactory(operstate="STOPPED")
158
        self.assertRaises(faults.BadRequest, servers.stop, vm)
159
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
160
        self.assertRaises(faults.BadRequest, servers.resize, vm)
161
        # Check that connect/disconnect is allowed only in STOPPED vms
162
        # if hotplug is disabled.
163
        vm = mfactory.VirtualMachineFactory(operstate="STARTED")
164
        network = mfactory.NetworkFactory(state="ACTIVE")
165
        with override_settings(settings, GANETI_USE_HOTPLUG=False):
166
            self.assertRaises(faults.BadRequest, servers.connect, vm, network)
167
            self.assertRaises(faults.BadRequest, servers.disconnect, vm,
168
                              network)
169
        #test valid
170
        vm = mfactory.VirtualMachineFactory(operstate="STOPPED")
171
        mrapi().StartupInstance.return_value = 1
172
        with mocked_quotaholder():
173
            servers.start(vm)
174
        vm.task = None
175
        vm.task_job_id = None
176
        vm.save()
177
        mrapi().RebootInstance.return_value = 1
178
        with mocked_quotaholder():
179
            servers.reboot(vm, "HARD")
180

    
181
    def test_commission(self, mrapi):
182
        vm = mfactory.VirtualMachineFactory(operstate="STOPPED")
183
        # Still pending
184
        vm.serial = mfactory.QuotaHolderSerialFactory(serial=200,
185
                                                      resolved=False,
186
                                                      pending=True)
187
        serial = vm.serial
188
        mrapi().StartupInstance.return_value = 1
189
        with mocked_quotaholder() as m:
190
            servers.start(vm)
191
            m.resolve_commissions.assert_called_once_with('', [],
192
                                                          [serial.serial])
193
            self.assertTrue(m.issue_one_commission.called)
194
        # Not pending, rejct
195
        vm.task = None
196
        vm.serial = mfactory.QuotaHolderSerialFactory(serial=400,
197
                                                      resolved=False,
198
                                                      pending=False,
199
                                                      accept=False)
200
        serial = vm.serial
201
        mrapi().StartupInstance.return_value = 1
202
        with mocked_quotaholder() as m:
203
            servers.start(vm)
204
            m.resolve_commissions.assert_called_once_with('', [],
205
                                                          [serial.serial])
206
            self.assertTrue(m.issue_one_commission.called)
207
        # Not pending, accept
208
        vm.task = None
209
        vm.serial = mfactory.QuotaHolderSerialFactory(serial=600,
210
                                                      resolved=False,
211
                                                      pending=False,
212
                                                      accept=True)
213
        serial = vm.serial
214
        mrapi().StartupInstance.return_value = 1
215
        with mocked_quotaholder() as m:
216
            servers.start(vm)
217
            m.resolve_commissions.assert_called_once_with('', [serial.serial],
218
                                                          [])
219
            self.assertTrue(m.issue_one_commission.called)
220

    
221
        mrapi().StartupInstance.side_effect = ValueError
222
        vm.task = None
223
        vm.serial = None
224
        # Test reject if Ganeti erro
225
        with mocked_quotaholder() as m:
226
            try:
227
                servers.start(vm)
228
            except:
229
                m.resolve_commissions\
230
                 .assert_called_once_with('', [], [vm.serial.serial])
231

    
232
    def test_task_after(self, mrapi):
233
        return
234
        vm = mfactory.VirtualMachineFactory()
235
        mrapi().StartupInstance.return_value = 1
236
        mrapi().ShutdownInstance.return_value = 2
237
        mrapi().RebootInstance.return_value = 2
238
        with mocked_quotaholder():
239
            vm.task = None
240
            vm.operstate = "STOPPED"
241
            servers.start(vm)
242
            self.assertEqual(vm.task, "START")
243
            self.assertEqual(vm.task_job_id, 1)
244
        with mocked_quotaholder():
245
            vm.task = None
246
            vm.operstate = "STARTED"
247
            servers.stop(vm)
248
            self.assertEqual(vm.task, "STOP")
249
            self.assertEqual(vm.task_job_id, 2)
250
        with mocked_quotaholder():
251
            vm.task = None
252
            servers.reboot(vm)
253
            self.assertEqual(vm.task, "REBOOT")
254
            self.assertEqual(vm.task_job_id, 3)