Revision 92c53da1

b/api/handlers.py
26 26
    raise fault.serviceUnavailable
27 27
#If we can't connect to the rapi successfully, don't do anything
28 28

  
29
backend_prefix_id = settings.BACKEND_PREFIX_ID
30

  
31 29
VERSIONS = [
32 30
    {
33 31
        "status": "CURRENT",
b/db/models.py
3 3
from django.conf import settings
4 4
from django.db import models
5 5

  
6
from logic.credits import debit_account
7

  
8 6
import datetime
9 7

  
10
backend_prefix_id = settings.BACKEND_PREFIX_ID
11 8

  
12 9
class SynnefoUser(models.Model):
13 10
    name = models.CharField('Synnefo Username', max_length=255)
14 11
    credit = models.IntegerField('Credit Balance')
15 12
    created = models.DateTimeField('Time of creation', auto_now_add=True)
16 13
    updated = models.DateTimeField('Time of last update', auto_now=True)
17
    #
18
    # We do not rely on Django's user authentication mechanism.
19
    # Hence, no references to the User model.
20
    # [vkoukis], after discussion with [faidon].
21
    # user = models.ForeignKey(User)
22
    
14

  
23 15
    class Meta:
24 16
        verbose_name = u'Synnefo User'
25 17
    
......
133 125
                return fch_list[0].cost_inactive
134 126

  
135 127
        return 0
136
        
137 128

  
138 129
    def _current_cost_active(self):
139 130
        """Returns current active cost (property method)"""
......
344 335
        Strips the ganeti prefix atm. Needs a better name!
345 336
        
346 337
        """
347
        if not str(name).startswith(backend_prefix_id):
338
        if not str(name).startswith(settings.BACKEND_PREFIX_ID):
348 339
            raise VirtualMachine.InvalidBackendIdError(str(name))
349
        ns = str(name).lstrip(backend_prefix_id)
340
        ns = str(name).lstrip(settings.BACKEND_PREFIX_ID)
350 341
        if not ns.isdigit():
351 342
            raise VirtualMachine.InvalidBackendIdError(str(name))
352 343
        return int(ns)
......
434 425

  
435 426
    def _get_backend_id(self):
436 427
        """Returns the backend id for this VM by prepending backend-prefix."""
437
        return '%s%s' % (backend_prefix_id, str(self.id))
428
        return '%s%s' % (settings.BACKEND_PREFIX_ID, str(self.id))
438 429

  
439 430
    backend_id = property(_get_backend_id)
440 431

  
......
457 448
        self.charge()
458 449
        self._operstate = new_operstate
459 450

  
460
    @transaction.commit_on_success
461
    def charge(self):
462
        """Charges the owner of this VM.
463
        
464
        Charges the owner of a VM for the period
465
        from vm.charged to datetime.now(), based on the
466
        current operating state.
467
        
468
        """
469
        charged_states = ('STARTED', 'STOPPED')
470
       
471
        start_datetime = self.charged
472
        self.charged = datetime.datetime.now()
473

  
474
        # Only charge for a specific set of states
475
        if self._operstate in charged_states:
476
            cost_list = []
477

  
478
            # remember, we charge only for Started and Stopped
479
            if self._operstate == 'STARTED':
480
                cost_list = self.flavor.get_cost_active(start_datetime, self.charged)
481
            elif self._operstate == 'STOPPED':
482
                cost_list = self.flavor.get_cost_inactive(start_datetime, self.charged)
483

  
484
            # find the total vost
485
            total_cost = sum([x[1] for x in cost_list])
486

  
487
            # add the debit entry
488
            description = "Server = %s, charge = %d for state: %s" % (self.name, total_cost, self._operstate)
489
            debit_account(self.owner, total_cost, self, description)
490
        
491
        self.save()
492

  
493 451

  
494 452
class VirtualMachineGroup(models.Model):
495 453
    """Groups of VMs for SynnefoUsers"""
b/db/tests.py
72 72
        self.assertEqual(168, tia_cost, 'flavor.get_cost_inactive() is not working properly (%d!=%d)' % (tia_cost, 168))
73 73

  
74 74

  
75
class VirtualMachineTestCase(TestCase):
76
    fixtures = [ 'db_test_data' ]
77

  
78
    def test_charge_method(self):
79
        """Test VirtualMachine.charge() method"""
80

  
81
        # Since we have tested the costs, with this test
82
        # we must ensure the following:
83
        # 1. The vm.charged is updated
84
        # 2. Users credits are decreased
85

  
86
        vm_started = VirtualMachine.objects.get(pk=30000)
87

  
88
        initial_date = vm_started.charged
89
        initial_credits = vm_started.owner.credit
90

  
91
        vm_started.charge()
92

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

  
96

  
97
class SynnefoUserTestCase(TestCase):
98
    fixtures = [ 'db_test_data' ]
99

  
100
    def test_synnefo_user(self):
101
        """Test a SynnefoUser object"""
102
        s_user = SynnefoUser.objects.get(pk=30000)
103
        v_machine = VirtualMachine.objects.get(pk=30000)
104

  
105
        # charge the user
106
        s_user.debit_account(10, v_machine, "This should be a structured debit message!")
107

  
108
        # should have only one debit object
109
        d_list = Debit.objects.all()
110

  
111
        self.assertEqual(len(d_list), 1, 'SynnefoUser.debit_account() writes more than one debit entries!')
112

  
113
        # retrieve the user, now he/she should have zero credits
114
        s_user = SynnefoUser.objects.get(pk=30000)
115

  
116
        self.assertEqual(0, s_user.credit, 'SynnefoUser (pk=30000) should have zero credits (%d)' % ( s_user.credit, ))
b/logic/credits.py
3 3
#
4 4
# Copyright 2010 Greek Research and Technology Network
5 5
#
6

  
6 7
from datetime import datetime
7 8

  
8 9
from db.models import Debit
......
11 12
@transaction.commit_on_success
12 13
def debit_account(user , amount, vm, description):
13 14
    """Charges the user with the specified amount of credits for a vm (resource)"""
14
    date_now = datetime.datetime.now()
15
    date_now = datetime.now()
15 16
    user.credit = user.credit - amount
16 17
    user.save()
17 18

  
......
28 29
def credit_account(self, amount, creditor, description):
29 30
    """No clue :)"""
30 31
    return
32

  
33

  
34
@transaction.commit_on_success
35
def charge(vm):
36
    """Charges the owner of this VM.
37

  
38
    Charges the owner of a VM for the period
39
    from vm.charged to datetime.now(), based on the
40
    current operating state.
41

  
42
    """
43
    charged_states = ('STARTED', 'STOPPED')
44

  
45
    start_datetime = vm.charged
46
    vm.charged = datetime.now()
47

  
48
    # Only charge for a specific set of states
49
    if vm._operstate in charged_states:
50
        cost_list = []
51

  
52
        # remember, we charge only for Started and Stopped
53
        if vm._operstate == 'STARTED':
54
            cost_list = vm.flavor.get_cost_active(start_datetime, vm.charged)
55
        elif vm._operstate == 'STOPPED':
56
            cost_list = vm.flavor.get_cost_inactive(start_datetime, vm.charged)
57

  
58
        # find the total vost
59
        total_cost = sum([x[1] for x in cost_list])
60

  
61
        # add the debit entry
62
        description = "Server = %s, charge = %d for state: %s" % (vm.name, total_cost, vm._operstate)
63
        debit_account(vm.owner, total_cost, vm, description)
64

  
65
    vm.save()
b/logic/models.py
1

  
b/logic/tests.py
5 5
#
6 6
# Copyright 2010 Greek Research and Technology Network
7 7
#
8

  
9
from db.models import *
10

  
11
from logic import credits
12

  
13
from django.test import TestCase
14

  
15

  
16
class ChargeTestCase(TestCase):
17
    fixtures = [ 'db_test_data' ]
18

  
19
    def test_charge_method(self):
20
        """Test VirtualMachine.charge() method"""
21

  
22
        # Since we have tested the costs, with this test
23
        # we must ensure the following:
24
        # 1. The vm.charged is updated
25
        # 2. Users credits are decreased
26

  
27
        vm_started = VirtualMachine.objects.get(pk=30000)
28

  
29
        initial_date = vm_started.charged
30
        initial_credits = vm_started.owner.credit
31

  
32
        credits.charge(vm_started)
33

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

  
37

  
38
class SynnefoUserTestCase(TestCase):
39
    fixtures = [ 'db_test_data' ]
40

  
41
    def test_synnefo_user(self):
42
        """Test a SynnefoUser object"""
43
        s_user = SynnefoUser.objects.get(pk=30000)
44
        v_machine = VirtualMachine.objects.get(pk=30000)
45

  
46
        # charge the user
47
        credits.debit_account(s_user, 10, v_machine, "This should be a structured debit message!")
48

  
49
        # should have only one debit object
50
        d_list = Debit.objects.all()
51

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

  
54
        # retrieve the user, now he/she should have zero credits
55
        s_user = SynnefoUser.objects.get(pk=30000)
56

  
57
        self.assertEqual(0, s_user.credit, 'SynnefoUser (pk=30000) should have zero credits (%d)' % ( s_user.credit, ))
b/logic/utils.py
1
#
2
# Various utility functions
3
#
4
# Copyright 2010 Greek Research and Technology Network
5
#
6

  

Also available in: Unified diff