manila/manila/tests/share/drivers/hitachi/test_hds_hnas.py

579 lines
25 KiB
Python

# Copyright (c) 2015 Hitachi Data Systems, 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 oslo_config import cfg
from manila import exception
import manila.share.configuration
import manila.share.driver
from manila.share.drivers.hitachi import hds_hnas
from manila.share.drivers.hitachi import ssh
from manila import test
CONF = cfg.CONF
share = {
'id': 'aa4a7710-f326-41fb-ad18-b4ad587fc87a',
'name': 'aa4a7710-f326-41fb-ad18-b4ad587fc87a',
'size': 50,
'host': 'hnas',
'share_proto': 'NFS',
'share_type_id': 1,
'share_network_id': 'bb329e24-3bdb-491d-acfd-dfe70c09b98d',
'share_server_id': 'cc345a53-491d-acfd-3bdb-dfe70c09b98d',
'export_locations': [{'path': '172.24.44.10:/shares/'
'aa4a7710-f326-41fb-ad18-b4ad587fc87a'}],
}
share_invalid_host = {
'id': 'aa4a7710-f326-41fb-ad18-b4ad587fc87a',
'name': 'aa4a7710-f326-41fb-ad18-b4ad587fc87a',
'size': 50,
'host': 'invalid',
'share_proto': 'NFS',
'share_type_id': 1,
'share_network_id': 'bb329e24-3bdb-491d-acfd-dfe70c09b98d',
'share_server_id': 'cc345a53-491d-acfd-3bdb-dfe70c09b98d',
'export_locations': [{'path': '172.24.44.10:/shares/'
'aa4a7710-f326-41fb-ad18-b4ad587fc87a'}],
}
access = {
'id': 'acdc7172b-fe07-46c4-b78f-df3e0324ccd0',
'access_type': 'ip',
'access_to': '172.24.44.200',
'access_level': 'rw',
'state': 'active',
}
snapshot = {
'id': 'abba6d9b-f29c-4bf7-aac1-618cda7aaf0f',
'share_id': 'aa4a7710-f326-41fb-ad18-b4ad587fc87a',
}
invalid_share = {
'id': 'aa4a7710-f326-41fb-ad18-b4ad587fc87a',
'name': 'aa4a7710-f326-41fb-ad18-b4ad587fc87a',
'size': 100,
'host': 'hnas',
'share_proto': 'CIFS',
}
invalid_access_type = {
'id': 'acdc7172b-fe07-46c4-b78f-df3e0324ccd0',
'access_type': 'user',
'access_to': 'manila_user',
'access_level': 'rw',
'state': 'active',
}
invalid_access_level = {
'id': 'acdc7172b-fe07-46c4-b78f-df3e0324ccd0',
'access_type': 'ip',
'access_to': 'manila_user',
'access_level': '777',
'state': 'active',
}
@ddt.ddt
class HDSHNASTestCase(test.TestCase):
def setUp(self):
super(HDSHNASTestCase, self).setUp()
CONF.set_default('driver_handles_share_servers', False)
CONF.hds_hnas_evs_id = '2'
CONF.hds_hnas_evs_ip = '172.24.44.10'
CONF.hds_hnas_ip = '172.24.44.1'
CONF.hds_hnas_ip_port = 'hds_hnas_ip_port'
CONF.hds_hnas_user = 'hds_hnas_user'
CONF.hds_hnas_password = 'hds_hnas_password'
CONF.hds_hnas_file_system_name = 'file_system'
CONF.hds_hnas_ssh_private_key = 'private_key'
CONF.hds_hnas_cluster_admin_ip0 = None
CONF.hds_hnas_stalled_job_timeout = 10
CONF.hds_hnas_driver_helper = ('manila.share.drivers.hitachi.ssh.'
'HNASSSHBackend')
self.fake_conf = manila.share.configuration.Configuration(None)
self.fake_private_storage = mock.Mock()
self.mock_object(self.fake_private_storage, 'get',
mock.Mock(return_value=None))
self.mock_object(self.fake_private_storage, 'delete',
mock.Mock(return_value=None))
self._driver = hds_hnas.HDSHNASDriver(
private_storage=self.fake_private_storage,
configuration=self.fake_conf)
self._driver.backend_name = "hnas"
self.mock_log = self.mock_object(hds_hnas, 'LOG')
@ddt.data('hds_hnas_driver_helper', 'hds_hnas_evs_id', 'hds_hnas_evs_ip',
'hds_hnas_ip', 'hds_hnas_user')
def test_init_invalid_conf_parameters(self, attr_name):
self.mock_object(manila.share.driver.ShareDriver,
'__init__')
setattr(CONF, attr_name, None)
self.assertRaises(exception.InvalidParameterValue,
self._driver.__init__)
def test_init_invalid_credentials(self):
self.mock_object(manila.share.driver.ShareDriver,
'__init__')
CONF.hds_hnas_password = None
CONF.hds_hnas_ssh_private_key = None
self.assertRaises(exception.InvalidParameterValue,
self._driver.__init__)
def test_update_access(self):
access1 = {
'access_type': 'ip',
'access_to': '172.24.10.10',
'access_level': 'rw'
}
access2 = {
'access_type': 'ip',
'access_to': '188.100.20.10',
'access_level': 'ro'
}
access_list = [access1, access2]
self.mock_object(self._driver, '_get_hnas_share_id',
mock.Mock(return_value='hnas_id'))
self.mock_object(self._driver, '_ensure_share')
self.mock_object(ssh.HNASSSHBackend, "update_access_rule",
mock.Mock())
self._driver.update_access('context', share, access_list, [], [])
ssh.HNASSSHBackend.update_access_rule.assert_called_once_with(
'hnas_id', [access1['access_to'] + '('
+ access1['access_level'] + ',norootsquash)',
access2['access_to'] + '('
+ access2['access_level'] + ')'])
self.assertTrue(self.mock_log.debug.called)
def test_update_access_ip_exception(self):
access1 = {
'access_type': 'ip',
'access_to': '188.100.20.10',
'access_level': 'ro'
}
access2 = {
'access_type': 'something',
'access_to': '172.24.10.10',
'access_level': 'rw'
}
access_list = [access1, access2]
self.mock_object(self._driver, '_ensure_share')
self.assertRaises(exception.InvalidShareAccess,
self._driver.update_access, 'context', share,
access_list, [], [])
def test_update_access_not_found_exception(self):
access1 = {
'access_type': 'ip',
'access_to': '188.100.20.10',
'access_level': 'ro'
}
access2 = {
'access_type': 'something',
'access_to': '172.24.10.10',
'access_level': 'rw'
}
access_list = [access1, access2]
self.mock_object(self._driver, '_ensure_share', mock.Mock(
side_effect=exception.HNASItemNotFoundException(msg='fake')))
self.assertRaises(exception.ShareResourceNotFound,
self._driver.update_access, 'context', share,
access_list, add_rules=[], delete_rules=[])
def test_create_share(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "vvol_create", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "quota_add", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "nfs_export_add", mock.Mock())
result = self._driver.create_share('context', share)
self.assertEqual(self._driver.hnas_evs_ip + ":/shares/" + share['id'],
result)
self.assertTrue(self.mock_log.debug.called)
ssh.HNASSSHBackend.vvol_create.assert_called_once_with(share['id'])
ssh.HNASSSHBackend.quota_add.assert_called_once_with(share['id'],
share['size'])
ssh.HNASSSHBackend.nfs_export_add.assert_called_once_with(share['id'])
def test_create_share_export_error(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "vvol_create", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "quota_add", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "nfs_export_add", mock.Mock(
side_effect=exception.HNASBackendException('msg')))
self.mock_object(ssh.HNASSSHBackend, "vvol_delete", mock.Mock())
self.assertRaises(exception.HNASBackendException,
self._driver.create_share, 'context', share)
self.assertTrue(self.mock_log.debug.called)
self.assertTrue(self.mock_log.exception.called)
ssh.HNASSSHBackend.vvol_create.assert_called_once_with(share['id'])
ssh.HNASSSHBackend.quota_add.assert_called_once_with(share['id'],
share['size'])
ssh.HNASSSHBackend.nfs_export_add.assert_called_once_with(share['id'])
ssh.HNASSSHBackend.vvol_delete.assert_called_once_with(share['id'])
def test_create_share_invalid_share_protocol(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_create_share",
mock.Mock(return_value="path"))
self.assertRaises(exception.ShareBackendException,
self._driver.create_share, 'context', invalid_share)
def test_delete_share(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "nfs_export_del", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "vvol_delete", mock.Mock())
self._driver.delete_share('context', share)
self.assertTrue(self.mock_log.debug.called)
ssh.HNASSSHBackend.nfs_export_del.assert_called_once_with('hnas_id')
ssh.HNASSSHBackend.vvol_delete.assert_called_once_with('hnas_id')
def test_create_snapshot(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share")
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(ssh.HNASSSHBackend, "get_host_list", mock.Mock(
return_value=['172.24.44.200(rw)']))
self.mock_object(ssh.HNASSSHBackend, "update_access_rule", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "tree_clone", mock.Mock())
self._driver.create_snapshot('context', snapshot)
ssh.HNASSSHBackend.get_host_list.assert_called_once_with('hnas_id')
ssh.HNASSSHBackend.update_access_rule.assert_any_call(
'hnas_id', ['172.24.44.200(ro)'])
ssh.HNASSSHBackend.update_access_rule.assert_any_call(
'hnas_id', ['172.24.44.200(rw)'])
ssh.HNASSSHBackend.tree_clone.assert_called_once_with(
'/shares/' + 'hnas_id', '/snapshots/' + 'hnas_id' + '/' +
snapshot['id'])
def test_create_snapshot_first_snapshot(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share")
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(ssh.HNASSSHBackend, "get_host_list", mock.Mock(
return_value=['172.24.44.200(rw)']))
self.mock_object(ssh.HNASSSHBackend, "update_access_rule", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "tree_clone", mock.Mock(
side_effect=exception.HNASNothingToCloneException('msg')))
self.mock_object(ssh.HNASSSHBackend, "create_directory", mock.Mock())
self._driver.create_snapshot('context', snapshot)
self.assertTrue(self.mock_log.warning.called)
ssh.HNASSSHBackend.get_host_list.assert_called_once_with('hnas_id')
ssh.HNASSSHBackend.update_access_rule.assert_any_call(
'hnas_id', ['172.24.44.200(ro)'])
ssh.HNASSSHBackend.update_access_rule.assert_any_call(
'hnas_id', ['172.24.44.200(rw)'])
ssh.HNASSSHBackend.create_directory.assert_called_once_with(
'/snapshots/' + 'hnas_id' + '/' + snapshot['id'])
def test_delete_snapshot(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted")
self.mock_object(ssh.HNASSSHBackend, "tree_delete", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "delete_directory", mock.Mock())
self._driver.delete_snapshot('context', snapshot)
self.assertTrue(self.mock_log.debug.called)
self.assertTrue(self.mock_log.info.called)
hds_hnas.HDSHNASDriver._check_fs_mounted.assert_called_once_with()
ssh.HNASSSHBackend.tree_delete.assert_called_once_with(
'/snapshots/' + 'hnas_id' + '/' + snapshot['id'])
ssh.HNASSSHBackend.delete_directory.assert_called_once_with(
'/snapshots/' + 'hnas_id')
def test_ensure_share(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "check_vvol", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "check_quota", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "check_export", mock.Mock())
result = self._driver.ensure_share('context', share)
self.assertEqual(['172.24.44.10:/shares/' + 'hnas_id'], result)
ssh.HNASSSHBackend.check_vvol.assert_called_once_with('hnas_id')
ssh.HNASSSHBackend.check_quota.assert_called_once_with('hnas_id')
ssh.HNASSSHBackend.check_export.assert_called_once_with('hnas_id')
def test_shrink_share(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "get_share_usage", mock.Mock(
return_value=10))
self.mock_object(ssh.HNASSSHBackend, "modify_quota", mock.Mock())
self._driver.shrink_share(share, 11)
ssh.HNASSSHBackend.get_share_usage.assert_called_once_with('hnas_id')
ssh.HNASSSHBackend.modify_quota.assert_called_once_with('hnas_id', 11)
def test_shrink_share_new_size_lower_than_usage(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "get_share_usage", mock.Mock(
return_value=10))
self.assertRaises(exception.ShareShrinkingPossibleDataLoss,
self._driver.shrink_share, share, 9)
ssh.HNASSSHBackend.get_share_usage.assert_called_once_with('hnas_id')
def test_extend_share(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "get_stats", mock.Mock(
return_value=(500, 200, True)))
self.mock_object(ssh.HNASSSHBackend, "modify_quota", mock.Mock())
self._driver.extend_share(share, 150)
ssh.HNASSSHBackend.get_stats.assert_called_once_with()
ssh.HNASSSHBackend.modify_quota.assert_called_once_with('hnas_id', 150)
def test_extend_share_with_no_available_space_in_fs(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "get_stats", mock.Mock(
return_value=(500, 200, False)))
self.mock_object(ssh.HNASSSHBackend, "modify_quota", mock.Mock())
self.assertRaises(exception.HNASBackendException,
self._driver.extend_share, share, 1000)
ssh.HNASSSHBackend.get_stats.assert_called_once_with()
def test_manage_existing(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value=share['id']))
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "get_share_quota", mock.Mock(
return_value=1))
self._driver.manage_existing(share, 'option')
ssh.HNASSSHBackend.get_share_quota.assert_called_once_with(share['id'])
def test_manage_existing_no_quota(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value=share['id']))
self.mock_object(hds_hnas.HDSHNASDriver, "_ensure_share", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "get_share_quota", mock.Mock(
return_value=None))
self.assertRaises(exception.ManageInvalidShare,
self._driver.manage_existing, share, 'option')
ssh.HNASSSHBackend.get_share_quota.assert_called_once_with(share['id'])
def test_manage_existing_wrong_share_id(self):
self.mock_object(self.fake_private_storage, 'get',
mock.Mock(return_value='Wrong_share_id'))
self.assertRaises(exception.HNASBackendException,
self._driver.manage_existing, share, 'option')
@ddt.data(':/', '1.1.1.1:/share_id', '1.1.1.1:/shares',
'1.1.1.1:shares/share_id', ':/share_id')
def test_manage_existing_wrong_path_format(self, wrong_location):
expected_exception = ("Share backend error: Incorrect path. It "
"should have the following format: "
"IP:/shares/share_id.")
share_copy = share.copy()
share_copy['export_locations'] = [{'path': wrong_location}]
ex = self.assertRaises(exception.ShareBackendException,
self._driver.manage_existing, share_copy,
'option')
self.assertEqual(expected_exception, ex.msg)
def test_manage_existing_wrong_evs_ip(self):
share['export_locations'] = [{'path': '172.24.44.189:/shares/'
'aa4a7710-f326-41fb-ad18-'}]
self.assertRaises(exception.ShareBackendException,
self._driver.manage_existing, share,
'option')
def test_manage_existing_invalid_host(self):
self.assertRaises(exception.ShareBackendException,
self._driver.manage_existing, share_invalid_host,
'option')
def test_unmanage(self):
self._driver.unmanage(share)
self.assertTrue(self.fake_private_storage.delete.called)
self.assertTrue(self.mock_log.info.called)
def test_get_network_allocations_number(self):
result = self._driver.get_network_allocations_number()
self.assertEqual(0, result)
def test_create_share_from_snapshot(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
mock.Mock())
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(ssh.HNASSSHBackend, "vvol_create", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "quota_add", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "tree_clone", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "nfs_export_add", mock.Mock())
result = self._driver.create_share_from_snapshot('context',
share, snapshot)
self.assertEqual('172.24.44.10:/shares/' + share['id'], result)
ssh.HNASSSHBackend.vvol_create.assert_called_once_with(share['id'])
ssh.HNASSSHBackend.quota_add.assert_called_once_with(share['id'],
share['size'])
ssh.HNASSSHBackend.tree_clone.assert_called_once_with(
'/snapshots/' + 'hnas_id' + '/' + snapshot['id'],
'/shares/' + share['id'])
ssh.HNASSSHBackend.nfs_export_add.assert_called_once_with(share['id'])
def test_create_share_from_snapshot_empty_snapshot(self):
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
mock.Mock())
self.mock_object(hds_hnas.HDSHNASDriver, "_get_hnas_share_id",
mock.Mock(return_value='hnas_id'))
self.mock_object(ssh.HNASSSHBackend, "vvol_create", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "quota_add", mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "tree_clone", mock.Mock(
side_effect=exception.HNASNothingToCloneException('msg')))
self.mock_object(ssh.HNASSSHBackend, "nfs_export_add", mock.Mock())
result = self._driver.create_share_from_snapshot('context', share,
snapshot)
self.assertEqual('172.24.44.10:/shares/' + share['id'], result)
self.assertTrue(self.mock_log.warning.called)
ssh.HNASSSHBackend.vvol_create.assert_called_once_with(share['id'])
ssh.HNASSSHBackend.quota_add.assert_called_once_with(share['id'],
share['size'])
ssh.HNASSSHBackend.tree_clone.assert_called_once_with(
'/snapshots/' + 'hnas_id' + '/' + snapshot['id'],
'/shares/' + share['id'])
ssh.HNASSSHBackend.nfs_export_add.assert_called_once_with(share['id'])
def test_create_share_from_snapshot_cleanup(self):
dest_path = '/snapshots/' + share['id'] + '/' + snapshot['id']
src_path = '/shares/' + share['id']
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
mock.Mock())
self.mock_object(ssh.HNASSSHBackend, "vvol_create")
self.mock_object(ssh.HNASSSHBackend, "quota_add")
self.mock_object(ssh.HNASSSHBackend, "tree_clone")
self.mock_object(ssh.HNASSSHBackend, "vvol_delete")
self.mock_object(ssh.HNASSSHBackend, "nfs_export_add", mock.Mock(
side_effect=exception.HNASBackendException(
msg='Error adding nfs export.')))
self.assertRaises(exception.HNASBackendException,
self._driver.create_share_from_snapshot,
'context', share, snapshot)
ssh.HNASSSHBackend.vvol_create.assert_called_once_with(
share['id'])
ssh.HNASSSHBackend.quota_add.assert_called_once_with(
share['id'], share['size'])
ssh.HNASSSHBackend.tree_clone.assert_called_once_with(
dest_path, src_path)
ssh.HNASSSHBackend.nfs_export_add.assert_called_once_with(
share['id'])
ssh.HNASSSHBackend.vvol_delete.assert_called_once_with(
share['id'])
def test__check_fs_mounted(self):
self.mock_object(ssh.HNASSSHBackend, 'check_fs_mounted', mock.Mock(
return_value=True))
self._driver._check_fs_mounted()
ssh.HNASSSHBackend.check_fs_mounted.assert_called_once_with()
def test__check_fs_mounted_not_mounted(self):
self.mock_object(ssh.HNASSSHBackend, 'check_fs_mounted', mock.Mock(
return_value=False))
self.assertRaises(
exception.HNASBackendException, self._driver._check_fs_mounted)
ssh.HNASSSHBackend.check_fs_mounted.assert_called_once_with()
def test__update_share_stats(self):
fake_data = {
'share_backend_name': self._driver.backend_name,
'driver_handles_share_servers':
self._driver.driver_handles_share_servers,
'vendor_name': 'HDS',
'driver_version': '2.0.0',
'storage_protocol': 'NFS',
'total_capacity_gb': 1000,
'free_capacity_gb': 200,
'reserved_percentage': hds_hnas.CONF.reserved_share_percentage,
'qos': False,
'thin_provisioning': True,
'dedupe': True,
}
self.mock_object(ssh.HNASSSHBackend, 'get_stats', mock.Mock(
return_value=(1000, 200, True)))
self.mock_object(hds_hnas.HDSHNASDriver, "_check_fs_mounted",
mock.Mock())
self.mock_object(manila.share.driver.ShareDriver,
'_update_share_stats', mock.Mock())
self._driver._update_share_stats()
self.assertTrue(self._driver.hnas.get_stats.called)
(manila.share.driver.ShareDriver._update_share_stats.
assert_called_once_with(fake_data))
self.assertTrue(self.mock_log.info.called)