~ubuntu-branches/ubuntu/raring/nova/raring-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, Adam Gandelman, Chuck Short
  • Date: 2012-11-23 09:04:58 UTC
  • mfrom: (1.1.66)
  • Revision ID: package-import@ubuntu.com-20121123090458-91565o7aev1i1h71
Tags: 2013.1~g1-0ubuntu1
[ Adam Gandelman ]
* debian/control: Ensure novaclient is upgraded with nova,
  require python-keystoneclient >= 1:2.9.0. (LP: #1073289)
* debian/patches/{ubuntu/*, rbd-security.patch}: Dropped, applied
  upstream.
* debian/control: Add python-testtools to Build-Depends.

[ Chuck Short ]
* New upstream version.
* Refreshed debian/patches/avoid_setuptools_git_dependency.patch.
* debian/rules: FTBFS if missing binaries.
* debian/nova-scheudler.install: Add missing rabbit-queues and
  nova-rpc-zmq-receiver.
* Remove nova-volume since it doesnt exist anymore, transition to cinder-*.
* debian/rules: install apport hook in the right place.
* debian/patches/ubuntu-show-tests.patch: Display test failures.
* debian/control: Add depends on genisoimage
* debian/control: Suggest guestmount.
* debian/control: Suggest websockify. (LP: #1076442)
* debian/nova.conf: Disable nova-volume service.
* debian/control: Depend on xen-system-* rather than the hypervisor.
* debian/control, debian/mans/nova-conductor.8, debian/nova-conductor.init,
  debian/nova-conductor.install, debian/nova-conductor.logrotate
  debian/nova-conductor.manpages, debian/nova-conductor.postrm
  debian/nova-conductor.upstart.in: Add nova-conductor service.
* debian/control: Add python-fixtures as a build deps.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
import base64
22
22
import copy
23
23
import datetime
24
 
import functools
25
24
import sys
26
25
import time
 
26
import uuid
27
27
 
28
28
import mox
29
29
 
40
40
from nova import context
41
41
from nova import db
42
42
from nova import exception
43
 
from nova import flags
 
43
from nova.network import api as network_api
 
44
from nova.network import model as network_model
 
45
from nova.openstack.common import cfg
44
46
from nova.openstack.common import importutils
45
47
from nova.openstack.common import jsonutils
46
48
from nova.openstack.common import log as logging
56
58
from nova.tests.compute import fake_resource_tracker
57
59
from nova.tests.db.fakes import FakeModel
58
60
from nova.tests import fake_network
 
61
from nova.tests import fake_network_cache_model
59
62
from nova.tests.image import fake as fake_image
 
63
from nova.tests import matchers
60
64
from nova import utils
61
 
import nova.volume
 
65
from nova.virt import fake
 
66
from nova.volume import cinder
62
67
 
63
68
 
64
69
QUOTAS = quota.QUOTAS
65
70
LOG = logging.getLogger(__name__)
66
 
FLAGS = flags.FLAGS
67
 
flags.DECLARE('live_migration_retry_count', 'nova.compute.manager')
 
71
CONF = cfg.CONF
 
72
CONF.import_opt('compute_manager', 'nova.config')
 
73
CONF.import_opt('compute_topic', 'nova.config')
 
74
CONF.import_opt('host', 'nova.config')
 
75
CONF.import_opt('live_migration_retry_count', 'nova.compute.manager')
68
76
 
69
77
 
70
78
FAKE_IMAGE_REF = 'fake-image-ref'
71
79
 
 
80
NODENAME = 'fakenode1'
 
81
 
72
82
 
73
83
def nop_report_driver_status(self):
74
84
    pass
85
95
            instance, dest):
86
96
        pass
87
97
 
 
98
    def prep_resize(self, ctxt, instance, instance_type, image, request_spec,
 
99
            filter_properties, reservations):
 
100
        pass
 
101
 
88
102
 
89
103
class BaseTestCase(test.TestCase):
90
104
 
93
107
        self.flags(compute_driver='nova.virt.fake.FakeDriver',
94
108
                   notification_driver=[test_notifier.__name__],
95
109
                   network_manager='nova.network.manager.FlatManager')
96
 
        self.compute = importutils.import_object(FLAGS.compute_manager)
 
110
        fake.set_nodes([NODENAME])
 
111
        self.compute = importutils.import_object(CONF.compute_manager)
97
112
 
98
113
        # override tracker with a version that doesn't need the database:
99
 
        self.compute.resource_tracker = \
100
 
            fake_resource_tracker.FakeResourceTracker(self.compute.host,
101
 
                    self.compute.driver)
 
114
        fake_rt = fake_resource_tracker.FakeResourceTracker(self.compute.host,
 
115
                    self.compute.driver, NODENAME)
 
116
        self.compute._resource_tracker_dict[NODENAME] = fake_rt
102
117
        self.compute.update_available_resource(
103
118
                context.get_admin_context())
104
119
 
111
126
        def fake_show(meh, context, id):
112
127
            return {'id': id, 'min_disk': None, 'min_ram': None,
113
128
                    'name': 'fake_name',
 
129
                    'status': 'active',
114
130
                    'properties': {'kernel_id': 'fake_kernel_id',
115
131
                                   'ramdisk_id': 'fake_ramdisk_id',
116
132
                                   'something_else': 'meow'}}
128
144
        notifier_api._reset_drivers()
129
145
        for instance in instances:
130
146
            db.instance_destroy(self.context.elevated(), instance['uuid'])
 
147
        fake.restore_nodes()
131
148
        super(BaseTestCase, self).tearDown()
132
149
 
133
150
    def _create_fake_instance(self, params=None, type_name='m1.tiny'):
143
160
        inst['user_id'] = self.user_id
144
161
        inst['project_id'] = self.project_id
145
162
        inst['host'] = 'fake_host'
 
163
        inst['node'] = NODENAME
146
164
        type_id = instance_types.get_instance_type_by_name(type_name)['id']
147
165
        inst['instance_type_id'] = type_id
148
166
        inst['ami_launch_index'] = 0
195
213
                                                          spectacular=True)
196
214
 
197
215
        super(ComputeTestCase, self).setUp()
198
 
        self.stubs.Set(nova.network.API, 'get_instance_nw_info',
 
216
        self.stubs.Set(network_api.API, 'get_instance_nw_info',
199
217
                       fake_get_nw_info)
200
 
        self.stubs.Set(nova.network.API, 'allocate_for_instance',
 
218
        self.stubs.Set(network_api.API, 'allocate_for_instance',
201
219
                       fake_get_nw_info)
202
220
        self.compute_api = compute.API()
 
221
        # Just to make long lines short
 
222
        self.rt = self.compute._get_resource_tracker(NODENAME)
203
223
 
204
224
    def tearDown(self):
205
225
        super(ComputeTestCase, self).tearDown()
216
236
        self.stubs.Set(compute_utils, 'add_instance_fault_from_exc',
217
237
                       did_it_add_fault)
218
238
 
219
 
        @nova.compute.manager.wrap_instance_fault
 
239
        @compute_manager.wrap_instance_fault
220
240
        def failer(self2, context, instance):
221
241
            raise NotImplementedError()
222
242
 
225
245
 
226
246
        self.assertTrue(called['fault_added'])
227
247
 
 
248
    def test_wrap_instance_fault_instance_in_args(self):
 
249
        inst = {"uuid": "fake_uuid"}
 
250
 
 
251
        called = {'fault_added': False}
 
252
 
 
253
        def did_it_add_fault(*args):
 
254
            called['fault_added'] = True
 
255
 
 
256
        self.stubs.Set(compute_utils, 'add_instance_fault_from_exc',
 
257
                       did_it_add_fault)
 
258
 
 
259
        @compute_manager.wrap_instance_fault
 
260
        def failer(self2, context, instance):
 
261
            raise NotImplementedError()
 
262
 
 
263
        self.assertRaises(NotImplementedError, failer,
 
264
                          self.compute, self.context, inst)
 
265
 
 
266
        self.assertTrue(called['fault_added'])
 
267
 
228
268
    def test_wrap_instance_fault_no_instance(self):
229
269
        inst_uuid = "fake_uuid"
230
270
 
236
276
        self.stubs.Set(compute_utils, 'add_instance_fault_from_exc',
237
277
                       did_it_add_fault)
238
278
 
239
 
        @nova.compute.manager.wrap_instance_fault
 
279
        @compute_manager.wrap_instance_fault
240
280
        def failer(self2, context, instance_uuid):
241
281
            raise exception.InstanceNotFound()
242
282
 
253
293
 
254
294
        try:
255
295
            self.compute.run_instance(self.context, instance=instance)
256
 
            instances = db.instance_get_all(context.get_admin_context())
 
296
            instances = db.instance_get_all(self.context)
257
297
            instance = instances[0]
258
298
 
259
299
            self.assertTrue(instance.config_drive)
268
308
 
269
309
        try:
270
310
            self.compute.run_instance(self.context, instance=instance)
271
 
            instances = db.instance_get_all(context.get_admin_context())
 
311
            instances = db.instance_get_all(self.context)
272
312
            instance = instances[0]
273
313
 
274
314
            self.assertTrue(instance.config_drive)
278
318
    def test_create_instance_unlimited_memory(self):
279
319
        """Default of memory limit=None is unlimited"""
280
320
        self.flags(reserved_host_disk_mb=0, reserved_host_memory_mb=0)
281
 
        self.compute.resource_tracker.update_available_resource(self.context)
 
321
        self.rt.update_available_resource(self.context.elevated())
282
322
        params = {"memory_mb": 999999999999}
283
323
        filter_properties = {'limits': {'memory_mb': None}}
284
324
        instance = self._create_fake_instance(params)
285
325
        self.compute.run_instance(self.context, instance=instance,
286
326
                filter_properties=filter_properties)
287
 
        self.assertEqual(999999999999,
288
 
                self.compute.resource_tracker.compute_node['memory_mb_used'])
 
327
        self.assertEqual(999999999999, self.rt.compute_node['memory_mb_used'])
289
328
 
290
329
    def test_create_instance_unlimited_disk(self):
291
330
        self.flags(reserved_host_disk_mb=0, reserved_host_memory_mb=0)
292
 
        self.compute.resource_tracker.update_available_resource(self.context)
 
331
        self.rt.update_available_resource(self.context.elevated())
293
332
        params = {"root_gb": 999999999999,
294
333
                  "ephemeral_gb": 99999999999}
295
334
        filter_properties = {'limits': {'disk_gb': None}}
299
338
 
300
339
    def test_create_multiple_instances_then_starve(self):
301
340
        self.flags(reserved_host_disk_mb=0, reserved_host_memory_mb=0)
302
 
        self.compute.resource_tracker.update_available_resource(self.context)
 
341
        self.rt.update_available_resource(self.context.elevated())
303
342
        filter_properties = {'limits': {'memory_mb': 4096, 'disk_gb': 1000}}
304
343
        params = {"memory_mb": 1024, "root_gb": 128, "ephemeral_gb": 128}
305
344
        instance = self._create_fake_instance(params)
306
345
        self.compute.run_instance(self.context, instance=instance,
307
346
                                  filter_properties=filter_properties)
308
 
        self.assertEquals(1024,
309
 
                self.compute.resource_tracker.compute_node['memory_mb_used'])
310
 
        self.assertEquals(256,
311
 
                self.compute.resource_tracker.compute_node['local_gb_used'])
 
347
        self.assertEquals(1024, self.rt.compute_node['memory_mb_used'])
 
348
        self.assertEquals(256, self.rt.compute_node['local_gb_used'])
312
349
 
313
350
        params = {"memory_mb": 2048, "root_gb": 256, "ephemeral_gb": 256}
314
351
        instance = self._create_fake_instance(params)
315
352
        self.compute.run_instance(self.context, instance=instance,
316
353
                                  filter_properties=filter_properties)
317
 
        self.assertEquals(3072,
318
 
                self.compute.resource_tracker.compute_node['memory_mb_used'])
319
 
        self.assertEquals(768,
320
 
                self.compute.resource_tracker.compute_node['local_gb_used'])
 
354
        self.assertEquals(3072, self.rt.compute_node['memory_mb_used'])
 
355
        self.assertEquals(768, self.rt.compute_node['local_gb_used'])
321
356
 
322
357
        params = {"memory_mb": 8192, "root_gb": 8192, "ephemeral_gb": 8192}
323
358
        instance = self._create_fake_instance(params)
329
364
        """Test passing of oversubscribed ram policy from the scheduler."""
330
365
 
331
366
        self.flags(reserved_host_disk_mb=0, reserved_host_memory_mb=0)
332
 
        self.compute.resource_tracker.update_available_resource(self.context)
 
367
        self.rt.update_available_resource(self.context.elevated())
333
368
 
334
369
        # get total memory as reported by virt driver:
335
 
        resources = self.compute.driver.get_available_resource()
 
370
        resources = self.compute.driver.get_available_resource(NODENAME)
336
371
        total_mem_mb = resources['memory_mb']
337
372
 
338
373
        oversub_limit_mb = total_mem_mb * 1.5
349
384
        self.compute.run_instance(self.context, instance=instance,
350
385
                filter_properties=filter_properties)
351
386
 
352
 
        self.assertEqual(instance_mb,
353
 
                self.compute.resource_tracker.compute_node['memory_mb_used'])
 
387
        self.assertEqual(instance_mb, self.rt.compute_node['memory_mb_used'])
354
388
 
355
389
    def test_create_instance_with_oversubscribed_ram_fail(self):
356
390
        """Test passing of oversubscribed ram policy from the scheduler, but
357
391
        with insufficient memory.
358
392
        """
359
393
        self.flags(reserved_host_disk_mb=0, reserved_host_memory_mb=0)
360
 
        self.compute.resource_tracker.update_available_resource(self.context)
 
394
        self.rt.update_available_resource(self.context.elevated())
361
395
 
362
396
        # get total memory as reported by virt driver:
363
 
        resources = self.compute.driver.get_available_resource()
 
397
        resources = self.compute.driver.get_available_resource(NODENAME)
364
398
        total_mem_mb = resources['memory_mb']
365
399
 
366
400
        oversub_limit_mb = total_mem_mb * 1.5
382
416
        """Test passing of oversubscribed cpu policy from the scheduler."""
383
417
 
384
418
        self.flags(reserved_host_disk_mb=0, reserved_host_memory_mb=0)
385
 
        self.compute.resource_tracker.update_available_resource(self.context)
 
419
        self.rt.update_available_resource(self.context.elevated())
386
420
        limits = {'vcpu': 3}
387
421
        filter_properties = {'limits': limits}
388
422
 
389
423
        # get total memory as reported by virt driver:
390
 
        resources = self.compute.driver.get_available_resource()
 
424
        resources = self.compute.driver.get_available_resource(NODENAME)
391
425
        self.assertEqual(1, resources['vcpus'])
392
426
 
393
427
        # build an instance, specifying an amount of memory that exceeds
398
432
        self.compute.run_instance(self.context, instance=instance,
399
433
                filter_properties=filter_properties)
400
434
 
401
 
        self.assertEqual(2,
402
 
                self.compute.resource_tracker.compute_node['vcpus_used'])
 
435
        self.assertEqual(2, self.rt.compute_node['vcpus_used'])
403
436
 
404
437
        # create one more instance:
405
438
        params = {"memory_mb": 10, "root_gb": 1,
408
441
        self.compute.run_instance(self.context, instance=instance,
409
442
                filter_properties=filter_properties)
410
443
 
411
 
        self.assertEqual(3,
412
 
                self.compute.resource_tracker.compute_node['vcpus_used'])
 
444
        self.assertEqual(3, self.rt.compute_node['vcpus_used'])
413
445
 
414
446
        # delete the instance:
415
447
        instance['vm_state'] = vm_states.DELETED
416
 
        self.compute.resource_tracker.update_usage(self.context,
 
448
        self.rt.update_usage(self.context,
417
449
                instance=instance)
418
450
 
419
 
        self.assertEqual(2,
420
 
                self.compute.resource_tracker.compute_node['vcpus_used'])
 
451
        self.assertEqual(2, self.rt.compute_node['vcpus_used'])
421
452
 
422
453
        # now oversubscribe vcpus and fail:
423
454
        params = {"memory_mb": 10, "root_gb": 1,
434
465
        """Test passing of oversubscribed disk policy from the scheduler."""
435
466
 
436
467
        self.flags(reserved_host_disk_mb=0, reserved_host_memory_mb=0)
437
 
        self.compute.resource_tracker.update_available_resource(self.context)
 
468
        self.rt.update_available_resource(self.context.elevated())
438
469
 
439
470
        # get total memory as reported by virt driver:
440
 
        resources = self.compute.driver.get_available_resource()
 
471
        resources = self.compute.driver.get_available_resource(NODENAME)
441
472
        total_disk_gb = resources['local_gb']
442
473
 
443
474
        oversub_limit_gb = total_disk_gb * 1.5
453
484
        self.compute.run_instance(self.context, instance=instance,
454
485
                filter_properties=filter_properties)
455
486
 
456
 
        self.assertEqual(instance_gb,
457
 
                self.compute.resource_tracker.compute_node['local_gb_used'])
 
487
        self.assertEqual(instance_gb, self.rt.compute_node['local_gb_used'])
458
488
 
459
489
    def test_create_instance_with_oversubscribed_disk_fail(self):
460
490
        """Test passing of oversubscribed disk policy from the scheduler, but
461
491
        with insufficient disk.
462
492
        """
463
493
        self.flags(reserved_host_disk_mb=0, reserved_host_memory_mb=0)
464
 
        self.compute.resource_tracker.update_available_resource(self.context)
 
494
        self.rt.update_available_resource(self.context.elevated())
465
495
 
466
496
        # get total memory as reported by virt driver:
467
 
        resources = self.compute.driver.get_available_resource()
 
497
        resources = self.compute.driver.get_available_resource(NODENAME)
468
498
        total_disk_gb = resources['local_gb']
469
499
 
470
500
        oversub_limit_gb = total_disk_gb * 1.5
489
519
        try:
490
520
            self.compute.run_instance(self.context, instance=instance,
491
521
                    is_first_time=True)
492
 
            instances = db.instance_get_all(context.get_admin_context())
 
522
            instances = db.instance_get_all(self.context)
493
523
            instance = instances[0]
494
524
 
495
525
            self.assertEqual(instance.access_ip_v4, '192.168.1.100')
503
533
        try:
504
534
            self.compute.run_instance(self.context, instance=instance,
505
535
                    is_first_time=True)
506
 
            instances = db.instance_get_all(context.get_admin_context())
 
536
            instances = db.instance_get_all(self.context)
507
537
            instance = instances[0]
508
538
 
509
539
            self.assertFalse(instance.access_ip_v4)
558
588
        self._assert_state({'vm_state': vm_states.ERROR,
559
589
                            'task_state': None})
560
590
 
 
591
    def test_run_instance_dealloc_network_instance_not_found(self):
 
592
        """ spawn network deallocate test.
 
593
 
 
594
        Make sure that when an instance is not found during spawn
 
595
        that the network is deallocated"""
 
596
        instance = self._create_instance()
 
597
 
 
598
        def fake(*args, **kwargs):
 
599
            raise exception.InstanceNotFound()
 
600
 
 
601
        self.stubs.Set(self.compute.driver, 'spawn', fake)
 
602
        self.mox.StubOutWithMock(self.compute, '_deallocate_network')
 
603
        self.compute._deallocate_network(mox.IgnoreArg(), mox.IgnoreArg())
 
604
        self.mox.ReplayAll()
 
605
 
 
606
        self.assertRaises(exception.InstanceNotFound,
 
607
                          self.compute.run_instance,
 
608
                          self.context, instance=instance)
 
609
 
561
610
    def test_can_terminate_on_error_state(self):
562
611
        """Make sure that the instance can be terminated in ERROR state"""
563
 
        elevated = context.get_admin_context()
564
612
        #check failed to schedule --> terminate
565
613
        instance = self._create_instance(params={'vm_state': vm_states.ERROR})
566
614
        self.compute.terminate_instance(self.context, instance=instance)
567
615
        self.assertRaises(exception.InstanceNotFound, db.instance_get_by_uuid,
568
 
                          elevated, instance['uuid'])
 
616
                          self.context, instance['uuid'])
 
617
        # Double check it's not there for admins, either.
 
618
        self.assertRaises(exception.InstanceNotFound, db.instance_get_by_uuid,
 
619
                          self.context.elevated(), instance['uuid'])
569
620
 
570
621
    def test_run_terminate(self):
571
622
        """Make sure it is possible to  run and terminate instance"""
573
624
 
574
625
        self.compute.run_instance(self.context, instance=instance)
575
626
 
576
 
        instances = db.instance_get_all(context.get_admin_context())
 
627
        instances = db.instance_get_all(self.context)
577
628
        LOG.info(_("Running instances: %s"), instances)
578
629
        self.assertEqual(len(instances), 1)
579
630
 
580
631
        self.compute.terminate_instance(self.context, instance=instance)
581
632
 
582
 
        instances = db.instance_get_all(context.get_admin_context())
 
633
        instances = db.instance_get_all(self.context)
583
634
        LOG.info(_("After terminating instances: %s"), instances)
584
635
        self.assertEqual(len(instances), 0)
585
636
 
591
642
 
592
643
        self.compute.run_instance(self.context, instance=instance)
593
644
 
594
 
        instances = db.instance_get_all(context.get_admin_context())
 
645
        instances = db.instance_get_all(self.context)
595
646
        LOG.info(_("Running instances: %s"), instances)
596
647
        self.assertEqual(len(instances), 1)
597
648
 
604
655
        def fake_volume_get(self, context, volume_id):
605
656
            return {'id': volume_id}
606
657
 
607
 
        self.stubs.Set(nova.volume.api.API, 'get', fake_volume_get)
608
 
        self.stubs.Set(nova.volume.api.API, 'check_attach', fake_check_attach)
609
 
        self.stubs.Set(nova.volume.api.API, 'reserve_volume',
 
658
        self.stubs.Set(cinder.API, 'get', fake_volume_get)
 
659
        self.stubs.Set(cinder.API, 'check_attach', fake_check_attach)
 
660
        self.stubs.Set(cinder.API, 'reserve_volume',
610
661
                       fake_reserve_volume)
611
662
 
612
663
        self.compute_api.attach_volume(self.context, instance, 1,
614
665
 
615
666
        self.compute.terminate_instance(self.context, instance=instance)
616
667
 
617
 
        instances = db.instance_get_all(context.get_admin_context())
 
668
        instances = db.instance_get_all(self.context)
618
669
        LOG.info(_("After terminating instances: %s"), instances)
619
670
        self.assertEqual(len(instances), 0)
 
671
        bdms = db.block_device_mapping_get_all_by_instance(self.context,
 
672
                                                           instance['uuid'])
 
673
        self.assertEqual(len(bdms), 0)
620
674
 
621
675
    def test_terminate_no_network(self):
622
676
        # This is as reported in LP bug 1008875
624
678
 
625
679
        self.compute.run_instance(self.context, instance=instance)
626
680
 
627
 
        instances = db.instance_get_all(context.get_admin_context())
 
681
        instances = db.instance_get_all(self.context)
628
682
        LOG.info(_("Running instances: %s"), instances)
629
683
        self.assertEqual(len(instances), 1)
630
684
 
637
691
 
638
692
        self.compute.terminate_instance(self.context, instance=instance)
639
693
 
640
 
        instances = db.instance_get_all(context.get_admin_context())
 
694
        instances = db.instance_get_all(self.context)
641
695
        LOG.info(_("After terminating instances: %s"), instances)
642
696
        self.assertEqual(len(instances), 0)
643
697
 
649
703
 
650
704
        self.compute.run_instance(self.context, instance=instance)
651
705
 
652
 
        instances = db.instance_get_all(context.get_admin_context())
 
706
        instances = db.instance_get_all(self.context)
653
707
        LOG.info(_("Running instances: %s"), instances)
654
708
        self.assertEqual(len(instances), 1)
655
709
 
667
721
        except TypeError:
668
722
            pass
669
723
 
670
 
        instances = db.instance_get_all(context.get_admin_context())
 
724
        instances = db.instance_get_all(self.context)
671
725
        LOG.info(_("After terminating instances: %s"), instances)
672
726
        self.assertEqual(len(instances), 1)
673
727
        self.assertEqual(instances[0]['task_state'], 'deleting')
684
738
        self.assertEqual(instance['deleted_at'], None)
685
739
        terminate = timeutils.utcnow()
686
740
        self.compute.terminate_instance(self.context, instance=instance)
687
 
        context = self.context.elevated(read_deleted="only")
688
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
741
        with utils.temporary_mutation(self.context, read_deleted='only'):
 
742
            instance = db.instance_get_by_uuid(self.context,
 
743
                    instance['uuid'])
689
744
        self.assert_(instance['launched_at'] < terminate)
690
745
        self.assert_(instance['deleted_at'] > terminate)
691
746
 
694
749
        instance = jsonutils.to_primitive(self._create_fake_instance())
695
750
        self.compute.run_instance(self.context, instance=instance)
696
751
        db.instance_update(self.context, instance['uuid'],
697
 
                           {"task_state": task_states.STOPPING})
 
752
                           {"task_state": task_states.POWERING_OFF})
698
753
        self.compute.stop_instance(self.context, instance=instance)
699
754
        self.compute.terminate_instance(self.context, instance=instance)
700
755
 
703
758
        instance = jsonutils.to_primitive(self._create_fake_instance())
704
759
        self.compute.run_instance(self.context, instance=instance)
705
760
        db.instance_update(self.context, instance['uuid'],
706
 
                           {"task_state": task_states.STOPPING})
 
761
                           {"task_state": task_states.POWERING_OFF})
707
762
        self.compute.stop_instance(self.context, instance=instance)
708
763
        db.instance_update(self.context, instance['uuid'],
709
 
                           {"task_state": task_states.STARTING})
 
764
                           {"task_state": task_states.POWERING_ON})
710
765
        self.compute.start_instance(self.context, instance=instance)
711
766
        self.compute.terminate_instance(self.context, instance=instance)
712
767
 
732
787
        instance_uuid = instance['uuid']
733
788
        self.compute.run_instance(self.context, instance=instance)
734
789
 
735
 
        db.instance_update(self.context, instance['uuid'],
 
790
        db.instance_update(self.context, instance_uuid,
736
791
                           {"task_state": task_states.RESCUING})
737
792
        self.compute.rescue_instance(self.context, instance=instance)
738
793
        self.assertTrue(called['rescued'])
739
 
        db.instance_update(self.context, instance['uuid'],
 
794
        db.instance_update(self.context, instance_uuid,
740
795
                           {"task_state": task_states.UNRESCUING})
741
796
        self.compute.unrescue_instance(self.context, instance=instance)
742
797
        self.assertTrue(called['unrescued'])
758
813
        self.compute.run_instance(self.context, instance=instance)
759
814
        db.instance_update(self.context, instance['uuid'],
760
815
                           {"task_state": task_states.POWERING_ON})
761
 
        self.compute.power_on_instance(self.context, instance=instance)
 
816
        self.compute.start_instance(self.context, instance=instance)
762
817
        self.assertTrue(called['power_on'])
763
818
        self.compute.terminate_instance(self.context, instance=instance)
764
819
 
777
832
        self.compute.run_instance(self.context, instance=instance)
778
833
        db.instance_update(self.context, instance['uuid'],
779
834
                           {"task_state": task_states.POWERING_OFF})
780
 
        self.compute.power_off_instance(self.context, instance=instance)
 
835
        self.compute.stop_instance(self.context, instance=instance)
781
836
        self.assertTrue(called['power_off'])
782
837
        self.compute.terminate_instance(self.context, instance=instance)
783
838
 
835
890
                                      image_ref, image_ref,
836
891
                                      injected_files=[],
837
892
                                      new_pass="new_password",
838
 
                                      orig_sys_metadata=sys_metadata)
 
893
                                      orig_sys_metadata=sys_metadata,
 
894
                                      bdms=[])
839
895
        self.compute.terminate_instance(self.context, instance=instance)
840
896
 
841
897
    def test_rebuild_launch_time(self):
854
910
        self.compute.rebuild_instance(self.context, instance,
855
911
                                      image_ref, image_ref,
856
912
                                      injected_files=[],
857
 
                                      new_pass="new_password")
858
 
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
913
                                      new_pass="new_password",
 
914
                                      bdms=[])
 
915
        instance = db.instance_get_by_uuid(self.context, instance_uuid,)
859
916
        self.assertEquals(cur_time, instance['launched_at'])
860
917
        self.compute.terminate_instance(self.context,
861
918
                instance=jsonutils.to_primitive(instance))
862
919
 
 
920
    def _stub_out_reboot(self, fake_net_info, fake_block_dev_info):
 
921
        def fake_reboot(driver, inst, net_info, reboot_type, block_dev_info):
 
922
            self.assertEqual(block_dev_info, fake_block_dev_info)
 
923
            self.assertEqual(net_info, fake_net_info)
 
924
 
 
925
        self.stubs.Set(nova.virt.fake.FakeDriver, 'legacy_nwinfo',
 
926
                       lambda x: False)
 
927
        self.stubs.Set(nova.virt.fake.FakeDriver, 'reboot', fake_reboot)
 
928
 
863
929
    def test_reboot_soft(self):
864
930
        """Ensure instance can be soft rebooted"""
865
931
        instance = jsonutils.to_primitive(self._create_fake_instance())
868
934
                           {'task_state': task_states.REBOOTING})
869
935
 
870
936
        reboot_type = "SOFT"
871
 
        self.compute.reboot_instance(self.context,
872
 
                                     instance=instance,
 
937
        fake_net_info = []
 
938
        fake_block_dev_info = {'foo': 'bar'}
 
939
        self._stub_out_reboot(fake_net_info, fake_block_dev_info)
 
940
        self.compute.reboot_instance(self.context, instance=instance,
 
941
                                     network_info=fake_net_info,
 
942
                                     block_device_info=fake_block_dev_info,
873
943
                                     reboot_type=reboot_type)
874
944
 
875
945
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
887
957
                           {'task_state': task_states.REBOOTING_HARD})
888
958
 
889
959
        reboot_type = "HARD"
 
960
        fake_net_info = []
 
961
        fake_block_dev_info = {'foo': 'bar'}
 
962
        self._stub_out_reboot(fake_net_info, fake_block_dev_info)
890
963
        self.compute.reboot_instance(self.context, instance=instance,
 
964
                                     network_info=fake_net_info,
 
965
                                     block_device_info=fake_block_dev_info,
891
966
                                     reboot_type=reboot_type)
892
967
 
893
968
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
897
972
        self.compute.terminate_instance(self.context,
898
973
                instance=jsonutils.to_primitive(inst_ref))
899
974
 
 
975
    def test_reboot_nwinfo(self):
 
976
        """Ensure instance network info is rehydrated in reboot"""
 
977
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
978
        self.compute.run_instance(self.context, instance=instance)
 
979
        db.instance_update(self.context, instance['uuid'],
 
980
                           {'task_state': task_states.REBOOTING_HARD})
 
981
 
 
982
        result = {'was_instance': []}
 
983
 
 
984
        # NOTE(danms): Beware the dragons ahead:
 
985
        # Since the _legacy_nw_info() method in manager runs inside a
 
986
        # try..except block, we can't assert from here. Further, this
 
987
        # will be run more than once during the operation we're about
 
988
        # to fire off, which means we need to make sure that it doesn't
 
989
        # fail any of the times it is run. Hence the obscurity below.
 
990
        def fake_legacy_nw_info(network_info):
 
991
            result['was_instance'].append(
 
992
                isinstance(network_info, network_model.NetworkInfo))
 
993
        self.stubs.Set(self.compute, '_legacy_nw_info', fake_legacy_nw_info)
 
994
 
 
995
        fake_net_info = network_model.NetworkInfo([
 
996
                fake_network_cache_model.new_vif(),
 
997
                fake_network_cache_model.new_vif(
 
998
                    {'address': 'bb:bb:bb:bb:bb:bb'})])
 
999
        fake_net_info_p = jsonutils.to_primitive(fake_net_info)
 
1000
        fake_block_dev_info = {'foo': 'bar'}
 
1001
        self.compute.reboot_instance(self.context, instance=instance,
 
1002
                                     network_info=fake_net_info_p,
 
1003
                                     block_device_info=fake_block_dev_info,
 
1004
                                     reboot_type="SOFT")
 
1005
 
 
1006
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
 
1007
        self.compute.terminate_instance(self.context,
 
1008
                instance=jsonutils.to_primitive(inst_ref))
 
1009
        self.assertFalse(False in result['was_instance'])
 
1010
 
900
1011
    def test_set_admin_password(self):
901
1012
        """Ensure instance can have its admin password set"""
902
1013
        instance = jsonutils.to_primitive(self._create_fake_instance())
1051
1162
                       fake_driver_reset_network)
1052
1163
 
1053
1164
        instance = jsonutils.to_primitive(self._create_fake_instance())
1054
 
        instance_uuid = instance['uuid']
1055
1165
        self.compute.run_instance(self.context, instance=instance)
1056
1166
 
1057
1167
        self.compute.reset_network(self.context, instance=instance)
1063
1173
    def test_snapshot(self):
1064
1174
        """Ensure instance can be snapshotted"""
1065
1175
        instance = jsonutils.to_primitive(self._create_fake_instance())
1066
 
        instance_uuid = instance['uuid']
1067
1176
        name = "myfakesnapshot"
1068
1177
        self.compute.run_instance(self.context, instance=instance)
1069
1178
        db.instance_update(self.context, instance['uuid'],
1090
1199
 
1091
1200
    def _assert_state(self, state_dict):
1092
1201
        """Assert state of VM is equal to state passed as parameter"""
1093
 
        instances = db.instance_get_all(context.get_admin_context())
 
1202
        instances = db.instance_get_all(self.context)
1094
1203
        self.assertEqual(len(instances), 1)
1095
1204
 
1096
1205
        if 'vm_state' in state_dict:
1166
1275
 
1167
1276
    def test_diagnostics(self):
1168
1277
        """Make sure we can get diagnostics for an instance."""
 
1278
        expected_diagnostic = {'cpu0_time': 17300000000,
 
1279
                             'memory': 524288,
 
1280
                             'vda_errors': -1,
 
1281
                             'vda_read': 262144,
 
1282
                             'vda_read_req': 112,
 
1283
                             'vda_write': 5778432,
 
1284
                             'vda_write_req': 488,
 
1285
                             'vnet1_rx': 2070139,
 
1286
                             'vnet1_rx_drop': 0,
 
1287
                             'vnet1_rx_errors': 0,
 
1288
                             'vnet1_rx_packets': 26701,
 
1289
                             'vnet1_tx': 140208,
 
1290
                             'vnet1_tx_drop': 0,
 
1291
                             'vnet1_tx_errors': 0,
 
1292
                             'vnet1_tx_packets': 662,
 
1293
                            }
 
1294
 
1169
1295
        instance = jsonutils.to_primitive(self._create_fake_instance())
1170
1296
        self.compute.run_instance(self.context, instance=instance)
1171
1297
 
1172
1298
        diagnostics = self.compute.get_diagnostics(self.context,
1173
1299
                instance=instance)
1174
 
        self.assertEqual(diagnostics, 'FAKE_DIAGNOSTICS')
1175
 
 
1176
 
        diagnostics = self.compute.get_diagnostics(self.context,
1177
 
                instance=instance)
1178
 
        self.assertEqual(diagnostics, 'FAKE_DIAGNOSTICS')
 
1300
        self.assertEqual(diagnostics, expected_diagnostic)
1179
1301
        self.compute.terminate_instance(self.context, instance=instance)
1180
1302
 
1181
1303
    def test_add_fixed_ip_usage_notification(self):
1182
1304
        def dummy(*args, **kwargs):
1183
1305
            pass
1184
1306
 
1185
 
        self.stubs.Set(nova.network.API, 'add_fixed_ip_to_instance',
 
1307
        self.stubs.Set(network_api.API, 'add_fixed_ip_to_instance',
1186
1308
                       dummy)
1187
1309
        self.stubs.Set(nova.compute.manager.ComputeManager,
1188
1310
                       'inject_network_info', dummy)
1190
1312
                       'reset_network', dummy)
1191
1313
 
1192
1314
        instance = jsonutils.to_primitive(self._create_fake_instance())
1193
 
        instance_uuid = instance['uuid']
1194
1315
 
1195
1316
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 0)
1196
1317
        self.compute.add_fixed_ip_to_instance(self.context, network_id=1,
1203
1324
        def dummy(*args, **kwargs):
1204
1325
            pass
1205
1326
 
1206
 
        self.stubs.Set(nova.network.API, 'remove_fixed_ip_from_instance',
 
1327
        self.stubs.Set(network_api.API, 'remove_fixed_ip_from_instance',
1207
1328
                       dummy)
1208
1329
        self.stubs.Set(nova.compute.manager.ComputeManager,
1209
1330
                       'inject_network_info', dummy)
1211
1332
                       'reset_network', dummy)
1212
1333
 
1213
1334
        instance = jsonutils.to_primitive(self._create_fake_instance())
1214
 
        instance_uuid = instance['uuid']
1215
1335
 
1216
1336
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 0)
1217
1337
        self.compute.remove_fixed_ip_from_instance(self.context, 1,
1339
1459
                       fake_cleanup_volumes)
1340
1460
 
1341
1461
        self.compute._delete_instance(self.context,
1342
 
                instance=jsonutils.to_primitive(instance))
 
1462
                instance=jsonutils.to_primitive(instance),
 
1463
                bdms={})
1343
1464
 
1344
1465
    def test_instance_termination_exception_sets_error(self):
1345
1466
        """Test that we handle InstanceTerminationFailure
1347
1468
        """
1348
1469
        instance = self._create_fake_instance()
1349
1470
 
1350
 
        def fake_delete_instance(context, instance):
 
1471
        def fake_delete_instance(context, instance, bdms):
1351
1472
            raise exception.InstanceTerminationFailure(reason='')
1352
1473
 
1353
1474
        self.stubs.Set(self.compute, '_delete_instance',
1364
1485
 
1365
1486
        self.mox.StubOutWithMock(self.compute, "_setup_block_device_mapping")
1366
1487
        self.compute._setup_block_device_mapping(
1367
 
                mox.IgnoreArg(),
 
1488
                mox.IgnoreArg(), mox.IgnoreArg(),
1368
1489
                mox.IgnoreArg()).AndRaise(rpc.common.RemoteError('', '', ''))
1369
1490
 
1370
1491
        self.mox.ReplayAll()
1416
1537
                instance=jsonutils.to_primitive(instance))
1417
1538
 
1418
1539
    def _test_state_revert(self, operation, pre_task_state,
1419
 
                           post_task_state):
 
1540
                           post_task_state=None, kwargs=None):
 
1541
        if kwargs is None:
 
1542
            kwargs = {}
 
1543
 
1420
1544
        instance = self._create_fake_instance()
1421
1545
        self.compute.run_instance(self.context, instance=instance)
1422
1546
 
1429
1553
        orig_notify = self.compute._notify_about_instance_usage
1430
1554
 
1431
1555
        def _get_an_exception(*args, **kwargs):
1432
 
            raise Exception("This fails every single time!")
 
1556
            raise test.TestingException()
1433
1557
 
1434
1558
        self.stubs.Set(self.context, 'elevated', _get_an_exception)
1435
1559
        self.stubs.Set(self.compute,
1436
1560
                       '_notify_about_instance_usage', _get_an_exception)
1437
1561
 
 
1562
        func = getattr(self.compute, operation)
 
1563
 
1438
1564
        raised = False
1439
1565
        try:
1440
 
            ret_val = getattr(self.compute, operation)(self.context,
1441
 
                                                       instance=instance)
1442
 
        except Exception:
 
1566
            func(self.context, instance=instance, **kwargs)
 
1567
        except test.TestingException:
1443
1568
            raised = True
1444
1569
        finally:
1445
1570
            # self.context.elevated() is called in tearDown()
1457
1582
    def test_state_revert(self):
1458
1583
        """ensure that task_state is reverted after a failed operation"""
1459
1584
        actions = [
1460
 
            ("reboot_instance", task_states.REBOOTING, None),
1461
 
            ("stop_instance", task_states.STOPPING, None),
1462
 
            ("start_instance", task_states.STARTING, None),
 
1585
            ("reboot_instance", task_states.REBOOTING),
 
1586
            ("stop_instance", task_states.POWERING_OFF),
 
1587
            ("start_instance", task_states.POWERING_ON),
1463
1588
            ("terminate_instance", task_states.DELETING,
1464
1589
                                   task_states.DELETING),
1465
 
            ("power_off_instance", task_states.POWERING_OFF, None),
1466
 
            ("power_on_instance", task_states.POWERING_ON, None),
1467
 
            ("rebuild_instance", task_states.REBUILDING, None),
1468
 
            ("set_admin_password", task_states.UPDATING_PASSWORD, None),
1469
 
            ("rescue_instance", task_states.RESCUING, None),
1470
 
            ("unrescue_instance", task_states.UNRESCUING, None),
1471
 
            ("revert_resize", task_states.RESIZE_REVERTING, None),
1472
 
            ("prep_resize", task_states.RESIZE_PREP, None),
1473
 
            ("resize_instance", task_states.RESIZE_PREP, None),
1474
 
            ("pause_instance", task_states.PAUSING, None),
1475
 
            ("unpause_instance", task_states.UNPAUSING, None),
1476
 
            ("suspend_instance", task_states.SUSPENDING, None),
1477
 
            ("resume_instance", task_states.RESUMING, None),
 
1590
            ("power_off_instance", task_states.POWERING_OFF),
 
1591
            ("power_on_instance", task_states.POWERING_ON),
 
1592
            ("soft_delete_instance", task_states.SOFT_DELETING),
 
1593
            ("restore_instance", task_states.RESTORING),
 
1594
            ("rebuild_instance", task_states.REBUILDING, None,
 
1595
                                 {'orig_image_ref': None,
 
1596
                                  'image_ref': None,
 
1597
                                  'injected_files': [],
 
1598
                                  'new_pass': ''}),
 
1599
            ("set_admin_password", task_states.UPDATING_PASSWORD),
 
1600
            ("rescue_instance", task_states.RESCUING),
 
1601
            ("unrescue_instance", task_states.UNRESCUING),
 
1602
            ("revert_resize", task_states.RESIZE_REVERTING, None,
 
1603
                              {'migration_id': None}),
 
1604
            ("prep_resize", task_states.RESIZE_PREP, None,
 
1605
                            {'image': {},
 
1606
                             'instance_type': {}}),
 
1607
            ("resize_instance", task_states.RESIZE_PREP, None,
 
1608
                                {'migration_id': None,
 
1609
                                 'image': {}}),
 
1610
            ("pause_instance", task_states.PAUSING),
 
1611
            ("unpause_instance", task_states.UNPAUSING),
 
1612
            ("suspend_instance", task_states.SUSPENDING),
 
1613
            ("resume_instance", task_states.RESUMING),
1478
1614
            ]
1479
1615
 
1480
 
        for operation, pre_state, post_state in actions:
1481
 
            self._test_state_revert(operation, pre_state, post_state)
 
1616
        for operation in actions:
 
1617
            self._test_state_revert(*operation)
1482
1618
 
1483
1619
    def _ensure_quota_reservations_committed(self):
1484
1620
        """Mock up commit of quota reservations"""
1506
1642
 
1507
1643
        reservations = self._ensure_quota_reservations_committed()
1508
1644
 
1509
 
        context = self.context.elevated()
1510
1645
        instance = jsonutils.to_primitive(self._create_fake_instance())
1511
1646
        instance_type = instance_types.get_default_instance_type()
1512
1647
        db.instance_update(self.context, instance["uuid"],
1513
1648
                          {"task_state": task_states.RESIZE_PREP})
1514
 
        self.compute.prep_resize(context, instance=instance,
 
1649
        self.compute.prep_resize(self.context, instance=instance,
1515
1650
                                 instance_type=instance_type,
1516
1651
                                 image={})
1517
 
        migration_ref = db.migration_get_by_instance_and_status(context,
1518
 
                instance['uuid'], 'pre-migrating')
 
1652
        migration_ref = db.migration_get_by_instance_and_status(
 
1653
                self.context.elevated(), instance['uuid'], 'pre-migrating')
1519
1654
        db.instance_update(self.context, instance["uuid"],
1520
1655
                           {"task_state": task_states.RESIZE_MIGRATED})
1521
 
        self.compute.finish_resize(context,
1522
 
                migration_id=int(migration_ref['id']),
 
1656
        self.compute.finish_resize(self.context,
 
1657
                migration=jsonutils.to_primitive(migration_ref),
1523
1658
                disk_info={}, image={}, instance=instance,
1524
1659
                reservations=reservations)
1525
1660
        self.compute.terminate_instance(self.context, instance=instance)
1537
1672
 
1538
1673
        reservations = self._ensure_quota_reservations_rolledback()
1539
1674
 
1540
 
        context = self.context.elevated()
1541
1675
        instance = jsonutils.to_primitive(self._create_fake_instance())
1542
1676
        instance_type = instance_types.get_default_instance_type()
1543
 
        self.compute.prep_resize(context, instance=instance,
 
1677
        self.compute.prep_resize(self.context, instance=instance,
1544
1678
                                 instance_type=instance_type,
1545
1679
                                 image={}, reservations=reservations)
1546
 
        migration_ref = db.migration_get_by_instance_and_status(context,
1547
 
                instance['uuid'], 'pre-migrating')
 
1680
        migration_ref = db.migration_get_by_instance_and_status(
 
1681
                self.context.elevated(), instance['uuid'], 'pre-migrating')
1548
1682
 
1549
1683
        db.instance_update(self.context, instance["uuid"],
1550
1684
                           {"task_state": task_states.RESIZE_MIGRATED})
1551
1685
        self.assertRaises(test.TestingException, self.compute.finish_resize,
1552
 
                          context, migration_id=int(migration_ref['id']),
 
1686
                          self.context,
 
1687
                          migration=jsonutils.to_primitive(migration_ref),
1553
1688
                          disk_info={}, image={}, instance=instance,
1554
1689
                          reservations=reservations)
1555
1690
 
1556
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
1691
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
1557
1692
        self.assertEqual(instance['vm_state'], vm_states.ERROR)
1558
1693
        self.compute.terminate_instance(self.context,
1559
1694
                instance=jsonutils.to_primitive(instance))
1582
1717
 
1583
1718
        db.instance_update(self.context, instance['uuid'],
1584
1719
                           {"task_state": task_states.REBUILDING})
1585
 
        self.compute.rebuild_instance(self.context.elevated(),
 
1720
        self.compute.rebuild_instance(self.context,
1586
1721
                                      jsonutils.to_primitive(instance),
1587
1722
                                      image_ref, new_image_ref,
1588
1723
                                      injected_files=[],
1589
1724
                                      new_pass=password,
1590
 
                                      orig_sys_metadata=orig_sys_metadata)
 
1725
                                      orig_sys_metadata=orig_sys_metadata,
 
1726
                                      bdms=[])
1591
1727
 
1592
1728
        instance = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
1593
1729
 
1630
1766
        cur_time = datetime.datetime(2012, 12, 21, 12, 21)
1631
1767
        timeutils.set_time_override(old_time)
1632
1768
        instance = jsonutils.to_primitive(self._create_fake_instance())
1633
 
        context = self.context.elevated()
1634
 
        old_type_id = instance_types.get_instance_type_by_name(
1635
 
                                                'm1.tiny')['id']
1636
1769
        new_type = instance_types.get_instance_type_by_name('m1.small')
1637
1770
        new_type = jsonutils.to_primitive(new_type)
1638
1771
        new_type_id = new_type['id']
1639
1772
        self.compute.run_instance(self.context, instance=instance)
1640
1773
 
1641
 
        db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1642
 
        db.instance_update(self.context, instance["uuid"],
 
1774
        new_instance = db.instance_update(self.context, instance['uuid'],
 
1775
                                      {'host': 'foo'})
 
1776
        new_instance = jsonutils.to_primitive(new_instance)
 
1777
        db.instance_update(self.context, new_instance["uuid"],
1643
1778
                           {"task_state": task_states.RESIZE_PREP})
1644
 
        self.compute.prep_resize(context, instance=instance,
 
1779
        self.compute.prep_resize(self.context, instance=new_instance,
1645
1780
                instance_type=new_type, image={})
1646
 
        migration_ref = db.migration_get_by_instance_and_status(context,
1647
 
                                                instance['uuid'],
1648
 
                                                'pre-migrating')
1649
 
        self.compute.resize_instance(context, instance=instance,
1650
 
                                     migration_id=migration_ref['id'],
1651
 
                                     image={})
 
1781
        migration_ref = db.migration_get_by_instance_and_status(
 
1782
                self.context.elevated(), new_instance['uuid'], 'pre-migrating')
 
1783
        self.compute.resize_instance(self.context, instance=new_instance,
 
1784
                migration=migration_ref, image={}, instance_type=new_type)
1652
1785
        timeutils.set_time_override(cur_time)
1653
1786
        test_notifier.NOTIFICATIONS = []
1654
1787
 
1655
 
        self.compute.finish_resize(context,
1656
 
                migration_id=int(migration_ref['id']), disk_info={}, image={},
1657
 
                instance=instance)
 
1788
        self.compute.finish_resize(self.context,
 
1789
                migration=jsonutils.to_primitive(migration_ref),
 
1790
                disk_info={}, image={}, instance=new_instance)
1658
1791
 
1659
1792
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
1660
1793
        msg = test_notifier.NOTIFICATIONS[0]
1667
1800
        payload = msg['payload']
1668
1801
        self.assertEquals(payload['tenant_id'], self.project_id)
1669
1802
        self.assertEquals(payload['user_id'], self.user_id)
1670
 
        self.assertEquals(payload['instance_id'], instance['uuid'])
 
1803
        self.assertEquals(payload['instance_id'], new_instance['uuid'])
1671
1804
        self.assertEquals(payload['instance_type'], 'm1.small')
1672
1805
        self.assertEquals(str(payload['instance_type_id']), str(new_type_id))
1673
1806
        self.assertTrue('display_name' in payload)
1676
1809
        self.assertEqual(payload['launched_at'], str(cur_time))
1677
1810
        image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
1678
1811
        self.assertEquals(payload['image_ref_url'], image_ref_url)
1679
 
        self.compute.terminate_instance(context,
1680
 
            instance=jsonutils.to_primitive(instance))
 
1812
        self.compute.terminate_instance(self.context,
 
1813
            instance=jsonutils.to_primitive(new_instance))
1681
1814
 
1682
1815
    def test_resize_instance_notification(self):
1683
1816
        """Ensure notifications on instance migrate/resize"""
1685
1818
        cur_time = datetime.datetime(2012, 12, 21, 12, 21)
1686
1819
        timeutils.set_time_override(old_time)
1687
1820
        instance = jsonutils.to_primitive(self._create_fake_instance())
1688
 
        context = self.context.elevated()
1689
1821
 
1690
1822
        self.compute.run_instance(self.context, instance=instance)
1691
1823
        timeutils.set_time_override(cur_time)
1692
1824
        test_notifier.NOTIFICATIONS = []
1693
1825
 
1694
 
        db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
 
1826
        new_instance = db.instance_update(self.context, instance['uuid'],
 
1827
                                      {'host': 'foo'})
 
1828
        new_instance = jsonutils.to_primitive(new_instance)
1695
1829
        instance_type = instance_types.get_default_instance_type()
1696
 
        self.compute.prep_resize(context, instance=instance,
 
1830
        self.compute.prep_resize(self.context, instance=new_instance,
1697
1831
                instance_type=instance_type, image={})
1698
 
        db.migration_get_by_instance_and_status(context,
1699
 
                                                instance['uuid'],
 
1832
        db.migration_get_by_instance_and_status(self.context.elevated(),
 
1833
                                                new_instance['uuid'],
1700
1834
                                                'pre-migrating')
1701
1835
 
1702
1836
        self.assertEquals(len(test_notifier.NOTIFICATIONS), 3)
1713
1847
        payload = msg['payload']
1714
1848
        self.assertEquals(payload['tenant_id'], self.project_id)
1715
1849
        self.assertEquals(payload['user_id'], self.user_id)
1716
 
        self.assertEquals(payload['instance_id'], instance['uuid'])
 
1850
        self.assertEquals(payload['instance_id'], new_instance['uuid'])
1717
1851
        self.assertEquals(payload['instance_type'], 'm1.tiny')
1718
1852
        type_id = instance_types.get_instance_type_by_name('m1.tiny')['id']
1719
1853
        self.assertEquals(str(payload['instance_type_id']), str(type_id))
1722
1856
        self.assertTrue('launched_at' in payload)
1723
1857
        image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
1724
1858
        self.assertEquals(payload['image_ref_url'], image_ref_url)
1725
 
        self.compute.terminate_instance(context, instance=instance)
 
1859
        self.compute.terminate_instance(self.context, instance=new_instance)
1726
1860
 
1727
 
    def test_prep_resize_instance_migration_error(self):
1728
 
        """Ensure prep_resize raise a migration error"""
 
1861
    def test_prep_resize_instance_migration_error_on_same_host(self):
 
1862
        """Ensure prep_resize raise a migration error if destination is set on
 
1863
        the same source host and allow_resize_to_same_host is false
 
1864
        """
1729
1865
        self.flags(host="foo", allow_resize_to_same_host=False)
1730
1866
 
1731
1867
        instance = jsonutils.to_primitive(self._create_fake_instance())
1732
 
        context = self.context.elevated()
1733
1868
 
1734
1869
        reservations = self._ensure_quota_reservations_rolledback()
1735
1870
 
1740
1875
        instance_type = instance_types.get_default_instance_type()
1741
1876
 
1742
1877
        self.assertRaises(exception.MigrationError, self.compute.prep_resize,
1743
 
                          context, instance=new_instance,
1744
 
                          instance_type=instance_type, image={},
1745
 
                          reservations=reservations)
1746
 
        self.compute.terminate_instance(context, instance=new_instance)
 
1878
                          self.context, instance=new_instance,
 
1879
                          instance_type=instance_type, image={},
 
1880
                          reservations=reservations)
 
1881
        self.compute.terminate_instance(self.context, instance=new_instance)
 
1882
 
 
1883
    def test_prep_resize_instance_migration_error_on_none_host(self):
 
1884
        """Ensure prep_resize raise a migration error if destination host is
 
1885
        not defined
 
1886
        """
 
1887
        instance = jsonutils.to_primitive(self._create_fake_instance())
 
1888
 
 
1889
        reservations = self._ensure_quota_reservations_rolledback()
 
1890
 
 
1891
        self.compute.run_instance(self.context, instance=instance)
 
1892
        new_instance = db.instance_update(self.context, instance['uuid'],
 
1893
                                          {'host': None})
 
1894
        new_instance = jsonutils.to_primitive(new_instance)
 
1895
        instance_type = instance_types.get_default_instance_type()
 
1896
 
 
1897
        self.assertRaises(exception.MigrationError, self.compute.prep_resize,
 
1898
                          self.context, instance=new_instance,
 
1899
                          instance_type=instance_type, image={},
 
1900
                          reservations=reservations)
 
1901
        self.compute.terminate_instance(self.context, instance=new_instance)
1747
1902
 
1748
1903
    def test_resize_instance_driver_error(self):
1749
1904
        """Ensure instance status set to Error on resize error"""
1756
1911
 
1757
1912
        instance = jsonutils.to_primitive(self._create_fake_instance())
1758
1913
        instance_type = instance_types.get_default_instance_type()
1759
 
        context = self.context.elevated()
1760
1914
 
1761
1915
        reservations = self._ensure_quota_reservations_rolledback()
1762
1916
 
1763
1917
        self.compute.run_instance(self.context, instance=instance)
1764
 
        db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1765
 
        self.compute.prep_resize(context, instance=instance,
 
1918
        new_instance = db.instance_update(self.context, instance['uuid'],
 
1919
                                      {'host': 'foo'})
 
1920
        new_instance = jsonutils.to_primitive(new_instance)
 
1921
        self.compute.prep_resize(self.context, instance=new_instance,
1766
1922
                                 instance_type=instance_type, image={},
1767
1923
                                 reservations=reservations)
1768
 
        migration_ref = db.migration_get_by_instance_and_status(context,
1769
 
                instance['uuid'], 'pre-migrating')
 
1924
        migration_ref = db.migration_get_by_instance_and_status(
 
1925
                self.context.elevated(), new_instance['uuid'], 'pre-migrating')
1770
1926
 
1771
 
        db.instance_update(self.context, instance['uuid'],
 
1927
        db.instance_update(self.context, new_instance['uuid'],
1772
1928
                           {"task_state": task_states.RESIZE_PREP})
1773
1929
        #verify
1774
1930
        self.assertRaises(test.TestingException, self.compute.resize_instance,
1775
 
                          context, instance=instance,
1776
 
                          migration_id=migration_ref['id'], image={},
1777
 
                          reservations=reservations)
1778
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
1931
                          self.context, instance=new_instance,
 
1932
                          migration=migration_ref, image={},
 
1933
                          reservations=reservations,
 
1934
                          instance_type=jsonutils.to_primitive(instance_type))
 
1935
        instance = db.instance_get_by_uuid(self.context, new_instance['uuid'])
1779
1936
        self.assertEqual(instance['vm_state'], vm_states.ERROR)
1780
1937
 
1781
 
        self.compute.terminate_instance(context,
 
1938
        self.compute.terminate_instance(self.context,
1782
1939
            instance=jsonutils.to_primitive(instance))
1783
1940
 
1784
1941
    def test_resize_instance(self):
1785
1942
        """Ensure instance can be migrated/resized"""
1786
1943
        instance = jsonutils.to_primitive(self._create_fake_instance())
1787
1944
        instance_type = instance_types.get_default_instance_type()
1788
 
        context = self.context.elevated()
1789
1945
 
1790
1946
        self.compute.run_instance(self.context, instance=instance)
1791
 
        db.instance_update(self.context, instance['uuid'],
1792
 
                           {'host': 'foo'})
1793
 
        self.compute.prep_resize(context, instance=instance,
 
1947
        new_instance = db.instance_update(self.context, instance['uuid'],
 
1948
                                      {'host': 'foo'})
 
1949
        new_instance = jsonutils.to_primitive(new_instance)
 
1950
        self.compute.prep_resize(self.context, instance=new_instance,
1794
1951
                instance_type=instance_type, image={})
1795
 
        migration_ref = db.migration_get_by_instance_and_status(context,
1796
 
                instance['uuid'], 'pre-migrating')
1797
 
        db.instance_update(self.context, instance['uuid'],
 
1952
        migration_ref = db.migration_get_by_instance_and_status(
 
1953
                self.context.elevated(), new_instance['uuid'], 'pre-migrating')
 
1954
        db.instance_update(self.context, new_instance['uuid'],
1798
1955
                           {"task_state": task_states.RESIZE_PREP})
1799
 
        self.compute.resize_instance(context, instance=instance,
1800
 
                                     migration_id=migration_ref['id'],
1801
 
                                     image={})
1802
 
        self.compute.terminate_instance(context,
1803
 
            instance=jsonutils.to_primitive(instance))
 
1956
        self.compute.resize_instance(self.context, instance=new_instance,
 
1957
                migration=migration_ref, image={},
 
1958
                instance_type=jsonutils.to_primitive(instance_type))
 
1959
        inst = db.instance_get_by_uuid(self.context, new_instance['uuid'])
 
1960
        self.assertEqual(migration_ref['dest_compute'], inst['host'])
 
1961
 
 
1962
        self.compute.terminate_instance(self.context,
 
1963
            instance=jsonutils.to_primitive(inst))
1804
1964
 
1805
1965
    def test_finish_revert_resize(self):
1806
1966
        """Ensure that the flavor is reverted to the original on revert"""
1812
1972
 
1813
1973
        reservations = self._ensure_quota_reservations_committed()
1814
1974
 
1815
 
        context = self.context.elevated()
1816
1975
        instance = jsonutils.to_primitive(self._create_fake_instance())
1817
1976
        instance_uuid = instance['uuid']
1818
1977
 
1819
1978
        self.compute.run_instance(self.context, instance=instance)
1820
1979
 
1821
1980
        # Confirm the instance size before the resize starts
1822
 
        inst_ref = db.instance_get_by_uuid(context, instance['uuid'])
1823
 
        instance_type_ref = db.instance_type_get(context,
 
1981
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
 
1982
        instance_type_ref = db.instance_type_get(self.context,
1824
1983
                inst_ref['instance_type_id'])
1825
1984
        self.assertEqual(instance_type_ref['flavorid'], '1')
1826
1985
 
1827
 
        new_inst_ref = db.instance_update(self.context, instance['uuid'],
 
1986
        new_inst_ref = db.instance_update(self.context, instance_uuid,
1828
1987
                                          {'host': 'foo'})
1829
1988
 
1830
 
        new_instance_type_ref = db.instance_type_get_by_flavor_id(context, 3)
1831
 
        self.compute.prep_resize(context,
 
1989
        new_instance_type_ref = db.instance_type_get_by_flavor_id(
 
1990
                self.context, 3)
 
1991
        new_instance_type_p = jsonutils.to_primitive(new_instance_type_ref)
 
1992
        self.compute.prep_resize(self.context,
1832
1993
                instance=jsonutils.to_primitive(new_inst_ref),
1833
 
                instance_type=jsonutils.to_primitive(new_instance_type_ref),
 
1994
                instance_type=new_instance_type_p,
1834
1995
                image={}, reservations=reservations)
1835
1996
 
1836
 
        migration_ref = db.migration_get_by_instance_and_status(context,
 
1997
        migration_ref = db.migration_get_by_instance_and_status(
 
1998
                self.context.elevated(),
1837
1999
                inst_ref['uuid'], 'pre-migrating')
1838
2000
 
1839
2001
        instance = jsonutils.to_primitive(inst_ref)
1840
 
        db.instance_update(self.context, instance["uuid"],
 
2002
        db.instance_update(self.context, instance_uuid,
1841
2003
                           {"task_state": task_states.RESIZE_PREP})
1842
 
        self.compute.resize_instance(context, instance=instance,
1843
 
                                     migration_id=migration_ref['id'],
1844
 
                                     image={})
1845
 
        self.compute.finish_resize(context,
1846
 
                    migration_id=int(migration_ref['id']), disk_info={},
1847
 
                    image={}, instance=instance)
 
2004
        self.compute.resize_instance(self.context, instance=instance,
 
2005
                                     migration=migration_ref,
 
2006
                                     image={},
 
2007
                                     instance_type=new_instance_type_p)
 
2008
        self.compute.finish_resize(self.context,
 
2009
                    migration=jsonutils.to_primitive(migration_ref),
 
2010
                    disk_info={}, image={}, instance=instance)
1848
2011
 
1849
2012
        # Prove that the instance size is now the new size
1850
 
        inst_ref = db.instance_get_by_uuid(context, instance['uuid'])
1851
 
        instance_type_ref = db.instance_type_get(context,
 
2013
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
 
2014
        instance_type_ref = db.instance_type_get(self.context,
1852
2015
                inst_ref['instance_type_id'])
1853
2016
        self.assertEqual(instance_type_ref['flavorid'], '3')
1854
2017
 
1855
2018
        # Finally, revert and confirm the old flavor has been applied
1856
2019
        rpcinst = jsonutils.to_primitive(inst_ref)
1857
 
        db.instance_update(self.context, instance["uuid"],
 
2020
        db.instance_update(self.context, instance_uuid,
1858
2021
                           {"task_state": task_states.RESIZE_REVERTING})
1859
 
        self.compute.revert_resize(context,
1860
 
                migration_id=migration_ref['id'], instance=rpcinst,
1861
 
                reservations=reservations)
1862
 
        self.compute.finish_revert_resize(context,
1863
 
                migration_id=migration_ref['id'], instance=rpcinst,
1864
 
                reservations=reservations)
1865
 
 
1866
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
2022
        self.compute.revert_resize(self.context,
 
2023
                migration_id=migration_ref['id'], instance=rpcinst,
 
2024
                reservations=reservations)
 
2025
 
 
2026
        def fake_setup_networks_on_host(cls, ctxt, instance, host):
 
2027
            self.assertEqual(host, migration_ref['source_compute'])
 
2028
            inst = db.instance_get_by_uuid(ctxt, instance['uuid'])
 
2029
            self.assertEqual(host, inst['host'])
 
2030
 
 
2031
        self.stubs.Set(network_api.API, 'setup_networks_on_host',
 
2032
                       fake_setup_networks_on_host)
 
2033
 
 
2034
        self.compute.finish_revert_resize(self.context,
 
2035
                migration=jsonutils.to_primitive(migration_ref),
 
2036
                instance=rpcinst, reservations=reservations)
 
2037
 
 
2038
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1867
2039
        self.assertEqual(instance['vm_state'], vm_states.ACTIVE)
1868
2040
        self.assertEqual(instance['task_state'], None)
1869
2041
 
1870
 
        inst_ref = db.instance_get_by_uuid(context, instance['uuid'])
1871
 
        instance_type_ref = db.instance_type_get(context,
 
2042
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
 
2043
        instance_type_ref = db.instance_type_get(self.context,
1872
2044
                inst_ref['instance_type_id'])
1873
2045
        self.assertEqual(instance_type_ref['flavorid'], '1')
1874
2046
        self.assertEqual(inst_ref['host'], migration_ref['source_compute'])
1875
2047
 
1876
 
        self.compute.terminate_instance(context,
 
2048
        self.compute.terminate_instance(self.context,
1877
2049
            instance=jsonutils.to_primitive(inst_ref))
1878
2050
 
1879
2051
    def test_get_by_flavor_id(self):
1907
2079
 
1908
2080
        inst_ref = jsonutils.to_primitive(self._create_fake_instance())
1909
2081
        instance_type = instance_types.get_default_instance_type()
1910
 
        context = self.context.elevated()
1911
2082
 
1912
2083
        self.compute.run_instance(self.context, instance=inst_ref)
1913
 
        db.instance_update(self.context, inst_ref['uuid'], {'host': 'foo'})
1914
 
        self.compute.prep_resize(context, instance=inst_ref,
 
2084
        inst_ref = db.instance_update(self.context, inst_ref['uuid'],
 
2085
                                      {'host': 'foo'})
 
2086
        inst_ref = jsonutils.to_primitive(inst_ref)
 
2087
        self.compute.prep_resize(self.context, instance=inst_ref,
1915
2088
                                 instance_type=instance_type,
1916
2089
                                 image={}, reservations=reservations)
1917
 
        migration_ref = db.migration_get_by_instance_and_status(context,
1918
 
                inst_ref['uuid'], 'pre-migrating')
 
2090
        migration_ref = db.migration_get_by_instance_and_status(
 
2091
                self.context.elevated(), inst_ref['uuid'], 'pre-migrating')
1919
2092
        db.instance_update(self.context, inst_ref['uuid'],
1920
2093
                           {"task_state": task_states.RESIZE_PREP})
1921
2094
        self.assertRaises(test.TestingException, self.compute.resize_instance,
1922
 
                          context, instance=inst_ref,
1923
 
                          migration_id=migration_ref['id'], image={},
1924
 
                          reservations=reservations)
1925
 
        inst_ref = db.instance_get_by_uuid(context, inst_ref['uuid'])
 
2095
                          self.context, instance=inst_ref,
 
2096
                          migration=migration_ref, image={},
 
2097
                          reservations=reservations,
 
2098
                          instance_type=jsonutils.to_primitive(instance_type))
 
2099
        inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
1926
2100
        self.assertEqual(inst_ref['vm_state'], vm_states.ERROR)
1927
 
        self.compute.terminate_instance(context,
 
2101
        self.compute.terminate_instance(self.context,
1928
2102
            instance=jsonutils.to_primitive(inst_ref))
1929
2103
 
1930
2104
    def test_check_can_live_migrate_source_works_correctly(self):
1931
2105
        """Confirm check_can_live_migrate_source works on positive path"""
1932
 
        context = self.context.elevated()
1933
2106
        inst_ref = jsonutils.to_primitive(self._create_fake_instance(
1934
2107
                                          {'host': 'fake_host_2'}))
1935
 
        inst_id = inst_ref["id"]
1936
 
        dest = "fake_host_1"
1937
2108
 
1938
2109
        self.mox.StubOutWithMock(db, 'instance_get')
1939
2110
        self.mox.StubOutWithMock(self.compute.driver,
1940
2111
                                 'check_can_live_migrate_source')
1941
2112
 
1942
2113
        dest_check_data = {"test": "data"}
1943
 
        self.compute.driver.check_can_live_migrate_source(context,
 
2114
        self.compute.driver.check_can_live_migrate_source(self.context,
1944
2115
                                                          inst_ref,
1945
2116
                                                          dest_check_data)
1946
2117
 
1947
2118
        self.mox.ReplayAll()
1948
 
        self.compute.check_can_live_migrate_source(context,
 
2119
        self.compute.check_can_live_migrate_source(self.context,
1949
2120
                dest_check_data=dest_check_data, instance=inst_ref)
1950
2121
 
1951
2122
    def test_check_can_live_migrate_destination_works_correctly(self):
1952
2123
        """Confirm check_can_live_migrate_destination works on positive path"""
1953
 
        context = self.context.elevated()
1954
2124
        inst_ref = jsonutils.to_primitive(self._create_fake_instance(
1955
2125
                                          {'host': 'fake_host_2'}))
1956
 
        inst_id = inst_ref["id"]
1957
 
        dest = "fake_host_1"
 
2126
        compute_info = {"compute": "info"}
1958
2127
 
 
2128
        self.mox.StubOutWithMock(self.compute,
 
2129
                                 '_get_compute_info')
1959
2130
        self.mox.StubOutWithMock(self.compute.driver,
1960
2131
                                 'check_can_live_migrate_destination')
1961
2132
        self.mox.StubOutWithMock(self.compute.compute_rpcapi,
1964
2135
                                 'check_can_live_migrate_destination_cleanup')
1965
2136
 
1966
2137
        dest_check_data = {"test": "data"}
1967
 
        self.compute.driver.check_can_live_migrate_destination(context,
1968
 
                inst_ref, True, False).AndReturn(dest_check_data)
1969
 
        self.compute.compute_rpcapi.check_can_live_migrate_source(context,
 
2138
        self.compute._get_compute_info(
 
2139
            self.context, inst_ref['host']).AndReturn(compute_info)
 
2140
        self.compute._get_compute_info(
 
2141
            self.context, CONF.host).AndReturn(compute_info)
 
2142
        self.compute.driver.check_can_live_migrate_destination(self.context,
 
2143
                inst_ref,
 
2144
                compute_info, compute_info,
 
2145
                True, False).AndReturn(dest_check_data)
 
2146
        self.compute.compute_rpcapi.check_can_live_migrate_source(self.context,
1970
2147
                inst_ref, dest_check_data)
1971
2148
        self.compute.driver.check_can_live_migrate_destination_cleanup(
1972
 
                context, dest_check_data)
 
2149
                self.context, dest_check_data)
1973
2150
 
1974
2151
        self.mox.ReplayAll()
1975
 
        self.compute.check_can_live_migrate_destination(context,
 
2152
        self.compute.check_can_live_migrate_destination(self.context,
1976
2153
                block_migration=True, disk_over_commit=False,
1977
2154
                instance=inst_ref)
1978
2155
 
1979
2156
    def test_check_can_live_migrate_destination_fails_dest_check(self):
1980
2157
        """Confirm check_can_live_migrate_destination works on positive path"""
1981
 
        context = self.context.elevated()
1982
2158
        inst_ref = jsonutils.to_primitive(self._create_fake_instance(
1983
2159
                                          {'host': 'fake_host_2'}))
1984
 
        inst_id = inst_ref["id"]
1985
 
        dest = "fake_host_1"
 
2160
        compute_info = {"compute": "info"}
1986
2161
 
 
2162
        self.mox.StubOutWithMock(self.compute,
 
2163
                                 '_get_compute_info')
1987
2164
        self.mox.StubOutWithMock(self.compute.driver,
1988
2165
                                 'check_can_live_migrate_destination')
1989
2166
 
1990
 
        self.compute.driver.check_can_live_migrate_destination(context,
1991
 
                inst_ref, True, False).AndRaise(exception.Invalid())
 
2167
        self.compute._get_compute_info(
 
2168
            self.context, inst_ref['host']).AndReturn(compute_info)
 
2169
        self.compute._get_compute_info(
 
2170
            self.context, CONF.host).AndReturn(compute_info)
 
2171
        self.compute.driver.check_can_live_migrate_destination(self.context,
 
2172
                inst_ref,
 
2173
                compute_info, compute_info,
 
2174
                True, False).AndRaise(exception.Invalid())
1992
2175
 
1993
2176
        self.mox.ReplayAll()
1994
2177
        self.assertRaises(exception.Invalid,
1995
2178
                          self.compute.check_can_live_migrate_destination,
1996
 
                          context, block_migration=True,
 
2179
                          self.context, block_migration=True,
1997
2180
                          disk_over_commit=False, instance=inst_ref)
1998
2181
 
1999
2182
    def test_check_can_live_migrate_destination_fails_source(self):
2000
2183
        """Confirm check_can_live_migrate_destination works on positive path"""
2001
 
        context = self.context.elevated()
2002
2184
        inst_ref = jsonutils.to_primitive(self._create_fake_instance(
2003
2185
                                          {'host': 'fake_host_2'}))
2004
 
        inst_id = inst_ref["id"]
2005
 
        dest = "fake_host_1"
 
2186
        compute_info = {"compute": "info"}
2006
2187
 
 
2188
        self.mox.StubOutWithMock(self.compute,
 
2189
                                 '_get_compute_info')
2007
2190
        self.mox.StubOutWithMock(self.compute.driver,
2008
2191
                                 'check_can_live_migrate_destination')
2009
2192
        self.mox.StubOutWithMock(self.compute.compute_rpcapi,
2012
2195
                                 'check_can_live_migrate_destination_cleanup')
2013
2196
 
2014
2197
        dest_check_data = {"test": "data"}
2015
 
        self.compute.driver.check_can_live_migrate_destination(context,
2016
 
                inst_ref, True, False).AndReturn(dest_check_data)
2017
 
        self.compute.compute_rpcapi.check_can_live_migrate_source(context,
 
2198
        self.compute._get_compute_info(
 
2199
            self.context, inst_ref['host']).AndReturn(compute_info)
 
2200
        self.compute._get_compute_info(
 
2201
            self.context, CONF.host).AndReturn(compute_info)
 
2202
        self.compute.driver.check_can_live_migrate_destination(self.context,
 
2203
                inst_ref,
 
2204
                compute_info, compute_info,
 
2205
                True, False).AndReturn(dest_check_data)
 
2206
        self.compute.compute_rpcapi.check_can_live_migrate_source(self.context,
2018
2207
                inst_ref, dest_check_data).AndRaise(exception.Invalid())
2019
2208
        self.compute.driver.check_can_live_migrate_destination_cleanup(
2020
 
                context, dest_check_data)
 
2209
                self.context, dest_check_data)
2021
2210
 
2022
2211
        self.mox.ReplayAll()
2023
2212
        self.assertRaises(exception.Invalid,
2024
2213
                          self.compute.check_can_live_migrate_destination,
2025
 
                          context, block_migration=True,
 
2214
                          self.context, block_migration=True,
2026
2215
                          disk_over_commit=False, instance=inst_ref)
2027
2216
 
2028
2217
    def test_pre_live_migration_instance_has_no_fixed_ip(self):
2029
2218
        """Confirm raising exception if instance doesn't have fixed_ip."""
2030
2219
        # creating instance testdata
2031
 
        context = self.context.elevated()
2032
2220
        instance = jsonutils.to_primitive(self._create_fake_instance())
2033
 
        inst_id = instance["id"]
2034
2221
 
2035
2222
        self.mox.ReplayAll()
2036
2223
        self.assertRaises(exception.FixedIpNotFoundForInstance,
2037
 
                          self.compute.pre_live_migration, context,
 
2224
                          self.compute.pre_live_migration, self.context,
2038
2225
                          instance=instance)
2039
2226
 
2040
2227
    def test_pre_live_migration_works_correctly(self):
2048
2235
        # creating instance testdata
2049
2236
        instance = jsonutils.to_primitive(self._create_fake_instance(
2050
2237
                                          {'host': 'dummy'}))
2051
 
        inst_id = instance['id']
2052
2238
        c = context.get_admin_context()
2053
2239
        nw_info = fake_network.fake_get_instance_nw_info(self.stubs)
2054
2240
 
2079
2265
        inst_id = instance['id']
2080
2266
 
2081
2267
        c = context.get_admin_context()
2082
 
        topic = rpc.queue_get_for(c, FLAGS.compute_topic, instance['host'])
 
2268
        topic = rpc.queue_get_for(c, CONF.compute_topic, instance['host'])
2083
2269
 
2084
2270
        # creating volume testdata
2085
 
        volume_id = db.volume_create(c, {'size': 1})['id']
 
2271
        volume_id = 'fake'
2086
2272
        values = {'instance_uuid': inst_uuid, 'device_name': '/dev/vdc',
2087
2273
                  'delete_on_termination': False, 'volume_id': volume_id}
2088
2274
        db.block_device_mapping_create(c, values)
2089
2275
 
 
2276
        def fake_volume_get(self, context, volume_id):
 
2277
            return {'id': volume_id}
 
2278
 
 
2279
        self.stubs.Set(cinder.API, 'get', fake_volume_get)
 
2280
 
2090
2281
        # creating mocks
2091
2282
        self.mox.StubOutWithMock(rpc, 'call')
2092
2283
 
2106
2297
        rpc.call(c, 'network', {'method': 'setup_networks_on_host',
2107
2298
                                'args': {'instance_id': inst_id,
2108
2299
                                         'host': self.compute.host,
2109
 
                                         'teardown': False}})
 
2300
                                         'teardown': False},
 
2301
                                'version': '1.0'}, None)
2110
2302
        rpcinst = jsonutils.to_primitive(
2111
2303
                db.instance_get_by_uuid(self.context, instance['uuid']))
2112
2304
        rpc.call(c, topic,
2131
2323
        for bdms in db.block_device_mapping_get_all_by_instance(
2132
2324
            c, inst_uuid):
2133
2325
            db.block_device_mapping_destroy(c, bdms['id'])
2134
 
        db.volume_destroy(c, volume_id)
2135
2326
        db.instance_destroy(c, inst_uuid)
2136
2327
 
2137
2328
    def test_live_migration_works_correctly(self):
2146
2337
 
2147
2338
        # create
2148
2339
        self.mox.StubOutWithMock(rpc, 'call')
2149
 
        topic = rpc.queue_get_for(c, FLAGS.compute_topic, instance['host'])
 
2340
        topic = rpc.queue_get_for(c, CONF.compute_topic, instance['host'])
2150
2341
        rpc.call(c, topic,
2151
2342
                {"method": "pre_live_migration",
2152
2343
                 "args": {'instance': instance,
2167
2358
    def test_post_live_migration_working_correctly(self):
2168
2359
        """Confirm post_live_migration() works as expected correctly."""
2169
2360
        dest = 'desthost'
2170
 
        flo_addr = '1.2.1.2'
 
2361
        srchost = self.compute.host
2171
2362
 
2172
2363
        # creating testdata
2173
2364
        c = context.get_admin_context()
2174
2365
        inst_ref = jsonutils.to_primitive(self._create_fake_instance({
 
2366
                                'host': srchost,
2175
2367
                                'state_description': 'migrating',
2176
2368
                                'state': power_state.PAUSED}))
2177
2369
        inst_uuid = inst_ref['uuid']
2180
2372
        db.instance_update(c, inst_uuid,
2181
2373
                           {'task_state': task_states.MIGRATING,
2182
2374
                            'power_state': power_state.PAUSED})
2183
 
        v_ref = db.volume_create(c, {'size': 1, 'instance_id': inst_id})
2184
 
        fix_addr = db.fixed_ip_create(c, {'address': '1.1.1.1',
2185
 
                                          'instance_uuid': inst_ref['uuid']})
2186
 
        fix_ref = db.fixed_ip_get_by_address(c, fix_addr)
2187
 
        db.floating_ip_create(c, {'address': flo_addr,
2188
 
                                  'fixed_ip_id': fix_ref['id']})
2189
2375
 
2190
2376
        # creating mocks
2191
2377
        self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
2192
2378
        self.compute.driver.unfilter_instance(inst_ref, [])
 
2379
        self.mox.StubOutWithMock(self.compute.network_api,
 
2380
                                 'migrate_instance_start')
 
2381
        migration = {'source_compute': srchost,
 
2382
                     'dest_compute': dest, }
 
2383
        self.compute.network_api.migrate_instance_start(c, inst_ref, migration)
2193
2384
        self.mox.StubOutWithMock(rpc, 'call')
2194
 
        rpc.call(c, rpc.queue_get_for(c, FLAGS.compute_topic, dest),
 
2385
        rpc.call(c, rpc.queue_get_for(c, CONF.compute_topic, dest),
2195
2386
            {"method": "post_live_migration_at_destination",
2196
2387
             "args": {'instance': inst_ref, 'block_migration': False},
2197
2388
             "version": compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
2201
2392
        rpc.call(c, 'network', {'method': 'setup_networks_on_host',
2202
2393
                                'args': {'instance_id': inst_id,
2203
2394
                                         'host': self.compute.host,
2204
 
                                         'teardown': True}})
 
2395
                                         'teardown': True},
 
2396
                                'version': '1.0'}, None)
2205
2397
 
2206
2398
        # start test
2207
2399
        self.mox.ReplayAll()
2208
2400
        self.compute._post_live_migration(c, inst_ref, dest)
2209
2401
 
2210
 
        # make sure floating ips are rewritten to destinatioin hostname.
2211
 
        flo_refs = db.floating_ip_get_all_by_host(c, dest)
2212
 
        self.assertTrue(flo_refs)
2213
 
        self.assertEqual(flo_refs[0]['address'], flo_addr)
2214
 
 
2215
 
        # cleanup
2216
 
        db.instance_destroy(c, inst_uuid)
2217
 
        db.volume_destroy(c, v_ref['id'])
2218
 
        db.floating_ip_destroy(c, flo_addr)
 
2402
    def test_post_live_migration_at_destination(self):
 
2403
        params = {'task_state': task_states.MIGRATING,
 
2404
                  'power_state': power_state.PAUSED, }
 
2405
        instance = jsonutils.to_primitive(self._create_fake_instance(params))
 
2406
 
 
2407
        admin_ctxt = context.get_admin_context()
 
2408
        instance = db.instance_get_by_uuid(admin_ctxt, instance['uuid'])
 
2409
        self.mox.StubOutWithMock(self.compute.network_api,
 
2410
                                 'setup_networks_on_host')
 
2411
        self.compute.network_api.setup_networks_on_host(admin_ctxt, instance,
 
2412
                                                        self.compute.host)
 
2413
        self.mox.StubOutWithMock(self.compute.network_api,
 
2414
                                 'migrate_instance_finish')
 
2415
        migration = {'source_compute': instance['host'],
 
2416
                     'dest_compute': self.compute.host, }
 
2417
        self.compute.network_api.migrate_instance_finish(admin_ctxt,
 
2418
                                                         instance, migration)
 
2419
        self.mox.StubOutWithMock(self.compute.driver,
 
2420
                                 'post_live_migration_at_destination')
 
2421
        fake_net_info = []
 
2422
        self.compute.driver.post_live_migration_at_destination(admin_ctxt,
 
2423
                                                               instance,
 
2424
                                                               fake_net_info,
 
2425
                                                               False)
 
2426
        self.compute.network_api.setup_networks_on_host(admin_ctxt, instance,
 
2427
                                                        self.compute.host)
 
2428
 
 
2429
        self.mox.ReplayAll()
 
2430
        self.compute.post_live_migration_at_destination(admin_ctxt, instance)
 
2431
        instance = db.instance_get_by_uuid(admin_ctxt, instance['uuid'])
 
2432
        self.assertEqual(instance['host'], self.compute.host)
 
2433
        self.assertEqual(instance['vm_state'], vm_states.ACTIVE)
 
2434
        self.assertEqual(instance['task_state'], None)
2219
2435
 
2220
2436
    def test_run_kill_vm(self):
2221
2437
        """Detect when a vm is terminated behind the scenes"""
2226
2442
 
2227
2443
        self.compute.run_instance(self.context, instance=instance)
2228
2444
 
2229
 
        instances = db.instance_get_all(context.get_admin_context())
 
2445
        instances = db.instance_get_all(self.context)
2230
2446
        LOG.info(_("Running instances: %s"), instances)
2231
2447
        self.assertEqual(len(instances), 1)
2232
2448
 
2237
2453
        ctxt = context.get_admin_context()
2238
2454
        self.compute._sync_power_states(ctxt)
2239
2455
 
2240
 
        instances = db.instance_get_all(ctxt)
 
2456
        instances = db.instance_get_all(self.context)
2241
2457
        LOG.info(_("After force-killing instances: %s"), instances)
2242
2458
        self.assertEqual(len(instances), 1)
2243
 
        self.assertEqual(task_states.STOPPING, instances[0]['task_state'])
 
2459
        self.assertEqual(task_states.POWERING_OFF, instances[0]['task_state'])
2244
2460
 
2245
2461
    def test_add_instance_fault(self):
2246
2462
        exc_info = None
2247
 
        instance_uuid = str(utils.gen_uuid())
 
2463
        instance_uuid = str(uuid.uuid4())
2248
2464
 
2249
2465
        def fake_db_fault_create(ctxt, values):
2250
2466
            self.assertTrue(values['details'].startswith('test'))
2260
2476
 
2261
2477
        try:
2262
2478
            raise NotImplementedError('test')
2263
 
        except Exception:
 
2479
        except NotImplementedError:
2264
2480
            exc_info = sys.exc_info()
2265
2481
 
2266
2482
        self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
2270
2486
                                                  NotImplementedError('test'),
2271
2487
                                                  exc_info)
2272
2488
 
 
2489
    def test_add_instance_fault_with_remote_error(self):
 
2490
        exc_info = None
 
2491
        instance_uuid = str(uuid.uuid4())
 
2492
 
 
2493
        def fake_db_fault_create(ctxt, values):
 
2494
            self.assertTrue(values['details'].startswith('Remote error'))
 
2495
            self.assertTrue('raise rpc_common.RemoteError'
 
2496
                in values['details'])
 
2497
            del values['details']
 
2498
 
 
2499
            expected = {
 
2500
                'code': 500,
 
2501
                'instance_uuid': instance_uuid,
 
2502
                'message': 'My Test Message'
 
2503
            }
 
2504
            self.assertEquals(expected, values)
 
2505
 
 
2506
        try:
 
2507
            raise rpc_common.RemoteError('test', 'My Test Message')
 
2508
        except rpc_common.RemoteError as exc:
 
2509
            exc_info = sys.exc_info()
 
2510
 
 
2511
        self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
 
2512
 
 
2513
        ctxt = context.get_admin_context()
 
2514
        compute_utils.add_instance_fault_from_exc(ctxt, instance_uuid,
 
2515
            exc,
 
2516
            exc_info)
 
2517
 
2273
2518
    def test_add_instance_fault_user_error(self):
2274
2519
        exc_info = None
2275
 
        instance_uuid = str(utils.gen_uuid())
 
2520
        instance_uuid = str(uuid.uuid4())
2276
2521
 
2277
2522
        def fake_db_fault_create(ctxt, values):
2278
2523
 
2288
2533
 
2289
2534
        try:
2290
2535
            raise user_exc
2291
 
        except Exception:
 
2536
        except exception.Invalid:
2292
2537
            exc_info = sys.exc_info()
2293
2538
 
2294
2539
        self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
2298
2543
            user_exc, exc_info)
2299
2544
 
2300
2545
    def test_add_instance_fault_no_exc_info(self):
2301
 
        instance_uuid = str(utils.gen_uuid())
 
2546
        instance_uuid = str(uuid.uuid4())
2302
2547
 
2303
2548
        def fake_db_fault_create(ctxt, values):
2304
2549
            expected = {
2326
2571
 
2327
2572
        self.mox.StubOutWithMock(self.compute.driver, 'list_instances')
2328
2573
        self.compute.driver.list_instances().AndReturn([instance['name']])
2329
 
        FLAGS.running_deleted_instance_timeout = 3600
2330
 
        FLAGS.running_deleted_instance_action = 'reap'
 
2574
        self.flags(running_deleted_instance_timeout=3600,
 
2575
                   running_deleted_instance_action='reap')
2331
2576
 
2332
2577
        self.mox.StubOutWithMock(self.compute.db, "instance_get_all_by_host")
2333
2578
        self.compute.db.instance_get_all_by_host(admin_context,
2334
2579
                                                 self.compute.host
2335
2580
                                                ).AndReturn([instance])
2336
2581
 
 
2582
        bdms = []
 
2583
 
2337
2584
        self.mox.StubOutWithMock(self.compute, "_shutdown_instance")
2338
2585
        self.compute._shutdown_instance(admin_context,
2339
 
                                        instance).AndReturn(None)
 
2586
                                        instance,
 
2587
                                        bdms).AndReturn(None)
2340
2588
 
2341
2589
        self.mox.StubOutWithMock(self.compute, "_cleanup_volumes")
2342
2590
        self.compute._cleanup_volumes(admin_context,
2343
 
                                      instance['uuid']).AndReturn(None)
 
2591
                                      instance['uuid'],
 
2592
                                      bdms).AndReturn(None)
2344
2593
 
2345
2594
        self.mox.ReplayAll()
2346
2595
        self.compute._cleanup_running_deleted_instances(admin_context)
2350
2599
        self.compute.driver.list_instances().AndReturn(['herp', 'derp'])
2351
2600
        self.compute.host = 'host'
2352
2601
 
2353
 
        instance1 = mox.MockAnything()
2354
 
        instance1.name = 'herp'
2355
 
        instance1.deleted = True
2356
 
        instance1.deleted_at = "sometimeago"
 
2602
        instance1 = {}
 
2603
        instance1['name'] = 'herp'
 
2604
        instance1['deleted'] = True
 
2605
        instance1['deleted_at'] = "sometimeago"
2357
2606
 
2358
 
        instance2 = mox.MockAnything()
2359
 
        instance2.name = 'derp'
2360
 
        instance2.deleted = False
2361
 
        instance2.deleted_at = None
 
2607
        instance2 = {}
 
2608
        instance2['name'] = 'derp'
 
2609
        instance2['deleted'] = False
 
2610
        instance2['deleted_at'] = None
2362
2611
 
2363
2612
        self.mox.StubOutWithMock(timeutils, 'is_older_than')
2364
2613
        timeutils.is_older_than('sometimeago',
2365
 
                    FLAGS.running_deleted_instance_timeout).AndReturn(True)
 
2614
                    CONF.running_deleted_instance_timeout).AndReturn(True)
2366
2615
 
2367
2616
        self.mox.StubOutWithMock(self.compute.db, "instance_get_all_by_host")
2368
2617
        self.compute.db.instance_get_all_by_host('context',
2382
2631
        instances = []
2383
2632
        for x in xrange(5):
2384
2633
            uuid = 'fake-uuid-%s' % x
2385
 
            instance_map[uuid] = {'uuid': uuid, 'host': FLAGS.host}
 
2634
            instance_map[uuid] = {'uuid': uuid, 'host': CONF.host}
2386
2635
            instances.append(instance_map[uuid])
2387
2636
 
2388
2637
        call_info = {'get_all_by_host': 0, 'get_by_uuid': 0,
2486
2735
 
2487
2736
        def fake_migration_get_unconfirmed_by_dest_compute(context,
2488
2737
                resize_confirm_window, dest_compute):
2489
 
            self.assertEqual(dest_compute, FLAGS.host)
 
2738
            self.assertEqual(dest_compute, CONF.host)
2490
2739
            return migrations
2491
2740
 
2492
2741
        def fake_migration_update(context, migration_id, values):
2548
2797
        instances = []
2549
2798
        for x in xrange(5):
2550
2799
            uuid = 'fake-uuid-%s' % x
2551
 
            instance_map[uuid] = {'uuid': uuid, 'host': FLAGS.host,
 
2800
            instance_map[uuid] = {'uuid': uuid, 'host': CONF.host,
2552
2801
                    'vm_state': vm_states.BUILDING,
2553
2802
                    'created_at': created_at}
2554
2803
            instances.append(instance_map[uuid])
2580
2829
        instances = []
2581
2830
        for x in xrange(5):
2582
2831
            uuid = 'fake-uuid-%s' % x
2583
 
            instance_map[uuid] = {'uuid': uuid, 'host': FLAGS.host,
 
2832
            instance_map[uuid] = {'uuid': uuid, 'host': CONF.host,
2584
2833
                    'vm_state': vm_states.BUILDING,
2585
2834
                    'created_at': created_at}
2586
2835
            instances.append(instance_map[uuid])
2613
2862
        #expired instances
2614
2863
        for x in xrange(4):
2615
2864
            uuid = 'fake-uuid-%s' % x
2616
 
            instance_map[uuid] = {'uuid': uuid, 'host': FLAGS.host,
 
2865
            instance_map[uuid] = {'uuid': uuid, 'host': CONF.host,
2617
2866
                    'vm_state': vm_states.BUILDING,
2618
2867
                    'created_at': created_at}
2619
2868
            instances.append(instance_map[uuid])
2622
2871
        uuid = 'fake-uuid-5'
2623
2872
        instance_map[uuid] = {
2624
2873
            'uuid': uuid,
2625
 
            'host': FLAGS.host,
 
2874
            'host': CONF.host,
2626
2875
            'vm_state': vm_states.BUILDING,
2627
2876
            'created_at': timeutils.utcnow(),
2628
2877
        }
2642
2891
                                                          spectacular=True)
2643
2892
 
2644
2893
        super(ComputeAPITestCase, self).setUp()
2645
 
        self.stubs.Set(nova.network.API, 'get_instance_nw_info',
 
2894
        self.stubs.Set(network_api.API, 'get_instance_nw_info',
2646
2895
                       fake_get_nw_info)
2647
 
        self.security_group_api = compute.api.SecurityGroupAPI()
 
2896
        self.security_group_api = compute_api.SecurityGroupAPI()
2648
2897
        self.compute_api = compute.API(
2649
2898
                                   security_group_api=self.security_group_api)
2650
2899
        self.fake_image = {
2651
2900
            'id': 1,
2652
2901
            'name': 'fake_name',
 
2902
            'status': 'active',
2653
2903
            'properties': {'kernel_id': 'fake_kernel_id',
2654
2904
                           'ramdisk_id': 'fake_ramdisk_id'},
2655
2905
        }
2790
3040
    def test_create_instance_with_invalid_security_group_raises(self):
2791
3041
        instance_type = instance_types.get_default_instance_type()
2792
3042
 
2793
 
        pre_build_len = len(db.instance_get_all(context.get_admin_context()))
 
3043
        pre_build_len = len(db.instance_get_all(self.context))
2794
3044
        self.assertRaises(exception.SecurityGroupNotFoundForProject,
2795
3045
                          self.compute_api.create,
2796
3046
                          self.context,
2798
3048
                          image_href=None,
2799
3049
                          security_group=['this_is_a_fake_sec_group'])
2800
3050
        self.assertEqual(pre_build_len,
2801
 
                         len(db.instance_get_all(context.get_admin_context())))
 
3051
                         len(db.instance_get_all(self.context)))
2802
3052
 
2803
3053
    def test_create_with_large_user_data(self):
2804
3054
        """Test an instance type with too much user data."""
2849
3099
        db.instance_destroy(self.context, refs[0]['uuid'])
2850
3100
 
2851
3101
    def test_default_hostname_generator(self):
2852
 
        fake_uuids = [str(utils.gen_uuid()) for x in xrange(4)]
 
3102
        fake_uuids = [str(uuid.uuid4()) for x in xrange(4)]
2853
3103
 
2854
3104
        orig_populate = self.compute_api._populate_instance_for_create
2855
3105
 
2915
3165
        self.compute.run_instance(self.context, instance=instance)
2916
3166
 
2917
3167
        db.instance_update(self.context, instance['uuid'],
2918
 
                           {"task_state": task_states.STOPPING})
 
3168
                           {"task_state": task_states.POWERING_OFF})
2919
3169
        self.compute.stop_instance(self.context, instance=instance)
2920
3170
 
2921
3171
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2924
3174
        self.compute_api.start(self.context, instance)
2925
3175
 
2926
3176
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2927
 
        self.assertEqual(instance['task_state'], task_states.STARTING)
 
3177
        self.assertEqual(instance['task_state'], task_states.POWERING_ON)
2928
3178
 
2929
3179
        db.instance_destroy(self.context, instance['uuid'])
2930
3180
 
2939
3189
        self.compute_api.stop(self.context, instance)
2940
3190
 
2941
3191
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2942
 
        self.assertEqual(instance['task_state'], task_states.STOPPING)
 
3192
        self.assertEqual(instance['task_state'], task_states.POWERING_OFF)
2943
3193
 
2944
3194
        db.instance_destroy(self.context, instance['uuid'])
2945
3195
 
2971
3221
                    None)
2972
3222
 
2973
3223
        start_check_state(instance['uuid'], power_state.NOSTATE,
2974
 
                          vm_states.STOPPED, task_states.STARTING)
 
3224
                          vm_states.STOPPED, task_states.POWERING_ON)
2975
3225
 
2976
3226
        db.instance_destroy(self.context, instance['uuid'])
2977
3227
 
2978
3228
    def test_delete(self):
2979
3229
        instance, instance_uuid = self._run_instance(params={
2980
 
                'host': FLAGS.host})
2981
 
 
2982
 
        self.compute_api.delete(self.context, instance)
2983
 
 
2984
 
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
2985
 
        self.assertEqual(instance['task_state'], task_states.DELETING)
2986
 
 
2987
 
        db.instance_destroy(self.context, instance['uuid'])
 
3230
                'host': CONF.host})
 
3231
 
 
3232
        self.compute_api.delete(self.context, instance)
 
3233
 
 
3234
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
3235
        self.assertEqual(instance['task_state'], task_states.DELETING)
 
3236
 
 
3237
        db.instance_destroy(self.context, instance['uuid'])
 
3238
 
 
3239
    def test_delete_in_resized(self):
 
3240
        instance, instance_uuid = self._run_instance(params={
 
3241
                'host': CONF.host})
 
3242
 
 
3243
        instance['vm_state'] = vm_states.RESIZED
 
3244
 
 
3245
        self.compute_api.delete(self.context, instance)
 
3246
 
 
3247
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
3248
        self.assertEqual(instance['task_state'], task_states.DELETING)
 
3249
 
 
3250
        db.instance_destroy(self.context, instance['uuid'])
 
3251
 
 
3252
    def test_delete_with_down_host(self):
 
3253
        self.network_api_called = False
 
3254
 
 
3255
        def dummy(*args, **kwargs):
 
3256
            self.network_api_called = True
 
3257
 
 
3258
        self.stubs.Set(self.compute_api.network_api, 'deallocate_for_instance',
 
3259
                       dummy)
 
3260
 
 
3261
        #use old time to disable machine
 
3262
        old_time = datetime.datetime(2012, 4, 1)
 
3263
 
 
3264
        instance, instance_uuid = self._run_instance(params={
 
3265
                'host': CONF.host})
 
3266
        timeutils.set_time_override(old_time)
 
3267
        self.compute_api.delete(self.context, instance)
 
3268
        timeutils.clear_time_override()
 
3269
 
 
3270
        self.assertEqual(instance['task_state'], None)
 
3271
        self.assertTrue(self.network_api_called)
 
3272
 
 
3273
        # fetch the instance state from db and verify deletion.
 
3274
        deleted_context = context.RequestContext('fake', 'fake',
 
3275
                                                 read_deleted='yes')
 
3276
        instance = db.instance_get_by_uuid(deleted_context, instance_uuid)
 
3277
        self.assertEqual(instance['vm_state'], vm_states.DELETED)
 
3278
        self.assertEqual(instance['task_state'], None)
 
3279
        self.assertTrue(instance['deleted'])
2988
3280
 
2989
3281
    def test_repeated_delete_quota(self):
2990
3282
        in_use = {'instances': 1}
3001
3293
        self.stubs.Set(QUOTAS, 'commit', fake_commit)
3002
3294
 
3003
3295
        instance, instance_uuid = self._run_instance(params={
3004
 
                'host': FLAGS.host})
 
3296
                'host': CONF.host})
3005
3297
 
3006
3298
        self.compute_api.delete(self.context, instance)
3007
3299
        self.compute_api.delete(self.context, instance)
3021
3313
 
3022
3314
    def test_delete_handles_host_setting_race_condition(self):
3023
3315
        instance, instance_uuid = self._run_instance(params={
3024
 
                'host': FLAGS.host})
 
3316
                'host': CONF.host})
3025
3317
        instance['host'] = None  # make it think host was never set
3026
3318
        self.compute_api.delete(self.context, instance)
3027
3319
 
3032
3324
 
3033
3325
    def test_delete_fail(self):
3034
3326
        instance, instance_uuid = self._run_instance(params={
3035
 
                'host': FLAGS.host})
 
3327
                'host': CONF.host})
3036
3328
 
3037
3329
        instance = db.instance_update(self.context, instance_uuid,
3038
3330
                                      {'disable_terminate': True})
3044
3336
        db.instance_destroy(self.context, instance['uuid'])
3045
3337
 
3046
3338
    def test_delete_soft(self):
3047
 
        instance, instance_uuid = self._run_instance()
 
3339
        instance, instance_uuid = self._run_instance(params={
 
3340
                'host': CONF.host})
 
3341
 
 
3342
        self.mox.StubOutWithMock(nova.quota.QUOTAS, 'commit')
 
3343
        nova.quota.QUOTAS.commit(mox.IgnoreArg(), mox.IgnoreArg())
 
3344
        self.mox.ReplayAll()
3048
3345
 
3049
3346
        self.compute_api.soft_delete(self.context, instance)
3050
3347
 
3051
3348
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
3052
 
        self.assertEqual(instance['task_state'], task_states.POWERING_OFF)
 
3349
        self.assertEqual(instance['task_state'], task_states.SOFT_DELETING)
3053
3350
 
3054
3351
        db.instance_destroy(self.context, instance['uuid'])
3055
3352
 
3056
3353
    def test_delete_soft_fail(self):
3057
 
        instance, instance_uuid = self._run_instance()
3058
 
 
 
3354
        instance, instance_uuid = self._run_instance(params={
 
3355
                'host': CONF.host})
3059
3356
        instance = db.instance_update(self.context, instance_uuid,
3060
3357
                                      {'disable_terminate': True})
 
3358
 
3061
3359
        self.compute_api.soft_delete(self.context, instance)
3062
3360
 
3063
3361
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
3065
3363
 
3066
3364
        db.instance_destroy(self.context, instance['uuid'])
3067
3365
 
 
3366
    def test_delete_soft_rollback(self):
 
3367
        instance, instance_uuid = self._run_instance(params={
 
3368
                'host': CONF.host})
 
3369
 
 
3370
        self.mox.StubOutWithMock(nova.quota.QUOTAS, 'rollback')
 
3371
        nova.quota.QUOTAS.rollback(mox.IgnoreArg(), mox.IgnoreArg())
 
3372
        self.mox.ReplayAll()
 
3373
 
 
3374
        def fail(*args, **kwargs):
 
3375
            raise test.TestingException()
 
3376
        self.stubs.Set(self.compute_api.compute_rpcapi, 'soft_delete_instance',
 
3377
                       fail)
 
3378
 
 
3379
        self.assertRaises(test.TestingException, self.compute_api.soft_delete,
 
3380
                          self.context, instance)
 
3381
 
 
3382
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
3383
        self.assertEqual(instance['task_state'], task_states.SOFT_DELETING)
 
3384
 
 
3385
        db.instance_destroy(self.context, instance['uuid'])
 
3386
 
3068
3387
    def test_force_delete(self):
3069
3388
        """Ensure instance can be deleted after a soft delete"""
3070
3389
        instance = jsonutils.to_primitive(self._create_fake_instance(params={
3071
 
                'host': FLAGS.host}))
 
3390
                'host': CONF.host}))
3072
3391
        instance_uuid = instance['uuid']
3073
3392
        self.compute.run_instance(self.context, instance=instance)
3074
3393
 
3076
3395
        self.compute_api.soft_delete(self.context, instance)
3077
3396
 
3078
3397
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
3079
 
        self.assertEqual(instance['task_state'], task_states.POWERING_OFF)
 
3398
        self.assertEqual(instance['task_state'], task_states.SOFT_DELETING)
3080
3399
 
3081
3400
        # set the state that the instance gets when soft_delete finishes
3082
3401
        instance = db.instance_update(self.context, instance['uuid'],
3159
3478
 
3160
3479
    def test_restore(self):
3161
3480
        """Ensure instance can be restored from a soft delete"""
3162
 
        instance = jsonutils.to_primitive(self._create_fake_instance())
3163
 
        instance_uuid = instance['uuid']
3164
 
        self.compute.run_instance(self.context, instance=instance)
 
3481
        instance, instance_uuid = self._run_instance(params={
 
3482
                'host': CONF.host})
3165
3483
 
3166
3484
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
3167
3485
        self.compute_api.soft_delete(self.context, instance)
3168
3486
 
3169
3487
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
3170
 
        self.assertEqual(instance['task_state'], task_states.POWERING_OFF)
 
3488
        self.assertEqual(instance['task_state'], task_states.SOFT_DELETING)
3171
3489
 
3172
3490
        # set the state that the instance gets when soft_delete finishes
3173
3491
        instance = db.instance_update(self.context, instance['uuid'],
3174
3492
                                      {'vm_state': vm_states.SOFT_DELETED,
3175
3493
                                       'task_state': None})
3176
3494
 
 
3495
        self.mox.StubOutWithMock(nova.quota.QUOTAS, 'commit')
 
3496
        nova.quota.QUOTAS.commit(mox.IgnoreArg(), mox.IgnoreArg())
 
3497
        self.mox.ReplayAll()
 
3498
 
3177
3499
        self.compute_api.restore(self.context, instance)
3178
3500
 
3179
3501
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
3180
 
        self.assertEqual(instance['task_state'], task_states.POWERING_ON)
 
3502
        self.assertEqual(instance['task_state'], task_states.RESTORING)
3181
3503
 
3182
3504
        db.instance_destroy(self.context, instance['uuid'])
3183
3505
 
3226
3548
                'preserved': 'preserve this!'})
3227
3549
        db.instance_destroy(self.context, instance['uuid'])
3228
3550
 
 
3551
    def _stub_out_reboot(self, device_name):
 
3552
        def fake_reboot_instance(rpcapi, context, instance,
 
3553
                                 block_device_info,
 
3554
                                 network_info,
 
3555
                                 reboot_type):
 
3556
            self.assertEqual(
 
3557
                block_device_info['block_device_mapping'][0]['mount_device'],
 
3558
                device_name)
 
3559
            self.assertEqual(network_info[0]['network']['bridge'], 'fake_br1')
 
3560
        self.stubs.Set(nova.compute.rpcapi.ComputeAPI, 'reboot_instance',
 
3561
                       fake_reboot_instance)
 
3562
 
 
3563
        self.stubs.Set(nova.virt.fake.FakeDriver, 'legacy_nwinfo',
 
3564
                       lambda x: False)
 
3565
 
3229
3566
    def test_reboot_soft(self):
3230
3567
        """Ensure instance can be soft rebooted"""
3231
3568
        instance = jsonutils.to_primitive(self._create_fake_instance())
3232
3569
        self.compute.run_instance(self.context, instance=instance)
3233
3570
 
 
3571
        volume_id = 'fake'
 
3572
        device_name = '/dev/vdc'
 
3573
        volume = {'instance_uuid': instance['uuid'],
 
3574
                  'device_name': device_name,
 
3575
                  'delete_on_termination': False,
 
3576
                  'connection_info': '{"foo": "bar"}',
 
3577
                  'volume_id': volume_id}
 
3578
        db.block_device_mapping_create(self.context, volume)
 
3579
 
3234
3580
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
3235
3581
        self.assertEqual(inst_ref['task_state'], None)
3236
3582
 
3237
3583
        reboot_type = "SOFT"
 
3584
        self._stub_out_reboot(device_name)
3238
3585
        self.compute_api.reboot(self.context, inst_ref, reboot_type)
3239
3586
 
3240
3587
        inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
3247
3594
        instance = jsonutils.to_primitive(self._create_fake_instance())
3248
3595
        self.compute.run_instance(self.context, instance=instance)
3249
3596
 
 
3597
        volume_id = 'fake'
 
3598
        device_name = '/dev/vdc'
 
3599
        volume = {'instance_uuid': instance['uuid'],
 
3600
                  'device_name': device_name,
 
3601
                  'delete_on_termination': False,
 
3602
                  'connection_info': '{"foo": "bar"}',
 
3603
                  'volume_id': volume_id}
 
3604
        db.block_device_mapping_create(self.context, volume)
 
3605
 
3250
3606
        inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
3251
3607
        self.assertEqual(inst_ref['task_state'], None)
3252
3608
 
3253
3609
        reboot_type = "HARD"
 
3610
        self._stub_out_reboot(device_name)
3254
3611
        self.compute_api.reboot(self.context, inst_ref, reboot_type)
3255
3612
 
3256
3613
        inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid'])
3361
3718
        """Ensure a snapshot of an instance can be created"""
3362
3719
        instance = self._create_fake_instance()
3363
3720
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
3364
 
                                        {'extra_param': 'value1'})
 
3721
                                          {'extra_param': 'value1'})
3365
3722
 
3366
3723
        self.assertEqual(image['name'], 'snap1')
3367
3724
        properties = image['properties']
3390
3747
        instance['instance_type'].update(inst_params)
3391
3748
 
3392
3749
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
3393
 
                                        {'extra_param': 'value1'})
 
3750
                                          {'extra_param': 'value1'})
3394
3751
 
3395
3752
        self.assertEqual(image['name'], 'snap1')
3396
3753
        self.assertEqual(image['min_ram'], 256)
3422
3779
        instance = self._create_fake_instance()
3423
3780
 
3424
3781
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
3425
 
                                        {'extra_param': 'value1'})
 
3782
                                          {'extra_param': 'value1'})
3426
3783
 
3427
3784
        self.assertEqual(image['name'], 'snap1')
3428
3785
        self.assertEqual(image['min_ram'], 512)
3451
3808
        instance = self._create_fake_instance()
3452
3809
 
3453
3810
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
3454
 
                                        {'extra_param': 'value1'})
 
3811
                                          {'extra_param': 'value1'})
3455
3812
 
3456
3813
        self.assertEqual(image['name'], 'snap1')
3457
3814
        self.assertFalse('min_ram' in image)
3479
3836
        instance = self._create_fake_instance()
3480
3837
 
3481
3838
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
3482
 
                                        {'extra_param': 'value1'})
 
3839
                                          {'extra_param': 'value1'})
3483
3840
 
3484
3841
        self.assertEqual(image['name'], 'snap1')
3485
3842
 
3495
3852
 
3496
3853
        db.instance_destroy(self.context, instance['uuid'])
3497
3854
 
 
3855
    def test_snapshot_image_metadata_inheritance(self):
 
3856
        # Ensure image snapshots inherit metadata from the base image
 
3857
        self.flags(non_inheritable_image_properties=['spam'])
 
3858
 
 
3859
        def fake_instance_system_metadata_get(context, uuid):
 
3860
            return dict(image_a=1, image_b=2, image_c='c', d='d', spam='spam')
 
3861
 
 
3862
        self.stubs.Set(db, 'instance_system_metadata_get',
 
3863
                       fake_instance_system_metadata_get)
 
3864
 
 
3865
        instance = self._create_fake_instance()
 
3866
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
 
3867
                                          {'extra_param': 'value1'})
 
3868
 
 
3869
        properties = image['properties']
 
3870
        self.assertEqual(properties['a'], 1)
 
3871
        self.assertEqual(properties['b'], 2)
 
3872
        self.assertEqual(properties['c'], 'c')
 
3873
        self.assertEqual(properties['d'], 'd')
 
3874
        self.assertFalse('spam' in properties)
 
3875
 
3498
3876
    def test_backup(self):
3499
3877
        """Can't backup an instance which is already being backed up."""
3500
3878
        instance = self._create_fake_instance()
3545
3923
 
3546
3924
    def test_resize_confirm_through_api(self):
3547
3925
        instance = jsonutils.to_primitive(self._create_fake_instance())
3548
 
        context = self.context.elevated()
3549
3926
        self.compute.run_instance(self.context, instance=instance)
3550
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
3551
 
        self.compute_api.resize(context, instance, '4')
 
3927
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
 
3928
        self.compute_api.resize(self.context, instance, '4')
3552
3929
 
3553
3930
        # create a fake migration record (manager does this)
3554
 
        db.migration_create(context,
 
3931
        db.migration_create(self.context.elevated(),
3555
3932
                {'instance_uuid': instance['uuid'],
3556
3933
                 'status': 'finished'})
3557
3934
        # set the state that the instance gets when resize finishes
3559
3936
                                      {'task_state': None,
3560
3937
                                       'vm_state': vm_states.RESIZED})
3561
3938
 
3562
 
        self.compute_api.confirm_resize(context, instance)
3563
 
        self.compute.terminate_instance(context,
 
3939
        self.compute_api.confirm_resize(self.context, instance)
 
3940
        self.compute.terminate_instance(self.context,
3564
3941
            instance=jsonutils.to_primitive(instance))
3565
3942
 
3566
3943
    def test_resize_revert_through_api(self):
3567
3944
        instance = jsonutils.to_primitive(self._create_fake_instance())
3568
 
        context = self.context.elevated()
3569
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
3945
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
3570
3946
        self.compute.run_instance(self.context, instance=instance)
3571
3947
 
3572
 
        self.compute_api.resize(context, instance, '4')
 
3948
        self.compute_api.resize(self.context, instance, '4')
3573
3949
 
3574
3950
        # create a fake migration record (manager does this)
3575
 
        db.migration_create(context,
 
3951
        db.migration_create(self.context.elevated(),
3576
3952
                {'instance_uuid': instance['uuid'],
3577
3953
                 'status': 'finished'})
3578
3954
        # set the state that the instance gets when resize finishes
3580
3956
                                      {'task_state': None,
3581
3957
                                       'vm_state': vm_states.RESIZED})
3582
3958
 
3583
 
        self.compute_api.revert_resize(context, instance)
 
3959
        self.compute_api.revert_resize(self.context, instance)
3584
3960
 
3585
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
3961
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
3586
3962
        self.assertEqual(instance['vm_state'], vm_states.RESIZED)
3587
3963
        self.assertEqual(instance['task_state'], task_states.RESIZE_REVERTING)
3588
3964
 
3589
 
        self.compute.terminate_instance(context,
 
3965
        self.compute.terminate_instance(self.context,
3590
3966
            instance=jsonutils.to_primitive(instance))
3591
3967
 
3592
3968
    def test_resize_invalid_flavor_fails(self):
3593
3969
        """Ensure invalid flavors raise"""
3594
3970
        instance = self._create_fake_instance()
3595
 
        context = self.context.elevated()
3596
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
3971
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
3597
3972
        instance = jsonutils.to_primitive(instance)
3598
3973
        self.compute.run_instance(self.context, instance=instance)
3599
3974
 
3600
3975
        self.assertRaises(exception.NotFound, self.compute_api.resize,
3601
 
                context, instance, 200)
3602
 
 
3603
 
        self.compute.terminate_instance(context, instance=instance)
 
3976
                self.context, instance, 200)
 
3977
 
 
3978
        self.compute.terminate_instance(self.context, instance=instance)
 
3979
 
 
3980
    def test_resize_deleted_flavor_fails(self):
 
3981
        instance = self._create_fake_instance()
 
3982
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
 
3983
        instance = jsonutils.to_primitive(instance)
 
3984
        self.compute.run_instance(self.context, instance=instance)
 
3985
 
 
3986
        name = 'test_resize_new_flavor'
 
3987
        flavorid = 11
 
3988
        memory_mb = 128
 
3989
        root_gb = 0
 
3990
        vcpus = 1
 
3991
        instance_types.create(name, memory_mb, vcpus, root_gb, 0,
 
3992
                              flavorid, 0, 1.0, True)
 
3993
        instance_types.destroy(name)
 
3994
        self.assertRaises(exception.FlavorNotFound, self.compute_api.resize,
 
3995
                self.context, instance, 200)
 
3996
 
 
3997
        self.compute.terminate_instance(self.context, instance=instance)
3604
3998
 
3605
3999
    def test_resize_same_flavor_fails(self):
3606
4000
        """Ensure invalid flavors raise"""
3607
 
        context = self.context.elevated()
3608
4001
        instance = self._create_fake_instance()
3609
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
4002
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
3610
4003
        instance = jsonutils.to_primitive(instance)
3611
4004
 
3612
4005
        self.compute.run_instance(self.context, instance=instance)
3613
4006
 
3614
4007
        self.assertRaises(exception.CannotResizeToSameFlavor,
3615
 
                          self.compute_api.resize, context, instance, 1)
 
4008
                          self.compute_api.resize, self.context, instance, 1)
3616
4009
 
3617
 
        self.compute.terminate_instance(context, instance=instance)
 
4010
        self.compute.terminate_instance(self.context, instance=instance)
3618
4011
 
3619
4012
    def test_migrate(self):
3620
 
        context = self.context.elevated()
3621
4013
        instance = self._create_fake_instance()
3622
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
4014
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
3623
4015
        instance = jsonutils.to_primitive(instance)
3624
4016
        self.compute.run_instance(self.context, instance=instance)
3625
4017
        # Migrate simply calls resize() without a flavor_id.
3626
 
        self.compute_api.resize(context, instance, None)
3627
 
        self.compute.terminate_instance(context, instance=instance)
 
4018
        self.compute_api.resize(self.context, instance, None)
 
4019
        self.compute.terminate_instance(self.context, instance=instance)
3628
4020
 
3629
4021
    def test_resize_request_spec(self):
3630
 
        def _fake_cast(context, topic, msg):
 
4022
        def _fake_cast(_context, _topic, msg):
3631
4023
            request_spec = msg['args']['request_spec']
3632
4024
            filter_properties = msg['args']['filter_properties']
3633
4025
            instance_properties = request_spec['instance_properties']
3647
4039
 
3648
4040
        self.stubs.Set(rpc, 'cast', _fake_cast)
3649
4041
 
3650
 
        context = self.context.elevated()
3651
4042
        instance = self._create_fake_instance(dict(host='host2'))
3652
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
4043
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
3653
4044
        instance = jsonutils.to_primitive(instance)
 
4045
        instance['instance_type']['extra_specs'] = []
3654
4046
        orig_instance_type = instance['instance_type']
3655
4047
        self.compute.run_instance(self.context, instance=instance)
3656
4048
        # We need to set the host to something 'known'.  Unfortunately,
3657
 
        # the compute manager is using a cached copy of FLAGS.host,
 
4049
        # the compute manager is using a cached copy of CONF.host,
3658
4050
        # so we can't just self.flags(host='host2') before calling
3659
4051
        # run_instance above.  Also, set progress to 10 so we ensure
3660
4052
        # it is reset to 0 in compute_api.resize().  (verified in
3664
4056
        # different host
3665
4057
        self.flags(host='host3')
3666
4058
        try:
3667
 
            self.compute_api.resize(context, instance, None)
 
4059
            self.compute_api.resize(self.context, instance, None)
3668
4060
        finally:
3669
 
            self.compute.terminate_instance(context, instance=instance)
 
4061
            self.compute.terminate_instance(self.context, instance=instance)
3670
4062
 
3671
4063
    def test_resize_request_spec_noavoid(self):
3672
 
        def _fake_cast(context, topic, msg):
 
4064
        def _fake_cast(_context, topic, msg):
3673
4065
            request_spec = msg['args']['request_spec']
3674
4066
            filter_properties = msg['args']['filter_properties']
3675
4067
            instance_properties = request_spec['instance_properties']
3684
4076
        self.stubs.Set(rpc, 'cast', _fake_cast)
3685
4077
        self.flags(allow_resize_to_same_host=True)
3686
4078
 
3687
 
        context = self.context.elevated()
3688
4079
        instance = self._create_fake_instance(dict(host='host2'))
3689
 
        instance = db.instance_get_by_uuid(context, instance['uuid'])
 
4080
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
3690
4081
        instance = jsonutils.to_primitive(instance)
3691
4082
        self.compute.run_instance(self.context, instance=instance)
3692
4083
        # We need to set the host to something 'known'.  Unfortunately,
3693
 
        # the compute manager is using a cached copy of FLAGS.host,
 
4084
        # the compute manager is using a cached copy of CONF.host,
3694
4085
        # so we can't just self.flags(host='host2') before calling
3695
4086
        # run_instance above.  Also, set progress to 10 so we ensure
3696
4087
        # it is reset to 0 in compute_api.resize().  (verified in
3699
4090
                dict(host='host2', progress=10))
3700
4091
        # different host
3701
4092
        try:
3702
 
            self.compute_api.resize(context, instance, None)
 
4093
            self.compute_api.resize(self.context, instance, None)
3703
4094
        finally:
3704
 
            self.compute.terminate_instance(context, instance=instance)
 
4095
            self.compute.terminate_instance(self.context, instance=instance)
3705
4096
 
3706
4097
    def test_get(self):
3707
4098
        """Test get instance"""
 
4099
        exp_instance = self._create_fake_instance()
 
4100
        expected = dict(exp_instance.iteritems())
 
4101
        expected['name'] = exp_instance['name']
 
4102
 
 
4103
        def fake_db_get(_context, _instance_uuid):
 
4104
            return exp_instance
 
4105
 
 
4106
        self.stubs.Set(db, 'instance_get_by_uuid', fake_db_get)
 
4107
 
 
4108
        instance = self.compute_api.get(self.context, exp_instance['uuid'])
 
4109
        self.assertEquals(expected, instance)
 
4110
 
 
4111
    def test_get_with_admin_context(self):
 
4112
        """Test get instance"""
3708
4113
        c = context.get_admin_context()
3709
4114
        exp_instance = self._create_fake_instance()
3710
4115
        expected = dict(exp_instance.iteritems())
3720
4125
 
3721
4126
    def test_get_with_integer_id(self):
3722
4127
        """Test get instance with an integer id"""
3723
 
        c = context.get_admin_context()
3724
4128
        exp_instance = self._create_fake_instance()
3725
4129
        expected = dict(exp_instance.iteritems())
3726
4130
        expected['name'] = exp_instance['name']
3727
4131
 
3728
 
        def fake_db_get(context, instance_id):
 
4132
        def fake_db_get(_context, _instance_id):
3729
4133
            return exp_instance
3730
4134
 
3731
4135
        self.stubs.Set(db, 'instance_get', fake_db_get)
3732
4136
 
3733
 
        instance = self.compute_api.get(c, exp_instance['id'])
 
4137
        instance = self.compute_api.get(self.context, exp_instance['id'])
3734
4138
        self.assertEquals(expected, instance)
3735
4139
 
3736
4140
    def test_get_all_by_name_regexp(self):
3881
4285
                search_opts={'flavor': 5})
3882
4286
        self.assertEqual(len(instances), 0)
3883
4287
 
3884
 
        # ensure unknown filter maps to an empty list, not an exception
3885
 
        instances = self.compute_api.get_all(c, search_opts={'flavor': 99})
3886
 
        self.assertEqual(instances, [])
 
4288
        # ensure unknown filter maps to an exception
 
4289
        self.assertRaises(exception.FlavorNotFound,
 
4290
                          self.compute_api.get_all, c,
 
4291
                          search_opts={'flavor': 99})
3887
4292
 
3888
4293
        instances = self.compute_api.get_all(c, search_opts={'flavor': 3})
3889
4294
        self.assertEqual(len(instances), 1)
4169
4574
            ]
4170
4575
        bdms.sort()
4171
4576
        expected_result.sort()
4172
 
        self.assertDictListMatch(bdms, expected_result)
 
4577
        self.assertThat(bdms, matchers.DictListMatches(expected_result))
4173
4578
 
4174
4579
        self.compute_api._update_block_device_mapping(
4175
4580
            self.context, instance_types.get_default_instance_type(),
4205
4610
            {'no_device': True, 'device_name': '/dev/sdd4'}]
4206
4611
        bdms.sort()
4207
4612
        expected_result.sort()
4208
 
        self.assertDictListMatch(bdms, expected_result)
 
4613
        self.assertThat(bdms, matchers.DictListMatches(expected_result))
4209
4614
 
4210
4615
        for bdm in db.block_device_mapping_get_all_by_instance(
4211
4616
            self.context, instance['uuid']):
4267
4672
                        params={'architecture': ''}))
4268
4673
        try:
4269
4674
            self.compute.run_instance(self.context, instance=instance)
4270
 
            instances = db.instance_get_all(context.get_admin_context())
4271
 
            instance = instances[0]
 
4675
            instance = db.instance_get_by_uuid(self.context,
 
4676
                    instance['uuid'])
4272
4677
            self.assertNotEqual(instance['architecture'], 'Unknown')
4273
4678
        finally:
4274
4679
            db.instance_destroy(self.context, instance['uuid'])
4298
4703
        db.instance_destroy(self.context, i_ref['uuid'])
4299
4704
 
4300
4705
    def test_add_remove_fixed_ip(self):
4301
 
        instance = self._create_fake_instance(params={'host': FLAGS.host})
 
4706
        instance = self._create_fake_instance(params={'host': CONF.host})
4302
4707
        self.compute_api.add_fixed_ip(self.context, instance, '1')
4303
4708
        self.compute_api.remove_fixed_ip(self.context, instance, '192.168.1.1')
4304
4709
        self.compute_api.delete(self.context, instance)
4337
4742
 
4338
4743
        rpc.call(self.context, 'compute.%s' % fake_instance['host'],
4339
4744
                rpc_msg1, None).AndReturn(fake_connect_info2)
4340
 
        rpc.call(self.context, FLAGS.consoleauth_topic,
 
4745
        rpc.call(self.context, CONF.consoleauth_topic,
4341
4746
                rpc_msg2, None).AndReturn(None)
4342
4747
 
4343
4748
        self.mox.ReplayAll()
4355
4760
 
4356
4761
        db.instance_destroy(self.context, instance['uuid'])
4357
4762
 
 
4763
    def test_get_backdoor_port(self):
 
4764
        """Test api call to get backdoor_port"""
 
4765
        fake_backdoor_port = 59697
 
4766
 
 
4767
        self.mox.StubOutWithMock(rpc, 'call')
 
4768
 
 
4769
        rpc_msg = {'method': 'get_backdoor_port',
 
4770
                   'args': {},
 
4771
                   'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION}
 
4772
        rpc.call(self.context, 'compute.fake_host', rpc_msg,
 
4773
                 None).AndReturn(fake_backdoor_port)
 
4774
 
 
4775
        self.mox.ReplayAll()
 
4776
 
 
4777
        port = self.compute_api.get_backdoor_port(self.context, 'fake_host')
 
4778
        self.assertEqual(port, fake_backdoor_port)
 
4779
 
4358
4780
    def test_console_output(self):
4359
4781
        fake_instance = {'uuid': 'fake_uuid',
4360
4782
                         'host': 'fake_compute_host'}
4394
4816
        def fake_rpc_attach_volume(self, context, **kwargs):
4395
4817
            called['fake_rpc_attach_volume'] = True
4396
4818
 
4397
 
        self.stubs.Set(nova.volume.api.API, 'get', fake_volume_get)
4398
 
        self.stubs.Set(nova.volume.api.API, 'check_attach', fake_check_attach)
4399
 
        self.stubs.Set(nova.volume.api.API, 'reserve_volume',
 
4819
        self.stubs.Set(cinder.API, 'get', fake_volume_get)
 
4820
        self.stubs.Set(cinder.API, 'check_attach', fake_check_attach)
 
4821
        self.stubs.Set(cinder.API, 'reserve_volume',
4400
4822
                       fake_reserve_volume)
4401
4823
        self.stubs.Set(compute_rpcapi.ComputeAPI, 'attach_volume',
4402
4824
                       fake_rpc_attach_volume)
4425
4847
        def fake_rpc_attach_volume(self, context, **kwargs):
4426
4848
            called['fake_rpc_attach_volume'] = True
4427
4849
 
4428
 
        self.stubs.Set(nova.volume.api.API, 'get', fake_volume_get)
4429
 
        self.stubs.Set(nova.volume.api.API, 'check_attach', fake_check_attach)
4430
 
        self.stubs.Set(nova.volume.api.API, 'reserve_volume',
 
4850
        self.stubs.Set(cinder.API, 'get', fake_volume_get)
 
4851
        self.stubs.Set(cinder.API, 'check_attach', fake_check_attach)
 
4852
        self.stubs.Set(cinder.API, 'reserve_volume',
4431
4853
                       fake_reserve_volume)
4432
4854
        self.stubs.Set(compute_rpcapi.ComputeAPI, 'attach_volume',
4433
4855
                       fake_rpc_attach_volume)
4434
4856
 
 
4857
    def test_terminate_with_volumes(self):
 
4858
        """Make sure that volumes get detached during instance termination"""
 
4859
        admin = context.get_admin_context()
4435
4860
        instance = self._create_fake_instance()
4436
 
        self.compute_api.attach_volume(self.context, instance, 1, device=None)
4437
 
        self.assertTrue(called.get('fake_check_attach'))
4438
 
        self.assertTrue(called.get('fake_reserve_volume'))
4439
 
        self.assertTrue(called.get('fake_reserve_volume'))
4440
 
        self.assertTrue(called.get('fake_rpc_attach_volume'))
 
4861
 
 
4862
        volume_id = 'fake'
 
4863
        values = {'instance_uuid': instance['uuid'],
 
4864
                  'device_name': '/dev/vdc',
 
4865
                  'delete_on_termination': False,
 
4866
                  'volume_id': volume_id,
 
4867
                  }
 
4868
        db.block_device_mapping_create(admin, values)
 
4869
 
 
4870
        def fake_volume_get(self, context, volume):
 
4871
            return {'id': volume_id}
 
4872
        self.stubs.Set(cinder.API, "get", fake_volume_get)
 
4873
 
 
4874
        # Stub out and record whether it gets detached
 
4875
        result = {"detached": False}
 
4876
 
 
4877
        def fake_detach(self, context, volume):
 
4878
            result["detached"] = volume["id"] == volume_id
 
4879
        self.stubs.Set(cinder.API, "detach", fake_detach)
 
4880
 
 
4881
        def fake_terminate_connection(self, context, volume, connector):
 
4882
            return {}
 
4883
        self.stubs.Set(cinder.API, "terminate_connection",
 
4884
                       fake_terminate_connection)
 
4885
 
 
4886
        # Kill the instance and check that it was detached
 
4887
        self.compute.terminate_instance(admin, instance=instance)
 
4888
        self.assertTrue(result["detached"])
4441
4889
 
4442
4890
    def test_inject_network_info(self):
4443
 
        instance = self._create_fake_instance(params={'host': FLAGS.host})
 
4891
        instance = self._create_fake_instance(params={'host': CONF.host})
4444
4892
        self.compute.run_instance(self.context,
4445
4893
                instance=jsonutils.to_primitive(instance))
4446
4894
        instance = self.compute_api.get(self.context, instance['uuid'])
4515
4963
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4516
4964
 
4517
4965
        self.mox.StubOutWithMock(rpc, 'cast')
4518
 
        topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
 
4966
        topic = rpc.queue_get_for(self.context, CONF.compute_topic,
4519
4967
                                  instance['host'])
4520
4968
        rpc.cast(self.context, topic,
4521
4969
                {"method": "refresh_instance_security_rules",
4544
4992
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4545
4993
 
4546
4994
        self.mox.StubOutWithMock(rpc, 'cast')
4547
 
        topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
 
4995
        topic = rpc.queue_get_for(self.context, CONF.compute_topic,
4548
4996
                                  instance['host'])
4549
4997
        rpc.cast(self.context, topic,
4550
4998
                {"method": "refresh_instance_security_rules",
4585
5033
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4586
5034
 
4587
5035
        self.mox.StubOutWithMock(rpc, 'cast')
4588
 
        topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
 
5036
        topic = rpc.queue_get_for(self.context, CONF.compute_topic,
4589
5037
                                  instance['host'])
4590
5038
        rpc.cast(self.context, topic,
4591
5039
                {"method": "refresh_instance_security_rules",
4606
5054
        self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4607
5055
 
4608
5056
        self.mox.StubOutWithMock(rpc, 'cast')
4609
 
        topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
 
5057
        topic = rpc.queue_get_for(self.context, CONF.compute_topic,
4610
5058
                                  instance['host'])
4611
5059
        rpc.cast(self.context, topic,
4612
5060
                {"method": "refresh_instance_security_rules",
4690
5138
        metadata['foo_key1'] = None
4691
5139
        expected = self.api.update_aggregate_metadata(self.context,
4692
5140
                                             aggr['id'], metadata)
4693
 
        self.assertDictMatch(expected['metadata'], {'foo_key2': 'foo_value2'})
 
5141
        self.assertThat(expected['metadata'],
 
5142
                        matchers.DictMatches({'foo_key2': 'foo_value2'}))
4694
5143
 
4695
5144
    def test_delete_aggregate(self):
4696
5145
        """Ensure we can delete an aggregate."""
4698
5147
        aggr = self.api.create_aggregate(self.context, 'fake_aggregate',
4699
5148
                                         'fake_zone')
4700
5149
        self.api.delete_aggregate(self.context, aggr['id'])
4701
 
        expected = db.aggregate_get(self.context.elevated(read_deleted='yes'),
4702
 
                                    aggr['id'])
 
5150
        db.aggregate_get(self.context.elevated(read_deleted='yes'),
 
5151
                         aggr['id'])
4703
5152
        self.assertRaises(exception.AggregateNotFound,
4704
5153
                          self.api.delete_aggregate, self.context, aggr['id'])
4705
5154
 
4778
5227
                          self.context, aggr['id'], 'invalid_host')
4779
5228
 
4780
5229
 
 
5230
class ComputeBackdoorPortTestCase(BaseTestCase):
 
5231
    """This is for unit test coverage of backdoor port rpc"""
 
5232
 
 
5233
    def setUp(self):
 
5234
        super(ComputeBackdoorPortTestCase, self).setUp()
 
5235
        self.context = context.get_admin_context()
 
5236
        self.compute.backdoor_port = 59697
 
5237
 
 
5238
    def test_get_backdoor_port(self):
 
5239
        port = self.compute.get_backdoor_port(self.context)
 
5240
        self.assertEqual(port, self.compute.backdoor_port)
 
5241
 
 
5242
 
4781
5243
class ComputeAggrTestCase(BaseTestCase):
4782
5244
    """This is for unit coverage of aggregate-related methods
4783
5245
    defined in nova.compute.manager."""
4796
5258
        self.stubs.Set(self.compute.driver, "add_to_aggregate",
4797
5259
                       fake_driver_add_to_aggregate)
4798
5260
 
4799
 
        self.compute.add_aggregate_host(self.context, self.aggr.id, "host")
 
5261
        self.compute.add_aggregate_host(self.context, "host",
 
5262
                aggregate=jsonutils.to_primitive(self.aggr))
4800
5263
        self.assertTrue(fake_driver_add_to_aggregate.called)
4801
5264
 
4802
5265
    def test_remove_aggregate_host(self):
4808
5271
        self.stubs.Set(self.compute.driver, "remove_from_aggregate",
4809
5272
                       fake_driver_remove_from_aggregate)
4810
5273
 
4811
 
        self.compute.remove_aggregate_host(self.context, self.aggr.id, "host")
 
5274
        self.compute.remove_aggregate_host(self.context,
 
5275
                aggregate=jsonutils.to_primitive(self.aggr), host="host")
4812
5276
        self.assertTrue(fake_driver_remove_from_aggregate.called)
4813
5277
 
4814
5278
    def test_add_aggregate_host_passes_slave_info_to_driver(self):
4815
5279
        def driver_add_to_aggregate(context, aggregate, host, **kwargs):
4816
5280
            self.assertEquals(self.context, context)
4817
 
            self.assertEquals(aggregate.id, self.aggr.id)
 
5281
            self.assertEquals(aggregate['id'], self.aggr.id)
4818
5282
            self.assertEquals(host, "the_host")
4819
5283
            self.assertEquals("SLAVE_INFO", kwargs.get("slave_info"))
4820
5284
 
4821
5285
        self.stubs.Set(self.compute.driver, "add_to_aggregate",
4822
5286
                       driver_add_to_aggregate)
4823
5287
 
4824
 
        self.compute.add_aggregate_host(self.context, self.aggr.id,
4825
 
            "the_host", slave_info="SLAVE_INFO")
 
5288
        self.compute.add_aggregate_host(self.context, "the_host",
 
5289
                slave_info="SLAVE_INFO",
 
5290
                aggregate=jsonutils.to_primitive(self.aggr))
4826
5291
 
4827
5292
    def test_remove_from_aggregate_passes_slave_info_to_driver(self):
4828
5293
        def driver_remove_from_aggregate(context, aggregate, host, **kwargs):
4829
5294
            self.assertEquals(self.context, context)
4830
 
            self.assertEquals(aggregate.id, self.aggr.id)
 
5295
            self.assertEquals(aggregate['id'], self.aggr.id)
4831
5296
            self.assertEquals(host, "the_host")
4832
5297
            self.assertEquals("SLAVE_INFO", kwargs.get("slave_info"))
4833
5298
 
4835
5300
                       driver_remove_from_aggregate)
4836
5301
 
4837
5302
        self.compute.remove_aggregate_host(self.context,
4838
 
            self.aggr.id, "the_host", slave_info="SLAVE_INFO")
 
5303
                aggregate=jsonutils.to_primitive(self.aggr), host="the_host",
 
5304
                slave_info="SLAVE_INFO")
4839
5305
 
4840
5306
 
4841
5307
class ComputePolicyTestCase(BaseTestCase):
4852
5318
        nova.policy.reset()
4853
5319
 
4854
5320
    def _set_rules(self, rules):
4855
 
        common_policy.set_brain(common_policy.HttpBrain(rules))
 
5321
        common_policy.set_rules(common_policy.Rules(
 
5322
                dict((k, common_policy.parse_rule(v))
 
5323
                     for k, v in rules.items())))
4856
5324
 
4857
5325
    def test_actions_are_prefixed(self):
4858
5326
        self.mox.StubOutWithMock(nova.policy, 'enforce')
4859
5327
        nova.policy.enforce(self.context, 'compute:reboot', {})
4860
5328
        self.mox.ReplayAll()
4861
 
        nova.compute.api.check_policy(self.context, 'reboot', {})
 
5329
        compute_api.check_policy(self.context, 'reboot', {})
4862
5330
 
4863
5331
    def test_wrapped_method(self):
4864
5332
        instance = self._create_fake_instance(params={'host': None})
4943
5411
                          self.compute_api.get_instance_faults,
4944
5412
                          self.context, instances)
4945
5413
 
 
5414
    def test_force_host_fail(self):
 
5415
        rules = {"compute:create": [],
 
5416
                 "compute:create:forced_host": [["role:fake"]]}
 
5417
        self._set_rules(rules)
 
5418
 
 
5419
        self.assertRaises(exception.PolicyNotAuthorized,
 
5420
                          self.compute_api.create, self.context, None, '1',
 
5421
                          availability_zone='1:1')
 
5422
 
 
5423
    def test_force_host_pass(self):
 
5424
        rules = {"compute:create": [],
 
5425
                 "compute:create:forced_host": []}
 
5426
        self._set_rules(rules)
 
5427
 
 
5428
        self.compute_api.create(self.context, None, '1',
 
5429
                                availability_zone='1:1')
 
5430
 
4946
5431
 
4947
5432
class ComputeHostAPITestCase(BaseTestCase):
4948
5433
    def setUp(self):
5076
5561
 
5077
5562
    def test_create_keypair_quota_limit(self):
5078
5563
        def fake_quotas_count(self, context, resource, *args, **kwargs):
5079
 
            return FLAGS.quota_key_pairs
 
5564
            return CONF.quota_key_pairs
5080
5565
        self.stubs.Set(QUOTAS, "count", fake_quotas_count)
5081
5566
        self.assertRaises(exception.KeypairLimitExceeded,
5082
5567
                          self.keypair_api.create_key_pair,
5110
5595
 
5111
5596
    def test_import_keypair_quota_limit(self):
5112
5597
        def fake_quotas_count(self, context, resource, *args, **kwargs):
5113
 
            return FLAGS.quota_key_pairs
 
5598
            return CONF.quota_key_pairs
5114
5599
        self.stubs.Set(QUOTAS, "count", fake_quotas_count)
5115
5600
        self.assertRaises(exception.KeypairLimitExceeded,
5116
5601
                          self.keypair_api.import_key_pair,
5143
5628
 
5144
5629
    def test_can_build_instance_from_visible_instance_type(self):
5145
5630
        self.inst_type['disabled'] = False
5146
 
 
5147
 
        self.assertNotRaises(exception.InstanceTypeNotFound,
5148
 
            self.compute_api.create, self.context, self.inst_type, None,
5149
 
            exc_msg="Visible instance-types can be built from")
 
5631
        # Assert that exception.InstanceTypeNotFound is not raised
 
5632
        self.compute_api.create(self.context, self.inst_type, None)
5150
5633
 
5151
5634
    def test_cannot_build_instance_from_disabled_instance_type(self):
5152
5635
        self.inst_type['disabled'] = True
5161
5644
        instance['instance_type']['disabled'] = True
5162
5645
 
5163
5646
        # Assert no errors were raised
5164
 
        self.assertNotRaises(None,
5165
 
            self.compute_api.rebuild, self.context, instance, image_href,
5166
 
            admin_password,
5167
 
            exc_msg="Visible instance-types can be rebuilt from")
 
5647
        self.compute_api.rebuild(self.context, instance, image_href,
 
5648
                                 admin_password)
5168
5649
 
5169
5650
    def test_can_rebuild_instance_from_disabled_instance_type(self):
5170
5651
        """
5179
5660
        instance['instance_type']['disabled'] = True
5180
5661
 
5181
5662
        # Assert no errors were raised
5182
 
        self.assertNotRaises(None,
5183
 
            self.compute_api.rebuild, self.context, instance, image_href,
5184
 
            admin_password,
5185
 
            exc_msg="Disabled instance-types can be rebuilt from")
 
5663
        self.compute_api.rebuild(self.context, instance, image_href,
 
5664
                                 admin_password)
5186
5665
 
5187
5666
    def test_can_resize_to_visible_instance_type(self):
5188
5667
        instance = self._create_fake_instance()
5189
5668
        orig_get_instance_type_by_flavor_id =\
5190
5669
                instance_types.get_instance_type_by_flavor_id
5191
5670
 
5192
 
        def fake_get_instance_type_by_flavor_id(flavor_id):
5193
 
            instance_type = orig_get_instance_type_by_flavor_id(flavor_id)
 
5671
        def fake_get_instance_type_by_flavor_id(flavor_id, ctxt=None,
 
5672
                                                read_deleted="yes"):
 
5673
            instance_type = orig_get_instance_type_by_flavor_id(flavor_id,
 
5674
                                                                ctxt,
 
5675
                                                                read_deleted)
5194
5676
            instance_type['disabled'] = False
5195
5677
            return instance_type
5196
5678
 
5198
5680
                       fake_get_instance_type_by_flavor_id)
5199
5681
 
5200
5682
        # FIXME(sirp): for legacy this raises FlavorNotFound instead of
5201
 
        # InstanceTypeNot; we should eventually make it raise
 
5683
        # InstanceTypeNotFound; we should eventually make it raise
5202
5684
        # InstanceTypeNotFound for consistency.
5203
 
        self.assertNotRaises(exception.FlavorNotFound,
5204
 
            self.compute_api.resize, self.context, instance, '4',
5205
 
            exc_msg="Visible flavors can be resized to")
 
5685
        self.compute_api.resize(self.context, instance, '4')
5206
5686
 
5207
5687
    def test_cannot_resize_to_disabled_instance_type(self):
5208
5688
        instance = self._create_fake_instance()
5209
5689
        orig_get_instance_type_by_flavor_id = \
5210
5690
                instance_types.get_instance_type_by_flavor_id
5211
5691
 
5212
 
        def fake_get_instance_type_by_flavor_id(flavor_id):
5213
 
            instance_type = orig_get_instance_type_by_flavor_id(flavor_id)
 
5692
        def fake_get_instance_type_by_flavor_id(flavor_id, ctxt=None,
 
5693
                                                read_deleted="yes"):
 
5694
            instance_type = orig_get_instance_type_by_flavor_id(flavor_id,
 
5695
                                                                ctxt,
 
5696
                                                                read_deleted)
5214
5697
            instance_type['disabled'] = True
5215
5698
            return instance_type
5216
5699
 
5228
5711
        instance['instance_type']['disabled'] = False
5229
5712
 
5230
5713
        # FIXME(sirp): for legacy this raises FlavorNotFound instead of
5231
 
        # InstanceTypeNot; we should eventually make it raise
 
5714
        # InstanceTypeNotFound; we should eventually make it raise
5232
5715
        # InstanceTypeNotFound for consistency.
5233
 
        self.assertNotRaises(exception.FlavorNotFound,
5234
 
            self.compute_api.resize, self.context, instance, None,
5235
 
            exc_msg="Visible flavors can be migrated to")
 
5716
        self.compute_api.resize(self.context, instance, None)
5236
5717
 
5237
5718
    def test_can_migrate_to_disabled_instance_type(self):
5238
5719
        """
5243
5724
        instance['instance_type']['disabled'] = True
5244
5725
 
5245
5726
        # FIXME(sirp): for legacy this raises FlavorNotFound instead of
5246
 
        # InstanceTypeNot; we should eventually make it raise
 
5727
        # InstanceTypeNotFound; we should eventually make it raise
5247
5728
        # InstanceTypeNotFound for consistency.
5248
 
        self.assertNotRaises(exception.FlavorNotFound,
5249
 
            self.compute_api.resize, self.context, instance, None,
5250
 
            exc_msg="Disabled flavors can be migrated to")
 
5729
        self.compute_api.resize(self.context, instance, None)
5251
5730
 
5252
5731
 
5253
5732
class ComputeReschedulingTestCase(BaseTestCase):
5254
 
    """Tests related to re-scheduling build requests"""
 
5733
    """Tests re-scheduling logic for new build requests"""
5255
5734
 
5256
5735
    def setUp(self):
5257
5736
        super(ComputeReschedulingTestCase, self).setUp()
5258
5737
 
5259
 
        self._reschedule = self._reschedule_partial()
 
5738
        self.expected_task_state = task_states.SCHEDULING
5260
5739
 
5261
5740
        def fake_update(*args, **kwargs):
5262
5741
            self.updated_task_state = kwargs.get('task_state')
5263
5742
        self.stubs.Set(self.compute, '_instance_update', fake_update)
5264
5743
 
5265
 
    def _reschedule_partial(self):
5266
 
        uuid = "12-34-56-78-90"
5267
 
 
5268
 
        requested_networks = None
 
5744
    def _reschedule(self, request_spec=None, filter_properties=None):
 
5745
        if not filter_properties:
 
5746
            filter_properties = {}
 
5747
 
 
5748
        instance_uuid = "12-34-56-78-90"
 
5749
 
5269
5750
        admin_password = None
5270
5751
        injected_files = None
 
5752
        requested_networks = None
5271
5753
        is_first_time = False
5272
5754
 
5273
 
        return functools.partial(self.compute._reschedule, self.context, uuid,
5274
 
                requested_networks, admin_password, injected_files,
5275
 
                is_first_time, request_spec=None, filter_properties={})
 
5755
        scheduler_method = self.compute.scheduler_rpcapi.run_instance
 
5756
        method_args = (request_spec, admin_password, injected_files,
 
5757
                       requested_networks, is_first_time, filter_properties)
 
5758
        return self.compute._reschedule(self.context, request_spec,
 
5759
                filter_properties, instance_uuid, scheduler_method,
 
5760
                method_args, self.expected_task_state)
5276
5761
 
5277
5762
    def test_reschedule_no_filter_properties(self):
5278
5763
        """no filter_properties will disable re-scheduling"""
5296
5781
        self.assertTrue(self._reschedule(filter_properties=filter_properties,
5297
5782
            request_spec=request_spec))
5298
5783
        self.assertEqual(1, len(request_spec['instance_uuids']))
5299
 
        self.assertEqual(self.updated_task_state, task_states.SCHEDULING)
5300
 
 
5301
 
 
5302
 
class ThatsNoOrdinaryRabbitException(Exception):
 
5784
        self.assertEqual(self.updated_task_state, self.expected_task_state)
 
5785
 
 
5786
 
 
5787
class ComputeReschedulingResizeTestCase(ComputeReschedulingTestCase):
 
5788
    """Test re-scheduling logic for prep_resize requests"""
 
5789
 
 
5790
    def setUp(self):
 
5791
        super(ComputeReschedulingResizeTestCase, self).setUp()
 
5792
        self.expected_task_state = task_states.RESIZE_PREP
 
5793
 
 
5794
    def _reschedule(self, request_spec=None, filter_properties=None):
 
5795
        if not filter_properties:
 
5796
            filter_properties = {}
 
5797
 
 
5798
        instance_uuid = "12-34-56-78-90"
 
5799
 
 
5800
        instance = {'uuid': instance_uuid}
 
5801
        instance_type = {}
 
5802
        image = None
 
5803
        reservations = None
 
5804
 
 
5805
        scheduler_method = self.compute.scheduler_rpcapi.prep_resize
 
5806
        method_args = (instance, instance_type, image, request_spec,
 
5807
                filter_properties, reservations)
 
5808
 
 
5809
        return self.compute._reschedule(self.context, request_spec,
 
5810
                filter_properties, instance_uuid, scheduler_method,
 
5811
                method_args, self.expected_task_state)
 
5812
 
 
5813
 
 
5814
class InnerTestingException(Exception):
5303
5815
    pass
5304
5816
 
5305
5817
 
5306
 
class ComputeReschedulingExceptionTestCase(BaseTestCase):
5307
 
    """Tests for re-scheduling exception handling logic"""
5308
 
 
5309
 
    def setUp(self):
5310
 
        super(ComputeReschedulingExceptionTestCase, self).setUp()
5311
 
 
5312
 
        # cause _spawn to raise an exception to test the exception logic:
5313
 
        def exploding_spawn(*args, **kwargs):
5314
 
            raise ThatsNoOrdinaryRabbitException()
5315
 
        self.stubs.Set(self.compute, '_spawn',
5316
 
                exploding_spawn)
5317
 
 
5318
 
        self.fake_instance = jsonutils.to_primitive(
5319
 
                self._create_fake_instance())
5320
 
        self.instance_uuid = self.fake_instance['uuid']
5321
 
 
5322
 
    def test_exception_with_rescheduling_disabled(self):
5323
 
        """Spawn fails and re-scheduling is disabled."""
5324
 
        # this won't be re-scheduled:
5325
 
        self.assertRaises(ThatsNoOrdinaryRabbitException,
5326
 
                self.compute._run_instance, self.context,
5327
 
                None, {}, None, None, None, None, self.fake_instance)
5328
 
 
5329
 
    def test_exception_with_rescheduling_enabled(self):
5330
 
        """Spawn fails and re-scheduling is enabled.  Original exception
5331
 
        should *not* be re-raised.
5332
 
        """
5333
 
        # provide the expected status so that this one will be re-scheduled:
5334
 
        retry = dict(num_attempts=1)
5335
 
        filter_properties = dict(retry=retry)
5336
 
        request_spec = dict(num_attempts=1)
5337
 
        self.assertNotRaises(ThatsNoOrdinaryRabbitException,
5338
 
                self.compute._run_instance, self.context,
5339
 
                filter_properties=filter_properties, request_spec=request_spec,
5340
 
                instance=self.fake_instance)
5341
 
 
5342
 
    def test_exception_context_cleared(self):
5343
 
        """Test with no rescheduling and an additional exception occurs
5344
 
        clearing the original build error's exception context.
5345
 
        """
5346
 
        # clears the original exception context:
5347
 
        class FleshWoundException(Exception):
5348
 
            pass
5349
 
 
5350
 
        def reschedule_explode(*args, **kwargs):
5351
 
            raise FleshWoundException()
5352
 
        self.stubs.Set(self.compute, '_reschedule', reschedule_explode)
5353
 
 
5354
 
        # the original exception should now be raised:
5355
 
        self.assertRaises(ThatsNoOrdinaryRabbitException,
5356
 
                self.compute._run_instance, self.context,
5357
 
                None, {}, None, None, None, None, self.fake_instance)
 
5818
class ComputeRescheduleOrReraiseTestCase(BaseTestCase):
 
5819
    """Test logic and exception handling around rescheduling or re-raising
 
5820
    original exceptions when builds fail.
 
5821
    """
 
5822
 
 
5823
    def setUp(self):
 
5824
        super(ComputeRescheduleOrReraiseTestCase, self).setUp()
 
5825
        self.instance = self._create_fake_instance()
 
5826
 
 
5827
    def test_reschedule_or_reraise_called(self):
 
5828
        """Basic sanity check to make sure _reschedule_or_reraise is called
 
5829
        when a build fails.
 
5830
        """
 
5831
        self.mox.StubOutWithMock(self.compute, '_spawn')
 
5832
        self.mox.StubOutWithMock(self.compute, '_reschedule_or_reraise')
 
5833
 
 
5834
        self.compute._spawn(mox.IgnoreArg(), self.instance, None, None, None,
 
5835
                False, None).AndRaise(test.TestingException("BuildError"))
 
5836
        self.compute._reschedule_or_reraise(mox.IgnoreArg(), self.instance,
 
5837
                None, None, None, False, None, {})
 
5838
 
 
5839
        self.mox.ReplayAll()
 
5840
        self.compute._run_instance(self.context, None, {}, None, None, None,
 
5841
                False, self.instance)
 
5842
 
 
5843
    def test_deallocate_network_fail(self):
 
5844
        """Test de-allocation of network failing before re-scheduling logic
 
5845
        can even run.
 
5846
        """
 
5847
        instance_uuid = self.instance['uuid']
 
5848
        self.mox.StubOutWithMock(self.compute, '_deallocate_network')
 
5849
 
 
5850
        try:
 
5851
            raise test.TestingException("Original")
 
5852
        except Exception:
 
5853
            exc_info = sys.exc_info()
 
5854
 
 
5855
            self.compute._deallocate_network(self.context,
 
5856
                    self.instance).AndRaise(InnerTestingException("Error"))
 
5857
            self.compute._log_original_error(exc_info, instance_uuid)
 
5858
 
 
5859
            self.mox.ReplayAll()
 
5860
 
 
5861
            # should raise the deallocation exception, not the original build
 
5862
            # error:
 
5863
            self.assertRaises(InnerTestingException,
 
5864
                    self.compute._reschedule_or_reraise, self.context,
 
5865
                    self.instance, None, None, None, False, None, {})
 
5866
 
 
5867
    def test_reschedule_fail(self):
 
5868
        """Test handling of exception from _reschedule"""
 
5869
        instance_uuid = self.instance['uuid']
 
5870
        method_args = (None, None, None, None, False, {})
 
5871
        self.mox.StubOutWithMock(self.compute, '_deallocate_network')
 
5872
        self.mox.StubOutWithMock(self.compute, '_reschedule')
 
5873
 
 
5874
        self.compute._deallocate_network(self.context,
 
5875
                self.instance)
 
5876
        self.compute._reschedule(self.context, None, instance_uuid,
 
5877
                {}, self.compute.scheduler_rpcapi.run_instance,
 
5878
                method_args, task_states.SCHEDULING).AndRaise(
 
5879
                        InnerTestingException("Inner"))
 
5880
 
 
5881
        self.mox.ReplayAll()
 
5882
 
 
5883
        try:
 
5884
            raise test.TestingException("Original")
 
5885
        except Exception:
 
5886
            # not re-scheduling, should raise the original build error:
 
5887
            self.assertRaises(test.TestingException,
 
5888
                    self.compute._reschedule_or_reraise, self.context,
 
5889
                    self.instance, None, None, None, False, None, {})
 
5890
 
 
5891
    def test_reschedule_false(self):
 
5892
        """Test not-rescheduling, but no nested exception"""
 
5893
        instance_uuid = self.instance['uuid']
 
5894
        method_args = (None, None, None, None, False, {})
 
5895
        self.mox.StubOutWithMock(self.compute, '_deallocate_network')
 
5896
        self.mox.StubOutWithMock(self.compute, '_reschedule')
 
5897
 
 
5898
        self.compute._deallocate_network(self.context,
 
5899
                self.instance)
 
5900
        self.compute._reschedule(self.context, None, instance_uuid,
 
5901
                {}, self.compute.scheduler_rpcapi.run_instance, method_args,
 
5902
                task_states.SCHEDULING).AndReturn(False)
 
5903
 
 
5904
        self.mox.ReplayAll()
 
5905
 
 
5906
        try:
 
5907
            raise test.TestingException("Original")
 
5908
        except Exception:
 
5909
            # re-scheduling is False, the original build error should be
 
5910
            # raised here:
 
5911
            self.assertRaises(test.TestingException,
 
5912
                    self.compute._reschedule_or_reraise, self.context,
 
5913
                    self.instance, None, None, None, False, None, {})
 
5914
 
 
5915
    def test_reschedule_true(self):
 
5916
        """Test behavior when re-scheduling happens"""
 
5917
        instance_uuid = self.instance['uuid']
 
5918
        method_args = (None, None, None, None, False, {})
 
5919
        self.mox.StubOutWithMock(self.compute, '_deallocate_network')
 
5920
        self.mox.StubOutWithMock(self.compute, '_reschedule')
 
5921
 
 
5922
        try:
 
5923
            raise test.TestingException("Original")
 
5924
        except Exception:
 
5925
            exc_info = sys.exc_info()
 
5926
 
 
5927
            self.compute._deallocate_network(self.context,
 
5928
                    self.instance)
 
5929
            self.compute._reschedule(self.context, None, {}, instance_uuid,
 
5930
                    self.compute.scheduler_rpcapi.run_instance,
 
5931
                    method_args, task_states.SCHEDULING).AndReturn(True)
 
5932
            self.compute._log_original_error(exc_info, instance_uuid)
 
5933
 
 
5934
            self.mox.ReplayAll()
 
5935
 
 
5936
            # re-scheduling is True, original error is logged, but nothing
 
5937
            # is raised:
 
5938
            self.compute._reschedule_or_reraise(self.context, self.instance,
 
5939
                    None, None, None, False, None, {})
 
5940
 
 
5941
 
 
5942
class ComputeRescheduleResizeOrReraiseTestCase(BaseTestCase):
 
5943
    """Test logic and exception handling around rescheduling prep resize
 
5944
    requests
 
5945
    """
 
5946
    def setUp(self):
 
5947
        super(ComputeRescheduleResizeOrReraiseTestCase, self).setUp()
 
5948
        self.instance = self._create_fake_instance()
 
5949
        self.instance_uuid = self.instance['uuid']
 
5950
        self.instance_type = instance_types.get_instance_type_by_name(
 
5951
                "m1.tiny")
 
5952
 
 
5953
    def test_reschedule_resize_or_reraise_called(self):
 
5954
        """Verify the rescheduling logic gets called when there is an error
 
5955
        during prep_resize.
 
5956
        """
 
5957
        self.mox.StubOutWithMock(self.compute.db, 'migration_create')
 
5958
        self.mox.StubOutWithMock(self.compute, '_reschedule_resize_or_reraise')
 
5959
 
 
5960
        self.compute.db.migration_create(mox.IgnoreArg(),
 
5961
                mox.IgnoreArg()).AndRaise(test.TestingException("Original"))
 
5962
 
 
5963
        self.compute._reschedule_resize_or_reraise(mox.IgnoreArg(), None,
 
5964
                self.instance, self.instance_type, None, None, None)
 
5965
 
 
5966
        self.mox.ReplayAll()
 
5967
 
 
5968
        self.compute.prep_resize(self.context, None, self.instance,
 
5969
                self.instance_type)
 
5970
 
 
5971
    def test_reschedule_fails_with_exception(self):
 
5972
        """Original exception should be raised if the _reschedule method
 
5973
        raises another exception
 
5974
        """
 
5975
        method_args = (None, self.instance, self.instance_type, None, None,
 
5976
                None)
 
5977
        self.mox.StubOutWithMock(self.compute, "_reschedule")
 
5978
 
 
5979
        self.compute._reschedule(self.context, None, None, self.instance_uuid,
 
5980
                self.compute.scheduler_rpcapi.prep_resize, method_args,
 
5981
                task_states.RESIZE_PREP).AndRaise(
 
5982
                        InnerTestingException("Inner"))
 
5983
        self.mox.ReplayAll()
 
5984
 
 
5985
        try:
 
5986
            raise test.TestingException("Original")
 
5987
        except Exception:
 
5988
            self.assertRaises(test.TestingException,
 
5989
                    self.compute._reschedule_resize_or_reraise, self.context,
 
5990
                    None, self.instance, self.instance_type, None, {}, {})
 
5991
 
 
5992
    def test_reschedule_false(self):
 
5993
        """Original exception should be raised if the resize is not
 
5994
        rescheduled.
 
5995
        """
 
5996
        method_args = (None, self.instance, self.instance_type, None, None,
 
5997
                None)
 
5998
        self.mox.StubOutWithMock(self.compute, "_reschedule")
 
5999
 
 
6000
        self.compute._reschedule(self.context, None, None, self.instance_uuid,
 
6001
                self.compute.scheduler_rpcapi.prep_resize, method_args,
 
6002
                task_states.RESIZE_PREP).AndReturn(False)
 
6003
        self.mox.ReplayAll()
 
6004
 
 
6005
        try:
 
6006
            raise test.TestingException("Original")
 
6007
        except Exception:
 
6008
            self.assertRaises(test.TestingException,
 
6009
                    self.compute._reschedule_resize_or_reraise, self.context,
 
6010
                    None, self.instance, self.instance_type, None, {}, {})
 
6011
 
 
6012
    def test_reschedule_true(self):
 
6013
        """If rescheduled, the original resize exception should be logged"""
 
6014
        method_args = (self.instance, self.instance_type, None, {}, {}, None)
 
6015
        try:
 
6016
            raise test.TestingException("Original")
 
6017
        except Exception:
 
6018
            exc_info = sys.exc_info()
 
6019
 
 
6020
            self.mox.StubOutWithMock(self.compute, "_reschedule")
 
6021
            self.mox.StubOutWithMock(self.compute, "_log_original_error")
 
6022
            self.compute._reschedule(self.context, {}, {},
 
6023
                    self.instance_uuid,
 
6024
                    self.compute.scheduler_rpcapi.prep_resize, method_args,
 
6025
                    task_states.RESIZE_PREP).AndReturn(True)
 
6026
 
 
6027
            self.compute._log_original_error(exc_info, self.instance_uuid)
 
6028
            self.mox.ReplayAll()
 
6029
 
 
6030
            self.compute._reschedule_resize_or_reraise(self.context, None,
 
6031
                    self.instance, self.instance_type, None, {}, {})
 
6032
 
 
6033
 
 
6034
class ComputeInactiveImageTestCase(BaseTestCase):
 
6035
    def setUp(self):
 
6036
        super(ComputeInactiveImageTestCase, self).setUp()
 
6037
 
 
6038
        def fake_show(meh, context, id):
 
6039
            return {'id': id, 'min_disk': None, 'min_ram': None,
 
6040
                    'name': 'fake_name',
 
6041
                    'status': 'deleted',
 
6042
                    'properties': {'kernel_id': 'fake_kernel_id',
 
6043
                                   'ramdisk_id': 'fake_ramdisk_id',
 
6044
                                   'something_else': 'meow'}}
 
6045
 
 
6046
        fake_image.stub_out_image_service(self.stubs)
 
6047
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
 
6048
        self.compute_api = compute.API()
 
6049
 
 
6050
    def test_create_instance_with_deleted_image(self):
 
6051
        """Make sure we can't start an instance with a deleted image."""
 
6052
        inst_type = instance_types.get_instance_type_by_name('m1.tiny')
 
6053
        self.assertRaises(exception.ImageNotActive,
 
6054
                          self.compute_api.create,
 
6055
                          self.context, inst_type, None)