Add support of export location metadata feature

Add support of new Manila APIs for listing share and share instance
export locations. CLI looks like following:

$ manila share-export-location-list %share_id%
$ manila share-export-location-show %share_id% %el_uuid%

$ manila share-instance-export-location-list %si_id%
$ manila share-instance-export-location-show %si_id% %el_uuid%

Change-Id: I6ae57cb1fc1551e4d87658a16550f052d14641a0
Depends-On: I36d1aa8d9302e097ffb08d239cf7a81101d2c1cb
This commit is contained in:
Valeriy Ponomaryov 2015-12-09 14:59:04 +02:00 committed by vponomaryov
parent 8726bf5dda
commit 17f9908ce2
11 changed files with 739 additions and 6 deletions

View File

@ -31,7 +31,7 @@ if not LOG.handlers:
LOG.addHandler(logging.StreamHandler())
MAX_VERSION = '2.8'
MAX_VERSION = '2.9'
MIN_VERSION = '2.0'
DEPRECATED_VERSION = '1.0'
_VERSIONED_METHOD_MAP = {}

View File

@ -571,6 +571,19 @@ class ManilaCLIClient(base.CLIClient):
shares = utils.listing(shares_raw)
return shares
def list_share_instances(self, share_id=None, microversion=None):
"""List share instances.
:param share_id: ID of a share to filter by.
:param microversion: API microversion to be used for request.
"""
cmd = 'share-instance-list '
if share_id:
cmd += '--share-id %s' % share_id
share_instances_raw = self.manila(cmd, microversion=microversion)
share_instances = utils.listing(share_instances_raw)
return share_instances
def is_share_deleted(self, share, microversion=None):
"""Says whether share is deleted or not.
@ -836,3 +849,77 @@ class ManilaCLIClient(base.CLIClient):
if password is not None:
data += '--password %s ' % password
return data
@not_found_wrapper
def list_share_export_locations(self, share, columns=None,
microversion=None):
"""List share export locations.
:param share: str -- Name or ID of a share.
:param columns: str -- comma separated string of columns.
Example, "--columns uuid,path".
:param microversion: API microversion to be used for request.
"""
cmd = "share-export-location-list %s" % share
if columns is not None:
cmd += " --columns " + columns
export_locations_raw = self.manila(cmd, microversion=microversion)
export_locations = utils.listing(export_locations_raw)
return export_locations
@not_found_wrapper
def get_share_export_location(self, share, export_location_uuid,
microversion=None):
"""Returns an export location by share and its UUID.
:param share: str -- Name or ID of a share.
:param export_location_uuid: str -- UUID of an export location.
:param microversion: API microversion to be used for request.
"""
share_raw = self.manila(
'share-export-location-show %(share)s %(el_uuid)s' % {
'share': share,
'el_uuid': export_location_uuid,
},
microversion=microversion)
share = output_parser.details(share_raw)
return share
@not_found_wrapper
@forbidden_wrapper
def list_share_instance_export_locations(self, share_instance,
columns=None, microversion=None):
"""List share instance export locations.
:param share_instance: str -- Name or ID of a share instance.
:param columns: str -- comma separated string of columns.
Example, "--columns uuid,path".
:param microversion: API microversion to be used for request.
"""
cmd = "share-instance-export-location-list %s" % share_instance
if columns is not None:
cmd += " --columns " + columns
export_locations_raw = self.manila(cmd, microversion=microversion)
export_locations = utils.listing(export_locations_raw)
return export_locations
@not_found_wrapper
@forbidden_wrapper
def get_share_instance_export_location(self, share_instance,
export_location_uuid,
microversion=None):
"""Returns an export location by share instance and its UUID.
:param share_instance: str -- Name or ID of a share instance.
:param export_location_uuid: str -- UUID of an export location.
:param microversion: API microversion to be used for request.
"""
share_raw = self.manila(
'share-instance-export-location-show '
'%(share_instance)s %(el_uuid)s' % {
'share_instance': share_instance,
'el_uuid': export_location_uuid,
},
microversion=microversion)
share = output_parser.details(share_raw)
return share

View File

@ -0,0 +1,158 @@
# Copyright 2015 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 ddt
from oslo_utils import uuidutils
from manilaclient.tests.functional import base
@ddt.ddt
class ExportLocationReadWriteTest(base.BaseTestCase):
@classmethod
def setUpClass(cls):
super(ExportLocationReadWriteTest, cls).setUpClass()
cls.share = cls.create_share(
client=cls.get_user_client(),
cleanup_in_class=True)
@ddt.data('admin', 'user')
def test_list_share_export_locations(self, role):
client = self.admin_client if role == 'admin' else self.user_client
export_locations = client.list_share_export_locations(
self.share['id'])
self.assertTrue(len(export_locations) > 0)
expected_keys = (
'Path', 'Updated At', 'Created At', 'UUID',
)
for el in export_locations:
for key in expected_keys:
self.assertIn(key, el)
self.assertTrue(uuidutils.is_uuid_like(el['UUID']))
@ddt.data('admin', 'user')
def test_list_share_export_locations_with_columns(self, role):
client = self.admin_client if role == 'admin' else self.user_client
export_locations = client.list_share_export_locations(
self.share['id'], columns='uuid,path')
self.assertTrue(len(export_locations) > 0)
expected_keys = ('Uuid', 'Path')
unexpected_keys = ('Updated At', 'Created At')
for el in export_locations:
for key in expected_keys:
self.assertIn(key, el)
for key in unexpected_keys:
self.assertNotIn(key, el)
self.assertTrue(uuidutils.is_uuid_like(el['Uuid']))
@ddt.data('admin', 'user')
def test_get_share_export_location(self, role):
client = self.admin_client if role == 'admin' else self.user_client
export_locations = client.list_share_export_locations(
self.share['id'])
el = client.get_share_export_location(
self.share['id'], export_locations[0]['UUID'])
expected_keys = [
'path', 'updated_at', 'created_at', 'uuid',
]
if role == 'admin':
expected_keys.extend(['is_admin_only', 'share_instance_id'])
for key in expected_keys:
self.assertIn(key, el)
if role == 'admin':
self.assertTrue(uuidutils.is_uuid_like(el['share_instance_id']))
self.assertIn(el['is_admin_only'], ('True', 'False'))
self.assertTrue(uuidutils.is_uuid_like(el['uuid']))
for list_k, get_k in (
('UUID', 'uuid'), ('Created At', 'created_at'),
('Path', 'path'), ('Updated At', 'updated_at')):
self.assertEqual(
export_locations[0][list_k], el[get_k])
def test_list_share_instance_export_locations(self):
client = self.admin_client
share_instances = client.list_share_instances(self.share['id'])
self.assertTrue(len(share_instances) > 0)
self.assertIn('ID', share_instances[0])
self.assertTrue(uuidutils.is_uuid_like(share_instances[0]['ID']))
share_instance_id = share_instances[0]['ID']
export_locations = client.list_share_instance_export_locations(
share_instance_id)
self.assertTrue(len(export_locations) > 0)
expected_keys = (
'Path', 'Updated At', 'Created At', 'UUID', 'Is Admin only',
)
for el in export_locations:
for key in expected_keys:
self.assertIn(key, el)
self.assertTrue(uuidutils.is_uuid_like(el['UUID']))
def test_list_share_instance_export_locations_with_columns(self):
client = self.admin_client
share_instances = client.list_share_instances(self.share['id'])
self.assertTrue(len(share_instances) > 0)
self.assertIn('ID', share_instances[0])
self.assertTrue(uuidutils.is_uuid_like(share_instances[0]['ID']))
share_instance_id = share_instances[0]['ID']
export_locations = client.list_share_instance_export_locations(
share_instance_id, columns='uuid,path')
self.assertTrue(len(export_locations) > 0)
expected_keys = ('Uuid', 'Path')
unexpected_keys = (
'Updated At', 'Created At', 'Is Admin only',
)
for el in export_locations:
for key in expected_keys:
self.assertIn(key, el)
for key in unexpected_keys:
self.assertNotIn(key, el)
self.assertTrue(uuidutils.is_uuid_like(el['Uuid']))
def test_get_share_instance_export_location(self):
client = self.admin_client
share_instances = client.list_share_instances(self.share['id'])
self.assertTrue(len(share_instances) > 0)
self.assertIn('ID', share_instances[0])
self.assertTrue(uuidutils.is_uuid_like(share_instances[0]['ID']))
share_instance_id = share_instances[0]['ID']
export_locations = client.list_share_instance_export_locations(
share_instance_id)
el = client.get_share_instance_export_location(
share_instance_id, export_locations[0]['UUID'])
expected_keys = (
'path', 'updated_at', 'created_at', 'uuid',
'is_admin_only', 'share_instance_id',
)
for key in expected_keys:
self.assertIn(key, el)
self.assertIn(el['is_admin_only'], ('True', 'False'))
self.assertTrue(uuidutils.is_uuid_like(el['uuid']))
for list_k, get_k in (
('UUID', 'uuid'), ('Created At', 'created_at'),
('Path', 'path'), ('Updated At', 'updated_at')):
self.assertEqual(
export_locations[0][list_k], el[get_k])

View File

@ -42,6 +42,17 @@ fake_share_instance = {
}
def get_fake_export_location():
return {
'uuid': 'foo_el_uuid',
'path': '/foo/el/path',
'share_instance_id': 'foo_share_instance_id',
'is_admin_only': False,
'created_at': '2015-12-17T13:14:15Z',
'updated_at': '2015-12-17T14:15:16Z',
}
class FakeHTTPClient(fakes.FakeHTTPClient):
def get_(self, **kw):
@ -222,6 +233,24 @@ class FakeHTTPClient(fakes.FakeHTTPClient):
def get_share_instances(self, **kw):
return self._share_instances()
def get_share_instances_1234_export_locations(self, **kw):
export_locations = {
'export_locations': [
get_fake_export_location(),
]
}
return (200, {}, export_locations)
get_shares_1234_export_locations = (
get_share_instances_1234_export_locations)
def get_share_instances_1234_export_locations_fake_el_uuid(self, **kw):
export_location = {'export_location': get_fake_export_location()}
return (200, {}, export_location)
get_shares_1234_export_locations_fake_el_uuid = (
get_share_instances_1234_export_locations_fake_el_uuid)
def get_shares_fake_instances(self, **kw):
return self._share_instances()

View File

@ -0,0 +1,57 @@
# Copyright 2015 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 ddt
import mock
from manilaclient import api_versions
from manilaclient import extension
from manilaclient.tests.unit import utils
from manilaclient.tests.unit.v2 import fakes
from manilaclient.v2 import share_export_locations
extensions = [
extension.Extension('share_export_locations', share_export_locations),
]
cs = fakes.FakeClient(extensions=extensions)
@ddt.ddt
class ShareExportLocationsTest(utils.TestCase):
def _get_manager(self, microversion):
version = api_versions.APIVersion(microversion)
mock_microversion = mock.Mock(api_version=version)
return (
share_export_locations.ShareExportLocationManager(
api=mock_microversion)
)
def test_list_of_export_locations(self):
share_id = '1234'
cs.share_export_locations.list(share_id)
cs.assert_called(
'GET', '/shares/%s/export_locations' % share_id)
def test_get_single_export_location(self):
share_id = '1234'
el_uuid = 'fake_el_uuid'
cs.share_export_locations.get(share_id, el_uuid)
cs.assert_called(
'GET',
('/shares/%(share_id)s/export_locations/'
'%(el_uuid)s') % {
'share_id': share_id, 'el_uuid': el_uuid})

View File

@ -0,0 +1,58 @@
# Copyright 2015 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 ddt
import mock
from manilaclient import api_versions
from manilaclient import extension
from manilaclient.tests.unit import utils
from manilaclient.tests.unit.v2 import fakes
from manilaclient.v2 import share_instance_export_locations
extensions = [
extension.Extension('share_instance_export_locations',
share_instance_export_locations),
]
cs = fakes.FakeClient(extensions=extensions)
@ddt.ddt
class ShareInstanceExportLocationsTest(utils.TestCase):
def _get_manager(self, microversion):
version = api_versions.APIVersion(microversion)
mock_microversion = mock.Mock(api_version=version)
return (
share_instance_export_locations.ShareInstanceExportLocationManager(
api=mock_microversion)
)
def test_list_of_export_locations(self):
share_instance_id = '1234'
cs.share_instance_export_locations.list(share_instance_id)
cs.assert_called(
'GET', '/share_instances/%s/export_locations' % share_instance_id)
def test_get_single_export_location(self):
share_instance_id = '1234'
el_uuid = 'fake_el_uuid'
cs.share_instance_export_locations.get(share_instance_id, el_uuid)
cs.assert_called(
'GET',
('/share_instances/%(share_instance_id)s/export_locations/'
'%(el_uuid)s') % {
'share_instance_id': share_instance_id, 'el_uuid': el_uuid})

View File

@ -335,7 +335,28 @@ class ShellTest(test_utils.TestCase):
def test_share_instance_show(self):
self.run_command('share-instance-show 1234')
self.assert_called('GET', '/share_instances/1234')
self.assert_called_anytime('GET', '/share_instances/1234')
def test_share_instance_export_location_list(self):
self.run_command('share-instance-export-location-list 1234')
self.assert_called_anytime(
'GET', '/share_instances/1234/export_locations')
@mock.patch.object(cliutils, 'print_list', mock.Mock())
def test_share_instance_export_location_list_with_columns(self):
self.run_command(
'share-instance-export-location-list 1234 --columns uuid,path')
self.assert_called_anytime(
'GET', '/share_instances/1234/export_locations')
cliutils.print_list.assert_called_once_with(mock.ANY, ['Uuid', 'Path'])
def test_share_instance_export_location_show(self):
self.run_command(
'share-instance-export-location-show 1234 fake_el_uuid')
self.assert_called_anytime(
'GET', '/share_instances/1234/export_locations/fake_el_uuid')
def test_share_instance_reset_state(self):
self.run_command('share-instance-reset-state 1234')
@ -439,7 +460,25 @@ class ShellTest(test_utils.TestCase):
def test_show(self):
self.run_command('show 1234')
self.assert_called('GET', '/shares/1234')
self.assert_called_anytime('GET', '/shares/1234')
def test_share_export_location_list(self):
self.run_command('share-export-location-list 1234')
self.assert_called_anytime(
'GET', '/shares/1234/export_locations')
@mock.patch.object(cliutils, 'print_list', mock.Mock())
def test_share_export_location_list_with_columns(self):
self.run_command('share-export-location-list 1234 --columns uuid,path')
self.assert_called_anytime(
'GET', '/shares/1234/export_locations')
cliutils.print_list.assert_called_once_with(mock.ANY, ['Uuid', 'Path'])
def test_share_export_location_show(self):
self.run_command('share-export-location-show 1234 fake_el_uuid')
self.assert_called_anytime(
'GET', '/shares/1234/export_locations/fake_el_uuid')
@ddt.data({'cmd_args': '--driver_options opt1=opt1 opt2=opt2'
' --share_type fake_share_type',

View File

@ -30,6 +30,8 @@ from manilaclient.v2 import quotas
from manilaclient.v2 import scheduler_stats
from manilaclient.v2 import security_services
from manilaclient.v2 import services
from manilaclient.v2 import share_export_locations
from manilaclient.v2 import share_instance_export_locations
from manilaclient.v2 import share_instances
from manilaclient.v2 import share_networks
from manilaclient.v2 import share_servers
@ -210,7 +212,12 @@ class Client(object):
self.quotas = quotas.QuotaSetManager(self)
self.shares = shares.ShareManager(self)
self.share_export_locations = (
share_export_locations.ShareExportLocationManager(self))
self.share_instances = share_instances.ShareInstanceManager(self)
self.share_instance_export_locations = (
share_instance_export_locations.ShareInstanceExportLocationManager(
self))
self.share_snapshots = share_snapshots.ShareSnapshotManager(self)
self.share_types = share_types.ShareTypeManager(self)

View File

@ -0,0 +1,50 @@
# Copyright 2015 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.
from manilaclient import api_versions
from manilaclient import base
from manilaclient.openstack.common.apiclient import base as common_base
class ShareExportLocation(common_base.Resource):
"""Resource class for a share export location."""
def __repr__(self):
return "<ShareExportLocation: %s>" % self.id
def __getitem__(self, key):
return self._info[key]
class ShareExportLocationManager(base.ManagerWithFind):
"""Manage :class:`ShareExportLocation` resources."""
resource_class = ShareExportLocation
@api_versions.wraps("2.9")
def list(self, share):
"""List all share export locations."""
share_id = common_base.getid(share)
return self._list("/shares/%s/export_locations" % share_id,
"export_locations")
@api_versions.wraps("2.9")
def get(self, share, export_location):
"""Get a share export location."""
share_id = common_base.getid(share)
export_location_id = common_base.getid(export_location)
return self._get(
"/shares/%(share_id)s/export_locations/%(export_location_id)s" % {
"share_id": share_id,
"export_location_id": export_location_id}, "export_location")

View File

@ -0,0 +1,54 @@
# Copyright 2015 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.
from manilaclient import api_versions
from manilaclient import base
from manilaclient.openstack.common.apiclient import base as common_base
class ShareInstanceExportLocation(common_base.Resource):
"""Resource class for a share export location."""
def __repr__(self):
return "<ShareInstanceExportLocation: %s>" % self.id
def __getitem__(self, key):
return self._info[key]
class ShareInstanceExportLocationManager(base.ManagerWithFind):
"""Manage :class:`ShareInstanceExportLocation` resources."""
resource_class = ShareInstanceExportLocation
@api_versions.wraps("2.9")
def list(self, share_instance):
"""List all share export locations."""
share_instance_id = common_base.getid(share_instance)
return self._list(
"/share_instances/%s/export_locations" % share_instance_id,
"export_locations")
@api_versions.wraps("2.9")
def get(self, share_instance, export_location):
"""Get a share export location."""
share_instance_id = common_base.getid(share_instance)
export_location_id = common_base.getid(export_location)
return self._get(
("/share_instances/%(share_instance_id)s/export_locations/"
"%(export_location_id)s") % {
"share_instance_id": share_instance_id,
"export_location_id": export_location_id,
},
"export_location")

View File

@ -66,6 +66,20 @@ def _find_share(cs, share):
return apiclient_utils.find_resource(cs.shares, share)
def _transform_export_locations_to_string_view(export_locations):
export_locations_string_view = ''
for el in export_locations:
if hasattr(el, '_info'):
export_locations_dict = el._info
else:
export_locations_dict = el
for k, v in export_locations_dict.items():
export_locations_string_view += '\n%(k)s = %(v)s' % {
'k': k, 'v': v}
return export_locations_string_view
@api_versions.wraps("1.0", "2.8")
def _print_share(cs, share):
info = share._info.copy()
info.pop('links', None)
@ -96,17 +110,65 @@ def _print_share(cs, share):
cliutils.print_dict(info)
@api_versions.wraps("2.9") # noqa
def _print_share(cs, share):
info = share._info.copy()
info.pop('links', None)
# NOTE(vponomaryov): remove deprecated single field 'export_location' and
# leave only list field 'export_locations'. Also, transform the latter to
# text with new line separators to make it pretty in CLI.
# It will look like following:
# +-------------------+--------------------------------------------+
# | Property | Value |
# +-------------------+--------------------------------------------+
# | status | available |
# | export_locations | |
# | | uuid = FOO-UUID |
# | | path = 5.6.7.8:/foo/export/location/path |
# | | |
# | | uuid = BAR-UUID |
# | | path = 5.6.7.8:/bar/export/location/path |
# | | |
# | id | d778d2ee-b6bb-4c5f-9f5d-6f3057d549b1 |
# | size | 1 |
# | share_proto | NFS |
# +-------------------+--------------------------------------------+
if info.get('export_locations'):
info['export_locations'] = (
_transform_export_locations_to_string_view(
info['export_locations']))
# No need to print both volume_type and share_type to CLI
if 'volume_type' in info and 'share_type' in info:
info.pop('volume_type', None)
cliutils.print_dict(info)
def _find_share_instance(cs, instance):
"""Get a share instance by ID."""
return apiclient_utils.find_resource(cs.share_instances, instance)
@api_versions.wraps("1.0", "2.8")
def _print_share_instance(cs, instance):
info = instance._info.copy()
info.pop('links', None)
cliutils.print_dict(info)
@api_versions.wraps("2.9") # noqa
def _print_share_instance(cs, instance):
info = instance._info.copy()
info.pop('links', None)
if info.get('export_locations'):
info['export_locations'] = (
_transform_export_locations_to_string_view(
info['export_locations']))
cliutils.print_dict(info)
@api_versions.experimental_api
@api_versions.wraps("2.4")
def _find_consistency_group(cs, consistency_group):
@ -609,6 +671,52 @@ def do_metadata_update_all(cs, args):
cliutils.print_dict(metadata, 'Property')
@api_versions.wraps("2.9")
@cliutils.arg(
'share',
metavar='<share>',
help='Name or ID of the share.')
@cliutils.arg(
'--columns',
metavar='<columns>',
type=str,
default=None,
help='Comma separated list of columns to be displayed '
'e.g. --columns "id,host,status"')
def do_share_export_location_list(cs, args):
"""List export locations of a given share."""
if args.columns is not None:
list_of_keys = _split_columns(columns=args.columns)
else:
list_of_keys = [
'UUID',
'Created At',
'Updated At',
'Path',
]
share = _find_share(cs, args.share)
export_locations = cs.share_export_locations.list(share)
cliutils.print_list(export_locations, list_of_keys)
@api_versions.wraps("2.9")
@cliutils.arg(
'share',
metavar='<share>',
help='Name or ID of the share.')
@cliutils.arg(
'export_location',
metavar='<export_location>',
help='ID of the share export location.')
def do_share_export_location_show(cs, args):
"""Show export location of the share."""
share = _find_share(cs, args.share)
export_location = cs.share_export_locations.get(
share, args.export_location)
view_data = export_location._info.copy()
cliutils.print_dict(view_data)
@cliutils.arg(
'service_host',
metavar='<service_host>',
@ -738,6 +846,7 @@ def do_force_delete(cs, args):
"specified shares.")
@api_versions.wraps("1.0", "2.8")
@cliutils.arg(
'share',
metavar='<share>',
@ -748,6 +857,19 @@ def do_show(cs, args):
_print_share(cs, share)
@api_versions.wraps("2.9") # noqa
@cliutils.arg(
'share',
metavar='<share>',
help='Name or ID of the NAS share.')
def do_show(cs, args):
"""Show details about a NAS share."""
share = _find_share(cs, args.share)
export_locations = cs.share_export_locations.list(share)
share._info['export_locations'] = export_locations
_print_share(cs, share)
@cliutils.arg(
'share',
metavar='<share>',
@ -962,8 +1084,9 @@ def do_list(cs, args):
'Share Type Name', 'Host', 'Availability Zone'
]
if args.columns is not None:
list_of_keys = _split_columns(columns=args.columns)
columns = args.columns
if columns is not None:
list_of_keys = _split_columns(columns=columns)
all_tenants = int(os.environ.get("ALL_TENANTS", args.all_tenants))
empty_obj = type('Empty', (object,), {'id': None})
@ -1005,6 +1128,17 @@ def do_list(cs, args):
sort_key=args.sort_key,
sort_dir=args.sort_dir,
)
# NOTE(vponomaryov): usage of 'export_location' and
# 'export_locations' columns may cause scaling issue using API 2.9+ and
# when lots of shares are returned.
if (shares and columns is not None and 'export_location' in columns and
not hasattr(shares[0], 'export_location')):
# NOTE(vponomaryov): we will get here only using API 2.9+
for share in shares:
els_objs = cs.share_export_locations.list(share)
els = [el.to_dict()['path'] for el in els_objs]
setattr(share, 'export_locations', els)
setattr(share, 'export_location', els[0] if els else None)
cliutils.print_list(shares, list_of_keys)
@ -1043,17 +1177,30 @@ def do_share_instance_list(cs, args):
cliutils.print_list(instances, list_of_keys)
@api_versions.wraps("2.3", "2.8")
@cliutils.arg(
'instance',
metavar='<instance>',
help='Name or ID of the share instance.')
@api_versions.wraps("2.3")
def do_share_instance_show(cs, args):
"""Show details about a share instance."""
instance = _find_share_instance(cs, args.instance)
_print_share_instance(cs, instance)
@api_versions.wraps("2.9") # noqa
@cliutils.arg(
'instance',
metavar='<instance>',
help='Name or ID of the share instance.')
def do_share_instance_show(cs, args):
"""Show details about a share instance."""
instance = _find_share_instance(cs, args.instance)
export_locations = cs.share_instance_export_locations.list(instance)
instance._info['export_locations'] = export_locations
_print_share_instance(cs, instance)
@cliutils.arg(
'instance',
metavar='<instance>',
@ -1093,6 +1240,53 @@ def do_share_instance_reset_state(cs, args):
instance.reset_state(args.state)
@api_versions.wraps("2.9")
@cliutils.arg(
'instance',
metavar='<instance>',
help='Name or ID of the share instance.')
@cliutils.arg(
'--columns',
metavar='<columns>',
type=str,
default=None,
help='Comma separated list of columns to be displayed '
'e.g. --columns "id,host,status"')
def do_share_instance_export_location_list(cs, args):
"""List export locations of a given share instance."""
if args.columns is not None:
list_of_keys = _split_columns(columns=args.columns)
else:
list_of_keys = [
'UUID',
'Created At',
'Updated At',
'Path',
'Is Admin only',
]
instance = _find_share_instance(cs, args.instance)
export_locations = cs.share_instance_export_locations.list(instance)
cliutils.print_list(export_locations, list_of_keys)
@api_versions.wraps("2.9")
@cliutils.arg(
'instance',
metavar='<instance>',
help='Name or ID of the share instance.')
@cliutils.arg(
'export_location',
metavar='<export_location>',
help='ID of the share instance export location.')
def do_share_instance_export_location_show(cs, args):
"""Show export location for the share instance."""
instance = _find_share_instance(cs, args.instance)
export_location = cs.share_instance_export_locations.get(
instance, args.export_location)
view_data = export_location._info.copy()
cliutils.print_dict(view_data)
@cliutils.arg(
'--all-tenants',
dest='all_tenants',