Beispiel #1
0
    def _verify_data_file(self, fp, current_time):
        """
        Verify the metadata's name value matches what we think the object is
        named.

        :raises DiskFileCollision: if the metadata stored name does not match
                                   the referenced name of the file
        :raises DiskFileNotExist: if the object has expired
        :raises DiskFileQuarantined: if data inconsistencies were detected
                                     between the metadata and the file-system
                                     metadata
        """
        try:
            mname = self._metadata['name']
        except KeyError:
            raise self._quarantine(self._name, "missing name metadata")
        else:
            if mname != self._name:
                raise DiskFileCollision('Client path does not match path '
                                        'stored in object metadata')
        try:
            x_delete_at = int(self._metadata['X-Delete-At'])
        except KeyError:
            pass
        except ValueError:
            # Quarantine, the x-delete-at key is present but not an
            # integer.
            raise self._quarantine(
                self._name, "bad metadata x-delete-at value %s" %
                (self._metadata['X-Delete-At']))
        else:
            if current_time is None:
                current_time = time.time()
            if x_delete_at <= current_time:
                raise DiskFileNotExist('Expired')
        try:
            metadata_size = int(self._metadata['Content-Length'])
        except KeyError:
            raise self._quarantine(self._name,
                                   "missing content-length in metadata")
        except ValueError:
            # Quarantine, the content-length key is present but not an
            # integer.
            raise self._quarantine(
                self._name, "bad metadata content-length value %s" %
                (self._metadata['Content-Length']))
        try:
            fp.seek(0, 2)
            obj_size = fp.tell()
            fp.seek(0, 0)
        except OSError as err:
            # Quarantine, we can't successfully stat the file.
            raise self._quarantine(self._name, "not stat-able: %s" % err)
        if obj_size != metadata_size:
            raise self._quarantine(
                self._name, "metadata content-length %s does"
                " not match actual object size %s" % (metadata_size, obj_size))
        return fp
Beispiel #2
0
 def _verify_name(self):
     """
     Verify the metadata's name value matches what we think the object is
     named.
     """
     try:
         mname = self.metadata['name']
     except KeyError:
         pass
     else:
         if mname != self.name:
             self.logger.error(_('Client path %(client)s does not match '
                                 'path stored in object metadata %(meta)s'),
                               {'client': self.name, 'meta': mname})
             raise DiskFileCollision('Client path does not match path '
                                     'stored in object metadata')
    def _verify_data_file(self):
        """
        Verify the metadata's name value matches what we think the object is
        named.

        :raises DiskFileCollision: if the metadata stored name does not match
                                   the referenced name of the file
        :raises DiskFileNotExist: if the object has expired
        :raises DiskFileQuarantined: if data inconsistencies were detected
                                     between the metadata and the file-system
                                     metadata
        """
        try:
            mname = self._metadata['name']
        except KeyError:
            self._quarantine("missing name metadata")
        else:
            if mname != self._name:
                raise DiskFileCollision('Client path does not match path '
                                        'stored in object metadata')
        try:
            x_delete_at = int(self._metadata['X-Delete-At'])
        except KeyError:
            pass
        except ValueError:
            # Quarantine, the x-delete-at key is present but not an
            # integer.
            self._quarantine("bad metadata x-delete-at value %s" %
                             (self._metadata['X-Delete-At']))
        else:
            if x_delete_at <= time.time():
                raise DiskFileNotExist('Expired')
        try:
            metadata_size = int(self._metadata['Content-Length'])
        except KeyError:
            self._quarantine("missing content-length in metadata")
        except ValueError:
            # Quarantine, the content-length key is present but not an
            # integer.
            self._quarantine("bad metadata content-length value %s" %
                             (self._metadata['Content-Length']))

        obj_size = self._fs_inst.size(self._name)
        if obj_size != metadata_size:
            self._quarantine("metadata content-length %s does"
                             " not match actual object size %s" %
                             (metadata_size, obj_size))
Beispiel #4
0
 def __init__(self,
              path,
              device,
              partition,
              account,
              container,
              obj,
              logger,
              keep_data_fp=False,
              disk_chunk_size=65536,
              bytes_per_sync=(512 * 1024 * 1024),
              iter_hook=None,
              threadpool=None,
              obj_dir='objects',
              mount_check=False,
              disallowed_metadata_keys=None):
     if mount_check and not check_mount(path, device):
         raise DiskFileDeviceUnavailable()
     self.disk_chunk_size = disk_chunk_size
     self.bytes_per_sync = bytes_per_sync
     self.iter_hook = iter_hook
     self.name = '/' + '/'.join((account, container, obj))
     name_hash = hash_path(account, container, obj)
     self.datadir = join(path, device,
                         storage_directory(obj_dir, partition, name_hash))
     self.device_path = join(path, device)
     self.tmpdir = join(path, device, 'tmp')
     self.logger = logger
     self.disallowed_metadata_keys = disallowed_metadata_keys or []
     self.metadata = {}
     self.data_file = None
     self.fp = None
     self.iter_etag = None
     self.started_at_0 = False
     self.read_to_eof = False
     self.quarantined_dir = None
     self.keep_cache = False
     self.suppress_file_closing = False
     self.threadpool = threadpool or ThreadPool(nthreads=0)
     if not exists(self.datadir):
         return
     files = sorted(os.listdir(self.datadir), reverse=True)
     meta_file = None
     for afile in files:
         if afile.endswith('.ts'):
             self.data_file = None
             with open(join(self.datadir, afile)) as mfp:
                 self.metadata = read_metadata(mfp)
             self.metadata['deleted'] = True
             break
         if afile.endswith('.meta') and not meta_file:
             meta_file = join(self.datadir, afile)
         if afile.endswith('.data') and not self.data_file:
             self.data_file = join(self.datadir, afile)
             break
     if not self.data_file:
         return
     self.fp = open(self.data_file, 'rb')
     self.metadata = read_metadata(self.fp)
     if not keep_data_fp:
         self.close(verify_file=False)
     if meta_file:
         with open(meta_file) as mfp:
             for key in self.metadata.keys():
                 if key.lower() not in self.disallowed_metadata_keys:
                     del self.metadata[key]
             self.metadata.update(read_metadata(mfp))
     if 'name' in self.metadata:
         if self.metadata['name'] != self.name:
             self.logger.error(
                 _('Client path %(client)s does not match '
                   'path stored in object metadata %(meta)s'), {
                       'client': self.name,
                       'meta': self.metadata['name']
                   })
             raise DiskFileCollision('Client path does not match path '
                                     'stored in object metadata')
Beispiel #5
0
 def __init__(self,
              path,
              device,
              partition,
              account,
              container,
              obj,
              logger,
              keep_data_fp=False,
              disk_chunk_size=65536,
              bytes_per_sync=(512 * 1024 * 1024),
              iter_hook=None):
     self.disk_chunk_size = disk_chunk_size
     self.bytes_per_sync = bytes_per_sync
     self.iter_hook = iter_hook
     self.name = '/' + '/'.join((account, container, obj))
     name_hash = hash_path(account, container, obj)
     self.datadir = os.path.join(
         path, device, storage_directory(DATADIR, partition, name_hash))
     self.device_path = os.path.join(path, device)
     self.tmpdir = os.path.join(path, device, 'tmp')
     self.logger = logger
     self.metadata = {}
     self.meta_file = None
     self.data_file = None
     self.fp = None
     self.iter_etag = None
     self.started_at_0 = False
     self.read_to_eof = False
     self.quarantined_dir = None
     self.keep_cache = False
     self.suppress_file_closing = False
     if not os.path.exists(self.datadir):
         return
     files = sorted(os.listdir(self.datadir), reverse=True)
     for afile in files:
         if afile.endswith('.ts'):
             self.data_file = self.meta_file = None
             self.metadata = {'deleted': True}
             return
         if afile.endswith('.meta') and not self.meta_file:
             self.meta_file = os.path.join(self.datadir, afile)
         if afile.endswith('.data') and not self.data_file:
             self.data_file = os.path.join(self.datadir, afile)
             break
     if not self.data_file:
         return
     self.fp = open(self.data_file, 'rb')
     self.metadata = read_metadata(self.fp)
     if not keep_data_fp:
         self.close(verify_file=False)
     if self.meta_file:
         with open(self.meta_file) as mfp:
             for key in self.metadata.keys():
                 if key.lower() not in DISALLOWED_HEADERS:
                     del self.metadata[key]
             self.metadata.update(read_metadata(mfp))
     if 'name' in self.metadata:
         if self.metadata['name'] != self.name:
             self.logger.error(
                 _('Client path %(client)s does not match '
                   'path stored in object metadata %(meta)s'), {
                       'client': self.name,
                       'meta': self.metadata['name']
                   })
             raise DiskFileCollision('Client path does not match path '
                                     'stored in object metadata')
Beispiel #6
0
    def _verify_data_file(self, data_file, fp):
        """
        Verify the metadata's name value matches what we think the object is
        named.

        :param data_file: data file name being consider, used when quarantines
                          occur
        :param fp: open file pointer so that we can `fstat()` the file to
                   verify the on-disk size with Content-Length metadata value
        :raises DiskFileCollision: if the metadata stored name does not match
                                   the referenced name of the file
        :raises DiskFileNotExist: if the object has expired
        :raises DiskFileQuarantined: if data inconsistencies were detected
                                     between the metadata and the file-system
                                     metadata
        """
        try:
            mname = self._metadata['name']
        except KeyError:
            self._quarantine(data_file, "missing name metadata")
        else:
            if mname != self._name:
                self._logger.error(
                    _('Client path %(client)s does not match '
                      'path stored in object metadata %(meta)s'), {
                          'client': self._name,
                          'meta': mname
                      })
                raise DiskFileCollision('Client path does not match path '
                                        'stored in object metadata')
        try:
            x_delete_at = int(self._metadata['X-Delete-At'])
        except KeyError:
            pass
        except ValueError:
            # Quarantine, the x-delete-at key is present but not an
            # integer.
            self._quarantine(
                data_file, "bad metadata x-delete-at value %s" %
                (self._metadata['X-Delete-At']))
        else:
            if x_delete_at <= time.time():
                raise DiskFileNotExist('Expired')
        try:
            metadata_size = int(self._metadata['Content-Length'])
        except KeyError:
            self._quarantine(data_file, "missing content-length in metadata")
        except ValueError:
            # Quarantine, the content-length key is present but not an
            # integer.
            self._quarantine(
                data_file, "bad metadata content-length value %s" %
                (self._metadata['Content-Length']))
        fd = fp.fileno()
        try:
            statbuf = os.fstat(fd)
        except OSError as err:
            # Quarantine, we can't successfully stat the file.
            self._quarantine(data_file, "not stat-able: %s" % err)
        else:
            obj_size = statbuf.st_size
        if metadata_size is not None and obj_size != metadata_size:
            self._quarantine(
                data_file, "metadata content-length %s does"
                " not match actual object size %s" %
                (metadata_size, statbuf.st_size))
        return obj_size