Statistics
| Branch: | Tag: | Revision:

root / logic / tests.py @ 95aee02c

History | View | Annotate | Download (12.5 kB)

1
# vim: set fileencoding=utf-8 :
2
# Copyright 2011 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

    
33
from synnefo.db.models import *
34
from synnefo.logic import backend
35
from synnefo.logic import credits
36
from synnefo.logic import users
37
from synnefo.logic.utils import get_rsapi_state
38

    
39
from django.test import TestCase
40
from django.conf import settings
41

    
42
import time
43
import hashlib
44

    
45
class CostsTestCase(TestCase):
46
    fixtures = [ 'db_test_data' ]
47

    
48
    def test_get_costs(self):
49
        """Test the Flavor cost-related methods method"""
50
        # first an easy test, a Flavor with only one FlavorCost entry
51
        flavor = Flavor.objects.get(pk=30001)
52

    
53
        start_date = datetime.datetime(year=2010, month=1, day=1)
54
        end_date = datetime.datetime(year=2010, month=1, day=2)
55

    
56
        # we now that the cost should be 5*24 (inactive) and 10*24 (active)
57
        r_active = credits.get_cost_active(flavor, start_date, end_date)
58
        r_inactive = credits.get_cost_inactive(flavor, start_date, end_date)
59

    
60
        self.assertEqual(len(r_active), 1, 'get_cost_active() should have returned 1 entry (%d)' %(len(r_active),))
61
        self.assertEqual(len(r_inactive), 1, 'get_cost_inactive() should have returned 1 entry (%d)'% (len(r_inactive),))
62

    
63
        self.assertEqual(10*24, r_active[0][1], 'get_cost_active() is not working properly (%d!=%d)' % (r_active[0][1], 10*24))
64
        self.assertEqual(5*24, r_inactive[0][1], 'get_cost_inactive() is not working properly (%d!=%d)' % (r_inactive[0][1], 5*24))
65

    
66
        # The second test, will involve a more complex cost example
67
        # The overall cost will be calculated by two FlavorCost entries
68

    
69
        flavor = Flavor.objects.get(pk=30000)
70

    
71
        start_date = datetime.datetime(year=2010, month=12, day=31)
72
        end_date = datetime.datetime(year=2011, month=01, day=2)
73

    
74
        # this is more complicated, active costs are 5*24 + 10*24 = 360
75
        # and inactive costs are 2*24 + 5*24 = 168
76

    
77
        r_active = credits.get_cost_active(flavor, start_date, end_date)
78
        r_inactive = credits.get_cost_inactive(flavor, start_date, end_date)
79

    
80
        self.assertEqual(len(r_active), 2, 'get_cost_active() should have returned 2 entries (%d)' %(len(r_active),))
81
        self.assertEqual(len(r_inactive), 2, 'get_cost_inactive() should have returned 2 entries (%d)'% (len(r_inactive),))
82

    
83
        ta_cost = sum([x[1] for x in r_active])
84
        tia_cost = sum([x[1] for x in r_inactive])
85

    
86
        self.assertEqual(360, ta_cost, 'get_cost_active() is not working properly (%d!=%d)' % (ta_cost, 360))
87
        self.assertEqual(168, tia_cost, 'get_cost_inactive() is not working properly (%d!=%d)' % (tia_cost, 168))
88

    
89
        
90
class ChargeTestCase(TestCase):
91
    fixtures = [ 'db_test_data' ]
92

    
93
    def test_charge_method(self):
94
        """Test VirtualMachine.charge() method"""
95

    
96
        # Since we have tested the costs, with this test
97
        # we must ensure the following:
98
        # 1. The vm.charged is updated
99
        # 2. Users credits are decreased
100

    
101
        vm_started = VirtualMachine.objects.get(pk=30000)
102

    
103
        initial_date = vm_started.charged
104
        initial_credits = vm_started.owner.credit
105

    
106
        credits.charge(vm_started)
107

    
108
        self.assertTrue(vm_started.charged > initial_date, 'Initial charged date should not be greater')
109
        self.assertTrue(initial_credits > vm_started.owner.credit, 'The user should have less credits now! (%d>%d)' % (initial_credits, vm_started.owner.credit))
110

    
111

    
112
class DebitAccountTestCase(TestCase):
113
    fixtures = [ 'db_test_data' ]
114

    
115
    def test_debit_account(self):
116
        """Test a SynnefoUser object"""
117
        s_user = SynnefoUser.objects.get(pk=30000)
118
        v_machine = VirtualMachine.objects.get(pk=30000)
119

    
120
        # charge the user
121
        credits.debit_account(s_user, 10, v_machine, "This should be a structured debit message!")
122

    
123
        # should have only one debit object
124
        d_list = Debit.objects.all()
125

    
126
        self.assertEqual(len(d_list), 1, 'debit_account() writes more than one or zero (%d) debit entries!' % ( len(d_list), ))
127

    
128
        # retrieve the user, now he/she should have zero credits
129
        s_user = SynnefoUser.objects.get(pk=30000)
130

    
131
        self.assertEqual(0, s_user.credit, 'SynnefoUser (pk=30000) should have zero credits (%d)' % ( s_user.credit, ))
132

    
133

    
134
class AuthTestCase(TestCase):
135
    fixtures = [ 'db_test_data' ]
136

    
137
    def _register_user(self):
138
        users.register_student ("Jimmy Page", "jpage", "jpage@zoso.com")
139
        self.user = SynnefoUser.objects.get(name = "jpage")
140

    
141
    def test_register(self):
142
        """ test user registration
143
        """
144
        self._register_user()
145
        self.assertNotEquals(self.user, None)
146

    
147
        #Check hash generation
148
        md5 = hashlib.md5()
149
        md5.update(self.user.uniq)
150
        md5.update(self.user.name)
151
        md5.update(time.asctime())
152

    
153
        self.assertEquals(self.user.auth_token, md5.hexdigest())
154

    
155
    def test_del_user(self):
156
        """ test user deletion
157
        """
158
        self._register_user()
159
        self.assertNotEquals(self.user, None)
160
        
161
        users.delete_user(self.user)
162

    
163
        self.assertRaises(SynnefoUser.DoesNotExist, SynnefoUser.objects.get,
164
                          name = "jpage")
165

    
166

    
167
class ProcessOpStatusTestCase(TestCase):
168
    fixtures = ['db_test_data']
169
    msg_op = {
170
        'instance': 'instance-name',
171
        'type': 'ganeti-op-status',
172
        'operation': 'OP_INSTANCE_STARTUP',
173
        'jobId': 0,
174
        'status': 'success',
175
        'logmsg': 'unittest - simulated message'
176
    }
177

    
178
    def test_op_startup_success(self):
179
        """Test notification for successful OP_INSTANCE_START"""
180
        msg = self.msg_op
181
        msg['operation'] = 'OP_INSTANCE_STARTUP'
182
        msg['status'] = 'success'
183

    
184
        # This machine is initially in BUILD
185
        vm = VirtualMachine.objects.get(pk=30002)
186
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
187
                                  msg["status"], msg["logmsg"])
188
        self.assertEquals(get_rsapi_state(vm), 'ACTIVE')
189

    
190
    def test_op_shutdown_success(self):
191
        """Test notification for successful OP_INSTANCE_SHUTDOWN"""
192
        msg = self.msg_op
193
        msg['operation'] = 'OP_INSTANCE_SHUTDOWN'
194
        msg['status'] = 'success'
195

    
196
        # This machine is initially in BUILD
197
        vm = VirtualMachine.objects.get(pk=30002)
198
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
199
                                  msg["status"], msg["logmsg"])
200
        self.assertEquals(get_rsapi_state(vm), 'STOPPED')
201

    
202
    def test_op_reboot_success(self):
203
        """Test notification for successful OP_INSTANCE_REBOOT"""
204
        msg = self.msg_op
205
        msg['operation'] = 'OP_INSTANCE_REBOOT'
206
        msg['status'] = 'success'
207

    
208
        # This machine is initially in BUILD
209
        vm = VirtualMachine.objects.get(pk=30002)
210
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
211
                                  msg["status"], msg["logmsg"])
212
        self.assertEquals(get_rsapi_state(vm), 'ACTIVE')
213

    
214
    def test_op_create_success(self):
215
        """Test notification for successful OP_INSTANCE_CREATE"""
216
        msg = self.msg_op
217
        msg['operation'] = 'OP_INSTANCE_CREATE'
218
        msg['status'] = 'success'
219

    
220
        # This machine is initially in BUILD
221
        vm = VirtualMachine.objects.get(pk=30002)
222
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
223
                                  msg["status"], msg["logmsg"])
224
        self.assertEquals(get_rsapi_state(vm), 'ACTIVE')
225

    
226
    def test_op_remove_success(self):
227
        """Test notification for successful OP_INSTANCE_REMOVE"""
228
        msg = self.msg_op
229
        msg['operation'] = 'OP_INSTANCE_REMOVE'
230
        msg['status'] = 'success'
231

    
232
        # This machine is initially in BUILD
233
        vm = VirtualMachine.objects.get(pk=30002)
234
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
235
                                  msg["status"], msg["logmsg"])
236
        self.assertEquals(get_rsapi_state(vm), 'DELETED')
237
        self.assertTrue(vm.deleted)
238

    
239
    def test_unknown_op(self):
240
        """Test notification for unknown Ganeti op raises exception"""
241
        msg = self.msg_op
242
        msg['operation'] = 'OP_INSTANCE_SOMETHING_ELSE'
243
        msg['status'] = 'success'
244

    
245
        # This machine is initially in BUILD
246
        vm = VirtualMachine.objects.get(pk=30002)
247
        self.assertRaises(VirtualMachine.InvalidBackendMsgError,
248
                          backend.process_op_status,
249
                          vm, msg["jobId"], msg["operation"],
250
                          msg["status"], msg["logmsg"])
251

    
252
    def test_op_create_error(self):
253
        """Test notification for failed OP_INSTANCE_CREATE"""
254
        msg = self.msg_op
255
        msg['operation'] = 'OP_INSTANCE_CREATE'
256
        msg['status'] = 'error'
257

    
258
        # This machine is initially in BUILD
259
        vm = VirtualMachine.objects.get(pk=30002)
260
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
261
                                  msg["status"], msg["logmsg"])
262
        self.assertEquals(get_rsapi_state(vm), 'ERROR')
263
        self.assertFalse(vm.deleted)
264

    
265
    def test_remove_machine_in_error(self):
266
        """Test notification for failed OP_INSTANCE_REMOVE, server in ERROR"""
267
        msg = self.msg_op
268
        msg['operation'] = 'OP_INSTANCE_REMOVE'
269
        msg['status'] = 'error'
270

    
271
        # This machine is initially in BUILD
272
        vm = VirtualMachine.objects.get(pk=30002)
273
        backend.process_op_status(vm, 0, "OP_INSTANCE_CREATE", "error", "test")
274
        self.assertEquals(get_rsapi_state(vm), 'ERROR')
275

    
276
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
277
                                  msg["status"], msg["logmsg"])
278
        self.assertEquals(get_rsapi_state(vm), 'DELETED')
279
        self.assertTrue(vm.deleted)
280

    
281

    
282
class ProcessNetStatusTestCase(TestCase):
283
    fixtures = ['db_test_data']
284
    def test_set_ipv4(self):
285
        """Test reception of a net status notification"""
286
        msg = {'instance': 'instance-name',
287
               'type':     'ganeti-net-status',
288
               'nics': [
289
                   {'ip': '192.168.33.1', 'mac': 'aa:00:00:58:1e:b9'}
290
               ]
291
        }
292
        vm = VirtualMachine.objects.get(pk=30000)
293
        backend.process_net_status(vm, msg['nics'])
294
        self.assertEquals(vm.nics.all()[0].ipv4, '192.168.33.1')
295

    
296
    def test_set_empty_ipv4(self):
297
        """Test reception of a net status notification with no IPv4 assigned"""
298
        msg = {'instance': 'instance-name',
299
               'type':     'ganeti-net-status',
300
               'nics': [
301
                   {'ip': '', 'mac': 'aa:00:00:58:1e:b9'}
302
               ]
303
        }
304
        vm = VirtualMachine.objects.get(pk=30000)
305
        backend.process_net_status(vm, msg['nics'])
306
        self.assertEquals(vm.nics.all()[0].ipv4, '')
307

    
308

    
309
class UsersTestCase(TestCase):
310

    
311
    def test_create_uname(self):
312
        username = users.create_uname("Donald Knuth")
313
        self.assertEquals(username, "knuthd")
314

    
315
        username = users.create_uname("Nemichandra Siddhanta Chakravati")
316
        self.assertEquals(username, "chakravn")
317

    
318
        username = users.create_uname(u'Γεώργιος Παπαγεωργίου')
319
        self.assertEquals(username, u'παπαγεωγ')