commit 92c53da193dbeff2f4b9630780ebae3daab74d87
Author: Vassilios Karakoidas <vassilios.karakoidas@gmail.com>
Date:   Tue Mar 22 18:23:05 2011 +0200

    Refactored charge (from VM model) and fixed unit tests
    
      * remove backend_id (now it is inline in the model code)
      * charge now resides in credits.py (logic)
      * logic is now a proper django app
      * remove unused backend_id from handlers.py
      * moved unit tests from db -> logic module

diff --git a/api/handlers.py b/api/handlers.py
index b935f05..14d7cd9 100644
--- a/api/handlers.py
+++ b/api/handlers.py
@@ -26,8 +26,6 @@ except Exception, e:
     raise fault.serviceUnavailable
 #If we can't connect to the rapi successfully, don't do anything
 
-backend_prefix_id = settings.BACKEND_PREFIX_ID
-
 VERSIONS = [
     {
         "status": "CURRENT",
diff --git a/db/models.py b/db/models.py
index b9adabb..a5cd967 100644
--- a/db/models.py
+++ b/db/models.py
@@ -3,23 +3,15 @@
 from django.conf import settings
 from django.db import models
 
-from logic.credits import debit_account
-
 import datetime
 
-backend_prefix_id = settings.BACKEND_PREFIX_ID
 
 class SynnefoUser(models.Model):
     name = models.CharField('Synnefo Username', max_length=255)
     credit = models.IntegerField('Credit Balance')
     created = models.DateTimeField('Time of creation', auto_now_add=True)
     updated = models.DateTimeField('Time of last update', auto_now=True)
-    #
-    # We do not rely on Django's user authentication mechanism.
-    # Hence, no references to the User model.
-    # [vkoukis], after discussion with [faidon].
-    # user = models.ForeignKey(User)
-    
+
     class Meta:
         verbose_name = u'Synnefo User'
     
@@ -133,7 +125,6 @@ class Flavor(models.Model):
                 return fch_list[0].cost_inactive
 
         return 0
-        
 
     def _current_cost_active(self):
         """Returns current active cost (property method)"""
@@ -344,9 +335,9 @@ class VirtualMachine(models.Model):
         Strips the ganeti prefix atm. Needs a better name!
         
         """
-        if not str(name).startswith(backend_prefix_id):
+        if not str(name).startswith(settings.BACKEND_PREFIX_ID):
             raise VirtualMachine.InvalidBackendIdError(str(name))
-        ns = str(name).lstrip(backend_prefix_id)
+        ns = str(name).lstrip(settings.BACKEND_PREFIX_ID)
         if not ns.isdigit():
             raise VirtualMachine.InvalidBackendIdError(str(name))
         return int(ns)
@@ -434,7 +425,7 @@ class VirtualMachine(models.Model):
 
     def _get_backend_id(self):
         """Returns the backend id for this VM by prepending backend-prefix."""
-        return '%s%s' % (backend_prefix_id, str(self.id))
+        return '%s%s' % (settings.BACKEND_PREFIX_ID, str(self.id))
 
     backend_id = property(_get_backend_id)
 
@@ -457,39 +448,6 @@ class VirtualMachine(models.Model):
         self.charge()
         self._operstate = new_operstate
 
-    @transaction.commit_on_success
-    def charge(self):
-        """Charges the owner of this VM.
-        
-        Charges the owner of a VM for the period
-        from vm.charged to datetime.now(), based on the
-        current operating state.
-        
-        """
-        charged_states = ('STARTED', 'STOPPED')
-       
-        start_datetime = self.charged
-        self.charged = datetime.datetime.now()
-
-        # Only charge for a specific set of states
-        if self._operstate in charged_states:
-            cost_list = []
-
-            # remember, we charge only for Started and Stopped
-            if self._operstate == 'STARTED':
-                cost_list = self.flavor.get_cost_active(start_datetime, self.charged)
-            elif self._operstate == 'STOPPED':
-                cost_list = self.flavor.get_cost_inactive(start_datetime, self.charged)
-
-            # find the total vost
-            total_cost = sum([x[1] for x in cost_list])
-
-            # add the debit entry
-            description = "Server = %s, charge = %d for state: %s" % (self.name, total_cost, self._operstate)
-            debit_account(self.owner, total_cost, self, description)
-        
-        self.save()
-
 
 class VirtualMachineGroup(models.Model):
     """Groups of VMs for SynnefoUsers"""
diff --git a/db/tests.py b/db/tests.py
index 5553694..5ab68e9 100644
--- a/db/tests.py
+++ b/db/tests.py
@@ -72,45 +72,3 @@ class FlavorTestCase(TestCase):
         self.assertEqual(168, tia_cost, 'flavor.get_cost_inactive() is not working properly (%d!=%d)' % (tia_cost, 168))
 
 
-class VirtualMachineTestCase(TestCase):
-    fixtures = [ 'db_test_data' ]
-
-    def test_charge_method(self):
-        """Test VirtualMachine.charge() method"""
-
-        # Since we have tested the costs, with this test
-        # we must ensure the following:
-        # 1. The vm.charged is updated
-        # 2. Users credits are decreased
-
-        vm_started = VirtualMachine.objects.get(pk=30000)
-
-        initial_date = vm_started.charged
-        initial_credits = vm_started.owner.credit
-
-        vm_started.charge()
-
-        self.assertTrue(vm_started.charged > initial_date, 'Initial charged date should not be greater')
-        self.assertTrue(initial_credits > vm_started.owner.credit, 'The user should have less credits now! (%d>%d)' % (initial_credits, vm_started.owner.credit))
-
-
-class SynnefoUserTestCase(TestCase):
-    fixtures = [ 'db_test_data' ]
-
-    def test_synnefo_user(self):
-        """Test a SynnefoUser object"""
-        s_user = SynnefoUser.objects.get(pk=30000)
-        v_machine = VirtualMachine.objects.get(pk=30000)
-
-        # charge the user
-        s_user.debit_account(10, v_machine, "This should be a structured debit message!")
-
-        # should have only one debit object
-        d_list = Debit.objects.all()
-
-        self.assertEqual(len(d_list), 1, 'SynnefoUser.debit_account() writes more than one debit entries!')
-
-        # retrieve the user, now he/she should have zero credits
-        s_user = SynnefoUser.objects.get(pk=30000)
-
-        self.assertEqual(0, s_user.credit, 'SynnefoUser (pk=30000) should have zero credits (%d)' % ( s_user.credit, ))
diff --git a/logic/credits.py b/logic/credits.py
index 7488a11..b3be59f 100644
--- a/logic/credits.py
+++ b/logic/credits.py
@@ -3,6 +3,7 @@
 #
 # Copyright 2010 Greek Research and Technology Network
 #
+
 from datetime import datetime
 
 from db.models import Debit
@@ -11,7 +12,7 @@ from django.db import transaction
 @transaction.commit_on_success
 def debit_account(user , amount, vm, description):
     """Charges the user with the specified amount of credits for a vm (resource)"""
-    date_now = datetime.datetime.now()
+    date_now = datetime.now()
     user.credit = user.credit - amount
     user.save()
 
@@ -28,3 +29,37 @@ def debit_account(user , amount, vm, description):
 def credit_account(self, amount, creditor, description):
     """No clue :)"""
     return
+
+
+@transaction.commit_on_success
+def charge(vm):
+    """Charges the owner of this VM.
+
+    Charges the owner of a VM for the period
+    from vm.charged to datetime.now(), based on the
+    current operating state.
+
+    """
+    charged_states = ('STARTED', 'STOPPED')
+
+    start_datetime = vm.charged
+    vm.charged = datetime.now()
+
+    # Only charge for a specific set of states
+    if vm._operstate in charged_states:
+        cost_list = []
+
+        # remember, we charge only for Started and Stopped
+        if vm._operstate == 'STARTED':
+            cost_list = vm.flavor.get_cost_active(start_datetime, vm.charged)
+        elif vm._operstate == 'STOPPED':
+            cost_list = vm.flavor.get_cost_inactive(start_datetime, vm.charged)
+
+        # find the total vost
+        total_cost = sum([x[1] for x in cost_list])
+
+        # add the debit entry
+        description = "Server = %s, charge = %d for state: %s" % (vm.name, total_cost, vm._operstate)
+        debit_account(vm.owner, total_cost, vm, description)
+
+    vm.save()
diff --git a/logic/models.py b/logic/models.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/logic/models.py
@@ -0,0 +1 @@
+
diff --git a/logic/tests.py b/logic/tests.py
index b4162f6..e147138 100644
--- a/logic/tests.py
+++ b/logic/tests.py
@@ -5,3 +5,53 @@
 #
 # Copyright 2010 Greek Research and Technology Network
 #
+
+from db.models import *
+
+from logic import credits
+
+from django.test import TestCase
+
+
+class ChargeTestCase(TestCase):
+    fixtures = [ 'db_test_data' ]
+
+    def test_charge_method(self):
+        """Test VirtualMachine.charge() method"""
+
+        # Since we have tested the costs, with this test
+        # we must ensure the following:
+        # 1. The vm.charged is updated
+        # 2. Users credits are decreased
+
+        vm_started = VirtualMachine.objects.get(pk=30000)
+
+        initial_date = vm_started.charged
+        initial_credits = vm_started.owner.credit
+
+        credits.charge(vm_started)
+
+        self.assertTrue(vm_started.charged > initial_date, 'Initial charged date should not be greater')
+        self.assertTrue(initial_credits > vm_started.owner.credit, 'The user should have less credits now! (%d>%d)' % (initial_credits, vm_started.owner.credit))
+
+
+class SynnefoUserTestCase(TestCase):
+    fixtures = [ 'db_test_data' ]
+
+    def test_synnefo_user(self):
+        """Test a SynnefoUser object"""
+        s_user = SynnefoUser.objects.get(pk=30000)
+        v_machine = VirtualMachine.objects.get(pk=30000)
+
+        # charge the user
+        credits.debit_account(s_user, 10, v_machine, "This should be a structured debit message!")
+
+        # should have only one debit object
+        d_list = Debit.objects.all()
+
+        self.assertEqual(len(d_list), 1, 'SynnefoUser.debit_account() writes more than one or zero (%d) debit entries!' % ( len(d_list), ))
+
+        # retrieve the user, now he/she should have zero credits
+        s_user = SynnefoUser.objects.get(pk=30000)
+
+        self.assertEqual(0, s_user.credit, 'SynnefoUser (pk=30000) should have zero credits (%d)' % ( s_user.credit, ))
diff --git a/logic/utils.py b/logic/utils.py
new file mode 100644
index 0000000..319de39
--- /dev/null
+++ b/logic/utils.py
@@ -0,0 +1,6 @@
+#
+# Various utility functions
+#
+# Copyright 2010 Greek Research and Technology Network
+#
+
diff --git a/logic/views.py b/logic/views.py
new file mode 100644
index 0000000..e69de29
