767 lines
29 KiB
Python
767 lines
29 KiB
Python
# Copyright 2014 Mirantis Inc.
|
|
# 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.
|
|
|
|
import json
|
|
import time
|
|
|
|
import six
|
|
from six.moves.urllib import parse as urlparse
|
|
|
|
from tempest import config
|
|
from tempest.lib.common import rest_client
|
|
from tempest.lib.common.utils import data_utils
|
|
from tempest.lib import exceptions
|
|
|
|
from manila_tempest_tests import share_exceptions
|
|
|
|
CONF = config.CONF
|
|
|
|
|
|
class SharesClient(rest_client.RestClient):
|
|
"""Tempest REST client for Manila.
|
|
|
|
It handles shares and access to it in OpenStack.
|
|
"""
|
|
|
|
def __init__(self, auth_provider):
|
|
super(SharesClient, self).__init__(
|
|
auth_provider,
|
|
CONF.share.catalog_type,
|
|
CONF.share.region or CONF.identity.region,
|
|
endpoint_type=CONF.share.endpoint_type)
|
|
self.share_protocol = None
|
|
if CONF.share.enable_protocols:
|
|
self.share_protocol = CONF.share.enable_protocols[0]
|
|
self.share_network_id = CONF.share.share_network_id
|
|
self.build_interval = CONF.share.build_interval
|
|
self.build_timeout = CONF.share.build_timeout
|
|
self.share_size = CONF.share.share_size
|
|
|
|
def create_share(self, share_protocol=None, size=None,
|
|
name=None, snapshot_id=None, description=None,
|
|
metadata=None, share_network_id=None,
|
|
share_type_id=None, is_public=False):
|
|
metadata = metadata or {}
|
|
if name is None:
|
|
name = data_utils.rand_name("tempest-created-share")
|
|
if description is None:
|
|
description = data_utils.rand_name("tempest-created-share-desc")
|
|
if size is None:
|
|
size = self.share_size
|
|
if share_protocol is None:
|
|
share_protocol = self.share_protocol
|
|
if share_protocol is None:
|
|
raise share_exceptions.ShareProtocolNotSpecified()
|
|
post_body = {
|
|
"share": {
|
|
"share_proto": share_protocol,
|
|
"description": description,
|
|
"snapshot_id": snapshot_id,
|
|
"name": name,
|
|
"size": size,
|
|
"metadata": metadata,
|
|
"is_public": is_public,
|
|
}
|
|
}
|
|
if share_network_id:
|
|
post_body["share"]["share_network_id"] = share_network_id
|
|
if share_type_id:
|
|
post_body["share"]["share_type"] = share_type_id
|
|
body = json.dumps(post_body)
|
|
resp, body = self.post("shares", body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def delete_share(self, share_id):
|
|
resp, body = self.delete("shares/%s" % share_id)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def manage_share(self, service_host, protocol, export_path,
|
|
share_type_id, name=None, description=None):
|
|
post_body = {
|
|
"share": {
|
|
"export_path": export_path,
|
|
"service_host": service_host,
|
|
"protocol": protocol,
|
|
"share_type": share_type_id,
|
|
"name": name,
|
|
"description": description,
|
|
}
|
|
}
|
|
body = json.dumps(post_body)
|
|
resp, body = self.post("os-share-manage", body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def unmanage_share(self, share_id):
|
|
resp, body = self.post(
|
|
"os-share-unmanage/%s/unmanage" % share_id, None)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def list_shares(self, detailed=False, params=None):
|
|
"""Get list of shares w/o filters."""
|
|
uri = 'shares/detail' if detailed else 'shares'
|
|
uri += '?%s' % urlparse.urlencode(params) if params else ''
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def list_shares_with_detail(self, params=None):
|
|
"""Get detailed list of shares w/o filters."""
|
|
return self.list_shares(detailed=True, params=params)
|
|
|
|
def get_share(self, share_id):
|
|
resp, body = self.get("shares/%s" % share_id)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def create_access_rule(self, share_id, access_type="ip",
|
|
access_to="0.0.0.0", access_level=None):
|
|
post_body = {
|
|
"os-allow_access": {
|
|
"access_type": access_type,
|
|
"access_to": access_to,
|
|
"access_level": access_level,
|
|
}
|
|
}
|
|
body = json.dumps(post_body)
|
|
resp, body = self.post("shares/%s/action" % share_id, body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def list_access_rules(self, share_id):
|
|
body = {"os-access_list": None}
|
|
resp, body = self.post("shares/%s/action" % share_id, json.dumps(body))
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def delete_access_rule(self, share_id, rule_id):
|
|
post_body = {
|
|
"os-deny_access": {
|
|
"access_id": rule_id,
|
|
}
|
|
}
|
|
body = json.dumps(post_body)
|
|
resp, body = self.post("shares/%s/action" % share_id, body)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def extend_share(self, share_id, new_size):
|
|
post_body = {
|
|
"os-extend": {
|
|
"new_size": new_size,
|
|
}
|
|
}
|
|
body = json.dumps(post_body)
|
|
resp, body = self.post("shares/%s/action" % share_id, body)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def shrink_share(self, share_id, new_size):
|
|
post_body = {
|
|
"os-shrink": {
|
|
"new_size": new_size,
|
|
}
|
|
}
|
|
body = json.dumps(post_body)
|
|
resp, body = self.post("shares/%s/action" % share_id, body)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def create_snapshot(self, share_id, name=None, description=None,
|
|
force=False):
|
|
if name is None:
|
|
name = data_utils.rand_name("tempest-created-share-snap")
|
|
if description is None:
|
|
description = data_utils.rand_name(
|
|
"tempest-created-share-snap-desc")
|
|
post_body = {
|
|
"snapshot": {
|
|
"name": name,
|
|
"force": force,
|
|
"description": description,
|
|
"share_id": share_id,
|
|
}
|
|
}
|
|
body = json.dumps(post_body)
|
|
resp, body = self.post("snapshots", body)
|
|
self.expected_success(202, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def get_snapshot(self, snapshot_id):
|
|
resp, body = self.get("snapshots/%s" % snapshot_id)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def list_snapshots(self, detailed=False, params=None):
|
|
"""Get list of share snapshots w/o filters."""
|
|
uri = 'snapshots/detail' if detailed else 'snapshots'
|
|
uri += '?%s' % urlparse.urlencode(params) if params else ''
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def list_snapshots_with_detail(self, params=None):
|
|
"""Get detailed list of share snapshots w/o filters."""
|
|
return self.list_snapshots(detailed=True, params=params)
|
|
|
|
def delete_snapshot(self, snap_id):
|
|
resp, body = self.delete("snapshots/%s" % snap_id)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def wait_for_share_status(self, share_id, status):
|
|
"""Waits for a share to reach a given status."""
|
|
body = self.get_share(share_id)
|
|
share_name = body['name']
|
|
share_status = body['status']
|
|
start = int(time.time())
|
|
|
|
while share_status != status:
|
|
time.sleep(self.build_interval)
|
|
body = self.get_share(share_id)
|
|
share_status = body['status']
|
|
if share_status == status:
|
|
return
|
|
elif 'error' in share_status.lower():
|
|
raise share_exceptions.\
|
|
ShareBuildErrorException(share_id=share_id)
|
|
|
|
if int(time.time()) - start >= self.build_timeout:
|
|
message = ('Share %s failed to reach %s status within '
|
|
'the required time (%s s).' %
|
|
(share_name, status, self.build_timeout))
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
def wait_for_snapshot_status(self, snapshot_id, status):
|
|
"""Waits for a snapshot to reach a given status."""
|
|
body = self.get_snapshot(snapshot_id)
|
|
snapshot_name = body['name']
|
|
snapshot_status = body['status']
|
|
start = int(time.time())
|
|
|
|
while snapshot_status != status:
|
|
time.sleep(self.build_interval)
|
|
body = self.get_snapshot(snapshot_id)
|
|
snapshot_status = body['status']
|
|
if 'error' in snapshot_status:
|
|
raise share_exceptions.\
|
|
SnapshotBuildErrorException(snapshot_id=snapshot_id)
|
|
|
|
if int(time.time()) - start >= self.build_timeout:
|
|
message = ('Share Snapshot %s failed to reach %s status '
|
|
'within the required time (%s s).' %
|
|
(snapshot_name, status, self.build_timeout))
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
def wait_for_access_rule_status(self, share_id, rule_id, status):
|
|
"""Waits for an access rule to reach a given status."""
|
|
rule_status = "new"
|
|
start = int(time.time())
|
|
while rule_status != status:
|
|
time.sleep(self.build_interval)
|
|
rules = self.list_access_rules(share_id)
|
|
for rule in rules:
|
|
if rule["id"] in rule_id:
|
|
rule_status = rule['state']
|
|
break
|
|
if 'error' in rule_status:
|
|
raise share_exceptions.\
|
|
AccessRuleBuildErrorException(rule_id=rule_id)
|
|
|
|
if int(time.time()) - start >= self.build_timeout:
|
|
message = ('Share Access Rule %s failed to reach %s status '
|
|
'within the required time (%s s).' %
|
|
(rule_id, status, self.build_timeout))
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
def default_quotas(self, tenant_id):
|
|
resp, body = self.get("os-quota-sets/%s/defaults" % tenant_id)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def show_quotas(self, tenant_id, user_id=None):
|
|
uri = "os-quota-sets/%s" % tenant_id
|
|
if user_id is not None:
|
|
uri += "?user_id=%s" % user_id
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def reset_quotas(self, tenant_id, user_id=None):
|
|
uri = "os-quota-sets/%s" % tenant_id
|
|
if user_id is not None:
|
|
uri += "?user_id=%s" % user_id
|
|
resp, body = self.delete(uri)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def update_quotas(self, tenant_id, user_id=None, shares=None,
|
|
snapshots=None, gigabytes=None, snapshot_gigabytes=None,
|
|
share_networks=None, force=True):
|
|
uri = "os-quota-sets/%s" % tenant_id
|
|
if user_id is not None:
|
|
uri += "?user_id=%s" % user_id
|
|
|
|
put_body = {"tenant_id": tenant_id}
|
|
if force:
|
|
put_body["force"] = "true"
|
|
if shares is not None:
|
|
put_body["shares"] = shares
|
|
if snapshots is not None:
|
|
put_body["snapshots"] = snapshots
|
|
if gigabytes is not None:
|
|
put_body["gigabytes"] = gigabytes
|
|
if snapshot_gigabytes is not None:
|
|
put_body["snapshot_gigabytes"] = snapshot_gigabytes
|
|
if share_networks is not None:
|
|
put_body["share_networks"] = share_networks
|
|
put_body = json.dumps({"quota_set": put_body})
|
|
|
|
resp, body = self.put(uri, put_body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def get_limits(self):
|
|
resp, body = self.get("limits")
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def is_resource_deleted(self, *args, **kwargs):
|
|
"""Verifies whether provided resource deleted or not.
|
|
|
|
:param kwargs: dict with expected keys 'share_id', 'snapshot_id',
|
|
:param kwargs: 'sn_id', 'ss_id', 'vt_id' and 'server_id'
|
|
:raises share_exceptions.InvalidResource
|
|
"""
|
|
if "share_id" in kwargs:
|
|
if "rule_id" in kwargs:
|
|
rule_id = kwargs.get("rule_id")
|
|
share_id = kwargs.get("share_id")
|
|
rules = self.list_access_rules(share_id)
|
|
for rule in rules:
|
|
if rule["id"] == rule_id:
|
|
return False
|
|
return True
|
|
else:
|
|
return self._is_resource_deleted(
|
|
self.get_share, kwargs.get("share_id"))
|
|
elif "snapshot_id" in kwargs:
|
|
return self._is_resource_deleted(
|
|
self.get_snapshot, kwargs.get("snapshot_id"))
|
|
elif "sn_id" in kwargs:
|
|
return self._is_resource_deleted(
|
|
self.get_share_network, kwargs.get("sn_id"))
|
|
elif "ss_id" in kwargs:
|
|
return self._is_resource_deleted(
|
|
self.get_security_service, kwargs.get("ss_id"))
|
|
elif "vt_id" in kwargs:
|
|
return self._is_resource_deleted(
|
|
self.get_volume_type, kwargs.get("vt_id"))
|
|
elif "st_id" in kwargs:
|
|
return self._is_resource_deleted(
|
|
self.get_share_type, kwargs.get("st_id"))
|
|
elif "server_id" in kwargs:
|
|
return self._is_resource_deleted(
|
|
self.show_share_server, kwargs.get("server_id"))
|
|
else:
|
|
raise share_exceptions.InvalidResource(
|
|
message=six.text_type(kwargs))
|
|
|
|
def _is_resource_deleted(self, func, res_id):
|
|
try:
|
|
res = func(res_id)
|
|
except exceptions.NotFound:
|
|
return True
|
|
if res.get('status') in ['error_deleting', 'error']:
|
|
# Resource has "error_deleting" status and can not be deleted.
|
|
resource_type = func.__name__.split('_', 1)[-1]
|
|
raise share_exceptions.ResourceReleaseFailed(
|
|
res_type=resource_type, res_id=res_id)
|
|
return False
|
|
|
|
def wait_for_resource_deletion(self, *args, **kwargs):
|
|
"""Waits for a resource to be deleted."""
|
|
start_time = int(time.time())
|
|
while True:
|
|
if self.is_resource_deleted(*args, **kwargs):
|
|
return
|
|
if int(time.time()) - start_time >= self.build_timeout:
|
|
raise exceptions.TimeoutException
|
|
time.sleep(self.build_interval)
|
|
|
|
def list_extensions(self):
|
|
resp, extensions = self.get("extensions")
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(extensions)
|
|
|
|
def update_share(self, share_id, name=None, desc=None, is_public=None):
|
|
body = {"share": {}}
|
|
if name is not None:
|
|
body["share"].update({"display_name": name})
|
|
if desc is not None:
|
|
body["share"].update({"display_description": desc})
|
|
if is_public is not None:
|
|
body["share"].update({"is_public": is_public})
|
|
body = json.dumps(body)
|
|
resp, body = self.put("shares/%s" % share_id, body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def rename_snapshot(self, snapshot_id, name, desc=None):
|
|
body = {"snapshot": {"display_name": name}}
|
|
if desc is not None:
|
|
body["snapshot"].update({"display_description": desc})
|
|
body = json.dumps(body)
|
|
resp, body = self.put("snapshots/%s" % snapshot_id, body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def reset_state(self, s_id, status="error", s_type="shares"):
|
|
"""Resets the state of a share or a snapshot.
|
|
|
|
status: available, error, creating, deleting, error_deleting
|
|
s_type: shares, snapshots
|
|
"""
|
|
body = {"os-reset_status": {"status": status}}
|
|
body = json.dumps(body)
|
|
resp, body = self.post("%s/%s/action" % (s_type, s_id), body)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def force_delete(self, s_id, s_type="shares"):
|
|
"""Force delete share or snapshot.
|
|
|
|
s_type: shares, snapshots
|
|
"""
|
|
body = {"os-force_delete": None}
|
|
body = json.dumps(body)
|
|
resp, body = self.post("%s/%s/action" % (s_type, s_id), body)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
###############
|
|
|
|
def list_services(self, params=None):
|
|
"""List services."""
|
|
uri = 'os-services'
|
|
if params:
|
|
uri += '?%s' % urlparse.urlencode(params)
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
###############
|
|
|
|
def _update_metadata(self, share_id, metadata=None, method="post"):
|
|
uri = "shares/%s/metadata" % share_id
|
|
if metadata is None:
|
|
metadata = {}
|
|
post_body = {"metadata": metadata}
|
|
body = json.dumps(post_body)
|
|
if method is "post":
|
|
resp, metadata = self.post(uri, body)
|
|
if method is "put":
|
|
resp, metadata = self.put(uri, body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(metadata)
|
|
|
|
def set_metadata(self, share_id, metadata=None):
|
|
return self._update_metadata(share_id, metadata)
|
|
|
|
def update_all_metadata(self, share_id, metadata=None):
|
|
return self._update_metadata(share_id, metadata, method="put")
|
|
|
|
def delete_metadata(self, share_id, key):
|
|
resp, body = self.delete("shares/%s/metadata/%s" % (share_id, key))
|
|
self.expected_success(200, resp.status)
|
|
return body
|
|
|
|
def get_metadata(self, share_id):
|
|
resp, body = self.get("shares/%s/metadata" % share_id)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
###############
|
|
|
|
def create_security_service(self, ss_type="ldap", **kwargs):
|
|
# ss_type: ldap, kerberos, active_directory
|
|
# kwargs: name, description, dns_ip, server, domain, user, password
|
|
post_body = {"type": ss_type}
|
|
post_body.update(kwargs)
|
|
body = json.dumps({"security_service": post_body})
|
|
resp, body = self.post("security-services", body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def update_security_service(self, ss_id, **kwargs):
|
|
# ss_id - id of security-service entity
|
|
# kwargs: dns_ip, server, domain, user, password, name, description
|
|
# for 'active' status can be changed
|
|
# only 'name' and 'description' fields
|
|
body = json.dumps({"security_service": kwargs})
|
|
resp, body = self.put("security-services/%s" % ss_id, body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def get_security_service(self, ss_id):
|
|
resp, body = self.get("security-services/%s" % ss_id)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def list_security_services(self, detailed=False, params=None):
|
|
uri = "security-services"
|
|
if detailed:
|
|
uri += '/detail'
|
|
if params:
|
|
uri += "?%s" % urlparse.urlencode(params)
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def delete_security_service(self, ss_id):
|
|
resp, body = self.delete("security-services/%s" % ss_id)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
###############
|
|
|
|
def create_share_network(self, **kwargs):
|
|
# kwargs: name, description
|
|
# + for neutron: neutron_net_id, neutron_subnet_id
|
|
body = json.dumps({"share_network": kwargs})
|
|
resp, body = self.post("share-networks", body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def update_share_network(self, sn_id, **kwargs):
|
|
# kwargs: name, description
|
|
# + for neutron: neutron_net_id, neutron_subnet_id
|
|
body = json.dumps({"share_network": kwargs})
|
|
resp, body = self.put("share-networks/%s" % sn_id, body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def get_share_network(self, sn_id):
|
|
resp, body = self.get("share-networks/%s" % sn_id)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def list_share_networks(self):
|
|
resp, body = self.get("share-networks")
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def list_share_networks_with_detail(self, params=None):
|
|
"""List the details of all shares."""
|
|
uri = "share-networks/detail"
|
|
if params:
|
|
uri += "?%s" % urlparse.urlencode(params)
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def delete_share_network(self, sn_id):
|
|
resp, body = self.delete("share-networks/%s" % sn_id)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
###############
|
|
|
|
def _map_security_service_and_share_network(self, sn_id, ss_id,
|
|
action="add"):
|
|
# sn_id: id of share_network_entity
|
|
# ss_id: id of security service entity
|
|
# action: add, remove
|
|
data = {
|
|
"%s_security_service" % action: {
|
|
"security_service_id": ss_id,
|
|
}
|
|
}
|
|
body = json.dumps(data)
|
|
resp, body = self.post("share-networks/%s/action" % sn_id, body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def add_sec_service_to_share_network(self, sn_id, ss_id):
|
|
body = self._map_security_service_and_share_network(sn_id, ss_id)
|
|
return body
|
|
|
|
def remove_sec_service_from_share_network(self, sn_id, ss_id):
|
|
body = self._map_security_service_and_share_network(
|
|
sn_id, ss_id, "remove")
|
|
return body
|
|
|
|
def list_sec_services_for_share_network(self, sn_id):
|
|
resp, body = self.get("security-services?share_network_id=%s" % sn_id)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
###############
|
|
|
|
def list_share_types(self, params=None):
|
|
uri = 'types'
|
|
if params is not None:
|
|
uri += '?%s' % urlparse.urlencode(params)
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def create_share_type(self, name, is_public=True, **kwargs):
|
|
post_body = {
|
|
'name': name,
|
|
'extra_specs': kwargs.get('extra_specs'),
|
|
'os-share-type-access:is_public': is_public,
|
|
}
|
|
post_body = json.dumps({'share_type': post_body})
|
|
resp, body = self.post('types', post_body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def delete_share_type(self, share_type_id):
|
|
resp, body = self.delete("types/%s" % share_type_id)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def get_share_type(self, share_type_id):
|
|
resp, body = self.get("types/%s" % share_type_id)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def add_access_to_share_type(self, share_type_id, project_id):
|
|
uri = 'types/%s/action' % share_type_id
|
|
post_body = {'project': project_id}
|
|
post_body = json.dumps({'addProjectAccess': post_body})
|
|
resp, body = self.post(uri, post_body)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def remove_access_from_share_type(self, share_type_id, project_id):
|
|
uri = 'types/%s/action' % share_type_id
|
|
post_body = {'project': project_id}
|
|
post_body = json.dumps({'removeProjectAccess': post_body})
|
|
resp, body = self.post(uri, post_body)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def list_access_to_share_type(self, share_type_id):
|
|
uri = 'types/%s/os-share-type-access' % share_type_id
|
|
resp, body = self.get(uri)
|
|
# [{"share_type_id": "%st_id%", "project_id": "%project_id%"}, ]
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
###############
|
|
|
|
def create_share_type_extra_specs(self, share_type_id, extra_specs):
|
|
url = "types/%s/extra_specs" % share_type_id
|
|
post_body = json.dumps({'extra_specs': extra_specs})
|
|
resp, body = self.post(url, post_body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def get_share_type_extra_spec(self, share_type_id, extra_spec_name):
|
|
uri = "types/%s/extra_specs/%s" % (share_type_id, extra_spec_name)
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def get_share_type_extra_specs(self, share_type_id, params=None):
|
|
uri = "types/%s/extra_specs" % share_type_id
|
|
if params is not None:
|
|
uri += '?%s' % urlparse.urlencode(params)
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def update_share_type_extra_spec(self, share_type_id, spec_name,
|
|
spec_value):
|
|
uri = "types/%s/extra_specs/%s" % (share_type_id, spec_name)
|
|
extra_spec = {spec_name: spec_value}
|
|
post_body = json.dumps(extra_spec)
|
|
resp, body = self.put(uri, post_body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def update_share_type_extra_specs(self, share_type_id, extra_specs):
|
|
uri = "types/%s/extra_specs" % share_type_id
|
|
extra_specs = {"extra_specs": extra_specs}
|
|
post_body = json.dumps(extra_specs)
|
|
resp, body = self.post(uri, post_body)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def delete_share_type_extra_spec(self, share_type_id, extra_spec_name):
|
|
uri = "types/%s/extra_specs/%s" % (share_type_id, extra_spec_name)
|
|
resp, body = self.delete(uri)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
###############
|
|
|
|
def list_share_servers(self, search_opts=None):
|
|
"""Get list of share servers."""
|
|
uri = "share-servers"
|
|
if search_opts:
|
|
uri += "?%s" % urlparse.urlencode(search_opts)
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def delete_share_server(self, share_server_id):
|
|
"""Delete share server by its ID."""
|
|
uri = "share-servers/%s" % share_server_id
|
|
resp, body = self.delete(uri)
|
|
self.expected_success(202, resp.status)
|
|
return body
|
|
|
|
def show_share_server(self, share_server_id):
|
|
"""Get share server info."""
|
|
uri = "share-servers/%s" % share_server_id
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
def show_share_server_details(self, share_server_id):
|
|
"""Get share server details only."""
|
|
uri = "share-servers/%s/details" % share_server_id
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|
|
|
|
###############
|
|
|
|
def list_pools(self, detail=False, search_opts=None):
|
|
"""Get list of scheduler pools."""
|
|
uri = 'scheduler-stats/pools'
|
|
if detail:
|
|
uri += '/detail'
|
|
if search_opts:
|
|
uri += "?%s" % urlparse.urlencode(search_opts)
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return json.loads(body)
|
|
|
|
###############
|
|
|
|
def list_availability_zones(self):
|
|
"""Get list of availability zones."""
|
|
uri = 'os-availability-zone'
|
|
resp, body = self.get(uri)
|
|
self.expected_success(200, resp.status)
|
|
return self._parse_resp(body)
|