def hold_message(self, destination, data, headers):
        """ Calls the reduction script. """
        logger.debug("holding thread")
        message = Message()
        message.populate(data)

        self.update_child_process_list()
        if not self.should_proceed(message):  # wait while the run shouldn't proceed
            # pylint: disable=maybe-no-member
            reactor.callLater(10, self.hold_message,  # pragma: no cover
                              destination, data,
                              headers)

            return

        if self.should_cancel(message):
            self.cancel_run(message)  # pylint: disable=maybe-no-member
            return


        if not os.path.isfile(MISC['post_process_directory']):
            logger.warning("Could not find autoreduction post processing file "
                           "- please contact a system administrator")
        python_path = sys.executable
        logger.info("Calling: %s %s %s %s",
                    python_path, MISC['post_process_directory'], destination,
                    message.serialize(limit_reduction_script=True))
        proc = subprocess.Popen([python_path,
                                 MISC['post_process_directory'],
                                 destination,
                                 message.serialize()])  # PPA expects json data
        self.add_process(proc, message)
 def _remove_with_wait(self, remove_folder, full_path):
     """ Removes a folder or file and waits for it to be removed. """
     file_deleted = False
     for sleep in [0, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20]:
         try:
             if remove_folder:
                 os.removedirs(full_path)
             else:
                 if os.path.isfile(full_path):
                     os.remove(full_path)
                     file_deleted = True
                 elif sleep == 20:
                     logger.warning(
                         "Unable to delete file %s, file could not be found",
                         full_path)
                 elif file_deleted is True:
                     logger.debug("file %s has been successfully deleted",
                                  full_path)
                     break
         except OSError as exp:
             if exp.errno == errno.ENOENT:
                 # File has been deleted
                 break
         time.sleep(sleep)
     else:
         self.log_and_message("Failed to delete %s" % full_path)
    def __init__(self, message, client):
        logger.debug("Message data: %s",
                     message.serialize(limit_reduction_script=True))
        self.read_write_map = {"R": "read", "W": "write"}

        self.message = message
        self.client = client

        self.reduction_log_stream = io.StringIO()
        self.admin_log_stream = io.StringIO()

        try:
            self.data_file = windows_to_linux_path(self.validate_input('data'),
                                                   MISC["temp_root_directory"])
            self.facility = self.validate_input('facility')
            self.instrument = self.validate_input('instrument').upper()
            self.proposal = str(int(
                self.validate_input('rb_number')))  # Integer-string validation
            self.run_number = str(int(self.validate_input('run_number')))
            self.reduction_script = self.validate_input('reduction_script')
            self.reduction_arguments = self.validate_input(
                'reduction_arguments')
        except ValueError:
            logger.info('JSON data error', exc_info=True)
            raise
 def validate_input(self, attribute):
     """
     Validates the input message
     :param attribute: attribute to validate
     :return: The value of the key or raise an exception if none
     """
     attribute_dict = self.message.__dict__
     if attribute in attribute_dict and attribute_dict[
             attribute] is not None:
         value = attribute_dict[attribute]
         logger.debug("%s: %s", attribute, str(value)[:50])
         return value
     raise ValueError('%s is missing' % attribute)
    def send_reduction_message(self, message, amq_message):
        """Send/Update AMQ reduction message
        :param message: (str) amq reduction  status
        :param amq_message: (str) reduction status path
        """
        try:
            logger.debug("Calling: %s\n%s", amq_message,
                         self.message.serialize(limit_reduction_script=True))
            self.client.send(amq_message, self.message)
            logger.info("Reduction: %s", message)

        except AttributeError:
            logger.debug("Failed to find send reduction message: %s",
                         amq_message)
    def on_message(self, headers, data):
        """ handles message consuming. It will consume a message. """
        destination = headers['destination']
        logger.debug("Received frame destination: %s", destination)
        logger.debug("Received frame priority: %s", headers["priority"])

        self.update_child_process_list()
        message = Message()
        message.populate(data)

        if message.cancel:
            self.add_cancel(message)
            return

        self.hold_message(destination, data, headers)