1457
1582
def test_state_revert(self):
1458
1583
"""ensure that task_state is reverted after a failed operation"""
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,
1597
'injected_files': [],
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,
1606
'instance_type': {}}),
1607
("resize_instance", task_states.RESIZE_PREP, None,
1608
{'migration_id': None,
1610
("pause_instance", task_states.PAUSING),
1611
("unpause_instance", task_states.UNPAUSING),
1612
("suspend_instance", task_states.SUSPENDING),
1613
("resume_instance", task_states.RESUMING),
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)
1483
1619
def _ensure_quota_reservations_committed(self):
1484
1620
"""Mock up commit of quota reservations"""
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()
1761
1915
reservations = self._ensure_quota_reservations_rolledback()
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'],
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')
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})
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)
1781
self.compute.terminate_instance(context,
1938
self.compute.terminate_instance(self.context,
1782
1939
instance=jsonutils.to_primitive(instance))
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()
1790
1946
self.compute.run_instance(self.context, instance=instance)
1791
db.instance_update(self.context, instance['uuid'],
1793
self.compute.prep_resize(context, instance=instance,
1947
new_instance = db.instance_update(self.context, instance['uuid'],
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'],
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'])
1962
self.compute.terminate_instance(self.context,
1963
instance=jsonutils.to_primitive(inst))
1805
1965
def test_finish_revert_resize(self):
1806
1966
"""Ensure that the flavor is reverted to the original on revert"""
1813
1973
reservations = self._ensure_quota_reservations_committed()
1815
context = self.context.elevated()
1816
1975
instance = jsonutils.to_primitive(self._create_fake_instance())
1817
1976
instance_uuid = instance['uuid']
1819
1978
self.compute.run_instance(self.context, instance=instance)
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')
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'})
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(
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)
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')
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'],
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,
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)
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')
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)
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)
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'])
2031
self.stubs.Set(network_api.API, 'setup_networks_on_host',
2032
fake_setup_networks_on_host)
2034
self.compute.finish_revert_resize(self.context,
2035
migration=jsonutils.to_primitive(migration_ref),
2036
instance=rpcinst, reservations=reservations)
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)
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'])
1876
self.compute.terminate_instance(context,
2048
self.compute.terminate_instance(self.context,
1877
2049
instance=jsonutils.to_primitive(inst_ref))
1879
2051
def test_get_by_flavor_id(self):
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()
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'],
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))
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"
1938
2109
self.mox.StubOutWithMock(db, 'instance_get')
1939
2110
self.mox.StubOutWithMock(self.compute.driver,
1940
2111
'check_can_live_migrate_source')
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,
1945
2116
dest_check_data)
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)
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"}
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')
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,
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)
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)
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"}
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')
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,
2173
compute_info, compute_info,
2174
True, False).AndRaise(exception.Invalid())
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)
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"}
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,
3580
3956
{'task_state': None,
3581
3957
'vm_state': vm_states.RESIZED})
3583
self.compute_api.revert_resize(context, instance)
3959
self.compute_api.revert_resize(self.context, instance)
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)
3589
self.compute.terminate_instance(context,
3965
self.compute.terminate_instance(self.context,
3590
3966
instance=jsonutils.to_primitive(instance))
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)
3600
3975
self.assertRaises(exception.NotFound, self.compute_api.resize,
3601
context, instance, 200)
3603
self.compute.terminate_instance(context, instance=instance)
3976
self.context, instance, 200)
3978
self.compute.terminate_instance(self.context, instance=instance)
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)
3986
name = 'test_resize_new_flavor'
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)
3997
self.compute.terminate_instance(self.context, instance=instance)
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)
3612
4005
self.compute.run_instance(self.context, instance=instance)
3614
4007
self.assertRaises(exception.CannotResizeToSameFlavor,
3615
self.compute_api.resize, context, instance, 1)
4008
self.compute_api.resize, self.context, instance, 1)
3617
self.compute.terminate_instance(context, instance=instance)
4010
self.compute.terminate_instance(self.context, instance=instance)
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)
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']
4425
4847
def fake_rpc_attach_volume(self, context, **kwargs):
4426
4848
called['fake_rpc_attach_volume'] = True
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)
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'))
4863
values = {'instance_uuid': instance['uuid'],
4864
'device_name': '/dev/vdc',
4865
'delete_on_termination': False,
4866
'volume_id': volume_id,
4868
db.block_device_mapping_create(admin, values)
4870
def fake_volume_get(self, context, volume):
4871
return {'id': volume_id}
4872
self.stubs.Set(cinder.API, "get", fake_volume_get)
4874
# Stub out and record whether it gets detached
4875
result = {"detached": False}
4877
def fake_detach(self, context, volume):
4878
result["detached"] = volume["id"] == volume_id
4879
self.stubs.Set(cinder.API, "detach", fake_detach)
4881
def fake_terminate_connection(self, context, volume, connector):
4883
self.stubs.Set(cinder.API, "terminate_connection",
4884
fake_terminate_connection)
4886
# Kill the instance and check that it was detached
4887
self.compute.terminate_instance(admin, instance=instance)
4888
self.assertTrue(result["detached"])
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'])
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)
5302
class ThatsNoOrdinaryRabbitException(Exception):
5784
self.assertEqual(self.updated_task_state, self.expected_task_state)
5787
class ComputeReschedulingResizeTestCase(ComputeReschedulingTestCase):
5788
"""Test re-scheduling logic for prep_resize requests"""
5791
super(ComputeReschedulingResizeTestCase, self).setUp()
5792
self.expected_task_state = task_states.RESIZE_PREP
5794
def _reschedule(self, request_spec=None, filter_properties=None):
5795
if not filter_properties:
5796
filter_properties = {}
5798
instance_uuid = "12-34-56-78-90"
5800
instance = {'uuid': instance_uuid}
5805
scheduler_method = self.compute.scheduler_rpcapi.prep_resize
5806
method_args = (instance, instance_type, image, request_spec,
5807
filter_properties, reservations)
5809
return self.compute._reschedule(self.context, request_spec,
5810
filter_properties, instance_uuid, scheduler_method,
5811
method_args, self.expected_task_state)
5814
class InnerTestingException(Exception):
5306
class ComputeReschedulingExceptionTestCase(BaseTestCase):
5307
"""Tests for re-scheduling exception handling logic"""
5310
super(ComputeReschedulingExceptionTestCase, self).setUp()
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',
5318
self.fake_instance = jsonutils.to_primitive(
5319
self._create_fake_instance())
5320
self.instance_uuid = self.fake_instance['uuid']
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)
5329
def test_exception_with_rescheduling_enabled(self):
5330
"""Spawn fails and re-scheduling is enabled. Original exception
5331
should *not* be re-raised.
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)
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.
5346
# clears the original exception context:
5347
class FleshWoundException(Exception):
5350
def reschedule_explode(*args, **kwargs):
5351
raise FleshWoundException()
5352
self.stubs.Set(self.compute, '_reschedule', reschedule_explode)
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.
5824
super(ComputeRescheduleOrReraiseTestCase, self).setUp()
5825
self.instance = self._create_fake_instance()
5827
def test_reschedule_or_reraise_called(self):
5828
"""Basic sanity check to make sure _reschedule_or_reraise is called
5831
self.mox.StubOutWithMock(self.compute, '_spawn')
5832
self.mox.StubOutWithMock(self.compute, '_reschedule_or_reraise')
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, {})
5839
self.mox.ReplayAll()
5840
self.compute._run_instance(self.context, None, {}, None, None, None,
5841
False, self.instance)
5843
def test_deallocate_network_fail(self):
5844
"""Test de-allocation of network failing before re-scheduling logic
5847
instance_uuid = self.instance['uuid']
5848
self.mox.StubOutWithMock(self.compute, '_deallocate_network')
5851
raise test.TestingException("Original")
5853
exc_info = sys.exc_info()
5855
self.compute._deallocate_network(self.context,
5856
self.instance).AndRaise(InnerTestingException("Error"))
5857
self.compute._log_original_error(exc_info, instance_uuid)
5859
self.mox.ReplayAll()
5861
# should raise the deallocation exception, not the original build
5863
self.assertRaises(InnerTestingException,
5864
self.compute._reschedule_or_reraise, self.context,
5865
self.instance, None, None, None, False, None, {})
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')
5874
self.compute._deallocate_network(self.context,
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"))
5881
self.mox.ReplayAll()
5884
raise test.TestingException("Original")
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, {})
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')
5898
self.compute._deallocate_network(self.context,
5900
self.compute._reschedule(self.context, None, instance_uuid,
5901
{}, self.compute.scheduler_rpcapi.run_instance, method_args,
5902
task_states.SCHEDULING).AndReturn(False)
5904
self.mox.ReplayAll()
5907
raise test.TestingException("Original")
5909
# re-scheduling is False, the original build error should be
5911
self.assertRaises(test.TestingException,
5912
self.compute._reschedule_or_reraise, self.context,
5913
self.instance, None, None, None, False, None, {})
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')
5923
raise test.TestingException("Original")
5925
exc_info = sys.exc_info()
5927
self.compute._deallocate_network(self.context,
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)
5934
self.mox.ReplayAll()
5936
# re-scheduling is True, original error is logged, but nothing
5938
self.compute._reschedule_or_reraise(self.context, self.instance,
5939
None, None, None, False, None, {})
5942
class ComputeRescheduleResizeOrReraiseTestCase(BaseTestCase):
5943
"""Test logic and exception handling around rescheduling prep resize
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(
5953
def test_reschedule_resize_or_reraise_called(self):
5954
"""Verify the rescheduling logic gets called when there is an error
5957
self.mox.StubOutWithMock(self.compute.db, 'migration_create')
5958
self.mox.StubOutWithMock(self.compute, '_reschedule_resize_or_reraise')
5960
self.compute.db.migration_create(mox.IgnoreArg(),
5961
mox.IgnoreArg()).AndRaise(test.TestingException("Original"))
5963
self.compute._reschedule_resize_or_reraise(mox.IgnoreArg(), None,
5964
self.instance, self.instance_type, None, None, None)
5966
self.mox.ReplayAll()
5968
self.compute.prep_resize(self.context, None, self.instance,
5971
def test_reschedule_fails_with_exception(self):
5972
"""Original exception should be raised if the _reschedule method
5973
raises another exception
5975
method_args = (None, self.instance, self.instance_type, None, None,
5977
self.mox.StubOutWithMock(self.compute, "_reschedule")
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()
5986
raise test.TestingException("Original")
5988
self.assertRaises(test.TestingException,
5989
self.compute._reschedule_resize_or_reraise, self.context,
5990
None, self.instance, self.instance_type, None, {}, {})
5992
def test_reschedule_false(self):
5993
"""Original exception should be raised if the resize is not
5996
method_args = (None, self.instance, self.instance_type, None, None,
5998
self.mox.StubOutWithMock(self.compute, "_reschedule")
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()
6006
raise test.TestingException("Original")
6008
self.assertRaises(test.TestingException,
6009
self.compute._reschedule_resize_or_reraise, self.context,
6010
None, self.instance, self.instance_type, None, {}, {})
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)
6016
raise test.TestingException("Original")
6018
exc_info = sys.exc_info()
6020
self.mox.StubOutWithMock(self.compute, "_reschedule")
6021
self.mox.StubOutWithMock(self.compute, "_log_original_error")
6022
self.compute._reschedule(self.context, {}, {},
6024
self.compute.scheduler_rpcapi.prep_resize, method_args,
6025
task_states.RESIZE_PREP).AndReturn(True)
6027
self.compute._log_original_error(exc_info, self.instance_uuid)
6028
self.mox.ReplayAll()
6030
self.compute._reschedule_resize_or_reraise(self.context, None,
6031
self.instance, self.instance_type, None, {}, {})
6034
class ComputeInactiveImageTestCase(BaseTestCase):
6036
super(ComputeInactiveImageTestCase, self).setUp()
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'}}
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()
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)