Merge "Fix backup creation errors with NetApp driver"
This commit is contained in:
commit
d773353502
@ -2315,7 +2315,9 @@ class NetAppRestClient(object):
|
|||||||
fields = ['state', 'source.svm.name', 'source.path',
|
fields = ['state', 'source.svm.name', 'source.path',
|
||||||
'destination.svm.name', 'destination.path',
|
'destination.svm.name', 'destination.path',
|
||||||
'transfer.end_time', 'uuid', 'policy.type',
|
'transfer.end_time', 'uuid', 'policy.type',
|
||||||
'transfer_schedule.name', 'transfer.state']
|
'transfer_schedule.name', 'transfer.state',
|
||||||
|
'last_transfer_type', 'transfer.bytes_transferred',
|
||||||
|
'healthy']
|
||||||
|
|
||||||
query = {}
|
query = {}
|
||||||
query['fields'] = ','.join(fields)
|
query['fields'] = ','.join(fields)
|
||||||
@ -2365,7 +2367,14 @@ class NetAppRestClient(object):
|
|||||||
(self._parse_timestamp(record['transfer']['end_time']) if
|
(self._parse_timestamp(record['transfer']['end_time']) if
|
||||||
record.get('transfer', {}).get('end_time') else 0),
|
record.get('transfer', {}).get('end_time') else 0),
|
||||||
'uuid': record['uuid'],
|
'uuid': record['uuid'],
|
||||||
'policy-type': record.get('policy', {}).get('type')
|
'policy-type': record.get('policy', {}).get('type'),
|
||||||
|
'is-healthy': (
|
||||||
|
'true'
|
||||||
|
if record.get('healthy', {}) is True else 'false'),
|
||||||
|
'last-transfer-type': record.get('last_transfer_type', None),
|
||||||
|
'last-transfer-size': record.get('transfer',
|
||||||
|
{}).get('bytes_transferred'),
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return snapmirrors
|
return snapmirrors
|
||||||
|
@ -73,20 +73,20 @@ def get_backend_configuration(backend_name):
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
def get_backup_configuration(backup_name):
|
def get_backup_configuration(backup_type):
|
||||||
config_stanzas = CONF.list_all_sections()
|
config_stanzas = CONF.list_all_sections()
|
||||||
if backup_name not in config_stanzas:
|
if backup_type not in config_stanzas:
|
||||||
msg = _("Could not find backend stanza %(backup_name)s in "
|
msg = _("Could not find backup_type stanza %(backup_type)s in "
|
||||||
"configuration which is required for backup workflows "
|
"configuration which is required for backup workflows "
|
||||||
"with the source share. Available stanzas are "
|
"with the source share. Available stanzas are "
|
||||||
"%(stanzas)s")
|
"%(stanzas)s")
|
||||||
params = {
|
params = {
|
||||||
"stanzas": config_stanzas,
|
"stanzas": config_stanzas,
|
||||||
"backend_name": backup_name,
|
"backup_type": backup_type,
|
||||||
}
|
}
|
||||||
raise exception.BadConfigurationException(reason=msg % params)
|
raise exception.BadConfigurationException(reason=msg % params)
|
||||||
config = configuration.Configuration(driver.share_opts,
|
config = configuration.Configuration(driver.share_opts,
|
||||||
config_group=backup_name)
|
config_group=backup_type)
|
||||||
config.append_config_values(na_opts.netapp_backup_opts)
|
config.append_config_values(na_opts.netapp_backup_opts)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
@ -64,9 +64,9 @@ class Backup(Enum):
|
|||||||
BACKUP_TYPE = "backup_type"
|
BACKUP_TYPE = "backup_type"
|
||||||
BACKEND_NAME = "netapp_backup_backend_section_name"
|
BACKEND_NAME = "netapp_backup_backend_section_name"
|
||||||
DES_VSERVER = "netapp_backup_vserver"
|
DES_VSERVER = "netapp_backup_vserver"
|
||||||
DES_VOLUME = "netapp_backup_share"
|
DES_VOLUME = "netapp_backup_volume"
|
||||||
SM_LABEL = "backup"
|
SM_LABEL = "backup"
|
||||||
DES_VSERVER_PREFIX = "backup_vserver"
|
DES_VSERVER_PREFIX = "backup"
|
||||||
DES_VOLUME_PREFIX = "backup_volume"
|
DES_VOLUME_PREFIX = "backup_volume"
|
||||||
VOLUME_TYPE = "dp"
|
VOLUME_TYPE = "dp"
|
||||||
SM_POLICY = "os_backup_policy"
|
SM_POLICY = "os_backup_policy"
|
||||||
@ -4350,13 +4350,24 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
" from command line or API.")
|
" from command line or API.")
|
||||||
|
|
||||||
# check the backend is related to NetApp
|
# check the backend is related to NetApp
|
||||||
|
try:
|
||||||
backup_config = data_motion.get_backup_configuration(backup_type)
|
backup_config = data_motion.get_backup_configuration(backup_type)
|
||||||
|
except exception.BadConfigurationException:
|
||||||
|
msg = _("Could not find backup_type '%(backup_type)s' stanza"
|
||||||
|
" in config file") % {'backup_type': backup_type}
|
||||||
|
raise exception.BadConfigurationException(reason=msg)
|
||||||
backend_name = backup_config.safe_get(Backup.BACKEND_NAME.value)
|
backend_name = backup_config.safe_get(Backup.BACKEND_NAME.value)
|
||||||
|
try:
|
||||||
backend_config = data_motion.get_backend_configuration(
|
backend_config = data_motion.get_backend_configuration(
|
||||||
backend_name)
|
backend_name
|
||||||
|
)
|
||||||
|
except exception.BadConfigurationException:
|
||||||
|
msg = _("Could not find backend '%(backend_name)s' stanza"
|
||||||
|
" in config file") % {'backend_name': backend_name}
|
||||||
|
raise exception.BadConfigurationException(reason=msg)
|
||||||
if (backend_config.safe_get("netapp_storage_family")
|
if (backend_config.safe_get("netapp_storage_family")
|
||||||
!= 'ontap_cluster'):
|
!= 'ontap_cluster'):
|
||||||
err_msg = _("Wrong vendor backend %s is provided, provide"
|
err_msg = _("Wrong vendor backend '%s' is provided, provide"
|
||||||
" only NetApp backend.") % backend_name
|
" only NetApp backend.") % backend_name
|
||||||
raise exception.BackupException(err_msg)
|
raise exception.BackupException(err_msg)
|
||||||
|
|
||||||
@ -4393,16 +4404,17 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
# Get the destination vserver and volume for relationship
|
# Get the destination vserver and volume for relationship
|
||||||
source_path = f"{src_vserver}:{src_vol}"
|
source_path = f"{src_vserver}:{src_vol}"
|
||||||
snapmirror_info = src_vserver_client.get_snapmirror_destinations(
|
snapmirror_info = src_vserver_client.get_snapmirror_destinations(
|
||||||
source_path=source_path)
|
source_path=source_path
|
||||||
|
)
|
||||||
if len(snapmirror_info) > 1:
|
if len(snapmirror_info) > 1:
|
||||||
err_msg = _("Source path %(path)s has more than one relationships."
|
msg = _("Source path '%(path)s' has more than one relationships."
|
||||||
" To create the share backup, delete the all source"
|
" To create the share backup, delete the all source"
|
||||||
" volume's SnapMirror relationships using 'snapmirror'"
|
" volume's SnapMirror relationships using 'snapmirror'"
|
||||||
" ONTAP CLI or System Manger.")
|
" ONTAP CLI or System Manager.")
|
||||||
msg_args = {
|
msg_args = {
|
||||||
'path': source_path
|
'path': source_path
|
||||||
}
|
}
|
||||||
raise exception.NetAppException(err_msg % msg_args)
|
raise exception.NetAppException(msg % msg_args)
|
||||||
elif len(snapmirror_info) == 1:
|
elif len(snapmirror_info) == 1:
|
||||||
des_vserver, des_volume = self._get_destination_vserver_and_vol(
|
des_vserver, des_volume = self._get_destination_vserver_and_vol(
|
||||||
src_vserver_client, source_path, False)
|
src_vserver_client, source_path, False)
|
||||||
@ -4431,7 +4443,8 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
if share_server:
|
if share_server:
|
||||||
self._delete_backup_vserver(backup, des_vserver)
|
self._delete_backup_vserver(backup, des_vserver)
|
||||||
|
|
||||||
msg = _("Failed to create a volume in vserver %(des_vserver)s")
|
msg = _("Failed to create a volume in vserver '%(des_vserver)s"
|
||||||
|
"'")
|
||||||
msg_args = {'des_vserver': des_vserver}
|
msg_args = {'des_vserver': des_vserver}
|
||||||
raise exception.NetAppException(msg % msg_args)
|
raise exception.NetAppException(msg % msg_args)
|
||||||
|
|
||||||
@ -4451,8 +4464,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
Backup.SM_LABEL.value)
|
Backup.SM_LABEL.value)
|
||||||
]
|
]
|
||||||
if len(snap_list_with_backup) == 1:
|
if len(snap_list_with_backup) == 1:
|
||||||
self.is_volume_backup_before = True
|
self._set_volume_has_backup_before(True)
|
||||||
|
|
||||||
policy_name = f"{Backup.SM_POLICY.value}_{share_instance['id']}"
|
policy_name = f"{Backup.SM_POLICY.value}_{share_instance['id']}"
|
||||||
try:
|
try:
|
||||||
des_vserver_client.create_snapmirror_policy(
|
des_vserver_client.create_snapmirror_policy(
|
||||||
@ -4490,9 +4502,9 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
des_volume,
|
des_volume,
|
||||||
share_server=share_server)
|
share_server=share_server)
|
||||||
msg = _("SnapVault relationship creation or initialization"
|
msg = _("SnapVault relationship creation or initialization"
|
||||||
" failed between source %(source_vserver)s:"
|
" failed between source '%(source_vserver)s:"
|
||||||
"%(source_volume)s and destination %(des_vserver)s:"
|
"%(source_volume)s' and destination '%(des_vserver)s:"
|
||||||
"%(des_volume)s for share id %(share_id)s.")
|
"%(des_volume)s' for share id %(share_id)s.")
|
||||||
|
|
||||||
msg_args = {
|
msg_args = {
|
||||||
'source_vserver': src_vserver,
|
'source_vserver': src_vserver,
|
||||||
@ -4564,7 +4576,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
}
|
}
|
||||||
msg = _("There is no SnapMirror relationship available for"
|
msg = _("There is no SnapMirror relationship available for"
|
||||||
" source path '%(source_path)s' and destination path"
|
" source path '%(source_path)s' and destination path"
|
||||||
" '%(des_path)s' yet.") % msg_args
|
" '%(des_path)s' yet.")
|
||||||
LOG.warning(msg, msg_args)
|
LOG.warning(msg, msg_args)
|
||||||
return progress_status
|
return progress_status
|
||||||
LOG.debug("SnapMirror details %s:", snapmirror_info)
|
LOG.debug("SnapMirror details %s:", snapmirror_info)
|
||||||
@ -4582,6 +4594,22 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
{'progress_status': progress_status})
|
{'progress_status': progress_status})
|
||||||
return progress_status
|
return progress_status
|
||||||
|
|
||||||
|
if snapmirror_info[0].get("is-healthy") == 'false':
|
||||||
|
self._resource_cleanup_for_backup(backup,
|
||||||
|
share_instance,
|
||||||
|
des_vserver,
|
||||||
|
des_vol,
|
||||||
|
share_server=share_server)
|
||||||
|
msg_args = {
|
||||||
|
'source_path': source_path,
|
||||||
|
'des_path': des_path,
|
||||||
|
}
|
||||||
|
msg = _("There is an issue with SnapMirror relationship with"
|
||||||
|
" source path '%(source_path)s' and destination path"
|
||||||
|
" '%(des_path)s'. Make sure destination volume is or was "
|
||||||
|
"not part of any other SnapMirror relationship.")
|
||||||
|
raise exception.NetAppException(message=msg % msg_args)
|
||||||
|
|
||||||
# Verify that snapshot is transferred to destination volume
|
# Verify that snapshot is transferred to destination volume
|
||||||
snap_name = self._get_backup_snapshot_name(backup,
|
snap_name = self._get_backup_snapshot_name(backup,
|
||||||
share_instance['id'])
|
share_instance['id'])
|
||||||
@ -4589,7 +4617,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
des_vol,
|
des_vol,
|
||||||
snap_name)
|
snap_name)
|
||||||
LOG.debug("Snapshot '%(snap_name)s' transferred successfully to"
|
LOG.debug("Snapshot '%(snap_name)s' transferred successfully to"
|
||||||
" destination", {'snap_name': snap_name})
|
" destination.", {'snap_name': snap_name})
|
||||||
# previously if volume was part of some relationship and if we delete
|
# previously if volume was part of some relationship and if we delete
|
||||||
# all the backup of share then last snapshot will be left on
|
# all the backup of share then last snapshot will be left on
|
||||||
# destination volume, and we can't delete that snapshot due to ONTAP
|
# destination volume, and we can't delete that snapshot due to ONTAP
|
||||||
@ -4611,11 +4639,11 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
snap_to_delete = snap_list_with_backup[1]
|
snap_to_delete = snap_list_with_backup[1]
|
||||||
else:
|
else:
|
||||||
snap_to_delete = snap_list_with_backup[0]
|
snap_to_delete = snap_list_with_backup[0]
|
||||||
self.is_volume_backup_before = False
|
self._set_volume_has_backup_before(False)
|
||||||
des_vserver_client.delete_snapshot(des_vol, snap_to_delete,
|
des_vserver_client.delete_snapshot(des_vol, snap_to_delete,
|
||||||
True)
|
True)
|
||||||
LOG.debug("Previous snapshot %{snap_name}s deleted"
|
LOG.debug("Previous snapshot %{snap_name}s deleted"
|
||||||
" successfully. ", {'snap_name': snap_to_delete})
|
" successfully.", {'snap_name': snap_to_delete})
|
||||||
return progress_status
|
return progress_status
|
||||||
|
|
||||||
@na_utils.trace
|
@na_utils.trace
|
||||||
@ -4676,7 +4704,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
"total_progress": Backup.TOTAL_PROGRESS_ZERO.value
|
"total_progress": Backup.TOTAL_PROGRESS_ZERO.value
|
||||||
}
|
}
|
||||||
return progress_status
|
return progress_status
|
||||||
LOG.debug("SnapMirror relationship of type RST is deleted")
|
LOG.debug("SnapMirror relationship of type RST is deleted.")
|
||||||
snap_name = self._get_backup_snapshot_name(backup,
|
snap_name = self._get_backup_snapshot_name(backup,
|
||||||
share_instance['id'])
|
share_instance['id'])
|
||||||
snapshot_list = src_vserver_client.list_volume_snapshots(src_vol_name)
|
snapshot_list = src_vserver_client.list_volume_snapshots(src_vol_name)
|
||||||
@ -4699,7 +4727,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
share_server=share_server,
|
share_server=share_server,
|
||||||
)
|
)
|
||||||
except exception.VserverNotFound:
|
except exception.VserverNotFound:
|
||||||
LOG.warning("Vserver associated with share %s was not found.",
|
LOG.warning("Vserver associated with share '%s' was not found.",
|
||||||
share_instance['id'])
|
share_instance['id'])
|
||||||
return
|
return
|
||||||
src_vol_name = self._get_backend_share_name(share_instance['id'])
|
src_vol_name = self._get_backend_share_name(share_instance['id'])
|
||||||
@ -4762,7 +4790,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
des_vserver_client.get_snapshot(des_vol, snap_name)
|
des_vserver_client.get_snapshot(des_vol, snap_name)
|
||||||
is_snapshot_deleted = self._is_snapshot_deleted(False)
|
is_snapshot_deleted = self._is_snapshot_deleted(False)
|
||||||
except (SnapshotResourceNotFound, netapp_api.NaApiError):
|
except (SnapshotResourceNotFound, netapp_api.NaApiError):
|
||||||
LOG.debug("Snapshot %s deleted successfully.", snap_name)
|
LOG.debug("Snapshot '%s' deleted successfully.", snap_name)
|
||||||
if not is_snapshot_deleted:
|
if not is_snapshot_deleted:
|
||||||
err_msg = _("Snapshot '%(snapshot_name)s' is not deleted"
|
err_msg = _("Snapshot '%(snapshot_name)s' is not deleted"
|
||||||
" successfully on ONTAP."
|
" successfully on ONTAP."
|
||||||
@ -4770,6 +4798,10 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
LOG.exception(err_msg)
|
LOG.exception(err_msg)
|
||||||
raise exception.NetAppException(err_msg)
|
raise exception.NetAppException(err_msg)
|
||||||
|
|
||||||
|
@na_utils.trace
|
||||||
|
def _set_volume_has_backup_before(self, value):
|
||||||
|
self.is_volume_backup_before = value
|
||||||
|
|
||||||
@na_utils.trace
|
@na_utils.trace
|
||||||
def _is_snapshot_deleted(self, is_deleted):
|
def _is_snapshot_deleted(self, is_deleted):
|
||||||
return is_deleted
|
return is_deleted
|
||||||
@ -4839,14 +4871,15 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
des_vserver_client)
|
des_vserver_client)
|
||||||
if not des_aggr:
|
if not des_aggr:
|
||||||
msg = _("Not able to find any aggregate from ONTAP"
|
msg = _("Not able to find any aggregate from ONTAP"
|
||||||
" to create the volume")
|
" to create the volume. Make sure aggregates are"
|
||||||
|
" added to destination vserver")
|
||||||
raise exception.NetAppException(msg)
|
raise exception.NetAppException(msg)
|
||||||
src_vol = self._get_backend_share_name(share_instance['id'])
|
src_vol = self._get_backend_share_name(share_instance['id'])
|
||||||
vol_attr = src_vserver_client.get_volume(src_vol)
|
vol_attr = src_vserver_client.get_volume(src_vol)
|
||||||
source_vol_size = vol_attr.get('size')
|
source_vol_size = vol_attr.get('size')
|
||||||
vol_size_in_gb = int(source_vol_size) / units.Gi
|
vol_size_in_gb = int(source_vol_size) / units.Gi
|
||||||
share_id = share_instance['id'].replace('-', '_')
|
share_id = share_instance['id'].replace('-', '_')
|
||||||
des_volume = f"backup_volume_{share_id}"
|
des_volume = f"{Backup.DES_VOLUME_PREFIX.value}_{share_id}"
|
||||||
des_vserver_client.create_volume(des_aggr, des_volume,
|
des_vserver_client.create_volume(des_aggr, des_volume,
|
||||||
vol_size_in_gb, volume_type='dp')
|
vol_size_in_gb, volume_type='dp')
|
||||||
return des_volume
|
return des_volume
|
||||||
@ -4860,7 +4893,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
|||||||
snapmirror_info = src_vserver_client.get_snapmirror_destinations(
|
snapmirror_info = src_vserver_client.get_snapmirror_destinations(
|
||||||
source_path=source_path)
|
source_path=source_path)
|
||||||
if validate_relation and len(snapmirror_info) != 1:
|
if validate_relation and len(snapmirror_info) != 1:
|
||||||
msg = _("There are more then one relationship with the source."
|
msg = _("There are more then one relationship with the source"
|
||||||
" '%(source_path)s'." % {'source_path': source_path})
|
" '%(source_path)s'." % {'source_path': source_path})
|
||||||
raise exception.NetAppException(msg)
|
raise exception.NetAppException(msg)
|
||||||
if len(snapmirror_info) == 1:
|
if len(snapmirror_info) == 1:
|
||||||
|
@ -21,6 +21,7 @@ as needed to provision shares.
|
|||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from manila.share.drivers.netapp.dataontap.cluster_mode.lib_base import Backup
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
@ -2393,7 +2394,7 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||||||
]
|
]
|
||||||
aggr_list = aggr_matching_list
|
aggr_list = aggr_matching_list
|
||||||
share_server_id = share_server['id']
|
share_server_id = share_server['id']
|
||||||
des_vserver = f"backup_{share_server_id}"
|
des_vserver = f"{Backup.DES_VSERVER_PREFIX.value}_{share_server_id}"
|
||||||
LOG.debug("Creating vserver %s:", des_vserver)
|
LOG.debug("Creating vserver %s:", des_vserver)
|
||||||
try:
|
try:
|
||||||
des_cluster_api_client.create_vserver(
|
des_cluster_api_client.create_vserver(
|
||||||
|
@ -309,7 +309,7 @@ netapp_backup_opts = [
|
|||||||
'are enabled, create separate config sections for each '
|
'are enabled, create separate config sections for each '
|
||||||
'backup type specifying the "netapp_backup_vserver", '
|
'backup type specifying the "netapp_backup_vserver", '
|
||||||
'"netapp_backup_backend_section_name", '
|
'"netapp_backup_backend_section_name", '
|
||||||
'"netapp_backup_share", and '
|
'"netapp_backup_volume", and '
|
||||||
'"netapp_snapmirror_job_timeout" as appropriate.'
|
'"netapp_snapmirror_job_timeout" as appropriate.'
|
||||||
' Example- netapp_enabled_backup_types = eng_backup,'
|
' Example- netapp_enabled_backup_types = eng_backup,'
|
||||||
' finance_backup'),
|
' finance_backup'),
|
||||||
@ -322,7 +322,7 @@ netapp_backup_opts = [
|
|||||||
help='vserver name of backend that is use for backup the share.'
|
help='vserver name of backend that is use for backup the share.'
|
||||||
' When user provide vserver value then backup volume will '
|
' When user provide vserver value then backup volume will '
|
||||||
' be created under this vserver '),
|
' be created under this vserver '),
|
||||||
cfg.StrOpt('netapp_backup_share',
|
cfg.StrOpt('netapp_backup_volume',
|
||||||
default='',
|
default='',
|
||||||
help='Specify backup share name in case user wanted to backup '
|
help='Specify backup share name in case user wanted to backup '
|
||||||
'the share. Some case user has dedicated volume for backup'
|
'the share. Some case user has dedicated volume for backup'
|
||||||
|
@ -3994,8 +3994,10 @@ SNAPMIRROR_GET_ITER_RESPONSE_REST = {
|
|||||||
"name": "hourly",
|
"name": "hourly",
|
||||||
},
|
},
|
||||||
"transfer": {
|
"transfer": {
|
||||||
"state": "success"
|
"state": "success",
|
||||||
}
|
"bytes_transferred": "3352",
|
||||||
|
},
|
||||||
|
"last_transfer_type": "update",
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"num_records": 1,
|
"num_records": 1,
|
||||||
@ -4012,7 +4014,10 @@ REST_GET_SNAPMIRRORS_RESPONSE = [{
|
|||||||
'uuid': FAKE_UUID,
|
'uuid': FAKE_UUID,
|
||||||
'policy-type': 'async',
|
'policy-type': 'async',
|
||||||
'schedule': 'hourly',
|
'schedule': 'hourly',
|
||||||
'transferring-state': 'success'
|
'transferring-state': 'success',
|
||||||
|
'is-healthy': 'true',
|
||||||
|
'last-transfer-size': '3352',
|
||||||
|
'last-transfer-type': 'update',
|
||||||
}]
|
}]
|
||||||
|
|
||||||
FAKE_CIFS_RECORDS = {
|
FAKE_CIFS_RECORDS = {
|
||||||
|
@ -2220,7 +2220,8 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
|
|||||||
':' + fake.SM_DEST_VOLUME),
|
':' + fake.SM_DEST_VOLUME),
|
||||||
'fields': 'state,source.svm.name,source.path,destination.svm.name,'
|
'fields': 'state,source.svm.name,source.path,destination.svm.name,'
|
||||||
'destination.path,transfer.end_time,uuid,policy.type,'
|
'destination.path,transfer.end_time,uuid,policy.type,'
|
||||||
'transfer_schedule.name,transfer.state'
|
'transfer_schedule.name,transfer.state,'
|
||||||
|
'last_transfer_type,transfer.bytes_transferred,healthy'
|
||||||
}
|
}
|
||||||
|
|
||||||
mock_send_request.assert_called_once_with('/snapmirror/relationships',
|
mock_send_request.assert_called_once_with('/snapmirror/relationships',
|
||||||
@ -2252,7 +2253,8 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
|
|||||||
':' + fake.SM_DEST_VOLUME),
|
':' + fake.SM_DEST_VOLUME),
|
||||||
'fields': 'state,source.svm.name,source.path,destination.svm.name,'
|
'fields': 'state,source.svm.name,source.path,destination.svm.name,'
|
||||||
'destination.path,transfer.end_time,uuid,policy.type,'
|
'destination.path,transfer.end_time,uuid,policy.type,'
|
||||||
'transfer_schedule.name,transfer.state'
|
'transfer_schedule.name,transfer.state,'
|
||||||
|
'last_transfer_type,transfer.bytes_transferred,healthy'
|
||||||
}
|
}
|
||||||
|
|
||||||
mock_send_request.assert_called_once_with('/snapmirror/relationships',
|
mock_send_request.assert_called_once_with('/snapmirror/relationships',
|
||||||
@ -2280,7 +2282,8 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
|
|||||||
':' + fake.SM_DEST_VOLUME),
|
':' + fake.SM_DEST_VOLUME),
|
||||||
'fields': 'state,source.svm.name,source.path,destination.svm.name,'
|
'fields': 'state,source.svm.name,source.path,destination.svm.name,'
|
||||||
'destination.path,transfer.end_time,uuid,policy.type,'
|
'destination.path,transfer.end_time,uuid,policy.type,'
|
||||||
'transfer_schedule.name,transfer.state'
|
'transfer_schedule.name,transfer.state,'
|
||||||
|
'last_transfer_type,transfer.bytes_transferred,healthy'
|
||||||
}
|
}
|
||||||
|
|
||||||
mock_send_request.assert_called_once_with('/snapmirror/relationships',
|
mock_send_request.assert_called_once_with('/snapmirror/relationships',
|
||||||
|
@ -81,7 +81,7 @@ def _get_config():
|
|||||||
CONF.set_override("netapp_backup_vserver",
|
CONF.set_override("netapp_backup_vserver",
|
||||||
"fake_backup_share",
|
"fake_backup_share",
|
||||||
group=backup_config)
|
group=backup_config)
|
||||||
CONF.set_override("netapp_backup_share",
|
CONF.set_override("netapp_backup_volume",
|
||||||
"fake_share_server",
|
"fake_share_server",
|
||||||
group=backup_config)
|
group=backup_config)
|
||||||
return config
|
return config
|
||||||
@ -8023,7 +8023,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
backup_config = 'backup_config'
|
backup_config = 'backup_config'
|
||||||
fake_config = configuration.Configuration(driver.share_opts,
|
fake_config = configuration.Configuration(driver.share_opts,
|
||||||
config_group=backup_config)
|
config_group=backup_config)
|
||||||
CONF.set_override("netapp_backup_share", "",
|
CONF.set_override("netapp_backup_volume", "",
|
||||||
group=backup_config)
|
group=backup_config)
|
||||||
CONF.set_override("netapp_backup_vserver", "",
|
CONF.set_override("netapp_backup_vserver", "",
|
||||||
group=backup_config)
|
group=backup_config)
|
||||||
@ -8045,7 +8045,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
backup_config = 'backup_config'
|
backup_config = 'backup_config'
|
||||||
fake_config = configuration.Configuration(driver.share_opts,
|
fake_config = configuration.Configuration(driver.share_opts,
|
||||||
config_group=backup_config)
|
config_group=backup_config)
|
||||||
CONF.set_override("netapp_backup_share", "",
|
CONF.set_override("netapp_backup_volume", "",
|
||||||
group=backup_config)
|
group=backup_config)
|
||||||
CONF.set_override("netapp_backup_vserver", "",
|
CONF.set_override("netapp_backup_vserver", "",
|
||||||
group=backup_config)
|
group=backup_config)
|
||||||
@ -8240,7 +8240,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
|
|
||||||
self._backup_mock_common_method(mock_des_vserver_client)
|
self._backup_mock_common_method(mock_des_vserver_client)
|
||||||
backup_config = 'backup_config'
|
backup_config = 'backup_config'
|
||||||
CONF.set_override("netapp_backup_share", "",
|
CONF.set_override("netapp_backup_volume", "",
|
||||||
group=backup_config)
|
group=backup_config)
|
||||||
CONF.set_override("netapp_backup_vserver", "",
|
CONF.set_override("netapp_backup_vserver", "",
|
||||||
group=backup_config)
|
group=backup_config)
|
||||||
@ -8469,6 +8469,48 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
fake.SHARE_BACKUP,
|
fake.SHARE_BACKUP,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_create_backup_when_invalid_backup_type_negative(self):
|
||||||
|
mock_src_client = mock.Mock()
|
||||||
|
self.mock_object(self.library,
|
||||||
|
'_get_vserver',
|
||||||
|
mock.Mock(return_value=(fake.VSERVER1,
|
||||||
|
mock_src_client)))
|
||||||
|
self.mock_object(self.mock_dm_session,
|
||||||
|
'get_backup_configuration',
|
||||||
|
mock.Mock(
|
||||||
|
side_effect=exception.BadConfigurationException,
|
||||||
|
))
|
||||||
|
self.assertRaises(
|
||||||
|
exception.BadConfigurationException,
|
||||||
|
self.library.create_backup,
|
||||||
|
self.context,
|
||||||
|
fake.SHARE_INSTANCE,
|
||||||
|
fake.SHARE_BACKUP,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_backup_when_invalid_backend_negative(self):
|
||||||
|
mock_src_client = mock.Mock()
|
||||||
|
self.mock_object(self.library,
|
||||||
|
'_get_vserver',
|
||||||
|
mock.Mock(return_value=(fake.VSERVER1,
|
||||||
|
mock_src_client)))
|
||||||
|
self.mock_object(data_motion,
|
||||||
|
'get_backup_configuration',
|
||||||
|
mock.Mock(return_value=_get_config()))
|
||||||
|
|
||||||
|
self.mock_object(self.mock_dm_session,
|
||||||
|
'get_backend_configuration',
|
||||||
|
mock.Mock(
|
||||||
|
side_effect=exception.BadConfigurationException,
|
||||||
|
))
|
||||||
|
self.assertRaises(
|
||||||
|
exception.BadConfigurationException,
|
||||||
|
self.library.create_backup,
|
||||||
|
self.context,
|
||||||
|
fake.SHARE_INSTANCE,
|
||||||
|
fake.SHARE_BACKUP,
|
||||||
|
)
|
||||||
|
|
||||||
def test_create_backup_continue_with_status_inprogress(self):
|
def test_create_backup_continue_with_status_inprogress(self):
|
||||||
vserver_client = mock.Mock()
|
vserver_client = mock.Mock()
|
||||||
mock_dest_client = mock.Mock()
|
mock_dest_client = mock.Mock()
|
||||||
@ -8578,6 +8620,60 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
fake.SHARE_BACKUP,
|
fake.SHARE_BACKUP,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_create_backup_continue_snapshot_left_from_old_relationship(self):
|
||||||
|
vserver_client = mock.Mock()
|
||||||
|
mock_dest_client = mock.Mock()
|
||||||
|
self._backup_mock_common_method(mock_dest_client)
|
||||||
|
self.mock_object(self.library,
|
||||||
|
'_get_vserver',
|
||||||
|
mock.Mock(return_value=(fake.VSERVER1,
|
||||||
|
vserver_client)))
|
||||||
|
snapmirror_info = [fake.SNAP_MIRROR_INFO]
|
||||||
|
self.mock_object(mock_dest_client,
|
||||||
|
'get_snapmirrors',
|
||||||
|
mock.Mock(return_value=snapmirror_info))
|
||||||
|
snap_list = ["snap1", "snap2"]
|
||||||
|
self.mock_object(self.library,
|
||||||
|
'_get_des_volume_backup_snapshots',
|
||||||
|
mock.Mock(return_value=snap_list))
|
||||||
|
|
||||||
|
self.library._set_volume_has_backup_before(True)
|
||||||
|
share_instance = fake.SHARE_INSTANCE
|
||||||
|
backup = fake.SHARE_BACKUP
|
||||||
|
self.library.create_backup_continue(self.context, share_instance,
|
||||||
|
backup)
|
||||||
|
self.library._set_volume_has_backup_before(False)
|
||||||
|
|
||||||
|
def test_create_backup_continue_relationship_not_healthy_negative(self):
|
||||||
|
vserver_client = mock.Mock()
|
||||||
|
mock_dest_client = mock.Mock()
|
||||||
|
self._backup_mock_common_method(mock_dest_client)
|
||||||
|
self.mock_object(self.library,
|
||||||
|
'_get_vserver',
|
||||||
|
mock.Mock(return_value=(fake.VSERVER1,
|
||||||
|
vserver_client)))
|
||||||
|
snapmirror_info = [
|
||||||
|
{
|
||||||
|
'source-vserver': fake.VSERVER1,
|
||||||
|
'source-volume': fake.FLEXVOL_NAME,
|
||||||
|
'destination-vserver': fake.VSERVER2,
|
||||||
|
'destination-volume': fake.FLEXVOL_NAME_1,
|
||||||
|
'relationship-status': "idle",
|
||||||
|
'last-transfer-type': "update",
|
||||||
|
'is-healthy': "false",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
self.mock_object(mock_dest_client,
|
||||||
|
'get_snapmirrors',
|
||||||
|
mock.Mock(return_value=snapmirror_info))
|
||||||
|
self.assertRaises(
|
||||||
|
exception.NetAppException,
|
||||||
|
self.library.create_backup_continue,
|
||||||
|
self.context,
|
||||||
|
fake.SHARE_INSTANCE,
|
||||||
|
fake.SHARE_BACKUP,
|
||||||
|
)
|
||||||
|
|
||||||
def test_restore_backup_with_vserver_volume_none(self):
|
def test_restore_backup_with_vserver_volume_none(self):
|
||||||
vserver_client = mock.Mock()
|
vserver_client = mock.Mock()
|
||||||
self.mock_object(self.library,
|
self.mock_object(self.library,
|
||||||
@ -8727,6 +8823,27 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
fake.SHARE_BACKUP,
|
fake.SHARE_BACKUP,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_delete_backup_snapshot_not_exist(self):
|
||||||
|
vserver_client = mock.Mock()
|
||||||
|
mock_des_client = mock.Mock()
|
||||||
|
self._backup_mock_common_method(mock_des_client)
|
||||||
|
self._backup_mock_common_method_for_negative(vserver_client,
|
||||||
|
mock_des_client)
|
||||||
|
self.mock_object(self.library,
|
||||||
|
'_get_des_volume_backup_snapshots',
|
||||||
|
mock.Mock(return_value=['fake_snapshot1',
|
||||||
|
'fake_snapshot2']))
|
||||||
|
self.mock_object(self.library,
|
||||||
|
'_is_snapshot_deleted',
|
||||||
|
mock.Mock(return_value=True))
|
||||||
|
msg = "entry doesn't exist"
|
||||||
|
self.mock_object(mock_des_client,
|
||||||
|
'delete_snapshot',
|
||||||
|
mock.Mock(side_effect=netapp_api.NaApiError(
|
||||||
|
message=msg)))
|
||||||
|
self.library.delete_backup(self.context, fake.SHARE_BACKUP,
|
||||||
|
fake.SHARE_INSTANCE)
|
||||||
|
|
||||||
def test__get_backup_progress_status(self):
|
def test__get_backup_progress_status(self):
|
||||||
mock_dest_client = mock.Mock()
|
mock_dest_client = mock.Mock()
|
||||||
vol_attr = {'name': 'fake_vol', 'size-used': '123454'}
|
vol_attr = {'name': 'fake_vol', 'size-used': '123454'}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
NetApp driver `bug #2058027
|
||||||
|
<https://bugs.launchpad.net/manila/+bug/2058027>`_:
|
||||||
|
Fix the issue for NetApp driver for backup feature. Backup status
|
||||||
|
update used to fail when administrator misconfigured backup settings
|
||||||
|
configuration or SnapMirror relationship created during backup
|
||||||
|
creation was not in healthy state.
|
Loading…
Reference in New Issue
Block a user