tests: Use valid UUIDs for cinder resources

This necessitates adding some missing return values for various mocks.
Combined, this brings our tests closer to reality and will be needed
once we add response schemas for these.

Change-Id: I1ff23082d257f98e4f63b84b287a3c374a62bf0b
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane
2025-06-12 16:44:58 +01:00
parent a8651eaff3
commit 2a546a8645
32 changed files with 270 additions and 232 deletions

View File

@@ -0,0 +1,6 @@
{
"share": {
"share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986",
"tag": "my-tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"share": {
"share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986"
}
}

View File

@@ -1,9 +1,9 @@
{
"snapshot": {
"createdAt": "2013-02-25T16:27:54.680544",
"createdAt": "2025-06-12T14:56:30.215430",
"displayDescription": "Daily backup",
"displayName": "snap-001",
"id": 100,
"id": "fe06e9f2-e6b0-47d1-a63e-c0a15ad51994",
"size": 100,
"status": "available",
"volumeId": "521752a6-acf6-4b2d-bc7a-119f9148cd8c"

View File

@@ -1,31 +1,31 @@
{
"snapshots": [
{
"createdAt": "2013-02-25T16:27:54.671372",
"createdAt": "2025-06-12T14:56:30.070910",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 100,
"id": "02d9627d-9e4d-42d7-aff2-3b23a0caf990",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "a41718ce-4f74-46cf-acb4-6ebfc435ad6e"
},
{
"createdAt": "2013-02-25T16:27:54.671378",
"createdAt": "2025-06-12T14:56:30.070925",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 101,
"id": "9780ef6b-6820-478b-8d01-c972e683a8aa",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "a41718ce-4f74-46cf-acb4-6ebfc435ad6e"
},
{
"createdAt": "2013-02-25T16:27:54.671381",
"createdAt": "2025-06-12T14:56:30.070934",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 102,
"id": "29b0f3f1-6cd7-4c65-b431-882cf54f158c",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "a41718ce-4f74-46cf-acb4-6ebfc435ad6e"
}
]
}

View File

@@ -1,31 +1,31 @@
{
"snapshots": [
{
"createdAt": "2013-02-25T16:27:54.684999",
"createdAt": "2025-06-12T14:56:28.865898",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 100,
"id": "f3ddb3ee-7fed-4237-ac25-1d4d8c0fb127",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "4fe5b5eb-694e-4ead-ba98-ecffc6ff1d21"
},
{
"createdAt": "2013-02-25T16:27:54.685005",
"createdAt": "2025-06-12T14:56:28.865915",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 101,
"id": "d018c6d5-0a75-4001-aef2-9f9df82feb6e",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "4fe5b5eb-694e-4ead-ba98-ecffc6ff1d21"
},
{
"createdAt": "2013-02-25T16:27:54.685008",
"createdAt": "2025-06-12T14:56:28.865925",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 102,
"id": "df0a2535-bab9-4bec-b03b-656f741b1c45",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "4fe5b5eb-694e-4ead-ba98-ecffc6ff1d21"
}
]
}

View File

@@ -1,11 +1,11 @@
{
"snapshot": {
"createdAt": "2013-02-25T16:27:54.724209",
"createdAt": "2025-06-12T14:56:28.922532",
"displayDescription": "Default description",
"displayName": "Default name",
"id": "100",
"id": "ec675a13-5be8-4077-8381-9d70a12f77fb",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "d7bccf30-48a2-4cfc-a9c0-71c5ee144f61"
}
}

View File

@@ -9,7 +9,7 @@
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803"
}
],
"availabilityZone": "zone1:host1",
"availabilityZone": "dublin",
"createdAt": "1999-01-01T01:01:01.000000",
"displayDescription": "Volume Description",
"displayName": "Volume Name",
@@ -18,7 +18,7 @@
"size": 100,
"snapshotId": null,
"status": "in-use",
"volumeType": "Backup"
"volumeType": "vol_type_name"
}
]
}

View File

@@ -8,7 +8,7 @@
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803"
}
],
"availabilityZone": "zone1:host1",
"availabilityZone": "dublin",
"createdAt": "2013-02-18T14:51:18.528085",
"displayDescription": "Volume Description",
"displayName": "Volume Name",
@@ -17,6 +17,6 @@
"size": 100,
"snapshotId": null,
"status": "in-use",
"volumeType": "Backup"
"volumeType": "vol_type_name"
}
}
}

View File

@@ -9,7 +9,7 @@
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803"
}
],
"availabilityZone": "zone1:host1",
"availabilityZone": "dublin",
"createdAt": "2013-02-19T20:01:40.274897",
"displayDescription": "Volume Description",
"displayName": "Volume Name",
@@ -18,7 +18,7 @@
"size": 100,
"snapshotId": null,
"status": "in-use",
"volumeType": "Backup"
"volumeType": "vol_type_name"
}
]
}
}

View File

@@ -1,6 +1,6 @@
{
"volume": {
"availability_zone": "zone1:host1",
"availability_zone": "dublin",
"display_name": "Volume Name",
"display_description": "Volume Description",
"size": 100

View File

@@ -8,7 +8,7 @@
"volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803"
}
],
"availabilityZone": "zone1:host1",
"availabilityZone": "dublin",
"createdAt": "2013-02-18T14:51:17.970024",
"displayDescription": "Volume Description",
"displayName": "Volume Name",
@@ -17,6 +17,6 @@
"size": 100,
"snapshotId": null,
"status": "in-use",
"volumeType": "Backup"
"volumeType": "vol_type_name"
}
}
}

View File

@@ -0,0 +1,15 @@
{
"rebuild" : {
"accessIPv4" : "1.2.3.4",
"accessIPv6" : "80fe::",
"OS-DCF:diskConfig": "AUTO",
"imageRef" : "70a599e0-31e7-49b7-b260-868f441e862b",
"name" : "foobar",
"adminPass" : "seekr3t",
"hostname": "updated-hostname.example.com",
"metadata" : {
"meta_var" : "meta_val"
},
"user_data": "ZWNobyAiaGVsbG8gd29ybGQi"
}
}

View File

@@ -0,0 +1,25 @@
{
"server" : {
"accessIPv4": "1.2.3.4",
"accessIPv6": "80fe::",
"name" : "new-server-test",
"imageRef" : "70a599e0-31e7-49b7-b260-868f441e862b",
"flavorRef" : "1",
"OS-DCF:diskConfig": "AUTO",
"availability_zone": "us-west",
"metadata" : {
"My Server Name" : "Apache1"
},
"security_groups": [
{
"name": "default"
}
],
"user_data" : "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==",
"networks": "auto",
"hostname": "new-server-test"
},
"OS-SCH-HNT:scheduler_hints": {
"same_host": "48e6a9f6-30af-47e0-bc04-acaed113bb4e"
}
}

View File

@@ -3,7 +3,7 @@
"createdAt": "%(strtime)s",
"displayDescription": "%(description)s",
"displayName": "%(snapshot_name)s",
"id": 100,
"id": "%(uuid)s",
"size": 100,
"status": "available",
"volumeId": "%(uuid)s"

View File

@@ -4,28 +4,28 @@
"createdAt": "%(strtime)s",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 100,
"id": "%(uuid)s",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "%(uuid)s"
},
{
"createdAt": "%(strtime)s",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 101,
"id": "%(uuid)s",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "%(uuid)s"
},
{
"createdAt": "%(strtime)s",
"displayDescription": "Default description",
"displayName": "Default name",
"id": 102,
"id": "%(uuid)s",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "%(uuid)s"
}
]
}

View File

@@ -4,28 +4,28 @@
"createdAt": "%(strtime)s",
"displayDescription": "%(text)s",
"displayName": "%(text)s",
"id": 100,
"id": "%(uuid)s",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "%(uuid)s"
},
{
"createdAt": "%(strtime)s",
"displayDescription": "%(text)s",
"displayName": "%(text)s",
"id": 101,
"id": "%(uuid)s",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "%(uuid)s"
},
{
"createdAt": "%(strtime)s",
"displayDescription": "%(text)s",
"displayName": "%(text)s",
"id": 102,
"id": "%(uuid)s",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "%(uuid)s"
}
]
}

View File

@@ -3,9 +3,9 @@
"createdAt": "%(strtime)s",
"displayDescription": "%(description)s",
"displayName": "%(snapshot_name)s",
"id": "100",
"id": "%(uuid)s",
"size": 100,
"status": "available",
"volumeId": 12
"volumeId": "%(uuid)s"
}
}

View File

@@ -9,7 +9,7 @@
"volumeId": "%(uuid)s"
}
],
"availabilityZone": "zone1:host1",
"availabilityZone": "dublin",
"createdAt": "%(strtime)s",
"displayDescription": "%(volume_desc)s",
"displayName": "%(volume_name)s",
@@ -18,7 +18,7 @@
"size": 100,
"snapshotId": null,
"status": "in-use",
"volumeType": "Backup"
"volumeType": "vol_type_name"
}
]
}

View File

@@ -8,7 +8,7 @@
"volumeId": "%(uuid)s"
}
],
"availabilityZone": "zone1:host1",
"availabilityZone": "dublin",
"createdAt": "%(strtime)s",
"displayDescription": "%(volume_desc)s",
"displayName": "%(volume_name)s",
@@ -17,6 +17,6 @@
"size": 100,
"snapshotId": null,
"status": "in-use",
"volumeType": "Backup"
"volumeType": "vol_type_name"
}
}

View File

@@ -9,7 +9,7 @@
"volumeId": "%(uuid)s"
}
],
"availabilityZone": "zone1:host1",
"availabilityZone": "dublin",
"createdAt": "%(strtime)s",
"displayDescription": "%(volume_desc)s",
"displayName": "%(volume_name)s",
@@ -18,7 +18,7 @@
"size": 100,
"snapshotId": null,
"status": "in-use",
"volumeType": "Backup"
"volumeType": "vol_type_name"
}
]
}

View File

@@ -1,6 +1,6 @@
{
"volume": {
"availability_zone": "zone1:host1",
"availability_zone": "dublin",
"display_name": "%(volume_name)s",
"display_description": "%(volume_desc)s",
"size": 100

View File

@@ -2,7 +2,7 @@
"volume": {
"status": "in-use",
"displayDescription": "%(volume_desc)s",
"availabilityZone": "zone1:host1",
"availabilityZone": "dublin",
"displayName": "%(volume_name)s",
"attachments": [
{ "device": "/",
@@ -11,7 +11,7 @@
"volumeId": "%(uuid)s"
}
],
"volumeType": "Backup",
"volumeType": "vol_type_name",
"snapshotId": null,
"metadata": {},
"id": "%(uuid)s",

View File

@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils.fixture import uuidsentinel as uuids
from nova.tests.functional.api_sample_tests import api_sample_base
from nova.tests.unit.api.openstack import fakes
@@ -54,7 +56,7 @@ class SnapshotsSampleJsonTests(api_sample_base.ApiSampleTestBaseV21):
def test_snapshots_delete(self):
self._create_snapshot()
response = self._do_delete('os-snapshots/100')
response = self._do_delete(f'os-snapshots/{uuids.snapshot}')
self.assertEqual(202, response.status_code)
self.assertEqual('', response.text)
@@ -67,7 +69,7 @@ class SnapshotsSampleJsonTests(api_sample_base.ApiSampleTestBaseV21):
self._verify_response('snapshots-list-resp', {}, response, 200)
def test_snapshots_show(self):
response = self._do_get('os-snapshots/100')
response = self._do_get(f'os-snapshots/{uuids.snapshot}')
subs = {
'snapshot_name': 'Default name',
'description': 'Default description'

View File

@@ -13,62 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import datetime
from oslo_utils.fixture import uuidsentinel as uuids
from nova.tests.functional.api_sample_tests import test_servers
from nova.tests.unit.api.openstack import fakes
def _get_volume_id():
return 'a26887c6-c47b-4654-abb5-dfadf7d3f803'
def _stub_volume(id, displayname="Volume Name",
displaydesc="Volume Description", size=100):
volume = {
'id': id,
'size': size,
'availability_zone': 'zone1:host1',
'status': 'in-use',
'attach_status': 'attached',
'name': 'vol name',
'display_name': displayname,
'display_description': displaydesc,
'created_at': datetime.datetime(2008, 12, 1, 11, 1, 55),
'snapshot_id': None,
'volume_type_id': 'fakevoltype',
'volume_metadata': [],
'volume_type': {'name': 'Backup'},
'multiattach': False,
'attachments': {'3912f2b4-c5ba-4aec-9165-872876fe202e':
{'mountpoint': '/',
'attachment_id':
'a26887c6-c47b-4654-abb5-dfadf7d3f803'
}
}
}
return volume
def _stub_volume_get(stub_self, context, volume_id):
return _stub_volume(volume_id)
def _stub_volume_delete(stub_self, context, *args, **param):
pass
def _stub_volume_get_all(stub_self, context, search_opts=None):
id = _get_volume_id()
return [_stub_volume(id)]
def _stub_volume_create(stub_self, context, size, name, description,
snapshot, **param):
id = _get_volume_id()
return _stub_volume(id)
class VolumesSampleJsonTest(test_servers.ServersSampleBase):
sample_dir = "os-volumes"
@@ -76,37 +26,36 @@ class VolumesSampleJsonTest(test_servers.ServersSampleBase):
super().setUp()
fakes.stub_out_networking(self)
self.stub_out("nova.volume.cinder.API.delete",
_stub_volume_delete)
self.stub_out("nova.volume.cinder.API.get", _stub_volume_get)
self.stub_out("nova.volume.cinder.API.get_all",
_stub_volume_get_all)
self.stub_out(
"nova.volume.cinder.API.delete", fakes.stub_volume_delete)
self.stub_out("nova.volume.cinder.API.get", fakes.stub_volume_get)
self.stub_out(
"nova.volume.cinder.API.get_all", fakes.stub_volume_get_all)
self.stub_out(
"nova.volume.cinder.API.create", fakes.stub_volume_create)
def _post_volume(self):
subs_req = {
'volume_name': "Volume Name",
'volume_desc': "Volume Description",
'volume_name': "Volume Name",
'volume_desc': "Volume Description",
}
self.stub_out("nova.volume.cinder.API.create",
_stub_volume_create)
response = self._do_post('os-volumes', 'os-volumes-post-req',
subs_req)
self._verify_response('os-volumes-post-resp', subs_req, response, 200)
def test_volumes_show(self):
subs = {
'volume_name': "Volume Name",
'volume_desc': "Volume Description",
'volume_name': "Volume Name",
'volume_desc': "Volume Description",
}
vol_id = _get_volume_id()
response = self._do_get('os-volumes/%s' % vol_id)
response = self._do_get(f'os-volumes/{uuids.volume}')
self._verify_response('os-volumes-get-resp', subs, response, 200)
def test_volumes_index(self):
subs = {
'volume_name': "Volume Name",
'volume_desc': "Volume Description",
'volume_name': "Volume Name",
'volume_desc': "Volume Description",
}
response = self._do_get('os-volumes')
self._verify_response('os-volumes-index-resp', subs, response, 200)
@@ -115,8 +64,8 @@ class VolumesSampleJsonTest(test_servers.ServersSampleBase):
# For now, index and detail are the same.
# See the volumes api
subs = {
'volume_name': "Volume Name",
'volume_desc': "Volume Description",
'volume_name': "Volume Name",
'volume_desc': "Volume Description",
}
response = self._do_get('os-volumes/detail')
self._verify_response('os-volumes-detail-resp', subs, response, 200)
@@ -126,7 +75,6 @@ class VolumesSampleJsonTest(test_servers.ServersSampleBase):
def test_volumes_delete(self):
self._post_volume()
vol_id = _get_volume_id()
response = self._do_delete('os-volumes/%s' % vol_id)
response = self._do_delete(f'os-volumes/{uuids.volume}')
self.assertEqual(202, response.status_code)
self.assertEqual('', response.text)

View File

@@ -15,6 +15,7 @@
from unittest import mock
from oslo_utils.fixture import uuidsentinel as uuids
import webob
from nova.api.openstack.compute import snapshots
@@ -23,11 +24,8 @@ from nova import test
from nova.tests.unit.api.openstack import fakes
from nova.volume import cinder
FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
class SnapshotApiTestV21(test.NoDBTestCase):
def setUp(self):
super().setUp()
fakes.stub_out_networking(self)
@@ -46,7 +44,7 @@ class SnapshotApiTestV21(test.NoDBTestCase):
self.req = fakes.HTTPRequest.blank('')
def _test_snapshot_create(self, force):
snapshot = {"volume_id": '12',
snapshot = {"volume_id": uuids.volume,
"force": force,
"display_name": "Snapshot Test Name",
"display_description": "Snapshot Test Desc"}
@@ -69,8 +67,9 @@ class SnapshotApiTestV21(test.NoDBTestCase):
def test_snapshot_create_invalid_force_param(self):
body = {'snapshot': {'volume_id': '1',
'force': '**&&^^%%$$##@@'}}
self.assertRaises(exception.ValidationError,
self.controller.create, self.req, body=body)
self.assertRaises(
exception.ValidationError,
self.controller.create, self.req, body=body)
def test_create_no_body(self):
self.assertRaises(
@@ -90,37 +89,29 @@ class SnapshotApiTestV21(test.NoDBTestCase):
self.controller.create, self.req, body=body)
def test_snapshot_delete(self):
snapshot_id = '123'
delete = self.controller.delete
result = delete(self.req, snapshot_id)
self.controller.delete(self.req, uuids.snapshot)
# NOTE: on v2.1, http status code is set as wsgi_codes of API
# method instead of status_int in a response object.
if isinstance(self.controller, snapshots.SnapshotController):
status_int = delete.wsgi_codes(self.req)
else:
status_int = result.status_int
status_int = self.controller.delete.wsgi_codes(self.req)
self.assertEqual(202, status_int)
@mock.patch.object(cinder.API, 'delete_snapshot',
side_effect=exception.SnapshotNotFound(snapshot_id=FAKE_UUID))
def test_delete_snapshot_not_exists(self, mock_mr):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
self.req, FAKE_UUID)
def test_snapshot_delete_invalid_id(self):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
self.req, '-1')
side_effect=exception.SnapshotNotFound(snapshot_id=uuids.missing))
def test_snapshot_delete_not_exists(self, mock_mr):
self.assertRaises(
webob.exc.HTTPNotFound, self.controller.delete,
self.req, uuids.missing)
def test_snapshot_show(self):
snapshot_id = '123'
resp_dict = self.controller.show(self.req, snapshot_id)
resp_dict = self.controller.show(self.req, uuids.snapshot)
self.assertIn('snapshot', resp_dict)
self.assertEqual(str(snapshot_id), resp_dict['snapshot']['id'])
self.assertEqual(uuids.snapshot, resp_dict['snapshot']['id'])
def test_snapshot_show_invalid_id(self):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.show,
self.req, '-1')
@mock.patch.object(cinder.API, 'get_snapshot',
side_effect=exception.SnapshotNotFound(snapshot_id=uuids.missing))
def test_snapshot_show_not_exists(self, mock_mr):
self.assertRaises(
webob.exc.HTTPNotFound, self.controller.show,
self.req, uuids.missing)
def test_snapshot_detail(self):
resp_dict = self.controller.detail(self.req)
@@ -129,7 +120,7 @@ class SnapshotApiTestV21(test.NoDBTestCase):
self.assertEqual(3, len(resp_snapshots))
resp_snapshot = resp_snapshots.pop()
self.assertEqual(102, resp_snapshot['id'])
self.assertEqual(uuids.snapshot_c, resp_snapshot['id'])
def test_snapshot_detail_offset_and_limit(self):
path = '/v2.1/os-snapshots/detail?offset=1&limit=1'
@@ -140,7 +131,7 @@ class SnapshotApiTestV21(test.NoDBTestCase):
self.assertEqual(1, len(resp_snapshots))
resp_snapshot = resp_snapshots.pop()
self.assertEqual(101, resp_snapshot['id'])
self.assertEqual(uuids.snapshot_b, resp_snapshot['id'])
def test_snapshot_index(self):
resp_dict = self.controller.index(self.req)
@@ -246,9 +237,9 @@ class TestSnapshotAPIDeprecation(test.NoDBTestCase):
def test_all_apis_return_not_found(self):
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.show, self.req, fakes.FAKE_UUID)
self.controller.show, self.req, uuids.snapshot_id)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.delete, self.req, fakes.FAKE_UUID)
self.controller.delete, self.req, uuids.snapshot_id)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.index, self.req)
self.assertRaises(exception.VersionNotFoundForAPIMethod,

View File

@@ -98,7 +98,6 @@ def fake_bdm_get_by_volume_and_instance(cls, ctxt, volume_id, instance_uuid):
class VolumeAttachTestsV21(test.NoDBTestCase):
validation_error = exception.ValidationError
microversion = '2.1'
_prefix = '/servers/id/os-volume_attachments'
@@ -367,7 +366,7 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
'volumeId': 'TESTVOLUME',
}
}
self.assertRaises(self.validation_error, self.controller.create,
self.assertRaises(exception.ValidationError, self.controller.create,
self.req, FAKE_UUID, body=body)
@mock.patch.object(compute_api.API, 'attach_volume',
@@ -397,7 +396,7 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
}
}
self.assertRaises(self.validation_error, self.controller.create,
self.assertRaises(exception.ValidationError, self.controller.create,
self.req, FAKE_UUID, body=body)
def test_attach_volume_with_extra_arg(self):
@@ -407,7 +406,7 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
'device': '/dev/fake',
'extra': 'extra_arg'}}
self.assertRaises(self.validation_error, self.controller.create,
self.assertRaises(exception.ValidationError, self.controller.create,
self.req, FAKE_UUID, body=body)
@mock.patch.object(compute_api.API, 'attach_volume')
@@ -490,7 +489,7 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
def test_swap_volume_without_volumeId(self):
body = {'volumeAttachment': {'device': '/dev/fake'}}
self.assertRaises(self.validation_error,
self.assertRaises(exception.ValidationError,
self._test_swap,
self.controller,
body=body)
@@ -499,7 +498,7 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
body = {'volumeAttachment': {'volumeId': FAKE_UUID_A,
'device': '/dev/fake'}}
self.assertRaises(self.validation_error,
self.assertRaises(exception.ValidationError,
self._test_swap,
self.controller,
body=body)
@@ -587,7 +586,6 @@ class VolumeAttachTestsV21(test.NoDBTestCase):
class VolumeAttachTestsV249(test.NoDBTestCase):
validation_error = exception.ValidationError
def setUp(self):
super().setUp()
@@ -617,7 +615,7 @@ class VolumeAttachTestsV249(test.NoDBTestCase):
self.assertRaises(exception.ValidationError, self.controller.create,
self.req, FAKE_UUID, body=body)
@mock.patch('nova.compute.api.API.attach_volume')
@mock.patch('nova.compute.api.API.attach_volume', return_value='/dev/fake')
@mock.patch('nova.compute.api.API.get', fake_get_instance)
def test_tagged_volume_attach_valid_tag(self, _):
body = {'volumeAttachment': {'volumeId': FAKE_UUID_A,
@@ -722,7 +720,7 @@ class VolumeAttachTestsV275(VolumeAttachTestsV21):
def test_list_with_additional_filter(self):
req = self._build_request(
'?limit=1&additional=something')
self.assertRaises(self.validation_error, self.controller.index,
self.assertRaises(exception.ValidationError, self.controller.index,
req, FAKE_UUID)
@@ -907,7 +905,7 @@ class VolumeAttachTestsV285(VolumeAttachTestsV279):
'device': '/dev/fake0',
'notathing': 'foo'}}
self.assertRaises(self.validation_error,
self.assertRaises(exception.ValidationError,
self._test_swap,
self.controller,
body=body)
@@ -1256,7 +1254,7 @@ class VolumeAttachTestsV289(VolumeAttachTestsV285):
'volumeId': FAKE_UUID_A,
'tag': None,
'delete_on_termination': False,
'attachment_id': None,
'attachment_id': uuids.attachment_id,
'bdm_uuid': uuids.bdm,
}
}

View File

@@ -31,9 +31,6 @@ from nova.volume import cinder
CONF = nova.conf.CONF
FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
IMAGE_UUID = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77'
class BootFromVolumeTest(test.TestCase):
@@ -56,11 +53,11 @@ class BootFromVolumeTest(test.TestCase):
resv_id = None
return ([{'id': 1,
'display_name': 'test_server',
'uuid': FAKE_UUID,
'uuid': uuids.server,
'flavor': flavor,
'access_ip_v4': '1.2.3.4',
'access_ip_v6': 'fead::1234',
'image_ref': IMAGE_UUID,
'image_ref': uuids.image,
'user_id': 'fake',
'project_id': fakes.FAKE_PROJECT_ID,
'created_at': datetime.datetime(2010, 10, 10, 12, 0, 0),
@@ -72,7 +69,7 @@ class BootFromVolumeTest(test.TestCase):
def test_create_root_volume(self):
body = dict(server=dict(
name='test_server', imageRef=IMAGE_UUID,
name='test_server', imageRef=uuids.image,
flavorRef=2, min_count=1, max_count=1,
block_device_mapping=[dict(
volume_id='ca9fe3f5-cede-43cb-8050-1672acabe348',
@@ -88,7 +85,7 @@ class BootFromVolumeTest(test.TestCase):
res = req.get_response(fakes.wsgi_app_v21())
self.assertEqual(202, res.status_int)
server = jsonutils.loads(res.body)['server']
self.assertEqual(FAKE_UUID, server['id'])
self.assertEqual(uuids.server, server['id'])
self.assertEqual(CONF.password_length, len(server['adminPass']))
self.assertEqual(1, len(self._block_device_mapping_seen))
self.assertTrue(self._legacy_bdm_seen)
@@ -99,7 +96,7 @@ class BootFromVolumeTest(test.TestCase):
def test_create_root_volume_bdm_v2(self):
body = dict(server=dict(
name='test_server', imageRef=IMAGE_UUID,
name='test_server', imageRef=uuids.image,
flavorRef=2, min_count=1, max_count=1,
block_device_mapping_v2=[dict(
source_type='volume',
@@ -117,7 +114,7 @@ class BootFromVolumeTest(test.TestCase):
res = req.get_response(fakes.wsgi_app_v21())
self.assertEqual(202, res.status_int)
server = jsonutils.loads(res.body)['server']
self.assertEqual(FAKE_UUID, server['id'])
self.assertEqual(uuids.server, server['id'])
self.assertEqual(CONF.password_length, len(server['adminPass']))
self.assertEqual(1, len(self._block_device_mapping_seen))
self.assertFalse(self._legacy_bdm_seen)
@@ -132,13 +129,13 @@ class VolumeApiTestV21(test.NoDBTestCase):
super().setUp()
fakes.stub_out_networking(self)
self.stub_out('nova.volume.cinder.API.create',
fakes.stub_volume_create)
self.stub_out('nova.volume.cinder.API.delete',
lambda self, context, volume_id: None)
self.stub_out(
'nova.volume.cinder.API.create', fakes.stub_volume_create)
self.stub_out(
'nova.volume.cinder.API.delete', fakes.stub_volume_delete)
self.stub_out('nova.volume.cinder.API.get', fakes.stub_volume_get)
self.stub_out('nova.volume.cinder.API.get_all',
fakes.stub_volume_get_all)
self.stub_out(
'nova.volume.cinder.API.get_all', fakes.stub_volume_get_all)
self.controller = volumes_v21.VolumeController()
self.req = fakes.HTTPRequest.blank('')
@@ -147,7 +144,7 @@ class VolumeApiTestV21(test.NoDBTestCase):
vol = {"size": 100,
"display_name": "Volume Test Name",
"display_description": "Volume Test Desc",
"availability_zone": "zone1:host1"}
"availability_zone": "dublin"}
body = {"volume": vol}
resp = self.controller.create(self.req, body=body).obj
@@ -168,7 +165,7 @@ class VolumeApiTestV21(test.NoDBTestCase):
vol = {"size": '10',
"display_name": "Volume Test Name",
"display_description": "Volume Test Desc",
"availability_zone": "zone1:host1"}
"availability_zone": "dublin"}
body = {"volume": vol}
self.assertRaises(api_exc,
@@ -176,7 +173,7 @@ class VolumeApiTestV21(test.NoDBTestCase):
body=body)
mock_create.assert_called_once_with(
mock.ANY, '10', 'Volume Test Name',
'Volume Test Desc', availability_zone='zone1:host1',
'Volume Test Desc', availability_zone='dublin',
metadata=None, snapshot=None, volume_type=None)
@mock.patch.object(cinder.API, 'get_snapshot')
@@ -335,9 +332,9 @@ class TestVolumesAPIDeprecation(test.NoDBTestCase):
def test_all_apis_return_not_found(self):
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.show, self.req, fakes.FAKE_UUID)
self.controller.show, self.req, uuids.volume)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.delete, self.req, fakes.FAKE_UUID)
self.controller.delete, self.req, uuids.volume)
self.assertRaises(exception.VersionNotFoundForAPIMethod,
self.controller.index, self.req)
self.assertRaises(exception.VersionNotFoundForAPIMethod,

View File

@@ -43,11 +43,9 @@ from nova.tests.unit import fake_block_device
from nova.tests.unit.objects import test_keypair
from nova import utils
CONF = nova.conf.CONF
QUOTAS = quota.QUOTAS
FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
FAKE_PROJECT_ID = '6a6a9c9eee154e9cb8cec487b98d36ab'
FAKE_USER_ID = '5fae60f5cf4642609ddd31f71748beac'
@@ -575,36 +573,40 @@ def stub_instance_obj(ctxt, *args, **kwargs):
def stub_volume(id, **kwargs):
# volumes IDs should be UUIDs
assert uuidutils.is_uuid_like(id), f'expected UUID, got {id}'
volume = {
'id': id,
'user_id': 'fakeuser',
'project_id': 'fakeproject',
'host': 'fakehost',
'size': 1,
'availability_zone': 'fakeaz',
'status': 'fakestatus',
'size': 100,
'availability_zone': 'dublin',
'status': 'in-use',
'attach_status': 'attached',
'name': 'vol name',
'display_name': 'displayname',
'display_description': 'displaydesc',
'created_at': datetime.datetime(1999, 1, 1, 1, 1, 1),
'display_name': 'Volume Name',
'display_description': 'Volume Description',
'created_at': datetime.datetime(2008, 12, 1, 11, 1, 55),
'snapshot_id': None,
'volume_type_id': 'fakevoltype',
'volume_metadata': [],
'volume_type': {'name': 'vol_type_name'},
'multiattach': False,
'attachments': {'fakeuuid': {'mountpoint': '/'},
'fakeuuid2': {'mountpoint': '/dev/sdb'}
}
}
'attachments': {
uuids.server: {
'mountpoint': '/',
'attachment_id': 'a26887c6-c47b-4654-abb5-dfadf7d3f803',
}
}
}
volume.update(kwargs)
return volume
def stub_volume_create(self, context, size, name, description, snapshot,
**param):
vol = stub_volume('1')
vol = stub_volume(uuids.volume)
vol['size'] = size
vol['display_name'] = name
vol['display_description'] = description
@@ -612,10 +614,14 @@ def stub_volume_create(self, context, size, name, description, snapshot,
vol['snapshot_id'] = snapshot['id']
except (KeyError, TypeError):
vol['snapshot_id'] = None
vol['availability_zone'] = param.get('availability_zone', 'fakeaz')
vol['availability_zone'] = param.get('availability_zone', 'dublin')
return vol
def stub_volume_delete(self, context, id):
assert uuidutils.is_uuid_like(id)
def stub_volume_update(self, context, *args, **param):
pass
@@ -625,9 +631,10 @@ def stub_volume_get(self, context, volume_id):
def stub_volume_get_all(context, search_opts=None):
return [stub_volume(100, project_id='fake'),
stub_volume(101, project_id='superfake'),
stub_volume(102, project_id='superduperfake')]
return [
stub_volume(
uuids.volume_a, project_id='ccbab0871dac4d598a4142f0583d94b2'),
]
def stub_volume_check_attach(self, context, *args, **param):
@@ -635,24 +642,31 @@ def stub_volume_check_attach(self, context, *args, **param):
def stub_snapshot(id, **kwargs):
# snapshot IDs should be UUIDs
assert uuidutils.is_uuid_like(id), f'expected UUID, got {id}'
if 'volume_id' in kwargs:
assert uuidutils.is_uuid_like(kwargs['volume_id'])
snapshot = {
'id': id,
'volume_id': 12,
'volume_id': uuids.volume,
'status': 'available',
'volume_size': 100,
'created_at': timeutils.utcnow(),
'display_name': 'Default name',
'display_description': 'Default description',
'project_id': 'fake'
}
}
snapshot.update(kwargs)
return snapshot
def stub_snapshot_create(self, context, volume_id, name, description):
return stub_snapshot(100, volume_id=volume_id, display_name=name,
display_description=description)
return stub_snapshot(
uuids.snapshot, volume_id=volume_id, display_name=name,
display_description=description)
def stub_compute_volume_snapshot_create(self, context, volume_id, create_info):
@@ -660,9 +674,9 @@ def stub_compute_volume_snapshot_create(self, context, volume_id, create_info):
'volumeId': volume_id}}
def stub_snapshot_delete(self, context, snapshot_id):
if snapshot_id == '-1':
raise exc.SnapshotNotFound(snapshot_id=snapshot_id)
def stub_snapshot_delete(self, context, id):
# snapshot IDs should be UUIDs
assert uuidutils.is_uuid_like(id), f'expected UUID, got {id}'
def stub_compute_volume_snapshot_delete(self, context, volume_id, snapshot_id,
@@ -670,16 +684,14 @@ def stub_compute_volume_snapshot_delete(self, context, volume_id, snapshot_id,
pass
def stub_snapshot_get(self, context, snapshot_id):
if snapshot_id == '-1':
raise exc.SnapshotNotFound(snapshot_id=snapshot_id)
return stub_snapshot(snapshot_id)
def stub_snapshot_get(self, context, id):
return stub_snapshot(id)
def stub_snapshot_get_all(self, context):
return [stub_snapshot(100, project_id='fake'),
stub_snapshot(101, project_id='superfake'),
stub_snapshot(102, project_id='superduperfake')]
return [stub_snapshot(uuids.snapshot_a, project_id='fake'),
stub_snapshot(uuids.snapshot_b, project_id='superfake'),
stub_snapshot(uuids.snapshot_c, project_id='superduperfake')]
def stub_bdm_get_all_by_instance_uuids(context, instance_uuids,

View File

@@ -40,6 +40,7 @@ class FakeDbBlockDeviceDict(block_device.BlockDeviceDict):
bdm_dict = bdm_dict or {}
db_id = bdm_dict.pop('id', 1)
db_uuid = bdm_dict.pop('uuid', uuids.bdm)
db_attachment_id = bdm_dict.get('attachment_id', None)
instance_uuid = bdm_dict.pop('instance_uuid', uuids.fake)
super(FakeDbBlockDeviceDict, self).__init__(bdm_dict=bdm_dict,
@@ -50,7 +51,7 @@ class FakeDbBlockDeviceDict(block_device.BlockDeviceDict):
if not anon:
fake_db_fields['id'] = db_id
fake_db_fields['uuid'] = db_uuid
fake_db_fields['attachment_id'] = None
fake_db_fields['attachment_id'] = db_attachment_id
fake_db_fields['created_at'] = timeutils.utcnow()
fake_db_fields['updated_at'] = timeutils.utcnow()
self.update(fake_db_fields)

View File

@@ -21,6 +21,17 @@ from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.policies import base
fake_snapshot = {
'created_at': '2024-11-26T18:20:21.000000',
'display_name': 'foo',
'display_description': None,
'id': uuids.snapshot_id,
'status': 'available',
'volume_id': uuids.volume_id,
'volume_size': 1,
}
class SnapshotsPolicyTest(base.BasePolicyTest):
"""Test Snapshots APIs policies with all possible context.
@@ -66,6 +77,7 @@ class SnapshotsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.volume.cinder.API.get_all_snapshots')
def test_list_snapshots_policy(self, mock_get):
mock_get.return_value = []
rule_name = "os_compute_api:os-volumes:snapshots:list"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.snapshot_ctlr.index,
@@ -73,6 +85,7 @@ class SnapshotsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.volume.cinder.API.get_all_snapshots')
def test_list_detail_snapshots_policy(self, mock_get):
mock_get.return_value = []
rule_name = "os_compute_api:os-volumes:snapshots:detail"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.snapshot_ctlr.detail,
@@ -80,6 +93,7 @@ class SnapshotsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.volume.cinder.API.get_snapshot')
def test_show_snapshot_policy(self, mock_get):
mock_get.return_value = fake_snapshot
rule_name = "os_compute_api:os-volumes:snapshots:show"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.snapshot_ctlr.show,
@@ -87,6 +101,7 @@ class SnapshotsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.volume.cinder.API.create_snapshot')
def test_create_snapshot_policy(self, mock_create):
mock_create.return_value = fake_snapshot
rule_name = "os_compute_api:os-volumes:snapshots:create"
body = {"snapshot": {"volume_id": uuids.fake_id}}
self.common_policy_auth(self.project_member_authorized_contexts,

View File

@@ -140,6 +140,7 @@ class VolumeAttachPolicyTest(base.BasePolicyTest):
@mock.patch('nova.compute.api.API.attach_volume')
def test_create_volume_attach_policy(self, mock_attach_volume):
mock_attach_volume.return_value = '/dev/sdb'
rule_name = self.policy_root % "create"
body = {'volumeAttachment': {'volumeId': FAKE_UUID_B,
'device': '/dev/fake'}}

View File

@@ -81,20 +81,42 @@ class VolumesPolicyTest(base.BasePolicyTest):
@mock.patch('nova.volume.cinder.API.get')
def test_show_volume_policy(self, mock_get):
mock_get.return_value = {
'attach_status': 'detached',
'availability_zone': 'nova',
'created_at': '2024-11-26T18:20:21.000000',
'display_name': 'foo',
'display_description': None,
'id': uuids.volume_id,
'size': 1,
'snapshot_id': None,
'status': 'available',
'volume_type_id': uuids.volume_type_id,
}
rule_name = "os_compute_api:os-volumes:show"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.show,
self.req, uuids.fake_id)
@mock.patch('nova.api.openstack.compute.volumes.'
'_translate_volume_detail_view')
@mock.patch('nova.volume.cinder.API.create')
def test_create_volumes_policy(self, mock_create, mock_view):
def test_create_volumes_policy(self, mock_create):
mock_create.return_value = {
'attach_status': 'detached',
'availability_zone': 'nova',
'created_at': '2024-11-26T18:20:21.000000',
'display_name': 'foo',
'display_description': None,
'id': uuids.volume_id,
'size': 1,
'snapshot_id': None,
'status': 'available',
'volume_type_id': uuids.volume_type_id,
}
rule_name = "os_compute_api:os-volumes:create"
body = {"volume": {"size": 100,
"display_name": "Volume Test Name",
"display_description": "Volume Test Desc",
"availability_zone": "zone1:host1"}}
"availability_zone": "dublin"}}
self.common_policy_auth(self.project_member_authorized_contexts,
rule_name, self.controller.create,
self.req, body=body)