Exemplo n.º 1
0
    def cache_tee_iter(self, image_id, image_iter, image_checksum):
        try:
            current_checksum = hashlib.md5()

            with self.driver.open_for_write(image_id) as cache_file:
                for chunk in image_iter:
                    try:
                        cache_file.write(chunk)
                    finally:
                        current_checksum.update(chunk)
                        yield chunk
                cache_file.flush()

                if (image_checksum and
                        image_checksum != current_checksum.hexdigest()):
                    msg = _("Checksum verification failed. Aborted "
                            "caching of image '%s'.") % image_id
                    raise exception.GlanceException(msg)

        except exception.GlanceException as e:
            with excutils.save_and_reraise_exception():
                # image_iter has given us bad, (size_checked_iter has found a
                # bad length), or corrupt data (checksum is wrong).
                LOG.exception(encodeutils.exception_to_unicode(e))
        except Exception as e:
            LOG.exception(_LE("Exception encountered while tee'ing "
                              "image '%(image_id)s' into cache: %(error)s. "
                              "Continuing with response.") %
                          {'image_id': image_id,
                           'error': encodeutils.exception_to_unicode(e)})

            # If no checksum provided continue responding even if
            # caching failed.
            for chunk in image_iter:
                yield chunk
Exemplo n.º 2
0
def size_checked_iter(response, image_meta, expected_size, image_iter,
                      notifier):
    image_id = image_meta['id']
    bytes_written = 0

    def notify_image_sent_hook(env):
        image_send_notification(bytes_written, expected_size,
                                image_meta, response.request, notifier)

    # Add hook to process after response is fully sent
    if 'eventlet.posthooks' in response.request.environ:
        response.request.environ['eventlet.posthooks'].append(
            (notify_image_sent_hook, (), {}))

    try:
        for chunk in image_iter:
            yield chunk
            bytes_written += len(chunk)
    except Exception as err:
        with excutils.save_and_reraise_exception():
            msg = (_LE("An error occurred reading from backend storage for "
                       "image %(image_id)s: %(err)s") % {'image_id': image_id,
                                                         'err': err})
            LOG.error(msg)

    if expected_size != bytes_written:
        msg = (_LE("Backend storage for image %(image_id)s "
                   "disconnected after writing only %(bytes_written)d "
                   "bytes") % {'image_id': image_id,
                               'bytes_written': bytes_written})
        LOG.error(msg)
        raise exception.GlanceException(_("Corrupt image download for "
                                          "image %(image_id)s") %
                                        {'image_id': image_id})
Exemplo n.º 3
0
        def tee_iter(image_id):
            try:
                current_checksum = hashlib.md5()

                with self.driver.open_for_write(image_id) as cache_file:
                    for chunk in image_iter:
                        try:
                            cache_file.write(chunk)
                        finally:
                            current_checksum.update(chunk)
                            yield chunk
                    cache_file.flush()

                if image_checksum and \
                        image_checksum != current_checksum.hexdigest():
                    msg = _("Checksum verification failed.  Aborted caching "
                            "of image %s." % image_id)
                    raise exception.GlanceException(msg)

            except Exception:
                LOG.exception(
                    _("Exception encountered while tee'ing "
                      "image '%s' into cache. Continuing "
                      "with response.") % image_id)

            # NOTE(markwash): continue responding even if caching failed
            for chunk in image_iter:
                yield chunk
Exemplo n.º 4
0
        def tee_iter(image_id):
            try:
                current_checksum = hashlib.md5()

                with self.driver.open_for_write(image_id) as cache_file:
                    for chunk in image_iter:
                        try:
                            cache_file.write(chunk)
                        finally:
                            current_checksum.update(chunk)
                            yield chunk
                    cache_file.flush()

                    if (image_checksum and
                            image_checksum != current_checksum.hexdigest()):
                        msg = _("Checksum verification failed. Aborted "
                                "caching of image '%s'." % image_id)
                        raise exception.GlanceException(msg)

            except exception.GlanceException as e:
                # image_iter has given us bad, (size_checked_iter has found a
                # bad length), or corrupt data (checksum is wrong).
                LOG.exception(e)
                raise
            except Exception as e:
                LOG.exception(
                    _("Exception encountered while tee'ing "
                      "image '%s' into cache: %s. Continuing "
                      "with response.") % (image_id, e))

            # NOTE(markwash): continue responding even if caching failed
            for chunk in image_iter:
                yield chunk
Exemplo n.º 5
0
def staging_store_path():
    """Return the local path to the staging store.

    :raises: GlanceException if staging store is not configured to be
             a file:// URI
    """
    if CONF.enabled_backends:
        separator, staging_dir = store_utils.get_dir_separator()
    else:
        staging_dir = CONF.node_staging_uri
    expected_prefix = 'file://'
    if not staging_dir.startswith(expected_prefix):
        raise exception.GlanceException('Unexpected scheme in staging store; '
                                        'unable to scan for residue')
    return staging_dir[len(expected_prefix):]
Exemplo n.º 6
0
    def __get_backend(self):
        if not self.__backend:
            if self.__config_group is None:
                backend_name = CONF[self.__pivot]
            else:
                backend_name = CONF[self.__config_group][self.__pivot]
            if backend_name not in self.__backends:
                msg = _('Invalid backend: %s') % backend_name
                raise exception.GlanceException(msg)

            backend = self.__backends[backend_name]
            if isinstance(backend, tuple):
                name = backend[0]
                fromlist = backend[1]
            else:
                name = backend
                fromlist = backend

            self.__backend = __import__(name, None, None, fromlist)
        return self.__backend
Exemplo n.º 7
0
    def _sync(self, version):
        """
        Place an existing database under migration control and upgrade it.
        """

        alembic_migrations.place_database_under_alembic_control()

        a_config = alembic_migrations.get_alembic_config()
        alembic_command.upgrade(a_config, version)
        heads = alembic_migrations.get_current_alembic_heads()
        if heads is None:
            raise exception.GlanceException("Database sync failed")
        revs = ", ".join(heads)
        if version == 'heads':
            print(_("Upgraded database, current revision(s):"), revs)
        else:
            print(
                _('Upgraded database to: %(v)s, current revision(s): %(r)s') %
                {
                    'v': version,
                    'r': revs
                })
Exemplo n.º 8
0
    def _get_sock_from_parent(self):
        # This is supposed to be called exactly once in the child process.
        # We're passing a copy of the socket through a pipe.
        pipe_handle = int(getattr(CONF, 'pipe_handle', 0))
        if not pipe_handle:
            err_msg = _("Did not receive a pipe handle, which is used when "
                        "communicating with the parent process.")
            raise exception.GlanceException(err_msg)

        # Get the length of the data to be received.
        buff = self._ioutils.get_buffer(4)
        self._ioutils.read_file(pipe_handle, buff, 4)
        socket_buff_sz = struct.unpack('<I', buff)[0]

        # Get the serialized socket object.
        socket_buff = self._ioutils.get_buffer(socket_buff_sz)
        self._ioutils.read_file(pipe_handle, socket_buff, socket_buff_sz)
        self._ioutils.close_handle(pipe_handle)

        # Recreate the socket object. This will only work with
        # Python 3.6 or later.
        return socket.fromshare(bytes(socket_buff[:]))
Exemplo n.º 9
0
 def test_specified_error_msg_with_kwargs(self):
     self.assertTrue('test: 500' in unicode(
         exception.GlanceException('test: %(code)s', code=500)))
Exemplo n.º 10
0
 def test_specified_error_msg(self):
     self.assertTrue('test' in unicode(exception.GlanceException('test')))
Exemplo n.º 11
0
 def faulty_backend():
     data = [b'a', b'b', b'c', b'Fail', b'd', b'e', b'f']
     for d in data:
         if d == b'Fail':
             raise exception.GlanceException('Backend failure')
         yield d
Exemplo n.º 12
0
 def test_specified_error_msg(self):
     msg = exception.GlanceException('test')
     self.assertIn('test', encodeutils.exception_to_unicode(msg))
Exemplo n.º 13
0
 def test_non_unicode_error_msg(self):
     exc = exception.GlanceException(str('test'))
     self.assertIsInstance(six.text_type(exc), six.text_type)
Exemplo n.º 14
0
 def data_iterator():
     self.notifier.log = []
     yield 'abcde'
     raise exception.GlanceException('Failed')
Exemplo n.º 15
0
        for chunk in image_iter:
            yield chunk
            bytes_written += len(chunk)
    except Exception, err:
        msg = _("An error occurred reading from backend storage "
                "for image %(image_id)s: %(err)s") % locals()
        LOG.error(msg)
        raise

    if expected_size != bytes_written:
        msg = _("Backend storage for image %(image_id)s "
                "disconnected after writing only %(bytes_written)d "
                "bytes") % locals()
        LOG.error(msg)
        raise exception.GlanceException(
            _("Corrupt image download for "
              "image %(image_id)s") % locals())


def image_send_notification(bytes_written, expected_size, image_meta, request,
                            notifier):
    """Send an image.send message to the notifier."""
    try:
        context = request.context
        payload = {
            'bytes_sent': bytes_written,
            'image_id': image_meta['id'],
            'owner_id': image_meta['owner'],
            'receiver_tenant_id': context.tenant,
            'receiver_user_id': context.user,
            'destination_ip': request.remote_addr,
Exemplo n.º 16
0
 def test_non_unicode_error_msg(self):
     exc = exception.GlanceException(str('test'))
     self.assertIsInstance(utils.exception_to_str(exc), str)
Exemplo n.º 17
0
 def test_specified_error_msg_with_kwargs(self):
     msg = exception.GlanceException('test: %(code)s', code=500)
     self.assertIn('test: 500', utils.exception_to_str(msg))
Exemplo n.º 18
0
 def test_specified_error_msg(self):
     msg = exception.GlanceException('test')
     self.assertIn('test', utils.exception_to_str(msg))
Exemplo n.º 19
0
 def test_specified_error_msg_with_kwargs(self):
     msg = exception.GlanceException('test: %(code)s',
                                     code=int(http.INTERNAL_SERVER_ERROR))
     self.assertIn('test: 500', encodeutils.exception_to_unicode(msg))