Revision 595bc9b0
b/snf-cyclades-app/synnefo/logic/tests.py | ||
---|---|---|
765 | 765 |
self.assertEqual(vm.buildpercentage, old) |
766 | 766 |
|
767 | 767 |
|
768 |
from synnefo.logic.reconciliation import VMState |
|
768 |
import logging |
|
769 |
from datetime import timedelta |
|
770 |
|
|
771 |
|
|
772 |
@patch("synnefo.logic.rapi_pool.GanetiRapiClient") |
|
769 | 773 |
class ReconciliationTest(TestCase): |
770 |
def get_vm(self, operstate, deleted=False): |
|
771 |
flavor = mfactory.FlavorFactory(cpu=2, ram=1024) |
|
772 |
vm = mfactory.VirtualMachineFactory(deleted=deleted, flavor=flavor) |
|
773 |
vm.operstate = operstate |
|
774 |
vm.save() |
|
775 |
return vm |
|
776 |
|
|
777 |
def test_get_servers_from_db(self): |
|
778 |
"""Test getting a dictionary from each server to its operstate""" |
|
779 |
backends = Backend.objects.all() |
|
780 |
vm1 = self.get_vm('STARTED') |
|
781 |
vm2 = self.get_vm('DESTROYED', deleted=True) |
|
782 |
vm3 = self.get_vm('STOPPED') |
|
783 |
self.assertEquals(reconciliation.get_servers_from_db(backends), |
|
784 |
{vm1.id: VMState(state='STARTED', cpu=2, ram=1024, nics=[]), |
|
785 |
vm3.id: VMState(state='STOPPED', cpu=2, ram=1024, nics=[])} |
|
786 |
) |
|
787 |
|
|
788 |
def test_stale_servers_in_db(self): |
|
789 |
"""Test discovery of stale entries in DB""" |
|
790 |
|
|
791 |
D = {1: None, 2: 'None', 3: None, 30000: 'BUILD', |
|
792 |
30002: 'None'} |
|
793 |
G = {1: True, 3: True, 30000: True} |
|
794 |
self.assertEquals(reconciliation.stale_servers_in_db(D, G), |
|
795 |
set([2, 30002])) |
|
796 |
|
|
797 |
@patch("synnefo.db.models.get_rapi_client") |
|
798 |
def test_stale_building_vm(self, client): |
|
799 |
vm = mfactory.VirtualMachineFactory() |
|
800 |
vm.state = 'BUILD' |
|
801 |
vm.backendjobid = 42 |
|
802 |
vm.save() |
|
803 |
D = {vm.id: 'BUILD'} |
|
804 |
G = {} |
|
805 |
for status in ['queued', 'waiting', 'running']: |
|
806 |
client.return_value.GetJobStatus.return_value = {'status': status} |
|
807 |
self.assertEqual(reconciliation.stale_servers_in_db(D, G), set([])) |
|
808 |
client.return_value.GetJobStatus\ |
|
809 |
.assert_called_once_with(vm.backendjobid) |
|
810 |
client.reset_mock() |
|
811 |
for status in ['success', 'error', 'canceled']: |
|
812 |
client.return_value.GetJobStatus.return_value = {'status': status} |
|
813 |
self.assertEqual(reconciliation.stale_servers_in_db(D, G), set([])) |
|
814 |
client.return_value.GetInstance\ |
|
815 |
.assert_called_once_with(vm.backend_vm_id) |
|
816 |
client.return_value.GetJobStatus\ |
|
817 |
.assert_called_once_with(vm.backendjobid) |
|
818 |
client.reset_mock() |
|
819 |
from synnefo.logic.rapi import GanetiApiError |
|
820 |
client.return_value.GetJobStatus.side_effect = GanetiApiError('Foo') |
|
821 |
self.assertEqual(reconciliation.stale_servers_in_db(D, G), |
|
822 |
set([vm.id])) |
|
823 |
|
|
824 |
def test_orphan_instances_in_ganeti(self): |
|
825 |
"""Test discovery of orphan instances in Ganeti, without a DB entry""" |
|
826 |
|
|
827 |
G = {1: True, 2: False, 3: False, 4: True, 50: True} |
|
828 |
D = {1: True, 3: False} |
|
829 |
self.assertEquals(reconciliation.orphan_instances_in_ganeti(D, G), |
|
830 |
set([2, 4, 50])) |
|
831 |
|
|
832 |
def test_unsynced_operstate(self): |
|
833 |
"""Test discovery of unsynced operstate between the DB and Ganeti""" |
|
834 |
mkstate = lambda state: VMState(state=state, cpu=1, ram=1024, nics=[]) |
|
835 |
vm1 = self.get_vm("STARTED") |
|
836 |
vm2 = self.get_vm("STARTED") |
|
837 |
vm3= self.get_vm("BUILD") |
|
838 |
vm4 = self.get_vm("STARTED") |
|
839 |
vm5 = self.get_vm("BUILD") |
|
840 |
|
|
841 |
D = {1: mkstate("STARTED"), 2: mkstate("STARTED"), 3: mkstate("BUILD"), |
|
842 |
4: mkstate("STARTED"), 50: mkstate("BUILD")} |
|
843 |
G = {vm1.id: mkstate(True), vm2.id: mkstate(False), |
|
844 |
vm4.id: mkstate(True), vm4.id: mkstate(False), |
|
845 |
vm5.id: mkstate(False)} |
|
846 |
self.assertEquals(reconciliation.unsynced_operstate(D, G), |
|
847 |
set([(vm2.id, "STARTED", False), |
|
848 |
(vm4.id, "STARTED", False)])) |
|
774 |
@patch("synnefo.logic.rapi_pool.GanetiRapiClient") |
|
775 |
def setUp(self, mrapi): |
|
776 |
self.backend = mfactory.BackendFactory() |
|
777 |
log = logging.getLogger() |
|
778 |
options = {"fix_unsynced": True, |
|
779 |
"fix_stale": True, |
|
780 |
"fix_orphans": True, |
|
781 |
"fix_unsynced_nics": True, |
|
782 |
"fix_unsynced_flavors": True} |
|
783 |
self.reconciler = reconciliation.BackendReconciler(self.backend, |
|
784 |
options=options, |
|
785 |
logger=log) |
|
786 |
|
|
787 |
def test_building_vm(self, mrapi): |
|
788 |
mrapi = self.reconciler.client |
|
789 |
vm1 = mfactory.VirtualMachineFactory(backend=self.backend, |
|
790 |
backendjobid=None, |
|
791 |
operstate="BUILD") |
|
792 |
self.reconciler.reconcile() |
|
793 |
# Assert not deleted |
|
794 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
795 |
self.assertFalse(vm1.deleted) |
|
796 |
self.assertEqual(vm1.operstate, "BUILD") |
|
797 |
|
|
798 |
vm1.created = vm1.created - timedelta(seconds=120) |
|
799 |
vm1.save() |
|
800 |
with mocked_quotaholder(): |
|
801 |
self.reconciler.reconcile() |
|
802 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
803 |
self.assertEqual(vm1.operstate, "ERROR") |
|
804 |
|
|
805 |
vm1 = mfactory.VirtualMachineFactory(backend=self.backend, |
|
806 |
backendjobid=1, |
|
807 |
deleted=False, |
|
808 |
operstate="BUILD") |
|
809 |
vm1.backendtime = vm1.created - timedelta(seconds=120) |
|
810 |
vm1.backendjobid = 10 |
|
811 |
vm1.save() |
|
812 |
for status in ["queued", "waiting", "running"]: |
|
813 |
mrapi.GetJobStatus.return_value = {"status": status} |
|
814 |
with mocked_quotaholder(): |
|
815 |
self.reconciler.reconcile() |
|
816 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
817 |
self.assertFalse(vm1.deleted) |
|
818 |
self.assertEqual(vm1.operstate, "BUILD") |
|
819 |
|
|
820 |
mrapi.GetJobStatus.return_value = {"status": "error"} |
|
821 |
with mocked_quotaholder(): |
|
822 |
self.reconciler.reconcile() |
|
823 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
824 |
self.assertFalse(vm1.deleted) |
|
825 |
self.assertEqual(vm1.operstate, "ERROR") |
|
826 |
|
|
827 |
for status in ["success", "cancelled"]: |
|
828 |
vm1.deleted = False |
|
829 |
vm1.save() |
|
830 |
mrapi.GetJobStatus.return_value = {"status": status} |
|
831 |
with mocked_quotaholder(): |
|
832 |
self.reconciler.reconcile() |
|
833 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
834 |
self.assertTrue(vm1.deleted) |
|
835 |
self.assertEqual(vm1.operstate, "DESTROYED") |
|
836 |
|
|
837 |
vm1 = mfactory.VirtualMachineFactory(backend=self.backend, |
|
838 |
backendjobid=1, |
|
839 |
operstate="BUILD") |
|
840 |
vm1.backendtime = vm1.created - timedelta(seconds=120) |
|
841 |
vm1.backendjobid = 10 |
|
842 |
vm1.save() |
|
843 |
cmrapi = self.reconciler.client |
|
844 |
cmrapi.GetInstances.return_value = \ |
|
845 |
[{"name": vm1.backend_vm_id, |
|
846 |
"beparams": {"maxmem": 1024, |
|
847 |
"minmem": 1024, |
|
848 |
"vcpus": 4}, |
|
849 |
"oper_state": False, |
|
850 |
"mtime": time(), |
|
851 |
"disk.sizes": [], |
|
852 |
"nic.ips": [], |
|
853 |
"nic.macs": [], |
|
854 |
"nic.networks": [], |
|
855 |
"tags": []}] |
|
856 |
mrapi.GetJobStatus.return_value = {"status": "running"} |
|
857 |
with mocked_quotaholder(): |
|
858 |
self.reconciler.reconcile() |
|
859 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
860 |
self.assertEqual(vm1.operstate, "BUILD") |
|
861 |
mrapi.GetJobStatus.return_value = {"status": "error"} |
|
862 |
with mocked_quotaholder(): |
|
863 |
self.reconciler.reconcile() |
|
864 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
865 |
self.assertEqual(vm1.operstate, "ERROR") |
|
866 |
|
|
867 |
def test_stale_server(self, mrapi): |
|
868 |
mrapi.GetInstances = [] |
|
869 |
vm1 = mfactory.VirtualMachineFactory(backend=self.backend, |
|
870 |
deleted=False, |
|
871 |
operstate="ERROR") |
|
872 |
with mocked_quotaholder(): |
|
873 |
self.reconciler.reconcile() |
|
874 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
875 |
self.assertTrue(vm1.deleted) |
|
876 |
|
|
877 |
def test_orphan_server(self, mrapi): |
|
878 |
cmrapi = self.reconciler.client |
|
879 |
mrapi().GetInstances.return_value =\ |
|
880 |
[{"name": "%s22" % settings.BACKEND_PREFIX_ID, |
|
881 |
"beparams": {"maxmem": 1024, |
|
882 |
"minmem": 1024, |
|
883 |
"vcpus": 4}, |
|
884 |
"oper_state": True, |
|
885 |
"mtime": time(), |
|
886 |
"disk.sizes": [], |
|
887 |
"nic.ips": [], |
|
888 |
"nic.macs": [], |
|
889 |
"nic.networks": [], |
|
890 |
"tags": []}] |
|
891 |
self.reconciler.reconcile() |
|
892 |
cmrapi.DeleteInstance.assert_called_once_with( |
|
893 |
"%s22" % settings.BACKEND_PREFIX_ID) |
|
894 |
|
|
895 |
def test_unsynced_operstate(self, mrapi): |
|
896 |
vm1 = mfactory.VirtualMachineFactory(backend=self.backend, |
|
897 |
deleted=False, |
|
898 |
operstate="STOPPED") |
|
899 |
mrapi().GetInstances.return_value =\ |
|
900 |
[{"name": vm1.backend_vm_id, |
|
901 |
"beparams": {"maxmem": 1024, |
|
902 |
"minmem": 1024, |
|
903 |
"vcpus": 4}, |
|
904 |
"oper_state": True, |
|
905 |
"mtime": time(), |
|
906 |
"disk.sizes": [], |
|
907 |
"nic.ips": [], |
|
908 |
"nic.macs": [], |
|
909 |
"nic.networks": [], |
|
910 |
"tags": []}] |
|
911 |
with mocked_quotaholder(): |
|
912 |
self.reconciler.reconcile() |
|
913 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
914 |
self.assertEqual(vm1.operstate, "STARTED") |
|
915 |
|
|
916 |
def test_unsynced_flavor(self, mrapi): |
|
917 |
flavor1 = mfactory.FlavorFactory(cpu=2, ram=1024, disk=1, |
|
918 |
disk_template="drbd") |
|
919 |
flavor2 = mfactory.FlavorFactory(cpu=4, ram=2048, disk=1, |
|
920 |
disk_template="drbd") |
|
921 |
vm1 = mfactory.VirtualMachineFactory(backend=self.backend, |
|
922 |
deleted=False, |
|
923 |
flavor=flavor1, |
|
924 |
operstate="STARTED") |
|
925 |
mrapi().GetInstances.return_value =\ |
|
926 |
[{"name": vm1.backend_vm_id, |
|
927 |
"beparams": {"maxmem": 2048, |
|
928 |
"minmem": 2048, |
|
929 |
"vcpus": 4}, |
|
930 |
"oper_state": True, |
|
931 |
"mtime": time(), |
|
932 |
"disk.sizes": [], |
|
933 |
"nic.ips": [], |
|
934 |
"nic.macs": [], |
|
935 |
"nic.networks": [], |
|
936 |
"tags": []}] |
|
937 |
with mocked_quotaholder(): |
|
938 |
self.reconciler.reconcile() |
|
939 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
940 |
self.assertEqual(vm1.flavor, flavor2) |
|
941 |
self.assertEqual(vm1.operstate, "STARTED") |
|
942 |
|
|
943 |
def test_unsynced_nics(self, mrapi): |
|
944 |
network1 = mfactory.NetworkFactory(subnet="10.0.0.0/24") |
|
945 |
network2 = mfactory.NetworkFactory(subnet="192.168.2.0/24") |
|
946 |
vm1 = mfactory.VirtualMachineFactory(backend=self.backend, |
|
947 |
deleted=False, |
|
948 |
operstate="STOPPED") |
|
949 |
mfactory.NetworkInterfaceFactory(machine=vm1, network=network1, |
|
950 |
ipv4="10.0.0.0") |
|
951 |
mrapi().GetInstances.return_value =\ |
|
952 |
[{"name": vm1.backend_vm_id, |
|
953 |
"beparams": {"maxmem": 2048, |
|
954 |
"minmem": 2048, |
|
955 |
"vcpus": 4}, |
|
956 |
"oper_state": True, |
|
957 |
"mtime": time(), |
|
958 |
"disk.sizes": [], |
|
959 |
"nic.ips": ["192.168.2.1"], |
|
960 |
"nic.macs": ["aa:00:bb:cc:dd:ee"], |
|
961 |
"nic.networks": [network2.backend_id], |
|
962 |
"tags": []}] |
|
963 |
with mocked_quotaholder(): |
|
964 |
self.reconciler.reconcile() |
|
965 |
vm1 = VirtualMachine.objects.get(id=vm1.id) |
|
966 |
self.assertEqual(vm1.operstate, "STARTED") |
|
967 |
nic = vm1.nics.all()[0] |
|
968 |
self.assertEqual(nic.network, network2) |
|
969 |
self.assertEqual(nic.ipv4, "192.168.2.1") |
|
970 |
self.assertEqual(nic.mac, "aa:00:bb:cc:dd:ee") |
|
971 |
|
|
849 | 972 |
|
850 | 973 |
from synnefo.logic.test.rapi_pool_tests import * |
851 | 974 |
from synnefo.logic.test.utils_tests import * |
Also available in: Unified diff