예제 #1
0
 def check_for_setup_error(self):
     """
     Runs once on startup of the manager, good a time as any to hit lunr and
     make sure cinder's got the types in the db.
     """
     lunr_admin_context = {'project_id': 'admin'}
     max_attempts = 3
     attempt = 0
     while True:
         attempt += 1
         try:
             client = LunrClient(self.url, lunr_admin_context, logger=LOG)
             resp = client.types.list()
         except Exception:
             if attempt >= max_attempts:
                 LOG.error('Unable up to read volume types from Lunr '
                           'after %s attempts.' % attempt)
                 return
             LOG.exception('failed attempt %s to retrieve volume types '
                           'from %s, will retry.' % (attempt, self.url))
             sleep(attempt**2)
         else:
             LOG.info('successfully pulled volume types from Lunr')
             break
     context = get_admin_context()
     for vtype in resp.body:
         if vtype['status'] != 'ACTIVE':
             LOG.debug('ignoring type %s with status %s' %
                       (vtype['name'], vtype['status']))
             continue
         try:
             volume_types.create(context, vtype['name'])
             LOG.info('volume type %s successfully created' % vtype['name'])
         except exception.VolumeTypeExists:
             LOG.info('volume type %s already exists' % vtype['name'])
예제 #2
0
 def attach_volume(self, context, volume, instance_uuid, host_name,
                   mountpoint):
     """Update lunr export metadata."""
     client = LunrClient(self.url, volume, logger=LOG)
     volume_id = self._lookup_volume_id(volume)
     client.exports.update(volume_id,
                           instance_id=instance_uuid,
                           mountpoint=mountpoint,
                           status='ATTACHED')
예제 #3
0
 def delete_volume(self, volume):
     try:
         client = LunrClient(self.url, volume, logger=LOG)
         volume_id = self._lookup_volume_id(volume)
         client.volumes.delete(volume_id)
     except LunrError, e:
         # ignore Not Found on delete
         if e.code != 404:
             raise
예제 #4
0
    def clone_image(self, context, volume, image_location, image_meta,
                    image_service):
        model_update = self._create_volume(volume, image_id=image_meta['id'])

        # Wait until the snapshot is ACTIVE
        client = LunrClient(self.url, volume, logger=LOG)
        volume_id = self._lookup_volume_id(volume, model_update)
        client.volumes.wait_on_status(volume_id, 'ACTIVE', 'IMAGING_SCRUB')

        return model_update, True
예제 #5
0
    def create_volume_from_snapshot(self, volume, snapshot):
        """Call the Lunr API to request a snapshot"""
        model_update = self._create_volume(volume, snapshot=snapshot)

        # Wait until the snapshot is ACTIVE
        client = LunrClient(self.url, volume, logger=LOG)
        volume_id = self._lookup_volume_id(volume, model_update)
        client.volumes.wait_on_status(volume_id, 'ACTIVE')

        return model_update
예제 #6
0
    def create_cloned_volume(self, volume, src_vref):
        """Call the Lunr API to request a clone """
        model_update = self._create_volume(volume, source=src_vref)

        # Wait until the volume is ACTIVE
        client = LunrClient(self.url, volume, logger=LOG)
        volume_id = self._lookup_volume_id(volume, model_update)
        client.volumes.wait_on_status(volume_id, 'ACTIVE')

        return model_update
예제 #7
0
 def delete_snapshot(self, snapshot):
     client = LunrClient(self.url, snapshot, logger=LOG)
     try:
         client.backups.delete(snapshot['id'])
         client.backups.wait_on_status(snapshot['id'], 'DELETED',
                                       'AUDITING')
     except LunrError, e:
         # ignore Not Found on delete_snapshot. Don't wait on status.
         if e.code == 404:
             return
         raise
예제 #8
0
    def _validate_lunr_volume_type(self, volume_type, size):
        if not volume_type:
            return

        lunr_context = {'project_id': 'admin'}
        try:
            client = LunrClient(CONF.lunr_api_endpoint,
                                lunr_context, logger=LOG)
            resp = client.types.get(volume_type['name'])
        except LunrError, e:
            LOG.error(_('unable to fetch volume type from LunR: %s'),
                      volume_type)
            raise
예제 #9
0
    def create_snapshot(self, snapshot):
        """Creates a snapshot."""
        try:
            context = get_admin_context()
            volume = self.db.volume_get(context, snapshot['volume_id'])
        except Exception as e:
            msg = (_('create_snapshot: get volume failed.'))
            LOG.error(msg)
            raise exception.VolumeDriverException(message=msg)

        client = LunrClient(self.url, snapshot, logger=LOG)
        volume_id = self._lookup_volume_id(volume)
        params = {'volume': volume_id}
        client.backups.create(snapshot['id'], **params)
        client.backups.wait_on_status(snapshot['id'], 'AVAILABLE')
예제 #10
0
 def terminate_connection(self, volume, connector, force=False):
     """Delete lunr export."""
     client = LunrClient(self.url, volume, logger=LOG)
     initiator = connector.get('initiator')
     volume_id = self._lookup_volume_id(volume)
     try:
         client.exports.delete(volume_id, force=force, initiator=initiator)
     except LunrError as e:
         with excutils.save_and_reraise_exception() as ctxt:
             # NOTE(buhman): the volume manager transforms all
             # exceptions from terminate_connection to a generic
             # driver exception. Because we don't consider
             # attempting to delete a non-existing export as a
             # failure, suppress the exception here
             if e.code == exc.HTTPNotFound.code:
                 ctxt.reraise = False
                 LOG.info(e)
예제 #11
0
    def _create_volume(self,
                       volume,
                       snapshot=None,
                       source=None,
                       image_id=None):
        model_update = {}
        model_update_meta = {}
        affinity = None
        maintenance_zone = None
        lunr_id = volume['id']
        if volume.get('volume_metadata'):
            for meta in volume.get('volume_metadata', []):
                model_update_meta[meta.key] = meta.value
                # Translating terms, rack->group. Last one specified wins.
                if meta.key == 'different_node':
                    affinity = "different_node:%s" % meta.value
                if meta.key == 'different_rack':
                    affinity = "different_group:%s" % meta.value
                if meta.key == 'maintenance_zone':
                    maintenance_zone = meta.value
        try:
            # Try to get the volume type name, else use the default volume type
            volume_type_name = volume['volume_type']['name']
        except (KeyError, TypeError):
            raise RuntimeError("Cinder failed to assign a volume type;"
                               " is 'CONF.default_volume_type' set?")

        params = {
            'name': volume['id'],
            'size': volume['size'],
            'volume_type_name': volume_type_name,
        }
        if snapshot:
            params['backup'] = snapshot['id']
        if source:
            source_volume_id = self._lookup_volume_id(source)
            params['source_volume'] = source_volume_id
        if image_id:
            params['image_id'] = image_id
        if affinity:
            params['affinity'] = affinity
        if maintenance_zone:
            params['zone'] = maintenance_zone
        migration_status = volume.get('migration_status', None)
        if migration_status and 'target' in migration_status:
            k, v = migration_status.split(':')
            params['name'] = v
            params['force_node'] = CONF.host

        # Make the Rest Call
        client = LunrClient(self.url, volume, logger=LOG)
        try:
            resp = client.volumes.create(lunr_id, **params)
        except LunrError as e:
            if e.code == 409:
                lunr_id = str(uuid4())
                resp = client.volumes.create(lunr_id, **params)
                model_update['_name_id'] = lunr_id
            else:
                raise

        if resp.body['size'] != volume['size']:
            model_update['size'] = resp.body['size']
        if resp.body.get('cinder_host'):
            model_update['host'] = resp.body['cinder_host']
        if resp.body.get('node_id'):
            model_update_meta['storage-node'] = resp.body['node_id']

        # return any model changes that cinder should make
        if model_update_meta:
            model_update['metadata'] = model_update_meta
        return model_update
예제 #12
0
 def accept_transfer(self, context, volume, new_user, new_project):
     if new_project == volume['project_id']:
         return
     client = LunrClient(self.url, volume, logger=LOG)
     volume_id = self._lookup_volume_id(volume)
     client.volumes.update(volume_id, account_id=new_project)
예제 #13
0
 def detach_volume(self, context, volume, attachment=None):
     """Update lunr export metadata."""
     client = LunrClient(self.url, volume, logger=LOG)
     volume_id = self._lookup_volume_id(volume)
     client.exports.update(volume['id'], instance_id=None)
예제 #14
0
 def initialize_connection(self, volume, connector, initiator_data=None):
     """Create export and return connection info."""
     client = LunrClient(self.url, volume, logger=LOG)
     volume_id = self._lookup_volume_id(volume)
     return initialize_connection(client, volume_id, connector)