summaryrefslogtreecommitdiff
path: root/nova
diff options
context:
space:
mode:
Diffstat (limited to 'nova')
-rw-r--r--nova/api/openstack/api_version_request.py3
-rw-r--r--nova/api/openstack/compute/rest_api_version_history.rst8
-rw-r--r--nova/api/openstack/compute/schemas/server_external_events.py4
-rw-r--r--nova/api/openstack/compute/server_external_events.py3
-rw-r--r--nova/api/openstack/compute/servers.py3
-rw-r--r--nova/compute/api.py24
-rw-r--r--nova/tests/fixtures/cinder.py9
-rw-r--r--nova/tests/functional/regressions/test_bug_1732947.py4
-rw-r--r--nova/tests/functional/regressions/test_bug_1902925.py5
-rw-r--r--nova/tests/functional/test_boot_from_volume.py40
-rw-r--r--nova/tests/functional/test_servers.py85
-rw-r--r--nova/tests/unit/compute/test_api.py159
12 files changed, 328 insertions, 19 deletions
diff --git a/nova/api/openstack/api_version_request.py b/nova/api/openstack/api_version_request.py
index a3a8b1f41e..84d8872f9e 100644
--- a/nova/api/openstack/api_version_request.py
+++ b/nova/api/openstack/api_version_request.py
@@ -252,6 +252,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
* 2.92 - Drop generation of keypair, add keypair name validation on
``POST /os-keypairs`` and allow including @ and dot (.) characters
in keypair name.
+ * 2.93 - Add support for volume backed server rebuild.
"""
# The minimum and maximum versions of the API supported
@@ -260,7 +261,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
# Note(cyeoh): This only applies for the v2.1 API once microversions
# support is fully merged. It does not affect the V2 API.
_MIN_API_VERSION = '2.1'
-_MAX_API_VERSION = '2.92'
+_MAX_API_VERSION = '2.93'
DEFAULT_API_VERSION = _MIN_API_VERSION
# Almost all proxy APIs which are related to network, images and baremetal
diff --git a/nova/api/openstack/compute/rest_api_version_history.rst b/nova/api/openstack/compute/rest_api_version_history.rst
index b65e50c62f..8f96a34e7d 100644
--- a/nova/api/openstack/compute/rest_api_version_history.rst
+++ b/nova/api/openstack/compute/rest_api_version_history.rst
@@ -1219,3 +1219,11 @@ Add support to pin a server to an availability zone or unpin a server from any a
The ``POST /os-keypairs`` API now forbids to generate a keypair and allows new
safe characters, specifically '@' and '.' (dot character).
+
+2.93
+----
+
+Add support for volume backed server rebuild. The end user will provide the
+image with the rebuild command and it will rebuild the volume with the new
+image similar to the result of rebuilding an ephemeral disk.
+
diff --git a/nova/api/openstack/compute/schemas/server_external_events.py b/nova/api/openstack/compute/schemas/server_external_events.py
index b8a89e047d..6ac3f009ec 100644
--- a/nova/api/openstack/compute/schemas/server_external_events.py
+++ b/nova/api/openstack/compute/schemas/server_external_events.py
@@ -63,3 +63,7 @@ name['enum'].append('power-update')
create_v282 = copy.deepcopy(create_v276)
name = create_v282['properties']['events']['items']['properties']['name']
name['enum'].append('accelerator-request-bound')
+
+create_v293 = copy.deepcopy(create_v282)
+name = create_v293['properties']['events']['items']['properties']['name']
+name['enum'].append('volume-reimaged')
diff --git a/nova/api/openstack/compute/server_external_events.py b/nova/api/openstack/compute/server_external_events.py
index 55f17e3541..23813d5790 100644
--- a/nova/api/openstack/compute/server_external_events.py
+++ b/nova/api/openstack/compute/server_external_events.py
@@ -69,7 +69,8 @@ class ServerExternalEventsController(wsgi.Controller):
@validation.schema(server_external_events.create, '2.0', '2.50')
@validation.schema(server_external_events.create_v251, '2.51', '2.75')
@validation.schema(server_external_events.create_v276, '2.76', '2.81')
- @validation.schema(server_external_events.create_v282, '2.82')
+ @validation.schema(server_external_events.create_v282, '2.82', '2.92')
+ @validation.schema(server_external_events.create_v293, '2.93')
def create(self, req, body):
"""Creates a new instance event."""
context = req.environ['nova.context']
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index 88f5fd4f8e..6a9bf1fa92 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -1205,6 +1205,9 @@ class ServersController(wsgi.Controller):
):
kwargs['hostname'] = rebuild_dict['hostname']
+ if api_version_request.is_supported(req, min_version='2.93'):
+ kwargs['reimage_boot_volume'] = True
+
for request_attribute, instance_attribute in attr_map.items():
try:
if request_attribute == 'name':
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 9fc4ca24a3..c06fefdd3c 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -3589,7 +3589,7 @@ class API:
@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED,
vm_states.ERROR])
def rebuild(self, context, instance, image_href, admin_password,
- files_to_inject=None, **kwargs):
+ files_to_inject=None, reimage_boot_volume=False, **kwargs):
"""Rebuild the given instance with the provided attributes."""
files_to_inject = files_to_inject or []
metadata = kwargs.get('metadata', {})
@@ -3670,15 +3670,16 @@ class API:
orig_image_ref = volume_image_metadata.get('image_id')
if orig_image_ref != image_href:
- # Leave a breadcrumb.
- LOG.debug('Requested to rebuild instance with a new image %s '
- 'for a volume-backed server with image %s in its '
- 'root volume which is not supported.', image_href,
- orig_image_ref, instance=instance)
- msg = _('Unable to rebuild with a different image for a '
- 'volume-backed server.')
- raise exception.ImageUnacceptable(
- image_id=image_href, reason=msg)
+ if not reimage_boot_volume:
+ # Leave a breadcrumb.
+ LOG.debug('Requested to rebuild instance with a new image '
+ '%s for a volume-backed server with image %s in '
+ 'its root volume which is not supported.',
+ image_href, orig_image_ref, instance=instance)
+ msg = _('Unable to rebuild with a different image for a '
+ 'volume-backed server.')
+ raise exception.ImageUnacceptable(
+ image_id=image_href, reason=msg)
else:
orig_image_ref = instance.image_ref
@@ -3793,7 +3794,8 @@ class API:
image_ref=image_href, orig_image_ref=orig_image_ref,
orig_sys_metadata=orig_sys_metadata, bdms=bdms,
preserve_ephemeral=preserve_ephemeral, host=host,
- request_spec=request_spec)
+ request_spec=request_spec,
+ reimage_boot_volume=reimage_boot_volume)
def _check_volume_status(self, context, bdms):
"""Check whether the status of the volume is "in-use".
diff --git a/nova/tests/fixtures/cinder.py b/nova/tests/fixtures/cinder.py
index 97b32d9b84..29889c784a 100644
--- a/nova/tests/fixtures/cinder.py
+++ b/nova/tests/fixtures/cinder.py
@@ -327,6 +327,12 @@ class CinderFixture(fixtures.Fixture):
_find_attachment(attachment_id)
LOG.info('Completing volume attachment: %s', attachment_id)
+ def fake_reimage_volume(*args, **kwargs):
+ if self.IMAGE_BACKED_VOL not in args:
+ raise exception.VolumeNotFound()
+ if 'reimage_reserved' not in kwargs:
+ raise exception.InvalidInput('reimage_reserved not specified')
+
self.test.stub_out(
'nova.volume.cinder.API.attachment_create', fake_attachment_create)
self.test.stub_out(
@@ -366,6 +372,9 @@ class CinderFixture(fixtures.Fixture):
self.test.stub_out(
'nova.volume.cinder.API.terminate_connection',
lambda *args, **kwargs: None)
+ self.test.stub_out(
+ 'nova.volume.cinder.API.reimage_volume',
+ fake_reimage_volume)
def volume_ids_for_instance(self, instance_uuid):
for volume_id, attachments in self.volume_to_attachment.items():
diff --git a/nova/tests/functional/regressions/test_bug_1732947.py b/nova/tests/functional/regressions/test_bug_1732947.py
index 3637f40bc2..db518fa8ce 100644
--- a/nova/tests/functional/regressions/test_bug_1732947.py
+++ b/nova/tests/functional/regressions/test_bug_1732947.py
@@ -28,7 +28,9 @@ class RebuildVolumeBackedSameImage(integrated_helpers._IntegratedTestBase):
original image.
"""
api_major_version = 'v2.1'
- microversion = 'latest'
+ # We need microversion <=2.93 to get the old BFV rebuild behavior
+ # that was the environment for this regression.
+ microversion = '2.92'
def _setup_scheduler_service(self):
# Add the IsolatedHostsFilter to the list of enabled filters since it
diff --git a/nova/tests/functional/regressions/test_bug_1902925.py b/nova/tests/functional/regressions/test_bug_1902925.py
index f0e823e2a4..59105c6cc6 100644
--- a/nova/tests/functional/regressions/test_bug_1902925.py
+++ b/nova/tests/functional/regressions/test_bug_1902925.py
@@ -28,6 +28,11 @@ class ComputeVersion5xPinnedRpcTests(integrated_helpers._IntegratedTestBase):
self.compute1 = self._start_compute(host='host1')
def _test_rebuild_instance_with_compute_rpc_pin(self, version_cap):
+ # Since passing the latest microversion (>= 2.93) passes
+ # the 'reimage_boot_volume' parameter as True and it is
+ # not acceptable with compute RPC version (required 6.1)
+ # These tests fail, so assigning microversion to 2.92
+ self.api.microversion = '2.92'
self.flags(compute=version_cap, group='upgrade_levels')
server_req = self._build_server(networks='none')
diff --git a/nova/tests/functional/test_boot_from_volume.py b/nova/tests/functional/test_boot_from_volume.py
index 0b963b5aa3..6396954bf4 100644
--- a/nova/tests/functional/test_boot_from_volume.py
+++ b/nova/tests/functional/test_boot_from_volume.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import fixtures
from unittest import mock
from nova import context
@@ -50,6 +51,9 @@ class BootFromVolumeTest(integrated_helpers._IntegratedTestBase):
self.flags(allow_resize_to_same_host=True)
super(BootFromVolumeTest, self).setUp()
self.admin_api = self.api_fixture.admin_api
+ self.useFixture(nova_fixtures.CinderFixture(self))
+ self.useFixture(fixtures.MockPatch(
+ 'nova.compute.manager.ComputeVirtAPI.wait_for_instance_event'))
def test_boot_from_volume_larger_than_local_gb(self):
# Verify no local disk is being used currently
@@ -138,6 +142,42 @@ class BootFromVolumeTest(integrated_helpers._IntegratedTestBase):
image_uuid = '155d900f-4e14-4e4c-a73d-069cbf4541e6'
post_data = {'rebuild': {'imageRef': image_uuid}}
self.api.post_server_action(server_id, post_data)
+
+ def test_rebuild_volume_backed_larger_than_local_gb(self):
+ # Verify no local disk is being used currently
+ self._verify_zero_local_gb_used()
+
+ # Create flavors with disk larger than available host local disk
+ flavor_id = self._create_flavor(memory_mb=64, vcpu=1, disk=8192,
+ ephemeral=0)
+
+ # Boot a server with a flavor disk larger than the available local
+ # disk. It should succeed for boot from volume.
+ server = self._build_server(image_uuid='', flavor_id=flavor_id)
+ volume_uuid = nova_fixtures.CinderFixture.IMAGE_BACKED_VOL
+ bdm = {'boot_index': 0,
+ 'uuid': volume_uuid,
+ 'source_type': 'volume',
+ 'destination_type': 'volume'}
+ server['block_device_mapping_v2'] = [bdm]
+ created_server = self.api.post_server({"server": server})
+ server_id = created_server['id']
+ self._wait_for_state_change(created_server, 'ACTIVE')
+
+ # Check that hypervisor local disk reporting is still 0
+ self._verify_zero_local_gb_used()
+ # Check that instance has not been saved with 0 root_gb
+ self._verify_instance_flavor_not_zero(server_id)
+ # Check that request spec has not been saved with 0 root_gb
+ self._verify_request_spec_flavor_not_zero(server_id)
+
+ # Rebuild
+ # The image_uuid is from CinderFixture for the
+ # volume representing IMAGE_BACKED_VOL.
+ self.api.microversion = '2.93'
+ image_uuid = '155d900f-4e14-4e4c-a73d-069cbf4541e6'
+ post_data = {'rebuild': {'imageRef': image_uuid}}
+ self.api.post_server_action(server_id, post_data)
self._wait_for_state_change(created_server, 'ACTIVE')
# Check that hypervisor local disk reporting is still 0
diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py
index ee8e30df0a..d1ab84aa7b 100644
--- a/nova/tests/functional/test_servers.py
+++ b/nova/tests/functional/test_servers.py
@@ -20,6 +20,7 @@ import time
from unittest import mock
import zlib
+from cinderclient import exceptions as cinder_exception
from keystoneauth1 import adapter
from oslo_config import cfg
from oslo_log import log as logging
@@ -1514,6 +1515,90 @@ class ServerRebuildTestCase(integrated_helpers._IntegratedTestBase):
'volume-backed server', str(resp))
+class ServerRebuildTestCaseV293(integrated_helpers._IntegratedTestBase):
+ api_major_version = 'v2.1'
+
+ def setUp(self):
+ super(ServerRebuildTestCaseV293, self).setUp()
+ self.cinder = nova_fixtures.CinderFixture(self)
+ self.useFixture(self.cinder)
+
+ def _bfv_server(self):
+ server_req_body = {
+ # There is no imageRef because this is boot from volume.
+ 'server': {
+ 'flavorRef': '1', # m1.tiny from DefaultFlavorsFixture,
+ 'name': 'test_volume_backed_rebuild_different_image',
+ 'networks': [],
+ 'block_device_mapping_v2': [{
+ 'boot_index': 0,
+ 'uuid':
+ nova_fixtures.CinderFixture.IMAGE_BACKED_VOL,
+ 'source_type': 'volume',
+ 'destination_type': 'volume'
+ }]
+ }
+ }
+ server = self.api.post_server(server_req_body)
+ return self._wait_for_state_change(server, 'ACTIVE')
+
+ def _test_rebuild(self, server):
+ self.api.microversion = '2.93'
+ # Now rebuild the server with a different image than was used to create
+ # our fake volume.
+ rebuild_image_ref = self.glance.auto_disk_config_enabled_image['id']
+ rebuild_req_body = {'rebuild': {'imageRef': rebuild_image_ref}}
+
+ with mock.patch.object(self.compute.manager.virtapi,
+ 'wait_for_instance_event'):
+ self.api.api_post('/servers/%s/action' % server['id'],
+ rebuild_req_body,
+ check_response_status=[202])
+
+ def test_volume_backed_rebuild_root_v293(self):
+ server = self._bfv_server()
+ self._test_rebuild(server)
+
+ def test_volume_backed_rebuild_root_create_failed(self):
+ server = self._bfv_server()
+ error = cinder_exception.ClientException(code=500)
+ with mock.patch.object(volume.cinder.API, 'attachment_create',
+ side_effect=error):
+ # We expect this to fail because we are doing cast-as-call
+ self.assertRaises(client.OpenStackApiException,
+ self._test_rebuild, server)
+ server = self.api.get_server(server['id'])
+ self.assertIn('Failed to rebuild volume backed instance',
+ server['fault']['message'])
+ self.assertEqual('ERROR', server['status'])
+
+ def test_volume_backed_rebuild_root_instance_deleted(self):
+ server = self._bfv_server()
+ error = exception.InstanceNotFound(instance_id=server['id'])
+ with mock.patch.object(self.compute.manager, '_detach_root_volume',
+ side_effect=error):
+ # We expect this to fail because we are doing cast-as-call
+ self.assertRaises(client.OpenStackApiException,
+ self._test_rebuild, server)
+ server = self.api.get_server(server['id'])
+ self.assertIn('Failed to rebuild volume backed instance',
+ server['fault']['message'])
+ self.assertEqual('ERROR', server['status'])
+
+ def test_volume_backed_rebuild_root_delete_old_failed(self):
+ server = self._bfv_server()
+ error = cinder_exception.ClientException(code=500)
+ with mock.patch.object(volume.cinder.API, 'attachment_delete',
+ side_effect=error):
+ # We expect this to fail because we are doing cast-as-call
+ self.assertRaises(client.OpenStackApiException,
+ self._test_rebuild, server)
+ server = self.api.get_server(server['id'])
+ self.assertIn('Failed to rebuild volume backed instance',
+ server['fault']['message'])
+ self.assertEqual('ERROR', server['status'])
+
+
class ServersTestV280(integrated_helpers._IntegratedTestBase):
api_major_version = 'v2.1'
diff --git a/nova/tests/unit/compute/test_api.py b/nova/tests/unit/compute/test_api.py
index 73b36c2ef0..ca72474a4c 100644
--- a/nova/tests/unit/compute/test_api.py
+++ b/nova/tests/unit/compute/test_api.py
@@ -4004,6 +4004,155 @@ class _ComputeAPIUnitTestMixIn(object):
_checks_for_create_and_rebuild.assert_called_once_with(
self.context, None, image, flavor, {}, [], None)
+ @ddt.data(True, False)
+ @mock.patch.object(objects.RequestSpec, 'save')
+ @mock.patch.object(objects.RequestSpec, 'get_by_instance_uuid')
+ @mock.patch.object(objects.Instance, 'save')
+ @mock.patch.object(objects.Instance, 'get_flavor')
+ @mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
+ @mock.patch.object(compute_api.API, '_get_image')
+ @mock.patch.object(compute_api.API, '_check_image_arch')
+ @mock.patch.object(compute_api.API, '_check_auto_disk_config')
+ @mock.patch.object(compute_api.API, '_checks_for_create_and_rebuild')
+ @mock.patch.object(compute_api.API, '_record_action_start')
+ def test_rebuild_volume_backed(self, reimage_boot_vol,
+ _record_action_start, _checks_for_create_and_rebuild,
+ _check_auto_disk_config,
+ _check_image_arch, mock_get_image,
+ mock_get_bdms, get_flavor,
+ instance_save, req_spec_get_by_inst_uuid, request_save):
+ """Test a scenario where the instance is volume backed and we rebuild
+ with following cases:
+
+ 1) reimage_boot_volume=True
+ 2) reimage_boot_volume=False
+
+ """
+ instance = fake_instance.fake_instance_obj(
+ self.context, vm_state=vm_states.ACTIVE, cell_name='fake-cell',
+ launched_at=timeutils.utcnow(),
+ system_metadata={}, image_ref=uuids.image_ref,
+ expected_attrs=['system_metadata'], node='fake')
+ bdms = objects.BlockDeviceMappingList(objects=[
+ objects.BlockDeviceMapping(
+ boot_index=None, image_id=None,
+ source_type='volume', destination_type='volume',
+ volume_type=None, snapshot_id=None,
+ volume_id=uuids.volume_id, volume_size=None)])
+ mock_get_bdms.return_value = bdms
+ get_flavor.return_value = test_flavor.fake_flavor
+ flavor = instance.get_flavor()
+ image = {
+ "id": uuids.image_ref,
+ "min_ram": 10, "min_disk": 1,
+ "properties": {
+ 'architecture': fields_obj.Architecture.X86_64}}
+ mock_get_image.return_value = (None, image)
+ fake_spec = objects.RequestSpec(id=1, force_nodes=None)
+ req_spec_get_by_inst_uuid.return_value = fake_spec
+ fake_volume = {'id': uuids.volume_id, 'status': 'in-use'}
+ fake_conn_info = '{}'
+ fake_device = 'fake_vda'
+ root_bdm = mock.MagicMock(
+ volume_id=uuids.volume_id, connection_info=fake_conn_info,
+ device_name=fake_device, attachment_id=uuids.old_attachment_id,
+ save=mock.MagicMock())
+ admin_pass = "new password"
+ with mock.patch.object(self.compute_api.volume_api, 'get',
+ return_value=fake_volume), \
+ mock.patch.object(compute_utils, 'get_root_bdm',
+ return_value=root_bdm), \
+ mock.patch.object(self.compute_api.compute_task_api,
+ 'rebuild_instance') as rebuild_instance:
+ if reimage_boot_vol:
+ self.compute_api.rebuild(self.context,
+ instance,
+ uuids.image_ref,
+ admin_pass,
+ reimage_boot_volume=True)
+ rebuild_instance.assert_called_once_with(self.context,
+ instance=instance, new_pass=admin_pass,
+ image_ref=uuids.image_ref,
+ orig_image_ref=None, orig_sys_metadata={},
+ injected_files=[], bdms=bdms,
+ preserve_ephemeral=False, host=None,
+ request_spec=fake_spec,
+ reimage_boot_volume=True)
+ _check_auto_disk_config.assert_called_once_with(
+ image=image, auto_disk_config=None)
+ _checks_for_create_and_rebuild.assert_called_once_with(
+ self.context, None, image, flavor, {}, [], root_bdm)
+ mock_get_bdms.assert_called_once_with(
+ self.context, instance.uuid)
+ else:
+ self.assertRaises(
+ exception.NovaException,
+ self.compute_api.rebuild,
+ self.context,
+ instance,
+ uuids.image_ref,
+ admin_pass,
+ reimage_boot_volume=False)
+
+ @mock.patch.object(objects.RequestSpec, 'save')
+ @mock.patch.object(objects.RequestSpec, 'get_by_instance_uuid')
+ @mock.patch.object(objects.Instance, 'save')
+ @mock.patch.object(objects.Instance, 'get_flavor')
+ @mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
+ @mock.patch.object(compute_api.API, '_get_image')
+ @mock.patch.object(compute_api.API, '_check_image_arch')
+ @mock.patch.object(compute_api.API, '_check_auto_disk_config')
+ @mock.patch.object(compute_api.API, '_checks_for_create_and_rebuild')
+ @mock.patch.object(compute_api.API, '_record_action_start')
+ def test_rebuild_volume_backed_fails(self, _record_action_start,
+ _checks_for_create_and_rebuild, _check_auto_disk_config,
+ _check_image_arch, mock_get_image,
+ mock_get_bdms, get_flavor,
+ instance_save, req_spec_get_by_inst_uuid, request_save):
+ """Test a scenario where we don't pass parameters to rebuild
+ boot volume
+ """
+ instance = fake_instance.fake_instance_obj(
+ self.context, vm_state=vm_states.ACTIVE, cell_name='fake-cell',
+ launched_at=timeutils.utcnow(),
+ system_metadata={}, image_ref=uuids.image_ref,
+ expected_attrs=['system_metadata'], node='fake')
+ bdms = objects.BlockDeviceMappingList(objects=[
+ objects.BlockDeviceMapping(
+ boot_index=None, image_id=None,
+ source_type='volume', destination_type='volume',
+ volume_type=None, snapshot_id=None,
+ volume_id=uuids.volume_id, volume_size=None)])
+ mock_get_bdms.return_value = bdms
+ get_flavor.return_value = test_flavor.fake_flavor
+ image = {
+ "id": uuids.image_ref,
+ "min_ram": 10, "min_disk": 1,
+ "properties": {
+ 'architecture': fields_obj.Architecture.X86_64}}
+ mock_get_image.return_value = (None, image)
+ fake_spec = objects.RequestSpec(id=1, force_nodes=None)
+ req_spec_get_by_inst_uuid.return_value = fake_spec
+ fake_volume = {'id': uuids.volume_id, 'status': 'in-use'}
+ fake_conn_info = '{}'
+ fake_device = 'fake_vda'
+ root_bdm = mock.MagicMock(
+ volume_id=uuids.volume_id, connection_info=fake_conn_info,
+ device_name=fake_device, attachment_id=uuids.old_attachment_id,
+ save=mock.MagicMock())
+ admin_pass = "new password"
+ with mock.patch.object(self.compute_api.volume_api, 'get',
+ return_value=fake_volume), \
+ mock.patch.object(compute_utils, 'get_root_bdm',
+ return_value=root_bdm):
+ self.assertRaises(exception.NovaException,
+ self.compute_api.rebuild,
+ self.context,
+ instance,
+ uuids.image_ref,
+ admin_pass,
+ reimage_boot_volume=False)
+
@mock.patch.object(objects.RequestSpec, 'get_by_instance_uuid')
@mock.patch.object(objects.Instance, 'save')
@mock.patch.object(objects.Instance, 'get_flavor')
@@ -4052,7 +4201,7 @@ class _ComputeAPIUnitTestMixIn(object):
orig_image_ref=uuids.image_ref,
orig_sys_metadata=orig_system_metadata, bdms=bdms,
preserve_ephemeral=False, host=instance.host,
- request_spec=fake_spec)
+ request_spec=fake_spec, reimage_boot_volume=False)
_check_auto_disk_config.assert_called_once_with(
image=image, auto_disk_config=None)
@@ -4125,7 +4274,7 @@ class _ComputeAPIUnitTestMixIn(object):
orig_image_ref=uuids.image_ref,
orig_sys_metadata=orig_system_metadata, bdms=bdms,
preserve_ephemeral=False, host=None,
- request_spec=fake_spec)
+ request_spec=fake_spec, reimage_boot_volume=False)
# assert the request spec was modified so the scheduler picks
# the existing instance host/node
req_spec_save.assert_called_once_with()
@@ -4193,7 +4342,7 @@ class _ComputeAPIUnitTestMixIn(object):
orig_image_ref=uuids.image_ref,
orig_sys_metadata=orig_system_metadata, bdms=bdms,
preserve_ephemeral=False, host=instance.host,
- request_spec=fake_spec)
+ request_spec=fake_spec, reimage_boot_volume=False)
_check_auto_disk_config.assert_called_once_with(
image=image, auto_disk_config=None)
@@ -4252,7 +4401,7 @@ class _ComputeAPIUnitTestMixIn(object):
orig_image_ref=uuids.image_ref,
orig_sys_metadata=orig_system_metadata, bdms=bdms,
preserve_ephemeral=False, host=instance.host,
- request_spec=fake_spec)
+ request_spec=fake_spec, reimage_boot_volume=False)
_check_auto_disk_config.assert_called_once_with(
image=image, auto_disk_config=None)
@@ -4316,7 +4465,7 @@ class _ComputeAPIUnitTestMixIn(object):
orig_image_ref=uuids.image_ref,
orig_sys_metadata=orig_system_metadata, bdms=bdms,
preserve_ephemeral=False, host=instance.host,
- request_spec=fake_spec)
+ request_spec=fake_spec, reimage_boot_volume=False)
_check_auto_disk_config.assert_called_once_with(
image=image, auto_disk_config=None)