Merge "tests: Use valid UUIDs for cinder resources"

This commit is contained in:
Zuul
2025-08-27 05:36:22 +00:00
committed by Gerrit Code Review
32 changed files with 270 additions and 232 deletions
@@ -0,0 +1,6 @@
{
"share": {
"share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986",
"tag": "my-tag"
}
}
@@ -0,0 +1,5 @@
{
"share": {
"share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986"
}
}
@@ -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"
@@ -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"
}
]
}
@@ -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"
}
]
}
@@ -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"
}
}
@@ -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"
}
]
}
@@ -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"
}
}
}
@@ -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"
}
]
}
}
@@ -1,6 +1,6 @@
{
"volume": {
"availability_zone": "zone1:host1",
"availability_zone": "dublin",
"display_name": "Volume Name",
"display_description": "Volume Description",
"size": 100
@@ -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"
}
}
}
@@ -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"
}
}
@@ -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"
}
}
@@ -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"
@@ -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"
}
]
}
@@ -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"
}
]
}
@@ -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"
}
}
@@ -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"
}
]
}
@@ -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"
}
}
@@ -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"
}
]
}
@@ -1,6 +1,6 @@
{
"volume": {
"availability_zone": "zone1:host1",
"availability_zone": "dublin",
"display_name": "%(volume_name)s",
"display_description": "%(volume_desc)s",
"size": 100
@@ -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",
@@ -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'
@@ -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)
@@ -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,
@@ -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,
}
}
@@ -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,
+44 -32
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,
+2 -1
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)
@@ -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,
@@ -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'}}
+26 -4
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)