Automate generation of volume actions api-ref samples

This patch adds the following tests:

1) Volume actions
2) Volume manage extensions

Change-Id: I7f27a336a6735f4d346cc47c983dfee55f47f55d
Partially-Implements: blueprint generating-sample-files
This commit is contained in:
whoami-rajat 2019-01-24 16:32:14 +05:30
parent 3902a2bf28
commit 15d1a00a57
17 changed files with 252 additions and 58 deletions

View File

@ -1,33 +0,0 @@
{
"volume": {
"status": "creating",
"user_id": "eae1472b5fc5496998a3d06550929e7e",
"attachments": [],
"links": [
{
"href": "http://10.0.2.15:8776/v3/87c8522052ca4eed98bc672b4c1a3ddb/volumes/23cf872b-c781-4cd4-847d-5f2ec8cbd91c",
"rel": "self"
},
{
"href": "http://10.0.2.15:8776/87c8522052ca4eed98bc672b4c1a3ddb/volumes/23cf872b-c781-4cd4-847d-5f2ec8cbd91c",
"rel": "bookmark"
}
],
"availability_zone": "az2",
"bootable": "false",
"encrypted": "false",
"created_at": "2014-07-18T00:12:54.000000",
"description": "Volume imported from existingLV",
"os-vol-tenant-attr:tenant_id": "87c8522052ca4eed98bc672b4c1a3ddb",
"volume_type": null,
"name": "New Volume",
"source_volid": null,
"snapshot_id": null,
"metadata": {
"key2": "value2",
"key1": "value1"
},
"id": "23cf872b-c781-4cd4-847d-5f2ec8cbd91c",
"size": 0
}
}

View File

@ -1,16 +1,16 @@
{
"os-volume_upload_image": {
"status": "uploading",
"container_format": "bare",
"image_name": "test",
"visibility": "private",
"updated_at": "2017-06-05T08:44:28.000000",
"image_id": "de75b74e-7f0d-4b59-a263-bd87bfc313bd",
"disk_format": "raw",
"display_description": null,
"id": "3a81fdac-e8ae-4e61-b6a2-2e14ff316f19",
"image_id": "de75b74e-7f0d-4b59-a263-bd87bfc313bd",
"image_name": "test",
"protected": false,
"size": 1,
"disk_format": "raw",
"volume_type": null,
"protected": false
"status": "uploading",
"updated_at": "2017-06-05T08:44:28.000000",
"visibility": "private",
"volume_type": null
}
}

View File

@ -0,0 +1,17 @@
{
"availability_zone": "az2",
"bootable": true,
"cluster": "cluster@backend",
"description": "Volume imported from existingLV",
"host": "null",
"metadata": {
"key1": "value1",
"key2": "value2"
},
"name": "New Volume",
"ref": {
"source-id": "1234",
"source-name": "existingLV"
},
"volume_type": "null"
}

View File

@ -56,7 +56,7 @@ Request
Request Example
---------------
.. literalinclude:: ./samples/volume-manage-request.json
.. literalinclude:: ./samples/volume_manage_extensions/volume-manage-request.json
:language: javascript
.. literalinclude:: ./samples/volume-manage-request-cluster.json
@ -94,7 +94,7 @@ Response
Response Example
----------------
.. literalinclude:: ./samples/volume-manage-response.json
.. literalinclude:: ./samples/volume_manage_extensions/volume-manage-response.json
:language: javascript

View File

@ -644,7 +644,7 @@ Request
Request Example
---------------
.. literalinclude:: ./samples/volume-upload-to-image-request.json
.. literalinclude:: ./samples/volume_actions/volume-upload-to-image-request.json
:language: javascript
Response Parameters
@ -670,7 +670,7 @@ Response Parameters
Response Example
----------------
.. literalinclude:: ./samples/volume-upload-to-image-response.json
.. literalinclude:: ./samples/volume_actions/volume-upload-to-image-response.json
:language: javascript

View File

@ -437,6 +437,17 @@ class TestCase(testtools.TestCase):
kwargs.setdefault('message', msg)
self.assertIs(False, x, *args, **kwargs)
def stub_out(self, old, new):
"""Replace a function for the duration of the test.
Use the monkey patch fixture to replace a function for the
duration of a test. Useful when you want to provide fake
methods instead of mocks during testing.
This should be used instead of self.stubs.Set (which is based
on mox) going forward.
"""
self.useFixture(fixtures.MonkeyPatch(old, new))
class ModelsObjectComparatorMixin(object):
def _dict_from_object(self, obj, ignored_keys):

View File

@ -0,0 +1,51 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def stub_copy_volume_to_image(self, context, volume, metadata, force):
image_metadata = {
"status": "uploading",
"container_format": "bare",
"image_name": "test",
"visibility": "private",
"updated_at": "2017-06-05T08:44:28.000000",
"image_id": "de75b74e-7f0d-4b59-a263-bd87bfc313bd",
"display_description": None,
"id": "3a81fdac-e8ae-4e61-b6a2-2e14ff316f19",
"size": 1,
"disk_format": "raw",
"volume_type": None,
"protected": False
}
return image_metadata
def stub_manage_existing(self, req, body):
volume = {
"host": "null",
"cluster": "cluster@backend",
"ref": {
"source-name": "existingLV",
"source-id": "1234"
},
"name": "New Volume",
"availability_zone": "az2",
"description": "Volume imported from existingLV",
"volume_type": "null",
"bootable": True,
"metadata": {
"key1": "value1",
"key2": "value2"
}
}
return volume

View File

@ -0,0 +1,8 @@
{
"os-volume_upload_image":{
"image_name": "test",
"force": false,
"disk_format": "raw",
"container_format": "bare"
}
}

View File

@ -0,0 +1,16 @@
{
"os-volume_upload_image": {
"container_format": "bare",
"disk_format": "raw",
"display_description": null,
"id": "3a81fdac-e8ae-4e61-b6a2-2e14ff316f19",
"image_id": "de75b74e-7f0d-4b59-a263-bd87bfc313bd",
"image_name": "test",
"protected": false,
"size": 1,
"status": "uploading",
"updated_at": "2017-06-05T08:44:28.000000",
"visibility": "private",
"volume_type": null
}
}

View File

@ -0,0 +1,18 @@
{
"volume": {
"host": "%(host)s",
"ref": {
"source-name": "existingLV",
"source-id": "1234"
},
"name": "New Volume",
"availability_zone": "az2",
"description": "Volume imported from existingLV",
"volume_type": null,
"bootable": true,
"metadata": {
"key1": "value1",
"key2": "value2"
}
}
}

View File

@ -0,0 +1,17 @@
{
"availability_zone": "az2",
"bootable": true,
"cluster": "cluster@backend",
"description": "Volume imported from existingLV",
"host": "null",
"metadata": {
"key1": "value1",
"key2": "value2"
},
"name": "New Volume",
"ref": {
"source-id": "1234",
"source-name": "existingLV"
},
"volume_type": "null"
}

View File

@ -0,0 +1,34 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_serialization import jsonutils
from cinder.tests.functional.api_sample_tests import fakes
from cinder.tests.functional.api_sample_tests import test_volumes
class VolumeActionsSampleJsonTest(test_volumes.VolumesSampleBase):
sample_dir = "volume_actions"
def setUp(self):
super(VolumeActionsSampleJsonTest, self).setUp()
self.response = self._create_volume()
self.stub_out("cinder.volume.api.API.copy_volume_to_image",
fakes.stub_copy_volume_to_image)
def test_volume_upload_image(self):
res = jsonutils.loads(self.response.content)['volume']
self._poll_volume_while(res['id'], ['creating'])
response = self._do_post('volumes/%s/action' % res['id'],
'volume-upload-to-image-request')
self._verify_response('volume-upload-to-image-response',
{}, response, 202)

View File

@ -0,0 +1,36 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from cinder.tests.functional.api_sample_tests import fakes
from cinder.tests.functional import api_samples_test_base
FAKE_HOST = 'hostname@backend'
class VolumeActionsSampleJsonTest(api_samples_test_base.ApiSampleTestBase):
sample_dir = "volume_manage_extensions"
def setUp(self):
super(VolumeActionsSampleJsonTest, self).setUp()
self.subs = {
'host': FAKE_HOST
}
self.stub_out("cinder.api.contrib.volume_manage."
"VolumeManageController.create",
fakes.stub_manage_existing)
def test_manage_existing(self):
response = self._do_post('os-volume-manage',
'volume-manage-request',
subs=self.subs)
self._verify_response('volume-manage-response',
{}, response, 202)

View File

@ -15,20 +15,30 @@ from oslo_serialization import jsonutils
from cinder.tests.functional import api_samples_test_base
class VolumesSampleJsonTest(api_samples_test_base.ApiSampleTestBase):
class VolumesSampleBase(api_samples_test_base.ApiSampleTestBase):
sample_dir = "volumes"
def _create_volume(self, _use_common_volume_api_samples=True, subs=None):
orig_value = self.__class__._use_common_volume_api_samples
try:
self.__class__._use_common_volume_api_samples = (
_use_common_volume_api_samples)
response = self._do_post('volumes',
'volume-create-request',
subs)
return response
finally:
self.__class__._use_common_volume_api_samples = orig_value
class VolumesSampleJsonTest(VolumesSampleBase):
def setUp(self):
super(VolumesSampleJsonTest, self).setUp()
super(VolumesSampleBase, self).setUp()
self.response = self._create_volume()
def _create_volume(self, subs=None):
response = self._do_post('volumes',
'volume-create-request',
subs)
return response
def test_volume_list_detail(self):
response = self._do_get('volumes/detail')

View File

@ -67,6 +67,7 @@ class ApiSampleTestBase(functional_helpers._FunctionalTestBase):
all_extensions = True
sample_dir = None
_project_id = True
_use_common_volume_api_samples = False
def __init__(self, *args, **kwargs):
super(ApiSampleTestBase, self).__init__(*args, **kwargs)
@ -100,9 +101,17 @@ class ApiSampleTestBase(functional_helpers._FunctionalTestBase):
def _get_sample_path(cls, name, dirname, suffix='', api_version=None):
parts = [dirname]
parts.append('samples')
parts.append(cls.sample_dir)
if api_version:
parts.append('v' + api_version)
# Note: if _use_common_volume_api_samples is set to True
# then common volume sample files present in 'volumes' directory
# will be used. As of now it is being used for volume POST request
# to avoid duplicate copy of volume req and resp sample files.
# Example - VolumesSampleBase's _create_volume method.
if cls._use_common_volume_api_samples:
parts.append('volumes')
else:
parts.append(cls.sample_dir)
if api_version:
parts.append('v' + api_version)
parts.append(name + ".json" + suffix)
return os.path.join(*parts)