Revision 47eeffa9 snf-cyclades-app/synnefo/logic/tests.py

b/snf-cyclades-app/synnefo/logic/tests.py
1 1
# vim: set fileencoding=utf-8 :
2
# Copyright 2011 GRNET S.A. All rights reserved.
2
# Copyright 2012 GRNET S.A. All rights reserved.
3 3
#
4 4
# Redistribution and use in source and binary forms, with or without
5 5
# modification, are permitted provided that the following conditions
......
30 30

  
31 31
# Provides automated tests for logic module
32 32

  
33
import time
34
import hashlib
35 33
from random import randint
36 34

  
37 35
from django.test import TestCase
38
from django.conf import settings
39 36

  
40 37
from synnefo.db.models import *
38
from synnefo.db import models_factory as mfactory
41 39
from synnefo.logic import backend
42 40
from synnefo.logic import reconciliation
43 41
from synnefo.logic.utils import get_rsapi_state
42
from synnefo.lib.utils import split_time
43
from datetime import datetime
44
from mock import patch
45
from synnefo.api.util import allocate_resource
46
from synnefo.logic.callbacks import update_db, update_net, update_network
47

  
48
now = datetime.now
49
from time import time
50
import json
51

  
52
## Test Callbacks
53

  
54

  
55
@patch('synnefo.lib.amqp.AMQPClient')
56
class UpdateDBTest(TestCase):
57
    def create_msg(self, **kwargs):
58
        """Create snf-ganeti-eventd message"""
59
        msg = {'event_time': split_time(time())}
60
        msg['type'] = 'ganeti-op-status'
61
        msg['status'] = 'success'
62
        msg['jobId'] = 1
63
        msg['logmsg'] = 'Dummy Log'
64
        for key, val in kwargs.items():
65
            msg[key] = val
66
        message = {'body': json.dumps(msg)}
67
        return message
68

  
69
    def test_missing_attribute(self, client):
70
        update_db(client, json.dumps({'body': {}}))
71
        client.basic_nack.assert_called_once()
72

  
73
    def test_unhandled_exception(self, client):
74
        update_db(client, {})
75
        client.basic_reject.assert_called_once()
76

  
77
    def test_missing_instance(self, client):
78
        msg = self.create_msg(operation='OP_INSTANCE_STARTUP',
79
                              instance='foo')
80
        update_db(client, msg)
81
        client.basic_nack.assert_called_once()
82

  
83
    def test_wrong_type(self, client):
84
        msg = self.create_msg(type="WRONG_TYPE")
85
        update_db(client, msg)
86
        client.basic_ack.assert_called_once()
87

  
88
    def test_start(self, client):
89
        vm = mfactory.VirtualMachineFactory()
90
        msg = self.create_msg(operation='OP_INSTANCE_STARTUP',
91
                              instance=vm.backend_vm_id)
92
        update_db(client, msg)
93
        client.basic_ack.assert_called_once()
94
        db_vm = VirtualMachine.objects.get(id=vm.id)
95
        self.assertEqual(db_vm.operstate, 'STARTED')
96

  
97
    def test_stop(self, client):
98
        vm = mfactory.VirtualMachineFactory()
99
        msg = self.create_msg(operation='OP_INSTANCE_SHUTDOWN',
100
                              instance=vm.backend_vm_id)
101
        update_db(client, msg)
102
        client.basic_ack.assert_called_once()
103
        db_vm = VirtualMachine.objects.get(id=vm.id)
104
        self.assertEqual(db_vm.operstate, 'STOPPED')
105

  
106
    def test_reboot(self, client):
107
        vm = mfactory.VirtualMachineFactory()
108
        msg = self.create_msg(operation='OP_INSTANCE_REBOOT',
109
                              instance=vm.backend_vm_id)
110
        update_db(client, msg)
111
        client.basic_ack.assert_called_once()
112
        db_vm = VirtualMachine.objects.get(id=vm.id)
113
        self.assertEqual(db_vm.operstate, 'STARTED')
114

  
115
    def test_remove(self, client):
116
        vm = mfactory.VirtualMachineFactory()
117
        # Also create a NIC
118
        mfactory.NetworkInterfaceFactory(machine=vm)
119
        msg = self.create_msg(operation='OP_INSTANCE_REMOVE',
120
                              instance=vm.backend_vm_id)
121
        update_db(client, msg)
122
        client.basic_ack.assert_called_once()
123
        db_vm = VirtualMachine.objects.get(id=vm.id)
124
        self.assertEqual(db_vm.operstate, 'DESTROYED')
125
        self.assertTrue(db_vm.deleted)
126
        # Check that nics are deleted
127
        self.assertFalse(db_vm.nics.all())
128

  
129
    def test_create(self, client):
130
        vm = mfactory.VirtualMachineFactory()
131
        msg = self.create_msg(operation='OP_INSTANCE_CREATE',
132
                              instance=vm.backend_vm_id)
133
        update_db(client, msg)
134
        client.basic_ack.assert_called_once()
135
        db_vm = VirtualMachine.objects.get(id=vm.id)
136
        self.assertEqual(db_vm.operstate, 'STARTED')
137

  
138
    def test_create_error(self, client):
139
        """Test that error create sets vm to ERROR state"""
140
        vm = mfactory.VirtualMachineFactory()
141
        msg = self.create_msg(operation='OP_INSTANCE_CREATE',
142
                              instance=vm.backend_vm_id,
143
                              status='error')
144
        update_db(client, msg)
145
        client.basic_ack.assert_called_once()
146
        db_vm = VirtualMachine.objects.get(id=vm.id)
147
        self.assertEqual(db_vm.operstate, 'ERROR')
148

  
149
    def test_remove_from_error(self, client):
150
        """Test that error removes delete error builds"""
151
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
152
        # Also create a NIC
153
        mfactory.NetworkInterfaceFactory(machine=vm)
154
        msg = self.create_msg(operation='OP_INSTANCE_REMOVE',
155
                              instance=vm.backend_vm_id)
156
        update_db(client, msg)
157
        client.basic_ack.assert_called_once()
158
        db_vm = VirtualMachine.objects.get(id=vm.id)
159
        self.assertEqual(db_vm.operstate, 'DESTROYED')
160
        self.assertTrue(db_vm.deleted)
161
        # Check that nics are deleted
162
        self.assertFalse(db_vm.nics.all())
163

  
164
    def test_other_error(self, client):
165
        """Test that other error messages do no affect the VM"""
166
        vm = mfactory.VirtualMachineFactory()
167
        msg = self.create_msg(operation='OP_INSTANCE_STARTUP',
168
                              instance=vm.backend_vm_id,
169
                              status='error')
170
        update_db(client, msg)
171
        client.basic_ack.assert_called_once()
172
        db_vm = VirtualMachine.objects.get(id=vm.id)
173
        self.assertEqual(db_vm.operstate, vm.operstate)
174
        self.assertEqual(db_vm.backendtime, vm.backendtime)
175

  
176

  
177
@patch('synnefo.lib.amqp.AMQPClient')
178
class UpdateNetTest(TestCase):
179
    def create_msg(self, **kwargs):
180
        """Create snf-ganeti-hook message"""
181
        msg = {'event_time': split_time(time())}
182
        msg['type'] = 'ganeti-net-status'
183
        msg['status'] = 'success'
184
        msg['jobId'] = 1
185
        msg['logmsg'] = 'Dummy Log'
186
        for key, val in kwargs.items():
187
            msg[key] = val
188
        message = {'body': json.dumps(msg)}
189
        return message
190

  
191
    def test_missing_attribute(self, client):
192
        update_net(client, json.dumps({'body': {}}))
193
        client.basic_nack.assert_called_once()
194

  
195
    def test_unhandled_exception(self, client):
196
        update_net(client, {})
197
        client.basic_reject.assert_called_once()
198

  
199
    def test_wrong_type(self, client):
200
        msg = self.create_msg(type="WRONG_TYPE")
201
        update_net(client, msg)
202
        client.basic_ack.assert_called_once()
203

  
204
    def test_missing_instance(self, client):
205
        msg = self.create_msg(operation='OP_INSTANCE_STARTUP',
206
                              instance='foo')
207
        update_net(client, msg)
208
        client.basic_nack.assert_called_once()
209

  
210
    def test_no_nics(self, client):
211
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
212
        mfactory.NetworkInterfaceFactory(machine=vm)
213
        mfactory.NetworkInterfaceFactory(machine=vm)
214
        mfactory.NetworkInterfaceFactory(machine=vm)
215
        self.assertEqual(len(vm.nics.all()), 3)
216
        msg = self.create_msg(nics=[],
217
                              instance=vm.backend_vm_id)
218
        update_net(client, msg)
219
        client.basic_ack.assert_called_once()
220
        db_vm = VirtualMachine.objects.get(id=vm.id)
221
        self.assertEqual(len(db_vm.nics.all()), 0)
222

  
223
    def test_empty_nic(self, client):
224
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
225
        for public in [True, False]:
226
            net = mfactory.NetworkFactory(public=public)
227
            msg = self.create_msg(nics=[{'network':net.backend_id}],
228
                                  instance=vm.backend_vm_id)
229
            update_net(client, msg)
230
            client.basic_ack.assert_called_once()
231
            db_vm = VirtualMachine.objects.get(id=vm.id)
232
            nics = db_vm.nics.all()
233
            self.assertEqual(len(nics), 1)
234
            self.assertEqual(nics[0].index, 0)
235
            self.assertEqual(nics[0].ipv4, '')
236
            self.assertEqual(nics[0].ipv6, '')
237
            self.assertEqual(nics[0].mac, '')
238
            if public:
239
                self.assertEqual(nics[0].firewall_profile,
240
                                 settings.DEFAULT_FIREWALL_PROFILE)
241
            else:
242
                self.assertEqual(nics[0].firewall_profile, '')
243

  
244
    def test_full_nic(self, client):
245
        vm = mfactory.VirtualMachineFactory(operstate='ERROR')
246
        net = mfactory.NetworkFactory(subnet='10.0.0.0/24')
247
        pool = net.get_pool()
248
        self.assertTrue(pool.is_available('10.0.0.22'))
249
        pool.save()
250
        msg = self.create_msg(nics=[{'network':net.backend_id,
251
                                     'ip': '10.0.0.22',
252
                                     'mac': 'aa:bb:cc:00:11:22'}],
253
                              instance=vm.backend_vm_id)
254
        update_net(client, msg)
255
        client.basic_ack.assert_called_once()
256
        db_vm = VirtualMachine.objects.get(id=vm.id)
257
        nics = db_vm.nics.all()
258
        self.assertEqual(len(nics), 1)
259
        self.assertEqual(nics[0].index, 0)
260
        self.assertEqual(nics[0].ipv4, '10.0.0.22')
261
        self.assertEqual(nics[0].ipv6, '')
262
        self.assertEqual(nics[0].mac, 'aa:bb:cc:00:11:22')
263
        pool = net.get_pool()
264
        self.assertFalse(pool.is_available('10.0.0.22'))
265
        pool.save()
266

  
267

  
268
@patch('synnefo.lib.amqp.AMQPClient')
269
class UpdateNetworkTest(TestCase):
270
    def create_msg(self, **kwargs):
271
        """Create snf-ganeti-eventd message"""
272
        msg = {'event_time': split_time(time())}
273
        msg['type'] = 'ganeti-network-status'
274
        msg['status'] = 'success'
275
        msg['jobId'] = 1
276
        msg['logmsg'] = 'Dummy Log'
277
        for key, val in kwargs.items():
278
            msg[key] = val
279
        message = {'body': json.dumps(msg)}
280
        return message
281

  
282
    def test_missing_attribute(self, client):
283
        update_network(client, json.dumps({'body': {}}))
284
        client.basic_nack.assert_called_once()
285

  
286
    def test_unhandled_exception(self, client):
287
        update_network(client, {})
288
        client.basic_reject.assert_called_once()
289

  
290
    def test_wrong_type(self, client):
291
        msg = self.create_msg(type="WRONG_TYPE")
292
        update_network(client, msg)
293
        client.basic_ack.assert_called_once()
294

  
295
    def test_missing_network(self, client):
296
        msg = self.create_msg(operation='OP_NETWORK_CREATE',
297
                              network='foo')
298
        update_network(client, msg)
299
        client.basic_nack.assert_called_once()
300

  
301
    def test_create(self, client):
302
        back_network = mfactory.BackendNetworkFactory(operstate='PENDING')
303
        net = back_network.network
304
        back1 = back_network.backend
305

  
306
        back_network2 = mfactory.BackendNetworkFactory(operstate='PENDING',
307
                                                       network=net)
308
        back2 = back_network2.backend
309
        # Message from first backend network
310
        msg = self.create_msg(operation='OP_NETWORK_CONNECT',
311
                              network=net.backend_id,
312
                              cluster=back1.clustername)
313
        update_network(client, msg)
314
        client.basic_ack.assert_called_once()
315

  
316
        back_net = BackendNetwork.objects.get(id=back_network.id)
317
        self.assertEqual(back_net.operstate, 'ACTIVE')
318
        db_net = Network.objects.get(id=net.id)
319
        self.assertEqual(db_net.state, 'PENDING')
320
        # msg from second backend network
321
        msg = self.create_msg(operation='OP_NETWORK_CONNECT',
322
                              network=net.backend_id,
323
                              cluster=back2.clustername)
324
        update_network(client, msg)
325
        client.basic_ack.assert_called_once()
326

  
327
        db_net = Network.objects.get(id=net.id)
328
        self.assertEqual(db_net.state, 'ACTIVE')
329
        back_net = BackendNetwork.objects.get(id=back_network.id)
330
        self.assertEqual(back_net.operstate, 'ACTIVE')
331

  
332
    def test_disconnect(self, client):
333
        bn1 = mfactory.BackendNetworkFactory(operstate='ACTIVE')
334
        net1 = bn1.network
335
        net1.operstate = 'ACTIVE'
336
        net1.save()
337
        bn2 = mfactory.BackendNetworkFactory(operstate='ACTIVE',
338
                                             network=net1)
339
        msg = self.create_msg(operation='OP_NETWORK_DISCONNECT',
340
                              network=net1.backend_id,
341
                              cluster=bn2.backend.clustername)
342
        update_network(client, msg)
343
        client.basic_ack.assert_called_once()
344
        self.assertEqual(Network.objects.get(id=net1.id).state, 'PENDING')
345
        self.assertEqual(BackendNetwork.objects.get(id=bn2.id).operstate,
346
                        'PENDING')
347

  
348
    def test_remove(self, client):
349
        mfactory.MacPrefixPoolTableFactory()
350
        mfactory.BridgePoolTableFactory()
351
        bn = mfactory.BackendNetworkFactory(operstate='ACTIVE')
352
        for old_state in ['success', 'canceled', 'error']:
353
            for flavor in Network.FLAVORS.keys():
354
                bn.operstate = old_state
355
                bn.save()
356
                net = bn.network
357
                net.state = 'ACTIVE'
358
                net.flavor = flavor
359
                if flavor == 'PHYSICAL_VLAN':
360
                    net.link = allocate_resource('bridge')
361
                if flavor == 'MAC_FILTERED':
362
                    net.mac_prefix = allocate_resource('mac_prefix')
363
                net.save()
364
                msg = self.create_msg(operation='OP_NETWORK_REMOVE',
365
                                      network=net.backend_id,
366
                                      cluster=bn.backend.clustername)
367
                update_network(client, msg)
368
                client.basic_ack.assert_called_once()
369
                db_bnet = BackendNetwork.objects.get(id=bn.id)
370
                self.assertEqual(db_bnet.operstate,
371
                                'DELETED')
372
                db_net = Network.objects.get(id=net.id)
373
                self.assertEqual(db_net.state, 'DELETED', flavor)
374
                self.assertTrue(db_net.deleted)
375
                if flavor == 'PHYSICAL_VLAN':
376
                    pool = BridgePoolTable.get_pool()
377
                    self.assertTrue(pool.is_available(net.link))
378
                if flavor == 'MAC_FILTERED':
379
                    pool = MacPrefixPoolTable.get_pool()
380
                    self.assertTrue(pool.is_available(net.mac_prefix))
381

  
382
    def test_error_opcode(self, client):
383
        for state, _ in Network.OPER_STATES:
384
            bn = mfactory.BackendNetworkFactory()
385
            bn.operstate = state
386
            bn.save()
387
            network = bn.network
388
            network.state = state
389
            network.save()
390
            for opcode, _ in BackendNetwork.BACKEND_OPCODES:
391
                if opcode in ['OP_NETWORK_REMOVE', 'OP_NETWORK_ADD']:
392
                    continue
393
                msg = self.create_msg(operation=opcode,
394
                                      network=bn.network.backend_id,
395
                                      status='error',
396
                                      cluster=bn.backend.clustername)
397
                update_network(client, msg)
398
                client.basic_ack.assert_called_once()
399
                db_bnet = BackendNetwork.objects.get(id=bn.id)
400
                self.assertEqual(bn.operstate, db_bnet.operstate)
401
                self.assertEqual(bn.network.state, db_bnet.network.state)
402

  
403
    def test_ips(self, client):
404
        network = mfactory.NetworkFactory(subnet='10.0.0.0/24')
405
        bn = mfactory.BackendNetworkFactory(network=network)
406
        msg = self.create_msg(operation='OP_NETWORK_SET_PARAMS',
407
                              network=network.backend_id,
408
                              cluster=bn.backend.clustername,
409
                              status='success',
410
                              add_reserved_ips=['10.0.0.10', '10.0.0.20'],
411
                              remove_reserved_ips=[])
412
        update_network(client, msg)
413
        client.basic_ack.assert_called_once()
414
        pool = network.get_pool()
415
        self.assertTrue(pool.is_reserved('10.0.0.10'))
416
        self.assertTrue(pool.is_reserved('10.0.0.20'))
417
        pool.save()
418
        # Release them
419
        msg = self.create_msg(operation='OP_NETWORK_SET_PARAMS',
420
                              network=network.backend_id,
421
                              cluster=bn.backend.clustername,
422
                              add_reserved_ips=[],
423
                              remove_reserved_ips=['10.0.0.10', '10.0.0.20'])
424
        update_network(client, msg)
425
        client.basic_ack.assert_called_once()
426
        pool = network.get_pool()
427
        self.assertFalse(pool.is_reserved('10.0.0.10'))
428
        self.assertFalse(pool.is_reserved('10.0.0.20'))
44 429

  
45 430

  
46 431
class ProcessOpStatusTestCase(TestCase):
......
62 447

  
63 448
        # This machine is initially in BUILD
64 449
        vm = VirtualMachine.objects.get(pk=30002)
65
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
450
        backend.process_op_status(vm, now(), msg["jobId"], msg["operation"],
66 451
                                  msg["status"], msg["logmsg"])
67 452
        self.assertEquals(get_rsapi_state(vm), 'ACTIVE')
68 453

  
......
74 459

  
75 460
        # This machine is initially in BUILD
76 461
        vm = VirtualMachine.objects.get(pk=30002)
77
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
462
        backend.process_op_status(vm, now(), msg["jobId"], msg["operation"],
78 463
                                  msg["status"], msg["logmsg"])
79 464
        self.assertEquals(get_rsapi_state(vm), 'STOPPED')
80 465

  
......
86 471

  
87 472
        # This machine is initially in BUILD
88 473
        vm = VirtualMachine.objects.get(pk=30002)
89
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
474
        backend.process_op_status(vm, now(), msg["jobId"], msg["operation"],
90 475
                                  msg["status"], msg["logmsg"])
91 476
        self.assertEquals(get_rsapi_state(vm), 'ACTIVE')
92 477

  
......
98 483

  
99 484
        # This machine is initially in BUILD
100 485
        vm = VirtualMachine.objects.get(pk=30002)
101
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
486
        backend.process_op_status(vm, now(), msg["jobId"], msg["operation"],
102 487
                                  msg["status"], msg["logmsg"])
103 488
        self.assertEquals(get_rsapi_state(vm), 'ACTIVE')
104 489

  
......
110 495

  
111 496
        # This machine is initially in BUILD
112 497
        vm = VirtualMachine.objects.get(pk=30002)
113
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
498
        backend.process_op_status(vm, now(), msg["jobId"], msg["operation"],
114 499
                                  msg["status"], msg["logmsg"])
115 500
        self.assertEquals(get_rsapi_state(vm), 'DELETED')
116 501
        self.assertTrue(vm.deleted)
......
123 508

  
124 509
        # This machine is initially in BUILD
125 510
        vm = VirtualMachine.objects.get(pk=30002)
126
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
511
        backend.process_op_status(vm, now(), msg["jobId"], msg["operation"],
127 512
                                  msg["status"], msg["logmsg"])
128 513
        self.assertEquals(get_rsapi_state(vm), 'ERROR')
129 514
        self.assertFalse(vm.deleted)
......
136 521

  
137 522
        # This machine is initially in BUILD
138 523
        vm = VirtualMachine.objects.get(pk=30002)
139
        backend.process_op_status(vm, 0, "OP_INSTANCE_CREATE", "error", "test")
524
        backend.process_op_status(vm, now(), 0, "OP_INSTANCE_CREATE", "error", "test")
140 525
        self.assertEquals(get_rsapi_state(vm), 'ERROR')
141 526

  
142
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
527
        backend.process_op_status(vm, now(), msg["jobId"], msg["operation"],
143 528
                                  msg["status"], msg["logmsg"])
144 529
        self.assertEquals(get_rsapi_state(vm), 'DELETED')
145 530
        self.assertTrue(vm.deleted)
......
153 538
        msg = {'instance': 'instance-name',
154 539
               'type':     'ganeti-net-status',
155 540
               'nics': [
156
                   {'ip': '192.168.33.1', 'mac': 'aa:00:00:58:1e:b9'}
541
                   {'ip': '10.0.0.21',
542
                    'mac': 'aa:00:00:58:1e:b9',
543
                    'network':'snf-net-30000'}
157 544
               ]
158 545
        }
159 546
        vm = VirtualMachine.objects.get(pk=30000)
160
        backend.process_net_status(vm, msg['nics'])
161
        self.assertEquals(vm.nics.all()[0].ipv4, '192.168.33.1')
547
        backend.process_net_status(vm, now(), msg['nics'])
548
        self.assertEquals(vm.nics.all()[0].ipv4, '10.0.0.21')
162 549

  
163 550
    def test_set_empty_ipv4(self):
164 551
        """Test reception of a net status notification with no IPv4 assigned"""
165 552
        msg = {'instance': 'instance-name',
166 553
               'type':     'ganeti-net-status',
167 554
               'nics': [
168
                   {'ip': '', 'mac': 'aa:00:00:58:1e:b9'}
555
                   {'ip': '',
556
                    'mac': 'aa:00:00:58:1e:b9',
557
                    'network':'snf-net-30000'}
169 558
               ]
170 559
        }
171 560
        vm = VirtualMachine.objects.get(pk=30000)
172
        backend.process_net_status(vm, msg['nics'])
561
        backend.process_net_status(vm, now(), msg['nics'])
173 562
        self.assertEquals(vm.nics.all()[0].ipv4, '')
174 563

  
175 564

  
......
183 572
        vm = VirtualMachine.objects.get(pk=30002)
184 573
        rprogress = randint(10, 100)
185 574

  
186
        backend.process_create_progress(vm, rprogress, 0)
575
        backend.process_create_progress(vm, now(), rprogress)
187 576
        self.assertEquals(vm.buildpercentage, rprogress)
188 577

  
189 578
        #self.assertRaises(ValueError, backend.process_create_progress,
190 579
        #                  vm, 9, 0)
191 580
        self.assertRaises(ValueError, backend.process_create_progress,
192
                          vm, -1, 0)
581
                          now(), vm, -1)
193 582
        self.assertRaises(ValueError, backend.process_create_progress,
194
                          vm, 'a', 0)
583
                          now(), vm, 'a')
195 584

  
196 585
        # This machine is ACTIVE
197 586
        #vm = VirtualMachine.objects.get(pk=30000)
......
212 601
    def test_stale_servers_in_db(self):
213 602
        """Test discovery of stale entries in DB"""
214 603

  
215
        D = {1: 'STARTED', 2: 'STOPPED', 3: 'STARTED', 4: 'BUILD', 5: 'BUILD'}
216
        G = {1: True, 3: True}
604
        D = {1: 'STARTED', 2: 'STOPPED', 3: 'STARTED', 30000: 'BUILD',
605
             30002: 'STOPPED'}
606
        G = {1: True, 3: True, 30000: True}
217 607
        self.assertEquals(reconciliation.stale_servers_in_db(D, G),
218
                          set([2, 4, 5]))
608
                          set([2, 30002]))
219 609

  
220 610
    def test_orphan_instances_in_ganeti(self):
221 611
        """Test discovery of orphan instances in Ganeti, without a DB entry"""

Also available in: Unified diff