Пример #1
0
    def post(self):
        """Retrieve the next queued work item from the run log queue.

    The next work item is determined based on the browser version and token.

    URL Params:
      tokens: A string that uniquely identifies an instance of a test run.
      instance_id: A string that uniquely identifies the machine making the
        request.
      useragent: A string representing the browser useragent string.
    """
        # Get the parameters from the request
        token = self.GetRequiredParameter('tokens')
        instance_id = self.GetRequiredParameter('instance_id')
        useragent = urllib.unquote(self.GetRequiredParameter('useragent'))

        # Log the parameters
        logging.info(
            '\n'.join(['token: %s', 'instance_id: %s', 'useragent: %s']),
            token, instance_id, useragent)

        browser_version = AcceptNextWorkItem._ParseBrowserVersion(useragent)
        if not browser_version:
            logging.error('Could not parse the given useragent.')
            self.response.out.write('null')
            return

        log = db.GqlQuery(
            'SELECT * FROM RunLog WHERE token = :1 AND browser_version = :2 AND '
            'status = :3 ORDER BY creation_time ASC, priority DESC LIMIT 1',
            token, browser_version, enum.CASE_STATUS.QUEUED).get()

        # Write out a null response if no log exists for the given criteria
        if not log:
            self.response.out.write('null')
            logging.info(
                'No more test cases remain, shutting down the machine "%s".',
                instance_id)
            deferred.defer(launch_tasks.TerminateFinishedMachine,
                           instance_id,
                           _countdown=launch_tasks.DEFAULT_COUNTDOWN,
                           _queue=launch_tasks.DEFAULT_QUEUE)
            return

        self.response.out.write(AcceptNextWorkItem._GetTestDataJson(log))

        # Update the work item status
        log.status = enum.CASE_STATUS.IN_PROGRESS
        log.client_id = instance_id
        log.start_time = datetime.datetime.now()
        log.put()

        # Update the machine status
        client_machine.SetMachineStatus(instance_id,
                                        enum.MACHINE_STATUS.RUNNING)
Пример #2
0
def RebootMachine(instance_id):
    """Reboot the machine associated with the given instance id.

  The status of the machine is set to RUNNING.

  Args:
    instance_id: A string that uniquely identifies a machine.
  """
    # Terminate the EC2 instance.
    ec2 = ec2_manager.EC2Manager()

    logging.info('Rebooting machine with instance id "%s".', instance_id)
    ec2.RebootInstances([instance_id])

    # Update the corresponding client machine model.
    client_machine.SetMachineStatus(instance_id, enum.MACHINE_STATUS.RUNNING)
    client_machine.IncrementRetryCount(instance_id)
Пример #3
0
def TerminateMachine(instance_id, status):
    """Terminate the machine associated with the given instance id.

  Args:
    instance_id: A string that uniquely identifies a machine.
    status: An integer representing an enum.MACHINE_STATUS value.
  """
    # Terminate the EC2 instance.
    ec2 = ec2_manager.EC2Manager()

    if TERMINATE_INSTANCES:
        logging.info('Terminating the machine with instance id "%s".',
                     instance_id)
        ec2.TerminateInstances([instance_id])
    else:
        logging.info('Stopping the machine with instance id "%s".',
                     instance_id)
        ec2.StopInstances([instance_id])

    # Update the corresponding client machine model.
    client_machine.SetMachineStatus(instance_id, status)
Пример #4
0
    def post(self):
        """Change the state of a run log entry from IN_PROGRESS to FINISHED.

    URL Params:
      key: A string that represents the run log entry key in the datastore.
      instance_id: A string that uniquely identifies the machine making the
        request.
      result: A string result for the finished work item.

    Raises:
      base.InvalidParameterValueError: The given key does not correspond with
        an existing run log in the datastore.
    """
        # Get the parameters from the request
        key = self.GetRequiredParameter('key')
        instance_id = self.GetRequiredParameter('instance_id')
        result = self.GetOptionalParameter('result',
                                           default_value=WORK_ITEM_SUCCESS)

        # Log the parameters
        logging.info('\n'.join(['key: %s', 'instance_id: %s', 'result: %s']),
                     key, instance_id, result)

        log = db.get(key)
        if not log:
            raise base.InvalidParameterValueError('key', key)

        logging.info('Current log status: "%d".', log.status)

        if log.status != enum.CASE_STATUS.IN_PROGRESS:
            # The run log has an invalid run status for finishing, just return
            logging.error(
                'The test case "%s" has an invalid status for finishing.', key)
            return

        if result == WORK_ITEM_SUCCESS:
            # Update the work item status
            log.status = enum.CASE_STATUS.FINISHED
            log.end_time = datetime.datetime.now()
            if log.start_time:
                duration = log.end_time - log.start_time
                log.duration = FinishWorkItem._TimedeltaToMilliseconds(
                    duration)
            logging.info('Work item finished successfully.')
        elif result == WORK_ITEM_FAILURE:
            FinishWorkItem._HandleFailureCase(log,
                                              enum.CASE_STATUS.UNKNOWN_ERROR,
                                              'failure')
        elif result == WORK_ITEM_UPLOAD_ERROR:
            FinishWorkItem._HandleFailureCase(log,
                                              enum.CASE_STATUS.UPLOAD_ERROR,
                                              'upload error')
        elif result == WORK_ITEM_TIMEOUT_ERROR:
            FinishWorkItem._HandleFailureCase(log,
                                              enum.CASE_STATUS.TIMEOUT_ERROR,
                                              'timeout error')

        log.put()

        # Update the machine status
        client_machine.SetMachineStatus(instance_id,
                                        enum.MACHINE_STATUS.RUNNING)
Пример #5
0
  def post(self):
    """Put the given result data into the database."""
    data = self._GetRequestData()

    # Touch the machine instance if the instance id is provided.
    if 'instance_id' in data:
      client_machine.SetMachineStatus(data['instance_id'],
                                      enum.MACHINE_STATUS.RUNNING)

    if 'key' not in data:
      update_suite_info = False
      suite_data = simplejson.loads(data['suiteInfo'])
      suite = test_suite.GetOrInsertSuite(
          suite_data['date'], suite_data['refBrowser'],
          suite_data['refBrowserChannel'])

      channel = None
      if 'channel' in data:
        channel = data['channel']

      # Following code is to take care of the scenario where test browser comes
      # up first with the data. Hence, at that time we don't have sufficient
      # data to put in ref browser.
      # If reference browser information is incomplete then let's mark
      # it for update.
      if suite.ref_browser.os is None:
        parser = useragent_parser.UAParser(data['userAgent'])
        if (parser.GetBrowserVersion() == suite.ref_browser.version and
            channel==suite_data['refBrowserChannel']):
          # If flag is present anywhere then it has to match.
          if 'flag' in data or suite.ref_browser.flag:
            if suite.ref_browser.flag == data['flag']:
              update_suite_info = True
          else:
            update_suite_info = True

      test_data = page_data.PageData()
      if 'screenshot' in data:
        test_data.screenshot = screenshot.AddScreenshot(data['screenshot'])

      test_data.test_suite = suite

      flag = None
      if 'flag' in data:
        flag = data['flag']
      test_data.browser = browser.GetOrInsertBrowser(
          data['userAgent'], channel=channel, flag=flag)

      if update_suite_info:
        logging.info('Updating Reference Browser in Test Suite. old_ref: %s,'
                     ' new_ref: %s', suite.ref_browser.key(),
                     test_data.browser.key())
        test_suite.UpdateRefBrowser(suite, test_data.browser,
                                    delete_old_ref=True)
      # Let's get run log key from suite_data.
      if 'key' not in suite_data:
        raise PutDataError('The run log "key" is a required parameter.')
      my_run_log = db.get(db.Key(suite_data['key']))
      url_config_key = my_run_log.config.key()
      test_data.site = site.GetOrInsertSiteFromUrl(data['url'], url_config_key)

      test_data.nodes_table = data['nodesTable']
      test_data.dynamic_content_table = data['dynamicContentTable']
      test_data.layout_table = data_list.CreateEmptyDataList()

      test_data.width = int(data['width'])
      test_data.height = int(data['height'])
      if 'metaData' in data:
        test_data.metadata = data['metaData']
      # If browser key matches with test_suite's ref browser then
      # let's mark the page_data as reference.
      if str(test_data.browser.key()) == str(suite.ref_browser.key()):
        test_data.is_reference = True
      else:
        test_data.is_reference = False

      test_data.put()

      if not test_data.is_reference:
        suite.AddTestBrowser(test_data.browser)

      response = {
          'key': str(test_data.key()),
          'nPieces': data_list.NUM_ENTRIES}
      self.response.out.write(simplejson.dumps(response))

    else:
      test_data = db.get(db.Key(data['key']))
      layout_table = simplejson.loads(data['layoutTable'])
      test_data.layout_table.AddEntry(int(data['i']), layout_table)
      self.response.out.write('received')