Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / tests.py @ 52194c77

History | View | Annotate | Download (22.5 kB)

1 b8033991 Georgios Gousios
# vim: set fileencoding=utf-8 :
2 47eeffa9 Christos Stavrakakis
# Copyright 2012 GRNET S.A. All rights reserved.
3 09c936a7 Vassilios Karakoidas
#
4 48130e66 Georgios Gousios
# Redistribution and use in source and binary forms, with or without
5 48130e66 Georgios Gousios
# modification, are permitted provided that the following conditions
6 48130e66 Georgios Gousios
# are met:
7 09c936a7 Vassilios Karakoidas
#
8 48130e66 Georgios Gousios
#   1. Redistributions of source code must retain the above copyright
9 48130e66 Georgios Gousios
#      notice, this list of conditions and the following disclaimer.
10 48130e66 Georgios Gousios
#
11 48130e66 Georgios Gousios
#  2. Redistributions in binary form must reproduce the above copyright
12 48130e66 Georgios Gousios
#     notice, this list of conditions and the following disclaimer in the
13 48130e66 Georgios Gousios
#     documentation and/or other materials provided with the distribution.
14 09c936a7 Vassilios Karakoidas
#
15 48130e66 Georgios Gousios
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
16 48130e66 Georgios Gousios
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 48130e66 Georgios Gousios
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 48130e66 Georgios Gousios
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19 48130e66 Georgios Gousios
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 48130e66 Georgios Gousios
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 48130e66 Georgios Gousios
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 48130e66 Georgios Gousios
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 48130e66 Georgios Gousios
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 48130e66 Georgios Gousios
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 48130e66 Georgios Gousios
# SUCH DAMAGE.
26 09c936a7 Vassilios Karakoidas
#
27 48130e66 Georgios Gousios
# The views and conclusions contained in the software and documentation are
28 48130e66 Georgios Gousios
# those of the authors and should not be interpreted as representing official
29 48130e66 Georgios Gousios
# policies, either expressed or implied, of GRNET S.A.
30 48130e66 Georgios Gousios
31 48130e66 Georgios Gousios
# Provides automated tests for logic module
32 92c53da1 Vassilios Karakoidas
33 c25cc9ec Vangelis Koukis
from random import randint
34 c25cc9ec Vangelis Koukis
35 c25cc9ec Vangelis Koukis
from django.test import TestCase
36 c25cc9ec Vangelis Koukis
37 420f2c20 Georgios Gousios
from synnefo.db.models import *
38 47eeffa9 Christos Stavrakakis
from synnefo.db import models_factory as mfactory
39 9fea53cc Vangelis Koukis
from synnefo.logic import reconciliation
40 47eeffa9 Christos Stavrakakis
from synnefo.lib.utils import split_time
41 47eeffa9 Christos Stavrakakis
from datetime import datetime
42 47eeffa9 Christos Stavrakakis
from mock import patch
43 47eeffa9 Christos Stavrakakis
from synnefo.api.util import allocate_resource
44 c8908e51 Christos Stavrakakis
from synnefo.logic.callbacks import (update_db, update_net, update_network,
45 c8908e51 Christos Stavrakakis
                                    update_build_progress)
46 47eeffa9 Christos Stavrakakis
47 47eeffa9 Christos Stavrakakis
now = datetime.now
48 47eeffa9 Christos Stavrakakis
from time import time
49 47eeffa9 Christos Stavrakakis
import json
50 47eeffa9 Christos Stavrakakis
51 47eeffa9 Christos Stavrakakis
## Test Callbacks
52 47eeffa9 Christos Stavrakakis
53 47eeffa9 Christos Stavrakakis
54 47eeffa9 Christos Stavrakakis
@patch('synnefo.lib.amqp.AMQPClient')
55 47eeffa9 Christos Stavrakakis
class UpdateDBTest(TestCase):
56 47eeffa9 Christos Stavrakakis
    def create_msg(self, **kwargs):
57 47eeffa9 Christos Stavrakakis
        """Create snf-ganeti-eventd message"""
58 47eeffa9 Christos Stavrakakis
        msg = {'event_time': split_time(time())}
59 47eeffa9 Christos Stavrakakis
        msg['type'] = 'ganeti-op-status'
60 47eeffa9 Christos Stavrakakis
        msg['status'] = 'success'
61 47eeffa9 Christos Stavrakakis
        msg['jobId'] = 1
62 47eeffa9 Christos Stavrakakis
        msg['logmsg'] = 'Dummy Log'
63 47eeffa9 Christos Stavrakakis
        for key, val in kwargs.items():
64 47eeffa9 Christos Stavrakakis
            msg[key] = val
65 47eeffa9 Christos Stavrakakis
        message = {'body': json.dumps(msg)}
66 47eeffa9 Christos Stavrakakis
        return message
67 47eeffa9 Christos Stavrakakis
68 47eeffa9 Christos Stavrakakis
    def test_missing_attribute(self, client):
69 47eeffa9 Christos Stavrakakis
        update_db(client, json.dumps({'body': {}}))
70 47eeffa9 Christos Stavrakakis
        client.basic_nack.assert_called_once()
71 47eeffa9 Christos Stavrakakis
72 47eeffa9 Christos Stavrakakis
    def test_unhandled_exception(self, client):
73 47eeffa9 Christos Stavrakakis
        update_db(client, {})
74 47eeffa9 Christos Stavrakakis
        client.basic_reject.assert_called_once()
75 47eeffa9 Christos Stavrakakis
76 47eeffa9 Christos Stavrakakis
    def test_missing_instance(self, client):
77 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_STARTUP',
78 47eeffa9 Christos Stavrakakis
                              instance='foo')
79 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
80 47eeffa9 Christos Stavrakakis
        client.basic_nack.assert_called_once()
81 47eeffa9 Christos Stavrakakis
82 47eeffa9 Christos Stavrakakis
    def test_wrong_type(self, client):
83 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(type="WRONG_TYPE")
84 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
85 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
86 47eeffa9 Christos Stavrakakis
87 47eeffa9 Christos Stavrakakis
    def test_start(self, client):
88 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
89 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_STARTUP',
90 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id)
91 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
92 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
93 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
94 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.operstate, 'STARTED')
95 47eeffa9 Christos Stavrakakis
96 47eeffa9 Christos Stavrakakis
    def test_stop(self, client):
97 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
98 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_SHUTDOWN',
99 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id)
100 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
101 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
102 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
103 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.operstate, 'STOPPED')
104 47eeffa9 Christos Stavrakakis
105 47eeffa9 Christos Stavrakakis
    def test_reboot(self, client):
106 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
107 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_REBOOT',
108 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id)
109 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
110 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
111 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
112 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.operstate, 'STARTED')
113 47eeffa9 Christos Stavrakakis
114 47eeffa9 Christos Stavrakakis
    def test_remove(self, client):
115 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
116 47eeffa9 Christos Stavrakakis
        # Also create a NIC
117 47eeffa9 Christos Stavrakakis
        mfactory.NetworkInterfaceFactory(machine=vm)
118 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_REMOVE',
119 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id)
120 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
121 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
122 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
123 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.operstate, 'DESTROYED')
124 47eeffa9 Christos Stavrakakis
        self.assertTrue(db_vm.deleted)
125 47eeffa9 Christos Stavrakakis
        # Check that nics are deleted
126 47eeffa9 Christos Stavrakakis
        self.assertFalse(db_vm.nics.all())
127 47eeffa9 Christos Stavrakakis
128 47eeffa9 Christos Stavrakakis
    def test_create(self, client):
129 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
130 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_CREATE',
131 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id)
132 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
133 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
134 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
135 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.operstate, 'STARTED')
136 47eeffa9 Christos Stavrakakis
137 47eeffa9 Christos Stavrakakis
    def test_create_error(self, client):
138 47eeffa9 Christos Stavrakakis
        """Test that error create sets vm to ERROR state"""
139 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
140 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_CREATE',
141 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id,
142 47eeffa9 Christos Stavrakakis
                              status='error')
143 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
144 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
145 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
146 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.operstate, 'ERROR')
147 47eeffa9 Christos Stavrakakis
148 47eeffa9 Christos Stavrakakis
    def test_remove_from_error(self, client):
149 47eeffa9 Christos Stavrakakis
        """Test that error removes delete error builds"""
150 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
151 47eeffa9 Christos Stavrakakis
        # Also create a NIC
152 47eeffa9 Christos Stavrakakis
        mfactory.NetworkInterfaceFactory(machine=vm)
153 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_REMOVE',
154 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id)
155 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
156 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
157 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
158 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.operstate, 'DESTROYED')
159 47eeffa9 Christos Stavrakakis
        self.assertTrue(db_vm.deleted)
160 47eeffa9 Christos Stavrakakis
        # Check that nics are deleted
161 47eeffa9 Christos Stavrakakis
        self.assertFalse(db_vm.nics.all())
162 47eeffa9 Christos Stavrakakis
163 47eeffa9 Christos Stavrakakis
    def test_other_error(self, client):
164 47eeffa9 Christos Stavrakakis
        """Test that other error messages do no affect the VM"""
165 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
166 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_STARTUP',
167 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id,
168 47eeffa9 Christos Stavrakakis
                              status='error')
169 47eeffa9 Christos Stavrakakis
        update_db(client, msg)
170 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
171 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
172 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.operstate, vm.operstate)
173 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_vm.backendtime, vm.backendtime)
174 47eeffa9 Christos Stavrakakis
175 47eeffa9 Christos Stavrakakis
176 47eeffa9 Christos Stavrakakis
@patch('synnefo.lib.amqp.AMQPClient')
177 47eeffa9 Christos Stavrakakis
class UpdateNetTest(TestCase):
178 47eeffa9 Christos Stavrakakis
    def create_msg(self, **kwargs):
179 47eeffa9 Christos Stavrakakis
        """Create snf-ganeti-hook message"""
180 47eeffa9 Christos Stavrakakis
        msg = {'event_time': split_time(time())}
181 47eeffa9 Christos Stavrakakis
        msg['type'] = 'ganeti-net-status'
182 47eeffa9 Christos Stavrakakis
        msg['status'] = 'success'
183 47eeffa9 Christos Stavrakakis
        msg['jobId'] = 1
184 47eeffa9 Christos Stavrakakis
        msg['logmsg'] = 'Dummy Log'
185 47eeffa9 Christos Stavrakakis
        for key, val in kwargs.items():
186 47eeffa9 Christos Stavrakakis
            msg[key] = val
187 47eeffa9 Christos Stavrakakis
        message = {'body': json.dumps(msg)}
188 47eeffa9 Christos Stavrakakis
        return message
189 47eeffa9 Christos Stavrakakis
190 47eeffa9 Christos Stavrakakis
    def test_missing_attribute(self, client):
191 47eeffa9 Christos Stavrakakis
        update_net(client, json.dumps({'body': {}}))
192 47eeffa9 Christos Stavrakakis
        client.basic_nack.assert_called_once()
193 47eeffa9 Christos Stavrakakis
194 47eeffa9 Christos Stavrakakis
    def test_unhandled_exception(self, client):
195 47eeffa9 Christos Stavrakakis
        update_net(client, {})
196 47eeffa9 Christos Stavrakakis
        client.basic_reject.assert_called_once()
197 47eeffa9 Christos Stavrakakis
198 47eeffa9 Christos Stavrakakis
    def test_wrong_type(self, client):
199 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(type="WRONG_TYPE")
200 47eeffa9 Christos Stavrakakis
        update_net(client, msg)
201 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
202 47eeffa9 Christos Stavrakakis
203 47eeffa9 Christos Stavrakakis
    def test_missing_instance(self, client):
204 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_INSTANCE_STARTUP',
205 47eeffa9 Christos Stavrakakis
                              instance='foo')
206 47eeffa9 Christos Stavrakakis
        update_net(client, msg)
207 47eeffa9 Christos Stavrakakis
        client.basic_nack.assert_called_once()
208 47eeffa9 Christos Stavrakakis
209 47eeffa9 Christos Stavrakakis
    def test_no_nics(self, client):
210 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
211 47eeffa9 Christos Stavrakakis
        mfactory.NetworkInterfaceFactory(machine=vm)
212 47eeffa9 Christos Stavrakakis
        mfactory.NetworkInterfaceFactory(machine=vm)
213 47eeffa9 Christos Stavrakakis
        mfactory.NetworkInterfaceFactory(machine=vm)
214 47eeffa9 Christos Stavrakakis
        self.assertEqual(len(vm.nics.all()), 3)
215 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(nics=[],
216 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id)
217 47eeffa9 Christos Stavrakakis
        update_net(client, msg)
218 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
219 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
220 47eeffa9 Christos Stavrakakis
        self.assertEqual(len(db_vm.nics.all()), 0)
221 47eeffa9 Christos Stavrakakis
222 47eeffa9 Christos Stavrakakis
    def test_empty_nic(self, client):
223 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
224 47eeffa9 Christos Stavrakakis
        for public in [True, False]:
225 47eeffa9 Christos Stavrakakis
            net = mfactory.NetworkFactory(public=public)
226 47eeffa9 Christos Stavrakakis
            msg = self.create_msg(nics=[{'network':net.backend_id}],
227 47eeffa9 Christos Stavrakakis
                                  instance=vm.backend_vm_id)
228 47eeffa9 Christos Stavrakakis
            update_net(client, msg)
229 47eeffa9 Christos Stavrakakis
            client.basic_ack.assert_called_once()
230 47eeffa9 Christos Stavrakakis
            db_vm = VirtualMachine.objects.get(id=vm.id)
231 47eeffa9 Christos Stavrakakis
            nics = db_vm.nics.all()
232 47eeffa9 Christos Stavrakakis
            self.assertEqual(len(nics), 1)
233 47eeffa9 Christos Stavrakakis
            self.assertEqual(nics[0].index, 0)
234 47eeffa9 Christos Stavrakakis
            self.assertEqual(nics[0].ipv4, '')
235 47eeffa9 Christos Stavrakakis
            self.assertEqual(nics[0].ipv6, '')
236 47eeffa9 Christos Stavrakakis
            self.assertEqual(nics[0].mac, '')
237 47eeffa9 Christos Stavrakakis
            if public:
238 47eeffa9 Christos Stavrakakis
                self.assertEqual(nics[0].firewall_profile,
239 47eeffa9 Christos Stavrakakis
                                 settings.DEFAULT_FIREWALL_PROFILE)
240 47eeffa9 Christos Stavrakakis
            else:
241 47eeffa9 Christos Stavrakakis
                self.assertEqual(nics[0].firewall_profile, '')
242 47eeffa9 Christos Stavrakakis
243 47eeffa9 Christos Stavrakakis
    def test_full_nic(self, client):
244 47eeffa9 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
245 47eeffa9 Christos Stavrakakis
        net = mfactory.NetworkFactory(subnet='10.0.0.0/24')
246 47eeffa9 Christos Stavrakakis
        pool = net.get_pool()
247 47eeffa9 Christos Stavrakakis
        self.assertTrue(pool.is_available('10.0.0.22'))
248 47eeffa9 Christos Stavrakakis
        pool.save()
249 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(nics=[{'network':net.backend_id,
250 47eeffa9 Christos Stavrakakis
                                     'ip': '10.0.0.22',
251 47eeffa9 Christos Stavrakakis
                                     'mac': 'aa:bb:cc:00:11:22'}],
252 47eeffa9 Christos Stavrakakis
                              instance=vm.backend_vm_id)
253 47eeffa9 Christos Stavrakakis
        update_net(client, msg)
254 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
255 47eeffa9 Christos Stavrakakis
        db_vm = VirtualMachine.objects.get(id=vm.id)
256 47eeffa9 Christos Stavrakakis
        nics = db_vm.nics.all()
257 47eeffa9 Christos Stavrakakis
        self.assertEqual(len(nics), 1)
258 47eeffa9 Christos Stavrakakis
        self.assertEqual(nics[0].index, 0)
259 47eeffa9 Christos Stavrakakis
        self.assertEqual(nics[0].ipv4, '10.0.0.22')
260 47eeffa9 Christos Stavrakakis
        self.assertEqual(nics[0].ipv6, '')
261 47eeffa9 Christos Stavrakakis
        self.assertEqual(nics[0].mac, 'aa:bb:cc:00:11:22')
262 47eeffa9 Christos Stavrakakis
        pool = net.get_pool()
263 47eeffa9 Christos Stavrakakis
        self.assertFalse(pool.is_available('10.0.0.22'))
264 47eeffa9 Christos Stavrakakis
        pool.save()
265 47eeffa9 Christos Stavrakakis
266 47eeffa9 Christos Stavrakakis
267 47eeffa9 Christos Stavrakakis
@patch('synnefo.lib.amqp.AMQPClient')
268 47eeffa9 Christos Stavrakakis
class UpdateNetworkTest(TestCase):
269 47eeffa9 Christos Stavrakakis
    def create_msg(self, **kwargs):
270 47eeffa9 Christos Stavrakakis
        """Create snf-ganeti-eventd message"""
271 47eeffa9 Christos Stavrakakis
        msg = {'event_time': split_time(time())}
272 47eeffa9 Christos Stavrakakis
        msg['type'] = 'ganeti-network-status'
273 47eeffa9 Christos Stavrakakis
        msg['status'] = 'success'
274 47eeffa9 Christos Stavrakakis
        msg['jobId'] = 1
275 47eeffa9 Christos Stavrakakis
        msg['logmsg'] = 'Dummy Log'
276 47eeffa9 Christos Stavrakakis
        for key, val in kwargs.items():
277 47eeffa9 Christos Stavrakakis
            msg[key] = val
278 47eeffa9 Christos Stavrakakis
        message = {'body': json.dumps(msg)}
279 47eeffa9 Christos Stavrakakis
        return message
280 47eeffa9 Christos Stavrakakis
281 47eeffa9 Christos Stavrakakis
    def test_missing_attribute(self, client):
282 47eeffa9 Christos Stavrakakis
        update_network(client, json.dumps({'body': {}}))
283 47eeffa9 Christos Stavrakakis
        client.basic_nack.assert_called_once()
284 47eeffa9 Christos Stavrakakis
285 47eeffa9 Christos Stavrakakis
    def test_unhandled_exception(self, client):
286 47eeffa9 Christos Stavrakakis
        update_network(client, {})
287 47eeffa9 Christos Stavrakakis
        client.basic_reject.assert_called_once()
288 47eeffa9 Christos Stavrakakis
289 47eeffa9 Christos Stavrakakis
    def test_wrong_type(self, client):
290 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(type="WRONG_TYPE")
291 47eeffa9 Christos Stavrakakis
        update_network(client, msg)
292 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
293 47eeffa9 Christos Stavrakakis
294 47eeffa9 Christos Stavrakakis
    def test_missing_network(self, client):
295 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_NETWORK_CREATE',
296 47eeffa9 Christos Stavrakakis
                              network='foo')
297 47eeffa9 Christos Stavrakakis
        update_network(client, msg)
298 47eeffa9 Christos Stavrakakis
        client.basic_nack.assert_called_once()
299 47eeffa9 Christos Stavrakakis
300 47eeffa9 Christos Stavrakakis
    def test_create(self, client):
301 47eeffa9 Christos Stavrakakis
        back_network = mfactory.BackendNetworkFactory(operstate='PENDING')
302 47eeffa9 Christos Stavrakakis
        net = back_network.network
303 47eeffa9 Christos Stavrakakis
        back1 = back_network.backend
304 47eeffa9 Christos Stavrakakis
305 47eeffa9 Christos Stavrakakis
        back_network2 = mfactory.BackendNetworkFactory(operstate='PENDING',
306 47eeffa9 Christos Stavrakakis
                                                       network=net)
307 47eeffa9 Christos Stavrakakis
        back2 = back_network2.backend
308 47eeffa9 Christos Stavrakakis
        # Message from first backend network
309 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_NETWORK_CONNECT',
310 47eeffa9 Christos Stavrakakis
                              network=net.backend_id,
311 47eeffa9 Christos Stavrakakis
                              cluster=back1.clustername)
312 47eeffa9 Christos Stavrakakis
        update_network(client, msg)
313 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
314 47eeffa9 Christos Stavrakakis
315 47eeffa9 Christos Stavrakakis
        back_net = BackendNetwork.objects.get(id=back_network.id)
316 47eeffa9 Christos Stavrakakis
        self.assertEqual(back_net.operstate, 'ACTIVE')
317 47eeffa9 Christos Stavrakakis
        db_net = Network.objects.get(id=net.id)
318 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_net.state, 'PENDING')
319 47eeffa9 Christos Stavrakakis
        # msg from second backend network
320 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_NETWORK_CONNECT',
321 47eeffa9 Christos Stavrakakis
                              network=net.backend_id,
322 47eeffa9 Christos Stavrakakis
                              cluster=back2.clustername)
323 47eeffa9 Christos Stavrakakis
        update_network(client, msg)
324 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
325 47eeffa9 Christos Stavrakakis
326 47eeffa9 Christos Stavrakakis
        db_net = Network.objects.get(id=net.id)
327 47eeffa9 Christos Stavrakakis
        self.assertEqual(db_net.state, 'ACTIVE')
328 47eeffa9 Christos Stavrakakis
        back_net = BackendNetwork.objects.get(id=back_network.id)
329 47eeffa9 Christos Stavrakakis
        self.assertEqual(back_net.operstate, 'ACTIVE')
330 47eeffa9 Christos Stavrakakis
331 47eeffa9 Christos Stavrakakis
    def test_disconnect(self, client):
332 47eeffa9 Christos Stavrakakis
        bn1 = mfactory.BackendNetworkFactory(operstate='ACTIVE')
333 47eeffa9 Christos Stavrakakis
        net1 = bn1.network
334 47eeffa9 Christos Stavrakakis
        net1.operstate = 'ACTIVE'
335 47eeffa9 Christos Stavrakakis
        net1.save()
336 47eeffa9 Christos Stavrakakis
        bn2 = mfactory.BackendNetworkFactory(operstate='ACTIVE',
337 47eeffa9 Christos Stavrakakis
                                             network=net1)
338 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_NETWORK_DISCONNECT',
339 47eeffa9 Christos Stavrakakis
                              network=net1.backend_id,
340 47eeffa9 Christos Stavrakakis
                              cluster=bn2.backend.clustername)
341 47eeffa9 Christos Stavrakakis
        update_network(client, msg)
342 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
343 47eeffa9 Christos Stavrakakis
        self.assertEqual(Network.objects.get(id=net1.id).state, 'PENDING')
344 47eeffa9 Christos Stavrakakis
        self.assertEqual(BackendNetwork.objects.get(id=bn2.id).operstate,
345 47eeffa9 Christos Stavrakakis
                        'PENDING')
346 47eeffa9 Christos Stavrakakis
347 47eeffa9 Christos Stavrakakis
    def test_remove(self, client):
348 47eeffa9 Christos Stavrakakis
        mfactory.MacPrefixPoolTableFactory()
349 47eeffa9 Christos Stavrakakis
        mfactory.BridgePoolTableFactory()
350 47eeffa9 Christos Stavrakakis
        bn = mfactory.BackendNetworkFactory(operstate='ACTIVE')
351 47eeffa9 Christos Stavrakakis
        for old_state in ['success', 'canceled', 'error']:
352 47eeffa9 Christos Stavrakakis
            for flavor in Network.FLAVORS.keys():
353 47eeffa9 Christos Stavrakakis
                bn.operstate = old_state
354 47eeffa9 Christos Stavrakakis
                bn.save()
355 47eeffa9 Christos Stavrakakis
                net = bn.network
356 47eeffa9 Christos Stavrakakis
                net.state = 'ACTIVE'
357 47eeffa9 Christos Stavrakakis
                net.flavor = flavor
358 47eeffa9 Christos Stavrakakis
                if flavor == 'PHYSICAL_VLAN':
359 47eeffa9 Christos Stavrakakis
                    net.link = allocate_resource('bridge')
360 47eeffa9 Christos Stavrakakis
                if flavor == 'MAC_FILTERED':
361 47eeffa9 Christos Stavrakakis
                    net.mac_prefix = allocate_resource('mac_prefix')
362 47eeffa9 Christos Stavrakakis
                net.save()
363 47eeffa9 Christos Stavrakakis
                msg = self.create_msg(operation='OP_NETWORK_REMOVE',
364 47eeffa9 Christos Stavrakakis
                                      network=net.backend_id,
365 47eeffa9 Christos Stavrakakis
                                      cluster=bn.backend.clustername)
366 47eeffa9 Christos Stavrakakis
                update_network(client, msg)
367 47eeffa9 Christos Stavrakakis
                client.basic_ack.assert_called_once()
368 47eeffa9 Christos Stavrakakis
                db_bnet = BackendNetwork.objects.get(id=bn.id)
369 47eeffa9 Christos Stavrakakis
                self.assertEqual(db_bnet.operstate,
370 47eeffa9 Christos Stavrakakis
                                'DELETED')
371 47eeffa9 Christos Stavrakakis
                db_net = Network.objects.get(id=net.id)
372 47eeffa9 Christos Stavrakakis
                self.assertEqual(db_net.state, 'DELETED', flavor)
373 47eeffa9 Christos Stavrakakis
                self.assertTrue(db_net.deleted)
374 47eeffa9 Christos Stavrakakis
                if flavor == 'PHYSICAL_VLAN':
375 47eeffa9 Christos Stavrakakis
                    pool = BridgePoolTable.get_pool()
376 47eeffa9 Christos Stavrakakis
                    self.assertTrue(pool.is_available(net.link))
377 47eeffa9 Christos Stavrakakis
                if flavor == 'MAC_FILTERED':
378 47eeffa9 Christos Stavrakakis
                    pool = MacPrefixPoolTable.get_pool()
379 47eeffa9 Christos Stavrakakis
                    self.assertTrue(pool.is_available(net.mac_prefix))
380 47eeffa9 Christos Stavrakakis
381 47eeffa9 Christos Stavrakakis
    def test_error_opcode(self, client):
382 47eeffa9 Christos Stavrakakis
        for state, _ in Network.OPER_STATES:
383 47eeffa9 Christos Stavrakakis
            bn = mfactory.BackendNetworkFactory()
384 47eeffa9 Christos Stavrakakis
            bn.operstate = state
385 47eeffa9 Christos Stavrakakis
            bn.save()
386 47eeffa9 Christos Stavrakakis
            network = bn.network
387 47eeffa9 Christos Stavrakakis
            network.state = state
388 47eeffa9 Christos Stavrakakis
            network.save()
389 47eeffa9 Christos Stavrakakis
            for opcode, _ in BackendNetwork.BACKEND_OPCODES:
390 47eeffa9 Christos Stavrakakis
                if opcode in ['OP_NETWORK_REMOVE', 'OP_NETWORK_ADD']:
391 47eeffa9 Christos Stavrakakis
                    continue
392 47eeffa9 Christos Stavrakakis
                msg = self.create_msg(operation=opcode,
393 47eeffa9 Christos Stavrakakis
                                      network=bn.network.backend_id,
394 47eeffa9 Christos Stavrakakis
                                      status='error',
395 47eeffa9 Christos Stavrakakis
                                      cluster=bn.backend.clustername)
396 47eeffa9 Christos Stavrakakis
                update_network(client, msg)
397 47eeffa9 Christos Stavrakakis
                client.basic_ack.assert_called_once()
398 47eeffa9 Christos Stavrakakis
                db_bnet = BackendNetwork.objects.get(id=bn.id)
399 47eeffa9 Christos Stavrakakis
                self.assertEqual(bn.operstate, db_bnet.operstate)
400 47eeffa9 Christos Stavrakakis
                self.assertEqual(bn.network.state, db_bnet.network.state)
401 47eeffa9 Christos Stavrakakis
402 47eeffa9 Christos Stavrakakis
    def test_ips(self, client):
403 47eeffa9 Christos Stavrakakis
        network = mfactory.NetworkFactory(subnet='10.0.0.0/24')
404 47eeffa9 Christos Stavrakakis
        bn = mfactory.BackendNetworkFactory(network=network)
405 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_NETWORK_SET_PARAMS',
406 47eeffa9 Christos Stavrakakis
                              network=network.backend_id,
407 47eeffa9 Christos Stavrakakis
                              cluster=bn.backend.clustername,
408 47eeffa9 Christos Stavrakakis
                              status='success',
409 47eeffa9 Christos Stavrakakis
                              add_reserved_ips=['10.0.0.10', '10.0.0.20'],
410 47eeffa9 Christos Stavrakakis
                              remove_reserved_ips=[])
411 47eeffa9 Christos Stavrakakis
        update_network(client, msg)
412 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
413 47eeffa9 Christos Stavrakakis
        pool = network.get_pool()
414 47eeffa9 Christos Stavrakakis
        self.assertTrue(pool.is_reserved('10.0.0.10'))
415 47eeffa9 Christos Stavrakakis
        self.assertTrue(pool.is_reserved('10.0.0.20'))
416 47eeffa9 Christos Stavrakakis
        pool.save()
417 47eeffa9 Christos Stavrakakis
        # Release them
418 47eeffa9 Christos Stavrakakis
        msg = self.create_msg(operation='OP_NETWORK_SET_PARAMS',
419 47eeffa9 Christos Stavrakakis
                              network=network.backend_id,
420 47eeffa9 Christos Stavrakakis
                              cluster=bn.backend.clustername,
421 47eeffa9 Christos Stavrakakis
                              add_reserved_ips=[],
422 47eeffa9 Christos Stavrakakis
                              remove_reserved_ips=['10.0.0.10', '10.0.0.20'])
423 47eeffa9 Christos Stavrakakis
        update_network(client, msg)
424 47eeffa9 Christos Stavrakakis
        client.basic_ack.assert_called_once()
425 47eeffa9 Christos Stavrakakis
        pool = network.get_pool()
426 47eeffa9 Christos Stavrakakis
        self.assertFalse(pool.is_reserved('10.0.0.10'))
427 47eeffa9 Christos Stavrakakis
        self.assertFalse(pool.is_reserved('10.0.0.20'))
428 95aee02c Vangelis Koukis
429 92c53da1 Vassilios Karakoidas
430 c8908e51 Christos Stavrakakis
@patch('synnefo.lib.amqp.AMQPClient')
431 c8908e51 Christos Stavrakakis
class UpdateBuildProgressTest(TestCase):
432 c8908e51 Christos Stavrakakis
    def setUp(self):
433 c8908e51 Christos Stavrakakis
        self.vm = mfactory.VirtualMachineFactory()
434 95aee02c Vangelis Koukis
435 c8908e51 Christos Stavrakakis
    def get_db_vm(self):
436 c8908e51 Christos Stavrakakis
        return VirtualMachine.objects.get(id=self.vm.id)
437 95aee02c Vangelis Koukis
438 c8908e51 Christos Stavrakakis
    def create_msg(self, **kwargs):
439 c8908e51 Christos Stavrakakis
        """Create snf-progress-monitor message"""
440 c8908e51 Christos Stavrakakis
        msg = {'event_time': split_time(time())}
441 c8908e51 Christos Stavrakakis
        msg['type'] = 'image-copy-progress'
442 c8908e51 Christos Stavrakakis
        msg['progress'] = 0
443 c8908e51 Christos Stavrakakis
        for key, val in kwargs.items():
444 c8908e51 Christos Stavrakakis
            msg[key] = val
445 c8908e51 Christos Stavrakakis
        message = {'body': json.dumps(msg)}
446 c8908e51 Christos Stavrakakis
        return message
447 95aee02c Vangelis Koukis
448 c8908e51 Christos Stavrakakis
    def test_missing_attribute(self, client):
449 c8908e51 Christos Stavrakakis
        update_build_progress(client, json.dumps({'body': {}}))
450 c8908e51 Christos Stavrakakis
        client.basic_nack.assert_called_once()
451 95aee02c Vangelis Koukis
452 c8908e51 Christos Stavrakakis
    def test_unhandled_exception(self, client):
453 c8908e51 Christos Stavrakakis
        update_build_progress(client, {})
454 c8908e51 Christos Stavrakakis
        client.basic_reject.assert_called_once()
455 c25cc9ec Vangelis Koukis
456 c8908e51 Christos Stavrakakis
    def test_missing_instance(self, client):
457 c8908e51 Christos Stavrakakis
        msg = self.create_msg(instance='foo')
458 c8908e51 Christos Stavrakakis
        update_build_progress(client, msg)
459 c8908e51 Christos Stavrakakis
        client.basic_nack.assert_called_once()
460 9068cd85 Georgios Gousios
461 c8908e51 Christos Stavrakakis
    def test_wrong_type(self, client):
462 c8908e51 Christos Stavrakakis
        msg = self.create_msg(type="WRONG_TYPE")
463 c8908e51 Christos Stavrakakis
        update_build_progress(client, msg)
464 c8908e51 Christos Stavrakakis
        client.basic_ack.assert_called_once()
465 9068cd85 Georgios Gousios
466 c8908e51 Christos Stavrakakis
    def test_progress_update(self, client):
467 c25cc9ec Vangelis Koukis
        rprogress = randint(10, 100)
468 c8908e51 Christos Stavrakakis
        msg = self.create_msg(progress=rprogress,
469 c8908e51 Christos Stavrakakis
                              instance=self.vm.backend_vm_id)
470 c8908e51 Christos Stavrakakis
        update_build_progress(client, msg)
471 c8908e51 Christos Stavrakakis
        client.basic_ack.assert_called_once()
472 c8908e51 Christos Stavrakakis
        vm = self.get_db_vm()
473 c8908e51 Christos Stavrakakis
        self.assertEqual(vm.buildpercentage, rprogress)
474 c8908e51 Christos Stavrakakis
475 c8908e51 Christos Stavrakakis
    def test_invalid_value(self, client):
476 c8908e51 Christos Stavrakakis
        old = self.vm.buildpercentage
477 c8908e51 Christos Stavrakakis
        for rprogress in [0, -1, 'a']:
478 c8908e51 Christos Stavrakakis
            msg = self.create_msg(progress=rprogress,
479 c8908e51 Christos Stavrakakis
                                  instance=self.vm.backend_vm_id)
480 c8908e51 Christos Stavrakakis
            update_build_progress(client, msg)
481 c8908e51 Christos Stavrakakis
            client.basic_ack.assert_called_once()
482 c8908e51 Christos Stavrakakis
            vm = self.get_db_vm()
483 c8908e51 Christos Stavrakakis
            self.assertEqual(vm.buildpercentage, old)
484 9068cd85 Georgios Gousios
485 9fea53cc Vangelis Koukis
486 c8908e51 Christos Stavrakakis
class ReconciliationTest(TestCase):
487 9fea53cc Vangelis Koukis
    SERVERS = 1000
488 9fea53cc Vangelis Koukis
    fixtures = ['db_test_data']
489 9fea53cc Vangelis Koukis
490 9fea53cc Vangelis Koukis
    def test_get_servers_from_db(self):
491 9fea53cc Vangelis Koukis
        """Test getting a dictionary from each server to its operstate"""
492 9fea53cc Vangelis Koukis
        self.assertEquals(reconciliation.get_servers_from_db(),
493 9fea53cc Vangelis Koukis
                          {30000: 'STARTED', 30001: 'STOPPED', 30002: 'BUILD'})
494 9fea53cc Vangelis Koukis
495 9fea53cc Vangelis Koukis
    def test_stale_servers_in_db(self):
496 9fea53cc Vangelis Koukis
        """Test discovery of stale entries in DB"""
497 9fea53cc Vangelis Koukis
498 47eeffa9 Christos Stavrakakis
        D = {1: 'STARTED', 2: 'STOPPED', 3: 'STARTED', 30000: 'BUILD',
499 47eeffa9 Christos Stavrakakis
             30002: 'STOPPED'}
500 47eeffa9 Christos Stavrakakis
        G = {1: True, 3: True, 30000: True}
501 9fea53cc Vangelis Koukis
        self.assertEquals(reconciliation.stale_servers_in_db(D, G),
502 47eeffa9 Christos Stavrakakis
                          set([2, 30002]))
503 9fea53cc Vangelis Koukis
504 c8908e51 Christos Stavrakakis
    @patch("synnefo.db.models.get_rapi_client")
505 c8908e51 Christos Stavrakakis
    def test_stale_building_vm(self, client):
506 c8908e51 Christos Stavrakakis
        vm = mfactory.VirtualMachineFactory()
507 c8908e51 Christos Stavrakakis
        vm.state = 'BUILD'
508 c8908e51 Christos Stavrakakis
        vm.backendjobid = 42
509 c8908e51 Christos Stavrakakis
        vm.save()
510 c8908e51 Christos Stavrakakis
        D = {vm.id: 'BUILD'}
511 c8908e51 Christos Stavrakakis
        G = {}
512 c8908e51 Christos Stavrakakis
        for status in ['queued', 'waiting', 'running']:
513 c8908e51 Christos Stavrakakis
            client.return_value.GetJobStatus.return_value = {'status': status}
514 c8908e51 Christos Stavrakakis
            self.assertEqual(reconciliation.stale_servers_in_db(D, G), set([]))
515 c8908e51 Christos Stavrakakis
            client.return_value.GetJobStatus.assert_called_once_with(vm.backendjobid)
516 c8908e51 Christos Stavrakakis
            client.reset_mock()
517 c8908e51 Christos Stavrakakis
        for status in ['success', 'error', 'canceled']:
518 c8908e51 Christos Stavrakakis
            client.return_value.GetJobStatus.return_value = {'status': status}
519 c8908e51 Christos Stavrakakis
            self.assertEqual(reconciliation.stale_servers_in_db(D, G), set([]))
520 c8908e51 Christos Stavrakakis
            client.return_value.GetInstance.assert_called_once_with(vm.backend_vm_id)
521 c8908e51 Christos Stavrakakis
            client.return_value.GetJobStatus.assert_called_once_with(vm.backendjobid)
522 c8908e51 Christos Stavrakakis
            client.reset_mock()
523 c8908e51 Christos Stavrakakis
        from synnefo.logic.rapi import GanetiApiError
524 c8908e51 Christos Stavrakakis
        client.return_value.GetJobStatus.side_effect = GanetiApiError('Foo')
525 c8908e51 Christos Stavrakakis
        self.assertEqual(reconciliation.stale_servers_in_db(D, G), set([vm.id]))
526 c8908e51 Christos Stavrakakis
527 9fea53cc Vangelis Koukis
    def test_orphan_instances_in_ganeti(self):
528 9fea53cc Vangelis Koukis
        """Test discovery of orphan instances in Ganeti, without a DB entry"""
529 9fea53cc Vangelis Koukis
530 9fea53cc Vangelis Koukis
        G = {1: True, 2: False, 3: False, 4: True, 50: True}
531 9fea53cc Vangelis Koukis
        D = {1: True, 3: False}
532 9fea53cc Vangelis Koukis
        self.assertEquals(reconciliation.orphan_instances_in_ganeti(D, G),
533 46704e06 Vangelis Koukis
                          set([2, 4, 50]))
534 9fea53cc Vangelis Koukis
535 9fea53cc Vangelis Koukis
    def test_unsynced_operstate(self):
536 9fea53cc Vangelis Koukis
        """Test discovery of unsynced operstate between the DB and Ganeti"""
537 9fea53cc Vangelis Koukis
538 9fea53cc Vangelis Koukis
        G = {1: True, 2: False, 3: True, 4: False, 50: True}
539 9fea53cc Vangelis Koukis
        D = {1: 'STARTED', 2: 'STARTED', 3: 'BUILD', 4: 'STARTED', 50: 'BUILD'}
540 9fea53cc Vangelis Koukis
        self.assertEquals(reconciliation.unsynced_operstate(D, G),
541 46704e06 Vangelis Koukis
                          set([(2, 'STARTED', False),
542 9fea53cc Vangelis Koukis
                           (3, 'BUILD', True), (4, 'STARTED', False),
543 46704e06 Vangelis Koukis
                           (50, 'BUILD', True)]))