360
374
#check failed to schedule --> terminate
361
375
instance_uuid = self._create_instance(params={'vm_state':
362
376
vm_states.ERROR})
363
self.compute.terminate_instance(self.context, instance_uuid)
377
inst_ref = db.instance_get_by_uuid(elevated, instance_uuid)
378
instance = jsonutils.to_primitive(inst_ref)
379
self.compute.terminate_instance(self.context, instance=instance)
364
380
self.assertRaises(exception.InstanceNotFound, db.instance_get_by_uuid,
365
381
elevated, instance_uuid)
367
383
def test_run_terminate(self):
368
384
"""Make sure it is possible to run and terminate instance"""
369
instance = self._create_fake_instance()
371
self.compute.run_instance(self.context, instance['uuid'])
373
instances = db.instance_get_all(context.get_admin_context())
374
LOG.info(_("Running instances: %s"), instances)
375
self.assertEqual(len(instances), 1)
377
self.compute.terminate_instance(self.context, instance['uuid'])
385
instance = jsonutils.to_primitive(self._create_fake_instance())
387
self.compute.run_instance(self.context, instance=instance)
389
instances = db.instance_get_all(context.get_admin_context())
390
LOG.info(_("Running instances: %s"), instances)
391
self.assertEqual(len(instances), 1)
393
self.compute.terminate_instance(self.context, instance=instance)
395
instances = db.instance_get_all(context.get_admin_context())
396
LOG.info(_("After terminating instances: %s"), instances)
397
self.assertEqual(len(instances), 0)
399
def test_terminate_no_network(self):
400
# This is as reported in LP bug 1008875
401
instance = jsonutils.to_primitive(self._create_fake_instance())
403
self.compute.run_instance(self.context, instance=instance)
405
instances = db.instance_get_all(context.get_admin_context())
406
LOG.info(_("Running instances: %s"), instances)
407
self.assertEqual(len(instances), 1)
409
# Make it look like this is no instance
410
self.mox.StubOutWithMock(self.compute, '_get_instance_nw_info')
411
self.compute._get_instance_nw_info(
413
mox.IgnoreArg()).AndRaise(exception.NetworkNotFound())
416
self.compute.terminate_instance(self.context, instance=instance)
379
418
instances = db.instance_get_all(context.get_admin_context())
380
419
LOG.info(_("After terminating instances: %s"), instances)
400
439
def test_stop(self):
401
440
"""Ensure instance can be stopped"""
402
instance = self._create_fake_instance()
403
instance_uuid = instance['uuid']
404
self.compute.run_instance(self.context, instance_uuid)
405
self.compute.stop_instance(self.context, instance_uuid)
406
self.compute.terminate_instance(self.context, instance_uuid)
441
instance = jsonutils.to_primitive(self._create_fake_instance())
442
self.compute.run_instance(self.context, instance=instance)
443
self.compute.stop_instance(self.context, instance=instance)
444
self.compute.terminate_instance(self.context, instance=instance)
408
446
def test_start(self):
409
447
"""Ensure instance can be started"""
410
instance = self._create_fake_instance()
411
instance_uuid = instance['uuid']
412
self.compute.run_instance(self.context, instance_uuid)
413
self.compute.stop_instance(self.context, instance_uuid)
414
self.compute.start_instance(self.context, instance_uuid)
415
self.compute.terminate_instance(self.context, instance_uuid)
448
instance = jsonutils.to_primitive(self._create_fake_instance())
449
self.compute.run_instance(self.context, instance=instance)
450
self.compute.stop_instance(self.context, instance=instance)
451
self.compute.start_instance(self.context, instance=instance)
452
self.compute.terminate_instance(self.context, instance=instance)
417
454
def test_rescue(self):
418
455
"""Ensure instance can be rescued and unrescued"""
431
469
self.stubs.Set(nova.virt.fake.FakeDriver, 'unrescue',
434
instance = self._create_fake_instance()
472
instance = jsonutils.to_primitive(self._create_fake_instance())
435
473
instance_uuid = instance['uuid']
436
self.compute.run_instance(self.context, instance_uuid)
437
self.compute.rescue_instance(self.context, instance_uuid)
438
self.assertTrue(called['rescued'])
439
self.compute.unrescue_instance(self.context, instance_uuid)
440
self.assertTrue(called['unrescued'])
441
self.compute.terminate_instance(self.context, instance_uuid)
474
self.compute.run_instance(self.context, instance=instance)
476
# Make sure these methods work with both instance and instance_uuid
478
self.compute.rescue_instance(self.context, instance=instance)
479
self.assertTrue(called['rescued'])
480
self.compute.unrescue_instance(self.context, instance=instance)
481
self.assertTrue(called['unrescued'])
483
self.compute.rescue_instance(self.context, instance_uuid=instance_uuid)
484
self.assertTrue(called['rescued'])
485
self.compute.unrescue_instance(self.context,
486
instance_uuid=instance_uuid)
487
self.assertTrue(called['unrescued'])
489
self.compute.terminate_instance(self.context, instance=instance)
443
491
def test_power_on(self):
444
492
"""Ensure instance can be powered on"""
469
516
self.stubs.Set(nova.virt.fake.FakeDriver, 'power_off',
470
517
fake_driver_power_off)
472
instance = self._create_fake_instance()
473
instance_uuid = instance['uuid']
474
self.compute.run_instance(self.context, instance_uuid)
475
self.compute.power_off_instance(self.context, instance_uuid)
519
instance = jsonutils.to_primitive(self._create_fake_instance())
520
self.compute.run_instance(self.context, instance=instance)
521
self.compute.power_off_instance(self.context, instance=instance)
476
522
self.assertTrue(called['power_off'])
477
self.compute.terminate_instance(self.context, instance_uuid)
523
self.compute.terminate_instance(self.context, instance=instance)
479
525
def test_pause(self):
480
526
"""Ensure instance can be paused and unpaused"""
481
instance = self._create_fake_instance()
482
instance_uuid = instance['uuid']
483
self.compute.run_instance(self.context, instance_uuid)
484
self.compute.pause_instance(self.context, instance_uuid)
485
self.compute.unpause_instance(self.context, instance_uuid)
486
self.compute.terminate_instance(self.context, instance_uuid)
527
instance = jsonutils.to_primitive(self._create_fake_instance())
528
self.compute.run_instance(self.context, instance=instance)
529
self.compute.pause_instance(self.context, instance=instance)
530
self.compute.unpause_instance(self.context, instance=instance)
531
self.compute.terminate_instance(self.context, instance=instance)
488
533
def test_suspend(self):
489
534
"""ensure instance can be suspended and resumed"""
490
instance = self._create_fake_instance()
535
instance = jsonutils.to_primitive(self._create_fake_instance())
536
self.compute.run_instance(self.context, instance=instance)
537
self.compute.suspend_instance(self.context, instance=instance)
538
self.compute.resume_instance(self.context, instance=instance)
539
self.compute.terminate_instance(self.context, instance=instance)
541
def test_suspend_error(self):
542
"""Ensure vm_state is ERROR when suspend error occurs"""
543
def fake(*args, **kwargs):
544
raise test.TestingException()
545
self.stubs.Set(self.compute.driver, 'suspend', fake)
547
instance = jsonutils.to_primitive(self._create_fake_instance())
491
548
instance_uuid = instance['uuid']
492
self.compute.run_instance(self.context, instance_uuid)
493
self.compute.suspend_instance(self.context, instance_uuid)
494
self.compute.resume_instance(self.context, instance_uuid)
495
self.compute.terminate_instance(self.context, instance_uuid)
549
self.compute.run_instance(self.context, instance=instance)
550
self.assertRaises(test.TestingException,
551
self.compute.suspend_instance,
554
instance = db.instance_get_by_uuid(self.context, instance_uuid)
555
self.assertEqual(instance['vm_state'], vm_states.ERROR)
556
self.compute.terminate_instance(self.context, instance=instance)
497
558
def test_rebuild(self):
498
559
"""Ensure instance can be rebuilt"""
499
instance = self._create_fake_instance()
500
instance_uuid = instance['uuid']
560
instance = jsonutils.to_primitive(self._create_fake_instance())
501
561
image_ref = instance['image_ref']
503
self.compute.run_instance(self.context, instance_uuid)
504
self.compute.rebuild_instance(self.context, instance_uuid,
505
image_ref, image_ref)
506
self.compute.terminate_instance(self.context, instance_uuid)
563
self.compute.run_instance(self.context, instance=instance)
564
self.compute.rebuild_instance(self.context, image_ref, image_ref,
566
self.compute.terminate_instance(self.context, instance=instance)
508
568
def test_rebuild_launch_time(self):
509
569
"""Ensure instance can be rebuilt"""
510
570
old_time = datetime.datetime(2012, 4, 1)
511
571
cur_time = datetime.datetime(2012, 12, 21, 12, 21)
512
572
timeutils.set_time_override(old_time)
513
instance = self._create_fake_instance()
573
instance = jsonutils.to_primitive(self._create_fake_instance())
514
574
instance_uuid = instance['uuid']
515
575
image_ref = instance['image_ref']
517
self.compute.run_instance(self.context, instance_uuid)
577
self.compute.run_instance(self.context, instance=instance)
518
578
timeutils.set_time_override(cur_time)
519
self.compute.rebuild_instance(self.context, instance_uuid,
520
image_ref, image_ref)
579
self.compute.rebuild_instance(self.context, image_ref, image_ref,
521
581
instance = db.instance_get_by_uuid(self.context, instance_uuid)
522
582
self.assertEquals(cur_time, instance['launched_at'])
523
self.compute.terminate_instance(self.context, instance_uuid)
583
self.compute.terminate_instance(self.context,
584
instance=jsonutils.to_primitive(instance))
525
586
def test_reboot_soft(self):
526
587
"""Ensure instance can be soft rebooted"""
527
instance = self._create_fake_instance()
528
self.compute.run_instance(self.context, instance['uuid'])
588
instance = jsonutils.to_primitive(self._create_fake_instance())
589
self.compute.run_instance(self.context, instance=instance)
529
590
db.instance_update(self.context, instance['uuid'],
530
591
{'task_state': task_states.REBOOTING})
532
593
reboot_type = "SOFT"
533
self.compute.reboot_instance(self.context, instance['uuid'],
594
self.compute.reboot_instance(self.context,
596
reboot_type=reboot_type)
536
598
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
537
599
self.assertEqual(inst_ref['power_state'], power_state.RUNNING)
538
600
self.assertEqual(inst_ref['task_state'], None)
540
self.compute.terminate_instance(self.context, inst_ref['uuid'])
602
self.compute.terminate_instance(self.context,
603
instance=jsonutils.to_primitive(inst_ref))
542
605
def test_reboot_hard(self):
543
606
"""Ensure instance can be hard rebooted"""
544
instance = self._create_fake_instance()
545
self.compute.run_instance(self.context, instance['uuid'])
607
instance = jsonutils.to_primitive(self._create_fake_instance())
608
self.compute.run_instance(self.context, instance=instance)
546
609
db.instance_update(self.context, instance['uuid'],
547
610
{'task_state': task_states.REBOOTING_HARD})
549
612
reboot_type = "HARD"
550
self.compute.reboot_instance(self.context, instance['uuid'],
613
self.compute.reboot_instance(self.context, instance=instance,
614
reboot_type=reboot_type)
553
616
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
554
617
self.assertEqual(inst_ref['power_state'], power_state.RUNNING)
555
618
self.assertEqual(inst_ref['task_state'], None)
557
self.compute.terminate_instance(self.context, inst_ref['uuid'])
620
self.compute.terminate_instance(self.context,
621
instance=jsonutils.to_primitive(inst_ref))
559
623
def test_set_admin_password(self):
560
624
"""Ensure instance can have its admin password set"""
561
instance = self._create_fake_instance()
562
self.compute.run_instance(self.context, instance['uuid'])
625
instance = jsonutils.to_primitive(self._create_fake_instance())
626
self.compute.run_instance(self.context, instance=instance)
563
627
db.instance_update(self.context, instance['uuid'],
564
628
{'task_state': task_states.UPDATING_PASSWORD})
567
631
self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
568
632
self.assertEqual(inst_ref['task_state'], task_states.UPDATING_PASSWORD)
570
self.compute.set_admin_password(self.context, instance['uuid'])
634
self.compute.set_admin_password(self.context, instance=instance)
572
636
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
573
637
self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
574
638
self.assertEqual(inst_ref['task_state'], None)
576
self.compute.terminate_instance(self.context, inst_ref['uuid'])
640
self.compute.terminate_instance(self.context,
641
instance=jsonutils.to_primitive(inst_ref))
578
643
def test_set_admin_password_bad_state(self):
579
644
"""Test setting password while instance is rebuilding."""
580
instance = self._create_fake_instance()
581
self.compute.run_instance(self.context, instance['uuid'])
645
instance = jsonutils.to_primitive(self._create_fake_instance())
646
self.compute.run_instance(self.context, instance=instance)
582
647
db.instance_update(self.context, instance['uuid'], {
583
648
"power_state": power_state.NOSTATE,
585
instance = db.instance_get_by_uuid(self.context, instance['uuid'])
650
instance = jsonutils.to_primitive(db.instance_get_by_uuid(
651
self.context, instance['uuid']))
587
653
self.assertEqual(instance['power_state'], power_state.NOSTATE)
628
695
#error raised from the driver should not reveal internal information
629
696
#so a new error is raised
630
self.assertRaises(exception.NovaException,
697
self.assertRaises(exception.InstancePasswordSetFailed,
631
698
self.compute.set_admin_password,
632
self.context, instance['uuid'])
700
instance=jsonutils.to_primitive(inst_ref))
634
702
inst_ref = db.instance_get_by_uuid(self.context, instance['uuid'])
635
self.assertEqual(inst_ref['vm_state'], vm_states.ERROR)
636
self.assertEqual(inst_ref['task_state'], task_states.UPDATING_PASSWORD)
638
self.compute.terminate_instance(self.context, inst_ref['uuid'])
703
self.assertEqual(inst_ref['vm_state'], expected_vm_state)
704
self.assertEqual(inst_ref['task_state'], expected_task_state)
706
self.compute.terminate_instance(self.context,
707
instance=jsonutils.to_primitive(inst_ref))
709
def test_set_admin_password_driver_not_authorized(self):
711
Ensure expected exception is raised if set_admin_password not
714
exc = exception.NotAuthorized(_('Internal error'))
715
self._do_test_set_admin_password_driver_error(exc,
719
def test_set_admin_password_driver_not_implemented(self):
721
Ensure expected exception is raised if set_admin_password not
722
implemented by driver.
724
exc = NotImplementedError()
725
self._do_test_set_admin_password_driver_error(exc,
640
729
def test_inject_file(self):
641
730
"""Ensure we can write a file to an instance"""
666
755
self.stubs.Set(nova.virt.fake.FakeDriver, 'inject_network_info',
667
756
fake_driver_inject_network)
669
instance = self._create_fake_instance()
670
instance_uuid = instance['uuid']
671
self.compute.run_instance(self.context, instance_uuid)
672
self.compute.inject_network_info(self.context, instance_uuid)
758
instance = jsonutils.to_primitive(self._create_fake_instance())
759
self.compute.run_instance(self.context, instance=instance)
760
self.compute.inject_network_info(self.context, instance=instance)
673
761
self.assertTrue(called['inject'])
674
self.compute.terminate_instance(self.context, instance_uuid)
762
self.compute.terminate_instance(self.context, instance=instance)
676
764
def test_reset_network(self):
677
765
"""Ensure we can reset networking on an instance"""
678
called = {'reset': False}
766
called = {'count': 0}
680
768
def fake_driver_reset_network(self, instance):
681
called['reset'] = True
683
771
self.stubs.Set(nova.virt.fake.FakeDriver, 'reset_network',
684
772
fake_driver_reset_network)
686
instance = self._create_fake_instance()
774
instance = jsonutils.to_primitive(self._create_fake_instance())
687
775
instance_uuid = instance['uuid']
688
self.compute.run_instance(self.context, instance_uuid)
689
self.compute.reset_network(self.context, instance_uuid)
690
self.assertTrue(called['reset'])
691
self.compute.terminate_instance(self.context, instance_uuid)
693
def test_agent_update(self):
694
"""Ensure instance can have its agent updated"""
695
called = {'agent_update': False}
697
def fake_driver_agent_update(self2, instance, url, md5hash):
698
called['agent_update'] = True
699
self.assertEqual(url, 'http://fake/url/')
700
self.assertEqual(md5hash, 'fakehash')
702
self.stubs.Set(nova.virt.fake.FakeDriver, 'agent_update',
703
fake_driver_agent_update)
705
instance = self._create_fake_instance()
706
self.compute.run_instance(self.context, instance['uuid'])
707
self.compute.agent_update(self.context, instance['uuid'],
708
'http://fake/url/', 'fakehash')
709
self.assertTrue(called['agent_update'])
710
self.compute.terminate_instance(self.context, instance['uuid'])
776
self.compute.run_instance(self.context, instance=instance)
778
# Make sure it works with both an instance and instance_uuid
779
self.compute.reset_network(self.context, instance=instance)
780
self.compute.reset_network(self.context, instance_uuid=instance_uuid)
782
self.assertEqual(called['count'], 2)
784
self.compute.terminate_instance(self.context, instance=instance)
712
786
def test_snapshot(self):
713
787
"""Ensure instance can be snapshotted"""
714
instance = self._create_fake_instance()
788
instance = jsonutils.to_primitive(self._create_fake_instance())
715
789
instance_uuid = instance['uuid']
716
790
name = "myfakesnapshot"
717
self.compute.run_instance(self.context, instance_uuid)
718
self.compute.snapshot_instance(self.context, instance_uuid, name)
719
self.compute.terminate_instance(self.context, instance_uuid)
791
self.compute.run_instance(self.context, instance=instance)
792
self.compute.snapshot_instance(self.context, name, instance=instance)
793
self.compute.terminate_instance(self.context, instance=instance)
721
795
def test_snapshot_fails(self):
722
796
"""Ensure task_state is set to None if snapshot fails"""
750
824
def test_console_output(self):
751
825
"""Make sure we can get console output from instance"""
752
instance = self._create_fake_instance()
753
self.compute.run_instance(self.context, instance['uuid'])
826
instance = jsonutils.to_primitive(self._create_fake_instance())
827
self.compute.run_instance(self.context, instance=instance)
755
829
output = self.compute.get_console_output(self.context,
757
831
self.assertEqual(output, 'FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE')
758
self.compute.terminate_instance(self.context, instance['uuid'])
832
self.compute.terminate_instance(self.context, instance=instance)
760
834
def test_console_output_tail(self):
761
835
"""Make sure we can get console output from instance"""
762
instance = self._create_fake_instance()
763
self.compute.run_instance(self.context, instance['uuid'])
836
instance = jsonutils.to_primitive(self._create_fake_instance())
837
self.compute.run_instance(self.context, instance=instance)
765
839
output = self.compute.get_console_output(self.context,
840
instance=instance, tail_length=2)
768
841
self.assertEqual(output, 'ANOTHER\nLAST LINE')
769
self.compute.terminate_instance(self.context, instance['uuid'])
842
self.compute.terminate_instance(self.context, instance=instance)
771
844
def test_novnc_vnc_console(self):
772
845
"""Make sure we can a vnc console for an instance."""
773
instance = self._create_fake_instance()
774
self.compute.run_instance(self.context, instance['uuid'])
776
console = self.compute.get_vnc_console(self.context,
779
self.assert_(console)
780
self.compute.terminate_instance(self.context, instance['uuid'])
846
instance = jsonutils.to_primitive(self._create_fake_instance())
847
self.compute.run_instance(self.context, instance=instance)
849
# Try with the full instance
850
console = self.compute.get_vnc_console(self.context, 'novnc',
852
self.assert_(console)
854
# Also make sure it still works with just the instance UUID
855
console = self.compute.get_vnc_console(self.context, 'novnc',
856
instance_uuid=instance['uuid'])
857
self.assert_(console)
859
self.compute.terminate_instance(self.context, instance=instance)
782
861
def test_xvpvnc_vnc_console(self):
783
862
"""Make sure we can a vnc console for an instance."""
784
instance = self._create_fake_instance()
785
self.compute.run_instance(self.context, instance['uuid'])
863
instance = jsonutils.to_primitive(self._create_fake_instance())
864
self.compute.run_instance(self.context, instance=instance)
787
console = self.compute.get_vnc_console(self.context,
866
console = self.compute.get_vnc_console(self.context, 'xvpvnc',
790
868
self.assert_(console)
791
self.compute.terminate_instance(self.context, instance['uuid'])
869
self.compute.terminate_instance(self.context, instance=instance)
793
871
def test_invalid_vnc_console_type(self):
794
872
"""Raise useful error if console type is an unrecognised string"""
795
instance = self._create_fake_instance()
796
self.compute.run_instance(self.context, instance['uuid'])
873
instance = jsonutils.to_primitive(self._create_fake_instance())
874
self.compute.run_instance(self.context, instance=instance)
798
876
self.assertRaises(exception.ConsoleTypeInvalid,
799
877
self.compute.get_vnc_console,
803
self.compute.terminate_instance(self.context, instance['uuid'])
878
self.context, 'invalid', instance=instance)
879
self.compute.terminate_instance(self.context, instance=instance)
805
881
def test_missing_vnc_console_type(self):
806
882
"""Raise useful error is console type is None"""
807
instance = self._create_fake_instance()
808
self.compute.run_instance(self.context, instance['uuid'])
883
instance = jsonutils.to_primitive(self._create_fake_instance())
884
self.compute.run_instance(self.context, instance=instance)
810
886
self.assertRaises(exception.ConsoleTypeInvalid,
811
887
self.compute.get_vnc_console,
815
self.compute.terminate_instance(self.context, instance['uuid'])
888
self.context, None, instance=instance)
889
self.compute.terminate_instance(self.context, instance=instance)
817
891
def test_diagnostics(self):
818
892
"""Make sure we can get diagnostics for an instance."""
819
instance = self._create_fake_instance()
820
self.compute.run_instance(self.context, instance['uuid'])
822
diagnostics = self.compute.get_diagnostics(self.context,
824
self.assertEqual(diagnostics, 'FAKE_DIAGNOSTICS')
825
self.compute.terminate_instance(self.context, instance['uuid'])
893
instance = jsonutils.to_primitive(self._create_fake_instance())
894
self.compute.run_instance(self.context, instance=instance)
896
diagnostics = self.compute.get_diagnostics(self.context,
897
instance_uuid=instance['uuid'])
898
self.assertEqual(diagnostics, 'FAKE_DIAGNOSTICS')
900
diagnostics = self.compute.get_diagnostics(self.context,
902
self.assertEqual(diagnostics, 'FAKE_DIAGNOSTICS')
903
self.compute.terminate_instance(self.context, instance=instance)
827
905
def test_add_fixed_ip_usage_notification(self):
828
906
def dummy(*args, **kwargs):
855
934
self.stubs.Set(nova.compute.manager.ComputeManager,
856
935
'reset_network', dummy)
858
instance = self._create_fake_instance()
937
instance = jsonutils.to_primitive(self._create_fake_instance())
859
938
instance_uuid = instance['uuid']
861
940
self.assertEquals(len(test_notifier.NOTIFICATIONS), 0)
862
self.compute.remove_fixed_ip_from_instance(self.context,
941
self.compute.remove_fixed_ip_from_instance(self.context, 1,
866
944
self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
867
self.compute.terminate_instance(self.context, instance_uuid)
945
self.compute.terminate_instance(self.context, instance=instance)
869
947
def test_run_instance_usage_notification(self):
870
"""Ensure run instance generates apropriate usage notification"""
871
inst_ref = self._create_fake_instance()
872
instance_uuid = inst_ref['uuid']
873
self.compute.run_instance(self.context, instance_uuid)
948
"""Ensure run instance generates appropriate usage notification"""
949
instance = jsonutils.to_primitive(self._create_fake_instance())
950
instance_uuid = instance['uuid']
951
self.compute.run_instance(self.context, instance=instance)
874
952
self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
875
953
inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
876
954
msg = test_notifier.NOTIFICATIONS[0]
877
955
self.assertEquals(msg['event_type'], 'compute.instance.create.start')
956
self.assertEquals(msg['payload']['image_name'], 'fake_name')
878
957
# The last event is the one with the sugar in it.
879
958
msg = test_notifier.NOTIFICATIONS[1]
880
959
self.assertEquals(msg['priority'], 'INFO')
881
960
self.assertEquals(msg['event_type'], 'compute.instance.create.end')
882
961
payload = msg['payload']
883
962
self.assertEquals(payload['tenant_id'], self.project_id)
963
self.assertEquals(payload['image_name'], 'fake_name')
884
964
self.assertEquals(payload['user_id'], self.user_id)
885
965
self.assertEquals(payload['instance_id'], inst_ref.uuid)
886
966
self.assertEquals(payload['instance_type'], 'm1.tiny')
1002
1084
self.assertRaises(rpc.common.RemoteError,
1003
1085
self.compute.run_instance,
1086
self.context, instance=instance)
1007
self.compute.terminate_instance(self.context, instance['uuid'])
1088
self.compute.terminate_instance(self.context, instance=instance)
1009
1090
def test_get_lock(self):
1010
instance = self._create_fake_instance()
1011
self.assertFalse(self.compute.get_lock(self.context, instance['uuid']))
1091
instance = jsonutils.to_primitive(self._create_fake_instance())
1092
self.assertFalse(self.compute._get_lock(self.context,
1012
1094
db.instance_update(self.context, instance['uuid'], {'locked': True})
1013
self.assertTrue(self.compute.get_lock(self.context, instance['uuid']))
1095
self.assertTrue(self.compute._get_lock(self.context, instance['uuid']))
1015
1097
def test_lock(self):
1016
1098
"""ensure locked instance cannot be changed"""
1017
instance = self._create_fake_instance()
1099
instance = jsonutils.to_primitive(self._create_fake_instance())
1018
1100
instance_uuid = instance['uuid']
1019
self.compute.run_instance(self.context, instance_uuid)
1101
self.compute.run_instance(self.context, instance=instance)
1021
1103
non_admin_context = context.RequestContext(None,
1023
1105
is_admin=False)
1025
# decorator should return False (fail) with locked nonadmin context
1026
self.compute.lock_instance(self.context, instance_uuid)
1027
ret_val = self.compute.reboot_instance(non_admin_context,
1029
self.assertEqual(ret_val, False)
1031
# decorator should return None (success) with unlocked nonadmin context
1032
self.compute.unlock_instance(self.context, instance_uuid)
1033
ret_val = self.compute.reboot_instance(non_admin_context,
1035
self.assertEqual(ret_val, None)
1037
self.compute.terminate_instance(self.context, instance_uuid)
1107
def check_task_state(task_state):
1108
instance = db.instance_get_by_uuid(self.context, instance_uuid)
1109
self.assertEqual(instance['task_state'], task_state)
1111
instance = db.instance_update(self.context, instance_uuid,
1112
{'task_state': task_states.REBOOTING})
1114
# should fail with locked nonadmin context, task_state won't be cleared
1115
self.compute_api.lock(self.context, instance)
1116
instance = db.instance_get_by_uuid(self.context, instance_uuid)
1117
self.compute.reboot_instance(non_admin_context,
1118
instance=jsonutils.to_primitive(instance))
1119
check_task_state(task_states.REBOOTING)
1121
# should succeed with unlocked nonadmin context, task_state cleared
1122
self.compute_api.unlock(self.context, instance)
1123
instance = db.instance_get_by_uuid(self.context, instance_uuid)
1124
self.compute.reboot_instance(non_admin_context,
1125
instance=jsonutils.to_primitive(instance))
1126
check_task_state(None)
1128
self.compute.terminate_instance(self.context,
1129
instance=jsonutils.to_primitive(instance))
1131
def _test_state_revert(self, operation, pre_task_state):
1132
instance = self._create_fake_instance()
1133
self.compute.run_instance(self.context, instance=instance)
1135
# The API would have set task_state, so do that here to test
1136
# that the state gets reverted on failure
1137
db.instance_update(self.context, instance['uuid'],
1138
{"task_state": pre_task_state})
1142
ret_val = getattr(self.compute, operation)(self.context,
1146
self.assertTrue(raised)
1148
# Fetch the instance's task_state and make sure it went to None
1149
instance = db.instance_get_by_uuid(self.context, instance['uuid'])
1150
self.assertEqual(instance["task_state"], None)
1152
def test_state_revert(self):
1153
"""ensure that task_state is reverted after a failed operation"""
1155
("reboot_instance", task_states.REBOOTING),
1156
("stop_instance", task_states.STOPPING),
1157
("start_instance", task_states.STARTING),
1158
("terminate_instance", task_states.DELETING),
1159
("power_off_instance", task_states.POWERING_OFF),
1160
("power_on_instance", task_states.POWERING_ON),
1161
("rebuild_instance", task_states.REBUILDING),
1162
("set_admin_password", task_states.UPDATING_PASSWORD),
1163
("rescue_instance", task_states.RESCUING),
1164
("unrescue_instance", task_states.UNRESCUING),
1165
("revert_resize", task_states.RESIZE_REVERTING),
1166
("prep_resize", task_states.RESIZE_PREP),
1167
("resize_instance", task_states.RESIZE_PREP),
1168
("pause_instance", task_states.PAUSING),
1169
("unpause_instance", task_states.UNPAUSING),
1170
("suspend_instance", task_states.SUSPENDING),
1171
("resume_instance", task_states.RESUMING),
1174
def _get_an_exception(*args, **kwargs):
1175
raise Exception("This fails every single time!")
1177
self.stubs.Set(self.compute, "_get_lock", _get_an_exception)
1178
for operation, pre_state in actions:
1179
self._test_state_revert(operation, pre_state)
1181
def _ensure_quota_reservations_committed(self):
1182
"""Mock up commit of quota reservations"""
1183
reservations = list('fake_res')
1184
self.mox.StubOutWithMock(nova.quota.QUOTAS, 'commit')
1185
nova.quota.QUOTAS.commit(mox.IgnoreArg(), reservations)
1186
self.mox.ReplayAll()
1189
def _ensure_quota_reservations_rolledback(self):
1190
"""Mock up rollback of quota reservations"""
1191
reservations = list('fake_res')
1192
self.mox.StubOutWithMock(nova.quota.QUOTAS, 'rollback')
1193
nova.quota.QUOTAS.rollback(mox.IgnoreArg(), reservations)
1194
self.mox.ReplayAll()
1039
1197
def test_finish_resize(self):
1040
1198
"""Contrived test to ensure finish_resize doesn't raise anything"""
1045
1203
self.stubs.Set(self.compute.driver, 'finish_migration', fake)
1205
reservations = self._ensure_quota_reservations_committed()
1047
1207
context = self.context.elevated()
1048
instance = self._create_fake_instance()
1049
self.compute.prep_resize(context, instance['uuid'], 1, {},
1050
filter_properties={})
1208
instance = jsonutils.to_primitive(self._create_fake_instance())
1209
self.compute.prep_resize(context, instance=instance, instance_type={},
1051
1211
migration_ref = db.migration_get_by_instance_and_status(context,
1052
1212
instance['uuid'], 'pre-migrating')
1053
self.compute.finish_resize(context, instance['uuid'],
1054
int(migration_ref['id']), {}, {})
1055
self.compute.terminate_instance(self.context, instance['uuid'])
1213
self.compute.finish_resize(context,
1214
migration_id=int(migration_ref['id']),
1215
disk_info={}, image={}, instance=instance,
1216
reservations=reservations)
1217
self.compute.terminate_instance(self.context, instance=instance)
1057
1219
def test_finish_resize_handles_error(self):
1058
1220
"""Make sure we don't leave the instance in RESIZE on error"""
1066
1228
self.stubs.Set(self.compute.driver, 'finish_migration', throw_up)
1230
reservations = self._ensure_quota_reservations_rolledback()
1068
1232
context = self.context.elevated()
1069
instance = self._create_fake_instance()
1070
self.compute.prep_resize(context, instance['uuid'], 1, {},
1071
filter_properties={})
1233
instance = jsonutils.to_primitive(self._create_fake_instance())
1234
self.compute.prep_resize(context, instance=instance, instance_type={},
1235
image={}, reservations=reservations)
1072
1236
migration_ref = db.migration_get_by_instance_and_status(context,
1073
1237
instance['uuid'], 'pre-migrating')
1075
1239
self.assertRaises(test.TestingException, self.compute.finish_resize,
1076
context, instance['uuid'],
1077
int(migration_ref['id']), {}, {})
1240
context, migration_id=int(migration_ref['id']),
1241
disk_info={}, image={}, instance=instance,
1242
reservations=reservations)
1079
1244
instance = db.instance_get_by_uuid(context, instance['uuid'])
1080
1245
self.assertEqual(instance['vm_state'], vm_states.ERROR)
1081
self.compute.terminate_instance(self.context, instance['uuid'])
1246
self.compute.terminate_instance(self.context,
1247
instance=jsonutils.to_primitive(instance))
1083
1249
def test_rebuild_instance_notification(self):
1084
1250
"""Ensure notifications on instance migrate/resize"""
1085
1251
old_time = datetime.datetime(2012, 4, 1)
1086
1252
cur_time = datetime.datetime(2012, 12, 21, 12, 21)
1087
1253
timeutils.set_time_override(old_time)
1088
inst_ref = self._create_fake_instance()
1089
self.compute.run_instance(self.context, inst_ref['uuid'])
1254
inst_ref = jsonutils.to_primitive(self._create_fake_instance())
1255
self.compute.run_instance(self.context, instance=inst_ref)
1090
1256
timeutils.set_time_override(cur_time)
1092
1258
test_notifier.NOTIFICATIONS = []
1132
1304
self.assertTrue('launched_at' in payload)
1133
1305
self.assertEqual(payload['launched_at'], str(cur_time))
1134
1306
self.assertEquals(payload['image_ref_url'], new_image_ref_url)
1135
self.compute.terminate_instance(self.context, inst_ref['uuid'])
1307
self.compute.terminate_instance(self.context,
1308
instance=jsonutils.to_primitive(inst_ref))
1137
1310
def test_finish_resize_instance_notification(self):
1138
1311
"""Ensure notifications on instance migrate/resize"""
1139
1312
old_time = datetime.datetime(2012, 4, 1)
1140
1313
cur_time = datetime.datetime(2012, 12, 21, 12, 21)
1141
1314
timeutils.set_time_override(old_time)
1142
instance = self._create_fake_instance()
1315
instance = jsonutils.to_primitive(self._create_fake_instance())
1143
1316
context = self.context.elevated()
1144
1317
old_type_id = instance_types.get_instance_type_by_name(
1145
1318
'm1.tiny')['id']
1146
new_type_id = instance_types.get_instance_type_by_name(
1148
self.compute.run_instance(self.context, instance['uuid'])
1319
new_type = instance_types.get_instance_type_by_name('m1.small')
1320
new_type = jsonutils.to_primitive(new_type)
1321
new_type_id = new_type['id']
1322
self.compute.run_instance(self.context, instance=instance)
1150
1324
db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1151
self.compute.prep_resize(context, instance['uuid'], new_type_id, {},
1152
filter_properties={})
1325
self.compute.prep_resize(context, instance=instance,
1326
instance_type=new_type, image={})
1153
1327
migration_ref = db.migration_get_by_instance_and_status(context,
1154
1328
instance['uuid'],
1155
1329
'pre-migrating')
1156
self.compute.resize_instance(context, instance['uuid'],
1157
migration_ref['id'], {})
1330
self.compute.resize_instance(context, migration_ref['id'], {},
1158
1332
timeutils.set_time_override(cur_time)
1159
1333
test_notifier.NOTIFICATIONS = []
1161
self.compute.finish_resize(context, instance['uuid'],
1162
int(migration_ref['id']), {}, {})
1335
self.compute.finish_resize(context,
1336
migration_id=int(migration_ref['id']), disk_info={}, image={},
1164
1339
self.assertEquals(len(test_notifier.NOTIFICATIONS), 2)
1165
1340
msg = test_notifier.NOTIFICATIONS[0]
1181
1356
self.assertEqual(payload['launched_at'], str(cur_time))
1182
1357
image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
1183
1358
self.assertEquals(payload['image_ref_url'], image_ref_url)
1184
self.compute.terminate_instance(context, instance['uuid'])
1359
self.compute.terminate_instance(context,
1360
instance=jsonutils.to_primitive(instance))
1186
1362
def test_resize_instance_notification(self):
1187
1363
"""Ensure notifications on instance migrate/resize"""
1188
1364
old_time = datetime.datetime(2012, 4, 1)
1189
1365
cur_time = datetime.datetime(2012, 12, 21, 12, 21)
1190
1366
timeutils.set_time_override(old_time)
1191
instance = self._create_fake_instance()
1367
instance = jsonutils.to_primitive(self._create_fake_instance())
1192
1368
context = self.context.elevated()
1194
self.compute.run_instance(self.context, instance['uuid'])
1370
self.compute.run_instance(self.context, instance=instance)
1195
1371
timeutils.set_time_override(cur_time)
1196
1372
test_notifier.NOTIFICATIONS = []
1198
1374
db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1199
self.compute.prep_resize(context, instance['uuid'], 1, {},
1200
filter_properties={})
1375
self.compute.prep_resize(context, instance=instance,
1376
instance_type={}, image={})
1201
1377
db.migration_get_by_instance_and_status(context,
1202
1378
instance['uuid'],
1203
1379
'pre-migrating')
1225
1401
self.assertTrue('launched_at' in payload)
1226
1402
image_ref_url = utils.generate_image_url(FAKE_IMAGE_REF)
1227
1403
self.assertEquals(payload['image_ref_url'], image_ref_url)
1228
self.compute.terminate_instance(context, instance['uuid'])
1404
self.compute.terminate_instance(context, instance=instance)
1230
1406
def test_prep_resize_instance_migration_error(self):
1231
1407
"""Ensure prep_resize raise a migration error"""
1232
1408
self.flags(host="foo", allow_resize_to_same_host=False)
1234
instance = self._create_fake_instance()
1410
instance = jsonutils.to_primitive(self._create_fake_instance())
1235
1411
context = self.context.elevated()
1237
self.compute.run_instance(self.context, instance['uuid'])
1238
db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1413
reservations = self._ensure_quota_reservations_rolledback()
1415
self.compute.run_instance(self.context, instance=instance)
1416
new_instance = db.instance_update(self.context, instance['uuid'],
1418
new_instance = jsonutils.to_primitive(new_instance)
1240
1420
self.assertRaises(exception.MigrationError, self.compute.prep_resize,
1241
context, instance['uuid'], 1, {})
1242
self.compute.terminate_instance(context, instance['uuid'])
1421
context, instance=new_instance,
1422
instance_type={}, image={},
1423
reservations=reservations)
1424
self.compute.terminate_instance(context, instance=new_instance)
1244
1426
def test_resize_instance_driver_error(self):
1245
1427
"""Ensure instance status set to Error on resize error"""
1250
1432
self.stubs.Set(self.compute.driver, 'migrate_disk_and_power_off',
1253
instance = self._create_fake_instance()
1435
instance = jsonutils.to_primitive(self._create_fake_instance())
1254
1436
context = self.context.elevated()
1256
self.compute.run_instance(self.context, instance['uuid'])
1438
reservations = self._ensure_quota_reservations_rolledback()
1440
self.compute.run_instance(self.context, instance=instance)
1257
1441
db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1258
self.compute.prep_resize(context, instance['uuid'], 1, {},
1259
filter_properties={})
1442
self.compute.prep_resize(context, instance=instance,
1443
instance_type={}, image={},
1444
reservations=reservations)
1260
1445
migration_ref = db.migration_get_by_instance_and_status(context,
1261
1446
instance['uuid'], 'pre-migrating')
1264
1449
self.assertRaises(test.TestingException, self.compute.resize_instance,
1265
context, instance['uuid'], migration_ref['id'], {})
1450
context, migration_ref['id'], {}, instance=instance,
1451
reservations=reservations)
1266
1452
instance = db.instance_get_by_uuid(context, instance['uuid'])
1267
1453
self.assertEqual(instance['vm_state'], vm_states.ERROR)
1269
self.compute.terminate_instance(context, instance['uuid'])
1455
self.compute.terminate_instance(context,
1456
instance=jsonutils.to_primitive(instance))
1271
1458
def test_resize_instance(self):
1272
1459
"""Ensure instance can be migrated/resized"""
1273
instance = self._create_fake_instance()
1460
instance = jsonutils.to_primitive(self._create_fake_instance())
1274
1461
context = self.context.elevated()
1276
self.compute.run_instance(self.context, instance['uuid'])
1463
self.compute.run_instance(self.context, instance=instance)
1277
1464
db.instance_update(self.context, instance['uuid'],
1278
1465
{'host': 'foo'})
1279
self.compute.prep_resize(context, instance['uuid'], 1, {},
1280
filter_properties={})
1466
self.compute.prep_resize(context, instance=instance,
1467
instance_type={}, image={})
1281
1468
migration_ref = db.migration_get_by_instance_and_status(context,
1282
1469
instance['uuid'], 'pre-migrating')
1283
self.compute.resize_instance(context, instance['uuid'],
1284
migration_ref['id'], {})
1285
self.compute.terminate_instance(context, instance['uuid'])
1470
self.compute.resize_instance(context, migration_ref['id'], {},
1472
self.compute.terminate_instance(context,
1473
instance=jsonutils.to_primitive(instance))
1287
1475
def test_finish_revert_resize(self):
1288
1476
"""Ensure that the flavor is reverted to the original on revert"""
1304
1494
inst_ref['instance_type_id'])
1305
1495
self.assertEqual(instance_type_ref['flavorid'], '1')
1307
db.instance_update(self.context, instance['uuid'], {'host': 'foo'})
1497
new_inst_ref = db.instance_update(self.context, instance['uuid'],
1309
1500
new_instance_type_ref = db.instance_type_get_by_flavor_id(context, 3)
1310
self.compute.prep_resize(context, inst_ref['uuid'],
1311
new_instance_type_ref['id'], {},
1312
filter_properties={})
1501
self.compute.prep_resize(context,
1502
instance=jsonutils.to_primitive(new_inst_ref),
1503
instance_type=jsonutils.to_primitive(new_instance_type_ref),
1504
image={}, reservations=reservations)
1314
1506
migration_ref = db.migration_get_by_instance_and_status(context,
1315
1507
inst_ref['uuid'], 'pre-migrating')
1317
self.compute.resize_instance(context, inst_ref['uuid'],
1318
migration_ref['id'], {})
1319
self.compute.finish_resize(context, inst_ref['uuid'],
1320
int(migration_ref['id']), {}, {})
1509
self.compute.resize_instance(context, migration_ref['id'], {},
1510
instance=jsonutils.to_primitive(inst_ref))
1511
self.compute.finish_resize(context,
1512
migration_id=int(migration_ref['id']), disk_info={},
1513
image={}, instance=jsonutils.to_primitive(inst_ref))
1322
1515
# Prove that the instance size is now the new size
1323
1516
inst_ref = db.instance_get_by_uuid(context, instance['uuid'])
1365
1565
'migrate_disk_and_power_off',
1366
1566
raise_migration_failure)
1368
inst_ref = self._create_fake_instance()
1568
reservations = self._ensure_quota_reservations_rolledback()
1570
inst_ref = jsonutils.to_primitive(self._create_fake_instance())
1369
1571
context = self.context.elevated()
1371
self.compute.run_instance(self.context, inst_ref['uuid'])
1573
self.compute.run_instance(self.context, instance=inst_ref)
1372
1574
db.instance_update(self.context, inst_ref['uuid'], {'host': 'foo'})
1373
self.compute.prep_resize(context, inst_ref['uuid'], 1, {},
1374
filter_properties={})
1575
self.compute.prep_resize(context, instance=inst_ref, instance_type={},
1576
image={}, reservations=reservations)
1375
1577
migration_ref = db.migration_get_by_instance_and_status(context,
1376
1578
inst_ref['uuid'], 'pre-migrating')
1377
1579
self.assertRaises(test.TestingException, self.compute.resize_instance,
1378
context, inst_ref['uuid'], migration_ref['id'], {})
1580
context, migration_ref['id'], {}, instance=inst_ref,
1581
reservations=reservations)
1379
1582
inst_ref = db.instance_get_by_uuid(context, inst_ref['uuid'])
1380
1583
self.assertEqual(inst_ref['vm_state'], vm_states.ERROR)
1381
self.compute.terminate_instance(context, inst_ref['uuid'])
1584
self.compute.terminate_instance(context,
1585
instance=jsonutils.to_primitive(inst_ref))
1587
def test_check_can_live_migrate_source_works_correctly(self):
1588
"""Confirm check_can_live_migrate_source works on positive path"""
1589
context = self.context.elevated()
1590
inst_ref = jsonutils.to_primitive(self._create_fake_instance(
1591
{'host': 'fake_host_2'}))
1592
inst_id = inst_ref["id"]
1593
dest = "fake_host_1"
1595
self.mox.StubOutWithMock(db, 'instance_get')
1596
self.mox.StubOutWithMock(self.compute.driver,
1597
'check_can_live_migrate_source')
1599
dest_check_data = {"test": "data"}
1600
self.compute.driver.check_can_live_migrate_source(context,
1604
self.mox.ReplayAll()
1605
self.compute.check_can_live_migrate_source(context,
1606
dest_check_data=dest_check_data, instance=inst_ref)
1608
def test_check_can_live_migrate_destination_works_correctly(self):
1609
"""Confirm check_can_live_migrate_destination works on positive path"""
1610
context = self.context.elevated()
1611
inst_ref = jsonutils.to_primitive(self._create_fake_instance(
1612
{'host': 'fake_host_2'}))
1613
inst_id = inst_ref["id"]
1614
dest = "fake_host_1"
1616
self.mox.StubOutWithMock(self.compute.driver,
1617
'check_can_live_migrate_destination')
1618
self.mox.StubOutWithMock(self.compute.compute_rpcapi,
1619
'check_can_live_migrate_source')
1620
self.mox.StubOutWithMock(self.compute.driver,
1621
'check_can_live_migrate_destination_cleanup')
1623
dest_check_data = {"test": "data"}
1624
self.compute.driver.check_can_live_migrate_destination(context,
1625
inst_ref, True, False).AndReturn(dest_check_data)
1626
self.compute.compute_rpcapi.check_can_live_migrate_source(context,
1627
inst_ref, dest_check_data)
1628
self.compute.driver.check_can_live_migrate_destination_cleanup(
1629
context, dest_check_data)
1631
self.mox.ReplayAll()
1632
self.compute.check_can_live_migrate_destination(context,
1633
block_migration=True, disk_over_commit=False,
1636
def test_check_can_live_migrate_destination_fails_dest_check(self):
1637
"""Confirm check_can_live_migrate_destination works on positive path"""
1638
context = self.context.elevated()
1639
inst_ref = jsonutils.to_primitive(self._create_fake_instance(
1640
{'host': 'fake_host_2'}))
1641
inst_id = inst_ref["id"]
1642
dest = "fake_host_1"
1644
self.mox.StubOutWithMock(self.compute.driver,
1645
'check_can_live_migrate_destination')
1647
self.compute.driver.check_can_live_migrate_destination(context,
1648
inst_ref, True, False).AndRaise(exception.Invalid())
1650
self.mox.ReplayAll()
1651
self.assertRaises(exception.Invalid,
1652
self.compute.check_can_live_migrate_destination,
1653
context, block_migration=True,
1654
disk_over_commit=False, instance=inst_ref)
1656
def test_check_can_live_migrate_destination_fails_source(self):
1657
"""Confirm check_can_live_migrate_destination works on positive path"""
1658
context = self.context.elevated()
1659
inst_ref = jsonutils.to_primitive(self._create_fake_instance(
1660
{'host': 'fake_host_2'}))
1661
inst_id = inst_ref["id"]
1662
dest = "fake_host_1"
1664
self.mox.StubOutWithMock(self.compute.driver,
1665
'check_can_live_migrate_destination')
1666
self.mox.StubOutWithMock(self.compute.compute_rpcapi,
1667
'check_can_live_migrate_source')
1668
self.mox.StubOutWithMock(self.compute.driver,
1669
'check_can_live_migrate_destination_cleanup')
1671
dest_check_data = {"test": "data"}
1672
self.compute.driver.check_can_live_migrate_destination(context,
1673
inst_ref, True, False).AndReturn(dest_check_data)
1674
self.compute.compute_rpcapi.check_can_live_migrate_source(context,
1675
inst_ref, dest_check_data).AndRaise(exception.Invalid())
1676
self.compute.driver.check_can_live_migrate_destination_cleanup(
1677
context, dest_check_data)
1679
self.mox.ReplayAll()
1680
self.assertRaises(exception.Invalid,
1681
self.compute.check_can_live_migrate_destination,
1682
context, block_migration=True,
1683
disk_over_commit=False, instance=inst_ref)
1383
1685
def test_pre_live_migration_instance_has_no_fixed_ip(self):
1384
1686
"""Confirm raising exception if instance doesn't have fixed_ip."""
1385
1687
# creating instance testdata
1386
inst_ref = self._create_fake_instance({'host': 'dummy'})
1387
c = context.get_admin_context()
1688
context = self.context.elevated()
1689
instance = jsonutils.to_primitive(self._create_fake_instance())
1690
inst_id = instance["id"]
1390
self.stubs.Set(time, 'sleep', lambda t: None)
1692
self.mox.ReplayAll()
1391
1693
self.assertRaises(exception.FixedIpNotFoundForInstance,
1392
self.compute.pre_live_migration,
1395
db.instance_destroy(c, inst_ref['uuid'])
1694
self.compute.pre_live_migration, context,
1397
1697
def test_pre_live_migration_works_correctly(self):
1398
1698
"""Confirm setup_compute_volume is called when volume is mounted."""
1401
1701
spectacular=True)
1402
1702
self.stubs.Set(nova.compute.manager.ComputeManager,
1403
1703
'_get_instance_nw_info', stupid)
1404
1705
# creating instance testdata
1405
inst_ref = self._create_fake_instance({'host': 'dummy'})
1706
instance = jsonutils.to_primitive(self._create_fake_instance(
1708
inst_id = instance['id']
1406
1709
c = context.get_admin_context()
1710
nw_info = fake_network.fake_get_instance_nw_info(self.stubs)
1408
1712
# creating mocks
1409
1713
self.mox.StubOutWithMock(self.compute.driver, 'pre_live_migration')
1410
self.compute.driver.pre_live_migration({'block_device_mapping': []})
1411
nw_info = fake_network.fake_get_instance_nw_info(self.stubs)
1412
self.mox.StubOutWithMock(self.compute.driver, 'plug_vifs')
1413
self.compute.driver.plug_vifs(mox.IsA(inst_ref), nw_info)
1714
self.compute.driver.pre_live_migration(mox.IsA(c), mox.IsA(instance),
1715
{'block_device_mapping': []},
1414
1717
self.mox.StubOutWithMock(self.compute.driver,
1415
1718
'ensure_filtering_rules_for_instance')
1416
1719
self.compute.driver.ensure_filtering_rules_for_instance(
1417
mox.IsA(inst_ref), nw_info)
1720
mox.IsA(instance), nw_info)
1420
1723
self.mox.ReplayAll()
1421
ret = self.compute.pre_live_migration(c, inst_ref['id'])
1724
ret = self.compute.pre_live_migration(c, instance=instance)
1422
1725
self.assertEqual(ret, None)
1425
db.instance_destroy(c, inst_ref['uuid'])
1728
db.instance_destroy(c, instance['uuid'])
1427
1730
def test_live_migration_dest_raises_exception(self):
1428
1731
"""Confirm exception when pre_live_migration fails."""
1429
1732
# creating instance testdata
1430
inst_ref = self._create_fake_instance({'host': 'dummy'})
1733
instance_ref = self._create_fake_instance({'host': 'dummy'})
1734
instance = jsonutils.to_primitive(instance_ref)
1735
inst_uuid = instance['uuid']
1736
inst_id = instance['id']
1432
1738
c = context.get_admin_context()
1433
topic = rpc.queue_get_for(c, FLAGS.compute_topic, inst_ref['host'])
1739
topic = rpc.queue_get_for(c, FLAGS.compute_topic, instance['host'])
1435
1741
# creating volume testdata
1436
1742
volume_id = db.volume_create(c, {'size': 1})['id']
1437
values = {'instance_uuid': inst_ref['uuid'], 'device_name': '/dev/vdc',
1743
values = {'instance_uuid': inst_uuid, 'device_name': '/dev/vdc',
1438
1744
'delete_on_termination': False, 'volume_id': volume_id}
1439
1745
db.block_device_mapping_create(c, values)
1442
1748
self.mox.StubOutWithMock(rpc, 'call')
1443
1749
rpc.call(c, FLAGS.volume_topic,
1444
1750
{"method": "check_for_export",
1445
"args": {'instance_id': inst_ref['id']}})
1447
self.mox.StubOutWithMock(self.compute.driver, 'get_instance_disk_info')
1448
self.compute.driver.get_instance_disk_info(inst_ref.name)
1451
{"method": "pre_live_migration",
1452
"args": {'instance_id': inst_ref['id'],
1453
'block_migration': True,
1455
"version": compute_rpcapi.ComputeAPI.RPC_API_VERSION
1456
}, None).AndRaise(rpc.common.RemoteError('', '', ''))
1751
"args": {'instance_id': inst_id}})
1753
self.mox.StubOutWithMock(self.compute.driver,
1754
'get_instance_disk_info')
1755
self.compute.driver.get_instance_disk_info(instance['name'])
1757
self.mox.StubOutWithMock(self.compute.compute_rpcapi,
1758
'pre_live_migration')
1759
self.compute.compute_rpcapi.pre_live_migration(c,
1760
mox.IsA(instance), True, None, instance['host']).AndRaise(
1761
rpc.common.RemoteError('', '', ''))
1458
1763
# mocks for rollback
1459
1764
rpc.call(c, 'network', {'method': 'setup_networks_on_host',
1460
'args': {'instance_id': inst_ref['id'],
1765
'args': {'instance_id': inst_id,
1461
1766
'host': self.compute.host,
1462
1767
'teardown': False}})
1768
rpcinst = jsonutils.to_primitive(
1769
db.instance_get_by_uuid(self.context, instance['uuid']))
1463
1770
rpc.call(c, topic,
1464
1771
{"method": "remove_volume_connection",
1465
"args": {'instance_id': inst_ref['id'],
1772
"args": {'instance': rpcinst,
1466
1773
'volume_id': volume_id},
1467
"version": compute_rpcapi.ComputeAPI.RPC_API_VERSION}, None)
1468
rpc.cast(c, topic, {"method": "rollback_live_migration_at_destination",
1469
"args": {'instance_id': inst_ref['id']}})
1774
"version": "1.26"}, None)
1776
{"method": "rollback_live_migration_at_destination",
1777
"args": {'instance': rpcinst},
1472
1781
self.mox.ReplayAll()
1473
1782
self.assertRaises(rpc_common.RemoteError,
1474
1783
self.compute.live_migration,
1475
c, inst_ref['id'], inst_ref['host'], True)
1784
c, dest=instance['host'], block_migration=True,
1478
1788
for bdms in db.block_device_mapping_get_all_by_instance(
1479
c, inst_ref['uuid']):
1480
1790
db.block_device_mapping_destroy(c, bdms['id'])
1481
1791
db.volume_destroy(c, volume_id)
1482
db.instance_destroy(c, inst_ref['uuid'])
1792
db.instance_destroy(c, inst_uuid)
1484
1794
def test_live_migration_works_correctly(self):
1485
1795
"""Confirm live_migration() works as expected correctly."""
1486
1796
# creating instance testdata
1487
instance = self._create_fake_instance({'host': 'dummy'})
1488
instance_id = instance['id']
1489
1797
c = context.get_admin_context()
1490
inst_ref = db.instance_get(c, instance_id)
1491
topic = rpc.queue_get_for(c, FLAGS.compute_topic, inst_ref['host'])
1798
instance_ref = self._create_fake_instance({'host': 'dummy'})
1799
inst_uuid = instance_ref['uuid']
1800
inst_id = instance_ref['id']
1802
instance = jsonutils.to_primitive(db.instance_get(c, inst_id))
1494
1805
self.mox.StubOutWithMock(rpc, 'call')
1806
topic = rpc.queue_get_for(c, FLAGS.compute_topic, instance['host'])
1495
1807
rpc.call(c, topic,
1496
1808
{"method": "pre_live_migration",
1497
"args": {'instance_id': instance_id,
1809
"args": {'instance': instance,
1498
1810
'block_migration': False,
1500
"version": compute_rpcapi.ComputeAPI.RPC_API_VERSION}, None)
1503
1816
self.mox.ReplayAll()
1504
ret = self.compute.live_migration(c, inst_ref['id'], inst_ref['host'])
1817
ret = self.compute.live_migration(c, dest=instance['host'],
1505
1819
self.assertEqual(ret, None)
1508
db.instance_destroy(c, instance['uuid'])
1822
db.instance_destroy(c, inst_uuid)
1510
1824
def test_post_live_migration_working_correctly(self):
1511
1825
"""Confirm post_live_migration() works as expected correctly."""
1515
1829
# creating testdata
1516
1830
c = context.get_admin_context()
1517
instance = self._create_fake_instance({
1518
'state_description': 'migrating',
1519
'state': power_state.PAUSED})
1520
instance_id = instance['id']
1521
i_ref = db.instance_get(c, instance_id)
1522
db.instance_update(c, i_ref['uuid'],
1831
inst_ref = jsonutils.to_primitive(self._create_fake_instance({
1832
'state_description': 'migrating',
1833
'state': power_state.PAUSED}))
1834
inst_uuid = inst_ref['uuid']
1835
inst_id = inst_ref['id']
1837
db.instance_update(c, inst_uuid,
1523
1838
{'task_state': task_states.MIGRATING,
1524
1839
'power_state': power_state.PAUSED})
1525
v_ref = db.volume_create(c, {'size': 1, 'instance_id': instance_id})
1840
v_ref = db.volume_create(c, {'size': 1, 'instance_id': inst_id})
1526
1841
fix_addr = db.fixed_ip_create(c, {'address': '1.1.1.1',
1527
'instance_id': instance_id})
1842
'instance_uuid': inst_ref['uuid']})
1528
1843
fix_ref = db.fixed_ip_get_by_address(c, fix_addr)
1529
1844
db.floating_ip_create(c, {'address': flo_addr,
1530
1845
'fixed_ip_id': fix_ref['id']})
1532
1847
# creating mocks
1533
1848
self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
1534
self.compute.driver.unfilter_instance(i_ref, [])
1849
self.compute.driver.unfilter_instance(inst_ref, [])
1535
1850
self.mox.StubOutWithMock(rpc, 'call')
1536
1851
rpc.call(c, rpc.queue_get_for(c, FLAGS.compute_topic, dest),
1537
1852
{"method": "post_live_migration_at_destination",
1538
"args": {'instance_id': i_ref['id'], 'block_migration': False},
1539
"version": compute_rpcapi.ComputeAPI.RPC_API_VERSION}, None)
1853
"args": {'instance': inst_ref, 'block_migration': False},
1854
"version": "1.20"}, None)
1540
1855
self.mox.StubOutWithMock(self.compute.driver, 'unplug_vifs')
1541
self.compute.driver.unplug_vifs(i_ref, [])
1856
self.compute.driver.unplug_vifs(inst_ref, [])
1542
1857
rpc.call(c, 'network', {'method': 'setup_networks_on_host',
1543
'args': {'instance_id': instance_id,
1858
'args': {'instance_id': inst_id,
1544
1859
'host': self.compute.host,
1545
1860
'teardown': True}})
1548
1863
self.mox.ReplayAll()
1549
self.compute.post_live_migration(c, i_ref, dest)
1864
self.compute._post_live_migration(c, inst_ref, dest)
1551
1866
# make sure floating ips are rewritten to destinatioin hostname.
1552
1867
flo_refs = db.floating_ip_get_all_by_host(c, dest)
1653
1968
self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
1655
1970
ctxt = context.get_admin_context()
1656
self.compute.add_instance_fault_from_exc(ctxt, instance_uuid,
1657
NotImplementedError('test'))
1659
def test_get_additional_capabilities(self):
1660
self.flags(additional_compute_capabilities=['test3=xyzzy',
1663
caps = compute_manager._get_additional_capabilities()
1664
all_caps = dict(test3='xyzzy',
1667
for c, val in all_caps.items():
1668
self.assertTrue(c in caps, c)
1669
self.assertEquals(val, caps[c])
1671
def test_report_driver_status(self):
1672
test_caps = dict(test1=1024, test2='foo', nothertest='bar')
1673
self.flags(additional_compute_capabilities=['test3=xyzzy',
1676
self.mox.StubOutWithMock(self.compute.driver, 'get_host_stats')
1677
self.compute.driver.get_host_stats(refresh=True).AndReturn(test_caps)
1678
self.compute._last_host_check = 0
1679
self.mox.ReplayAll()
1681
self.compute._report_driver_status(context.get_admin_context())
1682
caps = self.compute.last_capabilities
1683
all_caps = dict(test1=1024, test2='foo', test3='xyzzy',
1684
test4=True, nothertest='bar')
1685
for c, val in all_caps.items():
1686
self.assertTrue(c in caps, c)
1687
self.assertEquals(val, caps[c])
1971
self.compute._add_instance_fault_from_exc(ctxt, instance_uuid,
1972
NotImplementedError('test'))
1689
1974
def test_cleanup_running_deleted_instances(self):
1690
1975
admin_context = context.get_admin_context()
2160
2452
self.assertEqual(pre_build_len,
2161
2453
len(db.instance_get_all(context.get_admin_context())))
2455
def test_create_with_large_user_data(self):
2456
"""Test an instance type with too much user data."""
2458
inst_type = instance_types.get_default_instance_type()
2460
def fake_show(*args):
2461
img = copy.copy(self.fake_image)
2464
self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
2466
self.assertRaises(exception.InstanceUserDataTooLarge,
2467
self.compute_api.create, self.context, inst_type, None,
2468
user_data=('1' * 65536))
2470
def test_create_with_malformed_user_data(self):
2471
"""Test an instance type with malformed user data."""
2473
inst_type = instance_types.get_default_instance_type()
2475
def fake_show(*args):
2476
img = copy.copy(self.fake_image)
2479
self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
2481
self.assertRaises(exception.InstanceUserDataMalformed,
2482
self.compute_api.create, self.context, inst_type, None,
2485
def test_create_with_base64_user_data(self):
2486
"""Test an instance type with ok much user data."""
2488
inst_type = instance_types.get_default_instance_type()
2490
def fake_show(*args):
2491
img = copy.copy(self.fake_image)
2494
self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
2496
# NOTE(mikal): a string of length 48510 encodes to 65532 characters of
2498
(refs, resv_id) = self.compute_api.create(
2499
self.context, inst_type, None,
2500
user_data=base64.encodestring('1' * 48510))
2501
db.instance_destroy(self.context, refs[0]['uuid'])
2163
2503
def test_default_hostname_generator(self):
2164
2504
fake_uuids = [str(utils.gen_uuid()) for x in xrange(4)]
2548
2914
def test_set_admin_password(self):
2549
2915
"""Ensure instance can have its admin password set"""
2550
instance = self._create_fake_instance()
2916
instance = jsonutils.to_primitive(self._create_fake_instance())
2551
2917
instance_uuid = instance['uuid']
2552
self.compute.run_instance(self.context, instance_uuid)
2918
self.compute.run_instance(self.context, instance=instance)
2554
2920
inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
2555
2921
self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
2556
2922
self.assertEqual(inst_ref['task_state'], None)
2924
def fake_rpc_method(context, topic, msg, do_cast=True):
2925
self.assertFalse(do_cast)
2927
self.stubs.Set(rpc, 'call', fake_rpc_method)
2558
2929
self.compute_api.set_admin_password(self.context, inst_ref)
2560
2931
inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
2561
2932
self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
2562
self.assertEqual(inst_ref['task_state'], task_states.UPDATING_PASSWORD)
2933
self.assertEqual(inst_ref['task_state'],
2934
task_states.UPDATING_PASSWORD)
2564
self.compute.terminate_instance(self.context, instance_uuid)
2936
self.compute.terminate_instance(self.context,
2937
instance=jsonutils.to_primitive(inst_ref))
2566
2939
def test_rescue_unrescue(self):
2567
instance = self._create_fake_instance()
2940
instance = jsonutils.to_primitive(self._create_fake_instance())
2568
2941
instance_uuid = instance['uuid']
2569
self.compute.run_instance(self.context, instance_uuid)
2942
self.compute.run_instance(self.context, instance=instance)
2571
2944
instance = db.instance_get_by_uuid(self.context, instance_uuid)
2572
2945
self.assertEqual(instance['vm_state'], vm_states.ACTIVE)
2818
3193
self.assertEqual(instance['vm_state'], vm_states.RESIZED)
2819
3194
self.assertEqual(instance['task_state'], task_states.RESIZE_REVERTING)
2821
self.compute.terminate_instance(context, instance['uuid'])
3196
self.compute.terminate_instance(context,
3197
instance=jsonutils.to_primitive(instance))
2823
3199
def test_resize_invalid_flavor_fails(self):
2824
3200
"""Ensure invalid flavors raise"""
2825
3201
instance = self._create_fake_instance()
2826
3202
context = self.context.elevated()
2827
3203
instance = db.instance_get_by_uuid(context, instance['uuid'])
2828
self.compute.run_instance(self.context, instance['uuid'])
3204
instance = jsonutils.to_primitive(instance)
3205
self.compute.run_instance(self.context, instance=instance)
2830
3207
self.assertRaises(exception.NotFound, self.compute_api.resize,
2831
3208
context, instance, 200)
2833
self.compute.terminate_instance(context, instance['uuid'])
3210
self.compute.terminate_instance(context, instance=instance)
2835
3212
def test_resize_same_size_fails(self):
2836
3213
"""Ensure invalid flavors raise"""
2837
3214
context = self.context.elevated()
2838
3215
instance = self._create_fake_instance()
2839
3216
instance = db.instance_get_by_uuid(context, instance['uuid'])
3217
instance = jsonutils.to_primitive(instance)
2841
self.compute.run_instance(self.context, instance['uuid'])
3219
self.compute.run_instance(self.context, instance=instance)
2843
3221
self.assertRaises(exception.CannotResizeToSameSize,
2844
3222
self.compute_api.resize, context, instance, 1)
2846
self.compute.terminate_instance(context, instance['uuid'])
3224
self.compute.terminate_instance(context, instance=instance)
2848
3226
def test_migrate(self):
2849
3227
context = self.context.elevated()
2850
3228
instance = self._create_fake_instance()
2851
3229
instance = db.instance_get_by_uuid(context, instance['uuid'])
2852
self.compute.run_instance(self.context, instance['uuid'])
3230
instance = jsonutils.to_primitive(instance)
3231
self.compute.run_instance(self.context, instance=instance)
2853
3232
# Migrate simply calls resize() without a flavor_id.
2854
3233
self.compute_api.resize(context, instance, None)
2855
self.compute.terminate_instance(context, instance['uuid'])
3234
self.compute.terminate_instance(context, instance=instance)
2857
3236
def test_resize_request_spec(self):
2858
3237
def _fake_cast(context, topic, msg):
2966
3376
db.instance_destroy(c, instance2['uuid'])
2967
3377
db.instance_destroy(c, instance3['uuid'])
2969
def test_get_all_by_instance_name_regexp(self):
2970
"""Test searching instances by name"""
2971
self.flags(instance_name_template='instance-%d')
2973
c = context.get_admin_context()
2974
instance1 = self._create_fake_instance()
2975
instance2 = self._create_fake_instance({'id': 2})
2976
instance3 = self._create_fake_instance({'id': 10})
2978
instances = self.compute_api.get_all(c,
2979
search_opts={'instance_name': 'instance.*'})
2980
self.assertEqual(len(instances), 3)
2982
instances = self.compute_api.get_all(c,
2983
search_opts={'instance_name': '.*\-\d$'})
2984
self.assertEqual(len(instances), 2)
2985
instance_uuids = [instance['uuid'] for instance in instances]
2986
self.assertTrue(instance1['uuid'] in instance_uuids)
2987
self.assertTrue(instance2['uuid'] in instance_uuids)
2989
instances = self.compute_api.get_all(c,
2990
search_opts={'instance_name': 'i.*2'})
2991
self.assertEqual(len(instances), 1)
2992
self.assertEqual(instances[0]['uuid'], instance2['uuid'])
2994
db.instance_destroy(c, instance1['uuid'])
2995
db.instance_destroy(c, instance2['uuid'])
2996
db.instance_destroy(c, instance3['uuid'])
2998
3379
def test_get_all_by_multiple_options_at_once(self):
2999
3380
"""Test searching by multiple options at once"""
3000
3381
c = context.get_admin_context()
3624
4027
"/tmp/test", "File Contents")
3625
4028
db.instance_destroy(self.context, instance['uuid'])
4030
def test_secgroup_refresh(self):
4031
instance = self._create_fake_instance()
4033
def rule_get(*args, **kwargs):
4034
mock_rule = FakeModel({'parent_group_id': 1})
4037
def group_get(*args, **kwargs):
4038
mock_group = FakeModel({'instances': [instance]})
4042
self.compute_api.db,
4043
'security_group_rule_get_by_security_group_grantee',
4045
self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4047
self.mox.StubOutWithMock(rpc, 'cast')
4048
topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
4050
rpc.cast(self.context, topic,
4051
{"method": "refresh_instance_security_rules",
4052
"args": {'instance': jsonutils.to_primitive(instance)},
4054
self.mox.ReplayAll()
4056
self.security_group_api.trigger_members_refresh(self.context, [1])
4058
def test_secgroup_refresh_once(self):
4059
instance = self._create_fake_instance()
4061
def rule_get(*args, **kwargs):
4062
mock_rule = FakeModel({'parent_group_id': 1})
4065
def group_get(*args, **kwargs):
4066
mock_group = FakeModel({'instances': [instance]})
4070
self.compute_api.db,
4071
'security_group_rule_get_by_security_group_grantee',
4073
self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4075
self.mox.StubOutWithMock(rpc, 'cast')
4076
topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
4078
rpc.cast(self.context, topic,
4079
{"method": "refresh_instance_security_rules",
4080
"args": {'instance': jsonutils.to_primitive(instance)},
4082
self.mox.ReplayAll()
4084
self.security_group_api.trigger_members_refresh(self.context, [1, 2])
4086
def test_secgroup_refresh_none(self):
4087
def rule_get(*args, **kwargs):
4088
mock_rule = FakeModel({'parent_group_id': 1})
4091
def group_get(*args, **kwargs):
4092
mock_group = FakeModel({'instances': []})
4096
self.compute_api.db,
4097
'security_group_rule_get_by_security_group_grantee',
4099
self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4101
self.mox.StubOutWithMock(rpc, 'cast')
4102
self.mox.ReplayAll()
4104
self.security_group_api.trigger_members_refresh(self.context, [1])
4106
def test_secrule_refresh(self):
4107
instance = self._create_fake_instance()
4109
def group_get(*args, **kwargs):
4110
mock_group = FakeModel({'instances': [instance]})
4113
self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4115
self.mox.StubOutWithMock(rpc, 'cast')
4116
topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
4118
rpc.cast(self.context, topic,
4119
{"method": "refresh_instance_security_rules",
4120
"args": {'instance': jsonutils.to_primitive(instance)},
4122
self.mox.ReplayAll()
4124
self.security_group_api.trigger_rules_refresh(self.context, [1])
4126
def test_secrule_refresh_once(self):
4127
instance = self._create_fake_instance()
4129
def group_get(*args, **kwargs):
4130
mock_group = FakeModel({'instances': [instance]})
4133
self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4135
self.mox.StubOutWithMock(rpc, 'cast')
4136
topic = rpc.queue_get_for(self.context, FLAGS.compute_topic,
4138
rpc.cast(self.context, topic,
4139
{"method": "refresh_instance_security_rules",
4140
"args": {'instance': jsonutils.to_primitive(instance)},
4142
self.mox.ReplayAll()
4144
self.security_group_api.trigger_rules_refresh(self.context, [1, 2])
4146
def test_secrule_refresh_none(self):
4147
def group_get(*args, **kwargs):
4148
mock_group = FakeModel({'instances': []})
4151
self.stubs.Set(self.compute_api.db, 'security_group_get', group_get)
4153
self.mox.StubOutWithMock(rpc, 'cast')
4154
self.mox.ReplayAll()
4156
self.security_group_api.trigger_rules_refresh(self.context, [1, 2])
3628
4159
def fake_rpc_method(context, topic, msg, do_cast=True):
3711
4243
fake_zone = values.keys()[0]
3712
4244
aggr = self.api.create_aggregate(self.context,
3713
4245
'fake_aggregate', fake_zone)
3714
# let's mock the fact that the aggregate is active already!
3715
status = {'operational_state': aggregate_states.ACTIVE}
3716
db.aggregate_update(self.context, aggr['id'], status)
3717
4246
for host in values[fake_zone]:
3718
4247
aggr = self.api.add_host_to_aggregate(self.context,
3719
4248
aggr['id'], host)
3720
4249
self.assertEqual(len(aggr['hosts']), len(values[fake_zone]))
3721
self.assertEqual(aggr['operational_state'],
3722
aggregate_states.ACTIVE)
3724
def test_add_host_to_aggregate_invalid_changing_status(self):
3725
"""Ensure InvalidAggregateAction is raised when adding host while
3726
aggregate is not ready."""
3727
values = _create_service_entries(self.context)
3728
fake_zone = values.keys()[0]
3729
fake_host = values[fake_zone][0]
3730
aggr = self.api.create_aggregate(self.context,
3731
'fake_aggregate', fake_zone)
3732
aggr = self.api.add_host_to_aggregate(self.context,
3733
aggr['id'], fake_host)
3734
self.assertEqual(aggr['operational_state'],
3735
aggregate_states.CHANGING)
3736
self.assertRaises(exception.InvalidAggregateAction,
3737
self.api.add_host_to_aggregate, self.context,
3738
aggr['id'], fake_host)
3740
def test_add_host_to_aggregate_invalid_dismissed_status(self):
3741
"""Ensure InvalidAggregateAction is raised when aggregate is
3743
_create_service_entries(self.context, {'fake_zone': ['fake_host']})
3744
aggr = self.api.create_aggregate(self.context,
3745
'fake_aggregate', 'fake_zone')
3746
# let's mock the fact that the aggregate is dismissed!
3747
status = {'operational_state': aggregate_states.DISMISSED}
3748
db.aggregate_update(self.context, aggr['id'], status)
3749
self.assertRaises(exception.InvalidAggregateAction,
3750
self.api.add_host_to_aggregate, self.context,
3751
aggr['id'], 'fake_host')
3753
def test_add_host_to_aggregate_invalid_error_status(self):
3754
"""Ensure InvalidAggregateAction is raised when aggregate is
3756
_create_service_entries(self.context, {'fake_zone': ['fake_host']})
3757
aggr = self.api.create_aggregate(self.context,
3758
'fake_aggregate', 'fake_zone')
3759
# let's mock the fact that the aggregate is in error!
3760
status = {'operational_state': aggregate_states.ERROR}
3761
db.aggregate_update(self.context, aggr['id'], status)
3762
self.assertRaises(exception.InvalidAggregateAction,
3763
self.api.add_host_to_aggregate, self.context,
3764
aggr['id'], 'fake_host')
3766
4251
def test_add_host_to_aggregate_zones_mismatch(self):
3767
4252
"""Ensure InvalidAggregateAction is raised when zones don't match."""
3788
4273
fake_zone = values.keys()[0]
3789
4274
aggr = self.api.create_aggregate(self.context,
3790
4275
'fake_aggregate', fake_zone)
3791
# let's mock the fact that the aggregate is active already!
3792
status = {'operational_state': aggregate_states.ACTIVE}
3793
db.aggregate_update(self.context, aggr['id'], status)
3794
for host in values[fake_zone]:
3795
aggr = self.api.add_host_to_aggregate(self.context,
3797
expected = self.api.remove_host_from_aggregate(self.context,
3799
values[fake_zone][0])
3800
self.assertEqual(len(aggr['hosts']) - 1, len(expected['hosts']))
3801
self.assertEqual(expected['operational_state'],
3802
aggregate_states.ACTIVE)
3804
def test_remove_host_from_aggregate_error(self):
3805
"""Ensure we can remove a host from an aggregate even if in error."""
3806
values = _create_service_entries(self.context)
3807
fake_zone = values.keys()[0]
3808
aggr = self.api.create_aggregate(self.context,
3809
'fake_aggregate', fake_zone)
3810
# let's mock the fact that the aggregate is ready!
3811
status = {'operational_state': aggregate_states.ACTIVE}
3812
db.aggregate_update(self.context, aggr['id'], status)
3813
for host in values[fake_zone]:
3814
aggr = self.api.add_host_to_aggregate(self.context,
3816
# let's mock the fact that the aggregate is in error!
3817
status = {'operational_state': aggregate_states.ERROR}
3818
expected = self.api.remove_host_from_aggregate(self.context,
3820
values[fake_zone][0])
3821
self.assertEqual(len(aggr['hosts']) - 1, len(expected['hosts']))
3822
self.assertEqual(expected['operational_state'],
3823
aggregate_states.ACTIVE)
3825
def test_remove_host_from_aggregate_invalid_dismissed_status(self):
3826
"""Ensure InvalidAggregateAction is raised when aggregate is
3828
_create_service_entries(self.context, {'fake_zone': ['fake_host']})
3829
aggr = self.api.create_aggregate(self.context,
3830
'fake_aggregate', 'fake_zone')
3831
# let's mock the fact that the aggregate is dismissed!
3832
status = {'operational_state': aggregate_states.DISMISSED}
3833
db.aggregate_update(self.context, aggr['id'], status)
3834
self.assertRaises(exception.InvalidAggregateAction,
3835
self.api.remove_host_from_aggregate, self.context,
3836
aggr['id'], 'fake_host')
3838
def test_remove_host_from_aggregate_invalid_changing_status(self):
3839
"""Ensure InvalidAggregateAction is raised when aggregate is
3841
_create_service_entries(self.context, {'fake_zone': ['fake_host']})
3842
aggr = self.api.create_aggregate(self.context,
3843
'fake_aggregate', 'fake_zone')
3844
# let's mock the fact that the aggregate is changing!
3845
status = {'operational_state': aggregate_states.CHANGING}
3846
db.aggregate_update(self.context, aggr['id'], status)
3847
self.assertRaises(exception.InvalidAggregateAction,
3848
self.api.remove_host_from_aggregate, self.context,
3849
aggr['id'], 'fake_host')
4276
for host in values[fake_zone]:
4277
aggr = self.api.add_host_to_aggregate(self.context,
4279
expected = self.api.remove_host_from_aggregate(self.context,
4281
values[fake_zone][0])
4282
self.assertEqual(len(aggr['hosts']) - 1, len(expected['hosts']))
3851
4284
def test_remove_host_from_aggregate_raise_not_found(self):
3852
4285
"""Ensure ComputeHostNotFound is raised when removing invalid host."""
3879
4312
self.compute.add_aggregate_host(self.context, self.aggr.id, "host")
3880
4313
self.assertTrue(fake_driver_add_to_aggregate.called)
3882
def test_add_aggregate_host_raise_err(self):
3883
"""Ensure the undo operation works correctly on add."""
3884
def fake_driver_add_to_aggregate(context, aggregate, host):
3885
raise exception.AggregateError
3886
self.stubs.Set(self.compute.driver, "add_to_aggregate",
3887
fake_driver_add_to_aggregate)
3889
state = {'operational_state': aggregate_states.ACTIVE}
3890
db.aggregate_update(self.context, self.aggr.id, state)
3891
db.aggregate_host_add(self.context, self.aggr.id, 'fake_host')
3893
self.assertRaises(exception.AggregateError,
3894
self.compute.add_aggregate_host,
3895
self.context, self.aggr.id, "fake_host")
3896
excepted = db.aggregate_get(self.context, self.aggr.id)
3897
self.assertEqual(excepted.operational_state, aggregate_states.ERROR)
3898
self.assertEqual(excepted.hosts, [])
3900
4315
def test_remove_aggregate_host(self):
3901
4316
def fake_driver_remove_from_aggregate(context, aggregate, host):
3902
4317
fake_driver_remove_from_aggregate.called = True
4308
4734
self.assertNotRaises(exception.FlavorNotFound,
4309
4735
self.compute_api.resize, self.context, instance, None,
4310
4736
exc_msg="Disabled flavors can be migrated to")
4739
class ComputeReschedulingTestCase(BaseTestCase):
4740
"""Tests related to re-scheduling build requests"""
4743
super(ComputeReschedulingTestCase, self).setUp()
4745
self._reschedule = self._reschedule_partial()
4747
def _reschedule_partial(self):
4748
uuid = "12-34-56-78-90"
4750
requested_networks = None
4751
admin_password = None
4752
injected_files = None
4753
is_first_time = False
4755
return functools.partial(self.compute._reschedule, self.context, uuid,
4756
requested_networks, admin_password, injected_files,
4757
is_first_time, request_spec=None, filter_properties={})
4759
def test_reschedule_no_filter_properties(self):
4760
"""no filter_properties will disable re-scheduling"""
4761
self.assertFalse(self._reschedule())
4763
def test_reschedule_no_retry_info(self):
4764
"""no retry info will also disable re-scheduling"""
4765
filter_properties = {}
4766
self.assertFalse(self._reschedule(filter_properties=filter_properties))
4768
def test_reschedule_no_request_spec(self):
4769
"""no request spec will also disable re-scheduling"""
4770
retry = dict(num_attempts=1)
4771
filter_properties = dict(retry=retry)
4772
self.assertFalse(self._reschedule(filter_properties=filter_properties))
4774
def test_reschedule_success(self):
4775
retry = dict(num_attempts=1)
4776
filter_properties = dict(retry=retry)
4777
request_spec = {'num_instances': 42}
4778
self.assertTrue(self._reschedule(filter_properties=filter_properties,
4779
request_spec=request_spec))
4780
self.assertEqual(1, request_spec['num_instances'])
4783
class ThatsNoOrdinaryRabbitException(Exception):
4787
class ComputeReschedulingExceptionTestCase(BaseTestCase):
4788
"""Tests for re-scheduling exception handling logic"""
4791
super(ComputeReschedulingExceptionTestCase, self).setUp()
4793
# cause _spawn to raise an exception to test the exception logic:
4794
def exploding_spawn(*args, **kwargs):
4795
raise ThatsNoOrdinaryRabbitException()
4796
self.stubs.Set(self.compute, '_spawn',
4799
self.fake_instance = jsonutils.to_primitive(
4800
self._create_fake_instance())
4801
self.instance_uuid = self.fake_instance['uuid']
4803
def test_exception_with_rescheduling_disabled(self):
4804
"""Spawn fails and re-scheduling is disabled."""
4805
# this won't be re-scheduled:
4806
self.assertRaises(ThatsNoOrdinaryRabbitException,
4807
self.compute._run_instance, self.context,
4808
None, {}, None, None, None, None, self.fake_instance, None)
4810
def test_exception_with_rescheduling_enabled(self):
4811
"""Spawn fails and re-scheduling is enabled. Original exception
4812
should *not* be re-raised.
4814
# provide the expected status so that this one will be re-scheduled:
4815
retry = dict(num_attempts=1)
4816
filter_properties = dict(retry=retry)
4817
request_spec = dict(num_attempts=1)
4818
self.assertNotRaises(ThatsNoOrdinaryRabbitException,
4819
self.compute._run_instance, self.context,
4820
filter_properties=filter_properties, request_spec=request_spec,
4821
instance=self.fake_instance)
4823
def test_exception_context_cleared(self):
4824
"""Test with no rescheduling and an additional exception occurs
4825
clearing the original build error's exception context.
4827
# clears the original exception context:
4828
class FleshWoundException(Exception):
4831
def reschedule_explode(*args, **kwargs):
4832
raise FleshWoundException()
4833
self.stubs.Set(self.compute, '_reschedule', reschedule_explode)
4835
# the original exception should now be raised:
4836
self.assertRaises(ThatsNoOrdinaryRabbitException,
4837
self.compute._run_instance, self.context,
4838
None, {}, None, None, None, None, self.fake_instance, None)