Add backup_swift_create_storage_policy config opt
This configuration option is used by the Swift backup driver to select the storage policy to use when creating the container used to store backups. It defaults to None meaning the default behavior is preserved. Change-Id: I0a4a9d4e099c7d4a1d209be28ade5a517aeb96df
This commit is contained in:
parent
f340058145
commit
b292238405
@ -51,6 +51,7 @@ from oslo_log import log as logging
|
||||
from oslo_utils import secretutils
|
||||
from oslo_utils import timeutils
|
||||
from swiftclient import client as swift
|
||||
from swiftclient import exceptions as swift_exc
|
||||
|
||||
from cinder.backup import chunkeddriver
|
||||
from cinder import exception
|
||||
@ -108,6 +109,11 @@ swiftbackup_service_opts = [
|
||||
cfg.StrOpt('backup_swift_container',
|
||||
default='volumebackups',
|
||||
help='The default Swift container to use'),
|
||||
cfg.StrOpt('backup_swift_create_storage_policy',
|
||||
default=None,
|
||||
help='The storage policy to use when creating the Swift '
|
||||
'container. If the container already exists the '
|
||||
'storage policy cannot be enforced'),
|
||||
cfg.IntOpt('backup_swift_object_size',
|
||||
default=52428800,
|
||||
help='The size in bytes of Swift backup objects'),
|
||||
@ -318,12 +324,31 @@ class SwiftBackupDriver(chunkeddriver.ChunkedBackupDriver):
|
||||
return body
|
||||
|
||||
def put_container(self, container):
|
||||
"""Create the container if needed. No failure if it pre-exists."""
|
||||
"""Create the container if needed.
|
||||
|
||||
Check if the container exist by issuing a HEAD request, if
|
||||
the container does not exist we create it.
|
||||
|
||||
We cannot enforce a new storage policy on an
|
||||
existing container.
|
||||
"""
|
||||
try:
|
||||
self.conn.put_container(container)
|
||||
self.conn.head_container(container)
|
||||
except swift_exc.ClientException as e:
|
||||
if e.http_status == 404:
|
||||
try:
|
||||
storage_policy = CONF.backup_swift_create_storage_policy
|
||||
headers = ({'X-Storage-Policy': storage_policy}
|
||||
if storage_policy else None)
|
||||
self.conn.put_container(container, headers=headers)
|
||||
except socket.error as err:
|
||||
raise exception.SwiftConnectionFailed(reason=err)
|
||||
return
|
||||
LOG.warning("Failed to HEAD container to determine if it "
|
||||
"exists and should be created.")
|
||||
raise exception.SwiftConnectionFailed(reason=e)
|
||||
except socket.error as err:
|
||||
raise exception.SwiftConnectionFailed(reason=err)
|
||||
return
|
||||
|
||||
def get_container_entries(self, container, prefix):
|
||||
"""Get container entry names"""
|
||||
|
@ -299,6 +299,54 @@ class BackupSwiftTestCase(test.TestCase):
|
||||
starting_backoff=ANY,
|
||||
cacert=ANY)
|
||||
|
||||
@mock.patch.object(fake_swift_client.FakeSwiftConnection, 'put_container')
|
||||
def test_default_backup_swift_create_storage_policy(self, mock_put):
|
||||
service = swift_dr.SwiftBackupDriver(self.ctxt)
|
||||
service.put_container('missing_container')
|
||||
mock_put.assert_called_once_with('missing_container', headers=None)
|
||||
|
||||
@mock.patch.object(fake_swift_client.FakeSwiftConnection, 'put_container')
|
||||
def test_backup_swift_create_storage_policy(self, mock_put):
|
||||
self.override_config('backup_swift_create_storage_policy',
|
||||
'mypolicy')
|
||||
service = swift_dr.SwiftBackupDriver(self.ctxt)
|
||||
service.put_container('missing_container')
|
||||
mock_put.assert_called_once_with(
|
||||
'missing_container',
|
||||
headers={'X-Storage-Policy': 'mypolicy'}
|
||||
)
|
||||
|
||||
def test_default_backup_swift_create_storage_policy_put_socket_error(self):
|
||||
service = swift_dr.SwiftBackupDriver(self.ctxt)
|
||||
self.assertRaises(exception.SwiftConnectionFailed,
|
||||
service.put_container,
|
||||
'missing_container_socket_error_on_put')
|
||||
|
||||
def test_default_backup_swift_create_storage_policy_head_error(self):
|
||||
service = swift_dr.SwiftBackupDriver(self.ctxt)
|
||||
self.assertRaises(exception.SwiftConnectionFailed,
|
||||
service.put_container, 'unauthorized_container')
|
||||
|
||||
def test_backup_swift_create_storage_policy_head_error(self):
|
||||
self.override_config('backup_swift_create_storage_policy',
|
||||
'mypolicy')
|
||||
service = swift_dr.SwiftBackupDriver(self.ctxt)
|
||||
self.assertRaises(exception.SwiftConnectionFailed,
|
||||
service.put_container,
|
||||
'unauthorized_container')
|
||||
|
||||
def test_default_backup_swift_create_storage_policy_head_sockerr(self):
|
||||
service = swift_dr.SwiftBackupDriver(self.ctxt)
|
||||
self.assertRaises(exception.SwiftConnectionFailed,
|
||||
service.put_container, 'socket_error_on_head')
|
||||
|
||||
def test_backup_swift_create_storage_policy_head_socket_error(self):
|
||||
self.override_config('backup_swift_create_storage_policy',
|
||||
'mypolicy')
|
||||
service = swift_dr.SwiftBackupDriver(self.ctxt)
|
||||
self.assertRaises(exception.SwiftConnectionFailed,
|
||||
service.put_container, 'socket_error_on_head')
|
||||
|
||||
def test_backup_uncompressed(self):
|
||||
volume_id = '2b9f10a3-42b4-4fdf-b316-000000ceb039'
|
||||
self._create_backup_db_entry(volume_id=volume_id)
|
||||
|
@ -38,7 +38,8 @@ class FakeSwiftConnection(object):
|
||||
pass
|
||||
|
||||
def head_container(self, container):
|
||||
if container == 'missing_container':
|
||||
if container in ['missing_container',
|
||||
'missing_container_socket_error_on_put']:
|
||||
raise swift.ClientException('fake exception',
|
||||
http_status=http_client.NOT_FOUND)
|
||||
elif container == 'unauthorized_container':
|
||||
@ -48,8 +49,9 @@ class FakeSwiftConnection(object):
|
||||
raise socket.error(111, 'ECONNREFUSED')
|
||||
pass
|
||||
|
||||
def put_container(self, container):
|
||||
pass
|
||||
def put_container(self, container, headers=None):
|
||||
if container == 'missing_container_socket_error_on_put':
|
||||
raise socket.error(111, 'ECONNREFUSED')
|
||||
|
||||
def get_container(self, container, **kwargs):
|
||||
fake_header = None
|
||||
|
@ -46,7 +46,7 @@ class FakeSwiftConnection2(object):
|
||||
elif container == 'socket_error_on_head':
|
||||
raise socket.error(111, 'ECONNREFUSED')
|
||||
|
||||
def put_container(self, container):
|
||||
def put_container(self, container, headers=None):
|
||||
pass
|
||||
|
||||
def get_container(self, container, **kwargs):
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Swift backup driver: Added new configuration option ``backup_swift_create_storage_policy``
|
||||
for the Swift backup driver. If specified it will be used as the storage policy when
|
||||
creating the Swift Container, default value is None meaning it will not be used and Swift
|
||||
will use the system default. Please note that this only applies if a container doesn't exist
|
||||
as we cannot update the storage policy on an already existing container.
|
Loading…
Reference in New Issue
Block a user