"Fossies" - the Fresh Open Source Software Archive

Member "ec2-api-12.0.0/ec2api/api/snapshot.py" (14 Apr 2021, 5923 Bytes) of package /linux/misc/openstack/ec2-api-12.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "snapshot.py" see the Fossies "Dox" file reference documentation.

    1 # Copyright 2014
    2 # The Cloudscaling Group, Inc.
    3 #
    4 # Licensed under the Apache License, Version 2.0 (the "License");
    5 # you may not use this file except in compliance with the License.
    6 # You may obtain a copy of the License at
    7 # http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 # Unless required by applicable law or agreed to in writing, software
   10 # distributed under the License is distributed on an "AS IS" BASIS,
   11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   12 # See the License for the specific language governing permissions and
   13 # limitations under the License.
   14 
   15 from cinderclient import exceptions as cinder_exception
   16 
   17 from ec2api.api import common
   18 from ec2api.api import ec2utils
   19 from ec2api import clients
   20 from ec2api.db import api as db_api
   21 from ec2api import exception
   22 from ec2api.i18n import _
   23 
   24 
   25 """Snapshot related API implementation
   26 """
   27 
   28 
   29 Validator = common.Validator
   30 
   31 
   32 def create_snapshot(context, volume_id, description=None):
   33     volume = ec2utils.get_db_item(context, volume_id)
   34     cinder = clients.cinder(context)
   35     os_volume = cinder.volumes.get(volume['os_id'])
   36     # NOTE(ft): Easy fix to allow snapshot creation in statuses other than
   37     # AVAILABLE without cinder modifications. Potential race condition
   38     # though. Seems arguably non-fatal.
   39     if os_volume.status not in ['available', 'in-use',
   40                                 'attaching', 'detaching']:
   41         msg = (_("'%s' is not in a state where snapshots are allowed.") %
   42                volume_id)
   43         raise exception.IncorrectState(reason=msg)
   44     with common.OnCrashCleaner() as cleaner:
   45         os_snapshot = cinder.volume_snapshots.create(os_volume.id, True)
   46         cleaner.addCleanup(os_snapshot.delete)
   47         snapshot = db_api.add_item(context, 'snap', {'os_id': os_snapshot.id})
   48         cleaner.addCleanup(db_api.delete_item, context, snapshot['id'])
   49         os_snapshot.update(display_name=snapshot['id'],
   50                            display_description=description)
   51         # NOTE(andrey-mp): to re-read description in version dependent format
   52         os_snapshot.get()
   53 
   54     return _format_snapshot(context, snapshot, os_snapshot,
   55                             volume_id=volume_id)
   56 
   57 
   58 def delete_snapshot(context, snapshot_id):
   59     snapshot = ec2utils.get_db_item(context, snapshot_id)
   60     cinder = clients.cinder(context)
   61     try:
   62         cinder.volume_snapshots.delete(snapshot['os_id'])
   63     except cinder_exception.NotFound:
   64         pass
   65     # NOTE(andrey-mp) Don't delete item from DB until it disappears from Cloud
   66     # It will be deleted by describer in the future
   67     return True
   68 
   69 
   70 class SnapshotDescriber(common.TaggableItemsDescriber):
   71 
   72     KIND = 'snap'
   73     SORT_KEY = 'snapshotId'
   74     FILTER_MAP = {'description': 'description',
   75                   'owner-id': 'ownerId',
   76                   'progress': 'progress',
   77                   'snapshot-id': 'snapshotId',
   78                   'start-time': 'startTime',
   79                   'status': 'status',
   80                   'volume-id': 'volumeId',
   81                   'volume-size': 'volumeSize'}
   82 
   83     def format(self, snapshot, os_snapshot):
   84         return _format_snapshot(self.context, snapshot, os_snapshot,
   85                                 self.volumes)
   86 
   87     def get_db_items(self):
   88         self.volumes = {vol['os_id']: vol
   89                         for vol in db_api.get_items(self.context, 'vol')}
   90         return super(SnapshotDescriber, self).get_db_items()
   91 
   92     def get_os_items(self):
   93         return clients.cinder(self.context).volume_snapshots.list()
   94 
   95     def get_name(self, os_item):
   96         return ''
   97 
   98 
   99 def describe_snapshots(context, snapshot_id=None, owner=None,
  100                        restorable_by=None, filter=None,
  101                        max_results=None, next_token=None):
  102     if snapshot_id and max_results:
  103         msg = _('The parameter snapshotSet cannot be used with the parameter '
  104                 'maxResults')
  105         raise exception.InvalidParameterCombination(msg)
  106 
  107     snapshot_describer = SnapshotDescriber()
  108     formatted_snapshots = snapshot_describer.describe(
  109         context, ids=snapshot_id, filter=filter,
  110         max_results=max_results, next_token=next_token)
  111     result = {'snapshotSet': formatted_snapshots}
  112     if snapshot_describer.next_token:
  113         result['nextToken'] = snapshot_describer.next_token
  114     return result
  115 
  116 
  117 def _format_snapshot(context, snapshot, os_snapshot, volumes={},
  118                      volume_id=None):
  119     # NOTE(mikal): this is just a set of strings in cinder. If they
  120     # implement an enum, then we should move this code to use it. The
  121     # valid ec2 statuses are "pending", "completed", and "error".
  122     status_map = {'new': 'pending',
  123                   'creating': 'pending',
  124                   'available': 'completed',
  125                   'active': 'completed',
  126                   'deleting': 'pending',
  127                   'deleted': None,
  128                   'error': 'error'}
  129 
  130     mapped_status = status_map.get(os_snapshot.status, os_snapshot.status)
  131     if not mapped_status:
  132         return None
  133 
  134     if not volume_id and os_snapshot.volume_id:
  135         volume = ec2utils.get_db_item_by_os_id(
  136                 context, 'vol', os_snapshot.volume_id, volumes)
  137         volume_id = volume['id']
  138 
  139     # NOTE(andrey-mp): ownerId and progress are empty in just created snapshot
  140     ownerId = os_snapshot.project_id
  141     if not ownerId:
  142         ownerId = context.project_id
  143     progress = os_snapshot.progress
  144     if not progress:
  145         progress = '0%'
  146     description = (getattr(os_snapshot, 'description', None) or
  147         getattr(os_snapshot, 'display_description', None))
  148     return {'snapshotId': snapshot['id'],
  149             'volumeId': volume_id,
  150             'status': mapped_status,
  151             'startTime': os_snapshot.created_at,
  152             'progress': progress,
  153             'ownerId': ownerId,
  154             'volumeSize': os_snapshot.size,
  155             'description': description}