Add functional tests for OSC
In this patch we create the base for osc functional testing and add tests for 'openstack share' commands that are currently implemented. Change-Id: I3732229e4a61182a80f6f35ad7050075db84f6ce Partially-implements: bp openstack-client-support
This commit is contained in:
parent
3beec44af2
commit
134f07af6d
|
@ -0,0 +1,154 @@
|
|||
# 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 six
|
||||
import time
|
||||
|
||||
from tempest.lib.cli import base
|
||||
from tempest.lib.common.utils import data_utils
|
||||
|
||||
from manilaclient import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class OSCClientTestBase(base.ClientTestBase):
|
||||
"""Base class for OSC manila functional tests"""
|
||||
|
||||
def _get_clients(self):
|
||||
|
||||
return base.CLIClient(
|
||||
username=CONF.admin_username or CONF.username,
|
||||
password=CONF.admin_password or CONF.password,
|
||||
tenant_name=CONF.admin_tenant_name or CONF.tenant_name,
|
||||
uri=CONF.admin_auth_url or CONF.auth_url,
|
||||
cli_dir=CONF.manila_exec_dir,
|
||||
insecure=CONF.insecure,
|
||||
project_domain_name=(CONF.admin_project_domain_name or
|
||||
CONF.project_domain_name or None),
|
||||
project_domain_id=(CONF.admin_project_domain_id or
|
||||
CONF.project_domain_id or None),
|
||||
user_domain_name=(CONF.admin_user_domain_name or
|
||||
CONF.user_domain_name or None),
|
||||
user_domain_id=(CONF.admin_user_domain_id or
|
||||
CONF.user_domain_id or None)
|
||||
)
|
||||
|
||||
def _get_property_from_output(self, output):
|
||||
"""Creates a dictionary from the given output"""
|
||||
obj = {}
|
||||
items = self.parser.listing(output)
|
||||
for item in items:
|
||||
obj[item['Field']] = six.text_type(item['Value'])
|
||||
return obj
|
||||
|
||||
def _wait_for_object_status(self, object_name, object_id, status,
|
||||
timeout=CONF.build_timeout,
|
||||
interval=CONF.build_interval):
|
||||
"""Waits for a object to reach a given status."""
|
||||
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < timeout:
|
||||
if status == self.openstack(
|
||||
'%(obj)s show -c status -f value %(id)s'
|
||||
% {'obj': object_name,
|
||||
'id': object_id}).rstrip():
|
||||
break
|
||||
time.sleep(interval)
|
||||
else:
|
||||
self.fail("%s %s did not reach status %s after %d seconds."
|
||||
% (object_name, object_id, status, timeout))
|
||||
|
||||
def check_object_deleted(self, object_name, object_id,
|
||||
timeout=CONF.build_timeout,
|
||||
interval=CONF.build_interval):
|
||||
"""Check that object deleted successfully"""
|
||||
|
||||
cmd = '%s list -c ID -f value' % object_name
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < timeout:
|
||||
if object_id not in self.openstack(cmd):
|
||||
break
|
||||
time.sleep(interval)
|
||||
else:
|
||||
self.fail("%s %s not deleted after %d seconds."
|
||||
% (object_name, object_id, timeout))
|
||||
|
||||
def openstack(self, action, flags='', params='', fail_ok=False,
|
||||
merge_stderr=False):
|
||||
"""Executes openstack command for given action"""
|
||||
|
||||
if '--os-share-api-version' not in flags:
|
||||
flags = (
|
||||
flags + '--os-share-api-version %s'
|
||||
% CONF.max_api_microversion)
|
||||
|
||||
return self.clients.openstack(action, flags=flags, params=params,
|
||||
fail_ok=fail_ok,
|
||||
merge_stderr=merge_stderr)
|
||||
|
||||
def listing_result(self, object_name, command):
|
||||
"""Returns output for the given command as list of dictionaries"""
|
||||
|
||||
output = self.openstack(object_name, params=command)
|
||||
result = self.parser.listing(output)
|
||||
return result
|
||||
|
||||
def dict_result(self, object_name, command):
|
||||
"""Returns output for the given command as dictionary"""
|
||||
|
||||
output = self.openstack(object_name, params=command)
|
||||
result_dict = self._get_property_from_output(output)
|
||||
return result_dict
|
||||
|
||||
def create_share(self, share_protocol=None, size=None, name=None,
|
||||
snapshot_id=None, properties=None, share_network=None,
|
||||
description=None, public=False, share_type=None,
|
||||
availability_zone=None, share_group=None,
|
||||
add_cleanup=True):
|
||||
|
||||
name = name or data_utils.rand_name('autotest_share_name')
|
||||
# share_type = dhss_false until we have implemented
|
||||
# share network commands for osc
|
||||
share_type = share_type or 'dhss_false'
|
||||
|
||||
cmd = ('create '
|
||||
'%(protocol)s %(size)s %(name)s %(desc)s %(public)s %(stype)s'
|
||||
% {'protocol': share_protocol or 'NFS',
|
||||
'size': size or '1',
|
||||
'name': '--name %s' % name,
|
||||
'desc': '--description %s' % description,
|
||||
'public': '--public %s' % public,
|
||||
'stype': '--share-type %s' % share_type})
|
||||
|
||||
if snapshot_id:
|
||||
cmd = cmd + ' --snapshot-id %s' % snapshot_id
|
||||
if properties:
|
||||
for key, value in properties.items():
|
||||
cmd = (cmd + ' --property %(key)s=%(value)s'
|
||||
% {'key': key, 'value': value})
|
||||
if share_network:
|
||||
cmd = cmd + ' --share-network %s' % share_network
|
||||
if availability_zone:
|
||||
cmd = cmd + ' --availability-zone %s' % availability_zone
|
||||
if share_group:
|
||||
cmd = cmd + ' --share-group %s' % share_group
|
||||
|
||||
share_object = self.dict_result('share', cmd)
|
||||
self._wait_for_object_status(
|
||||
'share', share_object['id'], 'available')
|
||||
|
||||
if add_cleanup:
|
||||
self.addCleanup(
|
||||
self.openstack, 'share delete %s' % share_object['id']
|
||||
)
|
||||
return share_object
|
|
@ -0,0 +1,69 @@
|
|||
# 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 manilaclient.tests.functional.osc import base
|
||||
|
||||
|
||||
class SharesCLITest(base.OSCClientTestBase):
|
||||
|
||||
def test_openstack_share_create(self):
|
||||
share_name = 'test_create_share'
|
||||
share = self.create_share(name=share_name)
|
||||
|
||||
self.assertEqual(share['share_proto'], 'NFS')
|
||||
self.assertEqual(share['size'], '1')
|
||||
self.assertEqual(share['name'], share_name)
|
||||
|
||||
shares_list = self.listing_result('share', 'list')
|
||||
self.assertIn(share['id'], [item['ID'] for item in shares_list])
|
||||
|
||||
def test_openstack_share_list(self):
|
||||
share = self.create_share()
|
||||
shares_list = self.listing_result('share', 'list')
|
||||
self.assertTableStruct(shares_list, [
|
||||
'ID',
|
||||
'Name',
|
||||
'Size',
|
||||
'Share Proto',
|
||||
'Status',
|
||||
'Is Public',
|
||||
'Share Type Name',
|
||||
'Host',
|
||||
'Availability Zone'
|
||||
])
|
||||
self.assertIn(share['id'], [item['ID'] for item in shares_list])
|
||||
|
||||
def test_openstack_share_show(self):
|
||||
share = self.create_share()
|
||||
|
||||
result = self.dict_result('share', 'show %s' % share['id'])
|
||||
self.assertEqual(share['id'], result['id'])
|
||||
|
||||
listing_result = self.listing_result('share', 'show %s' % share['id'])
|
||||
self.assertTableStruct(listing_result, [
|
||||
'Field',
|
||||
'Value'
|
||||
])
|
||||
|
||||
def test_openstack_share_delete(self):
|
||||
share = self.create_share(add_cleanup=False)
|
||||
shares_list = self.listing_result('share', 'list')
|
||||
|
||||
self.assertIn(share['id'], [item['ID'] for item in shares_list])
|
||||
|
||||
self.openstack('share delete %s' % share['id'])
|
||||
self.check_object_deleted('share', share['id'])
|
||||
shares_list_after_delete = self.listing_result('share', 'list')
|
||||
|
||||
self.assertNotIn(
|
||||
share['id'], [item['ID'] for item in shares_list_after_delete])
|
Loading…
Reference in New Issue