Update Share backup APIs and add api ref
- Follow up change to fix suggestions from earlier pull request i.e. https://review.opendev.org/c/openstack/manila/+/343980 . - Add API-ref docs - Rename column availability_zone to availability_zone_id in share_backups table. Implement: blueprint share-backup Closes-bug: #2031311 Change-Id: Ice01ab7892b1eb52b3202f2c79957977f73f3aca
This commit is contained in:
parent
aafc221027
commit
3a2d220f8a
@ -66,3 +66,4 @@ Shared File Systems API (EXPERIMENTAL)
|
|||||||
.. include:: experimental.inc
|
.. include:: experimental.inc
|
||||||
.. include:: share-migration.inc
|
.. include:: share-migration.inc
|
||||||
.. include:: share-server-migration.inc
|
.. include:: share-server-migration.inc
|
||||||
|
.. include:: share-backups.inc
|
||||||
|
@ -72,6 +72,8 @@ Response parameters
|
|||||||
- maxTotalShareNetworks: maxTotalShareNetworks
|
- maxTotalShareNetworks: maxTotalShareNetworks
|
||||||
- maxTotalShareReplicas: maxTotalShareReplicas
|
- maxTotalShareReplicas: maxTotalShareReplicas
|
||||||
- maxTotalReplicaGigabytes: maxTotalReplicaGigabytes
|
- maxTotalReplicaGigabytes: maxTotalReplicaGigabytes
|
||||||
|
- maxTotalShareBackups: maxTotalShareBackups
|
||||||
|
- maxTotalBackupGigabytes: maxTotalBackupGigabytes
|
||||||
- totalSharesUsed: totalSharesUsed
|
- totalSharesUsed: totalSharesUsed
|
||||||
- totalShareSnapshotsUsed: totalShareSnapshotsUsed
|
- totalShareSnapshotsUsed: totalShareSnapshotsUsed
|
||||||
- totalShareNetworksUsed: totalShareNetworksUsed
|
- totalShareNetworksUsed: totalShareNetworksUsed
|
||||||
@ -79,6 +81,8 @@ Response parameters
|
|||||||
- totalSnapshotGigabytesUsed: totalSnapshotGigabytesUsed
|
- totalSnapshotGigabytesUsed: totalSnapshotGigabytesUsed
|
||||||
- totalShareReplicasUsed: totalShareReplicasUsed
|
- totalShareReplicasUsed: totalShareReplicasUsed
|
||||||
- totalReplicaGigabytesUsed: totalReplicaGigabytesUsed
|
- totalReplicaGigabytesUsed: totalReplicaGigabytesUsed
|
||||||
|
- totalShareBackupsUsed: totalShareBackupsUsed
|
||||||
|
- totalBackupGigabytesUsed: totalBackupGigabytesUsed
|
||||||
- uri: uri
|
- uri: uri
|
||||||
- regex: regex
|
- regex: regex
|
||||||
- value: value
|
- value: value
|
||||||
|
@ -25,6 +25,12 @@ api_version:
|
|||||||
type: string
|
type: string
|
||||||
description: >
|
description: >
|
||||||
The API version as returned in the links from the ``GET /`` call.
|
The API version as returned in the links from the ``GET /`` call.
|
||||||
|
backup_id_request_path:
|
||||||
|
description: |
|
||||||
|
The UUID of the share backup.
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
export_location_id_path:
|
export_location_id_path:
|
||||||
description: |
|
description: |
|
||||||
The UUID of the export location.
|
The UUID of the export location.
|
||||||
@ -224,6 +230,34 @@ backend_query:
|
|||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
backup_host_query:
|
||||||
|
description: |
|
||||||
|
The host name of the backup to query with. Querying by hostname is a
|
||||||
|
privileged operation. If restricted by API policy, this query parameter
|
||||||
|
may be silently ignored by the server.
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
backup_share_id_query:
|
||||||
|
description: |
|
||||||
|
The UUID of the share that the backup pertains to.
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
backup_status_query:
|
||||||
|
description: |
|
||||||
|
Filters by a backup status. A valid filter value can be one of 'creating',
|
||||||
|
'error', 'available', 'restoring'.
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
backup_topic_query:
|
||||||
|
description: |
|
||||||
|
Filters by a backup topic. A valid filter value can be one of
|
||||||
|
'manila-data', 'manila-share'.
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
cidr_query:
|
cidr_query:
|
||||||
description: |
|
description: |
|
||||||
The CIDR to filter share networks.
|
The CIDR to filter share networks.
|
||||||
@ -292,6 +326,12 @@ description_inexact_query:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
min_version: 2.36
|
min_version: 2.36
|
||||||
|
description_inexact_query_versionless:
|
||||||
|
description: |
|
||||||
|
The description pattern that can be used to filter share backups.
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
description_query:
|
description_query:
|
||||||
description: |
|
description: |
|
||||||
The user defined description text that can be used to filter resources.
|
The user defined description text that can be used to filter resources.
|
||||||
@ -386,7 +426,7 @@ is_soft_deleted_query:
|
|||||||
min_version: 2.69
|
min_version: 2.69
|
||||||
limit:
|
limit:
|
||||||
description: |
|
description: |
|
||||||
The maximum number of shares to return.
|
The maximum number of resource records to return.
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: integer
|
type: integer
|
||||||
@ -417,6 +457,12 @@ name_inexact_query:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
min_version: 2.36
|
min_version: 2.36
|
||||||
|
name_inexact_query_versionless:
|
||||||
|
description: |
|
||||||
|
The name pattern that can be used to filter share backups.
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
name_query:
|
name_query:
|
||||||
description: |
|
description: |
|
||||||
The user defined name of the resource to filter resources by.
|
The user defined name of the resource to filter resources by.
|
||||||
@ -688,6 +734,15 @@ sort_key:
|
|||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
sort_key_backup:
|
||||||
|
description: |
|
||||||
|
The key to sort a list of share backups. A valid value
|
||||||
|
is ``id``, ``status``, ``size``, ``host``, ``share_id``
|
||||||
|
``availability_zone``, ``created_at``, ``updated_at``, ``display_name``,
|
||||||
|
``topic``, ``progress`` and ``restore_progress``
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
sort_key_messages:
|
sort_key_messages:
|
||||||
description: |
|
description: |
|
||||||
The key to sort a list of messages. A valid value
|
The key to sort a list of messages. A valid value
|
||||||
@ -715,6 +770,12 @@ sort_key_transfer:
|
|||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
source_backup_id_query:
|
||||||
|
description: |
|
||||||
|
The UUID of the share's backup to filter the request based on.
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
source_share_group_snapshot_id_query:
|
source_share_group_snapshot_id_query:
|
||||||
description: |
|
description: |
|
||||||
The source share group snapshot ID to list the
|
The source share group snapshot ID to list the
|
||||||
@ -987,6 +1048,63 @@ backend_name:
|
|||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
backup_az:
|
||||||
|
description: |
|
||||||
|
The availability zone.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
backup_id_response:
|
||||||
|
description: |
|
||||||
|
The UUID of the share backup.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
backup_options_request:
|
||||||
|
description: |
|
||||||
|
One or more backup options key and value pairs as a
|
||||||
|
url encoded dictionary of strings.
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
type: object
|
||||||
|
backup_progress:
|
||||||
|
description: |
|
||||||
|
The progress of the backup creation in percentange.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
backup_restore_progress:
|
||||||
|
description: |
|
||||||
|
The progress of the backup restoration in percentage.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
backup_share_id:
|
||||||
|
description: |
|
||||||
|
The UUID of the share that the backup pertains to.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
backup_size:
|
||||||
|
description: |
|
||||||
|
The share backup size, in GiBs.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
backup_status:
|
||||||
|
description: |
|
||||||
|
The status of backup which can be one of ``creating``, ``error``,
|
||||||
|
``available``, ``restoring``.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
backup_status_request:
|
||||||
|
description: |
|
||||||
|
The backup status, which can be ``available``,
|
||||||
|
``error``, ``creating``, ``deleting``, ``restoring``.
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
capabilities:
|
capabilities:
|
||||||
description: |
|
description: |
|
||||||
The back end capabilities which include ``qos``, ``total_capacity_gb``,
|
The back end capabilities which include ``qos``, ``total_capacity_gb``,
|
||||||
@ -1655,6 +1773,22 @@ managed_share_user_id:
|
|||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
min_version: 2.16
|
min_version: 2.16
|
||||||
|
maxTotalBackupGigabytes:
|
||||||
|
description: |
|
||||||
|
The total maximum number of backup gigabytes
|
||||||
|
that are allowed in a project.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
min_version: 2.80
|
||||||
|
maxTotalBackupGigabytesOptional:
|
||||||
|
description: |
|
||||||
|
The total maximum number of backup gigabytes
|
||||||
|
that are allowed in a project.
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
type: integer
|
||||||
|
min_version: 2.80
|
||||||
maxTotalReplicaGigabytes:
|
maxTotalReplicaGigabytes:
|
||||||
description: |
|
description: |
|
||||||
The maximum number of replica gigabytes that are allowed in a project.
|
The maximum number of replica gigabytes that are allowed in a project.
|
||||||
@ -1673,6 +1807,22 @@ maxTotalReplicaGigabytesOptional:
|
|||||||
required: false
|
required: false
|
||||||
type: integer
|
type: integer
|
||||||
min_version: 2.53
|
min_version: 2.53
|
||||||
|
maxTotalShareBackups:
|
||||||
|
description: |
|
||||||
|
The total maximum number of share backups that
|
||||||
|
are allowed in a project.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
min_version: 2.80
|
||||||
|
maxTotalShareBackupsOptional:
|
||||||
|
description: |
|
||||||
|
The total maximum number of share backups that
|
||||||
|
are allowed in a project.
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
type: integer
|
||||||
|
min_version: 2.80
|
||||||
maxTotalShareGigabytes:
|
maxTotalShareGigabytes:
|
||||||
description: |
|
description: |
|
||||||
The total maximum number of share gigabytes that
|
The total maximum number of share gigabytes that
|
||||||
@ -2161,6 +2311,51 @@ protocol:
|
|||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
quota_backup_gigabytes:
|
||||||
|
description: |
|
||||||
|
The number of gigabytes for the backups allowed for each project.
|
||||||
|
in: body
|
||||||
|
min_version: 2.80
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
quota_backup_gigabytes_detail:
|
||||||
|
description: |
|
||||||
|
The limit, in_use, reserved number of gigabytes for the
|
||||||
|
backups allowed for each project.
|
||||||
|
in: body
|
||||||
|
min_version: 2.80
|
||||||
|
required: true
|
||||||
|
type: object
|
||||||
|
quota_backup_gigabytes_request:
|
||||||
|
description: |
|
||||||
|
The number of gigabytes for the backups for the
|
||||||
|
project.
|
||||||
|
in: body
|
||||||
|
min_version: 2.80
|
||||||
|
required: false
|
||||||
|
type: integer
|
||||||
|
quota_backups:
|
||||||
|
description: |
|
||||||
|
The number of backups allowed for each project.
|
||||||
|
in: body
|
||||||
|
min_version: 2.80
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
quota_backups_detail:
|
||||||
|
description: |
|
||||||
|
The limit, in_use, reserved number of backups allowed
|
||||||
|
for each project.
|
||||||
|
in: body
|
||||||
|
min_version: 2.80
|
||||||
|
required: true
|
||||||
|
type: object
|
||||||
|
quota_backups_request:
|
||||||
|
description: |
|
||||||
|
The number of backups for the project.
|
||||||
|
in: body
|
||||||
|
min_version: 2.80
|
||||||
|
required: false
|
||||||
|
type: integer
|
||||||
quota_class_id:
|
quota_class_id:
|
||||||
description: |
|
description: |
|
||||||
A ``quota_class_set`` id.
|
A ``quota_class_set`` id.
|
||||||
@ -3703,6 +3898,13 @@ snapshot_user_id:
|
|||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
min_version: 2.17
|
min_version: 2.17
|
||||||
|
source_backup_id_shares_response:
|
||||||
|
description: |
|
||||||
|
The UUID of the backup that was restored in the share.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
min_version: 2.80
|
||||||
source_share_group_snapshot_id:
|
source_share_group_snapshot_id:
|
||||||
description: |
|
description: |
|
||||||
The source share group snapshot ID to create the
|
The source share group snapshot ID to create the
|
||||||
@ -3805,6 +4007,13 @@ total_progress_server_migration:
|
|||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: integer
|
type: integer
|
||||||
|
totalBackupGigabytesUsed:
|
||||||
|
description: |
|
||||||
|
The total number of gigabytes used in a project
|
||||||
|
by backups.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
totalReplicaGigabytesUsed:
|
totalReplicaGigabytesUsed:
|
||||||
description: |
|
description: |
|
||||||
The total number of replica gigabytes used in a
|
The total number of replica gigabytes used in a
|
||||||
@ -3812,6 +4021,13 @@ totalReplicaGigabytesUsed:
|
|||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: integer
|
type: integer
|
||||||
|
totalShareBackupsUsed:
|
||||||
|
description: |
|
||||||
|
The total number of created share backups in a
|
||||||
|
project.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
totalShareGigabytesUsed:
|
totalShareGigabytesUsed:
|
||||||
description: |
|
description: |
|
||||||
The total number of gigabytes used in a project
|
The total number of gigabytes used in a project
|
||||||
|
@ -10,6 +10,8 @@ Quota classes can be shown and updated for a project.
|
|||||||
APIs in API version 2.53.
|
APIs in API version 2.53.
|
||||||
Per share gigabytes was added to quota management APIs in API
|
Per share gigabytes was added to quota management APIs in API
|
||||||
version 2.62.
|
version 2.62.
|
||||||
|
Share backups and backup gigabytes were added to quota management
|
||||||
|
APIs in API version 2.80.
|
||||||
|
|
||||||
|
|
||||||
Show quota classes for a project
|
Show quota classes for a project
|
||||||
@ -58,6 +60,8 @@ Response Parameters
|
|||||||
- share_replicas: maxTotalShareReplicas
|
- share_replicas: maxTotalShareReplicas
|
||||||
- replica_gigabytes: maxTotalReplicaGigabytes
|
- replica_gigabytes: maxTotalReplicaGigabytes
|
||||||
- per_share_gigabytes: perShareGigabytes
|
- per_share_gigabytes: perShareGigabytes
|
||||||
|
- backups: maxTotalShareBackups
|
||||||
|
- backup_gigabytes: maxTotalBackupGigabytes
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
@ -102,6 +106,8 @@ Request
|
|||||||
- share-replicas: maxTotalShareReplicasOptional
|
- share-replicas: maxTotalShareReplicasOptional
|
||||||
- replica-gigabytes: maxTotalReplicaGigabytesOptional
|
- replica-gigabytes: maxTotalReplicaGigabytesOptional
|
||||||
- per-share-gigabytes: perShareGigabytesOptional
|
- per-share-gigabytes: perShareGigabytesOptional
|
||||||
|
- backups: maxTotalShareBackupsOptional
|
||||||
|
- backup-gigabytes: maxTotalBackupGigabytesOptional
|
||||||
|
|
||||||
Request Example
|
Request Example
|
||||||
---------------
|
---------------
|
||||||
@ -126,6 +132,8 @@ Response Parameters
|
|||||||
- share_replicas: maxTotalShareReplicas
|
- share_replicas: maxTotalShareReplicas
|
||||||
- replica_gigabytes: maxTotalReplicaGigabytes
|
- replica_gigabytes: maxTotalReplicaGigabytes
|
||||||
- per_share_gigabytes: perShareGigabytes
|
- per_share_gigabytes: perShareGigabytes
|
||||||
|
- backups: maxTotalShareBackups
|
||||||
|
- backup_gigabytes: maxTotalBackupGigabytes
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
|
@ -22,6 +22,8 @@ Provides quotas management support.
|
|||||||
- ``share_replicas`` (since API version 2.53)
|
- ``share_replicas`` (since API version 2.53)
|
||||||
- ``replica_gigabytes`` (since API version 2.53)
|
- ``replica_gigabytes`` (since API version 2.53)
|
||||||
- ``per_share_gigabytes`` (since API version 2.62)
|
- ``per_share_gigabytes`` (since API version 2.62)
|
||||||
|
- ``backups`` (since API version 2.80)
|
||||||
|
- ``backup_gigabytes`` (since API version 2.80)
|
||||||
|
|
||||||
In order to manipulate share type quotas, the requests will be similar
|
In order to manipulate share type quotas, the requests will be similar
|
||||||
to the examples below, except that the ``user_id={user_id}`` must be
|
to the examples below, except that the ``user_id={user_id}`` must be
|
||||||
@ -36,6 +38,9 @@ Provides quotas management support.
|
|||||||
Per share gigabytes was added to quota management APIs in API
|
Per share gigabytes was added to quota management APIs in API
|
||||||
version 2.62.
|
version 2.62.
|
||||||
|
|
||||||
|
Share backups and backup gigabytes were added to quota management
|
||||||
|
APIs in API version 2.80.
|
||||||
|
|
||||||
|
|
||||||
Show default quota set
|
Show default quota set
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -83,6 +88,8 @@ Response parameters
|
|||||||
- share_replicas: quota_share_replicas
|
- share_replicas: quota_share_replicas
|
||||||
- replica_gigabytes: quota_replica_gigabytes
|
- replica_gigabytes: quota_replica_gigabytes
|
||||||
- per_share_gigabytes: quota_per_share_gigabytes
|
- per_share_gigabytes: quota_per_share_gigabytes
|
||||||
|
- backups: quota_backups
|
||||||
|
- backup_gigabytes: quota_backup_gigabytes
|
||||||
|
|
||||||
Response example
|
Response example
|
||||||
----------------
|
----------------
|
||||||
@ -142,6 +149,8 @@ Response parameters
|
|||||||
- share_replicas: quota_share_replicas
|
- share_replicas: quota_share_replicas
|
||||||
- replica_gigabytes: quota_replica_gigabytes
|
- replica_gigabytes: quota_replica_gigabytes
|
||||||
- per_share_gigabytes: quota_per_share_gigabytes
|
- per_share_gigabytes: quota_per_share_gigabytes
|
||||||
|
- backups: quota_backups
|
||||||
|
- backup_gigabytes: quota_backup_gigabytes
|
||||||
|
|
||||||
Response example
|
Response example
|
||||||
----------------
|
----------------
|
||||||
@ -203,6 +212,8 @@ Response parameters
|
|||||||
- share_replicas: quota_share_replicas_detail
|
- share_replicas: quota_share_replicas_detail
|
||||||
- replica_gigabytes: quota_replica_gigabytes_detail
|
- replica_gigabytes: quota_replica_gigabytes_detail
|
||||||
- per_share_gigabytes: quota_per_share_gigabytes_detail
|
- per_share_gigabytes: quota_per_share_gigabytes_detail
|
||||||
|
- backups: quota_backups_detail
|
||||||
|
- backup_gigabytes: quota_backup_gigabytes_detail
|
||||||
|
|
||||||
Response example
|
Response example
|
||||||
----------------
|
----------------
|
||||||
@ -256,6 +267,8 @@ Request
|
|||||||
- share_replicas: quota_share_replicas_request
|
- share_replicas: quota_share_replicas_request
|
||||||
- replica_gigabytes: quota_replica_gigabytes_request
|
- replica_gigabytes: quota_replica_gigabytes_request
|
||||||
- per_share_gigabytes: quota_per_share_gigabytes_request
|
- per_share_gigabytes: quota_per_share_gigabytes_request
|
||||||
|
- backups: quota_backups_request
|
||||||
|
- backup_gigabytes: quota_backup_gigabytes_request
|
||||||
|
|
||||||
Request example
|
Request example
|
||||||
---------------
|
---------------
|
||||||
@ -280,6 +293,8 @@ Response parameters
|
|||||||
- share_replicas: quota_share_replicas
|
- share_replicas: quota_share_replicas
|
||||||
- replica_gigabytes: quota_replica_gigabytes
|
- replica_gigabytes: quota_replica_gigabytes
|
||||||
- per_share_gigabytes: quota_per_share_gigabytes
|
- per_share_gigabytes: quota_per_share_gigabytes
|
||||||
|
- backups: quota_backups
|
||||||
|
- backup_gigabytes: quota_backup_gigabytes
|
||||||
|
|
||||||
Response example
|
Response example
|
||||||
----------------
|
----------------
|
||||||
|
@ -15,7 +15,11 @@
|
|||||||
"maxTotalShareReplicas": 100,
|
"maxTotalShareReplicas": 100,
|
||||||
"maxTotalReplicaGigabytes": 1000,
|
"maxTotalReplicaGigabytes": 1000,
|
||||||
"totalShareReplicasUsed": 0,
|
"totalShareReplicasUsed": 0,
|
||||||
"totalReplicaGigabytesUsed": 0
|
"totalReplicaGigabytesUsed": 0,
|
||||||
|
"maxTotalShareBackups": 100,
|
||||||
|
"maxTotalBackupGigabytes": 1000,
|
||||||
|
"totalShareBackupsUsed": 0,
|
||||||
|
"totalBackupGigabytesUsed": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
"share_networks": 10,
|
"share_networks": 10,
|
||||||
"share_replicas": 100,
|
"share_replicas": 100,
|
||||||
"replica_gigabytes": 1000,
|
"replica_gigabytes": 1000,
|
||||||
"per_share_gigabytes": -1
|
"per_share_gigabytes": -1,
|
||||||
|
"backups": 50,
|
||||||
|
"backup_gigabytes": 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
"share_networks": 10,
|
"share_networks": 10,
|
||||||
"share_replicas": 100,
|
"share_replicas": 100,
|
||||||
"replica_gigabytes": 1000,
|
"replica_gigabytes": 1000,
|
||||||
"per_share_gigabytes": -1
|
"per_share_gigabytes": -1,
|
||||||
|
"backups": 50,
|
||||||
|
"backup_gigabytes": 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,12 @@
|
|||||||
"reserved": 0},
|
"reserved": 0},
|
||||||
"per_share_gigabytes": {"in_use": 0,
|
"per_share_gigabytes": {"in_use": 0,
|
||||||
"limit": -1,
|
"limit": -1,
|
||||||
"reserved": 0}
|
"reserved": 0},
|
||||||
|
"backup_gigabytes": {"in_use": 0,
|
||||||
|
"limit": 1000,
|
||||||
|
"reserved": 0},
|
||||||
|
"backups": {"in_use": 0,
|
||||||
|
"limit": 50,
|
||||||
|
"reserved": 0}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
"share_group_snapshots": 10,
|
"share_group_snapshots": 10,
|
||||||
"share_replicas": 100,
|
"share_replicas": 100,
|
||||||
"replica_gigabytes": 1000,
|
"replica_gigabytes": 1000,
|
||||||
"per_share_gigabytes": -1
|
"per_share_gigabytes": -1,
|
||||||
|
"backups": 50,
|
||||||
|
"backup_gigabytes": 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
"share_group_snapshots": 12,
|
"share_group_snapshots": 12,
|
||||||
"share_replicas": 89,
|
"share_replicas": 89,
|
||||||
"replica_gigabytes": 1000,
|
"replica_gigabytes": 1000,
|
||||||
"per_share_gigabytes": -1
|
"per_share_gigabytes": -1,
|
||||||
|
"backups": 40,
|
||||||
|
"backup_gigabytes": 500
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
api-ref/source/samples/share-backup-create-request.json
Normal file
8
api-ref/source/samples/share-backup-create-request.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"share_backup": {
|
||||||
|
"share_id": "7b11dd53-546e-43cd-af0e-875434238c30",
|
||||||
|
"backup_options": {},
|
||||||
|
"description": null,
|
||||||
|
"name": "backup1"
|
||||||
|
}
|
||||||
|
}
|
15
api-ref/source/samples/share-backup-create-response.json
Normal file
15
api-ref/source/samples/share-backup-create-response.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"share_backup": {
|
||||||
|
"id": "c1cdc0ce-4ddc-4018-9796-505d2e26fcc7",
|
||||||
|
"share_id": "7b11dd53-546e-43cd-af0e-875434238c30",
|
||||||
|
"status": "creating",
|
||||||
|
"name": "backup1",
|
||||||
|
"description": null,
|
||||||
|
"size": 1,
|
||||||
|
"created_at": "2023-08-16T13:03:59.020692",
|
||||||
|
"updated_at": "2023-08-16T13:03:59.020692",
|
||||||
|
"availability_zone": null,
|
||||||
|
"progress": "0",
|
||||||
|
"restore_progress": "0"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"reset_status": {
|
||||||
|
"status": "error"
|
||||||
|
}
|
||||||
|
}
|
3
api-ref/source/samples/share-backup-restore-request.json
Normal file
3
api-ref/source/samples/share-backup-restore-request.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"restore": null
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"restore": {
|
||||||
|
"backup_id": "c1cdc0ce-4ddc-4018-9796-505d2e26fcc7",
|
||||||
|
"share_id": "7b11dd53-546e-43cd-af0e-875434238c30"
|
||||||
|
}
|
||||||
|
}
|
15
api-ref/source/samples/share-backup-show-response.json
Normal file
15
api-ref/source/samples/share-backup-show-response.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"share_backup": {
|
||||||
|
"id": "c1cdc0ce-4ddc-4018-9796-505d2e26fcc7",
|
||||||
|
"share_id": "7b11dd53-546e-43cd-af0e-875434238c30",
|
||||||
|
"status": "available",
|
||||||
|
"name": "backup1",
|
||||||
|
"description": null,
|
||||||
|
"size": 1,
|
||||||
|
"created_at": "2023-08-16T13:03:59.000000",
|
||||||
|
"updated_at": "2023-08-16T13:04:15.000000",
|
||||||
|
"availability_zone": null,
|
||||||
|
"progress": "100",
|
||||||
|
"restore_progress": "0"
|
||||||
|
}
|
||||||
|
}
|
6
api-ref/source/samples/share-backup-update-request.json
Normal file
6
api-ref/source/samples/share-backup-update-request.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"share_backup": {
|
||||||
|
"display_name": "backup2",
|
||||||
|
"display_description": "I am changing a description also. Here is a backup"
|
||||||
|
}
|
||||||
|
}
|
15
api-ref/source/samples/share-backup-update-response.json
Normal file
15
api-ref/source/samples/share-backup-update-response.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"share_backup": {
|
||||||
|
"id": "fa32a89f-ed0f-4906-b1d7-92eedf98fbb5",
|
||||||
|
"share_id": "7b11dd53-546e-43cd-af0e-875434238c30",
|
||||||
|
"status": "available",
|
||||||
|
"name": "backup2",
|
||||||
|
"description": "I am changing a description also. Here is a backup",
|
||||||
|
"size": 1,
|
||||||
|
"created_at": "2023-08-16T13:18:55.000000",
|
||||||
|
"updated_at": "2023-08-16T13:33:15.000000",
|
||||||
|
"availability_zone": null,
|
||||||
|
"progress": "100",
|
||||||
|
"restore_progress": "0"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"share_backups": [
|
||||||
|
{
|
||||||
|
"id": "1125c47a-0216-4ee0-a517-0460d63301a6",
|
||||||
|
"share_id": "112dffd-f033-4248-a315-319ca2bd70c8",
|
||||||
|
"status": "available",
|
||||||
|
"name": "backup3",
|
||||||
|
"description": null,
|
||||||
|
"size": 1,
|
||||||
|
"created_at": "2023-08-16T12:34:57.000000",
|
||||||
|
"updated_at": "2023-08-17T12:14:15.000000",
|
||||||
|
"availability_zone": null,
|
||||||
|
"progress": "100",
|
||||||
|
"restore_progress": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c1cdc0ce-4ddc-4018-9796-505d2e26fcc7",
|
||||||
|
"share_id": "7b11dd53-546e-43cd-af0e-875434238c30",
|
||||||
|
"status": "creating",
|
||||||
|
"name": "backup1",
|
||||||
|
"description": null,
|
||||||
|
"size": 1,
|
||||||
|
"created_at": "2023-08-16T13:03:59.020692",
|
||||||
|
"updated_at": "2023-08-16T13:13:15.000002",
|
||||||
|
"availability_zone": null,
|
||||||
|
"progress": "0",
|
||||||
|
"restore_progress": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
api-ref/source/samples/share-backups-list-response.json
Normal file
16
api-ref/source/samples/share-backups-list-response.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"share_backups": [
|
||||||
|
{
|
||||||
|
"id": "1125c47a-0216-4ee0-a517-0460d63301a6",
|
||||||
|
"name": "backup3",
|
||||||
|
"share_id": "112dffd-f033-4248-a315-319ca2bd70c8",
|
||||||
|
"status": "available"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c1cdc0ce-4ddc-4018-9796-505d2e26fcc7",
|
||||||
|
"name": "backup1",
|
||||||
|
"share_id": "7b11dd53-546e-43cd-af0e-875434238c30",
|
||||||
|
"status": "creating"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -17,6 +17,7 @@
|
|||||||
"share_server_id": "87d8943a-f5da-47a4-b2f2-ddfa6794aa82",
|
"share_server_id": "87d8943a-f5da-47a4-b2f2-ddfa6794aa82",
|
||||||
"share_group_id": null,
|
"share_group_id": null,
|
||||||
"snapshot_id": null,
|
"snapshot_id": null,
|
||||||
|
"source_backup_id": null,
|
||||||
"id": "f45cc5b2-d1bb-4a3e-ba5b-5c4125613adc",
|
"id": "f45cc5b2-d1bb-4a3e-ba5b-5c4125613adc",
|
||||||
"size": 1,
|
"size": 1,
|
||||||
"share_type": "25747776-08e5-494f-ab40-a64b9d20d8f7",
|
"share_type": "25747776-08e5-494f-ab40-a64b9d20d8f7",
|
||||||
@ -58,6 +59,7 @@
|
|||||||
],
|
],
|
||||||
"share_server_id": "87d8943a-f5da-47a4-b2f2-ddfa6794aa82",
|
"share_server_id": "87d8943a-f5da-47a4-b2f2-ddfa6794aa82",
|
||||||
"snapshot_id": null,
|
"snapshot_id": null,
|
||||||
|
"source_backup_id": null,
|
||||||
"id": "c4a2ced4-2c9f-4ae1-adaa-6171833e64df",
|
"id": "c4a2ced4-2c9f-4ae1-adaa-6171833e64df",
|
||||||
"size": 1,
|
"size": 1,
|
||||||
"share_type": "25747776-08e5-494f-ab40-a64b9d20d8f7",
|
"share_type": "25747776-08e5-494f-ab40-a64b9d20d8f7",
|
||||||
|
477
api-ref/source/share-backups.inc
Normal file
477
api-ref/source/share-backups.inc
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
.. -*- rst -*-
|
||||||
|
|
||||||
|
Share backups (since API v2.80)
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Use the Shared File Systems service to make backups of shares. A share
|
||||||
|
backup is a point-in-time, read-only copy of the data that is
|
||||||
|
contained in a share. The APIs below allow controlling share backups. They
|
||||||
|
are represented by a "backup" resource in the Shared File Systems service,
|
||||||
|
and they can have user-defined metadata such as a name and description.
|
||||||
|
|
||||||
|
You can create, restore, update, list and delete share backups. After you
|
||||||
|
create a share backup, you can access backup and use it. You can also restore
|
||||||
|
a backup into a share as long as certain criteria are met e.g. size.
|
||||||
|
|
||||||
|
You can update a share backup to change its name or description. As
|
||||||
|
administrator, you can also reset the state of a backup. Backup can be in
|
||||||
|
one of the following states:
|
||||||
|
|
||||||
|
- ``available``
|
||||||
|
|
||||||
|
- ``error``
|
||||||
|
|
||||||
|
- ``creating``
|
||||||
|
|
||||||
|
- ``deleting``
|
||||||
|
|
||||||
|
- ``restoring``
|
||||||
|
|
||||||
|
|
||||||
|
During a backup or restore operation, share can be in one of the following
|
||||||
|
states:
|
||||||
|
|
||||||
|
- ``available``
|
||||||
|
|
||||||
|
- ``backup_creating``
|
||||||
|
|
||||||
|
- ``backup_restoring``
|
||||||
|
|
||||||
|
- ``backup_restoring_error``
|
||||||
|
|
||||||
|
|
||||||
|
List share backups
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. rest_method:: GET /v2/share-backups
|
||||||
|
|
||||||
|
.. versionadded:: 2.80
|
||||||
|
|
||||||
|
Lists all share backups.
|
||||||
|
|
||||||
|
Response codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 200
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 401
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- share_id: backup_share_id_query
|
||||||
|
- name~: name_inexact_query_versionless
|
||||||
|
- description~: description_inexact_query_versionless
|
||||||
|
- limit: limit
|
||||||
|
- offset: offset
|
||||||
|
- sort_key: sort_key_backup
|
||||||
|
- sort_dir: sort_dir
|
||||||
|
- status: backup_status_query
|
||||||
|
- host: backup_host_query
|
||||||
|
- topic: backup_topic_query
|
||||||
|
|
||||||
|
Response parameters
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- id: backup_id_response
|
||||||
|
- share_id: backup_share_id
|
||||||
|
- status: backup_status
|
||||||
|
|
||||||
|
Response example
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backups-list-response.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
|
||||||
|
List share backups with details
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. rest_method:: GET /v2/share-backups/detail
|
||||||
|
|
||||||
|
.. versionadded:: 2.80
|
||||||
|
|
||||||
|
Lists all share backups with details.
|
||||||
|
|
||||||
|
Response codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 200
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 401
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- share_id: backup_share_id_query
|
||||||
|
- name~: name_inexact_query_versionless
|
||||||
|
- description~: description_inexact_query_versionless
|
||||||
|
- limit: limit
|
||||||
|
- offset: offset
|
||||||
|
- sort_key: sort_key_backup
|
||||||
|
- sort_dir: sort_dir
|
||||||
|
- status: backup_status_query
|
||||||
|
- host: backup_host_query
|
||||||
|
- topic: backup_topic_query
|
||||||
|
|
||||||
|
Response parameters
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- id: backup_id_response
|
||||||
|
- share_id: backup_share_id
|
||||||
|
- status: backup_status
|
||||||
|
- size: backup_size
|
||||||
|
- availability_zone: backup_az
|
||||||
|
- name: name
|
||||||
|
- description: description
|
||||||
|
- created_at: created_at
|
||||||
|
- updated_at: updated_at
|
||||||
|
- progress: backup_progress
|
||||||
|
- restore_progress: backup_restore_progress
|
||||||
|
|
||||||
|
Response example
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backups-list-detailed-response.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
|
||||||
|
Show share backup details
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. rest_method:: GET /v2/share-backups/{backup_id}
|
||||||
|
|
||||||
|
.. versionadded:: 2.80
|
||||||
|
|
||||||
|
Shows details for a share backup.
|
||||||
|
|
||||||
|
Response codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 200
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 401
|
||||||
|
- 404
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- backup_id: backup_id_request_path
|
||||||
|
|
||||||
|
Response parameters
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- id: backup_id_response
|
||||||
|
- share_id: backup_share_id
|
||||||
|
- status: backup_status
|
||||||
|
- size: backup_size
|
||||||
|
- availability_zone: backup_az
|
||||||
|
- name: name
|
||||||
|
- description: description
|
||||||
|
- created_at: created_at
|
||||||
|
- updated_at: updated_at
|
||||||
|
- progress: backup_progress
|
||||||
|
- restore_progress: backup_restore_progress
|
||||||
|
|
||||||
|
Response example
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backup-show-response.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
|
||||||
|
Create share backup
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. rest_method:: POST /v2/share-backups
|
||||||
|
|
||||||
|
.. versionadded:: 2.80
|
||||||
|
|
||||||
|
Creates a backup from a share.
|
||||||
|
|
||||||
|
|
||||||
|
Response codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 202
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 401
|
||||||
|
- 403
|
||||||
|
- 404
|
||||||
|
- 409
|
||||||
|
- 422
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- share_id: backup_share_id
|
||||||
|
- name: name_request
|
||||||
|
- description: description_request
|
||||||
|
- backup_options: backup_options_request
|
||||||
|
|
||||||
|
Request example
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backup-create-request.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
Response parameters
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- id: backup_id_response
|
||||||
|
- share_id: backup_share_id
|
||||||
|
- status: backup_status
|
||||||
|
- size: backup_size
|
||||||
|
- availability_zone: backup_az
|
||||||
|
- name: name
|
||||||
|
- description: description
|
||||||
|
- created_at: created_at
|
||||||
|
- updated_at: updated_at
|
||||||
|
- progress: backup_progress
|
||||||
|
- restore_progress: backup_restore_progress
|
||||||
|
|
||||||
|
Response example
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backup-create-response.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
|
||||||
|
Update share backup
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. rest_method:: PUT /v2/share-backups/{backup_id}
|
||||||
|
|
||||||
|
.. versionadded:: 2.80
|
||||||
|
|
||||||
|
Updates a share backup.
|
||||||
|
|
||||||
|
You can update these attributes:
|
||||||
|
|
||||||
|
- ``display_name``, which changes the ``name`` of the share backup.
|
||||||
|
|
||||||
|
- ``display_description``, which changes the ``description`` of
|
||||||
|
the share backup.
|
||||||
|
|
||||||
|
If you try to update other attributes, they retain their previous
|
||||||
|
values.
|
||||||
|
|
||||||
|
Response codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 200
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 401
|
||||||
|
- 403
|
||||||
|
- 404
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- backup_id: backup_id_request_path
|
||||||
|
- display_name: display_name_request
|
||||||
|
- display_description: display_description_request
|
||||||
|
|
||||||
|
Request example
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backup-update-request.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
Response parameters
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- id: backup_id_response
|
||||||
|
- share_id: backup_share_id
|
||||||
|
- status: backup_status
|
||||||
|
- size: backup_size
|
||||||
|
- availability_zone: backup_az
|
||||||
|
- name: name
|
||||||
|
- description: description
|
||||||
|
- created_at: created_at
|
||||||
|
- updated_at: updated_at
|
||||||
|
- progress: backup_progress
|
||||||
|
- restore_progress: backup_restore_progress
|
||||||
|
|
||||||
|
Response example
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backup-update-response.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
|
||||||
|
Delete share backup
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. rest_method:: DELETE /v2/share-backups/{backup_id}
|
||||||
|
|
||||||
|
.. versionadded:: 2.80
|
||||||
|
|
||||||
|
Deletes a share backup.
|
||||||
|
|
||||||
|
Preconditions
|
||||||
|
|
||||||
|
- Share backup status must be ``available`` or ``error``.
|
||||||
|
|
||||||
|
Response codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 202
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 401
|
||||||
|
- 403
|
||||||
|
- 404
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- backup_id: backup_id_request_path
|
||||||
|
|
||||||
|
|
||||||
|
Restore a share backup
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. rest_method:: POST /v2/share-backups/{backup_id}/action
|
||||||
|
|
||||||
|
.. versionadded:: 2.80
|
||||||
|
|
||||||
|
Restores a share backup into original share.
|
||||||
|
|
||||||
|
Preconditions
|
||||||
|
|
||||||
|
- Share backup status must be ``available``.
|
||||||
|
|
||||||
|
Response codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 202
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 401
|
||||||
|
- 403
|
||||||
|
- 404
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- backup_id: backup_id_request_path
|
||||||
|
|
||||||
|
Request example
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backup-restore-request.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
Response parameters
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- backup_id: backup_id_response
|
||||||
|
- share_id: backup_share_id
|
||||||
|
|
||||||
|
Response example
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backup-restore-response.json
|
||||||
|
:language: javascript
|
||||||
|
|
||||||
|
|
||||||
|
Reset share backup status
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. rest_method:: POST /v2/share-backups/{backup_id}/action
|
||||||
|
|
||||||
|
.. versionadded:: 2.80
|
||||||
|
|
||||||
|
Administrator only. Explicitly updates the state of a share backup.
|
||||||
|
|
||||||
|
Use the ``policy.yaml`` file to grant permissions for this action
|
||||||
|
to other roles.
|
||||||
|
|
||||||
|
Response codes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. rest_status_code:: success status.yaml
|
||||||
|
|
||||||
|
- 202
|
||||||
|
|
||||||
|
.. rest_status_code:: error status.yaml
|
||||||
|
|
||||||
|
- 400
|
||||||
|
- 401
|
||||||
|
- 403
|
||||||
|
- 404
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
|
- project_id: project_id_path
|
||||||
|
- backup_id: backup_id_request_path
|
||||||
|
- status: backup_status_request
|
||||||
|
|
||||||
|
Request example
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. literalinclude:: samples/share-backup-reset-status-request.json
|
||||||
|
:language: javascript
|
@ -36,6 +36,12 @@ A share has one of these status values:
|
|||||||
+----------------------------------------+--------------------------------------------------------+
|
+----------------------------------------+--------------------------------------------------------+
|
||||||
| Status | Description |
|
| Status | Description |
|
||||||
+----------------------------------------+--------------------------------------------------------+
|
+----------------------------------------+--------------------------------------------------------+
|
||||||
|
| ``backup_creating`` | The share is being backed up. |
|
||||||
|
+----------------------------------------+--------------------------------------------------------+
|
||||||
|
| ``backup_restoring`` | The share is being restored from backup. |
|
||||||
|
+----------------------------------------+--------------------------------------------------------+
|
||||||
|
| ``backup_restoring_error`` | An error occurred during share backup restore. |
|
||||||
|
+----------------------------------------+--------------------------------------------------------+
|
||||||
| ``creating`` | The share is being created. |
|
| ``creating`` | The share is being created. |
|
||||||
+----------------------------------------+--------------------------------------------------------+
|
+----------------------------------------+--------------------------------------------------------+
|
||||||
| ``creating_from_snapshot`` | The share is being created from a parent snapshot. |
|
| ``creating_from_snapshot`` | The share is being created from a parent snapshot. |
|
||||||
@ -122,6 +128,7 @@ Request
|
|||||||
- extra_specs: extra_specs_query
|
- extra_specs: extra_specs_query
|
||||||
- share_type_id: share_type_id_query
|
- share_type_id: share_type_id_query
|
||||||
- snapshot_id: snapshot_id_query
|
- snapshot_id: snapshot_id_query
|
||||||
|
- source_backup_id: source_backup_id_query
|
||||||
- host: host_query
|
- host: host_query
|
||||||
- share_network_id: share_network_id_query
|
- share_network_id: share_network_id_query
|
||||||
- project_id: project_id_query
|
- project_id: project_id_query
|
||||||
@ -191,6 +198,7 @@ Request
|
|||||||
- share_type_id: share_type_id_query
|
- share_type_id: share_type_id_query
|
||||||
- name: name_query
|
- name: name_query
|
||||||
- snapshot_id: snapshot_id_query
|
- snapshot_id: snapshot_id_query
|
||||||
|
- source_backup_id: source_backup_id_query
|
||||||
- host: host_query
|
- host: host_query
|
||||||
- share_network_id: share_network_id_query
|
- share_network_id: share_network_id_query
|
||||||
- project_id: project_id_query
|
- project_id: project_id_query
|
||||||
@ -221,6 +229,7 @@ Response parameters
|
|||||||
- description: description
|
- description: description
|
||||||
- project_id: project_id
|
- project_id: project_id
|
||||||
- snapshot_id: snapshot_id_shares_response
|
- snapshot_id: snapshot_id_shares_response
|
||||||
|
- source_backup_id: source_backup_id_shares_response
|
||||||
- share_network_id: share_network_id
|
- share_network_id: share_network_id
|
||||||
- share_proto: share_proto
|
- share_proto: share_proto
|
||||||
- metadata: metadata
|
- metadata: metadata
|
||||||
|
@ -234,6 +234,14 @@ function configure_manila {
|
|||||||
iniset $MANILA_CONF DEFAULT server_migration_driver_continue_update_interval $MANILA_SERVER_MIGRATION_PERIOD_TASK_INTERVAL
|
iniset $MANILA_CONF DEFAULT server_migration_driver_continue_update_interval $MANILA_SERVER_MIGRATION_PERIOD_TASK_INTERVAL
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! [[ -z $MANILA_CREATE_BACKUP_CONTINUE_TASK_INTERVAL ]]; then
|
||||||
|
iniset $MANILA_CONF DEFAULT driver_backup_continue_update_interval $MANILA_CREATE_BACKUP_CONTINUE_TASK_INTERVAL
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ -z $MANILA_RESTORE_BACKUP_CONTINUE_TASK_INTERVAL ]]; then
|
||||||
|
iniset $MANILA_CONF DEFAULT driver_restore_continue_update_interval $MANILA_RESTORE_BACKUP_CONTINUE_TASK_INTERVAL
|
||||||
|
fi
|
||||||
|
|
||||||
if ! [[ -z $MANILA_DATA_COPY_CHECK_HASH ]]; then
|
if ! [[ -z $MANILA_DATA_COPY_CHECK_HASH ]]; then
|
||||||
iniset $MANILA_CONF DEFAULT check_hash $MANILA_DATA_COPY_CHECK_HASH
|
iniset $MANILA_CONF DEFAULT check_hash $MANILA_DATA_COPY_CHECK_HASH
|
||||||
fi
|
fi
|
||||||
|
@ -64,6 +64,13 @@ class ShareUnmanageMixin(object):
|
|||||||
"'%(amount)s' dependent snapshot(s).") % {
|
"'%(amount)s' dependent snapshot(s).") % {
|
||||||
's_id': id, 'amount': len(snapshots)}
|
's_id': id, 'amount': len(snapshots)}
|
||||||
raise exc.HTTPForbidden(explanation=msg)
|
raise exc.HTTPForbidden(explanation=msg)
|
||||||
|
filters = {'share_id': id}
|
||||||
|
backups = self.share_api.db.share_backups_get_all(context, filters)
|
||||||
|
if backups:
|
||||||
|
msg = _("Share '%(s_id)s' can not be unmanaged because it has "
|
||||||
|
"'%(amount)s' dependent backup(s).") % {
|
||||||
|
's_id': id, 'amount': len(backups)}
|
||||||
|
raise exc.HTTPForbidden(explanation=msg)
|
||||||
self.share_api.unmanage(context, share)
|
self.share_api.unmanage(context, share)
|
||||||
except exception.NotFound as e:
|
except exception.NotFound as e:
|
||||||
raise exc.HTTPNotFound(explanation=e.msg)
|
raise exc.HTTPNotFound(explanation=e.msg)
|
||||||
|
@ -21,6 +21,7 @@ from manila.api.views import share_backups as backup_view
|
|||||||
from manila import db
|
from manila import db
|
||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.i18n import _
|
from manila.i18n import _
|
||||||
|
from manila import policy
|
||||||
from manila import share
|
from manila import share
|
||||||
|
|
||||||
|
|
||||||
@ -72,6 +73,31 @@ class ShareBackupController(wsgi.Controller, wsgi.AdminActionsMixin):
|
|||||||
if sort_key == key:
|
if sort_key == key:
|
||||||
sort_key = key_dict[key]
|
sort_key = key_dict[key]
|
||||||
|
|
||||||
|
if 'name' in search_opts:
|
||||||
|
search_opts['display_name'] = search_opts.pop('name')
|
||||||
|
if 'description' in search_opts:
|
||||||
|
search_opts['display_description'] = search_opts.pop(
|
||||||
|
'description')
|
||||||
|
|
||||||
|
# like filter
|
||||||
|
for key, db_key in (('name~', 'display_name~'),
|
||||||
|
('description~', 'display_description~')):
|
||||||
|
if key in search_opts:
|
||||||
|
search_opts[db_key] = search_opts.pop(key)
|
||||||
|
|
||||||
|
common.remove_invalid_options(context, search_opts,
|
||||||
|
self._get_backups_search_options())
|
||||||
|
|
||||||
|
# Read and remove key 'all_tenants' if was provided
|
||||||
|
search_opts['project_id'] = context.project_id
|
||||||
|
all_tenants = search_opts.pop('all_tenants',
|
||||||
|
search_opts.pop('all_projects', None))
|
||||||
|
if all_tenants:
|
||||||
|
allowed_to_list_all_tenants = policy.check_policy(
|
||||||
|
context, 'share_backup', 'get_all_project', do_raise=False)
|
||||||
|
if allowed_to_list_all_tenants:
|
||||||
|
search_opts.pop('project_id')
|
||||||
|
|
||||||
share_id = req.params.get('share_id')
|
share_id = req.params.get('share_id')
|
||||||
if share_id:
|
if share_id:
|
||||||
try:
|
try:
|
||||||
@ -94,6 +120,11 @@ class ShareBackupController(wsgi.Controller, wsgi.AdminActionsMixin):
|
|||||||
|
|
||||||
return backups
|
return backups
|
||||||
|
|
||||||
|
def _get_backups_search_options(self):
|
||||||
|
"""Return share backup search options allowed by non-admin."""
|
||||||
|
return ('display_name', 'status', 'share_id', 'topic', 'display_name~',
|
||||||
|
'display_description~', 'display_description')
|
||||||
|
|
||||||
@wsgi.Controller.api_version(MIN_SUPPORTED_API_VERSION, experimental=True)
|
@wsgi.Controller.api_version(MIN_SUPPORTED_API_VERSION, experimental=True)
|
||||||
@wsgi.Controller.authorize('get')
|
@wsgi.Controller.authorize('get')
|
||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
@ -190,7 +221,7 @@ class ShareBackupController(wsgi.Controller, wsgi.AdminActionsMixin):
|
|||||||
|
|
||||||
@wsgi.Controller.api_version(MIN_SUPPORTED_API_VERSION, experimental=True)
|
@wsgi.Controller.api_version(MIN_SUPPORTED_API_VERSION, experimental=True)
|
||||||
@wsgi.Controller.authorize
|
@wsgi.Controller.authorize
|
||||||
@wsgi.response(202)
|
@wsgi.response(200)
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
"""Update a backup."""
|
"""Update a backup."""
|
||||||
context = req.environ['manila.context']
|
context = req.environ['manila.context']
|
||||||
@ -217,6 +248,11 @@ class ShareBackupController(wsgi.Controller, wsgi.AdminActionsMixin):
|
|||||||
update_dict)
|
update_dict)
|
||||||
return self._view_builder.detail(req, backup)
|
return self._view_builder.detail(req, backup)
|
||||||
|
|
||||||
|
@wsgi.Controller.api_version(MIN_SUPPORTED_API_VERSION, experimental=True)
|
||||||
|
@wsgi.action('reset_status')
|
||||||
|
def backup_reset_status(self, req, id, body):
|
||||||
|
return self._reset_status(req, id, body)
|
||||||
|
|
||||||
|
|
||||||
def create_resource():
|
def create_resource():
|
||||||
return wsgi.Resource(ShareBackupController())
|
return wsgi.Resource(ShareBackupController())
|
||||||
|
@ -36,8 +36,9 @@ class BackupViewBuilder(common.ViewBuilder):
|
|||||||
|
|
||||||
backup_dict = {
|
backup_dict = {
|
||||||
'id': backup.get('id'),
|
'id': backup.get('id'),
|
||||||
|
'name': backup.get('display_name'),
|
||||||
'share_id': backup.get('share_id'),
|
'share_id': backup.get('share_id'),
|
||||||
'backup_state': backup.get('status'),
|
'status': backup.get('status'),
|
||||||
}
|
}
|
||||||
return {'share_backup': backup_dict}
|
return {'share_backup': backup_dict}
|
||||||
|
|
||||||
@ -55,14 +56,16 @@ class BackupViewBuilder(common.ViewBuilder):
|
|||||||
context = request.environ['manila.context']
|
context = request.environ['manila.context']
|
||||||
backup_dict = {
|
backup_dict = {
|
||||||
'id': backup.get('id'),
|
'id': backup.get('id'),
|
||||||
'size': backup.get('size'),
|
'name': backup.get('display_name'),
|
||||||
'share_id': backup.get('share_id'),
|
'share_id': backup.get('share_id'),
|
||||||
'availability_zone': backup.get('availability_zone'),
|
'status': backup.get('status'),
|
||||||
|
'description': backup.get('display_description'),
|
||||||
|
'size': backup.get('size'),
|
||||||
'created_at': backup.get('created_at'),
|
'created_at': backup.get('created_at'),
|
||||||
'updated_at': backup.get('updated_at'),
|
'updated_at': backup.get('updated_at'),
|
||||||
'backup_state': backup.get('status'),
|
'availability_zone': backup.get('availability_zone'),
|
||||||
'name': backup.get('display_name'),
|
'progress': backup.get('progress'),
|
||||||
'description': backup.get('display_description'),
|
'restore_progress': backup.get('restore_progress'),
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy.check_is_host_admin(context):
|
if policy.check_is_host_admin(context):
|
||||||
|
@ -38,6 +38,7 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
"add_progress_field",
|
"add_progress_field",
|
||||||
"translate_creating_from_snapshot_status",
|
"translate_creating_from_snapshot_status",
|
||||||
"add_share_recycle_bin_field",
|
"add_share_recycle_bin_field",
|
||||||
|
"add_source_backup_id_field",
|
||||||
]
|
]
|
||||||
|
|
||||||
def summary_list(self, request, shares, count=None):
|
def summary_list(self, request, shares, count=None):
|
||||||
@ -205,3 +206,7 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
share_dict['is_soft_deleted'] = share.get('is_soft_deleted')
|
share_dict['is_soft_deleted'] = share.get('is_soft_deleted')
|
||||||
share_dict['scheduled_to_be_deleted_at'] = share.get(
|
share_dict['scheduled_to_be_deleted_at'] = share.get(
|
||||||
'scheduled_to_be_deleted_at')
|
'scheduled_to_be_deleted_at')
|
||||||
|
|
||||||
|
@common.ViewBuilder.versioned_method("2.80")
|
||||||
|
def add_source_backup_id_field(self, context, share_dict, share):
|
||||||
|
share_dict['source_backup_id'] = share.get('source_backup_id')
|
||||||
|
@ -394,6 +394,8 @@ class DataManager(manager.Manager):
|
|||||||
share = self.db.share_get(context, share_id)
|
share = self.db.share_get(context, share_id)
|
||||||
backup = self.db.share_backup_get(context, backup_id)
|
backup = self.db.share_backup_get(context, backup_id)
|
||||||
|
|
||||||
|
self.db.share_backup_update(context, backup_id, {'host': self.host})
|
||||||
|
|
||||||
LOG.info('Create backup started, backup: %(backup_id)s '
|
LOG.info('Create backup started, backup: %(backup_id)s '
|
||||||
'share: %(share_id)s.',
|
'share: %(share_id)s.',
|
||||||
{'backup_id': backup_id, 'share_id': share_id})
|
{'backup_id': backup_id, 'share_id': share_id})
|
||||||
@ -410,13 +412,21 @@ class DataManager(manager.Manager):
|
|||||||
self.db.share_backup_update(
|
self.db.share_backup_update(
|
||||||
context, backup_id,
|
context, backup_id,
|
||||||
{'status': constants.STATUS_ERROR, 'fail_reason': err})
|
{'status': constants.STATUS_ERROR, 'fail_reason': err})
|
||||||
|
self.db.share_update(
|
||||||
|
context, share_id, {'status': constants.STATUS_AVAILABLE})
|
||||||
|
self.db.share_backup_update(
|
||||||
|
context, backup_id,
|
||||||
|
{'status': constants.STATUS_AVAILABLE, 'progress': '100'})
|
||||||
|
LOG.info("Created share backup %s successfully.", backup_id)
|
||||||
|
|
||||||
@periodic_task.periodic_task(
|
@periodic_task.periodic_task(
|
||||||
spacing=CONF.backup_continue_update_interval)
|
spacing=CONF.backup_continue_update_interval)
|
||||||
def create_backup_continue(self, context):
|
def create_backup_continue(self, context):
|
||||||
filters = {'status': constants.STATUS_CREATING,
|
filters = {
|
||||||
'host': self.host,
|
'status': constants.STATUS_CREATING,
|
||||||
'topic': CONF.data_topic}
|
'host': self.host,
|
||||||
|
'topic': CONF.data_topic
|
||||||
|
}
|
||||||
backups = self.db.share_backups_get_all(context, filters)
|
backups = self.db.share_backups_get_all(context, filters)
|
||||||
|
|
||||||
for backup in backups:
|
for backup in backups:
|
||||||
@ -426,17 +436,16 @@ class DataManager(manager.Manager):
|
|||||||
try:
|
try:
|
||||||
result = self.data_copy_get_progress(context, share_id)
|
result = self.data_copy_get_progress(context, share_id)
|
||||||
progress = result.get('total_progress', '0')
|
progress = result.get('total_progress', '0')
|
||||||
self.db.share_backup_update(context, backup_id,
|
backup_values = {'progress': progress}
|
||||||
{'progress': progress})
|
|
||||||
if progress == '100':
|
if progress == '100':
|
||||||
self.db.share_update(
|
self.db.share_update(
|
||||||
context, share_id,
|
context, share_id,
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
self.db.share_backup_update(
|
backup_values.update(
|
||||||
context, backup_id,
|
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
LOG.info("Created share backup %s successfully.",
|
LOG.info("Created share backup %s successfully.",
|
||||||
backup_id)
|
backup_id)
|
||||||
|
self.db.share_backup_update(context, backup_id, backup_values)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.warning("Failed to get progress of share %(share)s "
|
LOG.warning("Failed to get progress of share %(share)s "
|
||||||
"backing up in share_backup %(backup).",
|
"backing up in share_backup %(backup).",
|
||||||
@ -624,19 +633,29 @@ class DataManager(manager.Manager):
|
|||||||
{'status': constants.STATUS_BACKUP_RESTORING_ERROR})
|
{'status': constants.STATUS_BACKUP_RESTORING_ERROR})
|
||||||
self.db.share_backup_update(
|
self.db.share_backup_update(
|
||||||
context, backup_id,
|
context, backup_id,
|
||||||
{'status': constants.STATUS_ERROR})
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
|
self.db.share_update(
|
||||||
|
context, share_id, {'status': constants.STATUS_AVAILABLE})
|
||||||
|
self.db.share_backup_update(
|
||||||
|
context, backup_id,
|
||||||
|
{'status': constants.STATUS_AVAILABLE, 'restore_progress': '100'})
|
||||||
|
LOG.info("Share backup %s restored successfully.", backup_id)
|
||||||
|
|
||||||
@periodic_task.periodic_task(
|
@periodic_task.periodic_task(
|
||||||
spacing=CONF.restore_continue_update_interval)
|
spacing=CONF.restore_continue_update_interval)
|
||||||
def restore_backup_continue(self, context):
|
def restore_backup_continue(self, context):
|
||||||
filters = {'status': constants.STATUS_RESTORING,
|
filters = {
|
||||||
'host': self.host,
|
'status': constants.STATUS_RESTORING,
|
||||||
'topic': CONF.data_topic}
|
'host': self.host,
|
||||||
|
'topic': CONF.data_topic
|
||||||
|
}
|
||||||
backups = self.db.share_backups_get_all(context, filters)
|
backups = self.db.share_backups_get_all(context, filters)
|
||||||
for backup in backups:
|
for backup in backups:
|
||||||
backup_id = backup['id']
|
backup_id = backup['id']
|
||||||
try:
|
try:
|
||||||
filters = {'source_backup_id': backup_id}
|
filters = {
|
||||||
|
'source_backup_id': backup_id,
|
||||||
|
}
|
||||||
shares = self.db.share_get_all(context, filters)
|
shares = self.db.share_get_all(context, filters)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.warning('Failed to get shares for backup %s', backup_id)
|
LOG.warning('Failed to get shares for backup %s', backup_id)
|
||||||
@ -651,21 +670,21 @@ class DataManager(manager.Manager):
|
|||||||
try:
|
try:
|
||||||
result = self.data_copy_get_progress(context, share_id)
|
result = self.data_copy_get_progress(context, share_id)
|
||||||
progress = result.get('total_progress', '0')
|
progress = result.get('total_progress', '0')
|
||||||
self.db.share_backup_update(context, backup_id,
|
backup_values = {'restore_progress': progress}
|
||||||
{'restore_progress': progress})
|
|
||||||
if progress == '100':
|
if progress == '100':
|
||||||
self.db.share_update(
|
self.db.share_update(
|
||||||
context, share_id,
|
context, share_id,
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
self.db.share_backup_update(
|
backup_values.update(
|
||||||
context, backup_id,
|
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
LOG.info("Share backup %s restored successfully.",
|
LOG.info("Share backup %s restored successfully.",
|
||||||
backup_id)
|
backup_id)
|
||||||
|
self.db.share_backup_update(context, backup_id,
|
||||||
|
backup_values)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.warning("Failed to get progress of share_backup "
|
LOG.exception("Failed to get progress of share_backup "
|
||||||
"%(backup)s restoring in share %(share).",
|
"%(backup)s restoring in share %(share).",
|
||||||
{'share': share_id, 'backup': backup_id})
|
{'share': share_id, 'backup': backup_id})
|
||||||
self.db.share_update(
|
self.db.share_update(
|
||||||
context, share_id,
|
context, share_id,
|
||||||
{'status': constants.STATUS_BACKUP_RESTORING_ERROR})
|
{'status': constants.STATUS_BACKUP_RESTORING_ERROR})
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
"""backup_change_availability_zone_to_availability_zone_id
|
||||||
|
|
||||||
|
Revision ID: 2d708a9a3ba9
|
||||||
|
Revises: cb20f743ca7b
|
||||||
|
Create Date: 2023-08-24 11:01:41.134456
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '2d708a9a3ba9'
|
||||||
|
down_revision = 'cb20f743ca7b'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
from sqlalchemy import Column, ForeignKey, String
|
||||||
|
|
||||||
|
from manila.db.migrations import utils
|
||||||
|
|
||||||
|
|
||||||
|
def collect_existing_az(az_table, connection):
|
||||||
|
az_name_to_id_mapping = dict()
|
||||||
|
for az in connection.execute(az_table.select()):
|
||||||
|
if az.name in az_name_to_id_mapping:
|
||||||
|
continue
|
||||||
|
|
||||||
|
az_name_to_id_mapping[az.name] = az.id
|
||||||
|
return az_name_to_id_mapping
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
connection = op.get_bind()
|
||||||
|
|
||||||
|
op.add_column(
|
||||||
|
'share_backups',
|
||||||
|
Column('availability_zone_id', String(36),
|
||||||
|
ForeignKey('availability_zones.id', name='sb_az_id_fk'))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Collect existing AZs from availability_zones table
|
||||||
|
availability_zones_table = utils.load_table(
|
||||||
|
'availability_zones', connection)
|
||||||
|
az_name_to_id_mapping = collect_existing_az(
|
||||||
|
availability_zones_table, connection,)
|
||||||
|
|
||||||
|
# Map string AZ names to ID's in target table
|
||||||
|
# pylint: disable=no-value-for-parameter
|
||||||
|
set_az_id_in_table = lambda table, id, name: ( # noqa: E731
|
||||||
|
op.execute(
|
||||||
|
table.update().where(table.c.availability_zone == name).values(
|
||||||
|
{'availability_zone_id': id})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
share_backups_table = utils.load_table('share_backups', connection)
|
||||||
|
for name, id in az_name_to_id_mapping.items():
|
||||||
|
set_az_id_in_table(share_backups_table, id, name)
|
||||||
|
|
||||||
|
# Remove old AZ columns from table
|
||||||
|
op.drop_column('share_backups', 'availability_zone')
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
connection = op.get_bind()
|
||||||
|
|
||||||
|
# Create old AZ fields
|
||||||
|
op.add_column('share_backups',
|
||||||
|
Column('availability_zone', String(length=255)))
|
||||||
|
|
||||||
|
# Migrate data
|
||||||
|
az_table = utils.load_table('availability_zones', connection)
|
||||||
|
share_backups_table = utils.load_table('share_backups', connection)
|
||||||
|
|
||||||
|
for az in connection.execute(az_table.select()):
|
||||||
|
# pylint: disable=no-value-for-parameter
|
||||||
|
op.execute(
|
||||||
|
share_backups_table.update().where(
|
||||||
|
share_backups_table.c.availability_zone_id == az.id
|
||||||
|
).values({'availability_zone': az.name})
|
||||||
|
)
|
||||||
|
|
||||||
|
# Remove AZ_id columns and AZ table
|
||||||
|
op.drop_constraint('sb_az_id_fk', 'share_backups', type_='foreignkey')
|
||||||
|
op.drop_column('share_backups', 'availability_zone_id')
|
@ -7071,6 +7071,7 @@ def _share_backup_create(context, share_id, values):
|
|||||||
if not values.get('id'):
|
if not values.get('id'):
|
||||||
values['id'] = uuidutils.generate_uuid()
|
values['id'] = uuidutils.generate_uuid()
|
||||||
values.update({'share_id': share_id})
|
values.update({'share_id': share_id})
|
||||||
|
_ensure_availability_zone_exists(context, values)
|
||||||
|
|
||||||
share_backup_ref = models.ShareBackup()
|
share_backup_ref = models.ShareBackup()
|
||||||
share_backup_ref.update(values)
|
share_backup_ref.update(values)
|
||||||
@ -7170,6 +7171,7 @@ def _backup_data_get_for_project(context, project_id, user_id):
|
|||||||
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
|
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
|
||||||
@context_manager.writer
|
@context_manager.writer
|
||||||
def share_backup_update(context, backup_id, values):
|
def share_backup_update(context, backup_id, values):
|
||||||
|
_ensure_availability_zone_exists(context, values, strict=False)
|
||||||
backup_ref = share_backup_get(context, backup_id)
|
backup_ref = share_backup_get(context, backup_id)
|
||||||
backup_ref.update(values)
|
backup_ref.update(values)
|
||||||
backup_ref.save(session=context.session)
|
backup_ref.save(session=context.session)
|
||||||
|
@ -1504,6 +1504,11 @@ class ShareBackup(BASE, ManilaBase):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return CONF.share_backup_name_template % self.id
|
return CONF.share_backup_name_template % self.id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def availability_zone(self):
|
||||||
|
if self._availability_zone:
|
||||||
|
return self._availability_zone['name']
|
||||||
|
|
||||||
deleted = Column(String(36), default='False')
|
deleted = Column(String(36), default='False')
|
||||||
user_id = Column(String(255), nullable=False)
|
user_id = Column(String(255), nullable=False)
|
||||||
project_id = Column(String(255), nullable=False)
|
project_id = Column(String(255), nullable=False)
|
||||||
@ -1512,13 +1517,26 @@ class ShareBackup(BASE, ManilaBase):
|
|||||||
size = Column(Integer)
|
size = Column(Integer)
|
||||||
host = Column(String(255))
|
host = Column(String(255))
|
||||||
topic = Column(String(255))
|
topic = Column(String(255))
|
||||||
availability_zone = Column(String(255))
|
|
||||||
display_name = Column(String(255))
|
display_name = Column(String(255))
|
||||||
display_description = Column(String(255))
|
display_description = Column(String(255))
|
||||||
progress = Column(String(32))
|
progress = Column(String(32))
|
||||||
restore_progress = Column(String(32))
|
restore_progress = Column(String(32))
|
||||||
status = Column(String(255))
|
status = Column(String(255))
|
||||||
fail_reason = Column(String(1023))
|
fail_reason = Column(String(1023))
|
||||||
|
availability_zone_id = Column(String(36),
|
||||||
|
ForeignKey('availability_zones.id'),
|
||||||
|
nullable=True)
|
||||||
|
|
||||||
|
_availability_zone = orm.relationship(
|
||||||
|
"AvailabilityZone",
|
||||||
|
lazy='immediate',
|
||||||
|
primaryjoin=(
|
||||||
|
'and_('
|
||||||
|
'ShareBackup.availability_zone_id == '
|
||||||
|
'AvailabilityZone.id, '
|
||||||
|
'AvailabilityZone.deleted == \'False\')'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def register_models():
|
def register_models():
|
||||||
|
@ -39,6 +39,12 @@ deprecated_backup_get_all = policy.DeprecatedRule(
|
|||||||
deprecated_reason=DEPRECATED_REASON,
|
deprecated_reason=DEPRECATED_REASON,
|
||||||
deprecated_since='2023.2/Bobcat',
|
deprecated_since='2023.2/Bobcat',
|
||||||
)
|
)
|
||||||
|
deprecated_get_all_project = policy.DeprecatedRule(
|
||||||
|
name=BASE_POLICY_NAME % 'get_all_project',
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
deprecated_reason=DEPRECATED_REASON,
|
||||||
|
deprecated_since='2023.2/Bobcat',
|
||||||
|
)
|
||||||
deprecated_backup_restore = policy.DeprecatedRule(
|
deprecated_backup_restore = policy.DeprecatedRule(
|
||||||
name=BASE_POLICY_NAME % 'restore',
|
name=BASE_POLICY_NAME % 'restore',
|
||||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
@ -57,6 +63,12 @@ deprecated_backup_delete = policy.DeprecatedRule(
|
|||||||
deprecated_reason=DEPRECATED_REASON,
|
deprecated_reason=DEPRECATED_REASON,
|
||||||
deprecated_since='2023.2/Bobcat',
|
deprecated_since='2023.2/Bobcat',
|
||||||
)
|
)
|
||||||
|
deprecated_backup_reset_status = policy.DeprecatedRule(
|
||||||
|
name=BASE_POLICY_NAME % 'reset_status',
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
deprecated_reason=DEPRECATED_REASON,
|
||||||
|
deprecated_since='2023.2/Bobcat',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
share_backup_policies = [
|
share_backup_policies = [
|
||||||
@ -107,6 +119,24 @@ share_backup_policies = [
|
|||||||
],
|
],
|
||||||
deprecated_rule=deprecated_backup_get_all,
|
deprecated_rule=deprecated_backup_get_all,
|
||||||
),
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=BASE_POLICY_NAME % 'get_all_project',
|
||||||
|
check_str=base.ADMIN,
|
||||||
|
scope_types=['project'],
|
||||||
|
description="Get share backups of all projects.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/share-backups?all_tenants=1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/share-backups/detail?all_tenants=1'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
deprecated_rule=deprecated_get_all_project
|
||||||
|
),
|
||||||
|
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
name=BASE_POLICY_NAME % 'restore',
|
name=BASE_POLICY_NAME % 'restore',
|
||||||
check_str=base.ADMIN_OR_PROJECT_MEMBER,
|
check_str=base.ADMIN_OR_PROJECT_MEMBER,
|
||||||
@ -120,6 +150,19 @@ share_backup_policies = [
|
|||||||
],
|
],
|
||||||
deprecated_rule=deprecated_backup_restore,
|
deprecated_rule=deprecated_backup_restore,
|
||||||
),
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=BASE_POLICY_NAME % 'reset_status',
|
||||||
|
check_str=base.ADMIN,
|
||||||
|
scope_types=['project'],
|
||||||
|
description="Reset status.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'POST',
|
||||||
|
'path': '/share-backups/{backup_id}/action',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
deprecated_rule=deprecated_backup_reset_status
|
||||||
|
),
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
name=BASE_POLICY_NAME % 'update',
|
name=BASE_POLICY_NAME % 'update',
|
||||||
check_str=base.ADMIN_OR_PROJECT_MEMBER,
|
check_str=base.ADMIN_OR_PROJECT_MEMBER,
|
||||||
|
@ -3867,6 +3867,7 @@ class API(base.Base):
|
|||||||
raise exception.BackupLimitExceeded(
|
raise exception.BackupLimitExceeded(
|
||||||
allowed=quotas[over])
|
allowed=quotas[over])
|
||||||
|
|
||||||
|
backup_ref = {}
|
||||||
try:
|
try:
|
||||||
backup_ref = self.db.share_backup_create(
|
backup_ref = self.db.share_backup_create(
|
||||||
context, share['id'],
|
context, share['id'],
|
||||||
@ -3879,6 +3880,7 @@ class API(base.Base):
|
|||||||
'display_description': backup.get('description'),
|
'display_description': backup.get('description'),
|
||||||
'display_name': backup.get('name'),
|
'display_name': backup.get('name'),
|
||||||
'size': share['size'],
|
'size': share['size'],
|
||||||
|
'availability_zone': share['instance']['availability_zone']
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
QUOTAS.commit(context, reservations)
|
QUOTAS.commit(context, reservations)
|
||||||
@ -3891,15 +3893,16 @@ class API(base.Base):
|
|||||||
{'status': constants.STATUS_BACKUP_CREATING})
|
{'status': constants.STATUS_BACKUP_CREATING})
|
||||||
|
|
||||||
backup_ref['backup_options'] = backup.get('backup_options', {})
|
backup_ref['backup_options'] = backup.get('backup_options', {})
|
||||||
|
backup_values = {}
|
||||||
if backup_ref['backup_options']:
|
if backup_ref['backup_options']:
|
||||||
topic = CONF.share_topic
|
topic = CONF.share_topic
|
||||||
|
backup_ref['host'] = share_utils.extract_host(share['host'])
|
||||||
|
backup_values.update({'host': backup_ref['host']})
|
||||||
else:
|
else:
|
||||||
topic = CONF.data_topic
|
topic = CONF.data_topic
|
||||||
|
|
||||||
backup_ref['host'] = share['host']
|
backup_values.update({'topic': topic})
|
||||||
self.db.share_backup_update(
|
self.db.share_backup_update(context, backup_ref['id'], backup_values)
|
||||||
context, backup_ref['id'],
|
|
||||||
{'host': backup_ref['host'], 'topic': topic})
|
|
||||||
|
|
||||||
if topic == CONF.share_topic:
|
if topic == CONF.share_topic:
|
||||||
self.share_rpcapi.create_backup(context, backup_ref)
|
self.share_rpcapi.create_backup(context, backup_ref)
|
||||||
|
@ -5217,7 +5217,9 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
for backup in backups:
|
for backup in backups:
|
||||||
backup_id = backup['id']
|
backup_id = backup['id']
|
||||||
try:
|
try:
|
||||||
filters = {'source_backup_id': backup_id}
|
filters = {
|
||||||
|
'source_backup_id': backup_id,
|
||||||
|
}
|
||||||
shares = self.db.share_get_all(context, filters)
|
shares = self.db.share_get_all(context, filters)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.warning('Failed to get shares for backup %s', backup_id)
|
LOG.warning('Failed to get shares for backup %s', backup_id)
|
||||||
@ -5247,9 +5249,9 @@ class ShareManager(manager.SchedulerDependentManager):
|
|||||||
LOG.info("Share backup %s restored successfully.",
|
LOG.info("Share backup %s restored successfully.",
|
||||||
backup_id)
|
backup_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.warning("Failed to get progress of share_backup "
|
LOG.exception("Failed to get progress of share_backup "
|
||||||
"%(backup)s restoring in share %(share).",
|
"%(backup)s restoring in share %(share).",
|
||||||
{'share': share_id, 'backup': backup_id})
|
{'share': share_id, 'backup': backup_id})
|
||||||
self.db.share_update(
|
self.db.share_update(
|
||||||
context, share_id,
|
context, share_id,
|
||||||
{'status': constants.STATUS_BACKUP_RESTORING_ERROR})
|
{'status': constants.STATUS_BACKUP_RESTORING_ERROR})
|
||||||
|
@ -60,6 +60,9 @@ class ShareUnmanageTest(test.TestCase):
|
|||||||
self.mock_object(
|
self.mock_object(
|
||||||
self.controller.share_api.db, 'share_snapshot_get_all_for_share',
|
self.controller.share_api.db, 'share_snapshot_get_all_for_share',
|
||||||
mock.Mock(return_value=[]))
|
mock.Mock(return_value=[]))
|
||||||
|
self.mock_object(
|
||||||
|
self.controller.share_api.db, 'share_backups_get_all',
|
||||||
|
mock.Mock(return_value=[]))
|
||||||
|
|
||||||
actual_result = self.controller.unmanage(self.request, share['id'])
|
actual_result = self.controller.unmanage(self.request, share['id'])
|
||||||
|
|
||||||
@ -67,6 +70,10 @@ class ShareUnmanageTest(test.TestCase):
|
|||||||
(self.controller.share_api.db.share_snapshot_get_all_for_share.
|
(self.controller.share_api.db.share_snapshot_get_all_for_share.
|
||||||
assert_called_once_with(
|
assert_called_once_with(
|
||||||
self.request.environ['manila.context'], share['id']))
|
self.request.environ['manila.context'], share['id']))
|
||||||
|
filters = {'share_id': 'foo_id'}
|
||||||
|
(self.controller.share_api.db.share_backups_get_all.
|
||||||
|
assert_called_once_with(
|
||||||
|
self.request.environ['manila.context'], filters))
|
||||||
self.controller.share_api.get.assert_called_once_with(
|
self.controller.share_api.get.assert_called_once_with(
|
||||||
self.request.environ['manila.context'], share['id'])
|
self.request.environ['manila.context'], share['id'])
|
||||||
share_api.API.unmanage.assert_called_once_with(
|
share_api.API.unmanage.assert_called_once_with(
|
||||||
@ -99,6 +106,32 @@ class ShareUnmanageTest(test.TestCase):
|
|||||||
self.mock_policy_check.assert_called_once_with(
|
self.mock_policy_check.assert_called_once_with(
|
||||||
self.context, self.resource_name, 'unmanage')
|
self.context, self.resource_name, 'unmanage')
|
||||||
|
|
||||||
|
def test_unmanage_share_that_has_backups(self):
|
||||||
|
share = dict(status=constants.STATUS_AVAILABLE, id='foo_id',
|
||||||
|
instance={})
|
||||||
|
backups = ['foo', 'bar']
|
||||||
|
self.mock_object(self.controller.share_api, 'unmanage')
|
||||||
|
self.mock_object(
|
||||||
|
self.controller.share_api.db, 'share_backups_get_all',
|
||||||
|
mock.Mock(return_value=backups))
|
||||||
|
self.mock_object(
|
||||||
|
self.controller.share_api, 'get',
|
||||||
|
mock.Mock(return_value=share))
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
webob.exc.HTTPForbidden,
|
||||||
|
self.controller.unmanage, self.request, share['id'])
|
||||||
|
|
||||||
|
self.assertFalse(self.controller.share_api.unmanage.called)
|
||||||
|
filters = {'share_id': 'foo_id'}
|
||||||
|
(self.controller.share_api.db.share_backups_get_all.
|
||||||
|
assert_called_once_with(
|
||||||
|
self.request.environ['manila.context'], filters))
|
||||||
|
self.controller.share_api.get.assert_called_once_with(
|
||||||
|
self.request.environ['manila.context'], share['id'])
|
||||||
|
self.mock_policy_check.assert_called_once_with(
|
||||||
|
self.context, self.resource_name, 'unmanage')
|
||||||
|
|
||||||
def test_unmanage_share_that_has_replicas(self):
|
def test_unmanage_share_that_has_replicas(self):
|
||||||
share = dict(status=constants.STATUS_AVAILABLE, id='foo_id',
|
share = dict(status=constants.STATUS_AVAILABLE, id='foo_id',
|
||||||
instance={}, has_replicas=True)
|
instance={}, has_replicas=True)
|
||||||
@ -106,6 +139,8 @@ class ShareUnmanageTest(test.TestCase):
|
|||||||
'unmanage')
|
'unmanage')
|
||||||
mock_db_snapshots_get = self.mock_object(
|
mock_db_snapshots_get = self.mock_object(
|
||||||
self.controller.share_api.db, 'share_snapshot_get_all_for_share')
|
self.controller.share_api.db, 'share_snapshot_get_all_for_share')
|
||||||
|
mock_db_backups_get = self.mock_object(
|
||||||
|
self.controller.share_api.db, 'share_backups_get_all')
|
||||||
self.mock_object(
|
self.mock_object(
|
||||||
self.controller.share_api, 'get',
|
self.controller.share_api, 'get',
|
||||||
mock.Mock(return_value=share))
|
mock.Mock(return_value=share))
|
||||||
@ -116,6 +151,7 @@ class ShareUnmanageTest(test.TestCase):
|
|||||||
|
|
||||||
self.assertFalse(mock_api_unmanage.called)
|
self.assertFalse(mock_api_unmanage.called)
|
||||||
self.assertFalse(mock_db_snapshots_get.called)
|
self.assertFalse(mock_db_snapshots_get.called)
|
||||||
|
self.assertFalse(mock_db_backups_get.called)
|
||||||
self.controller.share_api.get.assert_called_once_with(
|
self.controller.share_api.get.assert_called_once_with(
|
||||||
self.request.environ['manila.context'], share['id'])
|
self.request.environ['manila.context'], share['id'])
|
||||||
self.mock_policy_check.assert_called_once_with(
|
self.mock_policy_check.assert_called_once_with(
|
||||||
|
@ -68,21 +68,23 @@ class ShareBackupsApiTest(test.TestCase):
|
|||||||
def _get_fake_backup(self, admin=False, summary=False, **values):
|
def _get_fake_backup(self, admin=False, summary=False, **values):
|
||||||
backup = fake_share.fake_backup(**values)
|
backup = fake_share.fake_backup(**values)
|
||||||
backup['updated_at'] = '2016-06-12T19:57:56.506805'
|
backup['updated_at'] = '2016-06-12T19:57:56.506805'
|
||||||
expected_keys = {'id', 'share_id', 'backup_state'}
|
expected_keys = {'id', 'share_id', 'status'}
|
||||||
expected_backup = {key: backup[key] for key in backup if key
|
expected_backup = {key: backup[key] for key in backup if key
|
||||||
in expected_keys}
|
in expected_keys}
|
||||||
|
expected_backup.update({'name': backup.get('display_name')})
|
||||||
|
|
||||||
if not summary:
|
if not summary:
|
||||||
expected_backup.update({
|
expected_backup.update({
|
||||||
'id': backup.get('id'),
|
'id': backup.get('id'),
|
||||||
'size': backup.get('size'),
|
|
||||||
'share_id': backup.get('share_id'),
|
'share_id': backup.get('share_id'),
|
||||||
'availability_zone': backup.get('availability_zone'),
|
'status': backup.get('status'),
|
||||||
'created_at': backup.get('created_at'),
|
|
||||||
'backup_state': backup.get('status'),
|
|
||||||
'updated_at': backup.get('updated_at'),
|
|
||||||
'name': backup.get('display_name'),
|
|
||||||
'description': backup.get('display_description'),
|
'description': backup.get('display_description'),
|
||||||
|
'size': backup.get('size'),
|
||||||
|
'created_at': backup.get('created_at'),
|
||||||
|
'updated_at': backup.get('updated_at'),
|
||||||
|
'availability_zone': backup.get('availability_zone'),
|
||||||
|
'progress': backup.get('progress'),
|
||||||
|
'restore_progress': backup.get('restore_progress'),
|
||||||
})
|
})
|
||||||
if admin:
|
if admin:
|
||||||
expected_backup.update({
|
expected_backup.update({
|
||||||
@ -102,7 +104,7 @@ class ShareBackupsApiTest(test.TestCase):
|
|||||||
self.mock_policy_check.assert_called_once_with(
|
self.mock_policy_check.assert_called_once_with(
|
||||||
self.member_context, self.resource_name, 'get_all')
|
self.member_context, self.resource_name, 'get_all')
|
||||||
|
|
||||||
def test_list_share_backups_summary(self):
|
def test_list_backups_summary_with_share_id(self):
|
||||||
fake_backup, expected_backup = self._get_fake_backup(summary=True)
|
fake_backup, expected_backup = self._get_fake_backup(summary=True)
|
||||||
self.mock_object(share.API, 'get',
|
self.mock_object(share.API, 'get',
|
||||||
mock.Mock(return_value={'id': 'FAKE_SHAREID'}))
|
mock.Mock(return_value={'id': 'FAKE_SHAREID'}))
|
||||||
@ -379,10 +381,10 @@ class ShareBackupsApiTest(test.TestCase):
|
|||||||
def test_delete_exception(self):
|
def test_delete_exception(self):
|
||||||
fake_backup_1 = self._get_fake_backup(
|
fake_backup_1 = self._get_fake_backup(
|
||||||
share_id='FAKE_SHARE_ID',
|
share_id='FAKE_SHARE_ID',
|
||||||
backup_state=constants.STATUS_BACKUP_CREATING)[0]
|
status=constants.STATUS_BACKUP_CREATING)[0]
|
||||||
fake_backup_2 = self._get_fake_backup(
|
fake_backup_2 = self._get_fake_backup(
|
||||||
share_id='FAKE_SHARE_ID',
|
share_id='FAKE_SHARE_ID',
|
||||||
backup_state=constants.STATUS_BACKUP_CREATING)[0]
|
status=constants.STATUS_BACKUP_CREATING)[0]
|
||||||
exception_type = exception.InvalidBackup(reason='xyz')
|
exception_type = exception.InvalidBackup(reason='xyz')
|
||||||
self.mock_object(share_backups.db, 'share_backup_get',
|
self.mock_object(share_backups.db, 'share_backup_get',
|
||||||
mock.Mock(return_value=fake_backup_1))
|
mock.Mock(return_value=fake_backup_1))
|
||||||
@ -398,7 +400,7 @@ class ShareBackupsApiTest(test.TestCase):
|
|||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
fake_backup = self._get_fake_backup(
|
fake_backup = self._get_fake_backup(
|
||||||
share_id='FAKE_SHARE_ID',
|
share_id='FAKE_SHARE_ID',
|
||||||
backup_state=constants.STATUS_AVAILABLE)[0]
|
status=constants.STATUS_AVAILABLE)[0]
|
||||||
self.mock_object(share_backups.db, 'share_backup_get',
|
self.mock_object(share_backups.db, 'share_backup_get',
|
||||||
mock.Mock(return_value=fake_backup))
|
mock.Mock(return_value=fake_backup))
|
||||||
self.mock_object(share.API, 'delete_share_backup')
|
self.mock_object(share.API, 'delete_share_backup')
|
||||||
@ -424,7 +426,7 @@ class ShareBackupsApiTest(test.TestCase):
|
|||||||
body = {'restore': {'share_id': 'fake_id'}}
|
body = {'restore': {'share_id': 'fake_id'}}
|
||||||
fake_backup = self._get_fake_backup(
|
fake_backup = self._get_fake_backup(
|
||||||
share_id='FAKE_SHARE_ID',
|
share_id='FAKE_SHARE_ID',
|
||||||
backup_state=constants.STATUS_AVAILABLE)[0]
|
status=constants.STATUS_AVAILABLE)[0]
|
||||||
self.mock_object(share_backups.db, 'share_backup_get',
|
self.mock_object(share_backups.db, 'share_backup_get',
|
||||||
mock.Mock(return_value=fake_backup))
|
mock.Mock(return_value=fake_backup))
|
||||||
|
|
||||||
@ -447,7 +449,7 @@ class ShareBackupsApiTest(test.TestCase):
|
|||||||
def test_update(self):
|
def test_update(self):
|
||||||
fake_backup = self._get_fake_backup(
|
fake_backup = self._get_fake_backup(
|
||||||
share_id='FAKE_SHARE_ID',
|
share_id='FAKE_SHARE_ID',
|
||||||
backup_state=constants.STATUS_AVAILABLE)[0]
|
status=constants.STATUS_AVAILABLE)[0]
|
||||||
self.mock_object(share_backups.db, 'share_backup_get',
|
self.mock_object(share_backups.db, 'share_backup_get',
|
||||||
mock.Mock(return_value=fake_backup))
|
mock.Mock(return_value=fake_backup))
|
||||||
|
|
||||||
|
@ -3152,6 +3152,10 @@ class ShareManageTest(test.TestCase):
|
|||||||
api_version.APIVersionRequest('2.8')):
|
api_version.APIVersionRequest('2.8')):
|
||||||
share['is_public'] = data['share']['is_public']
|
share['is_public'] = data['share']['is_public']
|
||||||
|
|
||||||
|
if (api_version.APIVersionRequest(version) >=
|
||||||
|
api_version.APIVersionRequest('2.80')):
|
||||||
|
share['source_backup_id'] = None
|
||||||
|
|
||||||
req = fakes.HTTPRequest.blank('/v2/fake/shares/manage',
|
req = fakes.HTTPRequest.blank('/v2/fake/shares/manage',
|
||||||
version=version,
|
version=version,
|
||||||
use_admin_context=True)
|
use_admin_context=True)
|
||||||
|
@ -522,12 +522,19 @@ class DataManagerTestCase(test.TestCase):
|
|||||||
|
|
||||||
# mocks
|
# mocks
|
||||||
self.mock_object(db, 'share_update')
|
self.mock_object(db, 'share_update')
|
||||||
|
self.mock_object(db, 'share_backup_update')
|
||||||
self.mock_object(db, 'share_get', mock.Mock(return_value=share_info))
|
self.mock_object(db, 'share_get', mock.Mock(return_value=share_info))
|
||||||
self.mock_object(db, 'share_backup_get',
|
self.mock_object(db, 'share_backup_get',
|
||||||
mock.Mock(return_value=backup_info))
|
mock.Mock(return_value=backup_info))
|
||||||
self.mock_object(self.manager, '_run_backup',
|
self.mock_object(self.manager, '_run_backup',
|
||||||
mock.Mock(side_effect=None))
|
mock.Mock(side_effect=None))
|
||||||
self.manager.create_backup(self.context, backup_info)
|
self.manager.create_backup(self.context, backup_info)
|
||||||
|
db.share_update.assert_called_with(
|
||||||
|
self.context, share_info['id'],
|
||||||
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
|
db.share_backup_update.assert_called_with(
|
||||||
|
self.context, backup_info['id'],
|
||||||
|
{'status': constants.STATUS_AVAILABLE, 'progress': '100'})
|
||||||
|
|
||||||
def test_create_share_backup_exception(self):
|
def test_create_share_backup_exception(self):
|
||||||
share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
|
share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
|
||||||
@ -550,7 +557,7 @@ class DataManagerTestCase(test.TestCase):
|
|||||||
db.share_update.assert_called_with(
|
db.share_update.assert_called_with(
|
||||||
self.context, share_info['id'],
|
self.context, share_info['id'],
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
db.share_backup_update.assert_called_once()
|
db.share_backup_update.assert_called()
|
||||||
|
|
||||||
@ddt.data('90', '100')
|
@ddt.data('90', '100')
|
||||||
def test_create_share_backup_continue(self, progress):
|
def test_create_share_backup_continue(self, progress):
|
||||||
@ -571,7 +578,7 @@ class DataManagerTestCase(test.TestCase):
|
|||||||
if progress == '100':
|
if progress == '100':
|
||||||
db.share_backup_update.assert_called_with(
|
db.share_backup_update.assert_called_with(
|
||||||
self.context, backup_info['id'],
|
self.context, backup_info['id'],
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE, 'progress': '100'})
|
||||||
db.share_update.assert_called_with(
|
db.share_update.assert_called_with(
|
||||||
self.context, share_info['id'],
|
self.context, share_info['id'],
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
@ -678,11 +685,18 @@ class DataManagerTestCase(test.TestCase):
|
|||||||
|
|
||||||
# mocks
|
# mocks
|
||||||
self.mock_object(db, 'share_update')
|
self.mock_object(db, 'share_update')
|
||||||
|
self.mock_object(db, 'share_backup_update')
|
||||||
self.mock_object(db, 'share_get', mock.Mock(return_value=share_info))
|
self.mock_object(db, 'share_get', mock.Mock(return_value=share_info))
|
||||||
self.mock_object(db, 'share_backup_get',
|
self.mock_object(db, 'share_backup_get',
|
||||||
mock.Mock(return_value=backup_info))
|
mock.Mock(return_value=backup_info))
|
||||||
self.mock_object(self.manager, '_run_restore')
|
self.mock_object(self.manager, '_run_restore')
|
||||||
self.manager.restore_backup(self.context, backup_info, share_id)
|
self.manager.restore_backup(self.context, backup_info, share_id)
|
||||||
|
db.share_update.assert_called_with(
|
||||||
|
self.context, share_info['id'],
|
||||||
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
|
db.share_backup_update.assert_called_with(
|
||||||
|
self.context, backup_info['id'],
|
||||||
|
{'status': constants.STATUS_AVAILABLE, 'restore_progress': '100'})
|
||||||
|
|
||||||
def test_restore_share_backup_exception(self):
|
def test_restore_share_backup_exception(self):
|
||||||
share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
|
share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
|
||||||
@ -730,7 +744,8 @@ class DataManagerTestCase(test.TestCase):
|
|||||||
if progress == '100':
|
if progress == '100':
|
||||||
db.share_backup_update.assert_called_with(
|
db.share_backup_update.assert_called_with(
|
||||||
self.context, backup_info['id'],
|
self.context, backup_info['id'],
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE,
|
||||||
|
'restore_progress': '100'})
|
||||||
db.share_update.assert_called_with(
|
db.share_update.assert_called_with(
|
||||||
self.context, share_info['id'],
|
self.context, share_info['id'],
|
||||||
{'status': constants.STATUS_AVAILABLE})
|
{'status': constants.STATUS_AVAILABLE})
|
||||||
|
@ -5385,16 +5385,6 @@ class ShareBackupDatabaseAPITestCase(BaseDatabaseAPITestCase):
|
|||||||
self.ctxt, self.share_id, self.backup)
|
self.ctxt, self.share_id, self.backup)
|
||||||
self._check_fields(expected=self.backup, actual=result)
|
self._check_fields(expected=self.backup, actual=result)
|
||||||
|
|
||||||
def test_create_with_duplicated_id(self):
|
|
||||||
db_api.share_backup_create(
|
|
||||||
self.ctxt, self.share_id, self.backup)
|
|
||||||
|
|
||||||
self.assertRaises(db_exception.DBDuplicateEntry,
|
|
||||||
db_api.share_backup_create,
|
|
||||||
self.ctxt,
|
|
||||||
self.share_id,
|
|
||||||
self.backup)
|
|
||||||
|
|
||||||
def test_get(self):
|
def test_get(self):
|
||||||
db_api.share_backup_create(
|
db_api.share_backup_create(
|
||||||
self.ctxt, self.share_id, self.backup)
|
self.ctxt, self.share_id, self.backup)
|
||||||
|
@ -328,7 +328,6 @@ def fake_backup(as_primitive=True, **kwargs):
|
|||||||
'user_id': 'fake',
|
'user_id': 'fake',
|
||||||
'project_id': 'fake',
|
'project_id': 'fake',
|
||||||
'availability_zone': 'fake_availability_zone',
|
'availability_zone': 'fake_availability_zone',
|
||||||
'backup_state': constants.STATUS_CREATING,
|
|
||||||
'status': constants.STATUS_CREATING,
|
'status': constants.STATUS_CREATING,
|
||||||
'progress': '0',
|
'progress': '0',
|
||||||
'restore_progress': '0',
|
'restore_progress': '0',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user