Merge "Move volume service clients under tempest.lib"
This commit is contained in:
commit
6faded6a7b
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Define volume service clients as libraries.
|
||||
The following volume service clients are defined as library interface,
|
||||
so the other projects can use these modules as stable libraries without
|
||||
any maintenance changes.
|
||||
|
||||
* volumes_client(v1)
|
||||
* volumes_client(v2)
|
|
@ -21,11 +21,9 @@ from tempest.lib.common import rest_client
|
|||
from tempest.lib import exceptions as lib_exc
|
||||
|
||||
|
||||
class BaseVolumesClient(rest_client.RestClient):
|
||||
class VolumesClient(rest_client.RestClient):
|
||||
"""Base client class to send CRUD Volume API requests"""
|
||||
|
||||
create_resp = 200
|
||||
|
||||
def _prepare_params(self, params):
|
||||
"""Prepares params for use in get or _ext_get methods.
|
||||
|
||||
|
@ -69,7 +67,7 @@ class BaseVolumesClient(rest_client.RestClient):
|
|||
post_body = json.dumps({'volume': kwargs})
|
||||
resp, body = self.post('volumes', post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(self.create_resp, resp.status)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_volume(self, volume_id, **kwargs):
|
|
@ -0,0 +1,340 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 as json
|
||||
import six
|
||||
from six.moves.urllib import parse as urllib
|
||||
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
|
||||
|
||||
class VolumesClient(rest_client.RestClient):
|
||||
"""Client class to send CRUD Volume V2 API requests"""
|
||||
api_version = "v2"
|
||||
|
||||
def _prepare_params(self, params):
|
||||
"""Prepares params for use in get or _ext_get methods.
|
||||
|
||||
If params is a string it will be left as it is, but if it's not it will
|
||||
be urlencoded.
|
||||
"""
|
||||
if isinstance(params, six.string_types):
|
||||
return params
|
||||
return urllib.urlencode(params)
|
||||
|
||||
def list_volumes(self, detail=False, params=None):
|
||||
"""List all the volumes created.
|
||||
|
||||
Params can be a string (must be urlencoded) or a dictionary.
|
||||
"""
|
||||
url = 'volumes'
|
||||
if detail:
|
||||
url += '/detail'
|
||||
if params:
|
||||
url += '?%s' % self._prepare_params(params)
|
||||
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_volume(self, volume_id):
|
||||
"""Returns the details of a single volume."""
|
||||
url = "volumes/%s" % volume_id
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_volume(self, **kwargs):
|
||||
"""Creates a new Volume.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html#createVolume
|
||||
"""
|
||||
post_body = json.dumps({'volume': kwargs})
|
||||
resp, body = self.post('volumes', post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_volume(self, volume_id, **kwargs):
|
||||
"""Updates the Specified Volume.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html#updateVolume
|
||||
"""
|
||||
put_body = json.dumps({'volume': kwargs})
|
||||
resp, body = self.put('volumes/%s' % volume_id, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_volume(self, volume_id):
|
||||
"""Deletes the Specified Volume."""
|
||||
resp, body = self.delete("volumes/%s" % volume_id)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def upload_volume(self, volume_id, **kwargs):
|
||||
"""Uploads a volume in Glance."""
|
||||
post_body = json.dumps({'os-volume_upload_image': kwargs})
|
||||
url = 'volumes/%s/action' % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def attach_volume(self, volume_id, **kwargs):
|
||||
"""Attaches a volume to a given instance on a given mountpoint.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html#attachVolume
|
||||
"""
|
||||
post_body = json.dumps({'os-attach': kwargs})
|
||||
url = 'volumes/%s/action' % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def set_bootable_volume(self, volume_id, **kwargs):
|
||||
"""set a bootable flag for a volume - true or false."""
|
||||
post_body = json.dumps({'os-set_bootable': kwargs})
|
||||
url = 'volumes/%s/action' % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def detach_volume(self, volume_id):
|
||||
"""Detaches a volume from an instance."""
|
||||
post_body = json.dumps({'os-detach': {}})
|
||||
url = 'volumes/%s/action' % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def reserve_volume(self, volume_id):
|
||||
"""Reserves a volume."""
|
||||
post_body = json.dumps({'os-reserve': {}})
|
||||
url = 'volumes/%s/action' % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def unreserve_volume(self, volume_id):
|
||||
"""Restore a reserved volume ."""
|
||||
post_body = json.dumps({'os-unreserve': {}})
|
||||
url = 'volumes/%s/action' % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def is_resource_deleted(self, id):
|
||||
try:
|
||||
self.show_volume(id)
|
||||
except lib_exc.NotFound:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def resource_type(self):
|
||||
"""Returns the primary type of resource this client works with."""
|
||||
return 'volume'
|
||||
|
||||
def extend_volume(self, volume_id, **kwargs):
|
||||
"""Extend a volume.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html#extendVolume
|
||||
"""
|
||||
post_body = json.dumps({'os-extend': kwargs})
|
||||
url = 'volumes/%s/action' % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def reset_volume_status(self, volume_id, **kwargs):
|
||||
"""Reset the Specified Volume's Status.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html#resetVolume
|
||||
"""
|
||||
post_body = json.dumps({'os-reset_status': kwargs})
|
||||
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_volume_transfer(self, **kwargs):
|
||||
"""Create a volume transfer.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html#createVolumeTransfer
|
||||
"""
|
||||
post_body = json.dumps({'transfer': kwargs})
|
||||
resp, body = self.post('os-volume-transfer', post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_volume_transfer(self, transfer_id):
|
||||
"""Returns the details of a volume transfer."""
|
||||
url = "os-volume-transfer/%s" % transfer_id
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def list_volume_transfers(self, **params):
|
||||
"""List all the volume transfers created.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html#listVolumeTransfer
|
||||
"""
|
||||
url = 'os-volume-transfer'
|
||||
if params:
|
||||
url += '?%s' % urllib.urlencode(params)
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_volume_transfer(self, transfer_id):
|
||||
"""Delete a volume transfer."""
|
||||
resp, body = self.delete("os-volume-transfer/%s" % transfer_id)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def accept_volume_transfer(self, transfer_id, **kwargs):
|
||||
"""Accept a volume transfer.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html#acceptVolumeTransfer
|
||||
"""
|
||||
url = 'os-volume-transfer/%s/accept' % transfer_id
|
||||
post_body = json.dumps({'accept': kwargs})
|
||||
resp, body = self.post(url, post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_volume_readonly(self, volume_id, **kwargs):
|
||||
"""Update the Specified Volume readonly."""
|
||||
post_body = json.dumps({'os-update_readonly_flag': kwargs})
|
||||
url = 'volumes/%s/action' % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def force_delete_volume(self, volume_id):
|
||||
"""Force Delete Volume."""
|
||||
post_body = json.dumps({'os-force_delete': {}})
|
||||
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_volume_metadata(self, volume_id, metadata):
|
||||
"""Create metadata for the volume."""
|
||||
put_body = json.dumps({'metadata': metadata})
|
||||
url = "volumes/%s/metadata" % volume_id
|
||||
resp, body = self.post(url, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_volume_metadata(self, volume_id):
|
||||
"""Get metadata of the volume."""
|
||||
url = "volumes/%s/metadata" % volume_id
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_volume_metadata(self, volume_id, metadata):
|
||||
"""Update metadata for the volume."""
|
||||
put_body = json.dumps({'metadata': metadata})
|
||||
url = "volumes/%s/metadata" % volume_id
|
||||
resp, body = self.put(url, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_volume_metadata_item(self, volume_id, id, meta_item):
|
||||
"""Update metadata item for the volume."""
|
||||
put_body = json.dumps({'meta': meta_item})
|
||||
url = "volumes/%s/metadata/%s" % (volume_id, id)
|
||||
resp, body = self.put(url, put_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_volume_metadata_item(self, volume_id, id):
|
||||
"""Delete metadata item for the volume."""
|
||||
url = "volumes/%s/metadata/%s" % (volume_id, id)
|
||||
resp, body = self.delete(url)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def retype_volume(self, volume_id, **kwargs):
|
||||
"""Updates volume with new volume type."""
|
||||
post_body = json.dumps({'os-retype': kwargs})
|
||||
resp, body = self.post('volumes/%s/action' % volume_id, post_body)
|
||||
self.expected_success(202, resp.status)
|
||||
|
||||
def update_volume_image_metadata(self, volume_id, **kwargs):
|
||||
"""Update image metadata for the volume.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html
|
||||
#setVolumeimagemetadata
|
||||
"""
|
||||
post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
|
||||
url = "volumes/%s/action" % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_volume_image_metadata(self, volume_id, key_name):
|
||||
"""Delete image metadata item for the volume."""
|
||||
post_body = json.dumps({'os-unset_image_metadata': {'key': key_name}})
|
||||
url = "volumes/%s/action" % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_pools(self, detail=False):
|
||||
# List all the volumes pools (hosts)
|
||||
url = 'scheduler-stats/get_pools'
|
||||
if detail:
|
||||
url += '?detail=True'
|
||||
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_backend_capabilities(self, host):
|
||||
"""Shows capabilities for a storage back end.
|
||||
|
||||
Output params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html
|
||||
#showBackendCapabilities
|
||||
"""
|
||||
url = 'capabilities/%s' % host
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
|
@ -24,7 +24,7 @@ from tempest.lib.services.volume.v1.quotas_client import QuotasClient
|
|||
from tempest.lib.services.volume.v1.services_client import ServicesClient
|
||||
from tempest.lib.services.volume.v1.snapshots_client import SnapshotsClient
|
||||
from tempest.lib.services.volume.v1.types_client import TypesClient
|
||||
from tempest.services.volume.v1.json.volumes_client import VolumesClient
|
||||
from tempest.lib.services.volume.v1.volumes_client import VolumesClient
|
||||
|
||||
__all__ = ['AvailabilityZoneClient', 'EncryptionTypesClient',
|
||||
'ExtensionsClient', 'HostsClient', 'QuotasClient',
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 tempest.services.volume.base import base_volumes_client
|
||||
|
||||
|
||||
class VolumesClient(base_volumes_client.BaseVolumesClient):
|
||||
"""Client class to send CRUD Volume V1 API requests"""
|
|
@ -24,7 +24,7 @@ from tempest.lib.services.volume.v2.quotas_client import QuotasClient
|
|||
from tempest.lib.services.volume.v2.services_client import ServicesClient
|
||||
from tempest.lib.services.volume.v2.snapshots_client import SnapshotsClient
|
||||
from tempest.lib.services.volume.v2.types_client import TypesClient
|
||||
from tempest.services.volume.v2.json.volumes_client import VolumesClient
|
||||
from tempest.lib.services.volume.v2.volumes_client import VolumesClient
|
||||
|
||||
__all__ = ['AvailabilityZoneClient', 'BackupsClient', 'EncryptionTypesClient',
|
||||
'ExtensionsClient', 'HostsClient', 'QosSpecsClient', 'QuotasClient',
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 as json
|
||||
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.services.volume.base import base_volumes_client
|
||||
|
||||
|
||||
class VolumesClient(base_volumes_client.BaseVolumesClient):
|
||||
"""Client class to send CRUD Volume V2 API requests"""
|
||||
api_version = "v2"
|
||||
create_resp = 202
|
||||
|
||||
def update_volume_image_metadata(self, volume_id, **kwargs):
|
||||
"""Update image metadata for the volume.
|
||||
|
||||
Available params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html
|
||||
#setVolumeimagemetadata
|
||||
"""
|
||||
post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
|
||||
url = "volumes/%s/action" % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def delete_volume_image_metadata(self, volume_id, key_name):
|
||||
"""Delete image metadata item for the volume."""
|
||||
post_body = json.dumps({'os-unset_image_metadata': {'key': key_name}})
|
||||
url = "volumes/%s/action" % (volume_id)
|
||||
resp, body = self.post(url, post_body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_pools(self, detail=False):
|
||||
# List all the volumes pools (hosts)
|
||||
url = 'scheduler-stats/get_pools'
|
||||
if detail:
|
||||
url += '?detail=True'
|
||||
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_backend_capabilities(self, host):
|
||||
"""Shows capabilities for a storage back end.
|
||||
|
||||
Output params: see http://developer.openstack.org/
|
||||
api-ref-blockstorage-v2.html
|
||||
#showBackendCapabilities
|
||||
"""
|
||||
url = 'capabilities/%s' % host
|
||||
resp, body = self.get(url)
|
||||
body = json.loads(body)
|
||||
self.expected_success(200, resp.status)
|
||||
return rest_client.ResponseBody(resp, body)
|
|
@ -18,7 +18,7 @@ import mock
|
|||
|
||||
from tempest.common import waiters
|
||||
from tempest import exceptions
|
||||
from tempest.services.volume.base import base_volumes_client
|
||||
from tempest.lib.services.volume.v2 import volumes_client
|
||||
from tempest.tests import base
|
||||
import tempest.tests.utils as utils
|
||||
|
||||
|
@ -57,7 +57,7 @@ class TestImageWaiters(base.TestCase):
|
|||
def test_wait_for_volume_status_error_restoring(self, mock_sleep):
|
||||
# Tests that the wait method raises VolumeRestoreErrorException if
|
||||
# the volume status is 'error_restoring'.
|
||||
client = mock.Mock(spec=base_volumes_client.BaseVolumesClient,
|
||||
client = mock.Mock(spec=volumes_client.VolumesClient,
|
||||
build_interval=1)
|
||||
volume1 = {'volume': {'status': 'restoring-backup'}}
|
||||
volume2 = {'volume': {'status': 'error_restoring'}}
|
||||
|
|
Loading…
Reference in New Issue