~ubuntu-branches/ubuntu/quantal/nova/quantal-proposed

« back to all changes in this revision

Viewing changes to nova/tests/compute/test_compute.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-08-16 14:04:11 UTC
  • mto: This revision was merged to the branch mainline in revision 84.
  • Revision ID: package-import@ubuntu.com-20120816140411-0mr4n241wmk30t9l
Tags: upstream-2012.2~f3
ImportĀ upstreamĀ versionĀ 2012.2~f3

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
#    under the License.
19
19
"""Tests for compute service"""
20
20
 
 
21
import base64
21
22
import copy
22
23
import datetime
 
24
import functools
23
25
import sys
24
26
import time
25
27
 
27
29
 
28
30
import nova
29
31
from nova import compute
30
 
from nova.compute import aggregate_states
31
32
from nova.compute import api as compute_api
32
33
from nova.compute import instance_types
33
34
from nova.compute import manager as compute_manager
39
40
from nova import db
40
41
from nova import exception
41
42
from nova import flags
42
 
from nova.notifier import test_notifier
43
43
from nova.openstack.common import importutils
 
44
from nova.openstack.common import jsonutils
44
45
from nova.openstack.common import log as logging
 
46
from nova.openstack.common.notifier import api as notifier_api
 
47
from nova.openstack.common.notifier import test_notifier
45
48
from nova.openstack.common import policy as common_policy
46
49
from nova.openstack.common import rpc
47
50
from nova.openstack.common.rpc import common as rpc_common
50
53
from nova import quota
51
54
from nova.scheduler import driver as scheduler_driver
52
55
from nova import test
 
56
from nova.tests.db.fakes import FakeModel
53
57
from nova.tests import fake_network
54
58
from nova.tests.image import fake as fake_image
55
59
from nova import utils
61
65
FLAGS = flags.FLAGS
62
66
flags.DECLARE('stub_network', 'nova.compute.manager')
63
67
flags.DECLARE('live_migration_retry_count', 'nova.compute.manager')
64
 
flags.DECLARE('additional_compute_capabilities', 'nova.compute.manager')
65
68
 
66
69
 
67
70
FAKE_IMAGE_REF = 'fake-image-ref'
103
106
    pass
104
107
 
105
108
 
 
109
class FakeSchedulerAPI(object):
 
110
    def run_instance(self, *args, **kwargs):
 
111
        pass
 
112
 
 
113
 
106
114
class BaseTestCase(test.TestCase):
107
115
 
108
116
    def setUp(self):
109
117
        super(BaseTestCase, self).setUp()
110
118
        self.flags(compute_driver='nova.virt.fake.FakeDriver',
111
119
                   stub_network=True,
112
 
                   notification_driver='nova.notifier.test_notifier',
 
120
         notification_driver=['nova.openstack.common.notifier.test_notifier'],
113
121
                   network_manager='nova.network.manager.FlatManager')
114
122
        self.compute = importutils.import_object(FLAGS.compute_manager)
115
123
 
121
129
 
122
130
        def fake_show(meh, context, id):
123
131
            return {'id': id, 'min_disk': None, 'min_ram': None,
 
132
                    'name': 'fake_name',
124
133
                    'properties': {'kernel_id': 'fake_kernel_id',
125
134
                                   'ramdisk_id': 'fake_ramdisk_id',
126
135
                                   'something_else': 'meow'}}
130
139
        self.stubs.Set(rpc, 'call', rpc_call_wrapper)
131
140
        self.stubs.Set(rpc, 'cast', rpc_cast_wrapper)
132
141
 
 
142
        fake_rpcapi = FakeSchedulerAPI()
 
143
        self.stubs.Set(self.compute, 'scheduler_rpcapi', fake_rpcapi)
 
144
 
133
145
    def tearDown(self):
134
146
        fake_image.FakeImageService_reset()
135
147
        instances = db.instance_get_all(self.context.elevated())
 
148
        notifier_api._reset_drivers()
136
149
        for instance in instances:
137
150
            db.instance_destroy(self.context.elevated(), instance['uuid'])
138
151
        super(BaseTestCase, self).tearDown()
203
216
                       fake_get_nw_info)
204
217
        self.stubs.Set(nova.network.API, 'allocate_for_instance',
205
218
                       fake_get_nw_info)
 
219
        self.compute_api = compute.API()
206
220
 
207
221
    def tearDown(self):
208
222
        super(ComputeTestCase, self).tearDown()
216
230
        def did_it_add_fault(*args):
217
231
            called['fault_added'] = True
218
232
 
219
 
        self.stubs.Set(self.compute, 'add_instance_fault_from_exc',
 
233
        self.stubs.Set(self.compute, '_add_instance_fault_from_exc',
220
234
                       did_it_add_fault)
221
235
 
222
236
        @nova.compute.manager.wrap_instance_fault
224
238
            raise NotImplementedError()
225
239
 
226
240
        self.assertRaises(NotImplementedError, failer,
227
 
                          self.compute, self.context, inst_uuid)
 
241
                          self.compute, self.context, instance_uuid=inst_uuid)
228
242
 
229
243
        self.assertTrue(called['fault_added'])
230
244
 
236
250
        def did_it_add_fault(*args):
237
251
            called['fault_added'] = True
238
252
 
239
 
        self.stubs.Set(self.compute, 'add_instance_fault_from_exc',
 
253
        self.stubs.Set(self.compute, '_add_instance_fault_from_exc',
240
254
                       did_it_add_fault)
241
255
 
242
256
        @nova.compute.manager.wrap_instance_fault
251
265
    def test_create_instance_with_img_ref_associates_config_drive(self):
252
266
        """Make sure create associates a config drive."""
253
267
 
254
 
        instance = self._create_fake_instance(
255
 
                        params={'config_drive': '1234', })
 
268
        instance = jsonutils.to_primitive(self._create_fake_instance(
 
269
                        params={'config_drive': '1234', }))
256
270
 
257
271
        try:
258
 
            self.compute.run_instance(self.context, instance['uuid'])
 
272
            self.compute.run_instance(self.context, instance=instance)
259
273
            instances = db.instance_get_all(context.get_admin_context())
260
274
            instance = instances[0]
261
275
 
266
280
    def test_create_instance_associates_config_drive(self):
267
281
        """Make sure create associates a config drive."""
268
282
 
269
 
        instance = self._create_fake_instance(
270
 
                        params={'config_drive': '1234', })
 
283
        instance = jsonutils.to_primitive(self._create_fake_instance(
 
284
                        params={'config_drive': '1234', }))
271
285
 
272
286
        try:
273
 
            self.compute.run_instance(self.context, instance['uuid'])
 
287
            self.compute.run_instance(self.context, instance=instance)
274
288
            instances = db.instance_get_all(context.get_admin_context())
275
289
            instance = instances[0]
276
290
 
280
294
 
281
295
    def test_default_access_ip(self):
282
296
        self.flags(default_access_ip_network_name='test1', stub_network=False)
283
 
        instance = self._create_fake_instance()
 
297
        instance = jsonutils.to_primitive(self._create_fake_instance())
284
298
 
285
299
        try:
286
 
            self.compute.run_instance(self.context, instance['uuid'],
 
300
            self.compute.run_instance(self.context, instance=instance,
287
301
                    is_first_time=True)
288
302
            instances = db.instance_get_all(context.get_admin_context())
289
303
            instance = instances[0]
294
308
            db.instance_destroy(self.context, instance['uuid'])
295
309
 
296
310
    def test_no_default_access_ip(self):
297
 
        instance = self._create_fake_instance()
 
311
        instance = jsonutils.to_primitive(self._create_fake_instance())
298
312
 
299
313
        try:
300
 
            self.compute.run_instance(self.context, instance['uuid'],
 
314
            self.compute.run_instance(self.context, instance=instance,
301
315
                    is_first_time=True)
302
316
            instances = db.instance_get_all(context.get_admin_context())
303
317
            instance = instances[0]
328
342
                       '_setup_block_device_mapping', fake)
329
343
        instance_uuid = self._create_instance()
330
344
        self.assertRaises(test.TestingException, self.compute.run_instance,
331
 
                          self.context, instance_uuid)
 
345
                          self.context, instance_uuid=instance_uuid)
332
346
        #check state is failed even after the periodic poll
333
347
        self._assert_state({'vm_state': vm_states.ERROR,
334
 
                            'task_state': task_states.BLOCK_DEVICE_MAPPING})
 
348
                            'task_state': None})
335
349
        self.compute.periodic_tasks(context.get_admin_context())
336
350
        self._assert_state({'vm_state': vm_states.ERROR,
337
 
                            'task_state': task_states.BLOCK_DEVICE_MAPPING})
 
351
                            'task_state': None})
338
352
 
339
353
    def test_run_instance_spawn_fail(self):
340
354
        """ spawn failure test.
346
360
        self.stubs.Set(self.compute.driver, 'spawn', fake)
347
361
        instance_uuid = self._create_instance()
348
362
        self.assertRaises(test.TestingException, self.compute.run_instance,
349
 
                          self.context, instance_uuid)
 
363
                          self.context, instance_uuid=instance_uuid)
350
364
        #check state is failed even after the periodic poll
351
365
        self._assert_state({'vm_state': vm_states.ERROR,
352
 
                            'task_state': task_states.SPAWNING})
 
366
                            'task_state': None})
353
367
        self.compute.periodic_tasks(context.get_admin_context())
354
368
        self._assert_state({'vm_state': vm_states.ERROR,
355
 
                            'task_state': task_states.SPAWNING})
 
369
                            'task_state': None})
356
370
 
357
371
    def test_can_terminate_on_error_state(self):
358
372
        """Make sure that the instance can be terminated in ERROR state"""
360
374
        #check failed to schedule --> terminate
361
375
        instance_uuid = self._create_instance(params={'vm_state':
362
376
                                                vm_states.ERROR})
363
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
377
        inst_ref = db.instance_get_by_uuid(elevated, instance_uuid)
 
378
        instance = jsonutils.to_primitive(inst_ref)
 
379
        self.compute.terminate_instance(self.context, instance=instance)
364
380
        self.assertRaises(exception.InstanceNotFound, db.instance_get_by_uuid,
365
381
                          elevated, instance_uuid)
366
382
 
367
383
    def test_run_terminate(self):
368
384
        """Make sure it is possible to  run and terminate instance"""
369
 
        instance = self._create_fake_instance()
370
 
 
371
 
        self.compute.run_instance(self.context, instance['uuid'])
372
 
 
373
 
        instances = db.instance_get_all(context.get_admin_context())
374
 
        LOG.info(_("Running instances: %s"), instances)
375
 
        self.assertEqual(len(instances), 1)
376
 
 
377
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
385
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
386
 
 
387
        self.compute.run_instance(self.context, instance=instance)
 
388
 
 
389
        instances = db.instance_get_all(context.get_admin_context())
 
390
        LOG.info(_("Running instances: %s"), instances)
 
391
        self.assertEqual(len(instances), 1)
 
392
 
 
393
        self.compute.terminate_instance(self.context, instance=instance)
 
394
 
 
395
        instances = db.instance_get_all(context.get_admin_context())
 
396
        LOG.info(_("After terminating instances: %s"), instances)
 
397
        self.assertEqual(len(instances), 0)
 
398
 
 
399
    def test_terminate_no_network(self):
 
400
        # This is as reported in LP bug 1008875
 
401
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
402
 
 
403
        self.compute.run_instance(self.context, instance=instance)
 
404
 
 
405
        instances = db.instance_get_all(context.get_admin_context())
 
406
        LOG.info(_("Running instances: %s"), instances)
 
407
        self.assertEqual(len(instances), 1)
 
408
 
 
409
        # Make it look like this is no instance
 
410
        self.mox.StubOutWithMock(self.compute, '_get_instance_nw_info')
 
411
        self.compute._get_instance_nw_info(
 
412
                mox.IgnoreArg(),
 
413
                mox.IgnoreArg()).AndRaise(exception.NetworkNotFound())
 
414
        self.mox.ReplayAll()
 
415
 
 
416
        self.compute.terminate_instance(self.context, instance=instance)
378
417
 
379
418
        instances = db.instance_get_all(context.get_admin_context())
380
419
        LOG.info(_("After terminating instances: %s"), instances)
382
421
 
383
422
    def test_run_terminate_timestamps(self):
384
423
        """Make sure timestamps are set for launched and destroyed"""
385
 
        instance = self._create_fake_instance()
 
424
        instance = jsonutils.to_primitive(self._create_fake_instance())
386
425
        self.assertEqual(instance['launched_at'], None)
387
426
        self.assertEqual(instance['deleted_at'], None)
388
427
        launch = timeutils.utcnow()
389
 
        self.compute.run_instance(self.context, instance['uuid'])
 
428
        self.compute.run_instance(self.context, instance=instance)
390
429
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
391
430
        self.assert_(instance['launched_at'] > launch)
392
431
        self.assertEqual(instance['deleted_at'], None)
393
432
        terminate = timeutils.utcnow()
394
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
433
        self.compute.terminate_instance(self.context, instance=instance)
395
434
        context = self.context.elevated(read_deleted="only")
396
435
        instance = db.instance_get_by_uuid(context, instance['uuid'])
397
436
        self.assert_(instance['launched_at'] < terminate)
399
438
 
400
439
    def test_stop(self):
401
440
        """Ensure instance can be stopped"""
402
 
        instance = self._create_fake_instance()
403
 
        instance_uuid = instance['uuid']
404
 
        self.compute.run_instance(self.context, instance_uuid)
405
 
        self.compute.stop_instance(self.context, instance_uuid)
406
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
441
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
442
        self.compute.run_instance(self.context, instance=instance)
 
443
        self.compute.stop_instance(self.context, instance=instance)
 
444
        self.compute.terminate_instance(self.context, instance=instance)
407
445
 
408
446
    def test_start(self):
409
447
        """Ensure instance can be started"""
410
 
        instance = self._create_fake_instance()
411
 
        instance_uuid = instance['uuid']
412
 
        self.compute.run_instance(self.context, instance_uuid)
413
 
        self.compute.stop_instance(self.context, instance_uuid)
414
 
        self.compute.start_instance(self.context, instance_uuid)
415
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
448
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
449
        self.compute.run_instance(self.context, instance=instance)
 
450
        self.compute.stop_instance(self.context, instance=instance)
 
451
        self.compute.start_instance(self.context, instance=instance)
 
452
        self.compute.terminate_instance(self.context, instance=instance)
416
453
 
417
454
    def test_rescue(self):
418
455
        """Ensure instance can be rescued and unrescued"""
420
457
        called = {'rescued': False,
421
458
                  'unrescued': False}
422
459
 
423
 
        def fake_rescue(self, context, instance_ref, network_info, image_meta):
 
460
        def fake_rescue(self, context, instance_ref, network_info, image_meta,
 
461
                        rescue_password):
424
462
            called['rescued'] = True
425
463
 
426
464
        self.stubs.Set(nova.virt.fake.FakeDriver, 'rescue', fake_rescue)
431
469
        self.stubs.Set(nova.virt.fake.FakeDriver, 'unrescue',
432
470
                       fake_unrescue)
433
471
 
434
 
        instance = self._create_fake_instance()
 
472
        instance = jsonutils.to_primitive(self._create_fake_instance())
435
473
        instance_uuid = instance['uuid']
436
 
        self.compute.run_instance(self.context, instance_uuid)
437
 
        self.compute.rescue_instance(self.context, instance_uuid)
438
 
        self.assertTrue(called['rescued'])
439
 
        self.compute.unrescue_instance(self.context, instance_uuid)
440
 
        self.assertTrue(called['unrescued'])
441
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
474
        self.compute.run_instance(self.context, instance=instance)
 
475
 
 
476
        # Make sure these methods work with both instance and instance_uuid
 
477
 
 
478
        self.compute.rescue_instance(self.context, instance=instance)
 
479
        self.assertTrue(called['rescued'])
 
480
        self.compute.unrescue_instance(self.context, instance=instance)
 
481
        self.assertTrue(called['unrescued'])
 
482
 
 
483
        self.compute.rescue_instance(self.context, instance_uuid=instance_uuid)
 
484
        self.assertTrue(called['rescued'])
 
485
        self.compute.unrescue_instance(self.context,
 
486
                                       instance_uuid=instance_uuid)
 
487
        self.assertTrue(called['unrescued'])
 
488
 
 
489
        self.compute.terminate_instance(self.context, instance=instance)
442
490
 
443
491
    def test_power_on(self):
444
492
        """Ensure instance can be powered on"""
451
499
        self.stubs.Set(nova.virt.fake.FakeDriver, 'power_on',
452
500
                       fake_driver_power_on)
453
501
 
454
 
        instance = self._create_fake_instance()
455
 
        instance_uuid = instance['uuid']
456
 
        self.compute.run_instance(self.context, instance_uuid)
457
 
        self.compute.power_on_instance(self.context, instance_uuid)
 
502
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
503
        self.compute.run_instance(self.context, instance=instance)
 
504
        self.compute.power_on_instance(self.context, instance=instance)
458
505
        self.assertTrue(called['power_on'])
459
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
506
        self.compute.terminate_instance(self.context, instance=instance)
460
507
 
461
508
    def test_power_off(self):
462
509
        """Ensure instance can be powered off"""
469
516
        self.stubs.Set(nova.virt.fake.FakeDriver, 'power_off',
470
517
                       fake_driver_power_off)
471
518
 
472
 
        instance = self._create_fake_instance()
473
 
        instance_uuid = instance['uuid']
474
 
        self.compute.run_instance(self.context, instance_uuid)
475
 
        self.compute.power_off_instance(self.context, instance_uuid)
 
519
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
520
        self.compute.run_instance(self.context, instance=instance)
 
521
        self.compute.power_off_instance(self.context, instance=instance)
476
522
        self.assertTrue(called['power_off'])
477
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
523
        self.compute.terminate_instance(self.context, instance=instance)
478
524
 
479
525
    def test_pause(self):
480
526
        """Ensure instance can be paused and unpaused"""
481
 
        instance = self._create_fake_instance()
482
 
        instance_uuid = instance['uuid']
483
 
        self.compute.run_instance(self.context, instance_uuid)
484
 
        self.compute.pause_instance(self.context, instance_uuid)
485
 
        self.compute.unpause_instance(self.context, instance_uuid)
486
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
527
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
528
        self.compute.run_instance(self.context, instance=instance)
 
529
        self.compute.pause_instance(self.context, instance=instance)
 
530
        self.compute.unpause_instance(self.context, instance=instance)
 
531
        self.compute.terminate_instance(self.context, instance=instance)
487
532
 
488
533
    def test_suspend(self):
489
534
        """ensure instance can be suspended and resumed"""
490
 
        instance = self._create_fake_instance()
 
535
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
536
        self.compute.run_instance(self.context, instance=instance)
 
537
        self.compute.suspend_instance(self.context, instance=instance)
 
538
        self.compute.resume_instance(self.context, instance=instance)
 
539
        self.compute.terminate_instance(self.context, instance=instance)
 
540
 
 
541
    def test_suspend_error(self):
 
542
        """Ensure vm_state is ERROR when suspend error occurs"""
 
543
        def fake(*args, **kwargs):
 
544
            raise test.TestingException()
 
545
        self.stubs.Set(self.compute.driver, 'suspend', fake)
 
546
 
 
547
        instance = jsonutils.to_primitive(self._create_fake_instance())
491
548
        instance_uuid = instance['uuid']
492
 
        self.compute.run_instance(self.context, instance_uuid)
493
 
        self.compute.suspend_instance(self.context, instance_uuid)
494
 
        self.compute.resume_instance(self.context, instance_uuid)
495
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
549
        self.compute.run_instance(self.context, instance=instance)
 
550
        self.assertRaises(test.TestingException,
 
551
                          self.compute.suspend_instance,
 
552
                          self.context,
 
553
                          instance=instance)
 
554
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
555
        self.assertEqual(instance['vm_state'], vm_states.ERROR)
 
556
        self.compute.terminate_instance(self.context, instance=instance)
496
557
 
497
558
    def test_rebuild(self):
498
559
        """Ensure instance can be rebuilt"""
499
 
        instance = self._create_fake_instance()
500
 
        instance_uuid = instance['uuid']
 
560
        instance = jsonutils.to_primitive(self._create_fake_instance())
501
561
        image_ref = instance['image_ref']
502
562
 
503
 
        self.compute.run_instance(self.context, instance_uuid)
504
 
        self.compute.rebuild_instance(self.context, instance_uuid,
505
 
                image_ref, image_ref)
506
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
563
        self.compute.run_instance(self.context, instance=instance)
 
564
        self.compute.rebuild_instance(self.context, image_ref, image_ref,
 
565
                instance=instance)
 
566
        self.compute.terminate_instance(self.context, instance=instance)
507
567
 
508
568
    def test_rebuild_launch_time(self):
509
569
        """Ensure instance can be rebuilt"""
510
570
        old_time = datetime.datetime(2012, 4, 1)
511
571
        cur_time = datetime.datetime(2012, 12, 21, 12, 21)
512
572
        timeutils.set_time_override(old_time)
513
 
        instance = self._create_fake_instance()
 
573
        instance = jsonutils.to_primitive(self._create_fake_instance())
514
574
        instance_uuid = instance['uuid']
515
575
        image_ref = instance['image_ref']
516
576
 
517
 
        self.compute.run_instance(self.context, instance_uuid)
 
577
        self.compute.run_instance(self.context, instance=instance)
518
578
        timeutils.set_time_override(cur_time)
519
 
        self.compute.rebuild_instance(self.context, instance_uuid,
520
 
                image_ref, image_ref)
 
579
        self.compute.rebuild_instance(self.context, image_ref, image_ref,
 
580
                instance=instance)
521
581
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
522
582
        self.assertEquals(cur_time, instance['launched_at'])
523
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
583
        self.compute.terminate_instance(self.context,
 
584
                instance=jsonutils.to_primitive(instance))
524
585
 
525
586
    def test_reboot_soft(self):
526
587
        """Ensure instance can be soft rebooted"""
527
 
        instance = self._create_fake_instance()
528
 
        self.compute.run_instance(self.context, instance['uuid'])
 
588
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
589
        self.compute.run_instance(self.context, instance=instance)
529
590
        db.instance_update(self.context, instance['uuid'],
530
591
                           {'task_state': task_states.REBOOTING})
531
592
 
532
593
        reboot_type = "SOFT"
533
 
        self.compute.reboot_instance(self.context, instance['uuid'],
534
 
                                     reboot_type)
 
594
        self.compute.reboot_instance(self.context,
 
595
                                     instance=instance,
 
596
                                     reboot_type=reboot_type)
535
597
 
536
598
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
537
599
        self.assertEqual(inst_ref['power_state'], power_state.RUNNING)
538
600
        self.assertEqual(inst_ref['task_state'], None)
539
601
 
540
 
        self.compute.terminate_instance(self.context, inst_ref['uuid'])
 
602
        self.compute.terminate_instance(self.context,
 
603
                instance=jsonutils.to_primitive(inst_ref))
541
604
 
542
605
    def test_reboot_hard(self):
543
606
        """Ensure instance can be hard rebooted"""
544
 
        instance = self._create_fake_instance()
545
 
        self.compute.run_instance(self.context, instance['uuid'])
 
607
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
608
        self.compute.run_instance(self.context, instance=instance)
546
609
        db.instance_update(self.context, instance['uuid'],
547
610
                           {'task_state': task_states.REBOOTING_HARD})
548
611
 
549
612
        reboot_type = "HARD"
550
 
        self.compute.reboot_instance(self.context, instance['uuid'],
551
 
                                     reboot_type)
 
613
        self.compute.reboot_instance(self.context, instance=instance,
 
614
                                     reboot_type=reboot_type)
552
615
 
553
616
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
554
617
        self.assertEqual(inst_ref['power_state'], power_state.RUNNING)
555
618
        self.assertEqual(inst_ref['task_state'], None)
556
619
 
557
 
        self.compute.terminate_instance(self.context, inst_ref['uuid'])
 
620
        self.compute.terminate_instance(self.context,
 
621
                instance=jsonutils.to_primitive(inst_ref))
558
622
 
559
623
    def test_set_admin_password(self):
560
624
        """Ensure instance can have its admin password set"""
561
 
        instance = self._create_fake_instance()
562
 
        self.compute.run_instance(self.context, instance['uuid'])
 
625
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
626
        self.compute.run_instance(self.context, instance=instance)
563
627
        db.instance_update(self.context, instance['uuid'],
564
628
                           {'task_state': task_states.UPDATING_PASSWORD})
565
629
 
567
631
        self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
568
632
        self.assertEqual(inst_ref['task_state'], task_states.UPDATING_PASSWORD)
569
633
 
570
 
        self.compute.set_admin_password(self.context, instance['uuid'])
 
634
        self.compute.set_admin_password(self.context, instance=instance)
571
635
 
572
636
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
573
637
        self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
574
638
        self.assertEqual(inst_ref['task_state'], None)
575
639
 
576
 
        self.compute.terminate_instance(self.context, inst_ref['uuid'])
 
640
        self.compute.terminate_instance(self.context,
 
641
                instance=jsonutils.to_primitive(inst_ref))
577
642
 
578
643
    def test_set_admin_password_bad_state(self):
579
644
        """Test setting password while instance is rebuilding."""
580
 
        instance = self._create_fake_instance()
581
 
        self.compute.run_instance(self.context, instance['uuid'])
 
645
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
646
        self.compute.run_instance(self.context, instance=instance)
582
647
        db.instance_update(self.context, instance['uuid'], {
583
648
            "power_state": power_state.NOSTATE,
584
649
        })
585
 
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
 
650
        instance = jsonutils.to_primitive(db.instance_get_by_uuid(
 
651
                                          self.context, instance['uuid']))
586
652
 
587
653
        self.assertEqual(instance['power_state'], power_state.NOSTATE)
588
654
 
596
662
        self.stubs.Set(nova.virt.fake.FakeDriver, 'get_info',
597
663
                       fake_driver_get_info)
598
664
 
599
 
        self.assertRaises(exception.Invalid,
 
665
        self.assertRaises(exception.InstancePasswordSetFailed,
600
666
                          self.compute.set_admin_password,
601
667
                          self.context,
602
 
                          instance['uuid'])
603
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
668
                          instance=instance)
 
669
        self.compute.terminate_instance(self.context, instance=instance)
604
670
 
605
 
    def test_set_admin_password_driver_error(self):
606
 
        """Ensure error is raised admin password set"""
 
671
    def _do_test_set_admin_password_driver_error(self, exc, expected_vm_state,
 
672
                                                 expected_task_state):
 
673
        """Ensure expected exception is raised if set_admin_password fails"""
607
674
 
608
675
        def fake_sleep(_time):
609
676
            pass
611
678
        self.stubs.Set(time, 'sleep', fake_sleep)
612
679
 
613
680
        def fake_driver_set_pass(self2, _instance, _pwd):
614
 
            raise exception.NotAuthorized(_('Internal error'))
 
681
            raise exc
615
682
 
616
683
        self.stubs.Set(nova.virt.fake.FakeDriver, 'set_admin_password',
617
684
                       fake_driver_set_pass)
618
685
 
619
 
        instance = self._create_fake_instance()
620
 
        self.compute.run_instance(self.context, instance['uuid'])
 
686
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
687
        self.compute.run_instance(self.context, instance=instance)
621
688
        db.instance_update(self.context, instance['uuid'],
622
689
                           {'task_state': task_states.UPDATING_PASSWORD})
623
690
 
627
694
 
628
695
        #error raised from the driver should not reveal internal information
629
696
        #so a new error is raised
630
 
        self.assertRaises(exception.NovaException,
 
697
        self.assertRaises(exception.InstancePasswordSetFailed,
631
698
                          self.compute.set_admin_password,
632
 
                          self.context, instance['uuid'])
 
699
                          self.context,
 
700
                          instance=jsonutils.to_primitive(inst_ref))
633
701
 
634
702
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
635
 
        self.assertEqual(inst_ref['vm_state'], vm_states.ERROR)
636
 
        self.assertEqual(inst_ref['task_state'], task_states.UPDATING_PASSWORD)
637
 
 
638
 
        self.compute.terminate_instance(self.context, inst_ref['uuid'])
 
703
        self.assertEqual(inst_ref['vm_state'], expected_vm_state)
 
704
        self.assertEqual(inst_ref['task_state'], expected_task_state)
 
705
 
 
706
        self.compute.terminate_instance(self.context,
 
707
                instance=jsonutils.to_primitive(inst_ref))
 
708
 
 
709
    def test_set_admin_password_driver_not_authorized(self):
 
710
        """
 
711
        Ensure expected exception is raised if set_admin_password not
 
712
        authorized.
 
713
        """
 
714
        exc = exception.NotAuthorized(_('Internal error'))
 
715
        self._do_test_set_admin_password_driver_error(exc,
 
716
                                                vm_states.ERROR,
 
717
                                                None)
 
718
 
 
719
    def test_set_admin_password_driver_not_implemented(self):
 
720
        """
 
721
        Ensure expected exception is raised if set_admin_password not
 
722
        implemented by driver.
 
723
        """
 
724
        exc = NotImplementedError()
 
725
        self._do_test_set_admin_password_driver_error(exc,
 
726
                                                      vm_states.ACTIVE,
 
727
                                                      None)
639
728
 
640
729
    def test_inject_file(self):
641
730
        """Ensure we can write a file to an instance"""
649
738
        self.stubs.Set(nova.virt.fake.FakeDriver, 'inject_file',
650
739
                       fake_driver_inject_file)
651
740
 
652
 
        instance = self._create_fake_instance()
653
 
        self.compute.run_instance(self.context, instance['uuid'])
654
 
        self.compute.inject_file(self.context, instance['uuid'], "/tmp/test",
655
 
                "File Contents")
 
741
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
742
        self.compute.run_instance(self.context, instance=instance)
 
743
        self.compute.inject_file(self.context, "/tmp/test",
 
744
                "File Contents", instance=instance)
656
745
        self.assertTrue(called['inject'])
657
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
746
        self.compute.terminate_instance(self.context, instance=instance)
658
747
 
659
748
    def test_inject_network_info(self):
660
749
        """Ensure we can inject network info"""
666
755
        self.stubs.Set(nova.virt.fake.FakeDriver, 'inject_network_info',
667
756
                       fake_driver_inject_network)
668
757
 
669
 
        instance = self._create_fake_instance()
670
 
        instance_uuid = instance['uuid']
671
 
        self.compute.run_instance(self.context, instance_uuid)
672
 
        self.compute.inject_network_info(self.context, instance_uuid)
 
758
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
759
        self.compute.run_instance(self.context, instance=instance)
 
760
        self.compute.inject_network_info(self.context, instance=instance)
673
761
        self.assertTrue(called['inject'])
674
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
762
        self.compute.terminate_instance(self.context, instance=instance)
675
763
 
676
764
    def test_reset_network(self):
677
765
        """Ensure we can reset networking on an instance"""
678
 
        called = {'reset': False}
 
766
        called = {'count': 0}
679
767
 
680
768
        def fake_driver_reset_network(self, instance):
681
 
            called['reset'] = True
 
769
            called['count'] += 1
682
770
 
683
771
        self.stubs.Set(nova.virt.fake.FakeDriver, 'reset_network',
684
772
                       fake_driver_reset_network)
685
773
 
686
 
        instance = self._create_fake_instance()
 
774
        instance = jsonutils.to_primitive(self._create_fake_instance())
687
775
        instance_uuid = instance['uuid']
688
 
        self.compute.run_instance(self.context, instance_uuid)
689
 
        self.compute.reset_network(self.context, instance_uuid)
690
 
        self.assertTrue(called['reset'])
691
 
        self.compute.terminate_instance(self.context, instance_uuid)
692
 
 
693
 
    def test_agent_update(self):
694
 
        """Ensure instance can have its agent updated"""
695
 
        called = {'agent_update': False}
696
 
 
697
 
        def fake_driver_agent_update(self2, instance, url, md5hash):
698
 
            called['agent_update'] = True
699
 
            self.assertEqual(url, 'http://fake/url/')
700
 
            self.assertEqual(md5hash, 'fakehash')
701
 
 
702
 
        self.stubs.Set(nova.virt.fake.FakeDriver, 'agent_update',
703
 
                       fake_driver_agent_update)
704
 
 
705
 
        instance = self._create_fake_instance()
706
 
        self.compute.run_instance(self.context, instance['uuid'])
707
 
        self.compute.agent_update(self.context, instance['uuid'],
708
 
                                  'http://fake/url/', 'fakehash')
709
 
        self.assertTrue(called['agent_update'])
710
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
776
        self.compute.run_instance(self.context, instance=instance)
 
777
 
 
778
        # Make sure it works with both an instance and instance_uuid
 
779
        self.compute.reset_network(self.context, instance=instance)
 
780
        self.compute.reset_network(self.context, instance_uuid=instance_uuid)
 
781
 
 
782
        self.assertEqual(called['count'], 2)
 
783
 
 
784
        self.compute.terminate_instance(self.context, instance=instance)
711
785
 
712
786
    def test_snapshot(self):
713
787
        """Ensure instance can be snapshotted"""
714
 
        instance = self._create_fake_instance()
 
788
        instance = jsonutils.to_primitive(self._create_fake_instance())
715
789
        instance_uuid = instance['uuid']
716
790
        name = "myfakesnapshot"
717
 
        self.compute.run_instance(self.context, instance_uuid)
718
 
        self.compute.snapshot_instance(self.context, instance_uuid, name)
719
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
791
        self.compute.run_instance(self.context, instance=instance)
 
792
        self.compute.snapshot_instance(self.context, name, instance=instance)
 
793
        self.compute.terminate_instance(self.context, instance=instance)
720
794
 
721
795
    def test_snapshot_fails(self):
722
796
        """Ensure task_state is set to None if snapshot fails"""
725
799
 
726
800
        self.stubs.Set(self.compute.driver, 'snapshot', fake_snapshot)
727
801
 
728
 
        instance = self._create_fake_instance()
729
 
        self.compute.run_instance(self.context, instance['uuid'])
 
802
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
803
        self.compute.run_instance(self.context, instance=instance)
730
804
        self.assertRaises(test.TestingException,
731
805
                          self.compute.snapshot_instance,
732
 
                          self.context, instance['uuid'], "failing_snapshot")
 
806
                          self.context, "failing_snapshot", instance=instance)
733
807
        self._assert_state({'task_state': None})
734
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
808
        self.compute.terminate_instance(self.context, instance=instance)
735
809
 
736
810
    def _assert_state(self, state_dict):
737
811
        """Assert state of VM is equal to state passed as parameter"""
749
823
 
750
824
    def test_console_output(self):
751
825
        """Make sure we can get console output from instance"""
752
 
        instance = self._create_fake_instance()
753
 
        self.compute.run_instance(self.context, instance['uuid'])
 
826
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
827
        self.compute.run_instance(self.context, instance=instance)
754
828
 
755
829
        output = self.compute.get_console_output(self.context,
756
 
                                                  instance['uuid'])
 
830
                instance=instance)
757
831
        self.assertEqual(output, 'FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE')
758
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
832
        self.compute.terminate_instance(self.context, instance=instance)
759
833
 
760
834
    def test_console_output_tail(self):
761
835
        """Make sure we can get console output from instance"""
762
 
        instance = self._create_fake_instance()
763
 
        self.compute.run_instance(self.context, instance['uuid'])
 
836
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
837
        self.compute.run_instance(self.context, instance=instance)
764
838
 
765
839
        output = self.compute.get_console_output(self.context,
766
 
                                                instance['uuid'],
767
 
                                                tail_length=2)
 
840
                instance=instance, tail_length=2)
768
841
        self.assertEqual(output, 'ANOTHER\nLAST LINE')
769
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
842
        self.compute.terminate_instance(self.context, instance=instance)
770
843
 
771
844
    def test_novnc_vnc_console(self):
772
845
        """Make sure we can a vnc console for an instance."""
773
 
        instance = self._create_fake_instance()
774
 
        self.compute.run_instance(self.context, instance['uuid'])
775
 
 
776
 
        console = self.compute.get_vnc_console(self.context,
777
 
                                               instance['uuid'],
778
 
                                               'novnc')
779
 
        self.assert_(console)
780
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
846
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
847
        self.compute.run_instance(self.context, instance=instance)
 
848
 
 
849
        # Try with the full instance
 
850
        console = self.compute.get_vnc_console(self.context, 'novnc',
 
851
                                               instance=instance)
 
852
        self.assert_(console)
 
853
 
 
854
        # Also make sure it still works with just the instance UUID
 
855
        console = self.compute.get_vnc_console(self.context, 'novnc',
 
856
                                               instance_uuid=instance['uuid'])
 
857
        self.assert_(console)
 
858
 
 
859
        self.compute.terminate_instance(self.context, instance=instance)
781
860
 
782
861
    def test_xvpvnc_vnc_console(self):
783
862
        """Make sure we can a vnc console for an instance."""
784
 
        instance = self._create_fake_instance()
785
 
        self.compute.run_instance(self.context, instance['uuid'])
 
863
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
864
        self.compute.run_instance(self.context, instance=instance)
786
865
 
787
 
        console = self.compute.get_vnc_console(self.context,
788
 
                                               instance['uuid'],
789
 
                                               'xvpvnc')
 
866
        console = self.compute.get_vnc_console(self.context, 'xvpvnc',
 
867
                                               instance=instance)
790
868
        self.assert_(console)
791
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
869
        self.compute.terminate_instance(self.context, instance=instance)
792
870
 
793
871
    def test_invalid_vnc_console_type(self):
794
872
        """Raise useful error if console type is an unrecognised string"""
795
 
        instance = self._create_fake_instance()
796
 
        self.compute.run_instance(self.context, instance['uuid'])
 
873
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
874
        self.compute.run_instance(self.context, instance=instance)
797
875
 
798
876
        self.assertRaises(exception.ConsoleTypeInvalid,
799
877
                          self.compute.get_vnc_console,
800
 
                          self.context,
801
 
                          instance['uuid'],
802
 
                          'invalid')
803
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
878
                          self.context, 'invalid', instance=instance)
 
879
        self.compute.terminate_instance(self.context, instance=instance)
804
880
 
805
881
    def test_missing_vnc_console_type(self):
806
882
        """Raise useful error is console type is None"""
807
 
        instance = self._create_fake_instance()
808
 
        self.compute.run_instance(self.context, instance['uuid'])
 
883
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
884
        self.compute.run_instance(self.context, instance=instance)
809
885
 
810
886
        self.assertRaises(exception.ConsoleTypeInvalid,
811
887
                          self.compute.get_vnc_console,
812
 
                          self.context,
813
 
                          instance['uuid'],
814
 
                          None)
815
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
888
                          self.context, None, instance=instance)
 
889
        self.compute.terminate_instance(self.context, instance=instance)
816
890
 
817
891
    def test_diagnostics(self):
818
892
        """Make sure we can get diagnostics for an instance."""
819
 
        instance = self._create_fake_instance()
820
 
        self.compute.run_instance(self.context, instance['uuid'])
821
 
 
822
 
        diagnostics = self.compute.get_diagnostics(self.context,
823
 
                                                   instance['uuid'])
824
 
        self.assertEqual(diagnostics, 'FAKE_DIAGNOSTICS')
825
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
893
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
894
        self.compute.run_instance(self.context, instance=instance)
 
895
 
 
896
        diagnostics = self.compute.get_diagnostics(self.context,
 
897
                instance_uuid=instance['uuid'])
 
898
        self.assertEqual(diagnostics, 'FAKE_DIAGNOSTICS')
 
899
 
 
900
        diagnostics = self.compute.get_diagnostics(self.context,
 
901
                instance=instance)
 
902
        self.assertEqual(diagnostics, 'FAKE_DIAGNOSTICS')
 
903
        self.compute.terminate_instance(self.context, instance=instance)
826
904
 
827
905
    def test_add_fixed_ip_usage_notification(self):
828
906
        def dummy(*args, **kwargs):
835
913
        self.stubs.Set(nova.compute.manager.ComputeManager,
836
914
                       'reset_network', dummy)
837
915
 
838
 
        instance = self._create_fake_instance()
 
916
        instance = jsonutils.to_primitive(self._create_fake_instance())
839
917
        instance_uuid = instance['uuid']
840
918
 
841
919
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 0)
842
 
        self.compute.add_fixed_ip_to_instance(self.context, instance_uuid, 1)
 
920
        self.compute.add_fixed_ip_to_instance(self.context, network_id=1,
 
921
                instance=instance)
843
922
 
844
923
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
845
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
924
        self.compute.terminate_instance(self.context, instance=instance)
846
925
 
847
926
    def test_remove_fixed_ip_usage_notification(self):
848
927
        def dummy(*args, **kwargs):
855
934
        self.stubs.Set(nova.compute.manager.ComputeManager,
856
935
                       'reset_network', dummy)
857
936
 
858
 
        instance = self._create_fake_instance()
 
937
        instance = jsonutils.to_primitive(self._create_fake_instance())
859
938
        instance_uuid = instance['uuid']
860
939
 
861
940
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 0)
862
 
        self.compute.remove_fixed_ip_from_instance(self.context,
863
 
                                                   instance_uuid,
864
 
                                                   1)
 
941
        self.compute.remove_fixed_ip_from_instance(self.context, 1,
 
942
                                                   instance=instance)
865
943
 
866
944
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
867
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
945
        self.compute.terminate_instance(self.context, instance=instance)
868
946
 
869
947
    def test_run_instance_usage_notification(self):
870
 
        """Ensure run instance generates apropriate usage notification"""
871
 
        inst_ref = self._create_fake_instance()
872
 
        instance_uuid = inst_ref['uuid']
873
 
        self.compute.run_instance(self.context, instance_uuid)
 
948
        """Ensure run instance generates appropriate usage notification"""
 
949
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
950
        instance_uuid = instance['uuid']
 
951
        self.compute.run_instance(self.context, instance=instance)
874
952
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
875
953
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
876
954
        msg = test_notifier.NOTIFICATIONS[0]
877
955
        self.assertEquals(msg['event_type'], 'compute.instance.create.start')
 
956
        self.assertEquals(msg['payload']['image_name'], 'fake_name')
878
957
        # The last event is the one with the sugar in it.
879
958
        msg = test_notifier.NOTIFICATIONS[1]
880
959
        self.assertEquals(msg['priority'], 'INFO')
881
960
        self.assertEquals(msg['event_type'], 'compute.instance.create.end')
882
961
        payload = msg['payload']
883
962
        self.assertEquals(payload['tenant_id'], self.project_id)
 
963
        self.assertEquals(payload['image_name'], 'fake_name')
884
964
        self.assertEquals(payload['user_id'], self.user_id)
885
965
        self.assertEquals(payload['instance_id'], inst_ref.uuid)
886
966
        self.assertEquals(payload['instance_type'], 'm1.tiny')
893
973
        self.assertTrue(payload['launched_at'])
894
974
        image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
895
975
        self.assertEquals(payload['image_ref_url'], image_ref_url)
896
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
976
        self.compute.terminate_instance(self.context,
 
977
                instance=jsonutils.to_primitive(inst_ref))
897
978
 
898
979
    def test_terminate_usage_notification(self):
899
 
        """Ensure terminate_instance generates apropriate usage notification"""
 
980
        """Ensure terminate_instance generates correct usage notification"""
900
981
        old_time = datetime.datetime(2012, 4, 1)
901
982
        cur_time = datetime.datetime(2012, 12, 21, 12, 21)
902
983
        timeutils.set_time_override(old_time)
903
984
 
904
 
        inst_ref = self._create_fake_instance()
905
 
        self.compute.run_instance(self.context, inst_ref['uuid'])
 
985
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
986
        self.compute.run_instance(self.context, instance=instance)
906
987
        test_notifier.NOTIFICATIONS = []
907
988
        timeutils.set_time_override(cur_time)
908
 
        self.compute.terminate_instance(self.context, inst_ref['uuid'])
 
989
        self.compute.terminate_instance(self.context, instance=instance)
909
990
 
910
991
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 4)
911
992
 
922
1003
        payload = msg1['payload']
923
1004
        self.assertEquals(payload['tenant_id'], self.project_id)
924
1005
        self.assertEquals(payload['user_id'], self.user_id)
925
 
        self.assertEquals(payload['instance_id'], inst_ref.uuid)
 
1006
        self.assertEquals(payload['instance_id'], instance['uuid'])
926
1007
        self.assertEquals(payload['instance_type'], 'm1.tiny')
927
1008
        type_id = instance_types.get_instance_type_by_name('m1.tiny')['id']
928
1009
        self.assertEquals(str(payload['instance_type_id']), str(type_id))
936
1017
 
937
1018
    def test_run_instance_existing(self):
938
1019
        """Ensure failure when running an instance that already exists"""
939
 
        instance = self._create_fake_instance()
940
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1020
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
1021
        self.compute.run_instance(self.context, instance=instance)
941
1022
        self.assertRaises(exception.Invalid,
942
1023
                          self.compute.run_instance,
943
1024
                          self.context,
944
 
                          instance['uuid'])
945
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
1025
                          instance=instance)
 
1026
        self.compute.terminate_instance(self.context, instance=instance)
946
1027
 
947
1028
    def test_instance_set_to_error_on_uncaught_exception(self):
948
1029
        """Test that instance is set to error state when exception is raised"""
949
 
        instance = self._create_fake_instance()
950
 
        instance_uuid = instance['uuid']
 
1030
        instance = jsonutils.to_primitive(self._create_fake_instance())
951
1031
 
952
1032
        self.mox.StubOutWithMock(self.compute.network_api,
953
1033
                                 "allocate_for_instance")
964
1044
        self.assertRaises(rpc_common.RemoteError,
965
1045
                          self.compute.run_instance,
966
1046
                          self.context,
967
 
                          instance_uuid)
 
1047
                          instance=instance)
968
1048
 
969
1049
        instance = db.instance_get_by_uuid(context.get_admin_context(),
970
 
                                           instance_uuid)
 
1050
                                           instance['uuid'])
971
1051
        self.assertEqual(vm_states.ERROR, instance['vm_state'])
972
1052
 
973
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
1053
        self.compute.terminate_instance(self.context,
 
1054
                instance=jsonutils.to_primitive(instance))
974
1055
 
975
1056
    def test_instance_termination_exception_sets_error(self):
976
1057
        """Test that we handle InstanceTerminationFailure
984
1065
        self.stubs.Set(self.compute, '_delete_instance',
985
1066
                       fake_delete_instance)
986
1067
 
987
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
1068
        self.compute.terminate_instance(self.context,
 
1069
                instance=jsonutils.to_primitive(instance))
988
1070
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
989
1071
        self.assertEqual(instance['vm_state'], vm_states.ERROR)
990
1072
 
991
1073
    def test_network_is_deallocated_on_spawn_failure(self):
992
1074
        """When a spawn fails the network must be deallocated"""
993
 
        instance = self._create_fake_instance()
 
1075
        instance = jsonutils.to_primitive(self._create_fake_instance())
994
1076
 
995
1077
        self.mox.StubOutWithMock(self.compute, "_setup_block_device_mapping")
996
1078
        self.compute._setup_block_device_mapping(
1001
1083
 
1002
1084
        self.assertRaises(rpc.common.RemoteError,
1003
1085
                          self.compute.run_instance,
1004
 
                          self.context,
1005
 
                          instance['uuid'])
 
1086
                          self.context, instance=instance)
1006
1087
 
1007
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
1088
        self.compute.terminate_instance(self.context, instance=instance)
1008
1089
 
1009
1090
    def test_get_lock(self):
1010
 
        instance = self._create_fake_instance()
1011
 
        self.assertFalse(self.compute.get_lock(self.context, instance['uuid']))
 
1091
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
1092
        self.assertFalse(self.compute._get_lock(self.context,
 
1093
                                                instance['uuid']))
1012
1094
        db.instance_update(self.context, instance['uuid'], {'locked': True})
1013
 
        self.assertTrue(self.compute.get_lock(self.context, instance['uuid']))
 
1095
        self.assertTrue(self.compute._get_lock(self.context, instance['uuid']))
1014
1096
 
1015
1097
    def test_lock(self):
1016
1098
        """ensure locked instance cannot be changed"""
1017
 
        instance = self._create_fake_instance()
 
1099
        instance = jsonutils.to_primitive(self._create_fake_instance())
1018
1100
        instance_uuid = instance['uuid']
1019
 
        self.compute.run_instance(self.context, instance_uuid)
 
1101
        self.compute.run_instance(self.context, instance=instance)
1020
1102
 
1021
1103
        non_admin_context = context.RequestContext(None,
1022
1104
                                                   None,
1023
1105
                                                   is_admin=False)
1024
1106
 
1025
 
        # decorator should return False (fail) with locked nonadmin context
1026
 
        self.compute.lock_instance(self.context, instance_uuid)
1027
 
        ret_val = self.compute.reboot_instance(non_admin_context,
1028
 
                                               instance_uuid)
1029
 
        self.assertEqual(ret_val, False)
1030
 
 
1031
 
        # decorator should return None (success) with unlocked nonadmin context
1032
 
        self.compute.unlock_instance(self.context, instance_uuid)
1033
 
        ret_val = self.compute.reboot_instance(non_admin_context,
1034
 
                                               instance_uuid)
1035
 
        self.assertEqual(ret_val, None)
1036
 
 
1037
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
1107
        def check_task_state(task_state):
 
1108
            instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
1109
            self.assertEqual(instance['task_state'], task_state)
 
1110
 
 
1111
        instance = db.instance_update(self.context, instance_uuid,
 
1112
                                      {'task_state': task_states.REBOOTING})
 
1113
 
 
1114
        # should fail with locked nonadmin context, task_state won't be cleared
 
1115
        self.compute_api.lock(self.context, instance)
 
1116
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
1117
        self.compute.reboot_instance(non_admin_context,
 
1118
                instance=jsonutils.to_primitive(instance))
 
1119
        check_task_state(task_states.REBOOTING)
 
1120
 
 
1121
        # should succeed with unlocked nonadmin context, task_state cleared
 
1122
        self.compute_api.unlock(self.context, instance)
 
1123
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
1124
        self.compute.reboot_instance(non_admin_context,
 
1125
                instance=jsonutils.to_primitive(instance))
 
1126
        check_task_state(None)
 
1127
 
 
1128
        self.compute.terminate_instance(self.context,
 
1129
                instance=jsonutils.to_primitive(instance))
 
1130
 
 
1131
    def _test_state_revert(self, operation, pre_task_state):
 
1132
        instance = self._create_fake_instance()
 
1133
        self.compute.run_instance(self.context, instance=instance)
 
1134
 
 
1135
        # The API would have set task_state, so do that here to test
 
1136
        # that the state gets reverted on failure
 
1137
        db.instance_update(self.context, instance['uuid'],
 
1138
                           {"task_state": pre_task_state})
 
1139
 
 
1140
        raised = False
 
1141
        try:
 
1142
            ret_val = getattr(self.compute, operation)(self.context,
 
1143
                                                       instance=instance)
 
1144
        except Exception:
 
1145
            raised = True
 
1146
        self.assertTrue(raised)
 
1147
 
 
1148
        # Fetch the instance's task_state and make sure it went to None
 
1149
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
 
1150
        self.assertEqual(instance["task_state"], None)
 
1151
 
 
1152
    def test_state_revert(self):
 
1153
        """ensure that task_state is reverted after a failed operation"""
 
1154
        actions = [
 
1155
            ("reboot_instance", task_states.REBOOTING),
 
1156
            ("stop_instance", task_states.STOPPING),
 
1157
            ("start_instance", task_states.STARTING),
 
1158
            ("terminate_instance", task_states.DELETING),
 
1159
            ("power_off_instance", task_states.POWERING_OFF),
 
1160
            ("power_on_instance", task_states.POWERING_ON),
 
1161
            ("rebuild_instance", task_states.REBUILDING),
 
1162
            ("set_admin_password", task_states.UPDATING_PASSWORD),
 
1163
            ("rescue_instance", task_states.RESCUING),
 
1164
            ("unrescue_instance", task_states.UNRESCUING),
 
1165
            ("revert_resize", task_states.RESIZE_REVERTING),
 
1166
            ("prep_resize", task_states.RESIZE_PREP),
 
1167
            ("resize_instance", task_states.RESIZE_PREP),
 
1168
            ("pause_instance", task_states.PAUSING),
 
1169
            ("unpause_instance", task_states.UNPAUSING),
 
1170
            ("suspend_instance", task_states.SUSPENDING),
 
1171
            ("resume_instance", task_states.RESUMING),
 
1172
            ]
 
1173
 
 
1174
        def _get_an_exception(*args, **kwargs):
 
1175
            raise Exception("This fails every single time!")
 
1176
 
 
1177
        self.stubs.Set(self.compute, "_get_lock", _get_an_exception)
 
1178
        for operation, pre_state in actions:
 
1179
            self._test_state_revert(operation, pre_state)
 
1180
 
 
1181
    def _ensure_quota_reservations_committed(self):
 
1182
        """Mock up commit of quota reservations"""
 
1183
        reservations = list('fake_res')
 
1184
        self.mox.StubOutWithMock(nova.quota.QUOTAS, 'commit')
 
1185
        nova.quota.QUOTAS.commit(mox.IgnoreArg(), reservations)
 
1186
        self.mox.ReplayAll()
 
1187
        return reservations
 
1188
 
 
1189
    def _ensure_quota_reservations_rolledback(self):
 
1190
        """Mock up rollback of quota reservations"""
 
1191
        reservations = list('fake_res')
 
1192
        self.mox.StubOutWithMock(nova.quota.QUOTAS, 'rollback')
 
1193
        nova.quota.QUOTAS.rollback(mox.IgnoreArg(), reservations)
 
1194
        self.mox.ReplayAll()
 
1195
        return reservations
1038
1196
 
1039
1197
    def test_finish_resize(self):
1040
1198
        """Contrived test to ensure finish_resize doesn't raise anything"""
1044
1202
 
1045
1203
        self.stubs.Set(self.compute.driver, 'finish_migration', fake)
1046
1204
 
 
1205
        reservations = self._ensure_quota_reservations_committed()
 
1206
 
1047
1207
        context = self.context.elevated()
1048
 
        instance = self._create_fake_instance()
1049
 
        self.compute.prep_resize(context, instance['uuid'], 1, {},
1050
 
                                 filter_properties={})
 
1208
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
1209
        self.compute.prep_resize(context, instance=instance, instance_type={},
 
1210
                                 image={})
1051
1211
        migration_ref = db.migration_get_by_instance_and_status(context,
1052
1212
                instance['uuid'], 'pre-migrating')
1053
 
        self.compute.finish_resize(context, instance['uuid'],
1054
 
                                   int(migration_ref['id']), {}, {})
1055
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
1213
        self.compute.finish_resize(context,
 
1214
                migration_id=int(migration_ref['id']),
 
1215
                disk_info={}, image={}, instance=instance,
 
1216
                reservations=reservations)
 
1217
        self.compute.terminate_instance(self.context, instance=instance)
1056
1218
 
1057
1219
    def test_finish_resize_handles_error(self):
1058
1220
        """Make sure we don't leave the instance in RESIZE on error"""
1065
1227
 
1066
1228
        self.stubs.Set(self.compute.driver, 'finish_migration', throw_up)
1067
1229
 
 
1230
        reservations = self._ensure_quota_reservations_rolledback()
 
1231
 
1068
1232
        context = self.context.elevated()
1069
 
        instance = self._create_fake_instance()
1070
 
        self.compute.prep_resize(context, instance['uuid'], 1, {},
1071
 
                                 filter_properties={})
 
1233
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
1234
        self.compute.prep_resize(context, instance=instance, instance_type={},
 
1235
                                 image={}, reservations=reservations)
1072
1236
        migration_ref = db.migration_get_by_instance_and_status(context,
1073
1237
                instance['uuid'], 'pre-migrating')
1074
1238
 
1075
1239
        self.assertRaises(test.TestingException, self.compute.finish_resize,
1076
 
                          context, instance['uuid'],
1077
 
                          int(migration_ref['id']), {}, {})
 
1240
                          context, migration_id=int(migration_ref['id']),
 
1241
                          disk_info={}, image={}, instance=instance,
 
1242
                          reservations=reservations)
1078
1243
 
1079
1244
        instance = db.instance_get_by_uuid(context, instance['uuid'])
1080
1245
        self.assertEqual(instance['vm_state'], vm_states.ERROR)
1081
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
1246
        self.compute.terminate_instance(self.context,
 
1247
                instance=jsonutils.to_primitive(instance))
1082
1248
 
1083
1249
    def test_rebuild_instance_notification(self):
1084
1250
        """Ensure notifications on instance migrate/resize"""
1085
1251
        old_time = datetime.datetime(2012, 4, 1)
1086
1252
        cur_time = datetime.datetime(2012, 12, 21, 12, 21)
1087
1253
        timeutils.set_time_override(old_time)
1088
 
        inst_ref = self._create_fake_instance()
1089
 
        self.compute.run_instance(self.context, inst_ref['uuid'])
 
1254
        inst_ref = jsonutils.to_primitive(self._create_fake_instance())
 
1255
        self.compute.run_instance(self.context, instance=inst_ref)
1090
1256
        timeutils.set_time_override(cur_time)
1091
1257
 
1092
1258
        test_notifier.NOTIFICATIONS = []
1099
1265
 
1100
1266
        password = "new_password"
1101
1267
 
1102
 
        self.compute._rebuild_instance(self.context, inst_ref['uuid'],
1103
 
                image_ref, new_image_ref, dict(new_pass=password))
 
1268
        instance = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
 
1269
 
 
1270
        self.compute.rebuild_instance(self.context.elevated(),
 
1271
                image_ref, new_image_ref,
 
1272
                instance=jsonutils.to_primitive(instance),
 
1273
                new_pass=password)
1104
1274
 
1105
1275
        instance = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
1106
1276
 
1116
1286
        self.assertEquals(msg['event_type'],
1117
1287
                          'compute.instance.rebuild.start')
1118
1288
        self.assertEquals(msg['payload']['image_ref_url'], new_image_ref_url)
 
1289
        self.assertEquals(msg['payload']['image_name'], 'fake_name')
1119
1290
        msg = test_notifier.NOTIFICATIONS[2]
1120
1291
        self.assertEquals(msg['event_type'],
1121
1292
                          'compute.instance.rebuild.end')
1122
1293
        self.assertEquals(msg['priority'], 'INFO')
1123
1294
        payload = msg['payload']
 
1295
        self.assertEquals(payload['image_name'], 'fake_name')
1124
1296
        self.assertEquals(payload['tenant_id'], self.project_id)
1125
1297
        self.assertEquals(payload['user_id'], self.user_id)
1126
1298
        self.assertEquals(payload['instance_id'], inst_ref['uuid'])
1132
1304
        self.assertTrue('launched_at' in payload)
1133
1305
        self.assertEqual(payload['launched_at'], str(cur_time))
1134
1306
        self.assertEquals(payload['image_ref_url'], new_image_ref_url)
1135
 
        self.compute.terminate_instance(self.context, inst_ref['uuid'])
 
1307
        self.compute.terminate_instance(self.context,
 
1308
                instance=jsonutils.to_primitive(inst_ref))
1136
1309
 
1137
1310
    def test_finish_resize_instance_notification(self):
1138
1311
        """Ensure notifications on instance migrate/resize"""
1139
1312
        old_time = datetime.datetime(2012, 4, 1)
1140
1313
        cur_time = datetime.datetime(2012, 12, 21, 12, 21)
1141
1314
        timeutils.set_time_override(old_time)
1142
 
        instance = self._create_fake_instance()
 
1315
        instance = jsonutils.to_primitive(self._create_fake_instance())
1143
1316
        context = self.context.elevated()
1144
1317
        old_type_id = instance_types.get_instance_type_by_name(
1145
1318
                                                'm1.tiny')['id']
1146
 
        new_type_id = instance_types.get_instance_type_by_name(
1147
 
                                                'm1.small')['id']
1148
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1319
        new_type = instance_types.get_instance_type_by_name('m1.small')
 
1320
        new_type = jsonutils.to_primitive(new_type)
 
1321
        new_type_id = new_type['id']
 
1322
        self.compute.run_instance(self.context, instance=instance)
1149
1323
 
1150
1324
        db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1151
 
        self.compute.prep_resize(context, instance['uuid'], new_type_id, {},
1152
 
                                 filter_properties={})
 
1325
        self.compute.prep_resize(context, instance=instance,
 
1326
                instance_type=new_type, image={})
1153
1327
        migration_ref = db.migration_get_by_instance_and_status(context,
1154
1328
                                                instance['uuid'],
1155
1329
                                                'pre-migrating')
1156
 
        self.compute.resize_instance(context, instance['uuid'],
1157
 
                                     migration_ref['id'], {})
 
1330
        self.compute.resize_instance(context, migration_ref['id'], {},
 
1331
                                     instance=instance)
1158
1332
        timeutils.set_time_override(cur_time)
1159
1333
        test_notifier.NOTIFICATIONS = []
1160
1334
 
1161
 
        self.compute.finish_resize(context, instance['uuid'],
1162
 
                                   int(migration_ref['id']), {}, {})
 
1335
        self.compute.finish_resize(context,
 
1336
                migration_id=int(migration_ref['id']), disk_info={}, image={},
 
1337
                instance=instance)
1163
1338
 
1164
1339
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
1165
1340
        msg = test_notifier.NOTIFICATIONS[0]
1181
1356
        self.assertEqual(payload['launched_at'], str(cur_time))
1182
1357
        image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
1183
1358
        self.assertEquals(payload['image_ref_url'], image_ref_url)
1184
 
        self.compute.terminate_instance(context, instance['uuid'])
 
1359
        self.compute.terminate_instance(context,
 
1360
            instance=jsonutils.to_primitive(instance))
1185
1361
 
1186
1362
    def test_resize_instance_notification(self):
1187
1363
        """Ensure notifications on instance migrate/resize"""
1188
1364
        old_time = datetime.datetime(2012, 4, 1)
1189
1365
        cur_time = datetime.datetime(2012, 12, 21, 12, 21)
1190
1366
        timeutils.set_time_override(old_time)
1191
 
        instance = self._create_fake_instance()
 
1367
        instance = jsonutils.to_primitive(self._create_fake_instance())
1192
1368
        context = self.context.elevated()
1193
1369
 
1194
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1370
        self.compute.run_instance(self.context, instance=instance)
1195
1371
        timeutils.set_time_override(cur_time)
1196
1372
        test_notifier.NOTIFICATIONS = []
1197
1373
 
1198
1374
        db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1199
 
        self.compute.prep_resize(context, instance['uuid'], 1, {},
1200
 
                                 filter_properties={})
 
1375
        self.compute.prep_resize(context, instance=instance,
 
1376
                instance_type={}, image={})
1201
1377
        db.migration_get_by_instance_and_status(context,
1202
1378
                                                instance['uuid'],
1203
1379
                                                'pre-migrating')
1225
1401
        self.assertTrue('launched_at' in payload)
1226
1402
        image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
1227
1403
        self.assertEquals(payload['image_ref_url'], image_ref_url)
1228
 
        self.compute.terminate_instance(context, instance['uuid'])
 
1404
        self.compute.terminate_instance(context, instance=instance)
1229
1405
 
1230
1406
    def test_prep_resize_instance_migration_error(self):
1231
1407
        """Ensure prep_resize raise a migration error"""
1232
1408
        self.flags(host="foo", allow_resize_to_same_host=False)
1233
1409
 
1234
 
        instance = self._create_fake_instance()
 
1410
        instance = jsonutils.to_primitive(self._create_fake_instance())
1235
1411
        context = self.context.elevated()
1236
1412
 
1237
 
        self.compute.run_instance(self.context, instance['uuid'])
1238
 
        db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
 
1413
        reservations = self._ensure_quota_reservations_rolledback()
 
1414
 
 
1415
        self.compute.run_instance(self.context, instance=instance)
 
1416
        new_instance = db.instance_update(self.context, instance['uuid'],
 
1417
                                          {'host': 'foo'})
 
1418
        new_instance = jsonutils.to_primitive(new_instance)
1239
1419
 
1240
1420
        self.assertRaises(exception.MigrationError, self.compute.prep_resize,
1241
 
                          context, instance['uuid'], 1, {})
1242
 
        self.compute.terminate_instance(context, instance['uuid'])
 
1421
                          context, instance=new_instance,
 
1422
                          instance_type={}, image={},
 
1423
                          reservations=reservations)
 
1424
        self.compute.terminate_instance(context, instance=new_instance)
1243
1425
 
1244
1426
    def test_resize_instance_driver_error(self):
1245
1427
        """Ensure instance status set to Error on resize error"""
1250
1432
        self.stubs.Set(self.compute.driver, 'migrate_disk_and_power_off',
1251
1433
                       throw_up)
1252
1434
 
1253
 
        instance = self._create_fake_instance()
 
1435
        instance = jsonutils.to_primitive(self._create_fake_instance())
1254
1436
        context = self.context.elevated()
1255
1437
 
1256
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1438
        reservations = self._ensure_quota_reservations_rolledback()
 
1439
 
 
1440
        self.compute.run_instance(self.context, instance=instance)
1257
1441
        db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1258
 
        self.compute.prep_resize(context, instance['uuid'], 1, {},
1259
 
                                 filter_properties={})
 
1442
        self.compute.prep_resize(context, instance=instance,
 
1443
                                 instance_type={}, image={},
 
1444
                                 reservations=reservations)
1260
1445
        migration_ref = db.migration_get_by_instance_and_status(context,
1261
1446
                instance['uuid'], 'pre-migrating')
1262
1447
 
1263
1448
        #verify
1264
1449
        self.assertRaises(test.TestingException, self.compute.resize_instance,
1265
 
                          context, instance['uuid'], migration_ref['id'], {})
 
1450
                          context, migration_ref['id'], {}, instance=instance,
 
1451
                          reservations=reservations)
1266
1452
        instance = db.instance_get_by_uuid(context, instance['uuid'])
1267
1453
        self.assertEqual(instance['vm_state'], vm_states.ERROR)
1268
1454
 
1269
 
        self.compute.terminate_instance(context, instance['uuid'])
 
1455
        self.compute.terminate_instance(context,
 
1456
            instance=jsonutils.to_primitive(instance))
1270
1457
 
1271
1458
    def test_resize_instance(self):
1272
1459
        """Ensure instance can be migrated/resized"""
1273
 
        instance = self._create_fake_instance()
 
1460
        instance = jsonutils.to_primitive(self._create_fake_instance())
1274
1461
        context = self.context.elevated()
1275
1462
 
1276
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1463
        self.compute.run_instance(self.context, instance=instance)
1277
1464
        db.instance_update(self.context, instance['uuid'],
1278
1465
                           {'host': 'foo'})
1279
 
        self.compute.prep_resize(context, instance['uuid'], 1, {},
1280
 
                                 filter_properties={})
 
1466
        self.compute.prep_resize(context, instance=instance,
 
1467
                instance_type={}, image={})
1281
1468
        migration_ref = db.migration_get_by_instance_and_status(context,
1282
1469
                instance['uuid'], 'pre-migrating')
1283
 
        self.compute.resize_instance(context, instance['uuid'],
1284
 
                migration_ref['id'], {})
1285
 
        self.compute.terminate_instance(context, instance['uuid'])
 
1470
        self.compute.resize_instance(context, migration_ref['id'], {},
 
1471
                                     instance=instance)
 
1472
        self.compute.terminate_instance(context,
 
1473
            instance=jsonutils.to_primitive(instance))
1286
1474
 
1287
1475
    def test_finish_revert_resize(self):
1288
1476
        """Ensure that the flavor is reverted to the original on revert"""
1292
1480
        self.stubs.Set(self.compute.driver, 'finish_migration', fake)
1293
1481
        self.stubs.Set(self.compute.driver, 'finish_revert_migration', fake)
1294
1482
 
 
1483
        reservations = self._ensure_quota_reservations_committed()
 
1484
 
1295
1485
        context = self.context.elevated()
1296
 
        instance = self._create_fake_instance()
 
1486
        instance = jsonutils.to_primitive(self._create_fake_instance())
1297
1487
        instance_uuid = instance['uuid']
1298
1488
 
1299
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1489
        self.compute.run_instance(self.context, instance=instance)
1300
1490
 
1301
1491
        # Confirm the instance size before the resize starts
1302
1492
        inst_ref = db.instance_get_by_uuid(context, instance['uuid'])
1304
1494
                inst_ref['instance_type_id'])
1305
1495
        self.assertEqual(instance_type_ref['flavorid'], '1')
1306
1496
 
1307
 
        db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
 
1497
        new_inst_ref = db.instance_update(self.context, instance['uuid'],
 
1498
                                          {'host': 'foo'})
1308
1499
 
1309
1500
        new_instance_type_ref = db.instance_type_get_by_flavor_id(context, 3)
1310
 
        self.compute.prep_resize(context, inst_ref['uuid'],
1311
 
                                 new_instance_type_ref['id'], {},
1312
 
                                 filter_properties={})
 
1501
        self.compute.prep_resize(context,
 
1502
                instance=jsonutils.to_primitive(new_inst_ref),
 
1503
                instance_type=jsonutils.to_primitive(new_instance_type_ref),
 
1504
                image={}, reservations=reservations)
1313
1505
 
1314
1506
        migration_ref = db.migration_get_by_instance_and_status(context,
1315
1507
                inst_ref['uuid'], 'pre-migrating')
1316
1508
 
1317
 
        self.compute.resize_instance(context, inst_ref['uuid'],
1318
 
                migration_ref['id'], {})
1319
 
        self.compute.finish_resize(context, inst_ref['uuid'],
1320
 
                    int(migration_ref['id']), {}, {})
 
1509
        self.compute.resize_instance(context, migration_ref['id'], {},
 
1510
                instance=jsonutils.to_primitive(inst_ref))
 
1511
        self.compute.finish_resize(context,
 
1512
                    migration_id=int(migration_ref['id']), disk_info={},
 
1513
                    image={}, instance=jsonutils.to_primitive(inst_ref))
1321
1514
 
1322
1515
        # Prove that the instance size is now the new size
1323
1516
        inst_ref = db.instance_get_by_uuid(context, instance['uuid'])
1326
1519
        self.assertEqual(instance_type_ref['flavorid'], '3')
1327
1520
 
1328
1521
        # Finally, revert and confirm the old flavor has been applied
1329
 
        self.compute.revert_resize(context, inst_ref['uuid'],
1330
 
                migration_ref['id'])
1331
 
        self.compute.finish_revert_resize(context, inst_ref['uuid'],
1332
 
                migration_ref['id'])
 
1522
        rpcinst = jsonutils.to_primitive(inst_ref)
 
1523
        self.compute.revert_resize(context,
 
1524
                migration_id=migration_ref['id'], instance=rpcinst,
 
1525
                reservations=reservations)
 
1526
        self.compute.finish_revert_resize(context,
 
1527
                migration_id=migration_ref['id'], instance=rpcinst,
 
1528
                reservations=reservations)
1333
1529
 
1334
1530
        instance = db.instance_get_by_uuid(context, instance['uuid'])
1335
1531
        self.assertEqual(instance['vm_state'], vm_states.ACTIVE)
1341
1537
        self.assertEqual(instance_type_ref['flavorid'], '1')
1342
1538
        self.assertEqual(inst_ref['host'], migration_ref['source_compute'])
1343
1539
 
1344
 
        self.compute.terminate_instance(context, inst_ref['uuid'])
 
1540
        self.compute.terminate_instance(context,
 
1541
            instance=jsonutils.to_primitive(inst_ref))
1345
1542
 
1346
1543
    def test_get_by_flavor_id(self):
1347
1544
        type = instance_types.get_instance_type_by_flavor_id(1)
1350
1547
    def test_resize_same_source_fails(self):
1351
1548
        """Ensure instance fails to migrate when source and destination are
1352
1549
        the same host"""
1353
 
        instance = self._create_fake_instance()
1354
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1550
        reservations = self._ensure_quota_reservations_rolledback()
 
1551
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
1552
        self.compute.run_instance(self.context, instance=instance)
1355
1553
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
1356
1554
        self.assertRaises(exception.MigrationError, self.compute.prep_resize,
1357
 
                self.context, instance['uuid'], 1, {})
1358
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
1555
                self.context, instance=instance,
 
1556
                instance_type={}, image={}, reservations=reservations)
 
1557
        self.compute.terminate_instance(self.context,
 
1558
                instance=jsonutils.to_primitive(instance))
1359
1559
 
1360
1560
    def test_resize_instance_handles_migration_error(self):
1361
1561
        """Ensure vm_state is ERROR when error occurs"""
1365
1565
                'migrate_disk_and_power_off',
1366
1566
                raise_migration_failure)
1367
1567
 
1368
 
        inst_ref = self._create_fake_instance()
 
1568
        reservations = self._ensure_quota_reservations_rolledback()
 
1569
 
 
1570
        inst_ref = jsonutils.to_primitive(self._create_fake_instance())
1369
1571
        context = self.context.elevated()
1370
1572
 
1371
 
        self.compute.run_instance(self.context, inst_ref['uuid'])
 
1573
        self.compute.run_instance(self.context, instance=inst_ref)
1372
1574
        db.instance_update(self.context, inst_ref['uuid'], {'host': 'foo'})
1373
 
        self.compute.prep_resize(context, inst_ref['uuid'], 1, {},
1374
 
                                 filter_properties={})
 
1575
        self.compute.prep_resize(context, instance=inst_ref, instance_type={},
 
1576
                                 image={}, reservations=reservations)
1375
1577
        migration_ref = db.migration_get_by_instance_and_status(context,
1376
1578
                inst_ref['uuid'], 'pre-migrating')
1377
1579
        self.assertRaises(test.TestingException, self.compute.resize_instance,
1378
 
                          context, inst_ref['uuid'], migration_ref['id'], {})
 
1580
                          context, migration_ref['id'], {}, instance=inst_ref,
 
1581
                          reservations=reservations)
1379
1582
        inst_ref = db.instance_get_by_uuid(context, inst_ref['uuid'])
1380
1583
        self.assertEqual(inst_ref['vm_state'], vm_states.ERROR)
1381
 
        self.compute.terminate_instance(context, inst_ref['uuid'])
 
1584
        self.compute.terminate_instance(context,
 
1585
            instance=jsonutils.to_primitive(inst_ref))
 
1586
 
 
1587
    def test_check_can_live_migrate_source_works_correctly(self):
 
1588
        """Confirm check_can_live_migrate_source works on positive path"""
 
1589
        context = self.context.elevated()
 
1590
        inst_ref = jsonutils.to_primitive(self._create_fake_instance(
 
1591
                                          {'host': 'fake_host_2'}))
 
1592
        inst_id = inst_ref["id"]
 
1593
        dest = "fake_host_1"
 
1594
 
 
1595
        self.mox.StubOutWithMock(db, 'instance_get')
 
1596
        self.mox.StubOutWithMock(self.compute.driver,
 
1597
                                 'check_can_live_migrate_source')
 
1598
 
 
1599
        dest_check_data = {"test": "data"}
 
1600
        self.compute.driver.check_can_live_migrate_source(context,
 
1601
                                                          inst_ref,
 
1602
                                                          dest_check_data)
 
1603
 
 
1604
        self.mox.ReplayAll()
 
1605
        self.compute.check_can_live_migrate_source(context,
 
1606
                dest_check_data=dest_check_data, instance=inst_ref)
 
1607
 
 
1608
    def test_check_can_live_migrate_destination_works_correctly(self):
 
1609
        """Confirm check_can_live_migrate_destination works on positive path"""
 
1610
        context = self.context.elevated()
 
1611
        inst_ref = jsonutils.to_primitive(self._create_fake_instance(
 
1612
                                          {'host': 'fake_host_2'}))
 
1613
        inst_id = inst_ref["id"]
 
1614
        dest = "fake_host_1"
 
1615
 
 
1616
        self.mox.StubOutWithMock(self.compute.driver,
 
1617
                                 'check_can_live_migrate_destination')
 
1618
        self.mox.StubOutWithMock(self.compute.compute_rpcapi,
 
1619
                                 'check_can_live_migrate_source')
 
1620
        self.mox.StubOutWithMock(self.compute.driver,
 
1621
                                 'check_can_live_migrate_destination_cleanup')
 
1622
 
 
1623
        dest_check_data = {"test": "data"}
 
1624
        self.compute.driver.check_can_live_migrate_destination(context,
 
1625
                inst_ref, True, False).AndReturn(dest_check_data)
 
1626
        self.compute.compute_rpcapi.check_can_live_migrate_source(context,
 
1627
                inst_ref, dest_check_data)
 
1628
        self.compute.driver.check_can_live_migrate_destination_cleanup(
 
1629
                context, dest_check_data)
 
1630
 
 
1631
        self.mox.ReplayAll()
 
1632
        self.compute.check_can_live_migrate_destination(context,
 
1633
                block_migration=True, disk_over_commit=False,
 
1634
                instance=inst_ref)
 
1635
 
 
1636
    def test_check_can_live_migrate_destination_fails_dest_check(self):
 
1637
        """Confirm check_can_live_migrate_destination works on positive path"""
 
1638
        context = self.context.elevated()
 
1639
        inst_ref = jsonutils.to_primitive(self._create_fake_instance(
 
1640
                                          {'host': 'fake_host_2'}))
 
1641
        inst_id = inst_ref["id"]
 
1642
        dest = "fake_host_1"
 
1643
 
 
1644
        self.mox.StubOutWithMock(self.compute.driver,
 
1645
                                 'check_can_live_migrate_destination')
 
1646
 
 
1647
        self.compute.driver.check_can_live_migrate_destination(context,
 
1648
                inst_ref, True, False).AndRaise(exception.Invalid())
 
1649
 
 
1650
        self.mox.ReplayAll()
 
1651
        self.assertRaises(exception.Invalid,
 
1652
                          self.compute.check_can_live_migrate_destination,
 
1653
                          context, block_migration=True,
 
1654
                          disk_over_commit=False, instance=inst_ref)
 
1655
 
 
1656
    def test_check_can_live_migrate_destination_fails_source(self):
 
1657
        """Confirm check_can_live_migrate_destination works on positive path"""
 
1658
        context = self.context.elevated()
 
1659
        inst_ref = jsonutils.to_primitive(self._create_fake_instance(
 
1660
                                          {'host': 'fake_host_2'}))
 
1661
        inst_id = inst_ref["id"]
 
1662
        dest = "fake_host_1"
 
1663
 
 
1664
        self.mox.StubOutWithMock(self.compute.driver,
 
1665
                                 'check_can_live_migrate_destination')
 
1666
        self.mox.StubOutWithMock(self.compute.compute_rpcapi,
 
1667
                                 'check_can_live_migrate_source')
 
1668
        self.mox.StubOutWithMock(self.compute.driver,
 
1669
                                 'check_can_live_migrate_destination_cleanup')
 
1670
 
 
1671
        dest_check_data = {"test": "data"}
 
1672
        self.compute.driver.check_can_live_migrate_destination(context,
 
1673
                inst_ref, True, False).AndReturn(dest_check_data)
 
1674
        self.compute.compute_rpcapi.check_can_live_migrate_source(context,
 
1675
                inst_ref, dest_check_data).AndRaise(exception.Invalid())
 
1676
        self.compute.driver.check_can_live_migrate_destination_cleanup(
 
1677
                context, dest_check_data)
 
1678
 
 
1679
        self.mox.ReplayAll()
 
1680
        self.assertRaises(exception.Invalid,
 
1681
                          self.compute.check_can_live_migrate_destination,
 
1682
                          context, block_migration=True,
 
1683
                          disk_over_commit=False, instance=inst_ref)
1382
1684
 
1383
1685
    def test_pre_live_migration_instance_has_no_fixed_ip(self):
1384
1686
        """Confirm raising exception if instance doesn't have fixed_ip."""
1385
1687
        # creating instance testdata
1386
 
        inst_ref = self._create_fake_instance({'host': 'dummy'})
1387
 
        c = context.get_admin_context()
 
1688
        context = self.context.elevated()
 
1689
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
1690
        inst_id = instance["id"]
1388
1691
 
1389
 
        # start test
1390
 
        self.stubs.Set(time, 'sleep', lambda t: None)
 
1692
        self.mox.ReplayAll()
1391
1693
        self.assertRaises(exception.FixedIpNotFoundForInstance,
1392
 
                          self.compute.pre_live_migration,
1393
 
                          c, inst_ref['id'])
1394
 
        # cleanup
1395
 
        db.instance_destroy(c, inst_ref['uuid'])
 
1694
                          self.compute.pre_live_migration, context,
 
1695
                          instance=instance)
1396
1696
 
1397
1697
    def test_pre_live_migration_works_correctly(self):
1398
1698
        """Confirm setup_compute_volume is called when volume is mounted."""
1401
1701
                                                          spectacular=True)
1402
1702
        self.stubs.Set(nova.compute.manager.ComputeManager,
1403
1703
                       '_get_instance_nw_info', stupid)
 
1704
 
1404
1705
        # creating instance testdata
1405
 
        inst_ref = self._create_fake_instance({'host': 'dummy'})
 
1706
        instance = jsonutils.to_primitive(self._create_fake_instance(
 
1707
                                          {'host': 'dummy'}))
 
1708
        inst_id = instance['id']
1406
1709
        c = context.get_admin_context()
 
1710
        nw_info = fake_network.fake_get_instance_nw_info(self.stubs)
1407
1711
 
1408
1712
        # creating mocks
1409
1713
        self.mox.StubOutWithMock(self.compute.driver, 'pre_live_migration')
1410
 
        self.compute.driver.pre_live_migration({'block_device_mapping': []})
1411
 
        nw_info = fake_network.fake_get_instance_nw_info(self.stubs)
1412
 
        self.mox.StubOutWithMock(self.compute.driver, 'plug_vifs')
1413
 
        self.compute.driver.plug_vifs(mox.IsA(inst_ref), nw_info)
 
1714
        self.compute.driver.pre_live_migration(mox.IsA(c), mox.IsA(instance),
 
1715
                                               {'block_device_mapping': []},
 
1716
                                               mox.IgnoreArg())
1414
1717
        self.mox.StubOutWithMock(self.compute.driver,
1415
1718
                                 'ensure_filtering_rules_for_instance')
1416
1719
        self.compute.driver.ensure_filtering_rules_for_instance(
1417
 
            mox.IsA(inst_ref), nw_info)
 
1720
            mox.IsA(instance), nw_info)
1418
1721
 
1419
1722
        # start test
1420
1723
        self.mox.ReplayAll()
1421
 
        ret = self.compute.pre_live_migration(c, inst_ref['id'])
 
1724
        ret = self.compute.pre_live_migration(c, instance=instance)
1422
1725
        self.assertEqual(ret, None)
1423
1726
 
1424
1727
        # cleanup
1425
 
        db.instance_destroy(c, inst_ref['uuid'])
 
1728
        db.instance_destroy(c, instance['uuid'])
1426
1729
 
1427
1730
    def test_live_migration_dest_raises_exception(self):
1428
1731
        """Confirm exception when pre_live_migration fails."""
1429
1732
        # creating instance testdata
1430
 
        inst_ref = self._create_fake_instance({'host': 'dummy'})
 
1733
        instance_ref = self._create_fake_instance({'host': 'dummy'})
 
1734
        instance = jsonutils.to_primitive(instance_ref)
 
1735
        inst_uuid = instance['uuid']
 
1736
        inst_id = instance['id']
1431
1737
 
1432
1738
        c = context.get_admin_context()
1433
 
        topic = rpc.queue_get_for(c, FLAGS.compute_topic, inst_ref['host'])
 
1739
        topic = rpc.queue_get_for(c, FLAGS.compute_topic, instance['host'])
1434
1740
 
1435
1741
        # creating volume testdata
1436
1742
        volume_id = db.volume_create(c, {'size': 1})['id']
1437
 
        values = {'instance_uuid': inst_ref['uuid'], 'device_name': '/dev/vdc',
 
1743
        values = {'instance_uuid': inst_uuid, 'device_name': '/dev/vdc',
1438
1744
                  'delete_on_termination': False, 'volume_id': volume_id}
1439
1745
        db.block_device_mapping_create(c, values)
1440
1746
 
1442
1748
        self.mox.StubOutWithMock(rpc, 'call')
1443
1749
        rpc.call(c, FLAGS.volume_topic,
1444
1750
                 {"method": "check_for_export",
1445
 
                  "args": {'instance_id': inst_ref['id']}})
1446
 
 
1447
 
        self.mox.StubOutWithMock(self.compute.driver, 'get_instance_disk_info')
1448
 
        self.compute.driver.get_instance_disk_info(inst_ref.name)
1449
 
 
1450
 
        rpc.call(c, topic,
1451
 
                 {"method": "pre_live_migration",
1452
 
                  "args": {'instance_id': inst_ref['id'],
1453
 
                           'block_migration': True,
1454
 
                           'disk': None},
1455
 
                  "version": compute_rpcapi.ComputeAPI.RPC_API_VERSION
1456
 
                 }, None).AndRaise(rpc.common.RemoteError('', '', ''))
 
1751
                  "args": {'instance_id': inst_id}})
 
1752
 
 
1753
        self.mox.StubOutWithMock(self.compute.driver,
 
1754
                                 'get_instance_disk_info')
 
1755
        self.compute.driver.get_instance_disk_info(instance['name'])
 
1756
 
 
1757
        self.mox.StubOutWithMock(self.compute.compute_rpcapi,
 
1758
                                 'pre_live_migration')
 
1759
        self.compute.compute_rpcapi.pre_live_migration(c,
 
1760
                mox.IsA(instance), True, None, instance['host']).AndRaise(
 
1761
                                        rpc.common.RemoteError('', '', ''))
1457
1762
 
1458
1763
        # mocks for rollback
1459
1764
        rpc.call(c, 'network', {'method': 'setup_networks_on_host',
1460
 
                                'args': {'instance_id': inst_ref['id'],
 
1765
                                'args': {'instance_id': inst_id,
1461
1766
                                         'host': self.compute.host,
1462
1767
                                         'teardown': False}})
 
1768
        rpcinst = jsonutils.to_primitive(
 
1769
                db.instance_get_by_uuid(self.context, instance['uuid']))
1463
1770
        rpc.call(c, topic,
1464
1771
                {"method": "remove_volume_connection",
1465
 
                 "args": {'instance_id': inst_ref['id'],
 
1772
                 "args": {'instance': rpcinst,
1466
1773
                          'volume_id': volume_id},
1467
 
                 "version": compute_rpcapi.ComputeAPI.RPC_API_VERSION}, None)
1468
 
        rpc.cast(c, topic, {"method": "rollback_live_migration_at_destination",
1469
 
                            "args": {'instance_id': inst_ref['id']}})
 
1774
                 "version": "1.26"}, None)
 
1775
        rpc.cast(c, topic,
 
1776
                {"method": "rollback_live_migration_at_destination",
 
1777
                 "args": {'instance': rpcinst},
 
1778
                 "version": "1.32"})
1470
1779
 
1471
1780
        # start test
1472
1781
        self.mox.ReplayAll()
1473
1782
        self.assertRaises(rpc_common.RemoteError,
1474
1783
                          self.compute.live_migration,
1475
 
                          c, inst_ref['id'], inst_ref['host'], True)
 
1784
                          c, dest=instance['host'], block_migration=True,
 
1785
                          instance=rpcinst)
1476
1786
 
1477
1787
        # cleanup
1478
1788
        for bdms in db.block_device_mapping_get_all_by_instance(
1479
 
            c, inst_ref['uuid']):
 
1789
            c, inst_uuid):
1480
1790
            db.block_device_mapping_destroy(c, bdms['id'])
1481
1791
        db.volume_destroy(c, volume_id)
1482
 
        db.instance_destroy(c, inst_ref['uuid'])
 
1792
        db.instance_destroy(c, inst_uuid)
1483
1793
 
1484
1794
    def test_live_migration_works_correctly(self):
1485
1795
        """Confirm live_migration() works as expected correctly."""
1486
1796
        # creating instance testdata
1487
 
        instance = self._create_fake_instance({'host': 'dummy'})
1488
 
        instance_id = instance['id']
1489
1797
        c = context.get_admin_context()
1490
 
        inst_ref = db.instance_get(c, instance_id)
1491
 
        topic = rpc.queue_get_for(c, FLAGS.compute_topic, inst_ref['host'])
 
1798
        instance_ref = self._create_fake_instance({'host': 'dummy'})
 
1799
        inst_uuid = instance_ref['uuid']
 
1800
        inst_id = instance_ref['id']
 
1801
 
 
1802
        instance = jsonutils.to_primitive(db.instance_get(c, inst_id))
1492
1803
 
1493
1804
        # create
1494
1805
        self.mox.StubOutWithMock(rpc, 'call')
 
1806
        topic = rpc.queue_get_for(c, FLAGS.compute_topic, instance['host'])
1495
1807
        rpc.call(c, topic,
1496
1808
                {"method": "pre_live_migration",
1497
 
                 "args": {'instance_id': instance_id,
 
1809
                 "args": {'instance': instance,
1498
1810
                          'block_migration': False,
1499
1811
                          'disk': None},
1500
 
                 "version": compute_rpcapi.ComputeAPI.RPC_API_VERSION}, None)
 
1812
                 "version": '1.23'},
 
1813
                None)
1501
1814
 
1502
1815
        # start test
1503
1816
        self.mox.ReplayAll()
1504
 
        ret = self.compute.live_migration(c, inst_ref['id'], inst_ref['host'])
 
1817
        ret = self.compute.live_migration(c, dest=instance['host'],
 
1818
                instance=instance)
1505
1819
        self.assertEqual(ret, None)
1506
1820
 
1507
1821
        # cleanup
1508
 
        db.instance_destroy(c, instance['uuid'])
 
1822
        db.instance_destroy(c, inst_uuid)
1509
1823
 
1510
1824
    def test_post_live_migration_working_correctly(self):
1511
1825
        """Confirm post_live_migration() works as expected correctly."""
1514
1828
 
1515
1829
        # creating testdata
1516
1830
        c = context.get_admin_context()
1517
 
        instance = self._create_fake_instance({
1518
 
                        'state_description': 'migrating',
1519
 
                        'state': power_state.PAUSED})
1520
 
        instance_id = instance['id']
1521
 
        i_ref = db.instance_get(c, instance_id)
1522
 
        db.instance_update(c, i_ref['uuid'],
 
1831
        inst_ref = jsonutils.to_primitive(self._create_fake_instance({
 
1832
                                'state_description': 'migrating',
 
1833
                                'state': power_state.PAUSED}))
 
1834
        inst_uuid = inst_ref['uuid']
 
1835
        inst_id = inst_ref['id']
 
1836
 
 
1837
        db.instance_update(c, inst_uuid,
1523
1838
                           {'task_state': task_states.MIGRATING,
1524
1839
                            'power_state': power_state.PAUSED})
1525
 
        v_ref = db.volume_create(c, {'size': 1, 'instance_id': instance_id})
 
1840
        v_ref = db.volume_create(c, {'size': 1, 'instance_id': inst_id})
1526
1841
        fix_addr = db.fixed_ip_create(c, {'address': '1.1.1.1',
1527
 
                                          'instance_id': instance_id})
 
1842
                                          'instance_uuid': inst_ref['uuid']})
1528
1843
        fix_ref = db.fixed_ip_get_by_address(c, fix_addr)
1529
1844
        db.floating_ip_create(c, {'address': flo_addr,
1530
1845
                                  'fixed_ip_id': fix_ref['id']})
1531
1846
 
1532
1847
        # creating mocks
1533
1848
        self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
1534
 
        self.compute.driver.unfilter_instance(i_ref, [])
 
1849
        self.compute.driver.unfilter_instance(inst_ref, [])
1535
1850
        self.mox.StubOutWithMock(rpc, 'call')
1536
1851
        rpc.call(c, rpc.queue_get_for(c, FLAGS.compute_topic, dest),
1537
1852
            {"method": "post_live_migration_at_destination",
1538
 
             "args": {'instance_id': i_ref['id'], 'block_migration': False},
1539
 
             "version": compute_rpcapi.ComputeAPI.RPC_API_VERSION}, None)
 
1853
             "args": {'instance': inst_ref, 'block_migration': False},
 
1854
             "version": "1.20"}, None)
1540
1855
        self.mox.StubOutWithMock(self.compute.driver, 'unplug_vifs')
1541
 
        self.compute.driver.unplug_vifs(i_ref, [])
 
1856
        self.compute.driver.unplug_vifs(inst_ref, [])
1542
1857
        rpc.call(c, 'network', {'method': 'setup_networks_on_host',
1543
 
                                'args': {'instance_id': instance_id,
 
1858
                                'args': {'instance_id': inst_id,
1544
1859
                                         'host': self.compute.host,
1545
1860
                                         'teardown': True}})
1546
1861
 
1547
1862
        # start test
1548
1863
        self.mox.ReplayAll()
1549
 
        self.compute.post_live_migration(c, i_ref, dest)
 
1864
        self.compute._post_live_migration(c, inst_ref, dest)
1550
1865
 
1551
1866
        # make sure floating ips are rewritten to destinatioin hostname.
1552
1867
        flo_refs = db.floating_ip_get_all_by_host(c, dest)
1554
1869
        self.assertEqual(flo_refs[0]['address'], flo_addr)
1555
1870
 
1556
1871
        # cleanup
1557
 
        db.instance_destroy(c, instance['uuid'])
 
1872
        db.instance_destroy(c, inst_uuid)
1558
1873
        db.volume_destroy(c, v_ref['id'])
1559
1874
        db.floating_ip_destroy(c, flo_addr)
1560
1875
 
1563
1878
        self.stubs.Set(compute_manager.ComputeManager,
1564
1879
                '_report_driver_status', nop_report_driver_status)
1565
1880
 
1566
 
        instance = self._create_fake_instance()
 
1881
        instance = jsonutils.to_primitive(self._create_fake_instance())
1567
1882
 
1568
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1883
        self.compute.run_instance(self.context, instance=instance)
1569
1884
 
1570
1885
        instances = db.instance_get_all(context.get_admin_context())
1571
1886
        LOG.info(_("Running instances: %s"), instances)
1607
1922
        self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
1608
1923
 
1609
1924
        ctxt = context.get_admin_context()
1610
 
        self.compute.add_instance_fault_from_exc(ctxt, instance_uuid,
1611
 
                                                 NotImplementedError('test'),
1612
 
                                                 exc_info)
 
1925
        self.compute._add_instance_fault_from_exc(ctxt, instance_uuid,
 
1926
                                                  NotImplementedError('test'),
 
1927
                                                  exc_info)
1613
1928
 
1614
1929
    def test_add_instance_fault_user_error(self):
1615
1930
        exc_info = None
1635
1950
        self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
1636
1951
 
1637
1952
        ctxt = context.get_admin_context()
1638
 
        self.compute.add_instance_fault_from_exc(ctxt, instance_uuid,
 
1953
        self.compute._add_instance_fault_from_exc(ctxt, instance_uuid,
1639
1954
            user_exc, exc_info)
1640
1955
 
1641
1956
    def test_add_instance_fault_no_exc_info(self):
1653
1968
        self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
1654
1969
 
1655
1970
        ctxt = context.get_admin_context()
1656
 
        self.compute.add_instance_fault_from_exc(ctxt, instance_uuid,
1657
 
                                                 NotImplementedError('test'))
1658
 
 
1659
 
    def test_get_additional_capabilities(self):
1660
 
        self.flags(additional_compute_capabilities=['test3=xyzzy',
1661
 
                                                    'test4',
1662
 
                                                    'nothertest=blat'])
1663
 
        caps = compute_manager._get_additional_capabilities()
1664
 
        all_caps = dict(test3='xyzzy',
1665
 
                        test4=True,
1666
 
                        nothertest='blat')
1667
 
        for c, val in all_caps.items():
1668
 
            self.assertTrue(c in caps, c)
1669
 
            self.assertEquals(val, caps[c])
1670
 
 
1671
 
    def test_report_driver_status(self):
1672
 
        test_caps = dict(test1=1024, test2='foo', nothertest='bar')
1673
 
        self.flags(additional_compute_capabilities=['test3=xyzzy',
1674
 
                                                    'test4',
1675
 
                                                    'nothertest=blat'])
1676
 
        self.mox.StubOutWithMock(self.compute.driver, 'get_host_stats')
1677
 
        self.compute.driver.get_host_stats(refresh=True).AndReturn(test_caps)
1678
 
        self.compute._last_host_check = 0
1679
 
        self.mox.ReplayAll()
1680
 
 
1681
 
        self.compute._report_driver_status(context.get_admin_context())
1682
 
        caps = self.compute.last_capabilities
1683
 
        all_caps = dict(test1=1024, test2='foo', test3='xyzzy',
1684
 
                        test4=True, nothertest='bar')
1685
 
        for c, val in all_caps.items():
1686
 
            self.assertTrue(c in caps, c)
1687
 
            self.assertEquals(val, caps[c])
 
1971
        self.compute._add_instance_fault_from_exc(ctxt, instance_uuid,
 
1972
                                                  NotImplementedError('test'))
1688
1973
 
1689
1974
    def test_cleanup_running_deleted_instances(self):
1690
1975
        admin_context = context.get_admin_context()
1828
2113
                      'task_state': None},
1829
2114
                     {'uuid': 'fake_uuid3', 'vm_state': vm_states.ACTIVE,
1830
2115
                      'task_state': task_states.REBOOTING},
1831
 
                     {'uuid': 'fake_uuid4', 'vm_state': vm_states.ACTIVE,
 
2116
                     {'uuid': 'fake_uuid4', 'vm_state': vm_states.RESIZED,
1832
2117
                      'task_state': None},
1833
2118
                     {'uuid': 'fake_uuid5', 'vm_state': vm_states.ACTIVE,
1834
 
                      'task_state': None}]
 
2119
                      'task_state': None},
 
2120
                     {'uuid': 'fake_uuid6', 'vm_state': vm_states.RESIZED,
 
2121
                      'task_state': 'deleting'}]
1835
2122
        expected_migration_status = {'fake_uuid1': 'confirmed',
1836
2123
                                     'noexist': 'error',
1837
2124
                                     'fake_uuid2': 'error',
1838
2125
                                     'fake_uuid3': 'error',
1839
2126
                                     'fake_uuid4': None,
1840
 
                                     'fake_uuid5': 'confirmed'}
 
2127
                                     'fake_uuid5': 'error',
 
2128
                                     'fake_uuid6': 'error'}
1841
2129
        migrations = []
1842
2130
        for i, instance in enumerate(instances, start=1):
1843
2131
            migrations.append({'id': i,
1852
2140
                if instance['uuid'] == instance_uuid:
1853
2141
                    return instance
1854
2142
 
1855
 
        def fake_migration_get_all_unconfirmed(context, resize_confirm_window):
 
2143
        def fake_migration_get_unconfirmed_by_dest_compute(context,
 
2144
                resize_confirm_window, dest_compute):
 
2145
            self.assertEqual(dest_compute, FLAGS.host)
1856
2146
            return migrations
1857
2147
 
1858
2148
        def fake_migration_update(context, migration_id, values):
1871
2161
 
1872
2162
        self.stubs.Set(db, 'instance_get_by_uuid',
1873
2163
                fake_instance_get_by_uuid)
1874
 
        self.stubs.Set(db, 'migration_get_all_unconfirmed',
1875
 
                fake_migration_get_all_unconfirmed)
 
2164
        self.stubs.Set(db, 'migration_get_unconfirmed_by_dest_compute',
 
2165
                fake_migration_get_unconfirmed_by_dest_compute)
1876
2166
        self.stubs.Set(db, 'migration_update',
1877
2167
                fake_migration_update)
1878
2168
        self.stubs.Set(self.compute.compute_api, 'confirm_resize',
2015
2305
                                   security_group_api=self.security_group_api)
2016
2306
        self.fake_image = {
2017
2307
            'id': 1,
 
2308
            'name': 'fake_name',
2018
2309
            'properties': {'kernel_id': 'fake_kernel_id',
2019
2310
                           'ramdisk_id': 'fake_ramdisk_id'},
2020
2311
        }
2021
2312
 
2022
2313
    def _run_instance(self):
2023
 
        instance = self._create_fake_instance()
 
2314
        instance = jsonutils.to_primitive(self._create_fake_instance())
2024
2315
        instance_uuid = instance['uuid']
2025
 
        self.compute.run_instance(self.context, instance_uuid)
 
2316
        self.compute.run_instance(self.context, instance=instance)
2026
2317
 
2027
2318
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2028
2319
        self.assertEqual(instance['task_state'], None)
2081
2372
            img = copy.copy(self.fake_image)
2082
2373
            img['min_ram'] = 2
2083
2374
            img['min_disk'] = 2
 
2375
            img['name'] = 'fake_name'
2084
2376
            return img
2085
2377
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
2086
2378
 
2126
2418
            self.assertEqual(sys_metadata,
2127
2419
                    {'image_kernel_id': 'fake_kernel_id',
2128
2420
                     'image_ramdisk_id': 'fake_ramdisk_id',
2129
 
                     'image_something_else': 'meow'})
 
2421
                     'image_something_else': 'meow', })
2130
2422
        finally:
2131
2423
            db.instance_destroy(self.context, ref[0]['uuid'])
2132
2424
 
2160
2452
        self.assertEqual(pre_build_len,
2161
2453
                         len(db.instance_get_all(context.get_admin_context())))
2162
2454
 
 
2455
    def test_create_with_large_user_data(self):
 
2456
        """Test an instance type with too much user data."""
 
2457
 
 
2458
        inst_type = instance_types.get_default_instance_type()
 
2459
 
 
2460
        def fake_show(*args):
 
2461
            img = copy.copy(self.fake_image)
 
2462
            img['min_ram'] = 2
 
2463
            return img
 
2464
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
 
2465
 
 
2466
        self.assertRaises(exception.InstanceUserDataTooLarge,
 
2467
            self.compute_api.create, self.context, inst_type, None,
 
2468
                          user_data=('1' * 65536))
 
2469
 
 
2470
    def test_create_with_malformed_user_data(self):
 
2471
        """Test an instance type with malformed user data."""
 
2472
 
 
2473
        inst_type = instance_types.get_default_instance_type()
 
2474
 
 
2475
        def fake_show(*args):
 
2476
            img = copy.copy(self.fake_image)
 
2477
            img['min_ram'] = 2
 
2478
            return img
 
2479
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
 
2480
 
 
2481
        self.assertRaises(exception.InstanceUserDataMalformed,
 
2482
            self.compute_api.create, self.context, inst_type, None,
 
2483
                          user_data='banana')
 
2484
 
 
2485
    def test_create_with_base64_user_data(self):
 
2486
        """Test an instance type with ok much user data."""
 
2487
 
 
2488
        inst_type = instance_types.get_default_instance_type()
 
2489
 
 
2490
        def fake_show(*args):
 
2491
            img = copy.copy(self.fake_image)
 
2492
            img['min_ram'] = 2
 
2493
            return img
 
2494
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
 
2495
 
 
2496
        # NOTE(mikal): a string of length 48510 encodes to 65532 characters of
 
2497
        # base64
 
2498
        (refs, resv_id) = self.compute_api.create(
 
2499
            self.context, inst_type, None,
 
2500
            user_data=base64.encodestring('1' * 48510))
 
2501
        db.instance_destroy(self.context, refs[0]['uuid'])
 
2502
 
2163
2503
    def test_default_hostname_generator(self):
2164
2504
        fake_uuids = [str(utils.gen_uuid()) for x in xrange(4)]
2165
2505
 
2222
2562
            db.instance_destroy(self.context, ref[0]['uuid'])
2223
2563
 
2224
2564
    def test_start(self):
2225
 
        instance = self._create_fake_instance()
 
2565
        instance = jsonutils.to_primitive(self._create_fake_instance())
2226
2566
        instance_uuid = instance['uuid']
2227
 
        self.compute.run_instance(self.context, instance_uuid)
 
2567
        self.compute.run_instance(self.context, instance=instance)
2228
2568
 
2229
 
        self.compute.stop_instance(self.context, instance_uuid)
 
2569
        self.compute.stop_instance(self.context, instance=instance)
2230
2570
 
2231
2571
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2232
2572
        self.assertEqual(instance['task_state'], None)
2239
2579
        db.instance_destroy(self.context, instance['uuid'])
2240
2580
 
2241
2581
    def test_stop(self):
2242
 
        instance = self._create_fake_instance()
 
2582
        instance = jsonutils.to_primitive(self._create_fake_instance())
2243
2583
        instance_uuid = instance['uuid']
2244
 
        self.compute.run_instance(self.context, instance_uuid)
 
2584
        self.compute.run_instance(self.context, instance=instance)
2245
2585
 
2246
2586
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2247
2587
        self.assertEqual(instance['task_state'], None)
2266
2606
            self.compute_api.start(self.context, instance)
2267
2607
            check_state(instance_uuid, power_state_, vm_state_, task_state_)
2268
2608
 
2269
 
        instance = self._create_fake_instance()
2270
 
        self.compute.run_instance(self.context, instance['uuid'])
 
2609
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
2610
        self.compute.run_instance(self.context, instance=instance)
2271
2611
 
2272
2612
        check_state(instance['uuid'], power_state.RUNNING, vm_states.ACTIVE,
2273
2613
                    None)
2295
2635
 
2296
2636
        db.instance_destroy(self.context, instance['uuid'])
2297
2637
 
 
2638
    def test_repeated_delete_quota(self):
 
2639
        in_use = {'instances': 1}
 
2640
 
 
2641
        def fake_reserve(context, **deltas):
 
2642
            return dict(deltas.iteritems())
 
2643
 
 
2644
        self.stubs.Set(QUOTAS, 'reserve', fake_reserve)
 
2645
 
 
2646
        def fake_commit(context, deltas):
 
2647
            for k, v in deltas.iteritems():
 
2648
                in_use[k] = in_use.get(k, 0) + v
 
2649
 
 
2650
        self.stubs.Set(QUOTAS, 'commit', fake_commit)
 
2651
 
 
2652
        instance, instance_uuid = self._run_instance()
 
2653
 
 
2654
        self.compute_api.delete(self.context, instance)
 
2655
        self.compute_api.delete(self.context, instance)
 
2656
 
 
2657
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
2658
        self.assertEqual(instance['task_state'], task_states.DELETING)
 
2659
 
 
2660
        self.assertEquals(in_use['instances'], 0)
 
2661
 
 
2662
        db.instance_destroy(self.context, instance['uuid'])
 
2663
 
2298
2664
    def test_delete_fast_if_host_not_set(self):
2299
2665
        instance = self._create_fake_instance({'host': None})
2300
2666
        self.compute_api.delete(self.context, instance)
2347
2713
 
2348
2714
    def test_force_delete(self):
2349
2715
        """Ensure instance can be deleted after a soft delete"""
2350
 
        instance = self._create_fake_instance()
 
2716
        instance = jsonutils.to_primitive(self._create_fake_instance())
2351
2717
        instance_uuid = instance['uuid']
2352
 
        self.compute.run_instance(self.context, instance_uuid)
 
2718
        self.compute.run_instance(self.context, instance=instance)
2353
2719
 
2354
2720
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2355
2721
        self.compute_api.soft_delete(self.context, instance)
2369
2735
 
2370
2736
    def test_suspend(self):
2371
2737
        """Ensure instance can be suspended"""
2372
 
        instance = self._create_fake_instance()
 
2738
        instance = jsonutils.to_primitive(self._create_fake_instance())
2373
2739
        instance_uuid = instance['uuid']
2374
 
        self.compute.run_instance(self.context, instance_uuid)
 
2740
        self.compute.run_instance(self.context, instance=instance)
2375
2741
 
2376
2742
        self.assertEqual(instance['task_state'], None)
2377
2743
 
2384
2750
 
2385
2751
    def test_resume(self):
2386
2752
        """Ensure instance can be resumed (if suspended)"""
2387
 
        instance = self._create_fake_instance()
2388
 
        self.compute.run_instance(self.context, instance['uuid'])
 
2753
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
2754
        self.compute.run_instance(self.context, instance=instance)
2389
2755
        db.instance_update(self.context, instance['uuid'],
2390
2756
                           {'vm_state': vm_states.SUSPENDED})
2391
2757
        instance = db.instance_get(self.context, instance['id'])
2401
2767
 
2402
2768
    def test_pause(self):
2403
2769
        """Ensure instance can be paused"""
2404
 
        instance = self._create_fake_instance()
 
2770
        instance = jsonutils.to_primitive(self._create_fake_instance())
2405
2771
        instance_uuid = instance['uuid']
2406
 
        self.compute.run_instance(self.context, instance_uuid)
 
2772
        self.compute.run_instance(self.context, instance=instance)
2407
2773
 
2408
2774
        self.assertEqual(instance['task_state'], None)
2409
2775
 
2416
2782
 
2417
2783
    def test_unpause(self):
2418
2784
        """Ensure instance can be unpaused"""
2419
 
        instance = self._create_fake_instance()
 
2785
        instance = jsonutils.to_primitive(self._create_fake_instance())
2420
2786
        instance_uuid = instance['uuid']
2421
 
        self.compute.run_instance(self.context, instance_uuid)
 
2787
        self.compute.run_instance(self.context, instance=instance)
2422
2788
 
2423
2789
        self.assertEqual(instance['task_state'], None)
2424
2790
 
2425
 
        self.compute.pause_instance(self.context, instance_uuid)
 
2791
        self.compute.pause_instance(self.context, instance=instance)
2426
2792
        # set the state that the instance gets when pause finishes
2427
2793
        instance = db.instance_update(self.context, instance['uuid'],
2428
2794
                                      {'vm_state': vm_states.PAUSED})
2436
2802
 
2437
2803
    def test_restore(self):
2438
2804
        """Ensure instance can be restored from a soft delete"""
2439
 
        instance = self._create_fake_instance()
 
2805
        instance = jsonutils.to_primitive(self._create_fake_instance())
2440
2806
        instance_uuid = instance['uuid']
2441
 
        self.compute.run_instance(self.context, instance_uuid)
 
2807
        self.compute.run_instance(self.context, instance=instance)
2442
2808
 
2443
2809
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2444
2810
        self.compute_api.soft_delete(self.context, instance)
2459
2825
        db.instance_destroy(self.context, instance['uuid'])
2460
2826
 
2461
2827
    def test_rebuild(self):
2462
 
        inst_ref = self._create_fake_instance()
2463
 
        instance_uuid = inst_ref['uuid']
2464
 
        self.compute.run_instance(self.context, instance_uuid)
 
2828
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
2829
        instance_uuid = instance['uuid']
 
2830
        self.compute.run_instance(self.context, instance=instance)
2465
2831
 
2466
2832
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2467
2833
        self.assertEqual(instance['task_state'], None)
2498
2864
                instance_uuid)
2499
2865
        self.assertEqual(sys_metadata,
2500
2866
                {'image_kernel_id': 'fake_kernel_id',
2501
 
                 'image_ramdisk_id': 'fake_ramdisk_id',
2502
 
                 'image_something_else': 'meow',
2503
 
                 'preserved': 'preserve this!'})
 
2867
                'image_ramdisk_id': 'fake_ramdisk_id',
 
2868
                'image_something_else': 'meow',
 
2869
                'preserved': 'preserve this!'})
2504
2870
        db.instance_destroy(self.context, instance['uuid'])
2505
2871
 
2506
2872
    def test_reboot_soft(self):
2507
2873
        """Ensure instance can be soft rebooted"""
2508
 
        inst_ref = self._create_fake_instance()
2509
 
        self.compute.run_instance(self.context, inst_ref['uuid'])
 
2874
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
2875
        self.compute.run_instance(self.context, instance=instance)
2510
2876
 
2511
 
        inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
 
2877
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
2512
2878
        self.assertEqual(inst_ref['task_state'], None)
2513
2879
 
2514
2880
        reboot_type = "SOFT"
2521
2887
 
2522
2888
    def test_reboot_hard(self):
2523
2889
        """Ensure instance can be hard rebooted"""
2524
 
        inst_ref = self._create_fake_instance()
2525
 
        self.compute.run_instance(self.context, inst_ref['uuid'])
 
2890
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
2891
        self.compute.run_instance(self.context, instance=instance)
2526
2892
 
2527
 
        inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
 
2893
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
2528
2894
        self.assertEqual(inst_ref['task_state'], None)
2529
2895
 
2530
2896
        reboot_type = "HARD"
2547
2913
 
2548
2914
    def test_set_admin_password(self):
2549
2915
        """Ensure instance can have its admin password set"""
2550
 
        instance = self._create_fake_instance()
 
2916
        instance = jsonutils.to_primitive(self._create_fake_instance())
2551
2917
        instance_uuid = instance['uuid']
2552
 
        self.compute.run_instance(self.context, instance_uuid)
 
2918
        self.compute.run_instance(self.context, instance=instance)
2553
2919
 
2554
2920
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
2555
2921
        self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
2556
2922
        self.assertEqual(inst_ref['task_state'], None)
2557
2923
 
 
2924
        def fake_rpc_method(context, topic, msg, do_cast=True):
 
2925
            self.assertFalse(do_cast)
 
2926
 
 
2927
        self.stubs.Set(rpc, 'call', fake_rpc_method)
 
2928
 
2558
2929
        self.compute_api.set_admin_password(self.context, inst_ref)
2559
2930
 
2560
2931
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
2561
2932
        self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
2562
 
        self.assertEqual(inst_ref['task_state'], task_states.UPDATING_PASSWORD)
 
2933
        self.assertEqual(inst_ref['task_state'],
 
2934
                         task_states.UPDATING_PASSWORD)
2563
2935
 
2564
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
2936
        self.compute.terminate_instance(self.context,
 
2937
                instance=jsonutils.to_primitive(inst_ref))
2565
2938
 
2566
2939
    def test_rescue_unrescue(self):
2567
 
        instance = self._create_fake_instance()
 
2940
        instance = jsonutils.to_primitive(self._create_fake_instance())
2568
2941
        instance_uuid = instance['uuid']
2569
 
        self.compute.run_instance(self.context, instance_uuid)
 
2942
        self.compute.run_instance(self.context, instance=instance)
2570
2943
 
2571
2944
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2572
2945
        self.assertEqual(instance['vm_state'], vm_states.ACTIVE)
2588
2961
        self.assertEqual(instance['vm_state'], vm_states.RESCUED)
2589
2962
        self.assertEqual(instance['task_state'], task_states.UNRESCUING)
2590
2963
 
2591
 
        self.compute.terminate_instance(self.context, instance_uuid)
 
2964
        self.compute.terminate_instance(self.context,
 
2965
                instance=jsonutils.to_primitive(instance))
2592
2966
 
2593
2967
    def test_snapshot(self):
2594
2968
        """Ensure a snapshot of an instance can be created"""
2777
3151
        db.instance_destroy(self.context, instance['uuid'])
2778
3152
 
2779
3153
    def test_resize_confirm_through_api(self):
2780
 
        instance = self._create_fake_instance()
 
3154
        instance = jsonutils.to_primitive(self._create_fake_instance())
2781
3155
        context = self.context.elevated()
2782
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3156
        self.compute.run_instance(self.context, instance=instance)
2783
3157
        instance = db.instance_get_by_uuid(context, instance['uuid'])
2784
3158
        self.compute_api.resize(context, instance, '4')
2785
3159
 
2793
3167
                                       'vm_state': vm_states.RESIZED})
2794
3168
 
2795
3169
        self.compute_api.confirm_resize(context, instance)
2796
 
        self.compute.terminate_instance(context, instance['uuid'])
 
3170
        self.compute.terminate_instance(context,
 
3171
            instance=jsonutils.to_primitive(instance))
2797
3172
 
2798
3173
    def test_resize_revert_through_api(self):
2799
 
        instance = self._create_fake_instance()
 
3174
        instance = jsonutils.to_primitive(self._create_fake_instance())
2800
3175
        context = self.context.elevated()
2801
3176
        instance = db.instance_get_by_uuid(context, instance['uuid'])
2802
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3177
        self.compute.run_instance(self.context, instance=instance)
2803
3178
 
2804
3179
        self.compute_api.resize(context, instance, '4')
2805
3180
 
2818
3193
        self.assertEqual(instance['vm_state'], vm_states.RESIZED)
2819
3194
        self.assertEqual(instance['task_state'], task_states.RESIZE_REVERTING)
2820
3195
 
2821
 
        self.compute.terminate_instance(context, instance['uuid'])
 
3196
        self.compute.terminate_instance(context,
 
3197
            instance=jsonutils.to_primitive(instance))
2822
3198
 
2823
3199
    def test_resize_invalid_flavor_fails(self):
2824
3200
        """Ensure invalid flavors raise"""
2825
3201
        instance = self._create_fake_instance()
2826
3202
        context = self.context.elevated()
2827
3203
        instance = db.instance_get_by_uuid(context, instance['uuid'])
2828
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3204
        instance = jsonutils.to_primitive(instance)
 
3205
        self.compute.run_instance(self.context, instance=instance)
2829
3206
 
2830
3207
        self.assertRaises(exception.NotFound, self.compute_api.resize,
2831
3208
                context, instance, 200)
2832
3209
 
2833
 
        self.compute.terminate_instance(context, instance['uuid'])
 
3210
        self.compute.terminate_instance(context, instance=instance)
2834
3211
 
2835
3212
    def test_resize_same_size_fails(self):
2836
3213
        """Ensure invalid flavors raise"""
2837
3214
        context = self.context.elevated()
2838
3215
        instance = self._create_fake_instance()
2839
3216
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
3217
        instance = jsonutils.to_primitive(instance)
2840
3218
 
2841
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3219
        self.compute.run_instance(self.context, instance=instance)
2842
3220
 
2843
3221
        self.assertRaises(exception.CannotResizeToSameSize,
2844
3222
                          self.compute_api.resize, context, instance, 1)
2845
3223
 
2846
 
        self.compute.terminate_instance(context, instance['uuid'])
 
3224
        self.compute.terminate_instance(context, instance=instance)
2847
3225
 
2848
3226
    def test_migrate(self):
2849
3227
        context = self.context.elevated()
2850
3228
        instance = self._create_fake_instance()
2851
3229
        instance = db.instance_get_by_uuid(context, instance['uuid'])
2852
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3230
        instance = jsonutils.to_primitive(instance)
 
3231
        self.compute.run_instance(self.context, instance=instance)
2853
3232
        # Migrate simply calls resize() without a flavor_id.
2854
3233
        self.compute_api.resize(context, instance, None)
2855
 
        self.compute.terminate_instance(context, instance['uuid'])
 
3234
        self.compute.terminate_instance(context, instance=instance)
2856
3235
 
2857
3236
    def test_resize_request_spec(self):
2858
3237
        def _fake_cast(context, topic, msg):
2860
3239
            filter_properties = msg['args']['filter_properties']
2861
3240
            instance_properties = request_spec['instance_properties']
2862
3241
            self.assertEqual(instance_properties['host'], 'host2')
 
3242
            # Ensure the instance passed to us has been updated with
 
3243
            # progress set to 0 and task_state set to RESIZE_PREP.
 
3244
            self.assertEqual(instance_properties['task_state'],
 
3245
                    task_states.RESIZE_PREP)
 
3246
            self.assertEqual(instance_properties['progress'], 0)
2863
3247
            self.assertIn('host2', filter_properties['ignore_hosts'])
2864
3248
 
2865
3249
        self.stubs.Set(rpc, 'cast', _fake_cast)
2867
3251
        context = self.context.elevated()
2868
3252
        instance = self._create_fake_instance(dict(host='host2'))
2869
3253
        instance = db.instance_get_by_uuid(context, instance['uuid'])
2870
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3254
        instance = jsonutils.to_primitive(instance)
 
3255
        self.compute.run_instance(self.context, instance=instance)
 
3256
        # We need to set the host to something 'known'.  Unfortunately,
 
3257
        # the compute manager is using a cached copy of FLAGS.host,
 
3258
        # so we can't just self.flags(host='host2') before calling
 
3259
        # run_instance above.  Also, set progress to 10 so we ensure
 
3260
        # it is reset to 0 in compute_api.resize().  (verified in
 
3261
        # _fake_cast above).
 
3262
        instance = db.instance_update(self.context, instance['uuid'],
 
3263
                dict(host='host2', progress=10))
 
3264
        # different host
 
3265
        self.flags(host='host3')
2871
3266
        try:
2872
3267
            self.compute_api.resize(context, instance, None)
2873
3268
        finally:
2874
 
            self.compute.terminate_instance(context, instance['uuid'])
 
3269
            self.compute.terminate_instance(context, instance=instance)
2875
3270
 
2876
3271
    def test_resize_request_spec_noavoid(self):
2877
3272
        def _fake_cast(context, topic, msg):
2879
3274
            filter_properties = msg['args']['filter_properties']
2880
3275
            instance_properties = request_spec['instance_properties']
2881
3276
            self.assertEqual(instance_properties['host'], 'host2')
 
3277
            # Ensure the instance passed to us has been updated with
 
3278
            # progress set to 0 and task_state set to RESIZE_PREP.
 
3279
            self.assertEqual(instance_properties['task_state'],
 
3280
                    task_states.RESIZE_PREP)
 
3281
            self.assertEqual(instance_properties['progress'], 0)
2882
3282
            self.assertNotIn('host2', filter_properties['ignore_hosts'])
2883
3283
 
2884
3284
        self.stubs.Set(rpc, 'cast', _fake_cast)
2887
3287
        context = self.context.elevated()
2888
3288
        instance = self._create_fake_instance(dict(host='host2'))
2889
3289
        instance = db.instance_get_by_uuid(context, instance['uuid'])
2890
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3290
        instance = jsonutils.to_primitive(instance)
 
3291
        self.compute.run_instance(self.context, instance=instance)
 
3292
        # We need to set the host to something 'known'.  Unfortunately,
 
3293
        # the compute manager is using a cached copy of FLAGS.host,
 
3294
        # so we can't just self.flags(host='host2') before calling
 
3295
        # run_instance above.  Also, set progress to 10 so we ensure
 
3296
        # it is reset to 0 in compute_api.resize().  (verified in
 
3297
        # _fake_cast above).
 
3298
        instance = db.instance_update(self.context, instance['uuid'],
 
3299
                dict(host='host2', progress=10))
 
3300
        # different host
2891
3301
        try:
2892
3302
            self.compute_api.resize(context, instance, None)
2893
3303
        finally:
2894
 
            self.compute.terminate_instance(context, instance['uuid'])
 
3304
            self.compute.terminate_instance(context, instance=instance)
2895
3305
 
2896
3306
    def test_get(self):
2897
3307
        """Test get instance"""
2933
3343
                'display_name': 'not-woot'})
2934
3344
 
2935
3345
        instances = self.compute_api.get_all(c,
2936
 
                search_opts={'name': 'woo.*'})
 
3346
                search_opts={'name': '^woo.*'})
2937
3347
        self.assertEqual(len(instances), 2)
2938
3348
        instance_uuids = [instance['uuid'] for instance in instances]
2939
3349
        self.assertTrue(instance1['uuid'] in instance_uuids)
2940
3350
        self.assertTrue(instance2['uuid'] in instance_uuids)
2941
3351
 
2942
3352
        instances = self.compute_api.get_all(c,
2943
 
                search_opts={'name': 'woot.*'})
 
3353
                search_opts={'name': '^woot.*'})
2944
3354
        instance_uuids = [instance['uuid'] for instance in instances]
2945
3355
        self.assertEqual(len(instances), 1)
2946
3356
        self.assertTrue(instance1['uuid'] in instance_uuids)
2953
3363
        self.assertTrue(instance3['uuid'] in instance_uuids)
2954
3364
 
2955
3365
        instances = self.compute_api.get_all(c,
2956
 
                search_opts={'name': 'n.*'})
 
3366
                search_opts={'name': '^n.*'})
2957
3367
        self.assertEqual(len(instances), 1)
2958
3368
        instance_uuids = [instance['uuid'] for instance in instances]
2959
3369
        self.assertTrue(instance3['uuid'] in instance_uuids)
2966
3376
        db.instance_destroy(c, instance2['uuid'])
2967
3377
        db.instance_destroy(c, instance3['uuid'])
2968
3378
 
2969
 
    def test_get_all_by_instance_name_regexp(self):
2970
 
        """Test searching instances by name"""
2971
 
        self.flags(instance_name_template='instance-%d')
2972
 
 
2973
 
        c = context.get_admin_context()
2974
 
        instance1 = self._create_fake_instance()
2975
 
        instance2 = self._create_fake_instance({'id': 2})
2976
 
        instance3 = self._create_fake_instance({'id': 10})
2977
 
 
2978
 
        instances = self.compute_api.get_all(c,
2979
 
                search_opts={'instance_name': 'instance.*'})
2980
 
        self.assertEqual(len(instances), 3)
2981
 
 
2982
 
        instances = self.compute_api.get_all(c,
2983
 
                search_opts={'instance_name': '.*\-\d$'})
2984
 
        self.assertEqual(len(instances), 2)
2985
 
        instance_uuids = [instance['uuid'] for instance in instances]
2986
 
        self.assertTrue(instance1['uuid'] in instance_uuids)
2987
 
        self.assertTrue(instance2['uuid'] in instance_uuids)
2988
 
 
2989
 
        instances = self.compute_api.get_all(c,
2990
 
                search_opts={'instance_name': 'i.*2'})
2991
 
        self.assertEqual(len(instances), 1)
2992
 
        self.assertEqual(instances[0]['uuid'], instance2['uuid'])
2993
 
 
2994
 
        db.instance_destroy(c, instance1['uuid'])
2995
 
        db.instance_destroy(c, instance2['uuid'])
2996
 
        db.instance_destroy(c, instance3['uuid'])
2997
 
 
2998
3379
    def test_get_all_by_multiple_options_at_once(self):
2999
3380
        """Test searching by multiple options at once"""
3000
3381
        c = context.get_admin_context()
3006
3387
                       'instance_get_id_to_uuid_mapping',
3007
3388
                       db.instance_get_id_to_uuid_mapping)
3008
3389
 
3009
 
        instance1 = self._create_fake_instance({'display_name': 'woot',
3010
 
                                                'id': 0})
 
3390
        instance1 = self._create_fake_instance({
 
3391
                'display_name': 'woot',
 
3392
                'id': 0,
 
3393
                'uuid': '00000000-0000-0000-0000-000000000010'})
3011
3394
        instance2 = self._create_fake_instance({
3012
3395
                'display_name': 'woo',
3013
 
                'id': 20})
 
3396
                'id': 20,
 
3397
                'uuid': '00000000-0000-0000-0000-000000000020'})
3014
3398
        instance3 = self._create_fake_instance({
3015
3399
                'display_name': 'not-woot',
3016
 
                'id': 30})
 
3400
                'id': 30,
 
3401
                'uuid': '00000000-0000-0000-0000-000000000030'})
3017
3402
 
3018
3403
        # ip ends up matching 2nd octet here.. so all 3 match ip
3019
3404
        # but 'name' only matches one
3221
3606
        db.instance_destroy(c, instance4['uuid'])
3222
3607
 
3223
3608
    def test_instance_metadata(self):
3224
 
        """Test searching instances by state"""
 
3609
        meta_changes = [None]
 
3610
 
 
3611
        def fake_change_instance_metadata(inst, ctxt, diff, instance=None,
 
3612
                                          instance_uuid=None):
 
3613
            meta_changes[0] = diff
 
3614
        self.stubs.Set(compute_rpcapi.ComputeAPI, 'change_instance_metadata',
 
3615
                       fake_change_instance_metadata)
 
3616
 
3225
3617
        _context = context.get_admin_context()
3226
3618
        instance = self._create_fake_instance({'metadata': {'key1': 'value1'}})
3227
3619
 
3232
3624
                                                  {'key2': 'value2'})
3233
3625
        metadata = self.compute_api.get_instance_metadata(_context, instance)
3234
3626
        self.assertEqual(metadata, {'key1': 'value1', 'key2': 'value2'})
 
3627
        self.assertEqual(meta_changes, [{'key2': ['+', 'value2']}])
3235
3628
 
3236
3629
        new_metadata = {'key2': 'bah', 'key3': 'value3'}
3237
3630
        self.compute_api.update_instance_metadata(_context, instance,
3238
3631
                                                  new_metadata, delete=True)
3239
3632
        metadata = self.compute_api.get_instance_metadata(_context, instance)
3240
3633
        self.assertEqual(metadata, new_metadata)
 
3634
        self.assertEqual(meta_changes, [{
 
3635
                    'key1': ['-'],
 
3636
                    'key2': ['+', 'bah'],
 
3637
                    'key3': ['+', 'value3'],
 
3638
                    }])
3241
3639
 
3242
3640
        self.compute_api.delete_instance_metadata(_context, instance, 'key2')
3243
3641
        metadata = self.compute_api.get_instance_metadata(_context, instance)
3244
3642
        self.assertEqual(metadata, {'key3': 'value3'})
 
3643
        self.assertEqual(meta_changes, [{'key2': ['-']}])
3245
3644
 
3246
3645
        db.instance_destroy(_context, instance['uuid'])
3247
3646
 
3395
3794
            self.context, instance['uuid']):
3396
3795
            db.block_device_mapping_destroy(self.context, bdm['id'])
3397
3796
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
3398
 
        self.compute.terminate_instance(self.context, instance['uuid'])
 
3797
        self.compute.terminate_instance(self.context,
 
3798
                                        instance_uuid=instance['uuid'])
3399
3799
 
3400
3800
    def test_volume_size(self):
3401
3801
        ephemeral_size = 2
3447
3847
 
3448
3848
    def test_instance_unknown_architecture(self):
3449
3849
        """Test if the architecture is unknown."""
3450
 
        instance = self._create_fake_instance(
3451
 
                        params={'architecture': ''})
 
3850
        instance = jsonutils.to_primitive(self._create_fake_instance(
 
3851
                        params={'architecture': ''}))
3452
3852
        try:
3453
 
            self.compute.run_instance(self.context, instance['uuid'])
 
3853
            self.compute.run_instance(self.context, instance=instance)
3454
3854
            instances = db.instance_get_all(context.get_admin_context())
3455
3855
            instance = instances[0]
3456
3856
            self.assertNotEqual(instance['architecture'], 'Unknown')
3491
3891
        self.assertRaises(exception.InvalidDevicePath,
3492
3892
                self.compute_api.attach_volume,
3493
3893
                self.context,
3494
 
                None,
 
3894
                {'locked': False},
3495
3895
                None,
3496
3896
                '/dev/invalid')
3497
3897
 
3512
3912
        self.mox.StubOutWithMock(rpc, 'call')
3513
3913
 
3514
3914
        rpc_msg1 = {'method': 'get_vnc_console',
3515
 
                    'args': {'instance_uuid': fake_instance['uuid'],
 
3915
                    'args': {'instance': fake_instance,
3516
3916
                             'console_type': fake_console_type},
3517
 
                   'version': compute_rpcapi.ComputeAPI.RPC_API_VERSION}
 
3917
                   'version': '1.17'}
3518
3918
        rpc_msg2 = {'method': 'authorize_console',
3519
3919
                    'args': fake_connect_info,
3520
3920
                    'version': '1.0'}
3539
3939
        self.mox.StubOutWithMock(rpc, 'call')
3540
3940
 
3541
3941
        rpc_msg = {'method': 'get_console_output',
3542
 
                   'args': {'instance_uuid': fake_instance['uuid'],
 
3942
                   'args': {'instance': fake_instance,
3543
3943
                            'tail_length': fake_tail_length},
3544
 
                   'version': compute_rpcapi.ComputeAPI.RPC_API_VERSION}
 
3944
                   'version': '1.7'}
3545
3945
        rpc.call(self.context, 'compute.%s' % fake_instance['host'],
3546
3946
                rpc_msg, None).AndReturn(fake_console_output)
3547
3947
 
3572
3972
 
3573
3973
    def test_inject_network_info(self):
3574
3974
        instance = self._create_fake_instance()
3575
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3975
        self.compute.run_instance(self.context,
 
3976
                instance=jsonutils.to_primitive(instance))
3576
3977
        instance = self.compute_api.get(self.context, instance['uuid'])
3577
3978
        self.compute_api.inject_network_info(self.context, instance)
3578
3979
        self.compute_api.delete(self.context, instance)
3579
3980
 
3580
3981
    def test_reset_network(self):
3581
3982
        instance = self._create_fake_instance()
3582
 
        self.compute.run_instance(self.context, instance['uuid'])
 
3983
        self.compute.run_instance(self.context,
 
3984
                instance=jsonutils.to_primitive(instance))
3583
3985
        instance = self.compute_api.get(self.context, instance['uuid'])
3584
3986
        self.compute_api.reset_network(self.context, instance)
3585
3987
 
3602
4004
    def test_add_remove_security_group(self):
3603
4005
        instance = self._create_fake_instance()
3604
4006
 
3605
 
        self.compute.run_instance(self.context, instance['uuid'])
 
4007
        self.compute.run_instance(self.context,
 
4008
                instance=jsonutils.to_primitive(instance))
3606
4009
        instance = self.compute_api.get(self.context, instance['uuid'])
3607
4010
        security_group_name = self._create_group()['name']
3608
4011
        self.security_group_api.add_to_instance(self.context,
3624
4027
                                     "/tmp/test", "File Contents")
3625
4028
        db.instance_destroy(self.context, instance['uuid'])
3626
4029
 
 
4030
    def test_secgroup_refresh(self):
 
4031
        instance = self._create_fake_instance()
 
4032
 
 
4033
        def rule_get(*args, **kwargs):
 
4034
            mock_rule = FakeModel({'parent_group_id': 1})
 
4035
            return [mock_rule]
 
4036
 
 
4037
        def group_get(*args, **kwargs):
 
4038
            mock_group = FakeModel({'instances': [instance]})
 
4039
            return mock_group
 
4040
 
 
4041
        self.stubs.Set(
 
4042
                   self.compute_api.db,
 
4043
                   'security_group_rule_get_by_security_group_grantee',
 
4044
                   rule_get)
 
4045
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
 
4046
 
 
4047
        self.mox.StubOutWithMock(rpc, 'cast')
 
4048
        topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
 
4049
                                  instance['host'])
 
4050
        rpc.cast(self.context, topic,
 
4051
                {"method": "refresh_instance_security_rules",
 
4052
                 "args": {'instance': jsonutils.to_primitive(instance)},
 
4053
                 "version": '1.41'})
 
4054
        self.mox.ReplayAll()
 
4055
 
 
4056
        self.security_group_api.trigger_members_refresh(self.context, [1])
 
4057
 
 
4058
    def test_secgroup_refresh_once(self):
 
4059
        instance = self._create_fake_instance()
 
4060
 
 
4061
        def rule_get(*args, **kwargs):
 
4062
            mock_rule = FakeModel({'parent_group_id': 1})
 
4063
            return [mock_rule]
 
4064
 
 
4065
        def group_get(*args, **kwargs):
 
4066
            mock_group = FakeModel({'instances': [instance]})
 
4067
            return mock_group
 
4068
 
 
4069
        self.stubs.Set(
 
4070
                   self.compute_api.db,
 
4071
                   'security_group_rule_get_by_security_group_grantee',
 
4072
                   rule_get)
 
4073
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
 
4074
 
 
4075
        self.mox.StubOutWithMock(rpc, 'cast')
 
4076
        topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
 
4077
                                  instance['host'])
 
4078
        rpc.cast(self.context, topic,
 
4079
                {"method": "refresh_instance_security_rules",
 
4080
                 "args": {'instance': jsonutils.to_primitive(instance)},
 
4081
                 "version": '1.41'})
 
4082
        self.mox.ReplayAll()
 
4083
 
 
4084
        self.security_group_api.trigger_members_refresh(self.context, [1, 2])
 
4085
 
 
4086
    def test_secgroup_refresh_none(self):
 
4087
        def rule_get(*args, **kwargs):
 
4088
            mock_rule = FakeModel({'parent_group_id': 1})
 
4089
            return [mock_rule]
 
4090
 
 
4091
        def group_get(*args, **kwargs):
 
4092
            mock_group = FakeModel({'instances': []})
 
4093
            return mock_group
 
4094
 
 
4095
        self.stubs.Set(
 
4096
                   self.compute_api.db,
 
4097
                   'security_group_rule_get_by_security_group_grantee',
 
4098
                   rule_get)
 
4099
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
 
4100
 
 
4101
        self.mox.StubOutWithMock(rpc, 'cast')
 
4102
        self.mox.ReplayAll()
 
4103
 
 
4104
        self.security_group_api.trigger_members_refresh(self.context, [1])
 
4105
 
 
4106
    def test_secrule_refresh(self):
 
4107
        instance = self._create_fake_instance()
 
4108
 
 
4109
        def group_get(*args, **kwargs):
 
4110
            mock_group = FakeModel({'instances': [instance]})
 
4111
            return mock_group
 
4112
 
 
4113
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
 
4114
 
 
4115
        self.mox.StubOutWithMock(rpc, 'cast')
 
4116
        topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
 
4117
                                  instance['host'])
 
4118
        rpc.cast(self.context, topic,
 
4119
                {"method": "refresh_instance_security_rules",
 
4120
                 "args": {'instance': jsonutils.to_primitive(instance)},
 
4121
                 "version": '1.41'})
 
4122
        self.mox.ReplayAll()
 
4123
 
 
4124
        self.security_group_api.trigger_rules_refresh(self.context, [1])
 
4125
 
 
4126
    def test_secrule_refresh_once(self):
 
4127
        instance = self._create_fake_instance()
 
4128
 
 
4129
        def group_get(*args, **kwargs):
 
4130
            mock_group = FakeModel({'instances': [instance]})
 
4131
            return mock_group
 
4132
 
 
4133
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
 
4134
 
 
4135
        self.mox.StubOutWithMock(rpc, 'cast')
 
4136
        topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
 
4137
                                  instance['host'])
 
4138
        rpc.cast(self.context, topic,
 
4139
                {"method": "refresh_instance_security_rules",
 
4140
                 "args": {'instance': jsonutils.to_primitive(instance)},
 
4141
                 "version": '1.41'})
 
4142
        self.mox.ReplayAll()
 
4143
 
 
4144
        self.security_group_api.trigger_rules_refresh(self.context, [1, 2])
 
4145
 
 
4146
    def test_secrule_refresh_none(self):
 
4147
        def group_get(*args, **kwargs):
 
4148
            mock_group = FakeModel({'instances': []})
 
4149
            return mock_group
 
4150
 
 
4151
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
 
4152
 
 
4153
        self.mox.StubOutWithMock(rpc, 'cast')
 
4154
        self.mox.ReplayAll()
 
4155
 
 
4156
        self.security_group_api.trigger_rules_refresh(self.context, [1, 2])
 
4157
 
3627
4158
 
3628
4159
def fake_rpc_method(context, topic, msg, do_cast=True):
3629
4160
    pass
3643
4174
    return values
3644
4175
 
3645
4176
 
3646
 
class ComputeAPIAggrTestCase(test.TestCase):
 
4177
class ComputeAPIAggrTestCase(BaseTestCase):
3647
4178
    """This is for unit coverage of aggregate-related methods
3648
4179
    defined in nova.compute.api."""
3649
4180
 
3661
4192
                          self.context, 'fake_aggr', 'fake_avail_zone')
3662
4193
 
3663
4194
    def test_update_aggregate_metadata(self):
 
4195
        """Ensure metadata can be updated"""
3664
4196
        _create_service_entries(self.context, {'fake_zone': ['fake_host']})
3665
4197
        aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
3666
4198
                                         'fake_zone')
3681
4213
        self.api.delete_aggregate(self.context, aggr['id'])
3682
4214
        expected = db.aggregate_get(self.context.elevated(read_deleted='yes'),
3683
4215
                                    aggr['id'])
3684
 
        self.assertNotEqual(aggr['operational_state'],
3685
 
                            expected['operational_state'])
 
4216
        self.assertRaises(exception.AggregateNotFound,
 
4217
                          self.api.delete_aggregate, self.context, aggr['id'])
3686
4218
 
3687
4219
    def test_delete_non_empty_aggregate(self):
3688
4220
        """Ensure InvalidAggregateAction is raised when non empty aggregate."""
3703
4235
                                         'fake_aggregate', fake_zone)
3704
4236
        aggr = self.api.add_host_to_aggregate(self.context,
3705
4237
                                              aggr['id'], fake_host)
3706
 
        self.assertEqual(aggr['operational_state'], aggregate_states.CHANGING)
 
4238
        self.assertEqual(len(aggr['hosts']), 1)
3707
4239
 
3708
4240
    def test_add_host_to_aggregate_multiple(self):
3709
4241
        """Ensure we can add multiple hosts to an aggregate."""
3711
4243
        fake_zone = values.keys()[0]
3712
4244
        aggr = self.api.create_aggregate(self.context,
3713
4245
                                         'fake_aggregate', fake_zone)
3714
 
        # let's mock the fact that the aggregate is active already!
3715
 
        status = {'operational_state': aggregate_states.ACTIVE}
3716
 
        db.aggregate_update(self.context, aggr['id'], status)
3717
4246
        for host in values[fake_zone]:
3718
4247
            aggr = self.api.add_host_to_aggregate(self.context,
3719
4248
                                                  aggr['id'], host)
3720
4249
        self.assertEqual(len(aggr['hosts']), len(values[fake_zone]))
3721
 
        self.assertEqual(aggr['operational_state'],
3722
 
                         aggregate_states.ACTIVE)
3723
 
 
3724
 
    def test_add_host_to_aggregate_invalid_changing_status(self):
3725
 
        """Ensure InvalidAggregateAction is raised when adding host while
3726
 
        aggregate is not ready."""
3727
 
        values = _create_service_entries(self.context)
3728
 
        fake_zone = values.keys()[0]
3729
 
        fake_host = values[fake_zone][0]
3730
 
        aggr = self.api.create_aggregate(self.context,
3731
 
                                         'fake_aggregate', fake_zone)
3732
 
        aggr = self.api.add_host_to_aggregate(self.context,
3733
 
                                              aggr['id'], fake_host)
3734
 
        self.assertEqual(aggr['operational_state'],
3735
 
                             aggregate_states.CHANGING)
3736
 
        self.assertRaises(exception.InvalidAggregateAction,
3737
 
                          self.api.add_host_to_aggregate, self.context,
3738
 
                          aggr['id'], fake_host)
3739
 
 
3740
 
    def test_add_host_to_aggregate_invalid_dismissed_status(self):
3741
 
        """Ensure InvalidAggregateAction is raised when aggregate is
3742
 
        deleted."""
3743
 
        _create_service_entries(self.context, {'fake_zone': ['fake_host']})
3744
 
        aggr = self.api.create_aggregate(self.context,
3745
 
                                         'fake_aggregate', 'fake_zone')
3746
 
        # let's mock the fact that the aggregate is dismissed!
3747
 
        status = {'operational_state': aggregate_states.DISMISSED}
3748
 
        db.aggregate_update(self.context, aggr['id'], status)
3749
 
        self.assertRaises(exception.InvalidAggregateAction,
3750
 
                          self.api.add_host_to_aggregate, self.context,
3751
 
                          aggr['id'], 'fake_host')
3752
 
 
3753
 
    def test_add_host_to_aggregate_invalid_error_status(self):
3754
 
        """Ensure InvalidAggregateAction is raised when aggregate is
3755
 
        in error."""
3756
 
        _create_service_entries(self.context, {'fake_zone': ['fake_host']})
3757
 
        aggr = self.api.create_aggregate(self.context,
3758
 
                                         'fake_aggregate', 'fake_zone')
3759
 
        # let's mock the fact that the aggregate is in error!
3760
 
        status = {'operational_state': aggregate_states.ERROR}
3761
 
        db.aggregate_update(self.context, aggr['id'], status)
3762
 
        self.assertRaises(exception.InvalidAggregateAction,
3763
 
                          self.api.add_host_to_aggregate, self.context,
3764
 
                          aggr['id'], 'fake_host')
3765
4250
 
3766
4251
    def test_add_host_to_aggregate_zones_mismatch(self):
3767
4252
        """Ensure InvalidAggregateAction is raised when zones don't match."""
3788
4273
        fake_zone = values.keys()[0]
3789
4274
        aggr = self.api.create_aggregate(self.context,
3790
4275
                                         'fake_aggregate', fake_zone)
3791
 
        # let's mock the fact that the aggregate is active already!
3792
 
        status = {'operational_state': aggregate_states.ACTIVE}
3793
 
        db.aggregate_update(self.context, aggr['id'], status)
3794
 
        for host in values[fake_zone]:
3795
 
            aggr = self.api.add_host_to_aggregate(self.context,
3796
 
                                                  aggr['id'], host)
3797
 
        expected = self.api.remove_host_from_aggregate(self.context,
3798
 
                                                       aggr['id'],
3799
 
                                                       values[fake_zone][0])
3800
 
        self.assertEqual(len(aggr['hosts']) - 1, len(expected['hosts']))
3801
 
        self.assertEqual(expected['operational_state'],
3802
 
                         aggregate_states.ACTIVE)
3803
 
 
3804
 
    def test_remove_host_from_aggregate_error(self):
3805
 
        """Ensure we can remove a host from an aggregate even if in error."""
3806
 
        values = _create_service_entries(self.context)
3807
 
        fake_zone = values.keys()[0]
3808
 
        aggr = self.api.create_aggregate(self.context,
3809
 
                                         'fake_aggregate', fake_zone)
3810
 
        # let's mock the fact that the aggregate is ready!
3811
 
        status = {'operational_state': aggregate_states.ACTIVE}
3812
 
        db.aggregate_update(self.context, aggr['id'], status)
3813
 
        for host in values[fake_zone]:
3814
 
            aggr = self.api.add_host_to_aggregate(self.context,
3815
 
                                                  aggr['id'], host)
3816
 
        # let's mock the fact that the aggregate is in error!
3817
 
        status = {'operational_state': aggregate_states.ERROR}
3818
 
        expected = self.api.remove_host_from_aggregate(self.context,
3819
 
                                                       aggr['id'],
3820
 
                                                       values[fake_zone][0])
3821
 
        self.assertEqual(len(aggr['hosts']) - 1, len(expected['hosts']))
3822
 
        self.assertEqual(expected['operational_state'],
3823
 
                         aggregate_states.ACTIVE)
3824
 
 
3825
 
    def test_remove_host_from_aggregate_invalid_dismissed_status(self):
3826
 
        """Ensure InvalidAggregateAction is raised when aggregate is
3827
 
        deleted."""
3828
 
        _create_service_entries(self.context, {'fake_zone': ['fake_host']})
3829
 
        aggr = self.api.create_aggregate(self.context,
3830
 
                                         'fake_aggregate', 'fake_zone')
3831
 
        # let's mock the fact that the aggregate is dismissed!
3832
 
        status = {'operational_state': aggregate_states.DISMISSED}
3833
 
        db.aggregate_update(self.context, aggr['id'], status)
3834
 
        self.assertRaises(exception.InvalidAggregateAction,
3835
 
                          self.api.remove_host_from_aggregate, self.context,
3836
 
                          aggr['id'], 'fake_host')
3837
 
 
3838
 
    def test_remove_host_from_aggregate_invalid_changing_status(self):
3839
 
        """Ensure InvalidAggregateAction is raised when aggregate is
3840
 
        changing."""
3841
 
        _create_service_entries(self.context, {'fake_zone': ['fake_host']})
3842
 
        aggr = self.api.create_aggregate(self.context,
3843
 
                                         'fake_aggregate', 'fake_zone')
3844
 
        # let's mock the fact that the aggregate is changing!
3845
 
        status = {'operational_state': aggregate_states.CHANGING}
3846
 
        db.aggregate_update(self.context, aggr['id'], status)
3847
 
        self.assertRaises(exception.InvalidAggregateAction,
3848
 
                          self.api.remove_host_from_aggregate, self.context,
3849
 
                          aggr['id'], 'fake_host')
 
4276
        for host in values[fake_zone]:
 
4277
            aggr = self.api.add_host_to_aggregate(self.context,
 
4278
                                                  aggr['id'], host)
 
4279
        expected = self.api.remove_host_from_aggregate(self.context,
 
4280
                                                       aggr['id'],
 
4281
                                                       values[fake_zone][0])
 
4282
        self.assertEqual(len(aggr['hosts']) - 1, len(expected['hosts']))
3850
4283
 
3851
4284
    def test_remove_host_from_aggregate_raise_not_found(self):
3852
4285
        """Ensure ComputeHostNotFound is raised when removing invalid host."""
3866
4299
        super(ComputeAggrTestCase, self).setUp()
3867
4300
        self.context = context.get_admin_context()
3868
4301
        values = {'name': 'test_aggr',
3869
 
                  'availability_zone': 'test_zone', }
 
4302
                  'availability_zone': 'test_zone'}
3870
4303
        self.aggr = db.aggregate_create(self.context, values)
3871
4304
 
3872
4305
    def test_add_aggregate_host(self):
3879
4312
        self.compute.add_aggregate_host(self.context, self.aggr.id, "host")
3880
4313
        self.assertTrue(fake_driver_add_to_aggregate.called)
3881
4314
 
3882
 
    def test_add_aggregate_host_raise_err(self):
3883
 
        """Ensure the undo operation works correctly on add."""
3884
 
        def fake_driver_add_to_aggregate(context, aggregate, host):
3885
 
            raise exception.AggregateError
3886
 
        self.stubs.Set(self.compute.driver, "add_to_aggregate",
3887
 
                       fake_driver_add_to_aggregate)
3888
 
 
3889
 
        state = {'operational_state': aggregate_states.ACTIVE}
3890
 
        db.aggregate_update(self.context, self.aggr.id, state)
3891
 
        db.aggregate_host_add(self.context, self.aggr.id, 'fake_host')
3892
 
 
3893
 
        self.assertRaises(exception.AggregateError,
3894
 
                          self.compute.add_aggregate_host,
3895
 
                          self.context, self.aggr.id, "fake_host")
3896
 
        excepted = db.aggregate_get(self.context, self.aggr.id)
3897
 
        self.assertEqual(excepted.operational_state, aggregate_states.ERROR)
3898
 
        self.assertEqual(excepted.hosts, [])
3899
 
 
3900
4315
    def test_remove_aggregate_host(self):
3901
4316
        def fake_driver_remove_from_aggregate(context, aggregate, host):
3902
4317
            fake_driver_remove_from_aggregate.called = True
3908
4323
        self.compute.remove_aggregate_host(self.context, self.aggr.id, "host")
3909
4324
        self.assertTrue(fake_driver_remove_from_aggregate.called)
3910
4325
 
3911
 
    def test_remove_aggregate_host_raise_err(self):
3912
 
        """Ensure the undo operation works correctly on remove."""
3913
 
        def fake_driver_remove_from_aggregate(context, aggregate, host):
3914
 
            raise exception.AggregateError
3915
 
        self.stubs.Set(self.compute.driver, "remove_from_aggregate",
3916
 
                       fake_driver_remove_from_aggregate)
3917
 
 
3918
 
        state = {'operational_state': aggregate_states.ACTIVE}
3919
 
        db.aggregate_update(self.context, self.aggr.id, state)
3920
 
 
3921
 
        self.assertRaises(exception.AggregateError,
3922
 
                          self.compute.remove_aggregate_host,
3923
 
                          self.context, self.aggr.id, "fake_host")
3924
 
        excepted = db.aggregate_get(self.context, self.aggr.id)
3925
 
        self.assertEqual(excepted.operational_state, aggregate_states.ERROR)
3926
 
        self.assertEqual(excepted.hosts, ['fake_host'])
3927
 
 
3928
4326
 
3929
4327
class ComputePolicyTestCase(BaseTestCase):
3930
4328
 
4055
4453
        self.assertEqual(call_info['msg'],
4056
4454
                {'method': 'set_host_enabled',
4057
4455
                 'args': {'enabled': 'fake_enabled'},
4058
 
                 'version': compute_rpcapi.ComputeAPI.RPC_API_VERSION})
 
4456
                 'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION})
 
4457
 
 
4458
    def test_get_host_uptime(self):
 
4459
        ctxt = context.RequestContext('fake', 'fake')
 
4460
        call_info = {}
 
4461
        self._rpc_call_stub(call_info)
 
4462
 
 
4463
        self.host_api.get_host_uptime(ctxt, 'fake_host')
 
4464
        self.assertEqual(call_info['context'], ctxt)
 
4465
        self.assertEqual(call_info['topic'], 'compute.fake_host')
 
4466
        self.assertEqual(call_info['msg'],
 
4467
                {'method': 'get_host_uptime',
 
4468
                 'args': {},
 
4469
                 'version': '1.1'})
4059
4470
 
4060
4471
    def test_host_power_action(self):
4061
4472
        ctxt = context.RequestContext('fake', 'fake')
4067
4478
        self.assertEqual(call_info['msg'],
4068
4479
                {'method': 'host_power_action',
4069
4480
                 'args': {'action': 'fake_action'},
4070
 
                 'version': compute_rpcapi.ComputeAPI.RPC_API_VERSION})
 
4481
                 'version':
 
4482
                 compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION})
4071
4483
 
4072
4484
    def test_set_host_maintenance(self):
4073
4485
        ctxt = context.RequestContext('fake', 'fake')
4079
4491
        self.assertEqual(call_info['msg'],
4080
4492
                {'method': 'host_maintenance_mode',
4081
4493
                 'args': {'host': 'fake_host', 'mode': 'fake_mode'},
4082
 
                 'version': compute_rpcapi.ComputeAPI.RPC_API_VERSION})
 
4494
                 'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION})
4083
4495
 
4084
4496
 
4085
4497
class KeypairAPITestCase(BaseTestCase):
4088
4500
        self.keypair_api = compute_api.KeypairAPI()
4089
4501
        self.ctxt = context.RequestContext('fake', 'fake')
4090
4502
        self._keypair_db_call_stubs()
 
4503
        self.existing_key_name = 'fake existing key name'
4091
4504
        self.pub_key = ('ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLnVkqJu9WVf'
4092
4505
                        '/5StU3JCrBR2r1s1j8K1tux+5XeSvdqaM8lMFNorzbY5iyoBbR'
4093
4506
                        'S56gy1jmm43QsMPJsrpfUZKcJpRENSe3OxIIwWXRoiapZe78u/'
4109
4522
        def db_key_pair_destroy(context, user_id, name):
4110
4523
            pass
4111
4524
 
 
4525
        def db_key_pair_get(context, user_id, name):
 
4526
            if name == self.existing_key_name:
 
4527
                return {'name': self.existing_key_name,
 
4528
                        'public_key': self.pub_key,
 
4529
                        'fingerprint': self.fingerprint}
 
4530
            else:
 
4531
                raise exception.KeypairNotFound(user_id=user_id, name=name)
 
4532
 
4112
4533
        self.stubs.Set(db, "key_pair_get_all_by_user",
4113
4534
                       db_key_pair_get_all_by_user)
4114
4535
        self.stubs.Set(db, "key_pair_create",
4115
4536
                       db_key_pair_create)
4116
4537
        self.stubs.Set(db, "key_pair_destroy",
4117
4538
                       db_key_pair_destroy)
 
4539
        self.stubs.Set(db, "key_pair_get",
 
4540
                       db_key_pair_get)
4118
4541
 
4119
4542
    def test_create_keypair(self):
4120
4543
        keypair = self.keypair_api.create_key_pair(self.ctxt,
4132
4555
                          self.ctxt, self.ctxt.user_id, '* BAD CHARACTERS! *')
4133
4556
 
4134
4557
    def test_create_keypair_already_exists(self):
4135
 
        def db_key_pair_get(context, user_id, name):
4136
 
            pass
4137
 
        self.stubs.Set(db, "key_pair_get",
4138
 
                       db_key_pair_get)
4139
4558
        self.assertRaises(exception.KeyPairExists,
4140
4559
                          self.keypair_api.create_key_pair,
4141
 
                          self.ctxt, self.ctxt.user_id, 'foo')
 
4560
                          self.ctxt, self.ctxt.user_id,
 
4561
                          self.existing_key_name)
4142
4562
 
4143
4563
    def test_create_keypair_quota_limit(self):
4144
4564
        def fake_quotas_count(self, context, resource, *args, **kwargs):
4182
4602
                          self.keypair_api.import_key_pair,
4183
4603
                          self.ctxt, self.ctxt.user_id, 'foo', self.pub_key)
4184
4604
 
 
4605
    def test_get_keypair(self):
 
4606
        keypair = self.keypair_api.get_key_pair(self.ctxt,
 
4607
                                                self.ctxt.user_id,
 
4608
                                                self.existing_key_name)
 
4609
        self.assertEqual(self.existing_key_name, keypair['name'])
 
4610
 
4185
4611
 
4186
4612
class DisabledInstanceTypesTestCase(BaseTestCase):
4187
4613
    """
4308
4734
        self.assertNotRaises(exception.FlavorNotFound,
4309
4735
            self.compute_api.resize, self.context, instance, None,
4310
4736
            exc_msg="Disabled flavors can be migrated to")
 
4737
 
 
4738
 
 
4739
class ComputeReschedulingTestCase(BaseTestCase):
 
4740
    """Tests related to re-scheduling build requests"""
 
4741
 
 
4742
    def setUp(self):
 
4743
        super(ComputeReschedulingTestCase, self).setUp()
 
4744
 
 
4745
        self._reschedule = self._reschedule_partial()
 
4746
 
 
4747
    def _reschedule_partial(self):
 
4748
        uuid = "12-34-56-78-90"
 
4749
 
 
4750
        requested_networks = None
 
4751
        admin_password = None
 
4752
        injected_files = None
 
4753
        is_first_time = False
 
4754
 
 
4755
        return functools.partial(self.compute._reschedule, self.context, uuid,
 
4756
                requested_networks, admin_password, injected_files,
 
4757
                is_first_time, request_spec=None, filter_properties={})
 
4758
 
 
4759
    def test_reschedule_no_filter_properties(self):
 
4760
        """no filter_properties will disable re-scheduling"""
 
4761
        self.assertFalse(self._reschedule())
 
4762
 
 
4763
    def test_reschedule_no_retry_info(self):
 
4764
        """no retry info will also disable re-scheduling"""
 
4765
        filter_properties = {}
 
4766
        self.assertFalse(self._reschedule(filter_properties=filter_properties))
 
4767
 
 
4768
    def test_reschedule_no_request_spec(self):
 
4769
        """no request spec will also disable re-scheduling"""
 
4770
        retry = dict(num_attempts=1)
 
4771
        filter_properties = dict(retry=retry)
 
4772
        self.assertFalse(self._reschedule(filter_properties=filter_properties))
 
4773
 
 
4774
    def test_reschedule_success(self):
 
4775
        retry = dict(num_attempts=1)
 
4776
        filter_properties = dict(retry=retry)
 
4777
        request_spec = {'num_instances': 42}
 
4778
        self.assertTrue(self._reschedule(filter_properties=filter_properties,
 
4779
            request_spec=request_spec))
 
4780
        self.assertEqual(1, request_spec['num_instances'])
 
4781
 
 
4782
 
 
4783
class ThatsNoOrdinaryRabbitException(Exception):
 
4784
    pass
 
4785
 
 
4786
 
 
4787
class ComputeReschedulingExceptionTestCase(BaseTestCase):
 
4788
    """Tests for re-scheduling exception handling logic"""
 
4789
 
 
4790
    def setUp(self):
 
4791
        super(ComputeReschedulingExceptionTestCase, self).setUp()
 
4792
 
 
4793
        # cause _spawn to raise an exception to test the exception logic:
 
4794
        def exploding_spawn(*args, **kwargs):
 
4795
            raise ThatsNoOrdinaryRabbitException()
 
4796
        self.stubs.Set(self.compute, '_spawn',
 
4797
                exploding_spawn)
 
4798
 
 
4799
        self.fake_instance = jsonutils.to_primitive(
 
4800
                self._create_fake_instance())
 
4801
        self.instance_uuid = self.fake_instance['uuid']
 
4802
 
 
4803
    def test_exception_with_rescheduling_disabled(self):
 
4804
        """Spawn fails and re-scheduling is disabled."""
 
4805
        # this won't be re-scheduled:
 
4806
        self.assertRaises(ThatsNoOrdinaryRabbitException,
 
4807
                self.compute._run_instance, self.context,
 
4808
                None, {}, None, None, None, None, self.fake_instance, None)
 
4809
 
 
4810
    def test_exception_with_rescheduling_enabled(self):
 
4811
        """Spawn fails and re-scheduling is enabled.  Original exception
 
4812
        should *not* be re-raised.
 
4813
        """
 
4814
        # provide the expected status so that this one will be re-scheduled:
 
4815
        retry = dict(num_attempts=1)
 
4816
        filter_properties = dict(retry=retry)
 
4817
        request_spec = dict(num_attempts=1)
 
4818
        self.assertNotRaises(ThatsNoOrdinaryRabbitException,
 
4819
                self.compute._run_instance, self.context,
 
4820
                filter_properties=filter_properties, request_spec=request_spec,
 
4821
                instance=self.fake_instance)
 
4822
 
 
4823
    def test_exception_context_cleared(self):
 
4824
        """Test with no rescheduling and an additional exception occurs
 
4825
        clearing the original build error's exception context.
 
4826
        """
 
4827
        # clears the original exception context:
 
4828
        class FleshWoundException(Exception):
 
4829
            pass
 
4830
 
 
4831
        def reschedule_explode(*args, **kwargs):
 
4832
            raise FleshWoundException()
 
4833
        self.stubs.Set(self.compute, '_reschedule', reschedule_explode)
 
4834
 
 
4835
        # the original exception should now be raised:
 
4836
        self.assertRaises(ThatsNoOrdinaryRabbitException,
 
4837
                self.compute._run_instance, self.context,
 
4838
                None, {}, None, None, None, None, self.fake_instance, None)