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:
parent
3902a2bf28
commit
15d1a00a57
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"os-volume_upload_image": {
|
"os-volume_upload_image": {
|
||||||
"status": "uploading",
|
|
||||||
"container_format": "bare",
|
"container_format": "bare",
|
||||||
"image_name": "test",
|
"disk_format": "raw",
|
||||||
"visibility": "private",
|
|
||||||
"updated_at": "2017-06-05T08:44:28.000000",
|
|
||||||
"image_id": "de75b74e-7f0d-4b59-a263-bd87bfc313bd",
|
|
||||||
"display_description": null,
|
"display_description": null,
|
||||||
"id": "3a81fdac-e8ae-4e61-b6a2-2e14ff316f19",
|
"id": "3a81fdac-e8ae-4e61-b6a2-2e14ff316f19",
|
||||||
|
"image_id": "de75b74e-7f0d-4b59-a263-bd87bfc313bd",
|
||||||
|
"image_name": "test",
|
||||||
|
"protected": false,
|
||||||
"size": 1,
|
"size": 1,
|
||||||
"disk_format": "raw",
|
"status": "uploading",
|
||||||
"volume_type": null,
|
"updated_at": "2017-06-05T08:44:28.000000",
|
||||||
"protected": false
|
"visibility": "private",
|
||||||
|
"volume_type": null
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,4 +15,4 @@
|
|||||||
"key2": "value2"
|
"key2": "value2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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"
|
||||||
|
}
|
@ -56,7 +56,7 @@ Request
|
|||||||
Request Example
|
Request Example
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
.. literalinclude:: ./samples/volume-manage-request.json
|
.. literalinclude:: ./samples/volume_manage_extensions/volume-manage-request.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
.. literalinclude:: ./samples/volume-manage-request-cluster.json
|
.. literalinclude:: ./samples/volume-manage-request-cluster.json
|
||||||
@ -94,7 +94,7 @@ Response
|
|||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
.. literalinclude:: ./samples/volume-manage-response.json
|
.. literalinclude:: ./samples/volume_manage_extensions/volume-manage-response.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ Request
|
|||||||
Request Example
|
Request Example
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
.. literalinclude:: ./samples/volume-upload-to-image-request.json
|
.. literalinclude:: ./samples/volume_actions/volume-upload-to-image-request.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
Response Parameters
|
Response Parameters
|
||||||
@ -670,7 +670,7 @@ Response Parameters
|
|||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
.. literalinclude:: ./samples/volume-upload-to-image-response.json
|
.. literalinclude:: ./samples/volume_actions/volume-upload-to-image-response.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,6 +437,17 @@ class TestCase(testtools.TestCase):
|
|||||||
kwargs.setdefault('message', msg)
|
kwargs.setdefault('message', msg)
|
||||||
self.assertIs(False, x, *args, **kwargs)
|
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):
|
class ModelsObjectComparatorMixin(object):
|
||||||
def _dict_from_object(self, obj, ignored_keys):
|
def _dict_from_object(self, obj, ignored_keys):
|
||||||
|
51
cinder/tests/functional/api_sample_tests/fakes.py
Normal file
51
cinder/tests/functional/api_sample_tests/fakes.py
Normal 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
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"os-volume_upload_image":{
|
||||||
|
"image_name": "test",
|
||||||
|
"force": false,
|
||||||
|
"disk_format": "raw",
|
||||||
|
"container_format": "bare"
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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"
|
||||||
|
}
|
@ -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)
|
@ -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)
|
@ -15,20 +15,30 @@ from oslo_serialization import jsonutils
|
|||||||
from cinder.tests.functional import api_samples_test_base
|
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"
|
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):
|
def setUp(self):
|
||||||
super(VolumesSampleJsonTest, self).setUp()
|
super(VolumesSampleBase, self).setUp()
|
||||||
self.response = self._create_volume()
|
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):
|
def test_volume_list_detail(self):
|
||||||
|
|
||||||
response = self._do_get('volumes/detail')
|
response = self._do_get('volumes/detail')
|
||||||
|
@ -67,6 +67,7 @@ class ApiSampleTestBase(functional_helpers._FunctionalTestBase):
|
|||||||
all_extensions = True
|
all_extensions = True
|
||||||
sample_dir = None
|
sample_dir = None
|
||||||
_project_id = True
|
_project_id = True
|
||||||
|
_use_common_volume_api_samples = False
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ApiSampleTestBase, self).__init__(*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):
|
def _get_sample_path(cls, name, dirname, suffix='', api_version=None):
|
||||||
parts = [dirname]
|
parts = [dirname]
|
||||||
parts.append('samples')
|
parts.append('samples')
|
||||||
parts.append(cls.sample_dir)
|
# Note: if _use_common_volume_api_samples is set to True
|
||||||
if api_version:
|
# then common volume sample files present in 'volumes' directory
|
||||||
parts.append('v' + api_version)
|
# 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)
|
parts.append(name + ".json" + suffix)
|
||||||
return os.path.join(*parts)
|
return os.path.join(*parts)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user