Example #1
0
 def __init__(self, config, quit_check_callback=None):
     super(FileSystemCrashStorage, self).__init__(config)
     self.pro_crash_store = ProcessedDumpStorage(
         root=config.pro_fs_root,
         minutesPerSlot=config.minutes_per_slot,
         subSlotCount=config.sub_slot_count,
         indexName=config.index_name,
         dateName=config.date_name,
         fileSuffix=config.processed_crash_file_suffix,
         gzipCompression=config.gzip_compression_level,
         storageDepth=config.storage_depth,
         dumpGID=config.dump_gid,
         dumpPermissions=config.dump_permissions,
         dirPermissions=config.dir_permissions,
     )
Example #2
0
 def __init__(self, config, quit_check_callback=None):
     super(FileSystemCrashStorage, self).__init__(config)
     self.pro_crash_store = ProcessedDumpStorage(
       root=config.pro_fs_root,
       minutesPerSlot=config.minutes_per_slot,
       subSlotCount=config.sub_slot_count,
       indexName=config.index_name,
       dateName=config.date_name,
       fileSuffix=config.processed_crash_file_suffix,
       gzipCompression=config.gzip_compression_level,
       storageDepth=config.storage_depth,
       dumpGID=config.dump_gid,
       dumpPermissions=config.dump_permissions,
       dirPermissions=config.dir_permissions,
     )
Example #3
0
class FileSystemCrashStorage(FileSystemThrottledCrashStorage):
    """This storage class is the only file system based crash storage system
    appropriate for storing both raw and processed crashes.  This class uses
    the same segregating raw crash storage as the previous class and adds
    processed storage.  Processed crashes are stored in their own file system
    root, 'pro_fs_root' (processed file system root) using the same radix
    directory system as the raw crashes."""

    required_config = Namespace()
    required_config.add_option(
        'pro_fs_root',
        doc='a path to a local file system for processed storage',
        default='./processedCrashStore',
        reference_value_from='resource.filesystem',
    )
    required_config.add_option(
        'minutes_per_slot',
        doc='the number of minutes in the lowest date directory',
        default=1,
        reference_value_from='resource.filesystem',
    )
    required_config.add_option(
        'sub_slot_count',
        doc='distribute data evenly among this many sub timeslots',
        default=1,
        reference_value_from='resource.filesystem',
    )
    required_config.add_option(
        'index_name',
        doc='the relative path to the top of the name storage tree from '
            'root parameter',
        default='name',
        reference_value_from='resource.filesystem',
    )
    required_config.add_option(
        'date_name',
        doc='the relative path to the top of the date storage tree from '
            'root parameter',
        default='date',
        reference_value_from='resource.filesystem',
    )
    required_config.add_option(
        'processed_crash_file_suffix',
        doc='the processed crash filename suffix',
        default='.jsonz',
        reference_value_from='resource.filesystem',
    )
    required_config.add_option(
        'gzip_compression_level',
        doc='the level of compression to use',
        default=9,
        reference_value_from='resource.filesystem',
    )
    required_config.add_option(
        'storage_depth',
        doc='the length of branches in the radix storage tree',
        default=2,
        reference_value_from='resource.filesystem',
    )

    #--------------------------------------------------------------------------
    def __init__(self, config, quit_check_callback=None):
        super(FileSystemCrashStorage, self).__init__(config)
        self.pro_crash_store = ProcessedDumpStorage(
          root=config.pro_fs_root,
          minutesPerSlot=config.minutes_per_slot,
          subSlotCount=config.sub_slot_count,
          indexName=config.index_name,
          dateName=config.date_name,
          fileSuffix=config.processed_crash_file_suffix,
          gzipCompression=config.gzip_compression_level,
          storageDepth=config.storage_depth,
          dumpGID=config.dump_gid,
          dumpPermissions=config.dump_permissions,
          dirPermissions=config.dir_permissions,
        )

    #--------------------------------------------------------------------------
    def save_processed(self, processed_crash):
        """save a processed crash (in the form of a Mapping) into a json
        file.  It first gets the underlying file system to give it a file
        handle open for writing, then it uses the 'json' module to write
        the mapping to the open file handle."""
        try:
            crash_id = processed_crash['uuid']
        except KeyError:
            raise CrashIDNotFound("uuid missing from processed_crash")
        try:
            self._stringify_dates_in_dict(processed_crash)
            processed_crash_file_handle = \
                self.pro_crash_store.newEntry(crash_id)
            try:
                json.dump(processed_crash, processed_crash_file_handle)
            finally:
                processed_crash_file_handle.close()
            self.logger.debug('saved processed- %s', crash_id)
        except Exception:
            self.logger.critical(
              'processed file system storage has failed for: %s',
              crash_id,
              exc_info=True
            )
            raise

    #--------------------------------------------------------------------------
    def get_unredacted_processed(self, crash_id):
        """fetch a processed json file from the underlying file system"""
        try:
            return self.pro_crash_store.getDumpFromFile(crash_id)
        except OSError:
            raise CrashIDNotFound(crash_id)

    #--------------------------------------------------------------------------
    def remove(self, crash_id):
        """remove the all traces of a crash, both raw and processed from the
        file system."""
        try:
            super(FileSystemCrashStorage, self).remove(crash_id)
        except CrashIDNotFound:
            self.logger.warning(
              'raw crash not found for deletion: %s',
              crash_id
            )
        try:
            self.pro_crash_store.removeDumpFile(crash_id)
        except OSError:
            self.logger.warning('processed crash not found for deletion: %s',
                                crash_id)

    #--------------------------------------------------------------------------
    @staticmethod
    def _stringify_dates_in_dict(a_dict):
        for name, value in a_dict.iteritems():
            if isinstance(value, datetime.datetime):
                a_dict[name] = ("%4d-%02d-%02d %02d:%02d:%02d.%d" %
                  (value.year,
                   value.month,
                   value.day,
                   value.hour,
                   value.minute,
                   value.second,
                   value.microsecond)
                )
Example #4
0
class FileSystemCrashStorage(FileSystemThrottledCrashStorage):
    """This storage class is the only file system based crash storage system
    appropriate for storing both raw and processed crashes.  This class uses
    the same segregating raw crash storage as the previous class and adds
    processed storage.  Processed crashes are stored in their own file system
    root, 'pro_fs_root' (processed file system root) using the same radix
    directory system as the raw crashes."""

    required_config = Namespace()
    required_config.add_option(
        "pro_fs_root",
        doc="a path to a local file system for processed storage",
        default="/home/socorro/processedCrashStore",
    )
    required_config.add_option("minutes_per_slot", doc="the number of minutes in the lowest date directory", default=1)
    required_config.add_option("sub_slot_count", doc="distribute data evenly among this many sub timeslots", default=1)
    required_config.add_option(
        "index_name", doc="the relative path to the top of the name storage tree from " "root parameter", default="name"
    )
    required_config.add_option(
        "date_name", doc="the relative path to the top of the date storage tree from " "root parameter", default="date"
    )
    required_config.add_option(
        "processed_crash_file_suffix", doc="the processed crash filename suffix", default=".jsonz"
    )
    required_config.add_option("gzip_compression_level", doc="the level of compression to use", default=9)
    required_config.add_option("storage_depth", doc="the length of branches in the radix storage tree", default=2)
    required_config.add_option(
        "forbidden_keys",
        doc="a comma delimited list of keys to not allowed in the processed " "crash",
        default="url, email, user_id",
        from_string_converter=lambda x: [i.strip() for i in x.split(",")],
    )

    # --------------------------------------------------------------------------
    def __init__(self, config, quit_check_callback=None):
        super(FileSystemCrashStorage, self).__init__(config)
        self.pro_crash_store = ProcessedDumpStorage(
            root=config.pro_fs_root,
            minutesPerSlot=config.minutes_per_slot,
            subSlotCount=config.sub_slot_count,
            indexName=config.index_name,
            dateName=config.date_name,
            fileSuffix=config.processed_crash_file_suffix,
            gzipCompression=config.gzip_compression_level,
            storageDepth=config.storage_depth,
            dumpGID=config.dump_gid,
            dumpPermissions=config.dump_permissions,
            dirPermissions=config.dir_permissions,
        )

    # --------------------------------------------------------------------------
    def save_processed(self, processed_crash):
        """save a processed crash (in the form of a Mapping) into a json
        file.  It first gets the underlying file system to give it a file
        handle open for writing, then it uses the 'json' module to write
        the mapping to the open file handle."""
        try:
            crash_id = processed_crash["uuid"]
        except KeyError:
            raise CrashIDNotFound("uuid missing from processed_crash")
        try:
            processed_crash = self.sanitize_processed_crash(processed_crash, self.config.forbidden_keys)
            self._stringify_dates_in_dict(processed_crash)
            processed_crash_file_handle = self.pro_crash_store.newEntry(crash_id)
            try:
                json.dump(processed_crash, processed_crash_file_handle)
            finally:
                processed_crash_file_handle.close()
            self.logger.debug("saved processed- %s", crash_id)
        except Exception:
            self.logger.critical("processed file system storage has failed for: %s", crash_id, exc_info=True)
            raise

    # --------------------------------------------------------------------------
    def get_processed(self, crash_id):
        """fetch a processed json file from the underlying file system"""
        try:
            return self.pro_crash_store.getDumpFromFile(crash_id)
        except OSError:
            raise CrashIDNotFound(crash_id)

    # --------------------------------------------------------------------------
    def remove(self, crash_id):
        """remove the all traces of a crash, both raw and processed from the
        file system."""
        try:
            super(FileSystemCrashStorage, self).remove(crash_id)
        except CrashIDNotFound:
            self.logger.warning("raw crash not found for deletion: %s", crash_id)
        try:
            self.pro_crash_store.removeDumpFile(crash_id)
        except OSError:
            self.logger.warning("processed crash not found for deletion: %s", crash_id)

    # --------------------------------------------------------------------------
    @staticmethod
    def sanitize_processed_crash(processed_crash, forbidden_keys):
        """returns a copy of a processed_crash with the forbidden keys removed.

        parameters:
            processed_crash - the processed crash in the form of a mapping
            forbidden_keys - a list of strings to be removed from the
                             processed crash

        returns:
            a mapping that is a shallow copy of the original processed_crash
            minus the forbidden keys and values"""

        a_copy = processed_crash.copy()
        for a_forbidden_key in forbidden_keys:
            if a_forbidden_key in a_copy:
                del a_copy[a_forbidden_key]
        return a_copy

    # --------------------------------------------------------------------------
    @staticmethod
    def _stringify_dates_in_dict(a_dict):
        for name, value in a_dict.iteritems():
            if isinstance(value, datetime.datetime):
                a_dict[name] = "%4d-%02d-%02d %02d:%02d:%02d.%d" % (
                    value.year,
                    value.month,
                    value.day,
                    value.hour,
                    value.minute,
                    value.second,
                    value.microsecond,
                )
Example #5
0
class FileSystemCrashStorage(FileSystemThrottledCrashStorage):
    """This storage class is the only file system based crash storage system
    appropriate for storing both raw and processed crashes.  This class uses
    the same segregating raw crash storage as the previous class and adds
    processed storage.  Processed crashes are stored in their own file system
    root, 'pro_fs_root' (processed file system root) using the same radix
    directory system as the raw crashes."""

    required_config = Namespace()
    required_config.add_option(
        'pro_fs_root',
        doc='a path to a local file system for processed storage',
        default='./processedCrashStore')
    required_config.add_option(
        'minutes_per_slot',
        doc='the number of minutes in the lowest date directory',
        default=1)
    required_config.add_option(
        'sub_slot_count',
        doc='distribute data evenly among this many sub timeslots',
        default=1)
    required_config.add_option(
        'index_name',
        doc='the relative path to the top of the name storage tree from '
        'root parameter',
        default='name')
    required_config.add_option(
        'date_name',
        doc='the relative path to the top of the date storage tree from '
        'root parameter',
        default='date')
    required_config.add_option('processed_crash_file_suffix',
                               doc='the processed crash filename suffix',
                               default='.jsonz')
    required_config.add_option('gzip_compression_level',
                               doc='the level of compression to use',
                               default=9)
    required_config.add_option(
        'storage_depth',
        doc='the length of branches in the radix storage tree',
        default=2)
    required_config.add_option(
        'forbidden_keys',
        doc='a comma delimited list of keys to not allowed in the processed '
        'crash',
        default='url, email, user_id, exploitability',
        from_string_converter=lambda x: [i.strip() for i in x.split(',')])

    #--------------------------------------------------------------------------
    def __init__(self, config, quit_check_callback=None):
        super(FileSystemCrashStorage, self).__init__(config)
        self.pro_crash_store = ProcessedDumpStorage(
            root=config.pro_fs_root,
            minutesPerSlot=config.minutes_per_slot,
            subSlotCount=config.sub_slot_count,
            indexName=config.index_name,
            dateName=config.date_name,
            fileSuffix=config.processed_crash_file_suffix,
            gzipCompression=config.gzip_compression_level,
            storageDepth=config.storage_depth,
            dumpGID=config.dump_gid,
            dumpPermissions=config.dump_permissions,
            dirPermissions=config.dir_permissions,
        )

    #--------------------------------------------------------------------------
    def save_processed(self, processed_crash):
        """save a processed crash (in the form of a Mapping) into a json
        file.  It first gets the underlying file system to give it a file
        handle open for writing, then it uses the 'json' module to write
        the mapping to the open file handle."""
        try:
            crash_id = processed_crash['uuid']
        except KeyError:
            raise CrashIDNotFound("uuid missing from processed_crash")
        try:
            processed_crash = self.sanitize_processed_crash(
                processed_crash, self.config.forbidden_keys)
            self._stringify_dates_in_dict(processed_crash)
            processed_crash_file_handle = \
                self.pro_crash_store.newEntry(crash_id)
            try:
                json.dump(processed_crash, processed_crash_file_handle)
            finally:
                processed_crash_file_handle.close()
            self.logger.debug('saved processed- %s', crash_id)
        except Exception:
            self.logger.critical(
                'processed file system storage has failed for: %s',
                crash_id,
                exc_info=True)
            raise

    #--------------------------------------------------------------------------
    def get_processed(self, crash_id):
        """fetch a processed json file from the underlying file system"""
        try:
            return self.pro_crash_store.getDumpFromFile(crash_id)
        except OSError:
            raise CrashIDNotFound(crash_id)

    #--------------------------------------------------------------------------
    def remove(self, crash_id):
        """remove the all traces of a crash, both raw and processed from the
        file system."""
        try:
            super(FileSystemCrashStorage, self).remove(crash_id)
        except CrashIDNotFound:
            self.logger.warning('raw crash not found for deletion: %s',
                                crash_id)
        try:
            self.pro_crash_store.removeDumpFile(crash_id)
        except OSError:
            self.logger.warning('processed crash not found for deletion: %s',
                                crash_id)

    #--------------------------------------------------------------------------
    @staticmethod
    def sanitize_processed_crash(processed_crash, forbidden_keys):
        """returns a copy of a processed_crash with the forbidden keys removed.

        parameters:
            processed_crash - the processed crash in the form of a mapping
            forbidden_keys - a list of strings to be removed from the
                             processed crash

        returns:
            a mapping that is a shallow copy of the original processed_crash
            minus the forbidden keys and values"""

        a_copy = processed_crash.copy()
        for a_forbidden_key in forbidden_keys:
            if a_forbidden_key in a_copy:
                del a_copy[a_forbidden_key]
        return a_copy

    #--------------------------------------------------------------------------
    @staticmethod
    def _stringify_dates_in_dict(a_dict):
        for name, value in a_dict.iteritems():
            if isinstance(value, datetime.datetime):
                a_dict[name] = (
                    "%4d-%02d-%02d %02d:%02d:%02d.%d" %
                    (value.year, value.month, value.day, value.hour,
                     value.minute, value.second, value.microsecond))