NexentaStor5: Added extend method to NFS driver
Added extend method and support for extending the volume in create_volume_from_snapshot if the size of new volume is larger than original volume size. Added a method to replace / with %2F in URLs when needed. Change-Id: I5debfccaa81ecf8d58b118f5ca0cccc735d35d24 DocImpact Closes-Bug: #1562167
This commit is contained in:
parent
7502e1fed3
commit
e0a6071b59
@ -156,11 +156,13 @@ class TestNexentaNfsDriver(test.TestCase):
|
||||
self.drv.delete_snapshot(self.TEST_SNAPSHOT)
|
||||
self.nef_mock.delete.assert_called_with(url)
|
||||
|
||||
@patch('cinder.volume.drivers.nexenta.ns5.nfs.'
|
||||
'NexentaNfsDriver.extend_volume')
|
||||
@patch('cinder.volume.drivers.nexenta.ns5.nfs.'
|
||||
'NexentaNfsDriver.local_path')
|
||||
@patch('cinder.volume.drivers.nexenta.ns5.nfs.'
|
||||
'NexentaNfsDriver._share_folder')
|
||||
def test_create_volume_from_snapshot(self, share, path):
|
||||
def test_create_volume_from_snapshot(self, share, path, extend):
|
||||
self._create_volume_db_entry()
|
||||
url = ('storage/pools/%(pool)s/'
|
||||
'filesystems/%(fs)s/snapshots/%(snap)s/clone') % {
|
||||
@ -174,6 +176,43 @@ class TestNexentaNfsDriver(test.TestCase):
|
||||
self.TEST_VOLUME2, self.TEST_SNAPSHOT)
|
||||
self.nef_mock.post.assert_called_with(url, data)
|
||||
|
||||
# make sure the volume get extended!
|
||||
extend.assert_called_once_with(self.TEST_VOLUME2, 2)
|
||||
|
||||
@patch('cinder.volume.drivers.nexenta.ns5.nfs.'
|
||||
'NexentaNfsDriver.local_path')
|
||||
@patch('oslo_concurrency.processutils.execute')
|
||||
def test_extend_volume_sparsed(self, _execute, path):
|
||||
self._create_volume_db_entry()
|
||||
path.return_value = 'path'
|
||||
|
||||
self.drv.extend_volume(self.TEST_VOLUME, 2)
|
||||
|
||||
_execute.assert_called_with(
|
||||
'truncate', '-s', '2G',
|
||||
'path',
|
||||
root_helper='sudo cinder-rootwrap /etc/cinder/rootwrap.conf',
|
||||
run_as_root=True)
|
||||
|
||||
@patch('cinder.volume.drivers.nexenta.ns5.nfs.'
|
||||
'NexentaNfsDriver.local_path')
|
||||
@patch('oslo_concurrency.processutils.execute')
|
||||
def test_extend_volume_nonsparsed(self, _execute, path):
|
||||
self._create_volume_db_entry()
|
||||
path.return_value = 'path'
|
||||
with mock.patch.object(self.drv,
|
||||
'sparsed_volumes',
|
||||
False):
|
||||
|
||||
self.drv.extend_volume(self.TEST_VOLUME, 2)
|
||||
|
||||
_execute.assert_called_with(
|
||||
'dd', 'if=/dev/zero', 'seek=1073741824',
|
||||
'of=path',
|
||||
'bs=1M', 'count=1024',
|
||||
root_helper='sudo cinder-rootwrap /etc/cinder/rootwrap.conf',
|
||||
run_as_root=True)
|
||||
|
||||
def test_get_capacity_info(self):
|
||||
self.nef_mock.get.return_value = {
|
||||
'bytesAvailable': 1000,
|
||||
|
@ -17,6 +17,7 @@ import hashlib
|
||||
import os
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import units
|
||||
|
||||
from cinder import context
|
||||
from cinder import db
|
||||
@ -28,7 +29,7 @@ from cinder.volume.drivers.nexenta import options
|
||||
from cinder.volume.drivers.nexenta import utils
|
||||
from cinder.volume.drivers import nfs
|
||||
|
||||
VERSION = '1.1.0'
|
||||
VERSION = '1.2.0'
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -40,6 +41,10 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
1.0.0 - Initial driver version.
|
||||
1.1.0 - Added HTTPS support.
|
||||
Added use of sessions for REST calls.
|
||||
1.2.0 - Support for extend volume.
|
||||
Support for extending the volume in
|
||||
create_volume_from_snapshot if the size of new volume is larger
|
||||
than original volume size.
|
||||
"""
|
||||
|
||||
driver_prefix = 'nexenta'
|
||||
@ -94,21 +99,21 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
:raise: :py:exc:`LookupError`
|
||||
"""
|
||||
pool_name, fs = self._get_share_datasets(self.share)
|
||||
url = 'storage/pools/%s' % (pool_name)
|
||||
url = 'storage/pools/%s' % pool_name
|
||||
self.nef.get(url)
|
||||
url = 'storage/pools/%s/filesystems/%s' % (pool_name, fs)
|
||||
url = 'storage/pools/%s/filesystems/%s' % (
|
||||
pool_name, self._escape_path(fs))
|
||||
self.nef.get(url)
|
||||
|
||||
path = '/'.join([pool_name, fs])
|
||||
shared = False
|
||||
response = self.nef.get('nas/nfs')
|
||||
for share in response['data']:
|
||||
if share.get('filesystem') == path:
|
||||
if share.get('filesystem') == self.share:
|
||||
shared = True
|
||||
break
|
||||
if not shared:
|
||||
raise LookupError(_("Dataset %s is not shared in Nexenta "
|
||||
"Store appliance") % path)
|
||||
"Store appliance") % self.share)
|
||||
|
||||
def initialize_connection(self, volume, connector):
|
||||
"""Allow connection to connector and return connection info.
|
||||
@ -157,7 +162,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
self._create_sparsed_file(self.local_path(volume), volume_size)
|
||||
else:
|
||||
url = 'storage/pools/%s/filesystems/%s' % (
|
||||
pool, '%2F'.join([fs, volume['name']]))
|
||||
pool, '%2F'.join([self._escape_path(fs), volume['name']]))
|
||||
compression = self.nef.get(url).get('compressionMode')
|
||||
if compression != 'off':
|
||||
# Disable compression, because otherwise will not use space
|
||||
@ -174,7 +179,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
except exception.NexentaException:
|
||||
try:
|
||||
url = 'storage/pools/%s/filesystems/%s' % (
|
||||
pool, '%2F'.join([fs, volume['name']]))
|
||||
pool, '%2F'.join([self._escape_path(fs), volume['name']]))
|
||||
self.nef.delete(url)
|
||||
except exception.NexentaException:
|
||||
LOG.warning(_LW("Cannot destroy created folder: "
|
||||
@ -188,7 +193,8 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
|
||||
:param volume: volume reference
|
||||
"""
|
||||
pool, fs = self._get_share_datasets(self.share)
|
||||
pool, fs_ = self._get_share_datasets(self.share)
|
||||
fs = self._escape_path(fs_)
|
||||
url = ('storage/pools/%(pool)s/filesystems/%(fs)s') % {
|
||||
'pool': pool,
|
||||
'fs': '%2F'.join([fs, volume['name']])
|
||||
@ -221,7 +227,31 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
if 'does not exist' in exc.args[0]:
|
||||
LOG.debug(
|
||||
'Volume %s does not exist on appliance', '/'.join(
|
||||
[pool, fs]))
|
||||
[pool, fs_]))
|
||||
|
||||
def extend_volume(self, volume, new_size):
|
||||
"""Extend an existing volume.
|
||||
|
||||
:param volume: volume reference
|
||||
:param new_size: volume new size in GB
|
||||
"""
|
||||
LOG.info(_LI('Extending volume: %(id)s New size: %(size)s GB'),
|
||||
{'id': volume['id'], 'size': new_size})
|
||||
if self.sparsed_volumes:
|
||||
self._execute('truncate', '-s', '%sG' % new_size,
|
||||
self.local_path(volume),
|
||||
run_as_root=self._execute_as_root)
|
||||
else:
|
||||
block_size_mb = 1
|
||||
block_count = ((new_size - volume['size']) * units.Gi //
|
||||
(block_size_mb * units.Mi))
|
||||
self._execute(
|
||||
'dd', 'if=/dev/zero',
|
||||
'seek=%d' % (volume['size'] * units.Gi / block_size_mb),
|
||||
'of=%s' % self.local_path(volume),
|
||||
'bs=%dM' % block_size_mb,
|
||||
'count=%d' % block_count,
|
||||
run_as_root=True)
|
||||
|
||||
def create_snapshot(self, snapshot):
|
||||
"""Creates a snapshot.
|
||||
@ -232,7 +262,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
pool, fs = self._get_share_datasets(self.share)
|
||||
url = 'storage/pools/%(pool)s/filesystems/%(fs)s/snapshots' % {
|
||||
'pool': pool,
|
||||
'fs': '%2F'.join([fs, volume['name']]),
|
||||
'fs': self._escape_path('/'.join([fs, volume['name']])),
|
||||
}
|
||||
data = {'name': snapshot['name']}
|
||||
self.nef.post(url, data)
|
||||
@ -247,7 +277,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
url = ('storage/pools/%(pool)s/'
|
||||
'filesystems/%(fs)s/snapshots/%(snap)s') % {
|
||||
'pool': pool,
|
||||
'fs': '%2F'.join([fs, volume['name']]),
|
||||
'fs': self._escape_path('/'.join([fs, volume['name']])),
|
||||
'snap': snapshot['name']
|
||||
}
|
||||
try:
|
||||
@ -272,7 +302,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
url = ('storage/pools/%(pool)s/'
|
||||
'filesystems/%(fs)s/snapshots/%(snap)s/clone') % {
|
||||
'pool': pool,
|
||||
'fs': '%2F'.join([fs, snapshot_vol['name']]),
|
||||
'fs': self._escape_path('/'.join([fs, snapshot_vol['name']])),
|
||||
'snap': snapshot['name']
|
||||
}
|
||||
path = '/'.join([pool, fs, volume['name']])
|
||||
@ -286,7 +316,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
url = ('storage/pools/%(pool)s/'
|
||||
'filesystems/%(fs)s') % {
|
||||
'pool': pool,
|
||||
'fs': volume['name']
|
||||
'fs': self._escape_path('/'.join([fs, volume['name']]))
|
||||
}
|
||||
self.nef.delete(url)
|
||||
except exception.NexentaException:
|
||||
@ -295,7 +325,11 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
{'vol': dataset_path,
|
||||
'filesystem': volume['name']})
|
||||
raise
|
||||
|
||||
if volume['size'] > snapshot['volume_size']:
|
||||
new_size = volume['size']
|
||||
volume['size'] = snapshot['volume_size']
|
||||
self.extend_volume(volume, new_size)
|
||||
volume['size'] = new_size
|
||||
return {'provider_location': volume['provider_location']}
|
||||
|
||||
def create_cloned_volume(self, volume, src_vref):
|
||||
@ -307,6 +341,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
LOG.info(_LI('Creating clone of volume: %s'), src_vref['id'])
|
||||
snapshot = {'volume_name': src_vref['name'],
|
||||
'volume_id': src_vref['id'],
|
||||
'volume_size': src_vref['size'],
|
||||
'name': self._get_clone_snapshot_name(volume)}
|
||||
self.create_snapshot(snapshot)
|
||||
try:
|
||||
@ -320,7 +355,6 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
LOG.warning(_LW('Failed to delete zfs snapshot '
|
||||
'%(volume_name)s@%(name)s'), snapshot)
|
||||
raise
|
||||
self.delete_snapshot(snapshot)
|
||||
|
||||
def local_path(self, volume):
|
||||
"""Get volume path (mounted locally fs path) for given volume.
|
||||
@ -351,7 +385,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
LOG.debug(
|
||||
'Creating ACL for filesystem %s on Nexenta Store', filesystem)
|
||||
url = 'storage/pools/%s/filesystems/%s/acl' % (
|
||||
pool, '%2F'.join([path.replace('/', '%2F'), filesystem]))
|
||||
pool, self._escape_path('/'.join([path, filesystem])))
|
||||
data = {
|
||||
"type": "allow",
|
||||
"principal": "everyone@",
|
||||
@ -392,7 +426,7 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
"""
|
||||
pool, fs = self._get_share_datasets(path)
|
||||
url = 'storage/pools/%s/filesystems/%s' % (
|
||||
pool, fs)
|
||||
pool, self._escape_path(fs))
|
||||
data = self.nef.get(url)
|
||||
total = utils.str2size(data['bytesAvailable'])
|
||||
allocated = utils.str2size(data['bytesUsed'])
|
||||
@ -444,3 +478,6 @@ class NexentaNfsDriver(nfs.NfsDriver):
|
||||
'volume_backend_name': self.backend_name,
|
||||
'nfs_mount_point_base': self.nfs_mount_point_base
|
||||
}
|
||||
|
||||
def _escape_path(self, path):
|
||||
return path.replace('/', '%2F')
|
||||
|
3
releasenotes/notes/nexenta-ns5-5d223f3b60f58aad.yaml
Normal file
3
releasenotes/notes/nexenta-ns5-5d223f3b60f58aad.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Added extend method to NFS driver for NexentaStor 5.
|
Loading…
Reference in New Issue
Block a user