Merge "[Manila] Add scenario for creation and deletion of Manila shares"
This commit is contained in:
commit
a01baae389
@ -207,6 +207,24 @@
|
||||
# (floating point value)
|
||||
#heat_stack_resume_poll_interval = 1.0
|
||||
|
||||
# Delay between creating Manila share and polling for its status.
|
||||
# (floating point value)
|
||||
#manila_share_create_prepoll_delay = 2.0
|
||||
|
||||
# Timeout for Manila share creation. (floating point value)
|
||||
#manila_share_create_timeout = 300.0
|
||||
|
||||
# Interval between checks when waiting for Manila share creation.
|
||||
# (floating point value)
|
||||
#manila_share_create_poll_interval = 3.0
|
||||
|
||||
# Timeout for Manila share deletion. (floating point value)
|
||||
#manila_share_delete_timeout = 180.0
|
||||
|
||||
# Interval between checks when waiting for Manila share deletion.
|
||||
# (floating point value)
|
||||
#manila_share_delete_poll_interval = 2.0
|
||||
|
||||
# Time to sleep after start before polling for status (floating point
|
||||
# value)
|
||||
#nova_server_start_prepoll_delay = 0.0
|
||||
|
@ -32,3 +32,26 @@
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
ManilaShares.create_and_delete_share:
|
||||
-
|
||||
args:
|
||||
share_proto: "nfs"
|
||||
size: 1
|
||||
min_sleep: 1
|
||||
max_sleep: 2
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 4
|
||||
concurrency: 4
|
||||
context:
|
||||
quotas:
|
||||
manila:
|
||||
shares: -1
|
||||
gigabytes: -1
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 1
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
@ -311,6 +311,18 @@ def _get_validated_flavor(config, clients, param_name):
|
||||
return (ValidationResult(False, message), None)
|
||||
|
||||
|
||||
@validator
|
||||
def validate_share_proto(config, clients, deployment):
|
||||
"""Validates value of share protocol for creation of Manila share."""
|
||||
allowed = ("NFS", "CIFS", "GLUSTERFS", "HDFS", )
|
||||
share_proto = config.get("args", {}).get("share_proto")
|
||||
if six.text_type(share_proto).upper() not in allowed:
|
||||
message = _("Share protocol '%(sp)s' is invalid, allowed values are "
|
||||
"%(allowed)s.") % {"sp": share_proto,
|
||||
"allowed": "', '".join(allowed)}
|
||||
return ValidationResult(False, message)
|
||||
|
||||
|
||||
@validator
|
||||
def image_exists(config, clients, deployment, param_name, nullable=False):
|
||||
"""Returns validator for image_id
|
||||
|
@ -22,6 +22,7 @@ from rally.plugins.openstack.scenarios.cinder import utils as cinder_utils
|
||||
from rally.plugins.openstack.scenarios.ec2 import utils as ec2_utils
|
||||
from rally.plugins.openstack.scenarios.glance import utils as glance_utils
|
||||
from rally.plugins.openstack.scenarios.heat import utils as heat_utils
|
||||
from rally.plugins.openstack.scenarios.manila import utils as manila_utils
|
||||
from rally.plugins.openstack.scenarios.nova import utils as nova_utils
|
||||
from rally.plugins.openstack.scenarios.sahara import utils as sahara_utils
|
||||
from rally.verification.tempest import config as tempest_conf
|
||||
@ -37,6 +38,7 @@ def list_opts():
|
||||
itertools.chain(cinder_utils.CINDER_BENCHMARK_OPTS,
|
||||
glance_utils.GLANCE_BENCHMARK_OPTS,
|
||||
heat_utils.HEAT_BENCHMARK_OPTS,
|
||||
manila_utils.MANILA_BENCHMARK_OPTS,
|
||||
nova_utils.NOVA_BENCHMARK_OPTS,
|
||||
sahara_utils.SAHARA_TIMEOUT_OPTS,
|
||||
ec2_utils.EC2_BENCHMARK_OPTS)),
|
||||
|
@ -250,6 +250,17 @@ class CinderQuotas(QuotaMixin, base.ResourceManager):
|
||||
pass
|
||||
|
||||
|
||||
# MANILA
|
||||
|
||||
_manila_order = get_order(450)
|
||||
|
||||
|
||||
@base.resource("manila", "shares", order=next(_manila_order),
|
||||
tenant_resource=True)
|
||||
class ManilaShare(base.ResourceManager):
|
||||
pass
|
||||
|
||||
|
||||
# GLANCE
|
||||
|
||||
@base.resource("glance", "images", order=500, tenant_resource=True)
|
||||
|
@ -22,6 +22,32 @@ from rally.plugins.openstack.scenarios.manila import utils
|
||||
class ManilaShares(utils.ManilaScenario):
|
||||
"""Benchmark scenarios for Manila shares."""
|
||||
|
||||
@validation.validate_share_proto()
|
||||
@validation.required_services(consts.Service.MANILA)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["manila"]})
|
||||
def create_and_delete_share(self, share_proto, size=1, min_sleep=0,
|
||||
max_sleep=0, **kwargs):
|
||||
"""Create and delete a share.
|
||||
|
||||
Optional 'min_sleep' and 'max_sleep' parameters allow the scenario
|
||||
to simulate a pause between share creation and deletion
|
||||
(of random duration from [min_sleep, max_sleep]).
|
||||
|
||||
:param share_proto: share protocol, valid values are NFS, CIFS,
|
||||
GlusterFS and HDFS
|
||||
:param size: share size in GB, should be greater than 0
|
||||
:param min_sleep: minimum sleep time in seconds (non-negative)
|
||||
:param max_sleep: maximum sleep time in seconds (non-negative)
|
||||
:param kwargs: optional args to create a share
|
||||
"""
|
||||
share = self._create_share(
|
||||
share_proto=share_proto,
|
||||
size=size,
|
||||
**kwargs)
|
||||
self.sleep_between(min_sleep, max_sleep)
|
||||
self._delete_share(share)
|
||||
|
||||
@validation.required_services(consts.Service.MANILA)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario()
|
||||
|
@ -13,12 +13,93 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from rally.benchmark.scenarios import base
|
||||
from rally.benchmark import utils as bench_utils
|
||||
|
||||
|
||||
MANILA_BENCHMARK_OPTS = [
|
||||
cfg.FloatOpt(
|
||||
"manila_share_create_prepoll_delay",
|
||||
default=2.0,
|
||||
help="Delay between creating Manila share and polling for its "
|
||||
"status."),
|
||||
cfg.FloatOpt(
|
||||
"manila_share_create_timeout",
|
||||
default=300.0,
|
||||
help="Timeout for Manila share creation."),
|
||||
cfg.FloatOpt(
|
||||
"manila_share_create_poll_interval",
|
||||
default=3.0,
|
||||
help="Interval between checks when waiting for Manila share "
|
||||
"creation."),
|
||||
cfg.FloatOpt(
|
||||
"manila_share_delete_timeout",
|
||||
default=180.0,
|
||||
help="Timeout for Manila share deletion."),
|
||||
cfg.FloatOpt(
|
||||
"manila_share_delete_poll_interval",
|
||||
default=2.0,
|
||||
help="Interval between checks when waiting for Manila share "
|
||||
"deletion."),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
benchmark_group = cfg.OptGroup(name="benchmark", title="benchmark options")
|
||||
CONF.register_opts(MANILA_BENCHMARK_OPTS, group=benchmark_group)
|
||||
|
||||
|
||||
class ManilaScenario(base.Scenario):
|
||||
"""Base class for Manila scenarios with basic atomic actions."""
|
||||
|
||||
@base.atomic_action_timer("manila.create_share")
|
||||
def _create_share(self, share_proto, size=1, **kwargs):
|
||||
"""Create a share.
|
||||
|
||||
:param share_proto: share protocol for new share,
|
||||
available values are NFS, CIFS, GlusterFS and HDFS.
|
||||
:param size: size of a share in GB
|
||||
:param snapshot_id: ID of the snapshot
|
||||
:param name: name of new share
|
||||
:param description: description of a share
|
||||
:param metadata: optional metadata to set on share creation
|
||||
:param share_network: either instance of ShareNetwork or str with ID
|
||||
:param share_type: either instance of ShareType or str with ID
|
||||
:param is_public: defines whether to set share as public or not.
|
||||
:returns: instance of :class:`Share`
|
||||
"""
|
||||
if not kwargs.get("name"):
|
||||
kwargs["name"] = self._generate_random_name()
|
||||
|
||||
share = self.clients("manila").shares.create(
|
||||
share_proto, size, **kwargs)
|
||||
time.sleep(CONF.benchmark.manila_share_create_prepoll_delay)
|
||||
share = bench_utils.wait_for(
|
||||
share,
|
||||
is_ready=bench_utils.resource_is("available"),
|
||||
update_resource=bench_utils.get_from_manager(),
|
||||
timeout=CONF.benchmark.manila_share_create_timeout,
|
||||
check_interval=CONF.benchmark.manila_share_create_poll_interval,
|
||||
)
|
||||
return share
|
||||
|
||||
@base.atomic_action_timer("manila.delete_share")
|
||||
def _delete_share(self, share):
|
||||
"""Delete the given share.
|
||||
|
||||
:param share: :class:`Share`
|
||||
"""
|
||||
share.delete()
|
||||
error_statuses = ("error_deleting", )
|
||||
bench_utils.wait_for_delete(
|
||||
share,
|
||||
update_resource=bench_utils.get_from_manager(error_statuses),
|
||||
timeout=CONF.benchmark.manila_share_delete_timeout,
|
||||
check_interval=CONF.benchmark.manila_share_delete_poll_interval)
|
||||
|
||||
@base.atomic_action_timer("manila.list_shares")
|
||||
def _list_shares(self, detailed=True, search_opts=None):
|
||||
"""Returns user shares list.
|
||||
|
@ -0,0 +1,29 @@
|
||||
{
|
||||
"ManilaShares.create_and_delete_share": [
|
||||
{
|
||||
"args": {
|
||||
"share_proto": "nfs",
|
||||
"size": 1,
|
||||
"min_sleep": 1,
|
||||
"max_sleep": 2
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 2,
|
||||
"concurrency": 2
|
||||
},
|
||||
"context": {
|
||||
"quotas": {
|
||||
"manila": {
|
||||
"shares": -1,
|
||||
"gigabytes": -1
|
||||
}
|
||||
},
|
||||
"users": {
|
||||
"tenants": 2,
|
||||
"users_per_tenant": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
---
|
||||
ManilaShares.create_and_delete_share:
|
||||
-
|
||||
args:
|
||||
share_proto: "nfs"
|
||||
size: 1
|
||||
min_sleep: 1
|
||||
max_sleep: 2
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 2
|
||||
concurrency: 2
|
||||
context:
|
||||
quotas:
|
||||
manila:
|
||||
shares: -1
|
||||
gigabytes: -1
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 1
|
@ -15,6 +15,7 @@
|
||||
|
||||
import os
|
||||
|
||||
import ddt
|
||||
from glanceclient import exc as glance_exc
|
||||
import mock
|
||||
from novaclient import exceptions as nova_exc
|
||||
@ -70,6 +71,7 @@ class ValidationUtilsTestCase(test.TestCase):
|
||||
self.assertFalse(validator(None, None, None).is_valid)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ValidatorsTestCase(test.TestCase):
|
||||
|
||||
def _unwrap_validator(self, validator, *args, **kwargs):
|
||||
@ -336,6 +338,23 @@ class ValidatorsTestCase(test.TestCase):
|
||||
result = validation._get_validated_flavor(config, clients, "flavor")
|
||||
self.assertFalse(result[0].is_valid, result[0].msg)
|
||||
|
||||
@ddt.data("nfS", "Cifs", "GLUSTERFS", "hdfs")
|
||||
def test_validate_share_proto_valid(self, share_proto):
|
||||
validator = self._unwrap_validator(validation.validate_share_proto)
|
||||
result = validator(
|
||||
{"args": {"share_proto": share_proto}}, "clients", "deployment")
|
||||
self.assertTrue(result.is_valid, result.msg)
|
||||
|
||||
@ddt.data(
|
||||
*([{"args": {"share_proto": v}} for v in (
|
||||
None, "", "nfsfoo", "foonfs", "nfscifs", )] +
|
||||
[{}, {"args": {}}])
|
||||
)
|
||||
def test_validate_share_proto_invalid(self, config):
|
||||
validator = self._unwrap_validator(validation.validate_share_proto)
|
||||
result = validator(config, "clients", "deployment")
|
||||
self.assertFalse(result.is_valid, result.msg)
|
||||
|
||||
def test_image_exists(self):
|
||||
validator = self._unwrap_validator(validation.image_exists, "param")
|
||||
result = validator({}, "clients", "deployment")
|
||||
|
@ -435,3 +435,26 @@ class SwiftContainerTestCase(test.TestCase):
|
||||
mock_manager().get_account.return_value = ("header", containers)
|
||||
self.assertEqual(len(containers),
|
||||
len(resources.SwiftContainer().list()))
|
||||
|
||||
|
||||
class ManilaShareTestCase(test.TestCase):
|
||||
|
||||
def test_list(self):
|
||||
share_resource = resources.ManilaShare()
|
||||
share_resource._manager = mock.MagicMock()
|
||||
|
||||
share_resource.list()
|
||||
|
||||
self.assertEqual("shares", share_resource._resource)
|
||||
share_resource._manager.return_value.list.assert_called_once_with()
|
||||
|
||||
def test_delete(self):
|
||||
share_resource = resources.ManilaShare()
|
||||
share_resource._manager = mock.MagicMock()
|
||||
share_resource.id = lambda: "fake_id"
|
||||
|
||||
share_resource.delete()
|
||||
|
||||
self.assertEqual("shares", share_resource._resource)
|
||||
share_resource._manager.return_value.delete.assert_called_once_with(
|
||||
"fake_id")
|
||||
|
@ -23,6 +23,24 @@ from tests.unit import test
|
||||
@ddt.ddt
|
||||
class ManilaSharesTestCase(test.TestCase):
|
||||
|
||||
@ddt.data(
|
||||
{"share_proto": "nfs", "size": 3},
|
||||
{"share_proto": "cifs", "size": 4,
|
||||
"share_network": "foo", "share_type": "bar"},
|
||||
)
|
||||
def test_create_and_delete_share(self, params):
|
||||
fake_share = mock.MagicMock()
|
||||
scenario = shares.ManilaShares()
|
||||
scenario._create_share = mock.MagicMock(return_value=fake_share)
|
||||
scenario.sleep_between = mock.MagicMock()
|
||||
scenario._delete_share = mock.MagicMock()
|
||||
|
||||
scenario.create_and_delete_share(min_sleep=3, max_sleep=4, **params)
|
||||
|
||||
scenario._create_share.assert_called_once_with(**params)
|
||||
scenario.sleep_between.assert_called_once_with(3, 4)
|
||||
scenario._delete_share.assert_called_once_with(fake_share)
|
||||
|
||||
@ddt.data(
|
||||
{},
|
||||
{"detailed": True},
|
||||
|
@ -19,30 +19,65 @@ import mock
|
||||
from rally.plugins.openstack.scenarios.manila import utils
|
||||
from tests.unit import test
|
||||
|
||||
MANILA_UTILS = "rally.plugins.openstack.scenarios.manila.utils.ManilaScenario."
|
||||
BM_UTILS = "rally.benchmark.utils."
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ManilaScenarioTestCase(test.TestCase):
|
||||
class ManilaScenarioTestCase(test.ClientsTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ManilaScenarioTestCase, self).setUp()
|
||||
self.scenario = utils.ManilaScenario()
|
||||
|
||||
@mock.patch("time.sleep")
|
||||
@mock.patch(BM_UTILS + "wait_for")
|
||||
@mock.patch(BM_UTILS + "get_from_manager")
|
||||
@mock.patch(BM_UTILS + "resource_is")
|
||||
def test__create_share(self, mock_resource_is, mock_get_from_manager,
|
||||
mock_wait_for, mock_sleep):
|
||||
fake_name = "fake_name"
|
||||
fake_share = mock.Mock()
|
||||
self.clients("manila").shares.create.return_value = fake_share
|
||||
self.scenario._generate_random_name = mock.Mock(return_value=fake_name)
|
||||
|
||||
self.scenario._create_share("nfs")
|
||||
|
||||
self.clients("manila").shares.create.assert_called_once_with(
|
||||
"nfs", 1, name=fake_name)
|
||||
|
||||
mock_wait_for.assert_called_once_with(
|
||||
fake_share, is_ready=mock.ANY, update_resource=mock.ANY,
|
||||
timeout=300, check_interval=3)
|
||||
mock_resource_is.assert_called_once_with("available")
|
||||
mock_get_from_manager.assert_called_once_with()
|
||||
self.assertTrue(mock_sleep.called)
|
||||
|
||||
@mock.patch(BM_UTILS + "get_from_manager")
|
||||
@mock.patch(BM_UTILS + "wait_for_delete")
|
||||
def test__delete_share(self, mock_wait_for_delete, mock_get_from_manager):
|
||||
fake_share = mock.MagicMock()
|
||||
|
||||
self.scenario._delete_share(fake_share)
|
||||
|
||||
fake_share.delete.assert_called_once_with()
|
||||
mock_get_from_manager.assert_called_once_with(("error_deleting", ))
|
||||
mock_wait_for_delete.assert_called_once_with(
|
||||
fake_share, update_resource=mock.ANY, timeout=180,
|
||||
check_interval=2)
|
||||
|
||||
@ddt.data(
|
||||
{},
|
||||
{"detailed": False, "search_opts": None},
|
||||
{"detailed": True, "search_opts": {"name": "foo_sn"}},
|
||||
{"search_opts": {"project_id": "fake_project"}},
|
||||
)
|
||||
@mock.patch(MANILA_UTILS + "clients")
|
||||
def test__list_shares(self, params, mock_clients):
|
||||
def test__list_shares(self, params):
|
||||
fake_shares = ["foo", "bar"]
|
||||
mock_clients.return_value.shares.list.return_value = fake_shares
|
||||
self.clients("manila").shares.list.return_value = fake_shares
|
||||
|
||||
result = self.scenario._list_shares(**params)
|
||||
|
||||
self.assertEqual(fake_shares, result)
|
||||
mock_clients.return_value.shares.list.assert_called_once_with(
|
||||
self.clients("manila").shares.list.assert_called_once_with(
|
||||
detailed=params.get("detailed", True),
|
||||
search_opts=params.get("search_opts", None))
|
||||
|
Loading…
x
Reference in New Issue
Block a user